Skip to content

Agent chat: the gutter beside every part of the floating stack scrolls the transcript - #23243

Merged
teamleaderleo merged 9 commits into
feat-cmux-nextfrom
cmux/dock-gutters-scroll
Oct 21, 2026
Merged

teamleaderleo merged 9 commits into
feat-cmux-nextfrom
cmux/dock-gutters-scroll

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

In the agent chat, when the bottom stack floats over the transcript, the wheel in the gutter beside the composer's card already scrolls the transcript (Leo 2026-10-20: "if it's not in the composer it should just scroll"). Beside the stack's other parts it did not. The question card, the pull request dock, error cards and the agents pill are bands as wide as the pane, with their card inset. The wheel in a band's gutters or empty room hit the band and scrolled nothing.

The fix keeps the bands catching the pointer. The transcript rows under the stack are only masked (.acpmux-scroll[data-docked]), so a band that passed the pointer through would let a hover, click or drag in its empty room reach rows no one can see: link hover cards, hidden links, tool rows, text selection. Instead, wheelPassThrough.ts forwards a wheel whose target is a band itself (a direct child of the floating .acpmux-dock, not the composer and not the dictation notice) to the transcript, the way it already forwards the wheel over Jump to latest. It does this only when the band can't scroll itself (scrollHeight <= clientHeight), so a pull request dock or question card that overflows in a short pane keeps its own wheel, and a wheel there never scrolls both. Because the bands take the pointer, those two parts' scrollbars can be dragged again. The composer is unchanged: it passes the pointer through around its card and queue.

Changelog

  • Fixed: In an agent chat, scrolling beside the question card, the pull request bar, an error card or the agents pill now scrolls the conversation.

Testing

CMUX_BROWSER_TESTS=1 bun test test/agent-pane-dock-gutters.test.ts (CI web / react-apps-check, Chromium and WebKit). One chat shows every part of the stack at once:

  • the question (a pending permission)
  • the pull request dock (3 PRs)
  • an error card (Edit CLAUDE.md, which the browser host refuses)
  • the agents pill (2 running subagents)
  • the queue (2 prompts) and the composer's card
  • later in the test, the dictation notice

