Transcript: a reply keeps its 2026-10-30 room before the next row
Leo, on the transcript spacing (2026-11-01):
i like this spacing kinda i prefer it to what we have now tho it's just minor differences
What changed
When Leo moved to one action footer per turn on 10-31 (hasReplyActions now returns false), each reply lost the 28px action-row room it used to have under it. That room was the only real difference between the 2026-10-30 spacing and what ships now. This PR restores the room under a finished reply that has more rows after it, but no per-reply action rows come back: the space is empty padding (--cv-reply-room = meta gap + meta row + message gap = 36px). The new keepsReplyRoom(row, next) in model.ts decides it. App.tsx uses it for the row class and the height estimates, and conversation.css pads .acpmux-row--reply-room. Streaming replies, replies right before the turn footer, empty replies and short notes inside an opened "Worked for" get no room. A reply to the person inside an opened "Worked for" (settled + foldedReply, which kept its action row) keeps it, so a turn's end, which marks the earlier replies settled, moves nothing.
Spec: leo-workspace design/chat-transcript.md, "Rows between replies". That section is updated in a follow-up leo-workspace PR.
Gaps, measured ink to ink in the new agent-pane.transcript-spacing-reference gallery entry (Chromium, light and dark gave the same numbers):
| gap | 2026-10-30 | base (4b48c641) | after |
|---|---|---|---|
| reply -> status/notice row | 43.75 | 17.75 | 43.75 |
| reply paragraph -> prompt | 49.75 | 21.75 | 49.75 |
| status/notice -> prompt | 23 | 17 | 17 |
| prompt -> sent message | 53.25 | 51.75 | 51.75 |
| sent message -> paragraph | 10.5 | 9 | 9 |
| paragraph -> paragraph | 19.75 | 19.75 | 19.75 |
| prompt -> run summary | 51.75 | 51.75 | 51.75 |
| card -> prompt | 28 | 28 | 28 |
Only the two gaps under a reply move, and only those two are asserted against 2026-10-30. The three that differ from 2026-10-30 on base come from the one-line row pitch Leo settled on 11-01 (#29965), and this PR leaves them alone; the test logs them.
Leo's screenshot may be from Claude desktop and not from a cmux build, because its gaps don't match any cmux commit. We've asked which app it is. If it is Claude desktop, a follow-up makes its numbers the target and revisits grid.md's turn gap. In this PR the screenshot-shaped fixture's numbers are logged for reference only and are not asserted.
Alignment check exception: transcript-row-alignment used to require equal space above and below a status row. A status row that follows a reply now has 26px more above (the reply's kept room) than below. The check allows exactly that offset and still requires the above sizes to agree with each other and the below sizes to agree with each other. Every left-edge, icon and text-x assertion from #29124 is unchanged.
Not touched: the newest message -> composer gap, steer visibility, the interim-prose gap between tool calls (#30400), #29124's left alignment, colours, type and glass.
Testing
- Red/green:
cmux-ci test --setup playwright -- env CMUX_BROWSER_TESTS=1 bun test test/transcript-spacing-reference.test.tsfails on base (4b48c641, this PR's source reverted) in light and dark (reply -> notice 17.75, paragraph -> prompt 21.75) and passes at this head. - 13 related transcript suites pass on the fleet at this head: 146 pass, 0 fail. They cover spacing reference, row alignment, row pitch, transcript spacing, turn footer, composer rest gap, continuation spacing, stream jitter, gap select, incoming disclosure, suggested tasks, row estimates and model.
agent-pane-stream-jittercaught the reply above a tool call dropping 26px at the turn's end (the reply turnedsettledand lost the room). Fixed by keeping the room for settled replies to the person;rowEstimates.test.tspins the predicate.transcript-gap-select-browser.test.tsset a 64px gap on a reply row with a selector the reply room now outranks, so its injected selector is made more specific. The test is unchanged otherwise.rowEstimates.test.ts: a status row between two replies is now estimated under the reply's kept room.
Observed / Not run
- Observed: gallery measurements on fleet Linux Chromium, light and dark.
- Not run: a DEV app build by hand.
- The design-tokens check fails on base too ("baseline can shrink" in
agent-session/acpmux/styles.css, a file this PR doesn't touch).
Changelog
- Replies in the agent transcript get their 2026-10-30 breathing room back before the next status row or prompt.
🤖 Generated with Claude Code
Agent session: agent session