Skip to content

fix(codex): clear stale context-engine projection after overflow retry#88699

Merged
steipete merged 1 commit into
openclaw:mainfrom
SebTardif:fix/context-engine-overflow-projection
Jun 2, 2026
Merged

fix(codex): clear stale context-engine projection after overflow retry#88699
steipete merged 1 commit into
openclaw:mainfrom
SebTardif:fix/context-engine-overflow-projection

Conversation

@SebTardif

Copy link
Copy Markdown
Contributor

Summary

When a resumed Codex thread with a thread_bootstrap context-engine binding overflows during turn/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.ts

After restartContextEngineCodexThread() creates the fresh retry thread, the fix reads the newly saved binding and clears the stale contextEngine.projection field. 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.ts

Updated the "retries a resumed context-engine thread on a fresh Codex thread without plugin compaction" test to assert the correct behavior: savedBinding.contextEngine.projection is undefined after overflow retry, not the stale epoch-before.

Real behavior proof

  • Behavior addressed: Context-engine overflow retry preserves a stale thread_bootstrap projection 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 build

    Step 2. Verify the fix is active in the production bundle:

    grep -n "cleared stale context-engine projection" dist/run-attempt-*.js

    Step 3. Run the context-engine test to verify behavioral change:

    node scripts/run-vitest.mjs extensions/codex/src/app-server/run-attempt.context-engine.test.ts
  • Evidence after fix: terminal output from the patched build:

    The fix is active in the production bundle:

    $ grep -n "cleared stale context-engine projection" dist/run-attempt-Bls4uL3x.js
    8465:log.info("codex app-server cleared stale context-engine projection after overflow retry", {

    The compiled overflow retry path correctly clears the stale projection binding before continuing:

    $ sed -n '8455,8470p' dist/run-attempt-Bls4uL3x.js
    const retryBinding = await readCodexAppServerBinding(activeSessionFile);
    if (retryBinding && retryBinding.threadId === thread.threadId && retryBinding.contextEngine?.projection) {
    const { schemaVersion: _schemaVersion, sessionFile: _boundSessionFile, updatedAt: _updatedAt, ...bindingForWrite } = retryBinding;
    await writeCodexAppServerBinding(activeSessionFile, {
    ...bindingForWrite,
    contextEngine: bindingForWrite.contextEngine ? {
    ...bindingForWrite.contextEngine,
    projection: void 0
    } : void 0
    });
    log.info("codex app-server cleared stale context-engine projection after overflow retry", {
    threadId: thread.threadId,
    previousEpoch: retryBinding.contextEngine.projection.epoch
    });
    }

    Terminal confirms the overflow retry test correctly asserts projection is cleared:

    $ node scripts/run-vitest.mjs extensions/codex/src/app-server/run-attempt.context-engine.test.ts 2>&1 | grep "retries.*resumed"
    ✓ retries a resumed context-engine thread on a fresh Codex thread without plugin compaction 115ms

    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-8468 correctly reads the freshly saved binding after overflow retry, detects the stale thread_bootstrap projection, clears it via projection: 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 asserts savedBinding.contextEngine.projection is undefined instead of asserting the stale epoch-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.

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]>
@openclaw-barnacle openclaw-barnacle Bot added extensions: codex size: XS proof: supplied External PR includes structured after-fix real behavior proof. labels May 31, 2026
@clawsweeper

clawsweeper Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed May 31, 2026, 12:26 PM ET / 16:26 UTC.

Summary
The PR clears contextEngine.projection from the Codex app-server binding after an overflow retry starts a fresh thread, and updates the focused context-engine regression test.

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 thread-fresh. I did not execute tests because this was a read-only review.

Review metrics: none identified.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🐚 platinum hermit
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add redacted terminal logs, copied live output, or a recording/artifact from a real gateway or integration-level context-engine overflow retry showing the stale projection is cleared.
  • Update the PR body with that proof so ClawSweeper can re-review automatically; if it does not, ask a maintainer to comment @clawsweeper re-review.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body supplies terminal output from a build, compiled-bundle grep, and a mocked Vitest path, but no real gateway or real context-engine plugin run showing the overflow retry behavior after the fix. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] The supplied proof is limited to a build/compiled-bundle grep and a mocked Vitest harness; it does not show a real gateway or real context-engine plugin overflow retry after the patch.

Maintainer options:

  1. Decide the mitigation before merge
    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.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] No automated repair is indicated: the branch is narrow and review found no code defect, but the external PR needs real behavior proof and normal maintainer verification before merge.

