Skip to content

Commit bc55be1

Browse files
committed
context: a Codex compaction request is not a disagreement
Codex records the request that compacts a session with a response id, but the cumulative total does not include it: the total change after a compaction repeats the previous total with zero last usage. The first collection on the production box marked 24 long Codex passes unknown for this, exactly the most expensive ones. A compaction request is now recognised by position: the response record whose next usage event is the compaction. Those are left out, and every other response record must match the total changes one for one, in order, with the same figures; anything else is still a disagreement. The parser version moves to 3 so those passes are measured again.
1 parent f41e183 commit bc55be1

2 files changed

Lines changed: 135 additions & 61 deletions

File tree

‎runner/bin/review_context.py‎

Lines changed: 88 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import os
1212
import re
1313

14-
PARSER = "review_context/2"
14+
PARSER = "review_context/3"
1515
MAX_BYTES = 256 << 20 # a log larger than this is not parsed
1616
SAVED = re.compile(r"Full output saved to:?\s*(\S+?\.txt)")
1717
SHELLS = ("exec", "exec_command", "shell", "local_shell", "container.exec")
@@ -299,59 +299,23 @@ def exec_label(name, given):
299299
return label(first) + ("+" if len(commands) > 1 else "")
300300

301301

302-
def codex(paths):
302+
def codex(threads):
303+
"""threads: each thread's rollouts, oldest first. The running total and
304+
the order of usage events carry across one thread's rollouts (a resume)
305+
and start again for the next thread."""
303306
out = empty("codex")
304307
out["subagents"] = None # child sessions are not linked yet
305-
by_id, rises, calls, damaged = {}, [], {}, [0]
306-
for path in paths:
307-
out["sources"].append(str(path))
308-
previous = None
309-
for row in lines(path, damaged):
310-
payload = row.get("payload") if isinstance(row.get("payload"), dict) else {}
311-
kind = payload.get("type")
312-
if row.get("type") == "session_meta":
313-
out["session_id"] = out["session_id"] or payload.get("id")
314-
out["cli_version"] = out["cli_version"] or payload.get("cli_version")
315-
if kind in ("compacted", "context_compacted") or row.get("type") == "compacted":
316-
out["compactions"] += 1
317-
if row.get("type") == "token_usage_record":
318-
usage = payload.get("usage")
319-
ident = payload.get("response_id")
320-
if not isinstance(usage, dict):
321-
damaged[0] += 1
322-
continue
323-
check_usage(usage, damaged) # every record, kept or not
324-
if ident is None:
325-
ident = "unidentified-%d" % len(by_id)
326-
out["warnings"].append("usage record without response id")
327-
by_id.setdefault(ident, usage)
328-
elif kind == "token_count" and isinstance(payload.get("info"), dict):
329-
# a request shows as a change in the cumulative total; a fall
330-
# is a reset (a resume), still a request; the same total again
331-
# is a repeated record
332-
info = payload["info"]
333-
totals = info.get("total_token_usage")
334-
last = info.get("last_token_usage")
335-
if totals is None and last is None:
336-
continue # a rate-limit-only record
337-
total = totals.get("total_tokens") if isinstance(totals, dict) else None
338-
if not count_ok(total) or not isinstance(last, dict):
339-
damaged[0] += 1
340-
continue
341-
check_usage(last, damaged)
342-
if total != previous:
343-
rises.append(last)
344-
previous = total
345-
elif kind in ("custom_tool_call", "function_call"):
346-
calls[payload.get("call_id")] = exec_label(payload.get("name"), payload.get("input") or payload.get("arguments"))
347-
elif kind in ("custom_tool_call_output", "function_call_output"):
348-
body = payload.get("output")
349-
if isinstance(body, list):
350-
text = "".join(x.get("text", "") for x in body if isinstance(x, dict) and isinstance(x.get("text"), str))
351-
else:
352-
text = body if isinstance(body, str) else json.dumps(body)
353-
if payload.get("call_id") in calls:
354-
add_tool(out, calls.pop(payload.get("call_id")), len(text))
308+
by_id, rises, calls, damaged, compacting = {}, [], {}, [0], set()
309+
for paths in threads:
310+
order, previous = [], None # this thread's usage events
311+
for path in paths:
312+
out["sources"].append(str(path))
313+
previous = parse_rollout(path, out, by_id, rises, calls, damaged, order, previous)
314+
# a compaction request is the response record whose next usage event
315+
# is the compaction itself: the total does not include it. Every
316+
# record keeps its own position, repeats included.
317+
compacting |= {ident for (what, ident), (after, _) in zip(order, order[1:])
318+
if what == "U" and after == "C"}
355319
requests = list(by_id.values()) or rises
356320
if not requests:
357321
raise ValueError("no usage records")
@@ -363,17 +327,80 @@ def codex(paths):
363327
if damaged[0]:
364328
raise Damaged("%d damaged records" % damaged[0], out)
365329
if by_id and rises:
366-
# both sources describe the same requests in the same order; where
367-
# they differ, which is right cannot be told: the figures stay as
368-
# found, but nothing reports them as known
369-
pairs = zip(by_id.values(), rises)
370-
if len(rises) != len(by_id) or any(
371-
a.get(k) != b.get(k) for a, b in pairs for k in ("input_tokens", "cached_input_tokens", "output_tokens")):
372-
raise Damaged("request sources disagree: %d usage records, %d total changes"
373-
% (len(by_id), len(rises)), out)
330+
ordinary = [usage for ident, usage in by_id.items() if ident not in compacting]
331+
if not agree(ordinary, rises):
332+
# which source is right cannot be told: the figures stay as
333+
# found, but nothing reports them as known
334+
raise Damaged("request sources disagree: %d usage records (%d compacting), %d total changes"
335+
% (len(by_id), len(compacting), len(rises)), out)
336+
if compacting:
337+
out["warnings"].append("%d compaction requests missing from totals" % len(compacting))
374338
return out
375339

376340

341+
def parse_rollout(path, out, by_id, rises, calls, damaged, order, previous):
342+
"""One rollout's records into the running measurement; returns the last
343+
cumulative total, for the thread's next rollout."""
344+
for row in lines(path, damaged):
345+
payload = row.get("payload") if isinstance(row.get("payload"), dict) else {}
346+
kind = payload.get("type")
347+
if row.get("type") == "session_meta":
348+
out["session_id"] = out["session_id"] or payload.get("id")
349+
out["cli_version"] = out["cli_version"] or payload.get("cli_version")
350+
if kind in ("compacted", "context_compacted") or row.get("type") == "compacted":
351+
out["compactions"] += 1
352+
order.append(("C", None))
353+
if row.get("type") == "token_usage_record":
354+
usage = payload.get("usage")
355+
ident = payload.get("response_id")
356+
if not isinstance(usage, dict):
357+
damaged[0] += 1
358+
continue
359+
check_usage(usage, damaged) # every record, kept or not
360+
if ident is None:
361+
ident = "unidentified-%d" % len(by_id)
362+
out["warnings"].append("usage record without response id")
363+
order.append(("U", ident))
364+
by_id.setdefault(ident, usage)
365+
elif kind == "token_count" and isinstance(payload.get("info"), dict):
366+
# a request shows as a change in the cumulative total; a fall is
367+
# a reset, still a request; the same total again is a repeat
368+
info = payload["info"]
369+
totals = info.get("total_token_usage")
370+
last = info.get("last_token_usage")
371+
if totals is None and last is None:
372+
continue # a rate-limit-only record
373+
total = totals.get("total_tokens") if isinstance(totals, dict) else None
374+
if not count_ok(total) or not isinstance(last, dict):
375+
damaged[0] += 1
376+
continue
377+
check_usage(last, damaged)
378+
if total != previous:
379+
rises.append(last)
380+
order.append(("T", None))
381+
previous = total
382+
elif kind in ("custom_tool_call", "function_call"):
383+
calls[payload.get("call_id")] = exec_label(payload.get("name"), payload.get("input") or payload.get("arguments"))
384+
elif kind in ("custom_tool_call_output", "function_call_output"):
385+
body = payload.get("output")
386+
if isinstance(body, list):
387+
text = "".join(x.get("text", "") for x in body if isinstance(x, dict) and isinstance(x.get("text"), str))
388+
else:
389+
text = body if isinstance(body, str) else json.dumps(body)
390+
if payload.get("call_id") in calls:
391+
add_tool(out, calls.pop(payload.get("call_id")), len(text))
392+
return previous
393+
394+
395+
def agree(records, rises):
396+
"""Whether the response records (compaction requests excluded) and the
397+
cumulative total changes describe the same requests, one for one, in
398+
order, with the same figures."""
399+
keys = ("input_tokens", "cached_input_tokens", "output_tokens")
400+
return len(records) == len(rises) and all(
401+
a.get(k) == b.get(k) for a, b in zip(records, rises) for k in keys)
402+
403+
377404
def failed(provider, error, retry, partial=None):
378405
out = {k: None for k in FIELDS}
379406
if partial:
@@ -403,7 +430,7 @@ def measure(attempt, job):
403430
if missing:
404431
# every thread the pass ran must be read, or it is undercounted
405432
return failed(provider, "no rollout for %s" % ",".join(missing), True)
406-
return codex([p for t in threads for p in found[t]])
433+
return codex([found[t] for t in threads])
407434
return failed(provider, "unknown provider %r" % provider, False)
408435
except Damaged as error:
409436
return failed(provider, "Damaged: %s" % error.args[0], False, error.args[1])

‎runner/tests/test_review_context.py‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,53 @@ def test_disagreeing_request_sources_make_the_measurement_unknown(self):
223223
self.assertIn("disagree", m["error"])
224224
self.assertFalse(rc.known(m))
225225

226+
def test_a_compaction_request_missing_from_the_totals_is_not_disagreement(self):
227+
# as the CLI writes it: the compaction request has a usage record, then
228+
# the total stays put with zero last usage
229+
rows = [tur("r1", 100, 0), count(105, 100, 0), tur("r2", 246, 0), {"type": "compacted"},
230+
{"type": "event_msg", "payload": {"type": "token_count", "info": {
231+
"total_token_usage": {"total_tokens": 105},
232+
"last_token_usage": {"input_tokens": 0, "cached_input_tokens": 0, "output_tokens": 0}}}},
233+
tur("r3", 20, 0), count(130, 20, 0)]
234+
write(self.rollout, codex_rows(rows))
235+
m = rc.measure(self.dir, self.job)
236+
self.assertIsNone(m["error"])
237+
self.assertEqual((m["requests"], m["sum_input"], m["compactions"]), (3, 366, 1))
238+
self.assertTrue(m["warnings"])
239+
# without the compaction, the same gap is disagreement
240+
write(self.rollout, codex_rows([r for r in rows if r != {"type": "compacted"}]))
241+
self.assertIn("disagree", rc.measure(self.dir, self.job)["error"])
242+
# a compaction elsewhere does not excuse an ordinary request the totals describe wrongly
243+
wrong = [tur("a", 100, 0), count(105, 100, 0), tur("c", 20, 0), {"type": "compacted"},
244+
tur("b", 999, 0), count(130, 20, 0)]
245+
write(self.rollout, codex_rows(wrong))
246+
self.assertIn("disagree", rc.measure(self.dir, self.job)["error"])
247+
248+
def test_a_repeated_record_keeps_its_place_before_a_compaction(self):
249+
# b is followed by a repeat of a, not by the compaction: b is not excused
250+
rows = [tur("a", 100, 0), count(105, 100, 0), tur("b", 50, 0), tur("a", 100, 0), {"type": "compacted"}]
251+
write(self.rollout, codex_rows(rows))
252+
self.assertIn("disagree", rc.measure(self.dir, self.job)["error"])
253+
254+
def test_another_threads_compaction_excuses_nothing(self):
255+
write(self.dir / "payload.log", [{"type": "thread.started", "thread_id": "T1"},
256+
{"type": "thread.started", "thread_id": "T2"}])
257+
write(self.rollout, codex_rows([tur("a", 100, 0), count(105, 100, 0), tur("b", 50, 0)]))
258+
write(self.home / "sessions/2026/10/05/rollout-2026-10-05T08-00-00-T2.jsonl",
259+
codex_rows([{"type": "compacted"}, tur("d", 30, 0), count(40, 30, 0)]))
260+
self.assertIn("disagree", rc.measure(self.dir, self.job)["error"])
261+
262+
def test_a_resumed_rollout_carries_the_running_total(self):
263+
zero = {"type": "event_msg", "payload": {"type": "token_count", "info": {
264+
"total_token_usage": {"total_tokens": 105},
265+
"last_token_usage": {"input_tokens": 0, "cached_input_tokens": 0, "output_tokens": 0}}}}
266+
write(self.rollout, codex_rows([tur("a", 100, 0), count(105, 100, 0)]))
267+
write(self.home / "sessions/2026/10/06/rollout-2026-10-06T01-00-00-T1.jsonl",
268+
codex_rows([tur("c", 246, 0), {"type": "compacted"}, zero, tur("b", 20, 0), count(130, 20, 0)]))
269+
m = rc.measure(self.dir, self.job)
270+
self.assertIsNone(m["error"])
271+
self.assertEqual(m["requests"], 3)
272+
226273
def test_null_usage_or_payload_damage_is_not_a_zero(self):
227274
write(self.rollout, codex_rows([{"type": "token_usage_record", "payload": {
228275
"response_id": "r1", "usage": {"input_tokens": None, "cached_input_tokens": 0}}}]))

0 commit comments

Comments
 (0)