For each part, the pointer 8 px left of the card reaches the band (for the composer's queue and card, the transcript) and the wheel there scrolls the transcript both ways. The same holds in the empty room right of a PR chip and right of the agents pill, where elementFromPoint must not be inside .acpmux-scroll. The wheel over a card moves nothing. The agents list dialog takes the pointer. In a 440 px pane, the wheel over the overflowing PR dock scrolls only the dock, and for each overflowing part the point 3 px in from the band's right edge (its scrollbar) reaches the band.

  • First approach (bands pass the pointer through), test-only head 1d4d573: red in both engines. Fixed at 3b3c868 (PASS). Review found the hidden-row problem above.
  • Test for the reviewed approach, test-only head 9895107: red in both engines:
    • The gutter beside the question card reached transcript, not band (line 250).
    • The pill's gutter with its list open reached transcript (line 309).
    • The PR dock's scrollbar reached transcript (line 342).
  • Fix 02fff40, then test-only follow-ups at 8ea0f9a (the question card asserts only that the transcript stays still) and 560891d (each wheel waits until the transcript holds still, after a WebKit run measured a glide that was still moving). On 560891d: PASS test/agent-pane-dock-gutters.test.ts (react-apps-check shard 3, both engines).

Observed / Not run

Observed: the CI logs above. On 02fff40 the two main cases passed in both engines. The short-pane case failed only on the question card's own scroll: the wheel over its rows moves neither the card nor the transcript. Wheels over a band's contents are handled the same way as on base, so this isn't caused by this PR. The test now asks only the PR dock to scroll alone, and asks the question card only that the transcript stays still and its scrollbar takes the pointer.

On 560891d, the remaining react-apps-check reds are secret-card and timeouts in composer-draft-wrap and composer-row-layout. Earlier heads also had reds in files this PR doesn't touch:

  • agent-pane-scrollbar-full-height
  • gallery-agent-pane-entries, gallery coverage
  • pane-english (run-board)
  • the + is its glyph and Add tooltip cases
  • pet picker and Chiefs list cases
  • the motion categories case
  • timeouts in composer-draft-wrap, composer-type-scale and composer-row-layout

Not run: nothing ran locally; browser tests run only on CI. The recap card (behind a Debug toggle) and the folder-choice, worktree and btw notices (shown only before a chat starts or with side sessions on) aren't in the fixture. They are bands of the same shape and get the same handling. Dragging a scrollbar is checked only through elementFromPoint, not with a real drag.

Agent session: cosmic-gray

🤖 Generated with Claude Code

…scrolls the transcript

A browser test (Chromium and WebKit) with one chat that shows every part of the bottom stack at
once: the question, the pull request dock, an error card, the agents pill, the queue and the
composer's card, then the dictation notice. Beside each part's card the pointer reaches the
transcript and the wheel scrolls it; over the card it does not. Red on this head: the question,
pull request dock, error card and agents pill bands take the pointer across the pane's width.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdc7-79b0-b869-8ac78b0edd90&host=cosmic-gray
@teamleaderleo teamleaderleo added risk:low Risk tier (docs/ci/risk-tiers.md) risk:normal Risk tier (docs/ci/risk-tiers.md) and removed risk:low Risk tier (docs/ci/risk-tiers.md) labels Oct 21, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by composer-scroll on cosmic-gray · session

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 1f6db4e: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr23243 -f ref=cmux/dock-gutters-scroll -f platform=macos -f backend_mode=local

Probably yours: streaming-text-frames.test.ts, streaming-text-frames.test.ts fails here but not on main's latest full suite.

CI failed on 1f6db4ed39 (run 39612738079 attempt 1): 1 code, 1 unknown.

Job Verdict Why
web / react-apps-check (2) code a web test failed
web / react-apps-check unknown no known signature; failed step: Check webview test shards

Failures:

  • new in this PR streaming-text-frames.test.ts chromium claude: a long reply streams within the frame budget, with no shift above its tail: failed (job)
  • new in this PR streaming-text-frames.test.ts webkit claude: a long reply streams within the frame budget, with no shift above its tail: failed (job)
Matched log lines
web / react-apps-check (2): (fail) chromium claude: a long reply streams within the frame budget, with no shift above its tail [34660.65ms]

Not re-run automatically: web / react-apps-check (2), web / react-apps-check are not machine failures.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

red: web / Web status; NEW: green on the base 95c0d1f; do not merge until green; see lane-rules
red: web / react-apps-check; no finished base run on 95c0d1f to compare; do not merge until green; see lane-rules
red: web / react-apps-check (2); no finished base run on 95c0d1f to compare; do not merge until green; see lane-rules

CI fast guards failed on 1f6db4ed39 (https://github.com/manaflow-ai/cmux/actions/runs/39612738079). It does not block the merge; a red guard merged into main breaks it for every open PR.
The log named no failed step; see the run.

Agents: python3 scripts/ci/guard_attribution.py fix applies the mechanical fixes locally.

Gallery before/after for 1f6db4e: 16 states rendered, 4 images differ, 625 more touched states not rendered. Images are in the run's artifact, not on this public PR.

gh run download 39612737705 -R manaflow-ai/cmux -n gallery-advisory-23243-1f6db4ed39754cac63ba6e0e83705afe29d7608c (then read gallery-review.json)

States
State Theme Status Diff Picked by
agent-pane.streaming-text/claude Apple System Colors changed 4.12% own bottomStack.css
agent-pane.streaming-text/claude Apple System Colors Light changed 0.0006% own bottomStack.css
agent-pane.streaming-text/codex Apple System Colors Light changed 0.0033% own bottomStack.css
agent-pane.streaming-text/codex Apple System Colors changed 0.0017% own bottomStack.css
agent-pane.chat-width/standard Apple System Colors Light unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.chat-width/standard Apple System Colors unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.chat-width/wide Apple System Colors Light unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.chat-width/wide Apple System Colors unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.chat-width/wide-blocks Apple System Colors Light unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.chat-width/wide-blocks Apple System Colors unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.composer-floats/scrolled-to-end Apple System Colors Light unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.composer-floats/scrolled-to-end Apple System Colors unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.composer-floats/composer-grown Apple System Colors Light unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.composer-floats/composer-grown Apple System Colors unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.docked-chat/new-chat Apple System Colors Light unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.docked-chat/new-chat Apple System Colors unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.docked-chat/after-turn Apple System Colors Light unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.docked-chat/after-turn Apple System Colors unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.docked-chat/working Apple System Colors Light unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.docked-chat/working Apple System Colors unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.docked-chat/typing-in-dock Apple System Colors Light unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.docked-chat/typing-in-dock Apple System Colors unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.docked-chat/long-title Apple System Colors Light unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.docked-chat/long-title Apple System Colors unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.orchestration-lab/local-queue Apple System Colors Light unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.orchestration-lab/local-queue Apple System Colors unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.orchestration-lab/huge-blue Apple System Colors Light unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.orchestration-lab/huge-blue Apple System Colors unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.orchestration-lab/cloud-fair-share Apple System Colors Light unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.orchestration-lab/cloud-fair-share Apple System Colors unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.streaming-follow-motion/stream Apple System Colors Light unchanged 0% imports wheelPassThrough.ts (1 hops)
agent-pane.streaming-follow-motion/stream Apple System Colors unchanged 0% imports wheelPassThrough.ts (1 hops)

Pick other states with a Gallery: entry.id, entry.id/variant line in the PR body.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-htb3f created for this PR by the cmux coordinator.

@blacksmith-sh

blacksmith-sh Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Found 3 test failures on Blacksmith runners:

Failures

Test View Logs
---/--- View Logs
test/streaming-text-frames.test.ts/streaming-text-frames.test View Logs
test/streaming-text-frames.test.ts/streaming-text-frames.test View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

…crolls the transcript

The floating bottom stack passed the pointer through only around the composer's card: its other
parts (the question card, the pull request dock, error cards, the agents pill) are bands the pane's
width wide with their card inset, and the band took the pointer, so the wheel in the gutter beside
them scrolled nothing. Now every part's band passes the pointer through and what it holds takes it,
the rule the composer had, so a new part gets it too. Text-only parts and notice lines keep the
whole band.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdc7-79b0-b869-8ac78b0edd90&host=cosmic-gray
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

codex-review: SHIP at 3b3c868

  • Reviewed the current diff, its focused tests, and the affected call paths; no correctness bug found.

teamleaderleo and others added 2 commits October 21, 2026 03:41
…n their empty room scrolls the transcript

Review of #23243: with the bands passing the pointer through, every empty spot in a band (right of
the agents pill, right of a pull request's chip, its padding) reached the transcript rows hidden
under the stack, so hover, click and drag acted on unseen rows. The test now asks that those spots
reach the band while the wheel there still scrolls the transcript, and that a part scrolling in a
short pane scrolls alone with its scrollbar under the pointer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdc7-79b0-b869-8ac78b0edd90&host=cosmic-gray
…l on to the transcript

Review of #23243: the transcript's rows under the floating stack are only masked, so a band that
passed the pointer through let a hover, click or drag in its empty room reach rows no one sees.
The bands take the pointer again (the composer still passes it through around its card), and
wheelPassThrough.ts forwards a wheel over a band itself to the transcript, as it does over Jump to
latest, unless the band scrolls itself; the pull request dock's and question card's scrollbars take
the pointer again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdc7-79b0-b869-8ac78b0edd90&host=cosmic-gray
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

cmux-next fast gates / fast gates is red on 12 of 18 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

teamleaderleo and others added 4 commits October 21, 2026 05:12
…croll alone; the question card only keeps the transcript still

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdc7-79b0-b869-8ac78b0edd90&host=cosmic-gray
… a timer

The fixed-waits ratchet (#23365): wheelAt counts animation frames until the transcript and the
stack's scrollers hold still for 12 frames, or 30 frames pass with nothing moved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdc7-79b0-b869-8ac78b0edd90&host=cosmic-gray
@cursor

cursor Bot commented Oct 21, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@teamleaderleo
teamleaderleo merged commit b17a1dc into feat-cmux-next Oct 21, 2026
@teamleaderleo
teamleaderleo deleted the cmux/dock-gutters-scroll branch October 21, 2026 14:39
teamleaderleo added a commit that referenced this pull request Oct 21, 2026
…ents pill (#23526)

#23104 replaced the agents pill with the tray of running work (on by default) after #23243 landed
this file, so the file's setup waited for a pill that never shows and hit the runner's 120 s
limit on every run. The file now waits for the tray, expects it in the stack's order, and checks
it as the dictation notice: the stack's gutter beside it passes through and scrolls the
transcript, the tray takes the pointer and the wheel over it scrolls nothing. The pill's own
list test goes with the pill.


Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdc7-79b0-b869-8ac78b0edd90&host=cosmic-gray

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant