Skip to content

feat(agent-chat): detect complete HTML writes from every harness (carry #26219) - #28732

Merged
teamleaderleo merged 5 commits into
feat-cmux-nextfrom
lane/carry-26219
Oct 31, 2026
Merged

teamleaderleo merged 5 commits into
feat-cmux-nextfrom
lane/carry-26219

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

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, plus test/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.

  • Legacy unmarked Edit/MultiEdit/replace/replace_in_file/edit_file snippets are not documents. Base's detector treated any unmarked diff as a whole file, so an Edit hunk on page.html showed an Open button for the fragment.
  • Codex adoption labels a multi-file change "Edit N files". An added HTML file in such a change opens only when the recorded input proves a whole add for that path or its canonical path (type: "add", integer additions, 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.
  • A whole Write input is used next to other recorded diffs and deduplicated by file identity. Before, it was used only when the call had no diff at all.
  • Kept from base: OpenCode's filePath and the absolute_path Write 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.ts is left out: base's ArtifactPanel.gallery.ts already covers the preview surface, and this PR changes only which completed records produce an Open button.

Observed

  • Red, with base's detector in place of artifactWrites.ts: bun test test/artifact-writes.test.ts gives 16 pass, 12 fail. The failures are the legacy Edit/MultiEdit/replace snippets, the writefile:/create_file: titles, input next to other diffs, the Codex multi-file add, the untrusted add provenance, and the empty/shell cases.
  • Green at head: bun test test/artifact-writes.test.ts test/artifact-html.test.tsx test/artifact-panel.test.tsx test/artifact-panel-sandbox.test.tsx gives 51 pass, 0 fail. vp fmt --check and vp lint are 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.ts covers 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

…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
@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review ef74516: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr28732 -f ref=lane/carry-26219 -f platform=macos -f backend_mode=local

Gallery before/after for b8d8be0: 16 states rendered, 25 images differ, 928 more touched states not rendered. Images are in the run's artifact, not on this public PR; the independent review of this head reads them on its own, so the PR needs no hand-made screenshots of these states.

gh run download 41192652536 -R manaflow-ai/cmux -n gallery-advisory-28732-b8d8be067ce83e1eb6e546770517172b2b3efc45 (then read gallery-review.json)

States
State Theme Status Diff Picked by
agent-pane.artifact-panel/edit-complete Apple System Colors Light new 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/edit-complete Apple System Colors new 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/replace-complete Apple System Colors Light new 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/replace-complete Apple System Colors new 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/edit-complete-open Apple System Colors Light new 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/edit-complete-open Apple System Colors new 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/edit-snippet Apple System Colors Light new 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/edit-snippet Apple System Colors new 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/claude-write Apple System Colors Light changed 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/claude-write Apple System Colors unchanged 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/codex-write Apple System Colors Light changed 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/codex-write Apple System Colors changed 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/pi-write Apple System Colors Light changed 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/pi-write Apple System Colors changed 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/gemini-write Apple System Colors Light changed 0% own ArtifactPanel.gallery.ts
agent-pane.artifact-panel/gemini-write Apple System Colors changed 0% own ArtifactPanel.gallery.ts
agent-pane.chat-inspector/full Apple System Colors Light unchanged 0% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/full Apple System Colors unchanged 0% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/workflow-running Apple System Colors Light changed 0.004% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/workflow-running Apple System Colors changed 0.004% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/workflow-finished Apple System Colors Light unchanged 0% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/workflow-finished Apple System Colors unchanged 0% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/workflow-agent-row-compact Apple System Colors Light changed 0.0047% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/workflow-agent-row-compact Apple System Colors changed 0.0042% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/workflow-agent-row-detail Apple System Colors Light changed 0.0046% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/workflow-agent-row-detail Apple System Colors changed 0.004% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/workflow-agent-row-grid Apple System Colors Light changed 0.0057% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/workflow-agent-row-grid Apple System Colors changed 0.0045% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/workflow-agent-row-narrow Apple System Colors Light changed 0.0047% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/workflow-agent-row-narrow Apple System Colors changed 0.0041% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/layout-glance Apple System Colors Light unchanged 0% imports writtenArtifacts.tsx (1 hops)
agent-pane.chat-inspector/layout-glance Apple System Colors unchanged 0% imports writtenArtifacts.tsx (1 hops)

Pick other states with a Gallery: entry.id, entry.id/variant line in the PR body.

web and size checks: green

Shipped in:

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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.

  1. [P1] [blocking] webviews/src/agent-session/acpmux/conversation/artifactWrites.ts:105 — The title guard also rejects complete ACP documents. A completed edit or replace carrying full old/new HTML contents loses its existing preview, because only add provenance bypasses partialEdit. Reproduced: base returns one artifact; head returns none. Restrict the guard to replacement snippets while preserving confirmed whole-file diffs.

  2. [P1] [blocking] webviews/src/agent-session/acpmux/conversation/artifactWrites.ts:112 — The changed detector adds/removes visible Open buttons, but no after screenshot was supplied. Existing button styling does not make this behavior invisible. Provide after captures demonstrating the changed cases and record in the PR body that the landing lane viewed them.

Validation: Nine isolated detector assertions passed using Babel and Node. The full Bun suite could not run because Bun and dependencies are absent.

@teamleaderleo teamleaderleo removed the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
… 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
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · took over from an earlier session · session

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, next-review): SHIP at ef74516

No blocking findings.

  • Non-blocking: webviews/src/agent-session/acpmux/conversation/ArtifactPanel.gallery.ts:122–123 — The “edit-snippet” fixture actually produces an Open button: its new_string differs from diff.newText, so the detector accepts it. Make the replacement match the diff to demonstrate the intended rejection.

@teamleaderleo teamleaderleo removed the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
cmux-bot[bot]
cmux-bot Bot previously approved these changes Oct 31, 2026

@cmux-bot cmux-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmux-bot approves ef74516: an independent review passed this exact head (next-review receipt by teamleaderleo). A push needs a new review; a later BLOCK at this head dismisses this approval.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6.1-sol high fast, router-review): SHIP at 26d3474

