Skip to content

Commit 22af950

Browse files
fix(codex): ignore zero-usage replay candidates
Apply the normal parsing non-zero usage rule before a snapshot can establish a replay burst. Initialisation records must not suppress a subagent's real first response. Add a regression with two zero snapshots followed by a real response within the replay window, retaining duplicate-only replay coverage. Co-authored-by: parttimediarybehavior <[email protected]>
1 parent 91b9881 commit 22af950

2 files changed

Lines changed: 55 additions & 3 deletions

File tree

‎rust/adapters/codex/src/loader.rs‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,6 +2429,52 @@ mod tests {
24292429
assert_eq!(events[0].input_tokens, 50);
24302430
}
24312431

2432+
#[test]
2433+
fn keeps_first_child_response_after_zero_usage_initialization() {
2434+
let token_count = |timestamp: &str, input_tokens: u64, output_tokens: u64| {
2435+
json!({
2436+
"timestamp": timestamp,
2437+
"type": "event_msg",
2438+
"payload": {
2439+
"type": "token_count",
2440+
"info": {
2441+
"last_token_usage": {
2442+
"input_tokens": input_tokens,
2443+
"output_tokens": output_tokens,
2444+
"total_tokens": input_tokens + output_tokens,
2445+
},
2446+
"total_token_usage": {
2447+
"input_tokens": input_tokens,
2448+
"output_tokens": output_tokens,
2449+
"total_tokens": input_tokens + output_tokens,
2450+
},
2451+
},
2452+
},
2453+
})
2454+
.to_string()
2455+
};
2456+
2457+
let fixture = fs_fixture!({
2458+
"child.jsonl": [
2459+
replay_metadata(
2460+
"2026-07-10T08:00:00.000Z",
2461+
"child",
2462+
Some("missing-parent"),
2463+
),
2464+
token_count("2026-07-10T08:00:00.100Z", 0, 0),
2465+
token_count("2026-07-10T08:00:00.200Z", 0, 0),
2466+
token_count("2026-07-10T08:00:00.500Z", 50, 1),
2467+
]
2468+
.join("\n"),
2469+
});
2470+
2471+
let events = load_codex_events_from_directory(fixture.root(), true).unwrap();
2472+
2473+
assert_eq!(events.len(), 1);
2474+
assert_eq!(events[0].input_tokens, 50);
2475+
assert_eq!(events[0].output_tokens, 1);
2476+
}
2477+
24322478
#[test]
24332479
fn skips_missing_parent_replay_with_duplicate_snapshots_and_advancing_usage() {
24342480
fn token_count(timestamp: &str, input: u64, total_input: u64) -> String {

‎rust/adapters/codex/src/parser.rs‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,15 @@ fn detect_rewritten_burst(path: &Path) -> Option<TimestampMs> {
175175
let Some(timestamp) = codex_session_timestamp(value.timestamp.as_ref()) else {
176176
continue;
177177
};
178-
if info
179-
.is_none_or(|info| info.last_token_usage.is_none() && info.total_token_usage.is_none())
180-
{
178+
if !info.is_some_and(|info| {
179+
info.last_token_usage
180+
.as_ref()
181+
.or(info.total_token_usage.as_ref())
182+
.copied()
183+
.map(normalize_codex_raw_usage)
184+
.as_ref()
185+
.is_some_and(has_codex_token_usage)
186+
}) {
181187
continue;
182188
}
183189
let Some(timestamp) = parse_ts_timestamp(&timestamp) else {

0 commit comments

Comments
 (0)