Event-granularity audit: surfaces that stall at turn boundaries despite live per-step sources
- Dominant language
- Rust
- Stars
- 41k
- Forks
- 3.6k
- Avg merge
- 13h 59m
- Merged PRs (30d)
- 299
Description
Follow-up to #5578 (cost fixed) and the same user report: with turns spanning many model calls, anything that only updates at `TurnComplete` reads as frozen. Audited 2026-08-23; findings ordered by value.
## Already live (no action)
- **Cost** — fixed in #5578 (per-step `TurnUsage` priced into a pending estimate).
- **Subagent/background cost** — `cost_status::drain()` sweeps every loop tick.
- **Timing metrics strip** — folds per-step `TurnUsage` already.
- **Context meter** — live-estimate driven; its trigger-mismatch question is #5577.
## Stalled at TurnComplete (candidates)
1. **Session token totals** (`total_tokens`, `total_input/output_tokens`, cache-class totals in the sidebar) — accrue only in the `TurnComplete` handler (`event_loop.rs` ~1615-1655). Live source exists: the same per-step `TurnUsage` receipts. Apply the exact #5578 pattern: display-only pending token counters, cleared at `TurnComplete` before the authoritative cumulative usage lands. Mechanical; the quickest win here.
2. **'worked Nh Mm' chip** — `cumulative_turn_duration` rolls up only at turn end; mid-turn the chip understates by the whole current turn. `turn_started_at` is available: display cumulative + live elapsed.
3. **`/cache` table rows** — one `TurnCacheRecord` per turn is by design, but a 50-call turn collapses all cache behavior into one row. `TurnUsage` carries per-call cache classes; consider optional per-step rows or a per-turn min/max spread.
4. **Session persistence** — metadata (cost, tokens) persists at turn boundaries; a crash mid-giant-turn loses that turn's telemetry entirely. Consider a periodic mid-turn checkpoint of the pending counters.
## Principle (from the Codex comparison)
A turn is the unit of *conversation*; it must not be the unit of *observability*. Every user-facing meter should update from per-model-call receipts; `TurnComplete` reconciles, it does not reveal.
Tracker: #5573. Related: #5577, #5578, #5580 (reducer refactor is the natural home for these handlers).
Contributor guide
Research direction
Start with event_loop.rs around lines 1615-1655 and compare the TurnComplete handling with the per-step TurnUsage pattern from #5578. Then inspect the reducer refactor in #5580 and decide which audited surface is in scope. Done means the selected user-facing meter updates during multi-call turns and reconciles correctly at TurnComplete.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli, observability
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100