Skip to content

feat(tui): Next transcript/composer shell (T3) - #429

Open
BunsDev wants to merge 5 commits into
feat/409-brand-primitivesfrom
feat/410-next-shell
Open

BunsDev wants to merge 5 commits into
feat/409-brand-primitivesfrom
feat/410-next-shell

Conversation

@BunsDev

@BunsDev BunsDev commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Refs #410. Stacked on #427 (#409), which is stacked on #426 (#408). Retarget to main after those merge. Classic stays the default renderer.

What this ships

The first usable Next journey (COVEN_CODE_UI=next): launch from a fresh home, see the workspace, write a multiline draft, submit, stream, scroll, inspect, cancel and quit.

  • Layout (next/layout.rs) follows the accepted docs: establish the TUI v2 source and compatibility baseline #421 thresholds. Below 80x24 is Focus, and below 120x32 is Single; in both the inspector replaces the main pane. At 120x32 and up, Split shows a transcript of at least 72 columns, a divider and a 40 to 60 column inspector. Rows are given out by priority (composer, status, header, rule, main, hints), so 20x6 down to 0x0 never underflows or hides the composer.
  • Workspace line: project, session title, model and familiar. The familiar is labeled (unverified) because a display name is not identity before [TUI v2][P0] T5: unify session/familiar navigation, identity visibility, and reconnect recovery #412. Optional parts are dropped from the end when they don't fit.
  • One inspector (Alt+I) with Activity, Session and Views pages. A new Inspector keybinding context is layered over Chat, so Escape closes the inspector first, Tab pages through it, and every other key still edits the draft. Views lists Work, Research and Memory as unavailable with their blocking issue ([TUI v2][P1] T6: expose Psyche-backed tasks, dependency tracking, lanes, and durable goals natively #413, [TUI v2][P1] T7: add a native research workbench with source provenance, citations, and resumable artifacts #414, [TUI v2][P1] T8: add a private, read-only familiar-memory inspector and explicit context selection #415); nothing is placeholder content. Commands remain the existing Ctrl+K palette and / suggestions.
  • Reading position: a scrolled reader stays on the same text while output arrives below or is removed, for example when a cancel clears live text. The offset is rescaled when the transcript rewraps and clamped to the scrollable range. A notice shows new activity and the jump-to-live key (Alt+L). Tool starts never move focus or position.
  • Cancellation (Next): Escape during streaming records a request that the loop performs through the turn's cancellation token. Next shows cancelling until no worker remains, then Cancelled.. A remote-control cancel also waits for the runtime.
  • Composer: the terminal cursor follows the draft for IME input, including wrapped, wide-character and taller-than-composer drafts. A non-empty draft is labeled draft not sent. Pasted newlines or / text never submit, and large pastes keep the existing placeholder.
  • Fallbacks: images and documents in messages, and pending image attachments, render as text such as [image shot.png 640x480]. Voice recording shows in the status line.
  • Selection: the Next transcript pane is now the selection and copy target, through Classic's row cache and highlight. Per-message hit maps stay empty, so nothing targets Classic's layout.

Classic is unchanged

Every new behavior is limited to Next. Classic's Escape and Ctrl+C handling, keys, goldens and docs match the #409 head.

A Classic bug was found and left alone. Escape during streaming only resets the screen: the turn keeps running and its output lands later, while the docs say Escape stops generation. This was reproduced on a65df294 with a fake claude. Next cancels through the turn's token. Fixing Classic the same way is a one-line change, which can be its own PR if you want it.

Review

An independent reviewer read faf60b8. The second commit resolves the findings:

Finding Resolution
The cancel outcome was never shown because the loop cleared the status settle_cancellation reports Cancelled.
A remote-control cancel was shown as done before the runtime stopped note_cancellation_sent keeps it pending
A cursor in a tall draft was hidden The composer scrolls to the cursor row
An earlier line with wide characters put the cursor on the wrong row Rows are counted with the same walk wrap_line uses
The anchor ignored shrinking, rewrap and over-scroll Signed correction, rescaling on width change, clamping
Inspector scroll had no upper bound Bounded by the last drawn page
The tmux completion check was vacuous, with only one resize The fake now finishes at 6s and is checked after 7s; resizes to 80x24, 40x12 and 120x40

The five new unit tests fail on faf60b8 and pass on the fix.

Not changed, recorded here instead:

  • A user chord that starts with Alt+I or Alt+L, such as alt+i alt+j, now resolves at the first key. Rebind or unbind the new action to restore it.
  • While the inspector is open, PageUp and PageDown scroll the inspector, not the Split transcript.
  • Inspector hints don't consider CHAT_FIXED_ROUTES.

Verification

All results are on the head of this PR.

Check Result
cargo test -p claurst-tui --locked --test next_shell 18 passed
cargo test --workspace --locked --no-fail-fast 2838 passed, 0 failed, 52 ignored
cargo clippy --workspace --all-targets --locked -- -D warnings clean
Default keybinding golden regenerated: 8 added lines, nothing else changed
tmux case 08_next_shell (real binary, fake claude, disposable home) 27/27; the quit check waits for the app to exit (51a7705)
Full tmux suite at 120x40 75/75
Full tmux suite at 80x24 69/71; both failures are the Classic help overlay (#423), same as the #409 baseline

The fake claude proves the shell journey only. It is not evidence for tools, approvals (#411), sessions (#412), tasks, research or memory.

Still open for #410

Build the first usable Next journey on the #408 seam and #409 primitives:
workspace line, transcript, status, persistent multiline composer and one
inspector.

- Layout follows the accepted #421 thresholds: Focus below 80x24, Single
  below 120x32 (inspector replaces the main pane), Split at 120x32 and up
  (transcript, divider, 40-60 column inspector). Rows degrade in a fixed
  priority so 20x6 and smaller never underflow or hide the composer.
- One inspector (Activity, Session, Views) layered over the composer's
  keys: Escape closes it before anything else, Tab pages, the draft and
  cursor stay editable. Views lists Work, Research and Memory as
  unavailable with their blocking issue instead of placeholder content.
- A scrolled reader keeps their position while output streams, sees a
  new-activity notice and returns with jumpToLive. Tool starts never move
  focus or position.
- Escape during streaming now records a cancel request that the loop
  performs through the turn's token, so the runtime actually stops; it
  previously only reset presentation state while the turn kept running.
  Next shows cancelling until no worker remains.
- Terminal cursor sits in the composer for IME input; unsent drafts are
  labeled; images and documents render as text stand-ins; Next registers
  its transcript as the selection target.
- Inspector context and toggleInspector/jumpToLive bindings go through
  the configurable keybinding system; Classic treats the new chords as
  unbound.
- tmux journey case drives a fresh-home Next session through draft,
  inspector, paste, submit, stream, scroll, resize, jump, cancel and quit
  against a fake claude, then checks terminal restoration.

Refs #410
- Show the confirmed outcome: settling a cancellation reports
  "Cancelled." after the loop clears the turn status; a remote-control
  cancel stays pending until the worker stops.
- Keep the composer cursor row visible in drafts taller than the composer
  and count wrapped rows with the same walk wrap_line uses, so wide
  characters on earlier lines no longer misplace the cursor.
- Reading anchor: track signed row changes below the reader (growth and
  removal), rescale on rewrap, clamp to the scrollable range.
- Bound inspector scrolling; show voice recording in the status line.
- Regenerate the default keybinding golden for the eight new bindings.
- tmux case: resize at each step, make the completion check real, and
  check that Escape stops a running turn in Classic too.

Refs #410
@vercel

vercel Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
docs Ready Ready Preview Nov 2, 2026 5:59am UTC

Request Review

Keys typed while the app is still exiting are read by it and lost, which
made the cooked-mode check intermittently fail.

Refs #410
Runtime cancellation through the turn's token, the pending
'cancelling' state and the settled outcome now apply to the Next
renderer only. Classic resets its screen state as before, and its
docs paragraph is restored.

Refs #410

This branch was successfully deployed

1 active deployment
Preview — 9bbe6f17 Deployed Nov 2, 2026 by vercel[bot]
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