Follow-ups:

  1. P2, defer: webviews/src/agent-session/acpmux/conversation/artifactWrites.ts:134: completeEditDiff bypasses the Codex add-provenance guard; for an Edit N files record, an unmarked diff starting with <!doctype html> opens even when changes lacks the required counters or names a different path. Scope the whole-document fallback to ordinary edit calls so multi-file adds need valid provenance, and add a negative test with a full-document diff.

@blacksmith-sh

blacksmith-sh Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Found 3 test failures on Blacksmith runners:

Failures

Test View Logs
test_a_picked_signing_label_has_a_rerun_alternative (main.RunsOnFallbackTests.test_
a_picked_signing_label_has_a_rerun_alternative)/
test_a_picked_signing_label_has_a_rerun_alternative (main.RunsOnFallbackTests.test_
a_picked_signing_label_has_a_rerun_alternative)
View Logs
test_every_listed_hook_is_one_glaeda_released_with_the_check (main.SigningHooksInSt
epWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check)/
test_every_listed_hook_is_one_glaeda_released_with_the_check (main.SigningHooksInSt
epWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check)
View Logs
test_no_runs_on_chain_ends_on_the_reserved_side_label (main.RunsOnFallbackTests.tes
t_no_runs_on_chain_ends_on_the_reserved_side_label)/
test_no_runs_on_chain_ends_on_the_reserved_side_label (main.RunsOnFallbackTests.tes
t_no_runs_on_chain_ends_on_the_reserved_side_label)
View Logs

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

@cmux-bot
cmux-bot Bot temporarily deployed to ci-routing-agent October 31, 2026 08:56 Inactive
@cmux-bot
cmux-bot Bot temporarily deployed to ci-routing-agent October 31, 2026 09:02 Inactive
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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:

  1. [P1] artifactWrites.ts:131 completeEditDiff applies to Codex's Edit N files, so an unmarked full-HTML update can bypass completeAddedDiff: already Codex multi-file add can open via the whole-HTML-document fallback without provenance #29105.
  2. [P1] artifactWrites.ts:59 addedProvenance ignores object-map input.changes: artifactWrites: addedProvenance ignores object-map input.changes #29287.
  3. [P1] artifactWrites.ts:109 a whole-file ACP diff is rejected when newText equals the input replacement: artifactWrites: whole-file ACP diff rejected when newText equals the input replacement #29288.
  4. [P2] artifactWrites.ts:13 wholeDocument() accepts a doctype without a closing html: artifactWrites: wholeDocument() accepts a doctype without a closing html #29289.

@teamleaderleo
teamleaderleo merged commit 50e69a6 into feat-cmux-next Oct 31, 2026
168 of 169 checks passed
@teamleaderleo
teamleaderleo deleted the lane/carry-26219 branch October 31, 2026 11:22

This branch was previously deployed

1 inactive deployment
ci-routing-agent — b8d8be06 Deployed Oct 31, 2026 by teamleaderleo via wait for same-key tree publisher #89197
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant