#221

fix: parse Codex saved-session transcripts

Openmmarufovwants to merge intofrom

Summary

When codex exec --json produces no JSONL, the runner falls back to a saved session. Its wrapped records do not match the stdout schema, so the parser reports zero activity even when commands ran.

  • Translate paginated completed items through the existing Codex parser, skipping duplicate response_item records. Match Codex's command quoting and display masking.
  • Without a stdout thread ID, require one new session with source exec. Exclude the shell canary and child agents instead of choosing by filename.
  • For unsupported Codex activity, omit result.json.o11y and expose o11y: null to EVAL.ts. Preserve usage and raw/parsed transcripts, including when a legacy session contains a terminal error.
  • Add optional top-level EVAL results.usage so token assertions still work without an activity summary. Existing o11y.usage and runner-reported usage precedence are preserved.

Saved sessions cannot recover missing in-flight commands or stdout-only retry notices, and error counts can differ between sources. Other agents retain their existing summary behavior. If useful, I can follow up separately with a general missing-summary contract; custom-agent parser selection in #217 is separate.

README updated and a minor changeset included for the added EVAL usage field.

Tests

  • Regression tests failed before the fixes. Coverage checks deduplication, command outcomes and masking, legacy failures, canary/child/ambiguous session selection, usage, and the actual EVAL context and saved artifacts. Runner tests use the existing local sandbox support with a stand-in Codex executable.
  • Node 24.11.0: npm test passed (596 passed, 17 skipped), including Docker tests. Credentialed integration tests were disabled. npm run build, npm run lint, and git diff --check passed.
  • Also checked captured Codex CLI 0.162.1 stdout and saved sessions from a deterministic localhost Responses API fixture. No live model service was used.

Closes #190.