Skip to content

Agent chat: Worked for folds and unfolds with motion (cx-o90g7) - #20610

Closed
teamleaderleo wants to merge 16 commits into
feat-cmux-nextfrom
transcript/fold-motion
Closed

teamleaderleo wants to merge 16 commits into
feat-cmux-nextfrom
transcript/fold-motion

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

cx-o90g7. Stacked on #20582 (its commits show here until it lands). SHOW LEO: hold for Leo before merge.

What

The "Worked for" fold moves instead of jumping:

  • Turn ends (running → done): the steps fold away as the answer and the edits card settle into place. The steps fade out while the new rows fade in, so no frame goes empty.
  • Reader opens the fold: the header keeps its place. The answer slides down (--agent-motion-move, 190 ms ease-out), then the opened steps fade in under it.
  • Reader closes the fold: the steps fade out (--agent-motion-out, 80 ms) while the answer slides up into place.
  • While the turn runs: "Working for Ns" carries the existing "Thinking" sweep. It stops when the clock stops.

Rows are placed absolutely, so nothing animates a height. Each row's translate runs from where it was drawn to its new place (a FLIP, the way the New Tab list moves). The bottom-pin glide is off while this runs, so the whole pane never slides. A toggled fold keeps its header still and stops following when it opens past the end.

Reduce Motion keeps only a short fade (≤100 ms) and no movement. With animation speed off, there is no motion at all.

Variants

For comparison, #foldMotion= picks the variant:

  • slide: proposed, and the default.
  • fade: rows jump, steps fade.
  • none: no motion.

scripts/agent-pane/fold-motion-tour.mjs records all three against the mock agent.

Captures

