Handled steer can be re-acknowledged as new after a later compaction

Resolved 💬 2 comments Opened Jul 12, 2026 by Jc-Cloete Closed Jul 12, 2026

What version of Codex is running?

Current desktop app: 26.707.51957

Current desktop rollout metadata reports bundled CLI 0.144.0-alpha.4.

The local traces below span bundled CLI versions from 0.100.0-alpha.10 through 0.142.0-alpha.1, so this does not look specific to one release.

What subscription do you have?

ChatGPT subscription. The exact tier does not appear relevant to the client-side history behavior described below.

Which model were you using?

Observed across long-running Codex Desktop tasks. Not model behavior it's most likely harness.

What platform is your computer?

macOS 26.5.1, Apple Silicon (arm64)

What issue are you seeing?

A steering message can be handled once, then treated as newly relevant again after a later automatic compaction.

The sequence looks like this:

  1. Codex is already working on a task.
  2. I send a steering message.
  3. Codex acknowledges the steer and continues working with it.
  4. A later automatic compaction completes.
  5. With no new user message in between, the next assistant update acknowledges or restarts the steered work again.

This is not the older failure where compaction forgets the task that existed before the steer. In this case, Codex remembers the steer too strongly and presents it to the model as if it still needs first-time handling.

Redacted local evidence

I scanned 3,125 local Codex rollout files from 2026. The archive contained 82 unique root tasks where a user steer occurred before a later context_compacted event. I then manually checked the strongest candidate timelines rather than relying on text similarity alone.

Trace A:

| Offset | Recorded event |
|---:|---|
| T+0s | User steer asks Codex to integrate completed work, verify it, and publish it. Prompt fingerprint: e508c3f08a9d. |
| T+15s | Assistant acknowledges the steer and says it will integrate, verify, and publish. |
| T+45s | context_compacted |
| T+50s | Assistant again says it is going to integrate, verify, and publish, starting with repository checks. |

There is no user message between the first acknowledgement and the second one. Cosine similarity between the two redacted assistant updates is 0.605.

Trace B:

| Offset | Recorded event |
|---:|---|
| T+0s | User steer asks for date selectors to default to today's date. Prompt fingerprint: 859aca120fa2. |
| T+17s | Assistant says it will implement today's date defaults and starts inspecting the relevant file. |
| T+41s | context_compacted |
| T+47s | Assistant says it is implementing today's date defaults and starts inspecting the same flow again. |

Again, there is no intervening user message. Cosine similarity between the two assistant updates is 0.516.

I have kept project names, paths, prompt text, and thread IDs out of this report. I can provide the original thread IDs privately if an OpenAI maintainer needs them.

Why I think this is a history-shape problem

This section is an inference from current source, not proof of the server-side compaction summary.

On current main at commit 9e552e9:

  • steer_input queues the steer as TurnInput::UserInput.
  • record_pending_input records that steer through the ordinary user-prompt path.
  • The turn loop intentionally drains a pending steer only after a post-compaction continuation when needed. The behavior is described in turn.rs and covered by pending_input.rs.
  • Remote-v2 compaction retains recent user, developer, and system messages verbatim under a 64,000-token budget, then appends the opaque compaction output. See compact_remote_v2.rs and the retention code.

The likely failure mode is that a mid-turn steer loses its lifecycle once it is recorded. It becomes a bare recent user message with no model-visible indication that it arrived during active work and has already been absorbed. A later compaction retains that message, which can make it salient again as an unhandled instruction.

The remote compaction item is encrypted in the local rollout, so I cannot inspect its contents or claim that the server summary repeats the steer. The observable timeline and the retained-message code are enough to show the issue without making that stronger claim.

What steps can reproduce the bug?

This depends on hitting automatic compaction, but the following sequence has reproduced it in real long-running tasks:

  1. Start a task that will run long enough to approach the automatic compaction threshold.
  2. While Codex is still working, steer with a small additional requirement, for example: Also default the date fields to today.
  3. Wait until Codex explicitly acknowledges the steer and starts applying it.
  4. Continue the same task until the next automatic compaction finishes.
  5. Inspect the first assistant update after context_compacted.
  6. The assistant may acknowledge the same steer again or restart the already-started work.

A deterministic regression test may need two compactions: one around the active-turn steer handoff, followed by another compaction after that steer has been processed and recorded.

What is the expected behavior?

Once Codex has absorbed and acted on a steering message, later compactions should preserve the result and remaining work without presenting the steer as fresh input.

The model-facing state needs to distinguish at least these cases:

  • a newly queued steer that has not been seen by the model;
  • a steer currently being handled;
  • a steer already absorbed into the active task;
  • an ordinary user turn that should remain a fresh instruction after resume.

Related issues

  • #9734 reports the opposite failure: steer plus compaction can preserve only the steer and lose the earlier task.
  • #28892 discussed unfinished-task continuity around steer and compaction, but it was closed at the author's request. It does not document the repeated acknowledgement after a later compaction.

Possible regression coverage

Add a test where a steer is delivered and processed, then a second compaction occurs. The request after the second compaction should carry model-visible state that marks the steer as already absorbed, or should preserve its effect through the compacted task summary without retaining it as an indistinguishable fresh user instruction.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