feat(agent-chat): keep an open artifact preview live through rewrites

TE
8d ago
+1905-64

Stacked dependency note: this branch includes artifact sandbox A (#25190) and complete-write detector D (9ec77bdaa97158524624f8a65ad4464453a404e6). The own B diff is git diff 9ec77bdaa97158524624f8a65ad4464453a404e6...HEAD (17 files; producer, live cursor, propagation and regression coverage). It will be retargeted over the published D branch or shrink after its prerequisites land. Do not land this combined dependency view.

An opened side preview now follows its own fence while the agent streams and finishes it, and follows later completed writes to the same canonical file. Stale source revisions and failed writes cannot roll it backward. Choosing an older version keeps it selected.

Leo: "the /side thing i heard somebody really liked in codex... and i think html/html artifacts and that kinda good viewing and good support for it would be cool" and "like the claude.ai artifacts but imagien you didnt need to only have it on claude.ai...".

Reuses cmux/nx-artifact-live-1025 (7498124ed129, 0c6229439012, 96a613ec60cb), adapted to the current renderer. Depends on the existing sandbox and complete-write detector from the artifact A/D branches; adds no project artifact storage or file actions.

The opened fence resolves its row through the producer's O(1) index. Written files use one per-open subscription to the existing OrderedRows producer: coalesced changed-tool records are delivered at publication even when React skips a snapshot. Metadata never points to prior snapshot arrays, and pending records clear after every publication. The existing tool-update index limits live work to the changed tool. Versions are capped at 64 plus the single explicitly selected historical document. Close, chat change and unmount dispose the subscription. No new timer, animation loop or polling.

Explicit Run consent follows the same opened artifact as it updates; each accepted revision replaces the inner sandbox document. Passive markup that first gains script still waits for Run. Sandbox permissions and network/file restrictions remain unchanged.

Gallery versions: agent-pane.artifact-panel/live-stream, live-finished, live-write; the existing side-panel chrome remains. Reference: Claude's browser companion panel, cmux-design-references/apps/claude/live/browser-panel-expanded.png.

Observed / Not run

  • Hosted regression: cd webviews && bun test test/artifact-panel.test.tsx test/artifact-live-writes.test.ts executes 18 tests and passes at product head 0df70dda52b25feba67f65409e09230be8761f7a in 40489475179. The pre-fix panel fails the live revision regression in 40484619014; the integrated coalesced-write regression failed before the final repair in 40488706797.
  • The full hosted webviews check/typecheck completed at that product head with only two inherited App.tsx hook warnings (unlift, follow). Scoped lint on the exact base aa82735368f69b31aafcd6666304502a7716bc62 reproduces both. Own changed-file formatting and lint pass. Subsequent commits change gallery fixtures only.
  • Final gallery capture: 40493008642, source 6fa8abebb7d7920fb77dfd30c3a948a60e40558c; head plays 6/6 pass across three variants in light/dark. Matched file-write captures show the base preview remaining on “Preparing release” while the head updates to “Release ready.” The base cannot open streaming fences (four expected wait failures); the head opens and follows them. Twelve real final screenshots were decoded and SHA-verified from the hosted run.
  • The initial Astra xhigh review blocked on reconnect producer handoff, fold-local revision resets, highlighter fallback identity and nested block identity. Red-first tests and repairs are pushed; a second self-audit repair preserves each file’s completion event across unrelated/output-only updates. A final exact-head Astra re-review is still running; no SHIP is claimed until its receipt arrives.
  • Native compilation was not run: this changes the shared web renderer and existing side-preview state, with no native implementation or API change.

Integration seam: #25208 also adds metadata to OrderedRows.sorted(). Keep its pull-request activity/command and transcript-source stamps alongside this producer's publish; neither substitutes for the others. #26082's row renderer changes must retain the optional artifact identity/revision props. The prompt index and scroll anchor are unchanged.

Final-head verification is complete at 45aa50b83c4aa2fcdae261a1bdec4891aae6f81b. Hosted run 40497592765 is terminal-success: red-first overlay a7ad906e0bc6ae3cb6f607296d66e55ef35b17ef has 22 pass/1 deliberate semantic-order failure; final head has 23 pass/0 fail. Full web validation reports only the two inherited App.tsx hook warnings (unlift, follow), each reproduced on base aa82735368f69b31aafcd6666304502a7716bc62.

Actual hosted Chromium captures from source 6fa8abebb7d7920fb77dfd30c3a948a60e40558c (the subsequent changes repair lifecycle/identity paths without changing this panel chrome):

Completed file rewriteBeforeAfter
DarkBefore: stale documentAfter: live document
LightBefore: stale documentAfter: live document

Streaming fence follows its source

The same preview stays live when the turn finishes

Agent session: agent session