Repository navigation
feat(agent-chat): detect complete HTML writes from every harness (carry #26219) - #28732
Conversation
…6219) Carries the part of #26219 that is not on base (#26216 landed the rest): artifactWrites.ts with the partial-hunk guard and the multi-file add provenance, plus test/artifact-writes.test.ts. writtenArtifacts.tsx now re-exports toolArtifacts from it. From #26219: 392a6af, 4ed83ed, 446f9c7, f9ce1d9, bdf7318, ad5452b. Kept base's OpenCode filePath/absolute_path write fields, with test cases for them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Gallery before/after for
States
Pick other states with a web and size checks: green Shipped in:
|
|
Review (gpt-6-astra, router-review, independent): BLOCK at 6ae2bf5 Visual verdict: Missing required after screenshots. Button visibility changes, so the “No capture” exception does not apply.
Validation: Nine isolated detector assertions passed using Babel and Node. The full Bun suite could not run because Bun and dependencies are absent. |
… Open The edit-name guard from #26219 dropped every diff of an Edit/replace call unless Codex add provenance proved it, so OpenCode's edit and Gemini's replace, which record the whole old and new file, lost their preview and Open. An edit-named call's unmarked diff now opens when it is shown to be the file: it is not one of the replacement strings its input records (Claude Code's Edit and MultiEdit diffs are exactly those) and the input records some, or with no input its new text is a whole HTML document. Marked fragments and legacy snippets stay closed. Tests: a complete create, edit (Claude-shaped and OpenCode-shaped) and replace open; Edit/MultiEdit replacement snippets, a no-input legacy snippet and a marked fragment stay closed. Gallery: edit-complete, replace-complete, edit-complete-open and edit-snippet artifact-panel states. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-f71664ebfb6cf5206479
|
Owned by an agent session · took over from an earlier session · session |
|
Review (codex gpt-6-astra high, next-review): SHIP at ef74516 No blocking findings.
|
|
Review (codex gpt-6.1-sol high fast, router-review): SHIP at 26d3474 Follow-ups:
|
A newer verdict blocks 26d3474 (no independent SHIP at the head).
|
Found 3 test failures on Blacksmith runners: Failures
|
|
Review (codex gpt-6.1-sol high fast, router-review): SHIP at b8d8be0 The head is a lander base merge (update-branch) of 28bc5a9; the PR's own diff was reviewed. No blocking finding. Follow-ups:
|
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Carries #26219, keeping its commits' authorship (Leo Li). Most of #26219 already landed on base through #26216 (the artifact panel, sandbox and Open buttons). This PR carries only what is still missing:
artifactWrites.ts, the shared detector with the partial-hunk guard and the multi-file add provenance, plustest/artifact-writes.test.ts.Leo asked: "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...".
What changes
Completed HTML writes from every harness open the existing artifact preview. A full recorded ACP diff or a whole-file Write input opens the document. A replacement-only edit snippet no longer passes for a whole HTML file.
Edit/MultiEdit/replace/replace_in_file/edit_filesnippets are not documents. Base's detector treated any unmarked diff as a whole file, so an Edit hunk onpage.htmlshowed an Open button for the fragment.type: "add", integeradditions,deletions: 0, no old text, not a fragment). Updates, deletes, mismatched paths and fragments never open. Indexing is bounded: one pass over diffs, locations and changes, with no per-change rescans.filePathand theabsolute_pathWrite field (toolPaths.ts), now with test cases. The weak per-tool cache stays.It never reads a file, runs a tool or rebuilds a patch. It adds no timer, observer, storage or per-token transcript walk: each completed immutable tool record is parsed once, through the weak cache.
Not carried
The rest of #26219 (the gallery frames, the runtime plugin, the sandbox, the Swift scheme handler) is either on base through #26216 or was replaced there.
artifactWrites.gallery.tsis left out: base'sArtifactPanel.gallery.tsalready covers the preview surface, and this PR changes only which completed records produce an Open button.Observed
bun test test/artifact-writes.test.tsgives 16 pass, 12 fail. The failures are the legacy Edit/MultiEdit/replace snippets, thewritefile:/create_file:titles, input next to other diffs, the Codex multi-file add, the untrusted add provenance, and the empty/shell cases.bun test test/artifact-writes.test.ts test/artifact-html.test.tsx test/artifact-panel.test.tsx test/artifact-panel-sandbox.test.tsxgives 51 pass, 0 fail.vp fmt --checkandvp lintare clean on the changed files.Evidence
No capture: this is detection logic only. The Open button and the preview it opens are base's, and they don't change. What changes is which recorded tool calls produce the button, and
test/artifact-writes.test.tscovers that across the Claude, Codex, pi, Gemini, OpenCode and legacy Edit shapes.#26219 closes once this lands.
Agent session: agent session
🤖 Generated with Claude Code