Side by side: before (this branch's base, #20582), slide, and fade only. Real speed, then 4× slower. Recorded headless in Chromium against the mock agent on the private builder. I watched them frame by frame.

worked for motion

Full quality: worked-for-motion.mp4

worked for motion 4x slower

Full quality: worked-for-motion-4x-slower.mp4

Real app (cmux NEXT DEV)

Fleet DEV builds on a capture mini: after = this head (4152f790a721), before = its base on feat-cmux-next (2a68993bc732). The chat is the app's showcase mock agent (9 steps × 350 ms per turn), at the default animation speed (fast). Each app's agent-pane bundle was checked before shooting: foldMotion is in the head's pane.js and absent from the base's. Stills are the main window, cropped to the sidebar and chat; the mini's machine name in the composer is blanked.

Composer overlap

The end of a long chat (five turns). In the before shots the last turn's time, Copy and Fork row is clipped by the composer's top edge, the multi-line draft included; in the after shots it sits clear of the composer.

Before, light After, light Before, dark After, dark
Turn ended
After opening and closing the fold
Multi-line draft

Fold states

Before, light After, light Before, dark After, dark
Running (Working for, sweep)
Folded
Opened

A still catches the sweep at one point of its pass; in the after clips the highlight moves across "Working for" while the turn runs (the base's label stays flat gray). In the opened shots the fold runs past the end, so the view stops following and shows the jump-to-latest button.

Clips: turn ends and folds, then the fold opens and closes

The slide, fade and none clips are from a DEV build of 284dd5005850, which fixed the fade and none issues the first recording showed; the stills and the base clip are unchanged (the opened still matched on 284dd5005850). Each is 8 s: send at 0.3 s, the turn ends and folds at about 3.5 s, open at about 4.7 s, close at about 6.5 s. The mode was set through the agent pane's registry.js customization (it puts #foldMotion=<mode> on the page and reloads it); no app code changed for the captures.

Mode Clip
slide (default) mp4
fade (7d1c6d2f2fd9) mp4
none mp4
before (base) mp4

Watched frame by frame at 60 fps (284dd5005850):

  • slide: the answer slides down on open and up on close, and the steps fade in after it; no empty frame.
  • fade (re-recorded on 7d1c6d2f2fd9): no near-empty frame on open or close. Rows the fold moves fade from about 0.4 opacity and new steps from 0, settling over about 3 to 5 frames.
  • none: open and close are instant, and the "Worked for" header keeps its place in both.

Verification

  • bun run check passes on the builder.
  • Transcript tests pass: transcript-worked-fold, jump-latest, long-chat-updates. follow runs in the browser lane.
  • Seen in real cmux NEXT DEV builds of this head and its base: see Real app (cmux NEXT DEV) above.

Changelog

Changed: the agent chat's "Worked for" fold slides open and closed, and a finished turn folds its steps with a short crossfade.

🤖 Generated with Claude Code


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


Summary by cubic

The agent chat's "Worked for" fold now moves instead of jumping: finished turns fold their steps with a crossfade, and opening or closing a fold slides the rows that stay into place while the toggled header keeps its place on screen. The last turn's time, Copy and Fork rows always clear the composer, even with a long draft or while the next reply streams; slide is the default, with fade (moved rows fade from 0.4, steps from 0) and none variants selectable via #foldMotion=.

Also fixes turns that end on a tool call: the interim text now folds with the rest instead of remaining open as the answer, including when an edit runs a tool in the same step.

  • Rows sit absolutely and slide via translate (a FLIP); steps fade in or out where they are, so no height animates and no frame goes empty.
  • Reduce Motion keeps only a short fade; the transcript neither glides nor follows while a change plays.
  • The branch also carries participant avatars (SHA-256 deduplicated, read in the Channels page), agent.message.release withdrawal, the background-process registry, and daemon/Chief handoffs.

Written for commit 7d1c6d2. Summary will update on new commits.

View guided diff Turn on auto-fix

teamleaderleo and others added 6 commits October 14, 2026 04:10
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rked for

A finished turn's answer was simply its last text, so a turn that went on
to a tool after that text (or was stopped mid-tool) kept the interim text
open as if it were the answer, with the later tool rows drawn unfolded
below it, and a cancelled turn showed no fold at all. The answer is now
the last text only when no tool call follows it; otherwise the whole body
folds, as the Codex and Claude desktop apps fold it. Edits after the answer
still join the turn's card, and render cards, plans, subagent groups and
notices after it leave it open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…m text (red)

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

Calls after one text segment share an activity row, so the edit exemption
on the whole row kept the interim text as the answer whenever a step edited
and then ran something (the usual Claude Code ending). Work is now decided
per call: any call that is neither an edit nor a render call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cx-o90g7: when a turn ends and its steps fold under "Worked for", and
when the reader opens or closes the fold, the rows that stay slide from
where they were drawn (translate, --agent-motion-move), the steps that
open fade in after the rows below move out of their way, and the ones
that close fade out where they were. The header the reader toggled keeps
its place: the transcript neither glides nor follows meanwhile. Reduce
Motion keeps a short fade only; animation speed off, none. "Working for"
sweeps while its clock runs.

#foldMotion=fade|none picks the other variants for comparison captures
(scripts/agent-pane/fold-motion-tour.mjs records them).

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: 560cbf7d-61b8-4488-b555-bd39bdd83610

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.

@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 7d1c6d2f2f.

CI passes on 7d1c6d2f2f (run 38664470230 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 7d1c6d2f2f (https://github.com/manaflow-ai/cmux/actions/runs/38664470230). 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

Copy link
Copy Markdown
Contributor

cmux-next tour of c088e14b44f281a067156819bacdadd31d93031d (run)

The tour job failed before the tour ran (build or setup); the run log has the output.

The tour produced no media.

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

…pt/fold-motion

# Conflicts:
#	webviews/src/agent-session/acpmux/App.tsx
#	webviews/src/agent-session/acpmux/conversation/WorkingFor.tsx
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Gallery

Review in feed

168 states changed: agent-pane.transcript/long-code, agent-pane.transcript/fork-any-turn, agent-pane.transcript/fork-any-turn-codex, agent-pane.transcript/fork-latest-turn-only, agent-pane.transcript/long-chat, ... · 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/fork-any-turn (Apple System Colors Light, webkit)
agent-pane.transcript/fork-any-turn-codex (Apple System Colors Light, webkit)
agent-pane.transcript/fork-latest-turn-only (Apple System Colors Light, webkit)
agent-pane.transcript/fork-any-turn (Apple System Colors Light, chromium)
agent-pane.transcript/fork-any-turn-codex (Apple System Colors Light, chromium)

162 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-fold-motion/?entry=agent-pane.transcript#/agent-pane.transcript/long-code
  • agent-pane.transcript/fork-any-turn: /wt/transcript-fold-motion/?entry=agent-pane.transcript#/agent-pane.transcript/fork-any-turn
  • agent-pane.transcript/fork-any-turn-codex: /wt/transcript-fold-motion/?entry=agent-pane.transcript#/agent-pane.transcript/fork-any-turn-codex
  • agent-pane.transcript/fork-latest-turn-only: /wt/transcript-fold-motion/?entry=agent-pane.transcript#/agent-pane.transcript/fork-latest-turn-only
  • agent-pane.transcript/long-chat: /wt/transcript-fold-motion/?entry=agent-pane.transcript#/agent-pane.transcript/long-chat
  • agent-pane.transcript/web-video-loaded: /wt/transcript-fold-motion/?entry=agent-pane.transcript#/agent-pane.transcript/web-video-loaded
  • 24 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, webkit): play: waitFor did not hold within 5000 ms

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

300 unchanged · base 1cb7e58 · head 7d1c6d2

teamleaderleo and others added 3 commits October 14, 2026 16:07
…each fold motion moves its rows (red)

Leo on #20610 (2026-10-14):
- The composer covered the last message's time and Copy/Fork row. The
  guard reads, with the view where the page leaves it (or scrolled to
  its end after a fold toggle), how far the last turn's action row (or,
  while a reply streams, its last line) clears the composer: at least
  16px, after the turn ends, after the fold opens and closes, with a
  six-line draft and while the next reply streams.
- The fade option showed nothing. When the reader opens or closes a
  Worked for fold, every row that changes place must slide there
  (slide) or fade in there over 120-180 ms (fade, no slide); none
  animates nothing.

red: bun test test/agent-pane-chat-column.test.ts -t 'never under the composer|each fold motion' (builder)
     -> action row clears by 8px after the turn, -8px after the fold opens/closes;
        fade leaves assistant-5 and summary-29 jumping with no animation

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… 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>
@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
teamleaderleo temporarily deployed to cmux-tui-merge-tree October 14, 2026 23:17 — with GitHub Actions Inactive
@teamleaderleo

teamleaderleo commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator Author

Visual preview of 7d1c6d2: in the maintainers' private review feed.

teamleaderleo and others added 2 commits October 14, 2026 17:31
…led header keeps its place in every mode (red)

From the real-app captures on #20610: the fade option showed one frame
of a nearly empty transcript, and with no motion the toggled Worked for
header scrolled away. The fold-motion test now ends its chat with a
short turn followed at the end, its header in view, and clicks it as
the reader does (a DOM click, no scroll into view). It asserts that
fade animates no row the fold did not move, and that the toggled header
stays where it was in slide, fade and none. The composer guard now
reads once its measurement holds for 10 painted frames (the composer
grows with a draft and the view follows a frame or more later).

red: bun test test/agent-pane-chat-column.test.ts -t 'each fold motion' (builder)
     -> with no motion the header moves -36px on open, +36px on close

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eader holds with no motion

- fade decided what moved by screen position, so rows the scroll (or a
  first placement by estimate) moved faded too, and the transcript read
  as empty for a frame. It now compares each row's place in the
  transcript (RowFrame's translateY): rows the fold moved fade, others
  keep full ink.
- With no motion, arm() returned before recording the toggled header,
  so the transcript kept following and the header scrolled away. The
  header is now armed in every mode; with no motion the change only
  keeps it in place and ends at commit, animating nothing.

green: bun test test/agent-pane-chat-column.test.ts -t 'never under the composer|each fold motion'
       -> 15 of 15 under three parallel runs; whole file 10/10 x2; transcript-*, bottom-stack,
       follow-live, chat-find: 57 pass; bun run check clean

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo
teamleaderleo temporarily deployed to cmux-tui-merge-tree October 15, 2026 00:32 — with GitHub Actions Inactive
teamleaderleo and others added 3 commits October 14, 2026 17:54
…pt/fold-motion

# Conflicts:
#	webviews/test/agent-pane-chat-column.test.ts
The #20610 real-app clip of the fade option showed one near-empty frame
on opening a fold: the answer the fold moves faded in from nothing with
the new steps. A moved row's fade must start above zero opacity.

red: bun test test/agent-pane-chat-column.test.ts -t 'each fold motion' (builder)
     -> assistant-36 and summary-37 fade from 0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opening a fold under the fade option faded the moved answer in from
nothing with the new steps, so the view read as near empty for a frame
(#20610 real-app clip). A moved row now fades from 0.4 to full; the
steps that appear still fade in from nothing.

green: bun test test/agent-pane-chat-column.test.ts (builder) -> 10/10 in 6 of 6 runs, two in
       parallel; bun run check clean

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo added a commit that referenced this pull request Oct 15, 2026
…he same transcript height)

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

Copy link
Copy Markdown
Collaborator Author

Dead: a SHOW LEO PR from 10-14 with no follow-up, and it conflicts. #20582, which it was stacked on, merged by itself. Reopen and rebase if the Worked for fold motion is still wanted. Closing.

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