cmux NEXT Inspector: it shows only over the chat, where its toggle is, never over a diff in place
Leo's words (ask-9700045156). His screenshot shows the Inspector lying over a turn's diff ("Last turn +30 -0") and covering its code lines, with no close control in reach:
why's the diff viewer not opening up in the right split tab? what about the existing diff viewer elsewhere that was previously made? also wtf this sidebar like ik we're fixing it not being a whole fucking sidebar and shit but why does it FLICKER AND WHY DOES IT STAY ON IN THESE RANDOM SITUATIONS WITHOUT BEING CLOSABLE!?
This PR covers "STAYS ON IN THESE RANDOM SITUATIONS WITHOUT BEING CLOSABLE" for the agent chat's Inspector (webviews/src/agent-session/acpmux/inspector/). The diff-viewer part belongs to the toolbar-diffviewer lane. The flicker was fixed by #24275, merged.
What was wrong
The Inspector's open state belongs to the viewer and holds in every chat tab (localStorage). The panel is drawn as a child of the pane's shell, so it showed over whatever the pane showed:
- A turn's diff in place (
DiffPanel, full-pane below 1160px): the diff hides the chat header, and the Inspector's toggle with it. The panel floated over the diff's code lines (Leo's screenshot). Opening the diff from the Inspector closed it. A diff opened any other way left it on: a turn's changes chip, the summary, the palette, or an Inspector left open in another tab. - The event Inspector (the debug log view,
Inspector.tsx) also replaces the transcript and hides the header. - A handoff review: its form (760px) is wider than the transcript column that the float check measures, so a floating panel covered part of the editable form.
- A document in the side panel (
ArtifactPanel): the floating panel measured the whole pane, so it floated at the pane's right edge, over the document. Below 720px the side panel covers the whole pane, header included, and the Inspector stayed on under it.
The fix
- It shows only over the chat, where its toggle is.
useChatInspectortakescovered. App.tsx sets it for a diff in place, the event Inspector, or a side panel covering a narrow pane (useArtifactCoversPane). While covered, the panel steps aside. Its open state is kept and it comes back when that view closes.inspectorShown()holds the rule. - Opening it brings the chat back. The toggle closes the covering view first (
onUncover), then opens the panel over the chat. The toggle is reachable over the side-by-side diff at 1160px and wider. The palette's "Inspector" and a running line's count do the same. - It never covers content. Over a handoff review (
wide), it pushes the form aside instead of floating. The toggle stays in reach there, so suppressing the panel would turn the toggle into a dead click. It measures the chat's room without the side panel (paneRoom). The existing ResizeObserver does the measuring and now also observes the side panel. Floating, it ends at the side panel's edge (--acpmux-inspector-side). With too little room, it pushes, as before. - When it shows, it can be closed with its own x (#24126) or Esc. This PR leaves Esc alone. #24242 (open, same owner) narrows Esc to focus inside the panel, so it never takes stop-turn's Esc.
Unchanged: colours, glass, the diff viewer and the header toolbar layout. No new timers. The only new subscription is the narrow-pane matchMedia listener, removed by useSyncExternalStore's unsubscribe. The existing pane ResizeObserver now also watches the side panel; its cleanup is the existing disconnect().
Tests
webviews/test/chat-inspector-surfaces.test.tsx(new, 13 tests). They cover:- the visibility rule;
- left open, it steps aside under a diff and comes back still open;
- the toggle, the palette and a reveal over a covered chat close the view and open the panel;
- its x and Esc close it;
- the chat's room leaves out the side panel, and the floating card's right edge is the chat's;
- the narrow-pane query matches conversation.css and follows the pane's width;
- in a 1600px pane it floats beside the transcript, and over a handoff review it pushes.
- On huge-blue at f724ef3a: the new file passes 13/13, every
chat-inspector*andinspector-*test passes, andtsc --noEmit -p webviewspasses. The only reds, twogallery-coveragetests, fail the same way on base. - CI reds at cbfa0e4a are also red on base: gallery health (
agent-pane.composer#steer-read-hover) and cmux-next checks (the workflow-guard Python tests).
Gallery (Linux, before/after)
New entry agent-pane.chat-inspector-surfaces, wired as App.tsx wires the real useChatInspector. Its states:
transcriptdiff-in-place: the diff, with the Inspector left opendiff-closed: going back to the chat brings it backdocument-beside
Commit 6d7b19ae (the entry alone, on base behaviour) is the "before"; the head is the "after".
Gallery: agent-pane.chat-inspector-surfaces
Leo-ask: ask-9700045156
Agent session: cosmic-gray