Agent transcript: one-line activity rows share one pitch and columns

Merged
TE
4d ago
+393-61

Leo, 2026-11-01, on a column of transcript rows (tool rows, inbox lines, agent message lines, fold heads) whose vertical gaps differ by row type:

doesn't make sense for these to be spaced differently

Every one-line activity row in the agent transcript now draws on the tool rows' 22px line in a one-call tool run's frame (2px over, 4px under), and joins the step rows beside it, so any two consecutive one-line rows sit exactly 22px apart, top to top, whatever their kind. Their icons share one column and their words one text column.

Row (beside other one-line rows)Height beforePitch beforeHeight afterPitch after
Tool row (one-call run)2228-342222
Sent message line26342222
Received / inbox line2628-382222
Task notice line22 (drawn at the row's right end)28-342222
Report batch head2228-382222
Waiting group head26 (icon 4px right, words 5.5px right)382222

What changed:

  • model.ts: isLineRow names those rows (another agent's message, a notice, an inbox notice, a report batch, the waiting group). The estimator uses the same frame (LINE_ROW = 2 + 22 + 4) and an open group's member as its line alone.
  • App.tsx: marks them acpmux-row--line and treats them as step rows, so they join their neighbours as tool runs already do.
  • CSS: --cv-message-line is now the tool row height; received, pending and lane-batch lines drop their own vertical margins; the sent message's toggle is 22px and its hidden Copy no longer stretches the line to 24px; the waiting group's chevron and words sit on the shared icon and text columns; a task notice's tool line takes its row's width (it sat at the row's right end, since the row is a user row).
  • Merged with #29124 (status rows centred between replies): a one-line row between two replies still takes its centred room; statusDelta counts its 4px run gap as a tool run's.
  • model.ts also estimates a sent message (SendMessage, acpmux send, a sub-session's send_message) as one 22px line (review finding at 3bd8fe3).
  • A received line's buttons take the line's 22px (DisclosureRow.css gave them a 26px floor).
  • Design spec: leo-workspace design/chat-transcript.md, "One-line row pitch" (separate notes PR).

Prior art: #29754 (shared activity row grammar), #29613 (meta rows' icon and text columns) and #29124 (status rows' columns and centred gaps), all merged, are built on, not redone: this keeps their columns and adds the vertical rhythm. #29830 (flat waiting group) touches the group's contents, not its head geometry.

Changelog

Fixed: every one-line row in the agent transcript (tool rows, sent and received messages, inbox lines, background task lines, report and waiting-message fold heads) now sits on one line height and one spacing, with one icon and text column.

Test

CMUX_BROWSER_TESTS=1 bun test test/transcript-row-pitch-browser.test.ts (Chromium through cmux-ci test, real VirtualTranscript layout, light and dark): equal line height, equal top-to-top pitch, one icon x and one text x within 0.5px across 12 rows of 7 kinds.

Observed / Not run

  • Observed: the browser files above, plus at 8d0a64357139 (after the base merge) received-message-fold-browser, transcript-fold-no-blank-space-browser, other-session-message-actions-browser (all pass). Locally rowEstimates (a new case: a sent message estimates 2 + 22 + 4), agent-pane-reply-actions-frame, agent-pane-transcript-spacing, foldAnchor, footerActions pass; transcript-hover-fade fails on .cv-subagent__stop in subagents.css, a file this PR does not touch. Locally: rowEstimates, rowLayoutLinearity, continuationSpacing, lane-notice-batches, lane-notice-card, transcript-received-messages (41 pass). vp fmt / vp lint on the changed TS files, prepush-gate.py.
  • Not run: the full webview suite (CI runs it), a DEV build by hand. No screenshots.

risk:normal

Agent session: agent session

šŸ¤– Generated with Claude Code