Security
Cleared: The diff only changes Codex binding state handling and a focused test; it does not touch dependencies, secrets, workflows, install scripts, or other supply-chain surfaces.

Review details

Best 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 thread-fresh. I did not execute tests because this was a read-only review.

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 changes

Label changes:

  • add P2: This is a normal-priority Codex context continuity bug fix with limited scope but real session-state impact.
  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body supplies terminal output from a build, compiled-bundle grep, and a mocked Vitest path, but no real gateway or real context-engine plugin run showing the overflow retry behavior after the fix. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Label justifications:

  • P2: This is a normal-priority Codex context continuity bug fix with limited scope but real session-state impact.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body supplies terminal output from a build, compiled-bundle grep, and a mocked Vitest path, but no real gateway or real context-engine plugin run showing the overflow retry behavior after the fix. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +32, Tests 0. Total +32 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 32 0 +32
Tests 1 1 1 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 33 1 +32

What I checked:

  • Repository policy read: Read the full root policy and the scoped extensions policy; this review applied the Codex dependency-inspection rule and plugin-boundary guidance. (AGENTS.md:1, 5b310a7b27fa)
  • Current main reproduces the stale binding invariant in source: The existing overflow-retry test starts from a thread_bootstrap projection, retries on thread-fresh with bare input hello, and currently asserts the saved binding still has projection.epoch === "epoch-before". (extensions/codex/src/app-server/run-attempt.context-engine.test.ts:1137, 5b310a7b27fa)
  • Current retry path does not clear the new binding projection: On current main, a context-engine overflow after resume clears the old-thread binding, calls restartContextEngineCodexThread(), emits thread_ready_retry, and immediately retries turn/start without removing the projection written by the fresh thread start. (extensions/codex/src/app-server/run-attempt.ts:1838, 5b310a7b27fa)
  • PR diff targets the implicated state: The PR reads the fresh retry binding, checks that it matches the new thread id and has a projection, rewrites the binding with projection: undefined, and changes the regression assertion to expect no projection. (extensions/codex/src/app-server/run-attempt.ts:1873, 5438f8ad34bd)
  • Binding writer supports the repair shape: writeCodexAppServerBinding serializes the supplied contextEngine through JSON.stringify, so setting nested projection to undefined omits the stale projection while preserving the rest of the binding. (extensions/codex/src/app-server/session-binding.ts:146, 5b310a7b27fa)
  • Next-run logic will reproject when the projection is absent: resolveContextEngineBootstrapProjectionDecision returns project: true with reason missing-projection-binding when a binding has a thread id but no context-engine projection. (extensions/codex/src/app-server/attempt-context.ts:105, 5b310a7b27fa)

Likely related people:

  • steipete: Git blame attributes the current context-engine overflow retry path, the focused regression test, and binding helpers in this shallow checkout to Peter Steinberger, and recent adjacent Codex recovery work is in 827ceb55d0. (role: recent area contributor; confidence: high; commits: d1bec469af22, 827ceb55d074; files: extensions/codex/src/app-server/run-attempt.ts, extensions/codex/src/app-server/run-attempt.context-engine.test.ts, extensions/codex/src/app-server/session-binding.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. labels May 31, 2026
@steipete steipete self-assigned this Jun 2, 2026
@steipete

steipete commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Land-ready maintainer verification for PR #88699.

What changed: the Codex app-server retry path now clears only the stale contextEngine.projection on the freshly started overflow-retry thread, so later turns use the existing missing-projection path to re-project instead of trusting an epoch the fresh thread never received.

Local review/proof:

  • git status -sb on main: clean before checkout.
  • .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main --output /tmp/autoreview-88699.txt --json-output /tmp/autoreview-88699.json
  • Result: autoreview clean: no accepted/actionable findings reported.

CI/proof on head 5438f8ad34bda9e28b6ee9e12b9a8b822834ddac:

  • Merge state: CLEAN.
  • CI workflow run 26717883204: relevant checks successful, including preflight, security-fast, build-artifacts, checks-fast-bundled-protocol, check-guards, check-prod-types, check-lint, check-dependencies, check-test-types, check-additional-extension-bundled, and ci-timings-summary.
  • Real behavior proof workflow completed successfully on the PR after the structured proof body was supplied.

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.

@steipete
steipete merged commit e7aac17 into openclaw:main Jun 2, 2026
184 of 190 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

extensions: codex P2 Normal backlog priority with limited blast radius. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Context-engine overflow retry can bind a fresh Codex thread without projected context

2 participants