P0 agent-chat: isolate thread rail flash

Merged
TE
6d ago
+572-0

Problem

Leo (2026-10-26):

Like sometimes the thing, you know, the white highlights on the left session reel, sometimes it just, like, at the same time that the white highlights disappear, my screen flashes with the chat, the prompts or whatever, like it appears, disappears, whatever. But has that been fixed yet? Has that been investigated? Like there's some stupid thing with the redrawing and whatever. I don't know if it's, like, the agent messages coming in and the dynamic spacing and whatever, some bullshit deal with the blur.

Change

  • threadMinimap.css: .acpmux-minimap__rail gets isolation: isolate; will-change: transform, the same pair the preview card already has (#25960). The rail's lit ticks and hover spring then repaint in their own compositing surface instead of invalidating the transcript scroller under its edge mask.
  • webviews/test/thread-minimap-flash.test.ts + test/support/transcriptPixels.ts: a CDP screencast check that the transcript's painted text stays present through rail hover/leave, card open/close, a tick jump and a 12-chunk streamed reply (previous/next turn is checked for landing only), with positive controls that prove the detector catches a partial and a whole paint loss. Waits are painted-frame conditions with deadlines; no fixed sleeps.

This is not a proven fix. The hover-clear flash has never reproduced in headless Chromium, on base or head. The CSS is a low-risk compositing hint; the test is the regression net for when it does reproduce.

Risk: an extra compositor layer the size of the rail (36 x 320 CSS px here). Nothing inside the rail uses position: fixed, z-index or backdrop-filter, and the card is portaled outside it, so the new containing block / stacking context / backdrop root changes nothing it draws. The rail's [data-occluded] opacity, narrow hidden strip and hover reveal are unchanged; the full minimap suite below covers them.

Rail spec: design/session-rail.md (no rule changed; the rail's look is unchanged).

Visuals

Real harness (test/browser/thread-minimap.html, synthetic 30-turn chat) in headless Chromium at 2x on the fleet. "Before" forces isolation: auto; will-change: auto on the rail; "after" is this branch. Pixel diff before vs after: 0 changed pixels in all four states (dark rest, dark hover, light rest, light hover).

BeforeAfter
Dark, hoverdark hover beforedark hover after
Dark, restdark rest beforedark rest after
Light, hoverlight hover beforelight hover after
Light, restlight rest beforelight rest after

Viewed after image: yes (all four after stills opened by the landing lane).
Visual verdict: no visible change; the rail and its hover card look exactly as on base.

No capture: webview-only CSS with a pixel-identical result; no native UI changes.

Tests

  • react-apps-check at the previous head (7cb803a): test/thread-minimap-flash.test.ts ran (GitHub Actions, browser lane required) and passed first try in 48 s.
  • Fleet (cmux-ci, Blacksmith Linux, GITHUB_ACTIONS=true so the browser lane is required) at 5d06c98 (base merged in): run-webviews-tests.sh minimap rail-adapter: 26 files, 0 failed, 0 retried; then thread-minimap-flash.test.ts 3 more times alone with retries off: 3/3 pass.

Observed / Not run

Observed: the runs above and the pixel diffs. Not run: a native macOS recording of the flash (earlier attempts were refused by the capture privacy check; see the PR history). Whether this stops the flash Leo saw on macOS is unverified.

Changelog

none

Agent session: agent session