VS Code Minimap: streaming placeholder looks in the gallery; paired bench arm (4/4)
Last of the VS Code Minimap stack: #25275, #25276 and #25185 have landed, and #25422 (the keyboard scrollbar) lands before this PR. It is stacked on #25422; its own diff over #25422 is +287/−19.
Leo's words (2026-10-26)
... the mini map ... just because something's streaming in, like you could just put skeletons or some other sort of placeholder ... You can even do, like, a cute shimmer effect.
What this adds
-
Experiment:
chatMinimap/placeholder.experiment.ts(chat-minimap-placeholder) offers four looks for the streaming reply's place: skeleton, shimmer (the default, what #25185 ships), dotted and ghost lines. Only the shimmer moves. Its stop condition and Reduce Motion fallback are the same as in #25185: it stops when the placeholder unmounts at the stream's end, and it's off under Reduce Motion. -
Gallery: the entry
agent-pane.chat-minimaphas two variants, "streaming" and "at-rest". Its compare view shows the four looks side by side. -
Bench:
webviews/bench/thread-minimap-frame-cost.bench.ts(landed in #25173) gains:- a
<rail>+canvasarm (the setting turned on through a dev-server-only hook indev.tsx,window.cmuxDevDisplay, since a standalone daemon has no host to send thedisplayevent); - a per-run canvas draw count;
SCENARIOS=selection;- arms interleaved in alternating order;
- paired per-round p95 deltas (median, min, max, rounds under 1 ms).
These are the numbers in #25185.
- a

The image shows skeleton, shimmer (frame held mid-sweep), dotted and ghost lines.
The 1 ms budget now fails the run (re-review P2). The default arms include the minimap's pair (off, off+canvas, then compact, full). The run exits 1 when a +canvas arm's median p95 delta over its rail is over 1 ms in scroll or stream, and prints which. It exits 2 when the budget can't be checked: no +canvas arm with its rail, scroll or stream left out, or a +canvas page that drew no minimap. It is still a bench, not wired into CI.
The gate on a dedicated 32-vCPU Linux box (decides this stack): within budget
The bench now builds its own pane from the dev entry (vite's build of vite.config.acpmux-pane.mjs) when PROD_DIR is unset. It refuses the shipped pane (build-agent-pane-web.sh's output, with pane.js at its root) with exit 2: that pane waits for the app's native bridge, never joins the bench's stand-in daemon, and so timed out on every arm on CI. If a page never shows the chat, the bench prints whether it joined the daemon and its console errors, failed requests and HTTP errors. Missing static files (the dev entry's /__dev-host/* calls) are a 404, not a thrown ENOENT.
Run 40302041033 (cmux-ci test --setup playwright, Blacksmith 32 vCPU, load ~0.5), production build, 2,000 rows, unchanged gate. Values are minimap on − off:
Default arms (off, off+canvas, compact, full), 10 rounds
| p95 delta | median | min | max | rounds under 1 ms |
|---|---|---|---|---|
| idle | +0.01 | −0.01 | +0.06 | 10/10 |
| scroll | +0.20 | −1.18 | +2.19 | 7/10 |
| stream | +0.35 | −1.63 | +3.31 | 6/10 |
The on/off pair alone, 20 rounds
| p95 delta | median | min | max | rounds under 1 ms |
|---|---|---|---|---|
| idle | +0.01 | −0.03 | +0.09 | 20/20 |
| scroll | +0.49 | −1.95 | +2.48 | 12/20 |
| stream | +0.18 | −2.06 | +2.25 | 17/20 |
Both runs printed minimap budget: within 1 ms (median p95 delta) in scroll and stream. On that run both still exited 1, from the ENOENT noise that this PR's 404 change fixes (not re-run on CI since); the median deltas are what the gate reads. Absolute busy p95 per frame, default arms: scroll 6.96 off / 7.29 on, stream 9.59 off / 10.28 on, against the compact rail's 47.09 scroll and 65.66 stream. Canvas draws per run: 0 scrolling, 4 streaming (one per reply ending). The earlier numbers in this PR came from huge-blue, a shared and loaded host (load 9–20, spreads ±15–70 ms), and are superseded by these.
Review fixes (gpt-6-astra), tested by webviews/test/chat-minimap-looks.test.ts (fails on the first commit):
- The app always shimmers.
placeholderLook()passesstored: {}, so a storedcmux.experimentsoverride never changes the look in the app. Only the gallery, which setsglobalThis.cmuxExperimentsfor its arms, shows the others. - The compare script settles on both variants. It now waits for the drawn picture, which both reach, instead of a placeholder the at-rest variant never has. In a real gallery frame all 8 cells (2 variants × 4 arms) settle, and each streaming cell shows its own look.
The gallery manifest, agent-pane entries and play-names tests pass, and chat-minimap still passes with the experiment wired in.
Risk
None at runtime beyond #25185: the default arm is the shimmer it already ships. The dev.tsx hook exists only on the dev entry with a #endpoint daemon.
Agent session: huge-blue
🤖 Generated with Claude Code