cmux NEXT transcript: one row grammar for send, command and subagent rows (carry #28291)
This carries #28291 with its commits and authorship kept, merged up to feat-cmux-next, and fixes the review's BLOCK.
What this carry fixed
- BLOCK: a duplicate aria-hidden control. "Subagent finished"'s chevron was a second clickable element (
aria-hidden,onClick) beside the line's real open button, so it was hidden from assistive tech. Now the chevron only draws: no handler, no tab stop, not a button. The open button is the line's one control, and its hit area spans the row under the words (.cv-subagent-done::before). The duration and chevron pass clicks through to it (pointer-events: none), so clicking the chevron still opens the subagent. Restart, Retry and ⋯ stay their own buttons above it. The status words and chevrons still sit on one x. - The same pattern on message rows. This PR also moved AgentMessageRow's chevron out of the toggle as a clickable
aria-hiddenspan. It gets the same fix: the toggle's hit area reaches the status and the chevron. - Base merge. One conflict, in
SubsessionCallCard.css. Base's #463e538 ("the arrow over every button") had restyled.cv-sent__target, which this PR replaces with the recipient chip, so the chip's rules are kept. This PR's newcursor: pointerrules becomecursor: default, per that base change. - Not changed: the received report row ("grid-lane …"), whose chevron sits off the column at x≈485 in the old after still. It is IncomingMessageCard's DisclosureRow, not a component this PR touches, so it is a follow-up.
Test: RowGrammar.test.tsx adds two tests. One asserts a done line has exactly one focusable control, and that its chevron (aria-hidden, no tab stop, no handler) opens nothing when clicked on its own while the button does. The other asserts a message row's chevron does not toggle it. RUNS_PLACEHOLDER
MEDIA_PLACEHOLDER
Original body of #28291:
Leo, 2026-10-29: "this ui isn't consistent :(" and "this rendering can be better for sent stuff".
Every tool row in the transcript now follows one row grammar (design/chat-transcript.md, "One row grammar", teamleaderleo/leo-workspace#1663):
- Verb pattern. A shell
acpmux sendor sub-sessionsend_messagerow now reads "Sent to " ("Sending to" while it goes out), as SendMessage rows already did, instead of "Sent message to". - One recipient style. Both send rows show the recipient as the same chip (
.cv-agentmsg__name). The underlined link is gone. The chip still opens the recipient's chat when the session list knows it. - Fixed trailing column. Status ("Queued", "Delivered"), then duration, sit in grid column 3, right before the chevron in column 4 of the shared
.cv-toolgrid. AgentMessageRow used to be a flex row that put the chevron before its optional meta, so the chevron moved depending on whether a status was present. It is now the shared grid. The shell send's "· queued" moves out of the sentence into that column, and "Subagent finished: … · 2m 28s" moves its duration there too and gains the chevron its rows lacked. Rows with no status keep the column empty, so every chevron sits on one x. - One truncation rule. The sentence column ends in one ellipsis, and the preview (
.cv-agentmsg__preview) is the span that takes the cut. - Sent rows are compact. Shut, a send shows its first line once. Open, the line drops it and the message shows once below, with Raw still under it.
- No narration (transcript audit, cmuxterm-hq#5154): the started sub-session row drops its "Started sub-session" prefix. It is now the session's name next to its harness mark, per the transcript rule that the icon names the type.
Kept: colours, fonts and glass; expanding still shows the full message; Raw stays; the hover row (Copy, Reply) stays; Restart and Retry on subagent lines stay. Not touched: the composer, Session Info, the sidebar and menus.
Gallery
New entry agent-pane.transcript-row-grammar shows the four rows side by side (SendMessage, acpmux send, Ran 2 commands, Subagent finished) in four variants: chip (shipped), link, plain, and open. I picked the chip: it already marks a recipient in received rows, it stays legible next to a muted preview, and unlike a link it doesn't suggest navigation when the recipient opens nothing. Before/after comes from this PR's gallery advisory run (run 41087816263, agent-pane.agent-message-row, 420 px, Chromium). I viewed both pairs: in the after shots, every status word and chevron sits on one x, the failed send's reason moves out from under its chevron, and "Subagent stopped" gains its duration and chevron.
| Before | After | |
|---|---|---|
| Sends (dark) | ![]() | ![]() |
| Sends (light) | ![]() | ![]() |
| Outcomes (dark) | ![]() | ![]() |
The run flags one play check, a layout shift when a sent row opens (sent-opened, 0.0945). The base gives 0.0951 for the same check, so this PR doesn't introduce it.
Tests
RowGrammar.test.tsx renders the four row kinds side by side and checks:
- the column order (icon first, trailing column right before the chevron, chevron last);
- "Sent to" on both sends, with exactly one recipient chip;
- "Queued" in the trailing column and not in the sentence;
- one preview span, cut by the shared rule;
- the subagent duration in the trailing column;
- an opened send not repeating its first line;
- the grid columns in the stylesheet;
- the narration prefix being gone.
SentMessageLine.test.tsx is updated for the new words.
Observed / Not run
- Ran pr-overlap against feat-cmux-next: no overlapping open PRs (the search fell back to a 29-minute-old list).
- Strict fast-checks dispatch (16 focused bun files, then
bun run check, underset -o pipefail) at b7a49f1 (run 41083915458): 139 pass, 0 fail.check:design-tokensflagged the gallery's 20px padding, which f6f8ef1 fixed by moving it to 16px on the spacing scale.check:fixed-waitsreports 8 findings that the base has too.
Performance
| metric | before | after | delta | harness or run link |
|---|---|---|---|---|
| per-token work in transcript rows | none added | none added | 0 | no new timers, observers or effects; same components, CSS grid only |
Risk: normal. CSS and markup for the message rows, plus one subagent row layout. The Home ledger keeps its own .lg-run-messages .cv-agentmsg__line flex override.
Changelog
Changed: transcript message, command and subagent rows share one layout; sends read "Sent to" with the recipient as a chip and status before the chevron.
#28291 closes once this lands.
Agent session: agent session
🤖 Generated with Claude Code





