Codex App: Goal compaction resurrects completed manual steer before goal continuation resumes

Open 💬 9 comments Opened Jun 24, 2026 by pcy06
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

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:

  1. Start a long-running /goal, e.g. “migrate a large project with full parity and keep working until complete.”
  2. During the goal, send a normal user steering message, e.g. “please implement the cache boundary using backend X and keep it extensible.”
  3. The agent implements that steer and finishes the turn.
  4. 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.
...
``

  1. The agent correctly resumes the broader goal and works on unrelated next parity/evidence tasks.
  2. 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.
  3. The next model turn treats the old steering message as the current unresolved user instruction and performs the same steering task again.
  4. When that repeated steering turn completes, the goal-continuation message is injected again, so the agent briefly returns to the broader goal.
  5. 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:

  1. 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.
``

  1. Let Codex complete at least one goal-continuation turn.
  2. 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.
``

  1. Let Codex implement that steering instruction and finish the turn.
  2. Let the active goal continue automatically. It should move on to unrelated broader-goal work.
  3. Wait for or force a compaction.
  4. Observe whether the next turn repeats the already-completed steering instruction before the goal-continuation context is re-injected.
  5. 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_complete has 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.

View original on GitHub ↗

9 Comments

github-actions[bot] contributor · 2 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #28874
  • #28892
  • #29582
  • #28925

Powered by Codex Action

joshp123 · 1 month ago

codex generated analysis:

This still reproduces in the Codex App with GPT-5.6 Sol Max.

Feedback ID: 019f48b9-86a4-74e3-abda-5a45bb45f6d2
Second affected task: 019f48b9-7824-7d72-a756-1e0034bd9601
App: 26.707.62119 (5211)
CLI: 0.144.1
Platform: macOS

In the first task, the affected /goal remained one inProgress turn across several later user messages. It underwent three context compactions and emitted a final_answer without the turn completing. After compaction, a completed earlier manual steer was repeatedly treated as the current request, even after newer steering messages.

The second task shows the same lifecycle failure independently. A user prompt was answered once. A later automatic goal continuation crossed contextCompaction and answered that consumed prompt again. The next automatic continuation repeated it once more without a new user message.

This looks like goal/turn lifecycle state being restored incorrectly during compaction, rather than a model-attention failure: a consumed steer regains actionable status while the current goal checkpoint and consumed-steer state do not.

feedback ID 1:
<img width="822" height="497" alt="Image" src="https://github.com/user-attachments/assets/1749d488-b38d-499e-a58d-9425e55b7757" />

<img width="758" height="241" alt="Image" src="https://github.com/user-attachments/assets/b43b5b78-7fb5-4eca-b765-9ff86c78c498" />

<img width="781" height="270" alt="Image" src="https://github.com/user-attachments/assets/a89ebcf2-88bf-47eb-81d2-24908af72734" />

feedback ID 2:

<img width="785" height="490" alt="Image" src="https://github.com/user-attachments/assets/62ee5798-5402-4b36-be6c-681bf708fb85" />

andrew-adamson-proteros · 1 month ago

I'm also affected by this in Windows.
Feedback ID 019f7d4d-3161-7ce3-bb2e-2d0b8155f671
Version 26.715.31925

Wastes tokens and causes the steering command to be given more weight than it should.

One workaround I've come up to stop it re-handling old steering messages is to give a follow-up message with something like this:
"This steering command is an empty command to deal with a codex compacting bug that re-sends previous steering messages. Ignore this message."

andrew-adamson-proteros · 1 month ago

Further info:

  • This occurs in any long running task, it is not limited to goal mode.
  • If there is no newer steering command, the newest steering command from the PREVIOUS PROMPT will be used.
  • This bug is still present in version 26.715.72359
  • This really should be labelled as a critical bug, given that it has the ability to completely change/break/redirect a task
huihaixiao-ctrl · 1 month ago

I am seeing the same failure mode in the Codex App's active Goal workflow with GPT-5.6 Thinking.

A concrete instance:

  1. A long-running Goal was active and had already completed several review/checkpoint steps.
  2. I sent a one-off steering instruction to freeze at a safe checkpoint, verify that no agents were still running and no changes were left uncommitted, and record the exact resume entry point.
  3. Codex completed that instruction and reported the checkpoint as finished.
  4. After automatic context compaction, the same completed steering instruction became salient again and Codex started executing it a second time instead of continuing from the latest Goal checkpoint.

This is not merely repeated wording: it can repeat commands, file edits, Git checks, reviews, or other side-effecting work. The issue appears to be that compaction preserves the old user steer but loses or underweights the state proving that the steer was already consumed/completed.

Expected behavior: a one-off user steer handled by a completed turn should remain marked as completed after compaction. The resumed turn should restore the latest Goal phase/checkpoint and next action, and should not treat the historical steer as the current actionable request unless the user sends it again.

