Agent transcript: closing a line at the very bottom keeps the bottom pinned (no empty space)
Leo (2026-11-03): "the "tool call expanding at the bottom of the scrollable area in a chat expanding "up" aka shifting the elements above instead of simply creating empty space" doesn't seem like it's in yet... / it's weird to collapse and get all that empty space at the bottom"
What changed
With the agent transcript at its very bottom (the existing 4px follow deadband), every disclosure now keeps the bottom edge pinned, closing as well as opening. What opens pushes the text above up (#32644, unchanged); what closes pulls the text above down. No blank room is left under the rows, so there is also no jump on a later scroll. Away from the bottom nothing changes: the clicked line stays put.
Why #32644 missed it
#32644 changed only the opening branch (opensBody). Closing at the bottom still took #29703's path: a closing .cv-tool.is-toggle called keepBottomFoldRoom, which held the clicked line on its pixel and kept the expanded scroll extent as sticky blank room under the rows (until the rows grew back into it). Any other close at the bottom (Show less, Wrap lines) took the line-hold + keepFoldRoom path, which also leaves room. That room is the gap in Leo's second screenshot. #29703 implemented Leo's 2026-10-31 ask ("WHEN I COLLAPSE IT LEAVES THE SPACE / WHEN I SCROLL UP THAT SPACE IS REMOVED? WTH? JUST LEAVE THE SPACE"); today's ask replaces it: no space at all.
How
App.tsxbeginBottomStackFold: at the bottom, any disclosure (open or close) starts the existing bottom stack fold: the body lays out at once,settleFollowBottompins the end, and the thread plays one compositor translate from where it was. Any room an older close kept is dropped first. The sticky-room machinery (stickyFoldRoom,keepBottomFoldRoom) is removed.holdUnderStack: the rows under the clicked line are found by|moved| < |from|/2, so a close (negativefrom) holds them on their pixels as an open does.- No new observer or timer. The stack fold's existing stops apply: its animation's
onfinish/oncancel, itscleanupTimer(fold ms + 150ms, min 400ms), reader wheel/touch/key, session switch, send, Jump to latest and unmount (stopBottomStackFold). No per-row or per-token work.
Gallery and tests
agent-pane.expand-at-bottom gets four variants whose plays check where the bottom and the clicked line land (each throws when off): expand-at-bottom, collapse-at-bottom (a command's Shell card at the bottom, opened then closed, as in Leo's screenshots), collapse-tall-group (a group with a 40-line log closed), expand-away (an earlier "Worked for" line away from the bottom stays put). transcript-expand-at-bottom.test.ts runs the four plays in Chromium. The two #29703 assertions in transcript-fold-anchor-browser.test.ts that required the kept room now assert Leo's new rule.
Fleet runs (cmux-ci test, Chromium): results are posted below as a comment once the red (base App.tsx) and green runs finish.
Design references: no Claude or ChatGPT capture of a bottom collapse in cmux-design-references; Leo's own 2026-11-03 screenshots (private) are the reference. Spec: leo-workspace design/chat-transcript.md, "Tool expansion at the bottom" (updated in a notes PR).
Risk: scroll anchoring for closes at the very bottom only. Away from the bottom and while streaming nothing changes.
Changelog
- Fixed: Closing a tool call or other line in an agent chat scrolled to the very bottom pulls the text above down instead of leaving empty space at the bottom.
Agent session: agent session
🤖 Generated with Claude Code
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Closing a disclosure at the very bottom of the agent transcript now keeps the bottom edge pinned, so no blank room is left under the rows.
Previously, closing at the bottom (a tool call, Show less, Wrap lines) kept the expanded scroll extent as sticky empty space until the rows grew back into it. Now any disclosure at the bottom pins the bottom edge the same way opening does: what opens pushes the text above up, what closes pulls it down. The sticky-room machinery is removed, and the clicked line's anchor logic now holds the rows above it for both opens and closes. Away from the bottom, behavior is unchanged: the clicked line stays put.
- Adds four gallery plays and Chromium tests covering expand, collapse, tall-group collapse, and the away-from-bottom case.
- Updates two existing assertions that previously required the kept room.
- No new observers or timers; the existing bottom-stack-fold stops (wheel, keyboard, send, Jump to latest, unmount) still apply.