Skip to content

Ticket metrics

gaia_ticket.metrics is a multi-value gaia_metric field carrying arbitrary named metrics {name, value, unit?, recorded?}. Its primary purpose is the success side of a ticket — how well it went — complementing the run footprint, which measures the cost side of a run (effort: tokens, duration, turns).

The field is generic — names are a convention, not a schema

The metric name is a free string (data), never a config allowed-values list, so a new metric kind needs no schema change. The names below are the canonical catalog: agreeing on them keeps metrics comparable and aggregatable across tickets. They are not enforced — a typo is simply a distinct metric — so treat this list as a shared vocabulary, and extend it when a new metric earns a home.

value is decimal(12,4), for exact aggregation across counts, ratios and hours. unit is a free label (ratio, h, count). recorded is an optional UNIX timestamp.

Omit empty keys, never send an explicit null

Leave recorded and unit out when they are empty — do not send an explicit null recorded over JSON:API. Drupal core's TimestampNormalizer returns a 500 on a null timestamp; an absent key is the correct shape.

Canonical metrics

nameunitmeaningwho writes itwhen
ac_pass_rateratiofraction of acceptance criteria passing in the review fresh runagent (review)at review, from the AC matrix
review_bouncescountnumber of review→coding loops before doneagent/conductorincremented on each Not-OK bounce
time_to_done_hhwall-clock hours from spec entry to doneconductorat done
rework_followupscountfollow-up bugs that reference this ticket after doneconductor/humanpost-done, ongoing
human_interventionscountmanual human corrections/edits per run on this ticketconductor/humanduring/after a run

Write paths

  • Agent or conductor (session scope): a JSON:API PATCH of metrics on an in-scope ticket — allowed with no new permission, because a session write to an in-scope ticket already passes GaiaTicketAccessControlHandler and metrics falls through checkFieldAccess. The field is multi-value, so a write is a read-modify-write union: GET the current metrics, append, then PATCH the whole array — the same pattern as links. From an agent session the JSON:API call goes through the gaia dropsh shell, which resolves its target from the connection config.
  • Human: the Metrics widget on the ticket edit form, /admin/gaia/ticket/<id>/edit.

Reading and aggregating in Views

The gaia_metric Views handlers are keyed on the field type, so any gaia_metric field inherits them — gaia_ticket.metrics today, gaia_run.metrics later:

  • gaia_metric field — renders one metric's value, pinned by a metric_name option, and is aggregatable (for example AVG).
  • gaia_metric_value sortORDER BY the named metric's value.
  • gaia_metric_value filter — a numeric filter on the named metric's value (for example ac_pass_rate < 0.5), exposable.
  • gaia_metric_name filter — scope a view to one metric name before aggregating (presence or equality), exposable.

Not yet automated

  • Derivation of these metrics — the conductor or agent actually computing and writing ac_pass_rate, review_bounces and friends at the right lifecycle point — is follow-up work. What ships today is the field, the write path, and the Views handlers.
  • A dashboard widget surfacing per-project success over time is an optional follow-up.
  • Merging the run footprint into this model is reachable without rework, since the field type is reusable on gaia_run, but is deliberately not done yet: the run footprint stays its own model for now.
  • How GAIA works — where runs, footprints and ticket state fit together.
  • The normative spec — the TimeEntry and billing roll-up model that the cost side of a ticket uses.