Usage Sidecars Written Beside Every Stage
Capture per-turn context usage as each stage finishes, so a run carries its own numbers
0 milestones 7 sprints 20 agents
3 plan 7 execute 7 review 3 fix
157k peak context
107k median execute
1h 15m total 10m 14s per sprint
3m 39s plan 33m 57s execute 18m 14s review
60 edits 540 commands
codex harness
Gantry's context analysis used to reconstruct stage usage after the fact from whatever each harness left behind. This job moved that evidence into the run itself: counted stage transcripts can now sit beside a normalized usage sidecar, and the analyzer treats that sidecar as the durable source before falling back to older correlation paths.
How this walkthrough is structured
Feature
What did the run build and ship?
Current Gantry still writes normalized usage sidecars from the harness layer and reads them first during context analysis, while keeping degraded and historical fallback paths explicit.
Build
How did Gantry structure the work?
The job put the shared sidecar contract first, then let each harness and the analyzer consume that shape independently, with stress appearing at the contract, Opencode, and scanner boundaries.
Normalized Usage Contract
4 agents 10m 14s wall time 82k peak context 1 fix 1 replan
The sidecar module is still present in the engine. It defines a header record, turn records, version checking, source and harness fields, optional correlating identifiers, peak validation, and rules for degraded header-only captures. The writer derives a transcript-adjacent usage path and emits compact JSONL rather than copying a harness transcript or external store. Later changes have kept this module as the shared contract the harnesses and scanner meet on.
This was the load-bearing contract sprint. A fresh agent could hold it because no harness extractor needed to exist yet; the work was limited to a reusable sidecar model, serialization, validation, and tests around exact and degraded captures. The gate sent the sprint back, and review then forced a re-plan because the landed contract added line discriminators and a required note for header-only captures. That is the boundary where a change belonged, before later sprints depended on the shape.
Finalization Hook Reference
2 agents 11m 59s wall time 157k peak context
The build runner still calls a harness usage-capture hook after a successful counted stage and builds the context from the transcript path, stage, harness id, captured stream, and harness config. The shared harness layer still contains the non-fatal writer that turns missing or failed capture into a degraded sidecar rather than a failed stage. Claude's extractor still computes context from input tokens plus cache-read and cache-creation tokens and writes exact per-assistant-message turns through the shared sidecar type.
This piece joined the contract to the agent-stage boundary and used Claude as the reference because Claude already exposes assistant usage inside Gantry's captured stream. The brief was still narrow enough for a fresh agent: write sidecars only for counted stages, keep telemetry non-fatal, and prove the normalized context calculation against fixtures. It landed without a red sprint gate after the contract re-plan had clarified the discriminator and degraded-note rules.
Codex Rollout Extractor
2 agents 8m 46s wall time 107k peak context
The Codex harness still reads the stage stream for a thread identifier, searches an injectable sessions root for the matching rollout, and turns rollout token-count events into normalized usage turns. When the rollout is absent, unreadable, or lacks usable events, it writes a header-only degraded sidecar carrying the thread id when available. The implementation keeps full rollout content out of Gantry logs; only the compact usage series crosses into the sidecar.
Codex was cut as its own extractor because the hard part was correlation to an outside rollout store, not the sidecar format or the stage hook. The sprint brief gave the agent a synthetic sessions root, thread matching, compact token-count extraction, and degraded output for missing data. With the contract already set, this work stayed inside the Codex harness surface and passed without a recorded fix or re-plan.
Opencode Session Extractor
3 agents 13m 38s wall time 145k peak context 1 fix
The Opencode harness still discovers the session from the JSON stream's camel-case marker and reads assistant token usage from the external store through an overridable root. It supports message directory and database-backed store layouts, orders messages by stored metadata and fallback ids, and computes context from input plus cache read and write tokens. The user-facing harness guide also documents the sidecar behavior and the store-root override, so the operational contract remains visible outside the code.
Opencode carried more uncertainty than Codex because the brief required validating real session-id behavior before relying on stored messages. The work was still agent-sized because it had a clear scope: discover or pin the session, read an injectable store root, sort assistant messages, and degrade honestly when the store was missing. The sprint went red at the gate and was fixed, and the review summary records that the repair handled real store filenames and fallback ordering details.
Gemini Degraded Capture
2 agents 6m 23s wall time 126k peak context
The Gemini harness still writes an aggregate-only usage sidecar. Its code states that the captured Gemini output exposes final usage statistics but no trustworthy per-turn context signal, so it records a header with an aggregate context value when present and no fabricated turn records. Missing usage details produce the same header-only shape with a note, which keeps the analyzer informed without claiming exact per-turn data.
Gemini was scoped around an evidence check rather than an assumption of exactness. The sprint's boundary was to inspect what the harness actually exposes, then either extract real turns or record a degraded aggregate-only capture with a clear note. Because the earlier contract already allowed header-only sidecars, this harness could land without a red gate while preserving the same non-fatal telemetry rule as the exact extractors.
Sidecar-First Analysis
3 agents 14m 7s wall time 115k peak context 1 fix
The current context scanner still looks for a usage sidecar beside each transcript before applying legacy parsing. It accepts only the landed header and turn discriminators, validates version, required fields, turn counts, non-empty degraded notes, and per-turn sequence, then reports a sidecar-derived peak source. If no usable sidecar exists, the scanner continues through the older Claude, Codex, and Opencode correlation paths so pre-sidecar runs remain analyzable.
This sprint was placed after capture existed because it was the first consumer of the full contract. Its brief asked the agent to prefer transcript-adjacent sidecars, reject malformed records, and keep historical harness-specific fallbacks for older runs. The run facts show the stress after review, when a later gate failed and a fix added scanner contract coverage and ignored generated test noise. That placed the difficulty at the analyzer boundary, where new durable input met old archives.
Fleet Cross-Reference
2 agents 3m 23s wall time 73k peak context
The original plan documents this sprint edited have since been removed as housekeeping, so its exact text is no longer isolated in the live tree. Its operational effect is still visible in the analyzer and fleet collection tests: sidecar-bearing runs are treated as self-contained, and external Codex rollouts remain a fallback for older archives rather than a requirement for new ones. The Opencode and harness reference docs also retain the user-facing sidecar guidance that this pass helped align.
The closing sprint was intentionally thin: align documentation and final checks with the sidecar-first model after code paths had already landed. A fresh agent did not need to revisit extractor internals; it had to update the fleet collection story, preserve the historical Codex rollout fallback, and confirm the compact-record rule. The sprint stayed green, matching its role as a documentation and integration pass over already-proven behavior.