fix(codex): clear stale context-engine projection after overflow retry#88699
Conversation
When a resumed Codex thread with a thread_bootstrap context-engine binding overflows during turn/start, the retry creates a fresh thread but preserved the old projection epoch in the saved binding. The fresh thread never received the projected context, creating a false binding invariant that makes future runs skip re-projection. After restartContextEngineCodexThread() creates the fresh retry thread, read the saved binding, detect the stale projection, clear it, and log the previous epoch for observability. Closes openclaw#88355 Signed-off-by: Sebastien Tardif <[email protected]>
|
Codex review: needs real behavior proof before merge. Reviewed May 31, 2026, 12:26 PM ET / 16:26 UTC. Summary PR surface: Source +32, Tests 0. Total +32 across 2 files. Reproducibility: yes. source-reproducible: the current-main regression test constructs the overflow retry and asserts the stale projection remains on 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 this narrow binding-state fix after a contributor adds redacted real behavior proof for a live or integration-level context-engine overflow retry and the focused validation is green. Do we have a high-confidence way to reproduce the issue? Yes, source-reproducible: the current-main regression test constructs the overflow retry and asserts the stale projection remains on Is this the best way to solve the issue? Yes for the code shape: clearing only the projection preserves the context-engine binding while making the next run follow the existing missing-projection reproject path. The merge path still needs real behavior proof beyond mocks. AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 5b310a7b27fa. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +32, Tests 0. Total +32 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
|
|
Land-ready maintainer verification for PR #88699. What changed: the Codex app-server retry path now clears only the stale Local review/proof:
CI/proof on head
Known proof gap: I did not get a live gateway/lossless-claw overflow run for this branch. I’m accepting the source-level harness, CI, and maintainer review because the patch is narrowly scoped to removing false projection metadata from the exact fresh retry binding and leaves the retry turn behavior unchanged. |
Summary
When a resumed Codex thread with a
thread_bootstrapcontext-engine binding overflows duringturn/start, OpenClaw retries on a fresh thread but preserves the old projection epoch in the saved binding. The fresh thread never received the projected context, so the binding creates a false invariant: future runs treat the thread as if it already contains the context-engine bootstrap, skipping re-projection and silently losing context.Closes #88355
Changes
extensions/codex/src/app-server/run-attempt.tsAfter
restartContextEngineCodexThread()creates the fresh retry thread, the fix reads the newly saved binding and clears the stalecontextEngine.projectionfield. This ensures future runs will re-project instead of assuming the old epoch is still bootstrapped on the fresh thread.The fix follows the same binding read/strip/write pattern used by
markCodexAppServerBindingCoveredThroughTurn(same file) and adds an info-level log entry for observability.extensions/codex/src/app-server/run-attempt.context-engine.test.tsUpdated the "retries a resumed context-engine thread on a fresh Codex thread without plugin compaction" test to assert the correct behavior:
savedBinding.contextEngine.projectionis undefined after overflow retry, not the staleepoch-before.Real behavior proof
Behavior addressed: Context-engine overflow retry preserves a stale
thread_bootstrapprojection binding on the fresh Codex thread. The fresh thread never received the projected context, creating a false binding invariant that causes future runs to skip re-projection and silently lose context.Real environment tested: macOS 15.5, Node v22.19, OpenClaw built from patched source at
/tmp/fix-88355.Exact steps or command run after this patch:
Step 1. Build from the fix branch:
cd /tmp/fix-88355 CI=true pnpm install --frozen-lockfile pnpm buildStep 2. Verify the fix is active in the production bundle:
Step 3. Run the context-engine test to verify behavioral change:
Evidence after fix: terminal output from the patched build:
The fix is active in the production bundle:
The compiled overflow retry path correctly clears the stale projection binding before continuing:
Terminal confirms the overflow retry test correctly asserts projection is cleared:
Full test results: 22/23 pass (1 pre-existing failure in "does not inject mirrored history" unrelated to this change, same failure on upstream/main).
Observed result after fix: The compiled production code at
dist/run-attempt-Bls4uL3x.js:8455-8468correctly reads the freshly saved binding after overflow retry, detects the stalethread_bootstrapprojection, clears it viaprojection: void 0, and logs the previous epoch for observability. The test "retries a resumed context-engine thread on a fresh Codex thread without plugin compaction" now correctly assertssavedBinding.contextEngine.projectionis undefined instead of asserting the staleepoch-before.What was not tested: Live gateway session with a real context-engine plugin (lossless-claw) triggering a Codex context window overflow. The fix was verified through compiled production bundle inspection and the existing context-engine test harness.