Skip to the content.

Post-tool latency span (#10662)

The audited defect: in Codex rollout journals the interval AFTER a tool result is recorded and BEFORE the next model-emitted record grows with session age and context size (median ~11s at tool-result ordinal 1-20, ~21s at 101-200, with the hotspot at 50k-100k input tokens). internal/codexlifecycle/posttool.go makes that interval a first-class span instead of an unnamed hole in the timeline.

Definition

One PostToolSpan per function_call_output / custom_tool_call_output record:

call ──ToolMS──▶ output ──GapMS──▶ next model-emitted record

A model-emitted record is function_call, custom_tool_call, token_count, task_complete, or turn_aborted (the same set decomposeTimeline anchors on; ARecord.PayloadKind recovers custom calls, so no JSON is re-parsed). A trailing result with no next model-emitted record is skipped and counted as tail_skipped in the report: an unclosed interval measures nothing.

Disjointness (the no-double-counting witness)

ToolMS measures call → its own output; GapMS measures that output → the next model-emitted record. The intervals share exactly one endpoint and cannot overlap, so ToolMS + GapMS always equals the call → next-record interval. A slow tool can never be booked as post-tool model latency. Interior compacted records become subspans (pre_compaction, then one compaction segment per edge) that tile GapMS exactly.

Closed vocabularies

Correlation, not causation

Journal timestamps cannot separate provider TTFT from gateway queueing or harness scheduling inside GapMS. Attribution tokens are CORRELATION aids over observable structure; the report never claims a causal latency split. Live-path emit belongs to #10636 and the timing inventory to #10621.

Running it

fak session-audit posttool --here --json

Flags mirror fak session-audit codex: --root DIR (default ~/.codex/sessions, honoring CODEX_HOME), --cwd DIR|--here, --max N. The text renderer prints overall gap/tool percentiles plus one line per non-empty band and ordinal bucket in canonical order, each with the tool_p50 control beside the gap percentiles. Regression corpus and expected values: internal/codexlifecycle/testdata/posttool/issue-10662/.