Skip to content

Let the operator cancel the most recently queued message - #359

Merged
TheGreatAxios merged 2 commits into
mainfrom
cl-5572-cancel-queued-message
Aug 7, 2026
Merged

Let the operator cancel the most recently queued message#359
TheGreatAxios merged 2 commits into
mainfrom
cl-5572-cancel-queued-message

Conversation

@TheGreatAxios

@TheGreatAxios TheGreatAxios commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Ctrl+G cancels the newest queued or steered message: retracts it from SessionQueueState and marks its transcript row with a cancelled flag. paintStreamRow reads that flag and renders the [cancelled] prefix for user rows — row.text itself stays exactly what the operator typed, so copy-mode and anything else reading text sees the original message, not a mutated one.
  • Keybinding: Ctrl+G. Unclaimed by both TextareaRenderable's default bindings (checked against the bundled defaultTextareaKeyBindings table) and this shell's other chords. Readline/Emacs users already read it as "abort" — unlike Ctrl+X, the first attempt's pick, which is cut/prefix muscle memory.
  • Scope: last-only. cancelLast retracts the newest item regardless of kind (queue or steer). Reaching an earlier item would need a picker overlay — not justified without an operator asking for it. Editing a queued message (also named in CL-5563) stays out of scope.

Verification

  • bun run test — 3970 pass, 0 fail
  • bun run typecheck — clean
  • bun run build — clean
  • Regression tests assert on the rendered frame (captureCharFrame()), not only shell.streamLog — the exact gap that let the first attempt through. Covered for both queue- and steer-kind cancels, in session-queue.test.ts, shell.test.ts, and keybindings.test.ts.
  • Rendered before/after, withTestRenderer:

Before:

▍ keep this one
▍ oops wrong message
 queue 2

Row model: [{"text":"keep this one","meta":"queue"},{"text":"oops wrong message","meta":"queue"}]

After applyShellCancelLast:

▍ keep this one
▍ [cancelled] oops wrong message
 queue 1

Row model: [{"text":"keep this one","meta":"queue","cancelled":undefined},{"text":"oops wrong message","meta":"cancelled","cancelled":true}]text is unchanged; only the flag and the paint output differ.

Closes CL-5572

@linear-code

linear-code Bot commented Aug 7, 2026

Copy link
Copy Markdown

CL-5572

Ctrl+G retracts the newest queue or steer item and rewrites its
transcript row rather than leaving it tagged as still pending, so the
readout cannot show a cancelled message as one that will still
dispatch. Chose Ctrl+G because it is unclaimed by both the textarea's
own bindings and this shell's other chords, and readline/Emacs users
already read it as "abort", unlike Ctrl+X (cut, readline prefix).

Cancellation targets the last item only. Selecting an earlier item
would need a picker overlay; last-only is an honest minimum until an
operator actually asks for more.
paintStreamRow now owns turning a cancelled user row into the
"[cancelled]" prefix, reading a new cancelled flag on StreamRow.
row.text stays exactly what the operator typed, so copy-mode and
anything else reading it back are unaffected by the cancel.

Regression tests now assert on captureCharFrame() before and after a
cancel, not only on shell.streamLog, and cover a steer-kind cancel
alongside queue in session-queue.test.ts, shell.test.ts and
keybindings.test.ts.
@TheGreatAxios
TheGreatAxios force-pushed the cl-5572-cancel-queued-message branch from 912a2db to 906a207 Compare August 7, 2026 07:39
@TheGreatAxios
TheGreatAxios merged commit 6af12df into main Aug 7, 2026
2 checks passed
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