How we got here
The dojo and routing work made cost, model choice, and quota visible, but much of that signal still came from transcript parsing alone. v0.31.0 adds the receiver side: `ax serve` can accept harness telemetry directly, normalize it, and correlate it with sessions after ingest. The release then uses that new signal for usage views, hook latency analysis, and Studio context-budget work.
The range also contains a practical correction: the first Codex OTLP config format broke Codex commands, so the receiver shipped with a follow-up fix in the same release. That keeps the story narrow and factual - telemetry is useful only if installing it does not disturb the harness emitting it.
What changed
OTLP landed in the daemon (#423, #432, #426). `ax serve` accepts harness usage telemetry, decodes a curated OTLP/JSON subset, and writes normalized rows. Claude usage arrives through the receiver, and Codex log events flow into the same local graph. The Codex config was corrected after the first format broke commands.
ax install
ax serveThe install path writes the harness telemetry config; the serve daemon receives it on the local port. Transcript parsing remains the source for prompts, responses, and tool I/O, while OTLP adds usage and timing signals.
Usage became a first-class read surface (#421). The new usage model, ingest stage, CLI command, dashboard contract, and Studio route turn self-telemetry into a personal utilization view. This is the adoption-side counterpart to quota: not just "how much plan is left", but "what did my agent work actually consume?"
Hook latency became measurable (#425). The hooks latency query and CLI formatting add a regression lens over real hook-fire telemetry, so hook guardrails can be judged by runtime cost instead of only by correctness.
Dojo moved into MCP and spar accounting stayed clean (#420, #424). The `dojo_agenda` MCP tool replaced the deferred cron trigger, and spar sessions now carry a behavioral analytics exclusion tag. Spar cost still exists, but training experiments stop polluting behavior metrics that are meant to describe normal work.
Studio and profiles picked up the new signals (#427, #400, #428). Studio's remaining dashboard routes moved into the instrument treatment and added Context Budget reclaim and drift views. The public profile page got the dot-matrix treatment, and the sessions API fixed an all-sources `NONE` column issue by coalescing nullable fields to `null`.
Why it matters
Transcript parsing tells ax what happened. OTLP tells it how expensive and how slow parts of that work were. v0.31.0 connects those signals locally, without shipping content bodies elsewhere, so cost, usage, hook latency, and context budget can become operational surfaces instead of scattered metadata.