Agent chat: a streamed turn never flickers Session Info or the header (guard test)

Merged
TE
3d ago
+474-0

Leo, 2026-11-03: "likewise i don't want to see flickers of the session info or anything when there's random re-renders EVER"

Closes #33201. Builds on #33203, which stopped Session Info from re-rendering on every streamed update. This PR adds the painted-frame guard the issue asked for: it covers the chat header too, runs in WebKit as well as Chromium, and drives the real pane instead of a harness.

What flickered

Nothing, at base or at the commit just before #33203 (a86fae37df0). Every Session Info box (the panel, the Environment and Context sections and their bodies) and every chat header box (the header, its status slot, its tools) kept the same element, the same box, the same opacity and visibility, and its text, on every painted frame of the stream. No animationstart, transitionstart or transitionrun fired inside either one, and no element was removed from either one. The re-renders #33203 removed never reached the screen as a visible flicker. So this PR changes no product code and lands the test as a guard.

Test

webviews/test/agent-pane-streaming-no-flicker.test.ts (browser lane, Chromium and WebKit). The test serves the pane's dev entry and connects it to a stand-in acpmux. It turns Session Info on, then streams a long turn: 12 steps, each sending reply tokens one word at a time, a tool call that starts and finishes, and a usage tick with session_changed. After every painted frame (support/paintedFrames.ts) it reads each box of Session Info and of the header. It fails on any of these:

  • a remount (a new element, or an element removed per the MutationObserver)
  • a box that moves or resizes by more than 0.5 px
  • an opacity or visibility change
  • a box that had text and paints empty
  • an animation or transition that starts

A control at the end of the test replaces a section with a copy, dims the header for one frame and starts a CSS animation on a header tool. It asserts that the sampler reports all three, so a green run means nothing flickered, not that the sampler saw nothing.

Command: cmux-ci test --setup playwright -- bash -c 'export "$(bash scripts/ci/ensure-system-chrome.sh --optional | tail -1)"; cd webviews && CMUX_BROWSER_TESTS=1 bun test test/agent-pane-streaming-no-flicker.test.ts'

runchromium frameswebkit framesremounts / moves / blinks / empties / animations
base db4c64e44fe3853110 / 0 / 0 / 0 / 0
before #33203 (a86fae37df0)3732870 / 0 / 0 / 0 / 0
head (with control)4753920 / 0 / 0 / 0 / 0; control caught 2 remounts, 2 blinks, 1 animationstart in each engine

There is no red-on-base run because no flicker reproduces; the control is what shows the test can fail.

Observed / Not run

  • Observed: the runs in the table above, on the fleet, both engines green, with the frame counts and the control's catches as listed. scripts/web-lint.sh (with CMUX_LOCAL_HEAVY_CHECKS=0) and prepush-gate.py are clean.
  • Not run: the type-aware lint and type check, which are left to CI on this host. Sections that need a daemon with a git worktree, subagents or tasks (Changes, Tasks, Agents) do not appear in the stand-in, so the test does not cover them.

Changelog

none

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

Adds a guard test that a streamed agent turn never flickers Session Info or the chat header, in Chromium and WebKit.

  • Drives the real pane's dev entry with a stand-in acpmux over a long streamed turn, sampling every painted frame for remounts, layout shifts, opacity/visibility blinks, empty text, and starting animations or transitions.
  • A control at the end confirms the sampler catches each kind of flicker, so a green run means nothing flickered.
  • No product code changes; no flicker reproduces at base, so this lands as regression protection for the issue's "no flicker ever" requirement.