Skip to content

Session Info: a streamed update paints nothing in it - #33203

Merged
teamleaderleo merged 4 commits into
feat-cmux-nextfrom
lane/si-no-flicker
Nov 3, 2026
Merged

teamleaderleo merged 4 commits into
feat-cmux-nextfrom
lane/si-no-flicker

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Leo, 2026-11-03: "im still getting these weird layout shift things when im already scrolled up due to idk tool calls shifting/messages coming in maybe that should not happen / likewise i don't want to see flickers of the session info or anything when there's random re-renders EVER"

This PR is the Session Info half: an update that changes nothing Session Info shows (a streamed token, a tool call that makes nothing, a usage tick) draws nothing in it. Keeping the transcript in place while scrolled up is another lane's work.

Root causes

  • SessionInfo.tsx SessionInfoPresence: every acpmux snapshot is made of new objects, so the lists it derives (summary, made, links, documents, agents, transcriptTasks, processes, waiting, snapshot.sessions, peerKinds, grants, the started chats and workflows) were new on every token, and the <SessionInfo> sections, which were not memoized, all rendered again on every update. They now keep their identity while they hold the same data (new session-info/sameValue.ts, useSameValue), the sections render through a memoized SessionInfoSections, and the App's callbacks go through useStableCallback.
  • The same component computed the chat column with chatColumnOf(...), which returns a new object when the display sets its own width or the page is zoomed. The placement layout effect depends on it, so on every render it rewrote the shell's --acpmux-session-info-column and --acpmux-header-room and dispatched CHAT_LAYOUT_EVENT. The column is now kept by value.
  • The rows given to the sections (for the chat's gallery) stay the same until a row is added, the gallery count changes or the panel lists another agent. The tool-call ids a remote chat's background task row looks up are read in Presence, so a call added to an existing row still shows up (this was the review's BLOCK at d922a51).

Tests

  • webviews/test/session-info-no-flicker.test.tsx (jsdom): mounts the pane with Session Info open, then applies 50 updates: a token at a time, a tool call every fifth, and a usage tick with new objects holding the same values. It asserts no DOM mutation inside the panel (MutationObserver, takeRecords included), the same section elements, an unchanged frame style, and zero renders of OutputsSection/EnvironmentSection after mount (both spies count at mount as a positive control). Red at 95aa733 (all 50 updates rendered OutputsSection), green here. A second test (a remote chat's task row gets its Show call when the call lands in the existing activity row) is red at d922a51 and green here.
  • webviews/test/session-info-no-flicker-browser.test.ts + test/browser/session-info-no-flicker.harness.tsx (Chromium): 50 updates at 1400/1000/600 px (float, push, overlay). It asserts no mutation in the panel, no layout-shift entry with a source inside it, and one bounding rect throughout.

Performance

metric before after delta harness or run link
Session Info sections rendered per streamed update (jsdom, 50 updates) 50 / 50 0 / 50 -100% test/session-info-no-flicker.test.tsx
ui.session_info.cls (open play, Chromium) 0.0000 see the follow-up comment bun bench/ui-stability.bench.ts 3 --only session_info, base run https://github.com/manaflow-ai/cmux/actions/runs/41593125846

ui.session_info.cls was already 0.0000 at this PR's base (the 0.028 reading predates it). That bench measures the open play, not streaming, so this change is not expected to move it.

No new timer, observer or animation loop.

Observed / Not run

  • Ran locally: bun test on every test/session-info*.test.tsx, background-task-arrival, native-session-info-toggle and chat-header-every-tool-acts, all green except session-info-dead-clicks ("every line of the tray…"), which fails the same way at base. scripts/web-lint.sh is clean except check:design-tokens on cloudStart.css, a base red.
  • The browser test ran on the fleet at 95aa733: green at 1400 px. At 1000/600 px it recorded one style write on the card, caused by the harness itself: its dock's live line first appeared inside the observed window. The harness now starts that line before it observes. A fleet run of the browser test and the bench at f8af7fb is in progress.
  • Native panel: unchanged. It already sends its model only when the JSON changes.

Agent session: agent session

🤖 Generated with Claude Code

…s sections draw again on every token)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-7a7568197607c3cdfb81
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review f8af7fb: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr33203 -f ref=lane/si-no-flicker -f platform=macos -f backend_mode=local

Shipped in:

@github-actions github-actions Bot added the risk:low Risk tier (docs/ci/risk-tiers.md) label Nov 3, 2026
teamleaderleo and others added 3 commits November 3, 2026 06:51
…hing in it

Every snapshot is new objects, so the lists SessionInfoPresence derives from it
(what the chat made, its links, agents, usage, sessions) were new on every token
and the sections, not memoized, all drew again. They now keep their identity
while they hold the same things (sameValue.ts) and draw through a memoized
SessionInfoSections. The chat column the placement effect depends on is kept by
value too, so a zoomed page or an own chat width no longer rewrites the shell's
column pin and dispatches a chat-layout event on every render.

bun test test/session-info-no-flicker.test.tsx: red at 95aa733 (50 of 50
updates drew OutputsSection), green here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-7a7568197607c3cdfb81
…chat's task row

Review of d922a51: the sections kept their rows until a row was added, so
the tool calls a remote chat's background task row looks up went stale when a
call landed in the turn's existing activity row. SessionInfoPresence now reads
the call ids itself (kept while the same set) and hands them to the sections;
the kept gallery rows also follow the listed agent.

bun test test/session-info-no-flicker.test.tsx: the new remote-call test is red
at d922a51 and green here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-7a7568197607c3cdfb81
@github-actions github-actions Bot added risk:normal Risk tier (docs/ci/risk-tiers.md) and removed risk:low Risk tier (docs/ci/risk-tiers.md) labels Nov 3, 2026
@blacksmith-sh

blacksmith-sh Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Found 7 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmp39hc0tdv/summary-missing.json (live):/summary-missing.json (live): View Logs
/tmp/tmpviba5geh/summary-fail.json (live):/summary-fail.json (live): View Logs
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows/
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows
View Logs
[new_workspaces] the window draws no frames/[new_workspaces] the window draws no frames View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
build_only must be a conjunctive exclusion on the helper, signing, and publication jobs
, and must not gate the unsigned app build/
build_only must be a conjunctive exclusion on the helper, signing, and publication jobs
, and must not gate the unsigned app build
View Logs

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

@teamleaderleo teamleaderleo left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review (claude-opus-5-5): SHIP at f8af7fb

Review (subagent claude-opus-5-5): SHIP at f8af7fb

Visual verdict: unchanged by this diff (no UI drawn differently; Session Info only stops redrawing for updates that change nothing it shows).

Checked the fix for the earlier BLOCK at d922a51 (a remote chat's background task row lost Show call when a call landed in the existing activity row): SessionInfoPresence now reads the call ids itself through useSameValue and hands them to the sections; the remote-call test is red at d922a51 and green here. Also checked the structural-equality helper, the memoized sections and the column kept by value. session-info-dead-clicks fails the same way on base.

Follow-ups:

  • [follow-up] read the remote tool-call ids only when a background command has a toolCallId.
  • [follow-up] refresh the kept gallery rows when an image changes in place (same row count and gallery count).
  • [follow-up] make the remaining callback props to the sections stable, or test that they are.

@teamleaderleo teamleaderleo added the leo-named-fix An obvious fix to something Leo named: lands on push, review runs in parallel label Nov 3, 2026
@teamleaderleo
teamleaderleo merged commit 89e65a9 into feat-cmux-next Nov 3, 2026
207 of 216 checks passed
@teamleaderleo
teamleaderleo deleted the lane/si-no-flicker branch November 3, 2026 07:45
teamleaderleo added a commit that referenced this pull request Nov 3, 2026
…ader (#33526)

The real pane, with Session Info open, takes a long streamed turn (reply
tokens, tool calls that start and finish, usage ticks) and reads every box of
Session Info and of the chat header on every painted frame, in Chromium and
WebKit: none is replaced, moves, changes opacity or visibility, or paints empty,
and no CSS animation or transition starts in either. A control at the end
shows the sampler catches a remount, a blink and an animation start.

No flicker reproduces at base or at the commit before #33203; the test lands as
a guard (cmux#33201). Fleet runs: green in both engines at base (385/311
frames) and at a86fae3 (373/287 frames).


Agent-Session: https://cmux.com/deeplink/agent?id=aid-81baa1463f6190d4c5dc

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

This branch was previously deployed

1 inactive deployment
ci-routing-agent — f8af7fba Deployed Nov 3, 2026 by teamleaderleo via cmux-tui tree preflight #104574
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

leo-named-fix An obvious fix to something Leo named: lands on push, review runs in parallel risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant