fix(codex): restore bounded recovery continuity#88652
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed May 31, 2026, 10:21 AM ET / 14:21 UTC. Summary PR surface: Source +145, Tests +234. Total +379 across 2 files. Reproducibility: yes. source-reproducible: current main has empty Codex model-input history plus transient/fresh thread paths, and the linked issues give focused run-attempt test shapes. I did not execute tests because this review is read-only. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land after maintainer review with real Codex app-server recovery proof, keeping continuity as bounded turn input while leaving native thread developer instructions stable. Do we have a high-confidence way to reproduce the issue? Yes, source-reproducible: current main has empty Codex model-input history plus transient/fresh thread paths, and the linked issues give focused run-attempt test shapes. I did not execute tests because this review is read-only. Is this the best way to solve the issue? Yes, likely: a separate bounded continuity projection while keeping parallel model history empty matches the inspected Codex thread/turn contract. The remaining gap is live recovery proof rather than an obvious better code path. AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 1bfae9d45890. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +145, Tests +234. Total +379 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b990649560
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| : typeof message.timestamp === "string" | ||
| ? Date.parse(message.timestamp) | ||
| : Number.NaN; | ||
| return Number.isFinite(timestamp) && timestamp > bindingUpdatedAt; |
There was a problem hiding this comment.
Advance the continuity cutoff only after coverage
When a stale binding is resumed and the attempt then fails before a successful turn/completed (for example a transient turn/start error), startOrResumeThread has already rewritten the binding during thread_resume_write_binding, so binding.updatedAt now points at the failed attempt rather than the last covered native turn. On the next retry this new cutoff drops the post-binding visible messages here even though they were never covered by Codex, so a single transient failure can permanently lose the recovery continuity this patch is restoring. Use a separate covered-through timestamp or only advance the cutoff after a successful turn.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4f2e3d63a1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (action === "started") { | ||
| applyFreshThreadContinuityProjection(); | ||
| return true; |
There was a problem hiding this comment.
Preserve stale-binding cutoff for fresh starts
When a stale binding has newer post-binding messages, this branch only reuses that bounded projection if rotateStartupBindingForProjectedTurn set staleBindingContinuityForcedFreshStart. Other normal paths inside startOrResumeThread can also convert the run to action: "started" after the precompute, such as dynamic-tool/MCP/plugin/env fingerprint changes or a resume failure, and then this fallback calls applyFreshThreadContinuityProjection() and replays the entire mirrored transcript instead of only messages newer than the binding cutoff. In those fresh-start recoveries, already-covered native turns can be duplicated into the prompt and large old history can blow the bounded recovery this change is trying to provide.
Useful? React with 👍 / 👎.
|
Land-ready verification for head Local proof:
CI proof:
Behavior proof:
Known proof gap: no packaged app-server binary or live upstream model completion run for this PR. |
Summary
Codex source checked
../codex/codex-rs/app-server-protocol/src/protocol/v2/thread.rs:95and../codex/codex-rs/app-server-protocol/src/protocol/v2/thread.rs:330:thread/startandthread/resumecarrydeveloper_instructions.../codex/codex-rs/app-server-protocol/src/protocol/v2/turn.rs:66:turn/startcarriesinputand turn settings, not thread-level developer instructions.../codex/codex-rs/app-server/src/request_processors/thread_processor.rs:830and../codex/codex-rs/app-server/src/request_processors/thread_processor.rs:2474: start/resume map developer instructions into thread config overrides.../codex/codex-rs/app-server/src/request_processors/turn_processor.rs:413: turn input maps intoOp::UserInput.../codex/codex-rs/core/src/session/mod.rs:573and../codex/codex-rs/core/src/session/mod.rs:2692: Codex stores thread developer instructions in session config and emits them as developer messages.Verification
pnpm exec oxfmt --check --threads=1 extensions/codex/src/app-server/run-attempt.ts extensions/codex/src/app-server/run-attempt.test.tsgit diff --checknode scripts/run-vitest.mjs run --config test/vitest/vitest.extension-codex.config.ts extensions/codex/src/app-server/run-attempt.test.ts.agents/skills/autoreview/scripts/autoreview --mode local --prompt "..."clean after fixing accepted findingsReal behavior proof
Behavior addressed: Codex app-server recovery paths could lose OpenClaw-visible continuity when no active native Codex thread already covered the visible transcript, while healthy native resumes must still avoid duplicated mirrored history.
Real environment tested: Local OpenClaw source checkout with mocked Codex app-server lifecycle tests exercising
thread/start,thread/resume,turn/start, binding rotation, mirrored transcript filtering, and successful-turn binding coverage.Observed result after fix: fresh native starts receive bounded continuity; stale bindings receive only newer visible messages; active-turn persisted messages are not replayed on the next resume; Codex app-server mirror echoes are suppressed without suppressing other backend mirror identities; thread-start developer instructions remain stable after native start.
What was not tested: packaged app-server binary or live upstream model completion.
Closes #88352.
Closes #88354.