SIGN IN SIGN UP

feat(token-usage): match forked Codex sessions against their parent's usage prefix

A forked rollout replays its parent's history with timestamps rewritten
to the fork instant. The rewritten-burst heuristic (skip leading events
spaced <= 1s apart) misidentifies a real fork whose own first turn
follows the replay after a longer pause — observed in the wild as a
16,508-token replayed event counted as genuine usage 6.975s before the
child's first own turn.

Port ccusage's parent-prefix matching into the incremental extractor:
a fork now parks in AwaitingParent until the worker resolves the parent
rollout and answers with its pre-fork usage signatures (per-event
deltas, timestamps excluded; collected without replay filtering so a
prefix the parent itself replayed stays included, truncated at the
child's session_meta timestamp). The child's leading events consume the
matching front of that prefix; a mismatch after any match means the
replayed history ended, and a mismatch with nothing matched — or an
unresolvable parent — falls back to the burst heuristic exactly as
before (never retried, matching ccusage's unavailable-parent path).
The unmatched remainder persists in the extractor state, so the parent
is read once per fork, not per pass or restart.

The worker serves prefix requests after restoring state and after every
consumed line. Parent resolution tries files tracked under the parent's
external session id, then a bounded scan of the codex sessions tree,
always confirming a candidate by its recorded session_meta id (ccusage
locates parents by id, never filename) — a bounded single-file read in
the async worker.

The spec's fork section is rewritten and the split-burst accepted
limitation narrows to the unresolvable-parent fallback path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
S
Sasha Varlamov committed
262201056f65346acea89c3f149c7ff8113a03ca
Parent: aa9b098