feat(next): Pin an artifact preview across chat switches (W2-17)

Merged
TE
4d ago
+245-19

W2-17: an explicit Pin on the existing document preview

Independently implements the smallest source-owned slice of W2-17's investigation and brief. This is an own-branch draft, isolated from Austin's custom panes #26713, Leo's inline HTML/SVG #30673, and the still-held Artifacts/renderer owners.

User journey

  1. Open an agent-produced HTML, SVG or Markdown document from the conversation into the existing side preview.
  2. Click the new Pin control (reuses the existing message pushpin drawing and existing translated strings).
  3. Switch to another chat within the same agent-pane runtime. The side preview retains the pinned document with a "Pinned · " label.
  4. Versions come only from the original chat, snapshotted at Pin; another chat's document with the same <title> can never masquerade as a revision. Returning to the original chat resumes its live revision list.
  5. Unpin from another chat closes the old preview; Unpin in its source chat resumes ordinary close-on-chat-switch behavior. Opening a different preview intentionally replaces the previous one.

Changes

  • artifactPin.ts: small pure, testable state transitions, source identity and snapshot selection.
  • App.tsx: source-session gate on version lookup; pin state and originating chat title for the current panel.
  • ArtifactPanel.tsx: explicit accessible Pin/Unpin with aria-pressed, a compact source label; reuse the current preview, code, version and Run controls.
  • conversation.css: truncate long originating-chat names and keep narrow panes compact.
  • ArtifactPanel.gallery.ts: real-page Pin interaction fixture.
  • Tests: source-session collision/revision regressions plus component control test.

Evidence and limits

  • Source model: exact artifactPin.ts Git blob SHA 89da729b69013dde8f0d713fee16c6a7a833c5d0 was independently reproduced and SHA-matched in an isolated Node/TypeScript harness; 14 assertions PASS, covering wrong-chat same-title outputs, pin/unpin, source snapshots, null sessions and partial/paged source history.
  • Validation: focused webviews run 41372526014 passed all artifact-pin and artifact-panel tests; its only failure is the existing render-fence.test.tsx cut-reply assertion, reproduced on base by run 41373367717 with the same error. Router review SHIP at this exact head; its P2 follow-up is tracked in #31620.
  • Starting base at branch creation: 265c68a569ac4af557bdd5ad2e4b26365a453503; current branch head: 6a7d2cb7bd04056548956f5650483a8e51f215c6. Base had advanced to ca44136b499d5782e4f21a9e01da37817a132285 at PR creation. Recheck/merge latest base before SHIP.
  • Scope: a retained preview during an in-page chat switch, not a durable, synced artifact or a native split/tab. It does not persist through an app restart or onto another computer; those are owned by HQ #4984, Artifacts PRs and the right-pane API. No new network access, storage ledger, renderer, daemon action, store listing or grant.
  • Risks to examine: full pane unmount or native tab replacement; narrow-width preview covering the chat; a pinned preview deliberately replaced by another Open; source chat deleted/offline; existing ranRenders behavior inherited from the renderer. Keep the parent render/consent PR reviews separate.

Reviewer acceptance

  1. Pin a completed preview in chat A, choose revision 2, switch to chat B with a different document of the same title, return to A: the pinned preview still shows revision 2 and its source label, B's document never enters the version list.
  2. Unpin in B: the preview closes. Unpin in A: stays open until chat switch. Close and Escape always work; Pin is absent in gallery/no-host surfaces.
  3. During partial reconnect/paged reload of chat A, the saved revisions remain visible until A's complete history arrives.
  4. Scripted HTML still asks Run in each appropriate owner path, and the existing sandbox/CSP/bridge policy remains untouched.

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


Summary by cubic

Adds an explicit Pin control to the artifact preview so a document stays open when you switch chats within the same agent pane.

  • Pinning snapshots the source chat's version list, so a different chat's document with the same title never appears as a revision. The snapshot is kept until every captured revision reappears, so paged or reconnecting transcripts never show stale versions as new ones.
  • The pane shows a "Pinned · " label and keeps using the pinned preview's existing controls.
  • Unpinning from another chat closes the preview; unpinning in the source chat restores close-on-switch behavior.
  • Pinning has no effect when the preview lacks an owning session, and the Pin control is absent on gallery/no-host surfaces.

Agent session: agent session