A useful regression case would distinguish at least:

  • instruction lifecycle: one-off vs. persistent;
  • execution state: pending / in progress / completed;
  • the current Goal checkpoint and next action;
  • historical user messages vs. the active user instruction.

This report matches the positive-feedback-loop behavior described in the issue: replaying the stale steer adds more related context, making it increasingly likely to be replayed after later compactions.

XiaoTianFan · 23 days ago

Adding a current Windows reproduction with a slightly different—and especially damaging—variant: the resurrected message was the last ordinary user message from before the Goal was created, not a manual steer sent during the Goal.

Environment:

  • Feedback ID: 019fae90-5dd8-7721-860c-dc6b27d04fc0
  • Codex App (Microsoft Store): 26.727.6591.0
  • Bundled Codex CLI: 0.146.0-alpha.9.2
  • Platform: Windows x64
  • Model: GPT-5.6 Sol

I inspected the local Goal database and rollout JSONL read-only. The Goal was persisted as active in goals_1.sqlite; the session log then showed this sanitized control flow:

  1. The ordinary pre-Goal user message was answered and the turn emitted task_complete.
  2. A new Goal was created: thread_goal_updated → task_started → hidden user context <codex_internal_context source="goal">....
  3. The agent began doing the actual Goal work.
  4. Across eight automatic compactions, every replacement_history ended with the same pre-Goal ordinary user message followed by the compaction item. The retained tail did not contain the current hidden Goal continuation context.
  5. After multiple compactions, assistant commentary and even phase: "final_answer" returned to answering that already-completed pre-Goal message.
  6. After each stale final response, the turn emitted task_complete; only then did the next automatic Goal turn inject fresh hidden Goal context and resume the real objective.
  7. A later compaction restored the same stale pre-Goal message as actionable again, repeating the cycle.

Sanitized timestamps from one run (UTC):

18:05  pre-Goal turn final_answer + task_complete
18:18  thread_goal_updated; Goal task_started; hidden Goal context injected
18:39  compaction retains old pre-Goal user message, not current Goal context
19:53  same retained old-message tail
20:00  final_answer answers the stale pre-Goal question; task_complete
20:00  next Goal task starts and injects fresh Goal context
21:14  same stale-message retention after compaction
22:41  same stale-message retention
22:46  another final_answer answers the stale pre-Goal question; task_complete
22:46  next Goal task injects fresh Goal context
01:02  same stale-message retention
02:01  same stale-message retention
03:41  same stale-message retention
03:43  another stale final_answer; task_complete; Goal context then re-injected
04:44  same stale-message retention again

This confirms two important points:

  • The bug is not limited to a steer delivered during an active Goal. Any ordinary message immediately preceding Goal creation can become the replay anchor.
  • It contaminates the final conclusive response, not only intermediate reasoning/commentary. The agent can perform substantial Goal work and then conclude by answering the unrelated historical prompt.

This looks deterministic at the history/lifecycle layer rather than ordinary model drift: compaction repeatedly preserves the exact old user message while the state proving it was completed and the current Goal checkpoint are compressed or absent; task_complete then causes Goal context to be reattached only for the next cycle.

A focused regression should cover:

ordinary user prompt A
→ assistant answers A + task_complete
→ create Goal B
→ work on B
→ compact
→ assert A is historical/consumed
→ assert Goal B checkpoint/continuation is current
→ final_answer must belong to B, not A
→ compact again and repeat the assertion

Please treat this as an instruction-lifecycle / final-response-ownership issue in addition to compaction salience. Replaying a completed prompt can repeat edits, commands, or external actions, and in this reproduction it repeatedly displaced the Goal's own conclusive response.

nos1609 · 22 days ago

Adding a current Linux reproduction from a very large, long-running Goal thread.

Affected thread ID: 019f43ac-20b8-7ad1-965b-3b2e6460255d
Client: Codex CLI 0.146.0
Platform: Linux x86_64
Model: GPT-5.6 Sol

I inspected the canonical root rollout read-only. No session content, local paths, repository names, hostnames, or account details are included below.

48-hour evidence

From 2026-08-03T12:20Z through 2026-08-05T12:20Z:

  • 43 hidden Goal continuation turns carried the same objective.
  • 59 automatic context compactions occurred.
  • 44 task_complete events occurred.
  • 6,730 tool calls were recorded.
  • Raw token telemetry increased by 1.237 billion tokens, including 1.207 billion cached input tokens.
  • The root rollout grew to approximately 1.65 GB.

Several final_answer events stated that all non-gated work was complete. Later Goal continuations reopened and re-reviewed the same acceptance surfaces, then produced another completion statement. Completed one-off steering instructions also regained salience after later compactions.

Latest native compaction structure

The latest inspected native compaction was window_number: 702. Its replacement_history contained 495 items:

  • 493 message items with role: user
  • 1 message item with role: developer
  • 1 encrypted compaction item
  • 0 assistant messages

The serialized replacement history was approximately 1.27 MB. The retained user messages contained about 63,500 text characters. This means hundreds of historical user instructions remained visible after compaction, while the responses and lifecycle state proving that they were completed were represented only indirectly by the encrypted compaction item.

This matches the instruction-lifecycle failure described in this issue: old consumed prompts remain structurally prominent, while the current Goal checkpoint and completion ownership lose salience.

Control observations

The Goal was removed after the repeated review loop. No further hidden Goal continuation messages appeared after removal, which confirms that the Goal lifecycle was one part of the loop.

A later ordinary user turn still inherited the same long native history and reached 244,251 input tokens against a 258,400-token context window. Removing the Goal therefore stops automatic continuation, but it does not repair the already contaminated compacted history.

A local context handoff hook was also enabled. Its delivery was one-shot: 59 compactions produced 59 unique generations with no duplicate injection. The hook had a separate stale-tail selection problem that amplified old-request salience. However, the native compacted.replacement_history independently showed the 493-user / 0-assistant structure above.

Expected behavior

After task_complete, a handled steering message must remain historical and non-actionable across compaction. The compacted state should preserve:

  • the current Goal checkpoint and next action;
  • whether each user instruction is pending, active, completed, or aborted;
  • final-response ownership;
  • enough completion evidence to prevent replay of consumed instructions.

A completed prompt must not become actionable again merely because later history was compacted.

andrew-adamson-proteros · 7 days ago

@tibo-openai This. This is the easy stuff that you're missing. Bugs that affect every desktop user, are obvious, chew tokens for no reason, are easy to fix, and haven't been addressed for several months. I don't want new features - I just want to use Codex without every single update introducing new and exciting bugs.

Additional Windows reproduction on a later build.

Environment:

  • Codex App: 26.818.2441.0
  • Bundled CLI: 0.148.0-alpha.15
  • Model: GPT-5.6 Sol, medium reasoning
  • Platform: Windows 11 Pro 10.0.26200 x64

During a long running goal task:

  1. I sent a harmless one-off instruction: just checking if the replay bug has been fixed. Say "ding!" and continue.
  2. It was answered once, and I did not send it again.
  3. The conversation then recorded eight native compacted events, from 2026-08-20T12:49:08Z through 2026-08-21T01:18:49Z.
  4. Every replacement_history retained the old user message containing the ding! instruction. The visible retained message items contained user/developer messages plus the compaction item, but no assistant message item and no visible <codex_internal_context source="goal"> marker.
  5. Agent-message records containing ding! occurred at:

2026-08-20T07:18:54Z, 13:53:38Z, 14:38:13Z, 16:23:37Z, 17:38:24Z, 19:01:56Z, 23:51:53Z, and 2026-08-21T01:18:54Z.

This is a later Windows reproduction than the existing Windows report in this issue and provides a concrete replay sequence across eight compaction windows.

Expected behavior: once a one-off instruction has been consumed, it must remain historical across compaction and continuation. The next turn should resume the current checkpoint and must not re-play steering commands.

Minimal reproduction: start a long-running task, send a harmless distinctive instruction such as Say "ding!" once and continue, let it complete and continue into unrelated work, allow multiple compactions, and do not resend the instruction. Repeated "ding!" output after compaction reproduces the issue.

3amcinnamonroll · 3 days ago

This is a closely related variant in the Codex desktop app on macOS.

Summary

An earlier question was resolved through a revised goal. The user then activated that replacement goal, and Codex began executing it. Automatic context compaction occurred. Immediately afterward, Codex answered the earlier question as though it were still pending.

This suggests compaction retained the question but lost its disposition: resolved, superseded, and incorporated into the active goal.

Cleaned transcript

User:

The goal needs to avoid over-engineering and later backing out that over-engineering. Does this proposal pass an Occam's-razor test?

Assistant:

[Evaluates the proposal and supplies a revised, narrower goal.]

User:

/goal [the revised goal supplied by the assistant]

Assistant:

[Acknowledges the active goal, reconstructs repository state, begins the work, and launches bounded read-only audits.]

Assistant:

Baseline reconstruction is clean. The implementation work is underway, with one remaining architectural uncertainty being audited.

System/UI:

Context compacted

Assistant:

Mostly yes. It is broad because it finishes the cutover, but it does not prescribe a broad architecture...

Actual behavior

After compaction, Codex answered the first user message even though that question had already been resolved by the revised goal, which had subsequently been activated and was already being executed.

Expected behavior

Codex should continue the active /goal. The earlier question should remain marked resolved or superseded and should not be answered again.

Impact

No destructive action resulted in this instance, but losing request disposition after compaction could:

  • reopen settled decisions;
  • duplicate or contradict completed work;
  • divert an agent from an active goal;
  • make the user uncertain whether execution state survived compaction.

Privacy cleanup

Repository names, paths, commit hashes, database identifiers, project data, agent names, and unrelated transcript content have been removed.

This differs slightly from a mid-goal manual steer: the resurrected question was resolved before the replacement /goal was activated.