Repository navigation
Agent chat: opening or closing Worked for slides the rows below and fades its steps in or out - #24050
Conversation
…th animations off (red) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…ades what it shows or hides Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Passes: CI passes on CI passes on Written by red: cmux-next checks (god files, concurrency, crash safety, l10n); NEW: Tour of Gallery before/after for
States
Pick other states with a |
|
Found 8 test failures on Blacksmith runners: Failures
|
…redCollapse) The header stays where it was clicked (held by the transcript, or by the hook's own scroll correction elsewhere) while its body plays the shared fold. Tool groups, tool, command and MCP rows, settled runs, background task notes and thoughts use it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
|
Bead |
…anscript fold test in Chromium Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…ithout moving the view The card's line and its Details are anchored collapses (useAnchoredCollapse, the transcript's shared hook from #24050): the line the reader clicked (chevron, plain sender name, Reply, or the cut card) stays on its pixel while the card under it changes, inside the virtualized transcript. Before, at the latest row the view followed the card's growth and the line jumped 235 px up. A cut card slides open to its whole height and back (fold.ts playResize: height over --cv-fold-duration, easing out); Details and its envelope fold in and out in height and opacity. At once under Reduce Motion; Find opening a message for its match does not animate. useAnchoredCollapse.ts, ANCHORED_COLLAPSE_EVENT and App.tsx's holdAsked listener are #24050's, byte for byte, so this rebases onto it cleanly once it lands. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16028-eee2-75a1-b075-2e4023976100&host=Air-Blue
… no blank band shows under the rows sliding up Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…fold-animation # Conflicts: # webviews/src/agent-session/acpmux/conversation/ThoughtRow.tsx # webviews/src/agent-session/acpmux/conversation/ToolGroupRow.tsx # webviews/src/agent-session/acpmux/conversation/ToolRow.tsx
… lint Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…ling mid-fold moves rows alike; Show more rides the bubble edge Codex review of b0a7e8e: - Another toggle (click or anchored-collapse event) settles the turn fold still playing first: its slides finish and its ghost copies go, so the new hold measures a line that stays put. - Leaving the fold (time up, another chat) settles it too, so no ghost outlives a session switch. - Turn fold positions are measured from the clicked line, not the viewport, so a reader who scrolls mid-fold scrolls every row alike instead of rows sliding against the scroll. - A fold's own end timer only ends that fold. - Show more keeps its resize animations, cancels them on a reversal and on unmount, and moves the button with the bubble's bottom edge instead of letting it jump to its final place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…test per collapsible kind - Show less holds the button where it was clicked and the text shrinks back above it, drawn until clipped (the strip showed the text clamp at once inside a still-tall empty bubble). - A placement pass that moves a row still sliding replaces its slide from where it is drawn, so a row runs one animation at a time (the strips counted two on subagent rows). - Browser test: a thought, a tool call, a command group and Show more each open and close with the clicked line within 1 px and at most one running animation per element. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…e anchored fold The audit strip showed it appear and vanish in one frame. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…de on as copies; no per-render id copy Codex review of 63b3623: - A click below a playing turn fold settles it, then moves the offset by however far that moved the clicked line, so the new hold keeps the line on the pixel it was clicked at. - A row below the line that mounts mid-fold slides from where it was placed at the toggle, on the fold's own clock (a negative delay), so it moves with the rows around it. - A row the open pushes past the mounted rows leaves a copy that slides on to its place instead of vanishing; a row the close hides still fades out. - The fold reads row ids on demand and finds the toggled row from its last index, instead of mapping the whole transcript on every render while it plays. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…d evicted rows keep their motion Codex review of ca258cb: - Each row below the line plays from its place at the toggle to its place now, on the fold's own clock: an element that mounts mid-fold (a scroll, a remount) joins part way instead of snapping or restarting, a revealed row's fade included. - A row element that leaves the mounted rows mid-fold, including one mounted after the toggle, leaves a copy that goes on with the same motion from the same point; the copy goes when the row is drawn again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…rows to content that draws late The PR was past the 800-line rule (1233 lines). This PR keeps the shared anchored collapse and every collapsible that goes through it. The Worked for and subagent row motion (turnFold.ts, its tests and gallery variants) moves to its own PR, on top of this one once it lands. The audit's diff strip showed a one-file card's diff open to the few pixels drawn at the click, then snap to its full height when the diff rendered. An open now follows content that draws late: each larger size takes over from the drawn height for the time left. Its observer stops when the fold ends, when another starts, or on unmount. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…he held offset in the same frame Codex review of bf316ac: Show less on a prompt several screens tall, with motion off, shrank the row under the old offset, so the virtualizer dropped it (and the hold and focus with it) before the hold put the button back. The held row now stays in the mounted ranges while the hold lasts. When the hold moves the offset, the mounted rows take it in this frame, as the composer lift does, instead of waiting for the scroll event. A browser test covers a 400-line prompt with Reduce Motion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
|
Review (codex xhigh): SHIP at a6a13b7 No blocker or major findings. The round-two fix addresses the motion-off Show less virtualization failure by retaining the anchor row and synchronizing scroll state before paint. The full diff and the surrounding code were reviewed; no tests or builds were run. The earlier rounds of this review (Codex xhigh via acpmux, on a different model from the author) found these issues, all fixed at this head or moved out of this PR with the Worked for row motion:
|
|
Orphaned: no activity for 13 h, and no lane holds a lease on it. The orphan sweep could not merge |
…mation # Conflicts: # webviews/src/agent-session/acpmux/conversation/CommandRow.tsx # webviews/src/agent-session/acpmux/conversation/ToolGroupRow.tsx
Bugbot needs on-demand usage enabledBugbot 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. |
|
|
|
|
|
|
jsdom (and any header in another document) rejects a CustomEvent made by a different window, so the fold-motion and ThoughtRow tests never opened. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…a prompt mid-transcript The harness page loads no string table, so labels render as keys and a text match finds nothing; the latest command group can start open; and the tall prompt is virtualized away until the view walks up to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…mation # Conflicts: # webviews/src/agent-session/acpmux/conversation/ToolRun.tsx
|
|
…e clicking Rows that mount on the walk up are measured and shift the button, so a single placement sometimes left it off screen and the click missed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…HTMLElement A DOM with no global HTMLElement (the working-line tests' happy-dom) threw from the no-listener path on every toggle. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…and so does unmount Two quick toggles with no transcript listening each started a frame loop that moved the scroller, so their corrections added up and overshot. Also says why a Find reveal opens without a hold. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…mation # Conflicts: # webviews/src/agent-session/acpmux/conversation/CommandRow.tsx # webviews/src/agent-session/acpmux/conversation/McpCallRows.tsx # webviews/src/agent-session/acpmux/conversation/ToolRow.tsx
|
|
|
|
Show less now animates the text back to its first lines, so the clamp is read after the bubble's animations finish, not the frame aria-expanded flips. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
|
Review (codex xhigh, correctness first): SHIP at 3a581d7
|
|
Shipped in:
|
…the rows below and fades its steps (#24514) * Agent chat: Worked for and subagent groups open and close in motion, the rows below sliding and the steps fading Leo (2026-10-21): "these all need animations for expand and collpase!" Opening Worked for inserts whole virtual rows, so the in-row fold can't size it. turnFold.ts plays it instead: - rows below the clicked line slide from where they were drawn (a FLIP on translate); - the steps it reveals fade in; - on close, inert copies of the hidden steps fade out under the rows sliding up. Every row plays on one clock, so rows that mount or unmount mid-fold keep their motion. A second toggle settles the playing fold first and keeps the clicked line on its pixel. Nothing runs with animations off or under Reduce Motion. Reviewed in three Codex xhigh rounds while it was part of #24050. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray * Turn fold: an ended fold lets go of its rows, and unmount settles a playing one When its timer ended a fold, the transcript still pointed at it, with the rows as placed at the toggle, the tracked row elements and animations, until the next render. Unmount now settles a playing fold too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray * Turn fold: a pass runs only when its rows are placed again, never per streamed token A MutationObserver started at the toggle runs the pass when the thread's row elements mount or unmount or a row's placement (style, index) changes; a token streamed into a row changes neither. It disconnects when the fold ends (its timer, the next toggle, another chat, unmount). A render only checks in O(1) whether the fold is over. The turn-fold tests move into transcript-fold-anchor.test.tsx, which has the same transcript setup, and a new one counts passes while tokens stream. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray * turnFold.ts: shorter comments Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… card #24050 landed, so App.tsx, foldAnchor.ts and useAnchoredCollapse.ts are base's. The normal-mode card now holds its line through base's collapse (toggle, cut card, Show more), resizes its text with playResize, and folds Details; Minimal Mode is unchanged. Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0
…ithout moving the view (#24085) * Agent pane: another agent's message opens below its line, animated, without moving the view The card's line and its Details are anchored collapses (useAnchoredCollapse, the transcript's shared hook from #24050): the line the reader clicked (chevron, plain sender name, Reply, or the cut card) stays on its pixel while the card under it changes, inside the virtualized transcript. Before, at the latest row the view followed the card's growth and the line jumped 235 px up. A cut card slides open to its whole height and back (fold.ts playResize: height over --cv-fold-duration, easing out); Details and its envelope fold in and out in height and opacity. At once under Reduce Motion; Find opening a message for its match does not animate. useAnchoredCollapse.ts, ANCHORED_COLLAPSE_EVENT and App.tsx's holdAsked listener are #24050's, byte for byte, so this rebases onto it cleanly once it lands. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16028-eee2-75a1-b075-2e4023976100&host=Air-Blue * Agent pane: Reply opens a message without holding its line, so the editor is in view Holding the line while Reply opened a long message left the focused editor below the view at the latest row. Reply now opens the card as before (the view follows the editor), still animated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16028-eee2-75a1-b075-2e4023976100&host=Air-Blue * Agent pane: a cut message's card never shrinks a frame as it opens Show more leaves at once while the text slides from its cut height, so the card was a button shorter for one frame; at the latest row that pulled the transcript's end, and the held line, 24 px up. The text now starts at the height that keeps the card as tall as it was drawn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0 * Agent pane: Find opening a closing message stops its slide A card sliding shut that Find opened again kept playing its resize, clipped until it ended and then snapped open. Find's open now cancels it (fold.ts cancelResize). From the review of #24085. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0 * Agent pane: Minimal Mode's Details opens and closes at once, as before The envelope's fold ran in Minimal Mode too, animating Details and leaving the envelope mounted while it closed; #25002 shows and hides it at once there. The fold now runs only out of Minimal Mode. From the review of #24085. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0 * Agent pane: rows below a message's card follow its slide before paint playResize now marks its row as folding (heightFoldInFlight), as useFold does, so the transcript places the rows under a sliding card synchronously instead of a frame late. A long message with no Details had nothing else marking it. From the review of #24085. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0 * Agent pane: Find stops a message's slide even when it is already open Find's reveal cancelled the text's resize only through the [open] effect, so a card the reader had just opened kept sliding when Find landed on it. The reveal now cancels it directly. From the review of #24085. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0 * Agent pane: a cancelled message slide lets go of its clip at once cancelResize cleared the text's overflow only from the animation's cancel event, which comes after the next paint, so Find opening a sliding card could show it clipped for a frame. It now clears it before cancelling. From the review of #24085. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0 * Agent pane: each display mode folds its own message box Minimal Mode's card and the normal card's Details row shared one collapse, so switching Minimal Mode mid-close moved its ref to a new box while the old fold played on, and the whole card showed under the preview until it ended. Each mode now has its own collapse; the one not drawn changes at once. From the review of #24085. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Leo-ask: ask-a5c1976d1c
Leo-ask: ask-d974edac49
Leo-ask: ask-c07aebfca2
Leo-ask: ask-0bfebc52fd
Leo: "and we shuold also have some animation for collapsing and expanding" (the agent chat's transcript folds), and: "these situations when collapsibles get expanded i said earlier last night lawrence was talking about how it shouldnt move your scroll or whatever just expand the area at the bottom and you're in the same place... also this current one seems to shift the expandable area away also these all need animations for expand and collpase!", and: "and thne there were a few animations that didnt quite work for collapsing and expanding wrt tool calls and stufff".
What #23093 already covers (merged 2026-10-21): tool groups ("Ran 4 commands ›"), tool, command and MCP rows, settled runs and thoughts open and close with the shared fold (
fold.ts). The body's height and opacity animate over--cv-fold-duration(the host's move token, about 180 ms; 0 under Reduce Motion or with cmux animations off), the chevron turns on the same token, and a click on abutton.is-toggleholds that line in place.Scope: motion and anchoring only. This PR doesn't decide what goes inside a "Worked for" fold. Leo's takeaway rule lives in the shared
turns.tsfunction that tp/fold-interim-messages owns (#24300). This PR doesn't touchturns.ts.Split to stay under 800 lines. This PR is the shared primitive and every in-row collapsible. The "Worked for" and subagent-group row motion (whole virtual rows sliding and fading,
turnFold.ts) follows in its own PR once this one lands.What this PR does
useAnchoredCollapse(conversation/useAnchoredCollapse.ts):useAnchoredCollapse({ defaultOpen?, open?, onOpenChange?, animates? }) -> { open, present, toggle, setOpen, headerRef, bodyProps }.cmux:anchored-collapseevent that VirtualTranscript answers with the same hold cmux NEXT: expanding a tool call or thought animates and never moves your view #23093's click path uses. Keyboard toggles, and headers that are notbutton.is-toggle, are held too.useFoldnow follows the content as it grows: each larger size takes over from the drawn height for the time left. Its ResizeObserver stops when the fold ends, when another starts, or on unmount.Works with tp/fold-no-blank-space: this PR doesn't touch
reportDrawn,placeRowsor the row ResizeObserver.Changelog
Frame strips
These are synthetic gallery fixtures, captured with headless Playwright on the fleet at 760x640 in the dark theme. Each fold's token is slowed tenfold to 1800 ms so one fold yields 8 to 12 frames. Each strip shows the open, then the close. Each frame's label gives ms since the click, the clicked header's y offset (
dy), and the number of running animations (DUPwould mark an element running two at once). Head is bf316ac; the commit after it changes only the motion-off hold.Show more's
dyis the button's, which rides the bubble's growing edge by design. The gallery's prompt sits at the transcript's end, where closing lets the browser clamp the offset (the one documented exception, #23093). The browser test below checks Show less mid-transcript.One-file diff, before (no animation; the diff appears and vanishes in one frame):



After, Chromium and WebKit:
Show more / Show less, before (no animation):



After, Chromium and WebKit:
The rest, after (Chromium; WebKit measured the same, table above):






Live side by side (tailnet): https://cmux-lawrences-mac-mini.tail137216.ts.net:18796/compare/tp-fold-animation/?entry=agent-pane.transcript
Observed / Not run
transcript-fold-anchor-browser.test.ts(Chromium) adds the following:ShowcaseMachineNameTests.swiftandChatInspector.gallery.tsx.test_cmux_next_checks_workflow.pyweb-bundles. This PR touches no workflow.Agent session: cosmic-gray
🤖 Generated with Claude Code