fix(codex): replay legacy user-input requests as blocking - #13509
Conversation
Codex 0.156 requires `isBlocking` on `item/tool/requestUserInput`, and its own deserializer defaults a missing value to true for older clients. Transcripts recorded before 0.156 omit it, so the replay client rejected the request and the Codex plan_questions fixture stalled until its 60 second deadline. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
| ) { | ||
| const params = { ...(normalized.params as Record<string, unknown>) }; | ||
| // Codex treats a legacy request without `isBlocking` as blocking. | ||
| if (params.isBlocking === undefined) { |
There was a problem hiding this comment.
This changes how replayed inbound requests are delivered, but the PR adds no focused test for it. Could you add a replay test with a legacy item/tool/requestUserInput frame that omits isBlocking, asserting the client receives true, and one with an explicit false to verify it remains unchanged?
Posted via Macroscope — Effect Service Conventions
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: unavailable · PR result: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a narrowly scoped replay-harness compatibility fix that defaults only legacy user-input frames to blocking while preserving explicit values. Its runtime impact is confined to test/evaluation replay paths, with no production, schema, security, or deployment changes. You can add or adjust custom eligibility rules. Learn more. |
2e85a43
into
t3code/codex-turn-mapping
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
plan_questions/codexfails on the V2 branch tip (393d7b3): it stalls for 60 seconds and times out.Codex 0.156 made
isBlockingrequired onitem/tool/requestUserInput. The fixture's transcript was recorded on 0.120 and doesn't have it, so the replay client rejects the request as undecodable, and the scenario waits until its deadline. Codex itself treats a missingisBlockingastrue(codex-rs/app-server-protocol/src/protocol/v2/item.rs:1778atrust-v0.156.1, with a test for exactly this legacy case). The replay normalizer already fills other fields old transcripts lack (projectId,sessionId,startedAtMs); this addsisBlockingwith Codex's default.The failing fixture is the regression test.
Verification
OrchestratorReplayFixtures.integration.test.ts: 75/75 pass (before:plan_questions/codexfailed after 60,272 ms).effect-codex-app-servertests: 38/38. Typecheck: no errors or warnings. Format and lint clean onreplay.ts.Found by the agent re-recording Codex fixtures on 0.156.1 (#13505).
Model: Claude Opus 5.5 (Claude Code)
🤖 Generated with Claude Code