Skip to content

Transcript: a followed reply moves only by what is drawn - #20697

Merged
teamleaderleo merged 14 commits into
feat-cmux-nextfrom
transcript/glide-retarget
Oct 14, 2026
Merged

teamleaderleo merged 14 commits into
feat-cmux-nextfrom
transcript/glide-retarget

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes the base flake in webviews/test/agent-pane-chat-column.test.ts: "scrolls smoothly: its last line holds still" (24 > 23) and "a streaming reply keeps the view at its end, through a growing command and a queue". Both failed under CI load (seen on #20644 and #20633) and passed locally.

The load exposed two real scroll jitters:

  • A streaming reply scrolled ahead and back on every chunk. A reply's text draws one frame after the version that holds it. The row was first placed by an estimate of the new version, a line or more ahead of the text, then by its drawn height. Now a row keeps its last drawn height until its new version is drawn, so the view grows only by what has been drawn (App.tsx, heightAt).
  • The queue let the followed reply slip back a row. Superseded: base Agent chat: one bottom stack, so the queue never covers the PR dock #20521 (one bottom stack) removed --acpmux-queue-space, so that part of the fix was dropped in the base merge.

The test now loads the page itself with Emulation.setCPUThrottlingRate at 6×, so a local run reproduces what CI sees. The smoothness test no longer counts pixels per painted frame. That bound depends on frame timing: one loaded frame can hold two lines of growth. Instead it checks, for each frame, that the followed row moved exactly as far as the glides the thread started since the frame before. A step drawn at once fails at any frame rate. With glide() disabled, the test fails on that check. It still checks that the text never moves down or back.

The live-resize test (#20467) flaked too, but in the test, not the app. The watcher samples each frame in a task after its animation frame. On a loaded page a viewport resize could land between that frame and the sample. The sample's forced layout then read the new width (the reply rewrapped 341 px taller, the spacer and offset still placed for the old width), which the page never painted; the next frame was settled. A frame paints at the viewport its animation-frame callback saw, so a sample whose viewport changed since is skipped. The assertions are unchanged.

Testing

All runs were on the Linux builder, with the throttled page.

Command Result
Red (test commit) bun test test/agent-pane-chat-column.test.ts "keeps the view at its end" fails in 2 of 2 runs
Green (fix commit) same command 7 pass, 0 fail, in 3 of 3 runs
Green after merging base and adding the glide check same command 8 pass, 0 fail, in 3 of 3 runs
Red (resize test, loaded at 6×) bun test test/agent-pane-chat-column.test.ts -t 'pane resized' 16 of 16 fail
Green (painted-frame sampling) same command 0 of 16 fail; whole file 8/8 at 6×

Also run on the fix commit:

  • the related transcript, queue, step-row and steer browser tests: 31 of 31 pass;
  • bun run check: clean.

Changelog

  • Fixed: a streaming reply no longer slides ahead and back as it grows, and editing the queue no longer nudges the view.

🤖 Generated with Claude Code

teamleaderleo and others added 2 commits October 14, 2026 10:15
Base flake on loaded CI runners (#20644, #20633): "keeps the view at
its end" saw the text sink a few pixels, and "scrolls smoothly" saw a
24px step. The streaming tests now run with Chromium's CPU throttled
4x, the load the runners had, so every run reproduces the first. A
smoothness step is measured over the time its frame took, so a loaded
page that paints fewer frames is not read as a jump.

red: bun test test/agent-pane-chat-column.test.ts (browser lane, builder)
     -> 'keeps the view at its end' fails 2/2 at movedDown

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two causes of the chat-column flake on loaded runners:

- A streaming reply's text draws after the version that holds it, so
  the row was placed by an estimate of the new version (a line or more
  ahead of the text), then by its drawn height a frame later: the view
  scrolled ahead and back at every chunk. A row now keeps its last
  drawn height until its new version is drawn; growth comes from what
  is drawn.
- The queue cleared --acpmux-queue-space at every change before setting
  it again; the transcript's layout pass could run between the two,
  read the taller view and scroll the followed reply back by a row. The
  space now stays while the list redraws and goes with the list.

red:   bun test test/agent-pane-chat-column.test.ts (loaded, builder) -> 'keeps the view at its end' fails 2/2
green: same command -> 7 pass, 0 fail, 3/3 runs; related transcript and queue browser tests 31/31

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: aa995418-adf5-461f-8fb8-dcf5d4525135

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

teamleaderleo and others added 2 commits October 14, 2026 10:26
…pt/glide-retarget

# Conflicts:
#	webviews/test/agent-pane-chat-column.test.ts
…y frame rate

From the #20697 review: dividing a step by its frame's time let a snap
through on a slow frame, and a fixed px-per-painted-frame bound depends
on frame timing (a loaded frame holds two lines of growth). The check
now reads, per frame, how far the followed row moved under the thread's
glide and the glides the thread started since the frame before: a move
the glides do not account for is a step drawn at once.

Checked: with glide() disabled the test fails at snapped(); with it,
the file passes 8/8 three times on a 4x-throttled page (builder).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 14, 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.

…n is drawn

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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

@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

all web/size checks green

@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Passes: CI passes on 50edd2f848.

CI passes on 50edd2f848 (run 38648302122 attempt 1).

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.

@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

CI fast guards passes on 50edd2f848 (https://github.com/manaflow-ai/cmux/actions/runs/38648302122). This covers only the fast guards, not CI: CI's result is the ci-status check, and the CI failure attribution comment names any failing test.

@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Gallery

Review in feed

25 states changed: agent-pane.transcript/long-code, agent-pane.transcript/shell-grouped-commands, agent-pane.transcript/copy-last-code-block, agent-pane.transcript/archive-chat-key, agent-pane.transcript/mark-unread-menu, ... · 1 play check failed

Diff page and renders (the run's gallery-pr artifact)

State Before · after
agent-pane.transcript/long-code (Apple System Colors, chromium)
agent-pane.transcript/long-code (Apple System Colors, webkit)
agent-pane.transcript/shell-grouped-commands (Apple System Colors, webkit)
agent-pane.transcript/copy-last-code-block (Apple System Colors Light, webkit)
agent-pane.transcript/shell-grouped-commands (Apple System Colors Light, chromium)
agent-pane.transcript/archive-chat-key (Apple System Colors, webkit)

19 more on the diff page.

Live preview (follows this branch; start it with scripts/gallery-live.sh up <branch> from an hq checkout):

  • agent-pane.transcript/long-code: /wt/transcript-glide-retarget/?entry=agent-pane.transcript#/agent-pane.transcript/long-code
  • agent-pane.transcript/shell-grouped-commands: /wt/transcript-glide-retarget/?entry=agent-pane.transcript#/agent-pane.transcript/shell-grouped-commands
  • agent-pane.transcript/copy-last-code-block: /wt/transcript-glide-retarget/?entry=agent-pane.transcript#/agent-pane.transcript/copy-last-code-block
  • agent-pane.transcript/archive-chat-key: /wt/transcript-glide-retarget/?entry=agent-pane.transcript#/agent-pane.transcript/archive-chat-key
  • agent-pane.transcript/mark-unread-menu: /wt/transcript-glide-retarget/?entry=agent-pane.transcript#/agent-pane.transcript/mark-unread-menu
  • agent-pane.transcript/web-video-loaded: /wt/transcript-glide-retarget/?entry=agent-pane.transcript#/agent-pane.transcript/web-video-loaded
  • 9 more on the diff page

Play checks failed (0 px anchor movement, 0 layout shift, no frame over 33 ms unless the entry gives a reason):

  • agent-pane.thread-minimap/long-chat (Apple System Colors, webkit): play: waitFor did not hold within 5000 ms
  • agent-pane.thread-minimap/long-chat (Apple System Colors Light, webkit): play: waitFor did not hold within 5000 ms
  • agent-pane.thread-minimap/long-chat (Apple System Colors Light, webkit): play: waitFor did not hold within 5000 ms
  • agent-pane.thread-minimap/long-chat (Apple System Colors, webkit): play: waitFor did not hold within 5000 ms

77 nondeterministic states differed from a second render of the same head (a clock or fixture leak) and are not counted as changes.

410 unchanged · base a5341bc · head 50edd2f

@blacksmith-sh

This comment has been minimized.

@blacksmith-sh

This comment has been minimized.

…red)

The #20467 test 'a pane resized at every frame keeps its last line at
the bottom' failed on a loaded CI runner (#20697 react-apps-check,
https://github.com/manaflow-ai/cmux/actions/runs/38614942014/job/116065309559:
one frame with the last line 341px off). The chat-column tests now all
run at 6x CPU throttle.

red: bun test test/agent-pane-chat-column.test.ts -t 'pane resized' (builder) -> 16 of 16 fail

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo and others added 3 commits October 14, 2026 13:41
… before its paint

The chat-column watcher samples each frame in a task after its animation
frame. On a loaded page a viewport resize can land between that frame
and the sample: the read forces a layout at the new width (the reply
rewrapped 341px taller, the spacer and offset still placed for the old
width) that the page never painted, and the next frame shows it settled.
The rendering steps apply a resize before animation-frame callbacks and
no task runs between them and the paint, so a frame paints at the
viewport its callback saw; a sample whose viewport changed since is not
a frame and is skipped. The assertions are unchanged.

red:   bun test test/agent-pane-chat-column.test.ts -t 'pane resized' (6x, builder) -> 16 of 16 fail
green: same -> 0 of 16 fail; whole file 8/8 at 6x (5 runs); bun run check clean

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- vp fmt webviews/src/pages/home-channels/HomeChannelsPage.tsx

Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38637927193
@cursor

cursor Bot commented Oct 14, 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.

@cursor

cursor Bot commented Oct 14, 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 added a commit that referenced this pull request Oct 14, 2026
… option fades

Leo on #20610 (2026-10-14):
- The transcript's rows are placed under the thread's 16px top padding,
  but its height (the spacer, and the end the view follows to) left the
  padding out: the last row ended 16px under the view, and with its own
  8px padding the action row's time, Copy and Fork sat 8px under the
  composer. The height now counts the padding and 12px of room, so the
  action row clears the composer by 20px.
- The fade option only faded the step rows that appeared; the rows the
  fold moved jumped, and the steps that left faded out under them, so
  nothing visibly moved. Every row that changes place now fades in at
  its new place over 120-180 ms (Reduce Motion keeps its 100 ms cap),
  and the leaving copies are dropped in that mode.
- With the true end, a streaming reply's estimate overshoot (fixed the
  same way in #20697) moved the followed text back each chunk; a row
  keeps its last drawn height until its new version is drawn.

green: bun test test/agent-pane-chat-column.test.ts -t 'never under the composer|each fold motion' -> 2 pass
       agent-pane-*, transcript-*, chat-find*, queue-* browser tests: 127 pass; the 3 locale
       first-paint fails need a built Resources/agent-pane bundle (absent on the builder)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo
teamleaderleo merged commit 18260a5 into feat-cmux-next Oct 14, 2026
109 checks passed
@teamleaderleo
teamleaderleo deleted the transcript/glide-retarget branch October 14, 2026 23:24
github-actions Bot added a commit that referenced this pull request Oct 14, 2026
github-actions Bot added a commit that referenced this pull request Oct 14, 2026
github-actions Bot added a commit that referenced this pull request Oct 14, 2026
github-actions Bot added a commit that referenced this pull request Oct 14, 2026
github-actions Bot added a commit that referenced this pull request Oct 14, 2026
github-actions Bot added a commit that referenced this pull request Oct 14, 2026
github-actions Bot added a commit that referenced this pull request Oct 14, 2026
github-actions Bot added a commit that referenced this pull request Oct 14, 2026
github-actions Bot added a commit that referenced this pull request Oct 14, 2026
github-actions Bot added a commit that referenced this pull request Oct 14, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
github-actions Bot added a commit that referenced this pull request Oct 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

cmux-next tour of 50edd2f848ebd7c00ec079464584d6cee1c5a72b (run)

Path-selected interactions

Interaction Changed paths
agent-pane webviews/src/agent\-session/acpmux/App.tsx
webviews/test/agent\-pane\-chat\-column.test.ts
core webviews/src/pages/home\-channels/cloudHome.ts

Agent pane (before): 3 ok

tour

Video (mp4)

# Step Result Command
1 Launch ok
2 Open agent chat ok cmux agent new-chat
3 Queue a second chat ok cmux agent new-chat
Screenshots (3)

1. Launch
Launch

2. Open agent chat
Open agent chat

3. Queue a second chat
Queue a second chat

### Agent pane \(after\): 3 ok

tour

Video (mp4)

# Step Result Command
1 Launch ok
2 Open agent chat ok cmux agent new-chat
3 Queue a second chat ok cmux agent new-chat
Screenshots (3)

1. Launch
Launch

2. Open agent chat
Open agent chat

3. Queue a second chat
Queue a second chat

### Core UI \(before\): 12 ok

tour

Video (mp4)

# Step Result Command
1 Launch ok
2 New workspace ok cmux workspace new --name Tour
3 Type in the terminal ok cmux workspace name:Tour screen current pane current tab current terminal current write --text "echo hello from the cmux-next tour\r"
4 Split right ok cmux action run splitRight
5 Split down ok cmux action run splitDown
6 New terminal tab ok cmux action run newSurface
7 Browser tab ok cmux tab new-browser --url https://example.com
8 Hide the sidebar ok cmux action run toggleSidebar
9 Show the sidebar ok cmux action run toggleSidebar
10 Notification ok cmux notify --title Tour --body "Hello from CI"
11 Notifications panel ok cmux action run showNotifications
12 Agent chat ok cmux agent new-chat
Screenshots (11)

1. Launch
Launch

2. New workspace
New workspace

3. Type in the terminal
Type in the terminal

4. Split right
Split right

5. Split down
Split down

6. New terminal tab
New terminal tab

7. Browser tab
Browser tab

8. Hide the sidebar
Hide the sidebar

10. Notification
Notification

11. Notifications panel
Notifications panel

12. Agent chat
Agent chat

### Core UI \(after\): 12 ok

tour

Video (mp4)

# Step Result Command
1 Launch ok
2 New workspace ok cmux workspace new --name Tour
3 Type in the terminal ok cmux workspace name:Tour screen current pane current tab current terminal current write --text "echo hello from the cmux-next tour\r"
4 Split right ok cmux action run splitRight
5 Split down ok cmux action run splitDown
6 New terminal tab ok cmux action run newSurface
7 Browser tab ok cmux tab new-browser --url https://example.com
8 Hide the sidebar ok cmux action run toggleSidebar
9 Show the sidebar ok cmux action run toggleSidebar
10 Notification ok cmux notify --title Tour --body "Hello from CI"
11 Notifications panel ok cmux action run showNotifications
12 Agent chat ok cmux agent new-chat
Screenshots (11)

1. Launch
Launch

2. New workspace
New workspace

3. Type in the terminal
Type in the terminal

4. Split right
Split right

5. Split down
Split down

6. New terminal tab
New terminal tab

7. Browser tab
Browser tab

8. Hide the sidebar
Hide the sidebar

10. Notification
Notification

11. Notifications panel
Notifications panel

12. Agent chat
Agent chat

Tours are data in scripts/cmux-next/media/tours: add a step or a tour file to show your feature.

github-actions Bot added a commit that referenced this pull request Oct 15, 2026
teamleaderleo added a commit that referenced this pull request Oct 15, 2026
…6fbz) (#20733)

* test: a webviews test file can declare a longer limit (cx-v6fbz)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: editor-page declares a 240 s limit; the runner honors per-file limits (cx-v6fbz)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: browser tests warm their Vite server before the first page load (cx-v6fbz)

Vite prints its port before it has transformed a module, so a test's first
goto paid for the whole module graph inside its 30 s navigation timeout. On a
busy CI runner that failed chat-find and text-field-focus (#20697), and the
gallery-frame and agent-pane browser warm-ups hit the same wait (#20681).
warmDevServer requests the page and every module it imports first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: diff-virtualization clicks a tree row only while it is still under the pointer (cx-v6fbz)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci: react-apps-check job cap 30 -> 40 min (cx-v6fbz)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: the composer browser tests new on base warm their Vite server too (cx-v6fbz)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* check: a test that starts a Vite dev server must warm it (cx-v6fbz)

The browser-lane check now fails a test file that starts a dev server
(vite.listen() or a vp dev spawn) without warmViteServer/warmDevServer.
On base it flags 80 of 240 test files; on this head none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: a declared webviews file limit never shortens the default (cx-v6fbz)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: the longer of a declared and the default webviews file limit wins (cx-v6fbz)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: review follow-ups: settings-scroll warms after its readiness poll; the diff row check climbs out of shadow roots (cx-v6fbz)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: agent-pane-bottom-stack (new on base) warms its Vite server (cx-v6fbz)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: text-field-focus declares a 240 s limit; its gallery warm-up and 22 loads took about 115 s (cx-v6fbz)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci: move the react-apps-check cap raise to its own PR

The ci-web.yml edit widens this PR's web scope to the web/ unit shards,
which are red on base. The cap raise lands separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: give dev-server files 240 s and settle abandoned warm-up visits

Review follow-up: the spawned-server files and menu-focus warm the whole
gallery graph before their browser warm-up, which can pass the default
120 s file limit on a loaded runner. A failed warm-up visit no longer
leaves the other in-flight visits as unhandled rejections.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant