Goal mode replays the last manual steer on later continuation turns
What version of the IDE extension are you using?
26.5602.40724
What subscription do you have?
Pro 5x
Which IDE are you using?
VS Code
What platform is your computer?
Linux 6.18.33.1-microsoft-standard-WSL2 x86_64 x86_64
What issue are you seeing?
During an active /goal, if I manually steer the agent once, that steer can be handled correctly in the current active turn but then become salient again on later goal continuation turns.
The user-visible behavior is that Codex treats the last manual steer entered during the goal as if it were fresh work again, instead of treating it as already consumed by the active turn. This seems especially likely around compaction / resume boundaries, where the preserved history can make the old steer look like the latest real user request.
I originally framed this as hidden goal continuation context being persisted and replayed. After looking through #21291, #19910, #22045, and #22174, I think the broader issue is that manual steer input during an active goal lacks explicit consumed / turn-scoped lifecycle semantics, while goal continuation context also needs clear transient / reattachment semantics.
What steps can reproduce the bug?
- Start an active
/goal. - While the goal is running, manually steer the active turn with a short instruction.
- Let Codex handle that steer.
- Allow the goal to continue across later turns and/or compaction.
- Observe that the same manual steer can become salient again and be treated as fresh work.
A related core-level repro is to simulate resumed / compacted history containing a normal user steer plus goal continuation context. If fresh goal context is dropped or not reattached correctly, the older real user steer can remain the last preserved user message and regain salience as if it were the current request.
What is the expected behavior?
Manual steer input entered during an active goal should be visible to the model for the active turn, but once handled, it should not keep dominating later goal continuation turns as the latest real user request.
Goal continuation context should be regenerated or reattached from the persisted ThreadGoal at goal continuation / compaction boundaries. Hidden runtime context should not become stale durable replay history, but the active goal should still remain available to the model when continuation resumes.
Additional information
This seems closely related to #21291 and #19910, especially the #21291 failure mode where the last manual steer entered during an active goal becomes salient again after compaction and is treated as fresh work.
My reading is that #22045 improved one part of this by moving goal continuation / budget-limit steering from hidden developer context to hidden user context. However, the review discussion for that PR noted that hidden GoalContext could still be dropped by collect_user_messages() during compaction, leaving an older ordinary user steer as the last preserved user message. The follow-up discussion also acknowledged that compaction would need additional work.
That follow-up appears to have been #22174, which explicitly targeted the #21291 failure mode by preserving goal context during compaction, but it was closed as an unmerged draft. As a result, although #21291 and #19910 are now closed, this behavior appears not to be fully addressed: around goal continuation / compaction boundaries, the model can fall back to an older ordinary user message or manual steer and treat it as fresh work.
This suggests two complementary areas to check:
- Goal continuation context should be generated fresh from the persisted
ThreadGoalat goal continuation / compaction boundaries, rather than relying on stale hidden context persisted in replay history.
- Manual steer input entered during an active goal should have an explicit consumed / turn-scoped lifecycle, so once it has been handled in the active turn, it does not continue to dominate later goal continuation turns as the latest real user request.
These directions seem compatible with the issue described here: consumed manual steers should not dominate later goal turns, while hidden goal runtime context should have a clear transient / reattachment lifecycle instead of being relied on as stale durable replay history.
I locally explored a small patch direction that cleans up stale hidden goal internal context from replay history. I think that direction is compatible with the desired architecture, but it is not sufficient by itself: the user-visible stale-steer behavior also needs explicit consumed / turn-scoped semantics for manual steer input.
4 Comments
Adding corroborating macOS evidence and a current-source check. I initially opened #32627, but after following the issue cluster I agree this older report is the right canonical thread. I will close #32627 in favor of this one.
The important new point from my local traces is that an active
/goalis not required. Goal continuation appears to amplify the defect, but I found the same handled-steer replay during an ordinary active task.Redacted trace from Codex Desktop:
| Offset | Event |
|---:|---|
|
T+0s| User steers an active task with an integration, verification, and publish instruction. ||
T+15s| Assistant acknowledges the steer and begins that work. ||
T+45s|context_compacted||
T+50s| With no new user message, the assistant again announces the same integration, verification, and publish plan and restarts with repository checks. |The two assistant updates have cosine similarity
0.605. A second manually verified trace had the same shape for a request to set date defaults: acknowledgement, compaction 24 seconds later, then a second acknowledgement with no intervening user input. Similarity was0.516.Corpus check:
context_compactedI used similarity only to rank candidates, then manually checked event order. Prompt text, repository names, paths, and thread IDs are withheld.
Current source at
9e552e9still has the history shape described in this issue:Session::steer_inputqueues a steer asTurnInput::UserInput.record_pending_inputpersists it through the ordinary user-prompt path.user,developer, andsystemmessages verbatim under a 64,000-token budget, then appends the opaque compaction item.pending_inputcoverage verifies the first compaction and steer handoff. It does not cover a later compaction after the steer was processed and recorded.The issue history also explains why the earlier fix did not close the whole failure mode:
#31336 and #8648 report the broader symptom of arbitrary old prompts becoming active again. They may share the same task-ownership/history family, but those reports do not establish compaction or steer retention, so I would not claim one root cause for all of them yet. #30267 looks like stale UI pending-input restoration, and #30767 focuses on stale final-response ownership. Those may be adjacent defects rather than duplicates.
The strongest shared mechanism for the compaction subset is:
A focused regression should process a steer, perform a second compaction, and verify that the next model-visible state distinguishes the completed steer from the current task checkpoint. Merely asserting that the steer appears exactly once in the first post-compaction request does not cover this failure.
codex generated analysis:
This still reproduces in the Codex App with GPT-5.6 Sol Max.
Feedback ID:
019f48b9-86a4-74e3-abda-5a45bb45f6d2Second affected task:
019f48b9-7824-7d72-a756-1e0034bd9601App:
26.707.62119(5211)CLI:
0.144.1Platform: macOS
In the first task, the affected
/goalremained oneinProgressturn across several later user messages. It underwent three context compactions and emitted afinal_answerwithout 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
contextCompactionand 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.
Adding another independently observed reproduction, plus a source-level trace against current
main(2e4f55608b4ad26d9c48ea45a6fcd20bfd5e9fe8). This is seriously workflow-breaking in long-running tasks.Observed sequence in Codex Desktop:
This is not merely vague task drift: an already-consumed user instruction is promoted back into actionable state after compaction, despite intervening work and no new user submission.
Current source appears to preserve exactly the history shape that can cause this:
steer_inputqueues the steer as ordinaryTurnInput::UserInput.record_pending_inputpersists it through the ordinary user-prompt path. There is no persistedsource=steer, scope, or consumed/handled state; message metadata only carries a turn id.should_keep_compacted_history_itemdrops contextual user messages while retaining real user messages. This can remove fresh hidden goal-continuation context while preserving the older completed steer.The resulting model-visible shape can effectively be:
That makes the completed steer the most recent exact, explicit user instruction, while proof that it was handled exists only in compressed state. On every subsequent compaction it can regain the same salience, creating a repetition/context-consumption feedback loop.
There also appears to be a regression-test gap. The tests around
pending_inputverify the first compaction/steer handoff, but not the failing lifecycle:A regression should cover that sequence and assert that the next request distinguishes a completed steer from the current task checkpoint. Ideally a steer should have a durable turn-scoped lifecycle (
queued/handling/consumed) and a consumed steer should not be retained as an indistinguishable actionable user message. Goal continuation should also be regenerated from current goal state after compaction rather than being dropped.Related reports contributors may want to consolidate/check: #27731, #28874, #29811, #30859, #31099, and the corroborating duplicate #32627. The older exact report #21291 was closed, but its described failure still matches. PR #22174 explicitly attempted to prevent older real steers regaining salience by preserving goal context during compaction; it was approved but auto-closed for inactivity without merging. PR #22045 addressed adjacent goal-context behavior but its review explicitly noted that the compaction part still needed solving.
This behavior can redo file edits, commands, refactors, verification passes, or potentially destructive/external actions. It also forces users to repeatedly interrupt the agent to explain that the message was already handled. Please treat it as a serious state-restoration/idempotency issue rather than ordinary model forgetfulness.
I found a workaround for this issue: make sure that the last message is always "Okay", "Proceed", or similar.