Description
There is no model-side duration anywhere in a Claude Code transcript. Pairing a tool_use block to its tool_result record on tool_use_id produces the highest-value derived signal in the whole project, and it checks out against reality: Bash p50 1.8s, Grep p50 0.03s, Read p50 0.2s.
toolUseResult.durationMs exists on a minority of results only and must not be the basis for tool latency.
Acceptance Criteria
- #1 Pairs tool_use to tool_result on tool_use_id and sets Item.Duration with Source derived
- #2 An unpaired tool_use is recorded with Source absent, never with a zero duration
- #3 Response duration is derived from record adjacency and is never written into the TTFT field
- #4 toolUseResult shape is decoded per tool kind including the Bash fields, the edit structuredPatch line counts and the typed results
- #5 Tool errors set Outcome from is_error, interrupted and timedOutAfterMs
- #6 A test asserts a derived value can never reach an instrument whose contract is native
Definition of Done
- #1 just check passes: fmt-check, lint, build, test-short, probe-ci, dashboard-check and docs-links all clean
Implementation Plan
Wave 1 lane 4: write table-driven synthetic-fixture tests first, implement the Claude decoder across all documented record types, then run focused decoder tests; root integrates and runs the final gate.
Final Summary
Claude tool pairing and typed results carry derived durations and error outcomes without conflating response duration and TTFT; tests and corpus gate passed.