Skip to content
Home

Use case · Mapping tokens to outcomes

Your agents burn tokens. Some of it ships. The rest, you can't see.

Coding agents cost real money. Claude Code, Codex, Cursor, and Gemini all charge by the token, and none of them tell you what the money bought. Cardinal ties every session to a branch, a pull request, and an initiative, then classifies the spend by what actually happened to the work. Any row you cite, you can click into for the evidence.

The join, in one line

  1. tokens

    62.4M

    in the plugin's OTel stream

  2. session

    01JD…K4QF

    Claude · $14.20

  3. branch

    feat/outcomes-observability

    parsed on ingest

  4. PR

    #421

    reconciled from GitHub

  5. outcome

    merged

    predicate + reason code

01 · The outcome accounting

Four buckets. Every dollar lands in exactly one.

The top of the dashboard is a scorecard. Total spend splits four ways: MERGED, IN-FLIGHT, LOST, and AD-HOC. Below that, a by-type strip breaks the same total down into Feature, Bugfix, Refactor, Infra, and Research. The spend-over-time curve flags days beyond +2σ so unusual spikes are easy to find, and the activity heatmap surfaces off-hours bursts and single hot cells. Every number traces back to the session rows further down through the same primitives. Nothing is smoothed or estimated.

  • · MERGED: PR merged from the branch this session touched
  • · IN-FLIGHT: PR open, work still moving
  • · LOST: PR closed unmerged, stale, or superseded
  • · AD-HOC: research or investigation with no PR expected

Overview · four buckets, spend curve, activity heatmap

Click to enlarge · esc to close

Cardinal's Agent Outcomes overview: total spend split into MERGED, IN-FLIGHT, LOST, AD-HOC bucket cards; by-type strip for Feature, Bugfix, Refactor, Infra, Research; spend-over-time line with +2σ anomaly dots; activity heatmap by day x hour.

02 · The session ledger

Every session is a row. Every row carries its branch.

A small plugin in each engineer's agent streams OpenTelemetry to Cardinal after every tool call. Each row carries the session id, tokens, tool count, duration, and cost. A local git hook adds the branch and head SHA the work was done on, so we know which piece of work each session belongs to. Sessions land with the effort tier they ran at (HIGH or XHIGH), the model they used, and the skill they invoked. Sessions that sprawled across unrelated work get a DRIFT flag with the dollars it cost.

  • · Runs in Claude Code, Codex CLI, Cursor, and Gemini CLI
  • · git_state event fires post-tool, so nothing blocks the user
  • · Cost priced from the emitter's own usage records, not estimates
  • · Effort, model, skill, and drift signal are all attributes on the row

Sessions · state, model, skill, effort per row

Click to enlarge · esc to close

Cardinal's Sessions view: every agent session with state (MERGED, IN-FLIGHT, LOST, AD-HOC), model, skill tag, effort badge (HIGH or XHIGH), branch, tool count, duration, and per-session cost. DRIFT and negative-scope flags shown inline.

03 · Branches become initiatives

One branch, one initiative. Related PRs collapse.

Cardinal parses the branch name (feat/, fix/, refactor/, infra/, research/, spike/) and uses it to name and type the initiative. Every session on that branch aggregates into it, and sibling PRs from linked branches collapse into the same initiative. So the backend PR and the UI PR for one feature stop showing up as two unrelated line items. You see the engineers who touched it, the PRs it produced, and the spec it moved forward.

  • · Convention: <type>/<kebab-name>, parsed on ingest
  • · Delivery column shows shipped / in-progress / stuck per initiative
  • · Spec column shows scope conformance where a spec is attached
  • · Engineers, tokens, cost, session count all attributed per initiative

Initiatives · curated groups, sibling PRs collapsed

Click to enlarge · esc to close

Cardinal's Initiatives view: per-user spend cards on top, then a curated initiatives table with sibling PRs, engineers, delivery status (Shipped clean, Stuck), spec conformance (On scope / Off scope), achieved vs pending tokens, cost, and session count.

04 · PRs carry the delivery signal

Every session joined to its pull request. Or none at all.

A PR reconciler polls your connected GitHub integration for lifecycle state on every branch Cardinal is watching, then joins by branch and head SHA. Every session that ran on a git branch lands in the PR grid: one row per PR, with cost, sessions, model, spec conformance, and outcome. Sessions with no branch at all show up in a separate footnote. They can't map to a PR, and we don't count them as failures.

  • · GitHub App or PAT. One integration per org
  • · Reconciler runs every 30 min; webhook lands sub-minute (opt-in)
  • · Attribution confidence surfaced per row, never silently rolled up
  • · Stuck / abandoned / on-scope pills come from PR state and spec joins

Pull requests · sessions joined to PR state

Click to enlarge · esc to close

Cardinal's Pull Requests grid: one row per PR with repo, branch, engineer, delivery state, model, spec conformance, outcome pill, achieved vs pending tokens, cost, and session count. Sessions with no branch appear as unattributed footnotes.

05 · The same numbers, cut a different way

One ledger, several axes. The dollars in each view reconcile.

The same session-level facts drive every cut. Cost by model tier, by repo, by engineer. Nothing is re-aggregated in the UI. If the per-repo bars sum to the top-line, it's because the pipeline emitted them that way.

Cardinal's Model Mix view: stacked-bar-per-day of token spend across Haiku, Sonnet, Opus, and Fable, showing which tier the token mass actually lands on for the window.

By model tier

How much of the token mass lands on Haiku vs Sonnet vs Opus. Click a row to compare $/Mtok against teammates running the same kind of work on cheaper tiers. Useful when a workflow could run on a cheaper model but isn't.

Cardinal's By-Repo view: horizontal bar chart of spend per repository across the org, sorted by spend, with session counts alongside.

By repo

Which codebase the agent is actually investing in. Useful when one repo is quietly consuming most of the token budget, or when a repo that isn't a priority is soaking up sessions.

Per-engineer detail card in Cardinal: throughput (PRs merged, sessions/PR), spend, contribution shape by initiative, PRs landed per day, cost trend.

By engineer

Per-person throughput, spend, and contribution shape. Compare two engineers side by side to see who's producing durable delivery per dollar, and which initiatives they're actually landing.

06 · How the join works

Five primitives. Every rollup traces back to them.

No "productivity index." No opaque scoring. Each row on every screen is reproducible from a fixed set of versions (rule, predicate, normalizer, and PR-attribution). A scorecard you cite in a review can be regenerated a quarter later from the same trace.

PipelineDeterministic
  1. 01PluginEmits OTLP per tool call plus a cardinal.git_state event with { branch, head_sha, remote_url }.
  2. 02SessionizerWatermarks each session on the OTel logs stream, then closes it on inactivity or an explicit session.end.
  3. 03Initiative resolverParses the branch prefix, applies aliases (feature→feat, bugfix→fix), and attributes the session to a typed initiative.
  4. 04PR reconcilerPolls your connected GitHub integration and joins branch + head_sha against pull_request state.
  5. 05PredicateEmits { verdict, strength, reason_code } per session × workflow. Reprocessable, versioned, idempotent.

Point agents to Cardinal. Get the ledger the next day.

The plugin installs in one command and needs no code changes. The first outcomes show up as soon as sessions close. PR attribution starts once the GitHub integration is connected.