Codex App incorrectly treats completed Steered conversation prompts as current tasks after compaction when a goal is active
What version of the Codex App are you using (From “About Codex” dialog)?
26.623.81905
What subscription do you have?
ChatGPT Pro 20x
What platform is your computer?
Microsoft Windows NT 10.0.26200.0 x64
What issue are you seeing?
Codex App incorrectly treats a completed Steered conversation prompt as the current task after context compaction when a goal is active.
The issue is not just that Codex sometimes refers to older context. The narrower problem is this:
- A goal-continuation turn is running.
- The user inserts a one-off Steered conversation prompt during that turn.
- Codex handles that Steered conversation prompt.
- Later, after context compaction, Codex may treat that already-handled Steered conversation prompt as if it were the current task again.
In the persisted transcript and compacted model-visible history, the Steered conversation prompt may look like an ordinary role: "user" response item. If replacement_history carries that message near the end without an explicit handled/closed semantic that is visible to the next continuation, the old prompt may receive too much priority as if it were still the current task.
There are two observable failures:
- Wrong final answer target: Codex does useful work for the current goal continuation, but the final visible answer responds to the old Steered conversation prompt.
- Wrong next task selection: Codex actually plans around the old Steered conversation prompt again and repeats work that was already done.
This appears to be a state tracking issue in the app harness around active goals, Steered conversation prompts, and context compaction.
A sanitized transcript shape is below. All values are synthetic placeholders.
A goal continuation may appear as user-like internal context:
{
"type": "response_item",
"payload": {
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "<codex_internal_context source=\"goal\">Continue working toward the active thread goal...</codex_internal_context>"
}
],
"internal_chat_message_metadata_passthrough": {
"turn_id": "goal-turn-1"
}
}
}
A Steered conversation prompt inserted during that running goal turn may be persisted as an ordinary user message with the same turn id:
{
"type": "response_item",
"payload": {
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "Steered prompt about Topic X"
}
],
"internal_chat_message_metadata_passthrough": {
"turn_id": "goal-turn-1"
}
}
}
After Topic X is handled, a later compaction may still preserve that completed Steered conversation prompt as a plain user message near the tail of replacement history:
{
"type": "compacted",
"payload": {
"replacement_history": [
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "Steered prompt about Topic X"
}
],
"internal_chat_message_metadata_passthrough": {
"turn_id": "goal-turn-1"
}
},
{
"type": "compaction"
}
]
}
}
The app should keep an equivalent state marker or other model-visible semantic that means "this Steered conversation prompt has already been handled and must not become the current task again." For example, the shape could be:
{
"source": "steered_conversation",
"scope": "interrupt_current_turn",
"handled": true,
"handled_by_turn_id": "goal-turn-1",
"must_not_become_current_task": true
}
The exact field names above are illustrative, not observed existing fields. The important invariant is that compaction must preserve an equivalent handled/closed semantic across the model-visible continuation boundary.
Without that distinction, after compaction the model-visible state may effectively look like this:
{
"active_goal_continuation": true,
"recent_user_like_message": "Steered prompt about Topic X",
"old_steered_prompt_is_marked_handled": false
}
That can make an already-handled mid-turn Steered conversation prompt look like the current task.
What steps can reproduce the bug?
A minimal reproduction shape:
- Start a long-running Codex App thread with an active goal.
- Let Codex begin a goal-continuation task,
Task Y. - While
Task Yis running, use Steered conversation to insert a one-off instruction or question,Topic X. - Let Codex handle
Topic Xand continue the active goal. - Do not submit another ordinary user prompt.
- Continue the goal long enough for context compaction and another goal continuation to occur.
- Observe one of these outcomes:
- Codex works on
Task Y, but the final response answers or summarizes completedTopic X. - Codex plans around completed
Topic Xagain and repeats work for it.
This reproduction is narrower than generic stale-prompt behavior:
{
"requires_active_goal": true,
"requires_mid_turn_steered_conversation": true,
"requires_steered_prompt_handled_before_failure": true,
"requires_no_later_ordinary_user_prompt": true,
"usually_triggered_or_amplified_by_compaction": true
}
Subagent notifications may make the issue easier to trigger if they are also represented as model-visible user messages, but the essential problem is the handled-state of a Steered conversation prompt across goal continuation and compaction.
What is the expected behavior?
A Steered conversation prompt should be a turn-scoped interruption. After Codex handles it, it should not remain eligible to become the current task again.
Expected harness behavior:
{
"steered_conversation": {
"event_type": "steer",
"scope": "current_turn",
"priority": "interrupt",
"after_handled": "closed"
},
"compaction": {
"preserve_handled_state": true,
"may_keep_completed_steer_for_history": true,
"must_not_promote_completed_steer_to_current_task": true
},
"final_response": {
"owner": "current_turn_id",
"must_not_answer_a_completed_steer": true
}
}
A completed Steered conversation prompt may remain in transcript history for auditability, but it must not compete with the active goal checkpoint or any later real user instruction.
Additional information
Accuracy note from source inspection:
turn_steer/steer_inputattaches the new input to the active turn and returns the active turn id, which matches the observed same-turn behavior.- Internal goal context is represented as a user-role model-context fragment.
replacement_historyis persisted as response items and is the history future prompts may carry after compaction.- The suggested
handled_by_turn_id/must_not_become_current_taskfields are only one possible fix shape; I have not observed those exact field names as existing persisted fields. - There are related source tests for steered input around mid-turn compaction, but this report is specifically about active-goal continuation and stale task ownership after compaction.
Potential harness-level fixes:
- Serialize Steered conversation as a distinct event type, or as a message with explicit model-visible metadata such as
source="steered_conversation",scope="current_turn", andhandled=trueonce handled. - Preserve the handled/closed state through compaction.
- Ensure
compacted.payload.replacement_historymust not make an already-handled Steered conversation prompt appear to be the current task. - Bind final visible response ownership to the current turn id.
- Treat internal goal continuation context and asynchronous notifications as structured non-user events or lower-priority metadata, not as ordinary user prompts competing with real user intent.
Regression tests that would likely catch this:
[
{
"name": "completed_mid_turn_steer_not_treated_as_current_after_compaction",
"setup": ["active_goal", "mid_turn_steer", "steer_handled", "compact", "goal_continue"],
"assertion": "planner_continues_goal_not_completed_steer"
},
{
"name": "final_response_owned_by_current_turn",
"setup": ["active_goal", "completed_steer", "new_goal_work_performed"],
"assertion": "final_answer_summarizes_current_turn_work"
},
{
"name": "replacement_history_preserves_handled_steer_state",
"setup": ["steer_handled", "compact"],
"assertion": "completed_steer_cannot_be_current_task"
}
]
Related issue family: #29811, #30767, #14318, #14667, #24225, and #8648.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