Codex App: Goal compaction resurrects completed manual steer before goal continuation resumes
What version of the Codex App are you using (From “About Codex” dialog)?
26.616.51431
What subscription do you have?
Pro 20x
What platform is your computer?
Darwin 25.4.0 arm64 arm
What issue are you seeing?
In a long-running active /goal, a completed manual steering instruction is repeatedly resurrected after compaction and executed again before the active goal continuation is re-injected.
This appears to be the same failure mode as, or a regression/continuation of:
- #21291
- #27894
- #19910
- #28874
- #25900
- #28925
- #21269
It also appears related to the goal-continuation fixes discussed in:
- #22045
- #22174
I am intentionally omitting thread IDs, local paths, and exact project/conversation text. The example below is anonymized but preserves the observed control-flow shape.
Observed pattern:
- Start a long-running
/goal, e.g. “migrate a large project with full parity and keep working until complete.” - During the goal, send a normal user steering message, e.g. “please implement the cache boundary using backend X and keep it extensible.”
- The agent implements that steer and finishes the turn.
- Because the goal is still active, Codex starts the next turn by injecting an internal goal-continuation user message like:
``text``
<codex_internal_context source="goal">
Continue working toward the active thread goal.
...
- The agent correctly resumes the broader goal and works on unrelated next parity/evidence tasks.
- After a later compaction, the replacement history appears to preserve the original goal, app/developer context, AGENTS/project instructions, and the last ordinary user steering message. The visible replacement history does not appear to preserve enough of the later goal-continuation/checkpoint state that proves the steering task was already completed.
- The next model turn treats the old steering message as the current unresolved user instruction and performs the same steering task again.
- When that repeated steering turn completes, the goal-continuation message is injected again, so the agent briefly returns to the broader goal.
- At the next compaction, the same stale steering message regains salience again.
In the anonymized run I inspected, there were five compactions after the manual steer. All five replacement histories had the same high-level shape:
1. original /goal message
2. developer/app instructions
3. AGENTS/project instructions
4. latest ordinary user steer message
5. encrypted compaction summary
The observed behavior after those compactions was:
- Compaction 1: continued/cache-related follow-up work; arguably still close to the just-completed steering task.
- Compaction 2: re-checked the already-implemented cache backend and documentation, then eventually returned to the broader goal.
- Compaction 3: clearly re-executed the cache steer, introducing/rewiring a neutral cache interface and backend export again, then returned to broader parity work.
- Compaction 4: briefly summarized/re-verified the cache again, then resumed broader parity work.
- Compaction 5: clearly re-entered the cache steer again, including documentation lookup and additional cache interface expansion, despite the broader goal having moved on.
This creates a positive feedback loop: stale steer is replayed after compaction, which increases the amount of steer-related context, which makes the next compaction even more likely to preserve and emphasize that stale steer, which consumes more context and time.
What steps can reproduce the bug?
A minimal reproduction should be possible with a long-running goal and one mid-goal manual steer:
- Start a Codex App thread with a long-running goal:
``text``
/goal Perform a large migration/refactor. Keep working until all implementation and verification work is complete.
- Let Codex complete at least one goal-continuation turn.
- Send a normal user steering message that is concrete and easy to recognize later:
``text``
Please implement subsystem A using backend X. Keep the design extensible so backend Y can be added later.
- Let Codex implement that steering instruction and finish the turn.
- Let the active goal continue automatically. It should move on to unrelated broader-goal work.
- Wait for or force a compaction.
- Observe whether the next turn repeats the already-completed steering instruction before the goal-continuation context is re-injected.
- Let that repeated turn complete and then continue to another compaction. The same steer may repeat again.
I cannot include the original session/thread ID because the session contains private workspace details, but the local event log showed this control flow explicitly:
task_complete: completed steer work
new task_started
response_item role=user: <codex_internal_context source="goal"> Continue working...
agent resumes broader goal
...
compacted
replacement_history: original /goal + instructions + old ordinary steer + encrypted summary
agent starts by acting on old steer again
What is the expected behavior?
Once a manual steer inside an active goal has been completed, later compaction should not resurrect it as the current unresolved user task.
Compaction should preserve enough goal state/checkpoint metadata to distinguish:
completed manual steering instruction
from:
current active goal-continuation task
After compaction, the next turn should continue from the latest active goal checkpoint, e.g.:
The cache/backend steering instruction was completed earlier. Continue the broader migration goal from the current audit/checkpoint.
It should not re-run the completed steer unless the user explicitly asks for it again.
Additional information
This is particularly dangerous for destructive or expensive steer messages. In my case it caused repeated cache/backend work and repeated verification/documentation passes. With a different steer, the same mechanism could re-run deletion, rollback, large refactor, or external-service operations.
This looks like a state restoration issue rather than a model reasoning issue: after normal task_complete, the app does inject a hidden goal-continuation user message and the model resumes correctly. The failure appears specifically after compaction, where the older ordinary user steer becomes the latest visible user instruction again.
A robust fix likely needs one or more of:
- Preserve active
GoalContext/ goal-continuation state through compaction. - Mark manual steer messages as completed once a following
task_completehas handled them. - Include a compact checkpoint such as “last manual steer X was completed; current active work is Y.”
- Ensure replacement history after compaction does not make an old completed steer the latest actionable user message.
This seems closely aligned with the concerns in #21291 and #27894 and with the unmerged/draft direction in #22174.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