Skip to content

Collapse queue/steer into one gesture, add stop-and-reinject, stop discarding queued input on interrupt - #431

Merged
TheGreatAxios merged 1 commit into
mainfrom
cl-5763-steering-is-broken-two-bindings-do-the-same-thing
Aug 9, 2026
Merged

Collapse queue/steer into one gesture, add stop-and-reinject, stop discarding queued input on interrupt#431
TheGreatAxios merged 1 commit into
mainfrom
cl-5763-steering-is-broken-two-bindings-do-the-same-thing

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Collaborator

Summary

CL-5763: three defects in the mid-run send/steer/interrupt bindings.

  • Plain Enter and Alt+Enter both queued mid-run and waited for a turn boundary — two gestures, one effect. Alt+Enter is now stop-and-reinject: it hard-stops the run immediately and restarts from the typed message, without waiting for a boundary. Plain Enter always queues to steer at the next boundary.
  • Queued/steered/reinjected rows now say so on the row itself ([will steer next], [steering], [restarted here]) instead of leaving the operator to infer intent from a badge count.
  • Interrupting (Ctrl+C) no longer discards queued or steered messages. It used to report interrupt — discarded N pending; it now reports interrupt — N queued message(s) will steer the next run, and those messages survive to steer whatever run starts next.

The chord check

Drove Shift+Enter through a live shell (tmux) rather than trusting the doc or the report. It does insert a newline, but only on a terminal that negotiates the kitty keyboard protocol (this app requests it via useKittyKeyboard); on a plain terminal Enter and Shift+Enter send the same bare \r, so the chord is a silent no-op there — which is what the operator saw. The shortcut list's existing wording ("Shift+Enter also works on terminals that report the modifier") already states that condition rather than promising it unconditionally, so it wasn't changed. Ctrl+Enter/Ctrl+J remain the newline chord guaranteed to work everywhere.

Sub-agent lanes on redirect

Both interrupt paths (Ctrl+C and Alt+Enter) close the underlying agent. That cascades: closing aborts the shared operation signal the task tool was given, which the tool forwards into the child agent's own controller, so an in-flight sub-agent dispatch is aborted along with the parent's turn and reports back as cancelled by the operator rather than running to completion detached. Decision: redirecting the parent stops the fleet it dispatched too — there is no path today to redirect the parent while leaving running lanes alone. Documented in docs/TUI.md.

Verified live (tmux)

  • Queued a message mid-run with plain Enter — transcript showed [will steer next], then [steering] once delivered at the boundary.
  • Queued a message, then interrupted before it drained — transcript showed interrupt — 1 queued message will steer the next run, badge stayed at 1, no discard. Sent a new idle message afterward and watched the surviving item steer into the new run as [steering].
  • Typed a message and hit Alt+Enter while a sleep 8 tool call was in flight — saw stop — restarting from your message and [restarted here] ..., the run stopped immediately, and a new run started from the reinjected message without waiting for the sleep to finish.

Test plan

  • bun run typecheck
  • bun run build
  • bun run test — 4277 pass, 0 fail
  • keybindings.test.ts (the chord-through-a-live-shell suite) updated: Enter/Alt+Enter/Ctrl+C/Ctrl+G probes cover the new kinds; Ctrl+C probe also asserts a queued item survives a bridge-less local interrupt
  • session-queue.test.ts, runtime-bridge.test.ts, shell.test.ts updated for the new interrupt/reinject semantics

@linear-code

linear-code Bot commented Aug 9, 2026

Copy link
Copy Markdown

CL-5763

… and stop discarding queued input on interrupt

Plain Enter and Alt+Enter both waited for a turn boundary before delivering,
so an operator had two gestures with the same effect and no way to tell them
apart. Alt+Enter now hard-stops the run and restarts from the typed message
without waiting for a boundary; plain Enter always queues to steer at the
next boundary, and the transcript row says so plainly ([will steer next] /
[steering]) instead of leaving the operator to infer it from a badge count.

Interrupting used to discard every queued and steered message ("interrupt —
discarded N pending"). An operator who queued an instruction and then lost
patience was destroying the thing they were trying to deliver. Interrupt no
longer clears the queue; it reports what will steer the next run instead.

Verified live: Shift+Enter does insert a newline, but only on a terminal
that negotiates the kitty keyboard protocol (this app requests it); on a
plain terminal Enter and Shift+Enter send the same bare \r, so the chord is
silently a no-op there. Ctrl+Enter/Ctrl+J remain the newline chord that
works everywhere, and the shortcut list's existing wording already reflects
that condition rather than promising it unconditionally.

Both interrupt paths close the underlying agent, which cascades an abort
into any in-flight sub-agent dispatch (task-tool.ts forwards the parent's
operation signal into the child's own controller) — redirecting the parent
stops the fleet it dispatched too, not just its own turn. Documented in
docs/TUI.md.
@TheGreatAxios
TheGreatAxios force-pushed the cl-5763-steering-is-broken-two-bindings-do-the-same-thing branch from c75f4d6 to 1e5af67 Compare August 9, 2026 06:25
@TheGreatAxios
TheGreatAxios merged commit 826c7ba into main Aug 9, 2026
2 checks passed
@TheGreatAxios

TheGreatAxios commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator Author

Merged.

Rebased onto post-#430 main so steering and interrupt delivery share one model:

  • Enter mid-run steers at the tool boundary (queue item, not a new send).
  • Alt+Enter stop-and-reinjects: interrupt, then rebuild-safe deliver for the next prompt; rebuild failure surfaces a not-delivered notice rather than dropping the message.
  • Ctrl+C keeps the queue and drains at interrupt via the Report fleet progress to the operator unprompted #430 deliver path (not boundary-only keep).

Transcript rows label pending intent; sub-agent abort-on-parent-redirect stays documented. CI snow flake (CL-5766) left alone — not this PR’s surface.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant