Interrupt can merge queued follow-up input with later composer text into a single next-turn message

Open 💬 2 comments Opened Jun 23, 2026 by starSumi

Summary

Queued follow-up input can be merged with later composer text after an interrupt, and the next turn is then persisted as a single user message.

I am not reporting only a historical log reconstruction here. I reproduced this locally against codex-cli 0.142.0 on Windows 11 using a live interactive codex session, and then verified the resulting history and rollout files on disk.

The confusing part is that two distinct user intents become one next-turn message:

  1. a follow-up that was explicitly queued while a turn was running
  2. additional text typed later into the composer before interrupting that running turn

After Esc interrupts the running turn, pressing Enter submits both as one merged message.

Environment

  • Codex CLI: 0.142.0
  • Platform: Windows 11
  • Shell host: PowerShell 7 terminal environment
  • Working directory during repro: E:\Zero_Base\sumi_os
  • Reproduced on: June 23, 2026

Reproduction

I was able to reproduce this with a live interactive session:

  1. Launch codex --no-alt-screen.
  2. Submit a long-running prompt, for example a prompt that makes Codex run:
  • pwsh -NoProfile -Command Start-Sleep -Seconds 60
  1. While that turn is still running, type a follow-up marker and press Tab so it becomes queued.
  2. Without submitting, type additional text into the composer.
  3. Press Esc to interrupt the running turn.
  4. Press Enter once after the interrupt restore.

Actual Behavior

The queued follow-up and the later composer text are merged into a single next-turn user message.

In my live repro, the next persisted user message became:

FOLLOWUP_mixq_20260623_1
 IMPL_mixq_20260623_1

This was persisted as one message in both local history and rollout state, even though those two pieces of text were entered in different phases:

  • the first line was explicitly queued during the running turn
  • the second line was typed later into the composer before the interrupt-driven resubmission

Expected Behavior

One of these should happen instead:

  • queued follow-up input and later post-interrupt composer text should remain distinct
  • the UI should explicitly show that they are about to be merged before submission
  • persisted telemetry should record enough queue / restore metadata to make the merge unambiguous during later debugging

Why This Looks Real Rather Than User Confusion

The persisted sequence in the live repro matched the behavior I saw:

  1. the first turn started
  2. the first user message was persisted
  3. the turn was persisted as turn_aborted with reason interrupted
  4. the next turn started
  5. the next user message was persisted as the merged follow-up plus later draft

So this is not just a UI impression. The merged next-turn message shows up in durable local history.

Relevant Source Paths

The current local source also appears consistent with the observed behavior:

  • tui/src/chatwidget/input_flow.rs
  • running or not-yet-configured input is queued in queued_user_messages
  • tui/src/chatwidget/input_restore.rs
  • on_interrupted_turn() restores queued messages into the composer
  • queued messages are merged with the current composer state instead of being kept as a separate submission boundary

There are already tests around the individual pieces of this behavior, for example:

  • startup queued input submission
  • interrupt restoring queued messages into the composer
  • interrupt prepending queued messages before existing composer text

The issue is the combined outcome: distinct user intents can collapse into one next-turn message.

Notes

  • I also hit a local rusty_v8 Windows symlink privilege problem when trying to run the Rust test target directly, so my strongest evidence here is the live interactive repro plus the persisted rollout/history verification.
  • I think there may be two related concerns:
  • the product behavior itself
  • observability, because the persisted rollout does not seem to expose a first-class queued_input marker that explains this merge directly

View original on GitHub ↗

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