Agent pane: the running tray and Session Info never flicker while you scroll

TE
2d ago
+456-3

Leo, 2026-11-03: "ok yeah we NEED to have "dynamic" content such as the bottom running area + the session info thing not flicker EVER when im scrolling or whatever the f***. do what you gotta do"

Leo-ask: ask-cf247d0f94

What changed

  • Session Info's box is cut out of the transcript's clip wherever they overlap (session-info/chatCut.ts), so nothing scrolls behind its glass and its pixels hold still. The cut is measured again by a ResizeObserver and where the panel's enter slide ends.
  • A shimmer or spinner that mounts again (a row scrolled back into view) paints its first frame on the shared phase (alignLoopsIn in ui/spinnerClock.ts), so it never blinks.

Trade: where Session Info floats over the chat, its glass now frosts the still pane, not moving transcript text. The moving text under the glass was the flicker.

Observed / Not run

  • Observed: the branch merges feat-cmux-next cleanly (one import conflict in SessionInfo.tsx, both kept). An independent review passed. The tests run on CI at the head (results below).
  • Not run locally: the browser scroll test needs Chromium and WebKit, so it runs on CI.

Changelog

Fixed: the running tray above the composer and Session Info hold still while you scroll a running chat.

Agent session: agent session

🤖 Generated with Claude Code


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


Summary by cubic

Fixes flicker in the agent pane while a running chat scrolls: the running tray, Session Info, and the live line now hold still instead of repainting every frame.

  • Session Info's box is clipped out of the transcript wherever they overlap (chatCut.ts), so no rows or scrollbar move behind its glass or unfilled body. The cut re-measures where the panel's enter slide ends, because the slide moves the panel via transform, which no ResizeObserver sees.
  • A shimmer or spinner that mounts again (a row scrolled back into view) paints its first frame on the shared phase (alignLoopsIn in spinnerClock.ts), so it never blinks.

Tests
Adds regression tests that wheel-scroll a running chat through 100 frames in headless Chromium and WebKit at 1400, 1000, and 760 px widths. They assert the surfaces paint the same pixels, no node or attribute changes, and scrolled-back rows play no enter, fade, or shimmer restart, plus unit tests for the cut geometry.