You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Regression / behavior bug in the Codex app-server bridge.
Summary
After PR #88262, Codex app-server turns that cannot safely resume an existing Codex native thread can start a transient or fresh Codex thread with only the current prompt, even though OpenClaw has already loaded the mirrored session transcript.
The PR correctly tries to stop sending the mirrored OpenClaw transcript as parallel model history for normal Codex native resumes. The bug is that the same empty-history decision is now also used for the paths where there is no reliable Codex-native conversation to resume.
This means restricted Codex runs can silently lose prior conversation context unless an active OpenClaw context engine is present and successfully projects context.
The merged code reads the mirrored transcript, but then hard-codes the Codex-visible history list to [] before prompt hooks and turn input diagnostics are built:
The thread lifecycle deliberately refuses to resume an existing Codex thread when native code mode is disabled, preserving the old binding and starting a transient thread instead:
flowchart TD
A["OpenClaw session has prior visible messages"] --> B["run-attempt reads mirrored session history"]
B --> C["Codex native surface disabled or dynamic tools unavailable"]
C --> D["thread-lifecycle preserves old binding and starts transient thread"]
D --> E["PR #88262 sets codexModelInputHistoryMessages = []"]
E --> F["turn/start input = current prompt only"]
F --> G["Fresh Codex thread has no prior context"]
B -. "Before PR #88262" .-> H["shouldProjectMirroredHistoryForCodexStart"]
H -. "forceProject / missing binding / newer visible history" .-> I["Bounded quoted context was projected into prompt"]
I -.-> J["Transient/fresh thread retained continuity"]
Loading
Expected behavior
For a normal Codex native thread resume, OpenClaw should not duplicate the mirrored transcript into the model input. Codex owns that native thread history.
For a transient/fresh Codex start where OpenClaw intentionally does not resume the previous native thread, OpenClaw still needs a bounded continuity channel. The current prompt should either:
include a filtered, bounded projection of relevant OpenClaw-visible history, or
be routed through an active context engine that projects equivalent context, or
fail loudly / mark the turn as context-unavailable if continuity cannot be preserved.
The dangerous state is silent success with only the current prompt.
Actual behavior
When the native thread is not resumed, the code still uses the PR-wide codexModelInputHistoryMessages = [] decision. turn/start sends only the current prompt text.
This is not just a telemetry artifact. buildUserInput constructs the actual user input sent to Codex from promptText, and promptText remains params.prompt unless an active context engine projection ran.
Minimal reproduction shape
Add or adjust a focused test in extensions/codex/src/app-server/run-attempt.test.ts:
Create a session JSONL file with at least one prior user/assistant message.
Write an existing Codex app-server binding with a thread id.
Configure the run so native tool surface is disabled, for example by using a restrictive tool/sandbox mode that makes shouldEnableCodexAppServerNativeToolSurface(...) return false.
Do not attach an active context engine.
Start the next Codex app-server attempt.
Assert that the harness sees thread/start, not thread/resume.
Assert that the turn/start input contains the bounded prior visible context, or assert the run reports a context-preservation failure.
With the merged code, the final assertion fails because the input is only the current prompt.
Impact
This hits the exact cases where a user would expect OpenClaw to be conservative about continuity:
sandboxed or restricted Codex turns,
dynamic-tool-unavailable turns,
native code surface disabled by policy,
fresh starts after invalid or incompatible Codex thread binding,
any OpenClaw install that relies on the mirrored transcript but does not have an active context engine for that run.
The model can answer confidently while missing important prior instructions, constraints, or task state. That is worse than a visible failure because it looks like a normal successful Codex response.
Why this is not asking to revert the whole PR
The PR's main goal is valid: do not blindly inject mirrored history as parallel model history into a Codex native thread that already owns its conversation.
The issue is the conflation of two different concepts:
flowchart LR
A["Mirrored transcript as parallel model history"] -->|Should usually be empty for native Codex resume| B["codexModelInputHistoryMessages = []"]
C["Visible OpenClaw continuity for fresh/transient starts"] -->|Still needed when no native thread is resumed| D["bounded prompt/context-engine projection"]
Loading
Suggested fix direction
Keep codexModelInputHistoryMessages = [] for actual native Codex model history, but reintroduce a separate, narrowly named continuity path for starts that cannot resume native history.
For example:
codexModelInputHistoryMessages: remains empty for the model's parallel history input.
Only project freshThreadContinuityMessages when thread/start is used without an active context-engine projection or when forceProject is true because the native surface is disabled.
The previous helper already had most of the needed policy:
force project for non-native starts,
project for missing binding,
project for dynamic tool mismatch,
project for OpenClaw-visible history newer than the binding,
exclude Codex mirrored transcript messages.
The likely fix is to restore that policy under a clearer name so it cannot be confused with normal native Codex model history.
Bug type
Regression / behavior bug in the Codex app-server bridge.
Summary
After PR #88262, Codex app-server turns that cannot safely resume an existing Codex native thread can start a transient or fresh Codex thread with only the current prompt, even though OpenClaw has already loaded the mirrored session transcript.
The PR correctly tries to stop sending the mirrored OpenClaw transcript as parallel model history for normal Codex native resumes. The bug is that the same empty-history decision is now also used for the paths where there is no reliable Codex-native conversation to resume.
This means restricted Codex runs can silently lose prior conversation context unless an active OpenClaw context engine is present and successfully projects context.
Why this is high confidence
530351e394a19b1dd2943cb08259657a13f90572on 2026-05-30.[]before prompt hooks and turn input diagnostics are built:run-attempt.ts#L767-L777run-attempt.ts#L1626-L1640thread-lifecycle.ts#L274-L283thread-lifecycle.ts#L396-L407promptTextthroughbuildUserInput; there is no other transcript channel inturn/start:thread-lifecycle.ts#L1188-L1202attempt-context.tsat basef52355c,shouldProjectMirroredHistoryForCodexStartdiscussion_r3328358951Diagram
flowchart TD A["OpenClaw session has prior visible messages"] --> B["run-attempt reads mirrored session history"] B --> C["Codex native surface disabled or dynamic tools unavailable"] C --> D["thread-lifecycle preserves old binding and starts transient thread"] D --> E["PR #88262 sets codexModelInputHistoryMessages = []"] E --> F["turn/start input = current prompt only"] F --> G["Fresh Codex thread has no prior context"] B -. "Before PR #88262" .-> H["shouldProjectMirroredHistoryForCodexStart"] H -. "forceProject / missing binding / newer visible history" .-> I["Bounded quoted context was projected into prompt"] I -.-> J["Transient/fresh thread retained continuity"]Expected behavior
For a normal Codex native thread resume, OpenClaw should not duplicate the mirrored transcript into the model input. Codex owns that native thread history.
For a transient/fresh Codex start where OpenClaw intentionally does not resume the previous native thread, OpenClaw still needs a bounded continuity channel. The current prompt should either:
The dangerous state is silent success with only the current prompt.
Actual behavior
When the native thread is not resumed, the code still uses the PR-wide
codexModelInputHistoryMessages = []decision.turn/startsends only the current prompt text.This is not just a telemetry artifact.
buildUserInputconstructs the actual user input sent to Codex frompromptText, andpromptTextremainsparams.promptunless an active context engine projection ran.Minimal reproduction shape
Add or adjust a focused test in
extensions/codex/src/app-server/run-attempt.test.ts:shouldEnableCodexAppServerNativeToolSurface(...)return false.thread/start, notthread/resume.turn/startinput contains the bounded prior visible context, or assert the run reports a context-preservation failure.With the merged code, the final assertion fails because the input is only the current prompt.
Impact
This hits the exact cases where a user would expect OpenClaw to be conservative about continuity:
The model can answer confidently while missing important prior instructions, constraints, or task state. That is worse than a visible failure because it looks like a normal successful Codex response.
Why this is not asking to revert the whole PR
The PR's main goal is valid: do not blindly inject mirrored history as parallel model history into a Codex native thread that already owns its conversation.
The issue is the conflation of two different concepts:
flowchart LR A["Mirrored transcript as parallel model history"] -->|Should usually be empty for native Codex resume| B["codexModelInputHistoryMessages = []"] C["Visible OpenClaw continuity for fresh/transient starts"] -->|Still needed when no native thread is resumed| D["bounded prompt/context-engine projection"]Suggested fix direction
Keep
codexModelInputHistoryMessages = []for actual native Codex model history, but reintroduce a separate, narrowly named continuity path for starts that cannot resume native history.For example:
codexModelInputHistoryMessages: remains empty for the model's parallel history input.freshThreadContinuityMessages: filtered OpenClaw-visible messages, excluding Codex mirrored transcript echoes.freshThreadContinuityMessageswhenthread/startis used without an active context-engine projection or whenforceProjectis true because the native surface is disabled.The previous helper already had most of the needed policy:
The likely fix is to restore that policy under a clearer name so it cannot be confused with normal native Codex model history.
Evidence checked
openclaw/openclaw#88262, merge commit530351e394a19b1dd2943cb08259657a13f90572.04a4427d0c0b8f2e7bb666bbbcda5c557d033972.run-attempt.test.ts#L1722-L1748