Skip to content

cmux NEXT: a one-file Edited card expands to its diff; View changes shows new and out-of-repo files - #23161

Merged
teamleaderleo merged 8 commits into
feat-cmux-nextfrom
cmux/edit-card-expand
Oct 21, 2026
Merged

teamleaderleo merged 8 commits into
feat-cmux-nextfrom
cmux/edit-card-expand

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

A Claude Code turn that wrote one new file outside any repository (/tmp/l-setup.txt) ended with "Edited l-setup.txt +9 -0 [View changes]", and the card couldn't be expanded. Clicking the card's title or its new chevron now opens that file's diff inside the card, so a new file shows as all added lines. View changes opens a diff that includes the file.

What was wrong, and what changed:

  • No way to expand a one-file card. A one-file card had no per-file rows, and its chevron only appeared for multi-file cards in collapsed mode. Now a one-file card gets a chevron (and the title also toggles it). It opens the file's tool-call diff inline, using EditDiff, the same view the transcript uses for an edit. The open state is kept per row in the existing openStore.
  • View changes went to the chat folder's git diff beside the chat. That diff has nothing outside the repository, and a folder that isn't a repository gets the viewer's repository picker. Now View changes goes beside the chat only when the folder's git.status names a repository root and every file the turn changed is under that root. Otherwise the turn's own diff opens in place (turnChanges/viewChanges.ts, used by diffBeside). That diff is built from the tool calls.
  • A loaded turn checkpoint dropped the file. The checkpoint's repository files replaced the tool calls' files, so the outside file disappeared from the card's counts and from the in-place view. turnDisplay now keeps tool-call files at absolute paths outside the checkpoint's root, unless a checkpoint file already matches them (a /tmp vs /private/tmp alias), so no file lists twice.
  • Edit calls with no ACP diff item lost their change. When an edit call's content has no diff item, the change is now read from its latest input: Edit old_string/new_string and MultiEdit edits. A Write's input is used only when Claude Code's result says it created the file ("File created successfully at: …"). A Write over an existing file has no old text, so it still lists its path without counts. These diffs are marked fragment, so Undo never writes a file back from them, and a fragment is never marked as a new file.

The full diff viewer's internals aren't touched. This only changes the card and what the card hands to the viewer.

Changelog

  • Fixed: In cmux NEXT chats, the Edited card for a single file expands to show its diff, and View changes shows new files and files outside the chat's repository.

Tests

webviews/test/agent-pane-edited-card-expand.test.tsx (jsdom, the same style as permission-edit-diff.test.tsx) covers the three cases, each opened inline and through View changes:

  1. a new file from a Write, in two forms: the report's form (a diff with no old text) and an input-only Write whose result says it created the file. The input-only form offers no Undo.
  2. a file outside the repository, with the turn checkpoint loaded, plus a /tmp vs /private/tmp alias that lists once
  3. an edited file from an Edit with old_string/new_string, and a MultiEdit whose later input replaces its first one

It also covers a Write over an existing file (path only, no counts, no View changes), and a chat folder that isn't a repository (in place, even for a file inside it).

Command, from webviews/: bun test test/agent-pane-edited-card-expand.test.tsx

  • Base a3e14d3a9e0 source with the first version of the test: 0 pass, 7 fail. The failures read "Edited 1 file" / "Edited 0 files" instead of the file name, and there is no chevron.
  • Review round, with the new tests on the previous head's source (7a497fe8f99): 6 of 11 fail. These are the overwrite, alias, non-repo and View-changes cases. The MultiEdit latest-input case fails on 8885e264503 too ("+1-1" instead of "+3-2").
  • Head 51fb59b9e71: 11 pass, 0 fail, exit 0.

Observed / Not run

  • Observed: the red and green runs above, on cmux16, because local test runs are blocked on cosmic-gray. Also on cmux16 at 51fb59b9e71, 17 neighbouring jsdom tests that import the changed modules all pass, including permission-edit-diff, transcript-steer-continuous, agent-pane-turn-tokens and agent-pane-merge-restore. changes-file-review.test.tsx times out the same way at base on that loaded host. scripts/web-lint.sh reports 0 errors; its 2 warnings are in untouched files. check-layers, check-text-focus-rings and check-system-blue pass.
  • Observed in PR CI at 51fb59b9e71: agent-pane-edited-card-expand, permission-edit-diff and the browser-lane agent-pane-edited-side, agent-pane-edit-awaiting-permission, agent-pane-edited-calm, agent-pane-diff-find and agent-pane-edited-copy-overlap pass. The red webviews files there are composer and peer-chat tests (composer-mention, composer-history, composer-location-strip, composer-suggested-prompt, composer-claude-split, quiet-access-chip, agent-pane-peer-chat, agent-pane-working-counts), which this PR doesn't touch. The red cmux-next check is "Script tests (pin-cmux-tui, embed-cef, ensure-cef store)", including FIRST-TURN-COST for Chief, also untouched here.
  • Not run: gallery captures and the app build. I haven't checked the inline diff's look in the real app.

Agent session: cosmic-gray
🤖 Generated with Claude Code

teamleaderleo and others added 4 commits October 21, 2026 00:17
… View changes

A one-file edited-files card ("Edited l-setup.txt +9 -0") has no chevron
and nothing to click, View changes goes to the chat folder's git diff
(which holds no /tmp file), a loaded checkpoint drops files outside its
repository, and an edit call whose content has no diff item loses its
change. Covers a new file (Write), a file outside the repository and an
Edit with old and new strings, inline and through View changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d24-cf0a-7373-a03a-75491e4d724a&host=cosmic-gray
…shows files outside the repo

"Edited l-setup.txt +9 -0" could not be expanded: a one-file card drew no
rows and no chevron. Its title and a new chevron now open the file's diff
in the card (EditDiff, the transcript's edit view), built from the tool
calls, so a new file shows as all added lines.

View changes went to the chat folder's git diff beside the chat, which
holds nothing outside the folder (a new /tmp file). A turn that wrote
outside the folder now opens its own diff in place. A loaded turn
checkpoint replaced the tool calls' files with its repository's, which
dropped such a file from the card's counts and the view; it now keeps
tool-call files at absolute paths outside the checkpoint's root.

An edit call whose content carries no diff item (Claude Code's Write,
Edit, MultiEdit) now takes its change from its input, marked fragment so
Undo never writes a file back from it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d24-cf0a-7373-a03a-75491e4d724a&host=cosmic-gray
… diff

The reported card ("Edited l-setup.txt +9 -0") came from a Write whose
ACP content carried a diff with no old text; the test now runs that shape
and the input-only shape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d24-cf0a-7373-a03a-75491e4d724a&host=cosmic-gray
… first import

The inline diff's Pierre lines watch their size, which jsdom cannot, and
the first card's import of the pane and Pierre's chunk took over five
seconds on a loaded host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d24-cf0a-7373-a03a-75491e4d724a&host=cosmic-gray
@teamleaderleo teamleaderleo added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 21, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by projects-ba on cosmic-gray · session

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by projects-ba on cosmic-gray · session

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

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

Review b2f2417: 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=pr23161 -f ref=cmux/edit-card-expand -f platform=macos -f backend_mode=local

Unclear: web / react-apps-check failed: no known signature; failed step: Check webview test shards.

CI failed on b2f24178bb (run 39590918970 attempt 1): 3 code, 1 unknown.

Job Verdict Why
web / react-apps-check (2) code a web test failed
web / react-apps-check (3) code a web test failed
web / react-apps-check (1) code a web test failed
web / react-apps-check unknown no known signature; failed step: Check webview test shards

Failures:

  • seen on other PRs chiefsCard.test.tsx Chiefs lists every Chief: picture, name, role, backend and lock: failed (job)
  • seen on other PRs chiefsCard.test.tsx a row names the backend the way Home and the Chief editor do, never by its raw id: failed (job)
  • seen on other PRs chiefsCard.test.tsx a row shows a chosen model even when no harness is named: failed (job)
  • seen on other PRs chiefsCard.test.tsx a row opens the same editor as Home, and Save goes through the host's relay: failed (job)
  • seen on other PRs chiefsCard.test.tsx New Chief opens the editor empty; Back returns to the list: failed (job)
  • seen on other PRs categories.test.ts the categories are the approved ones, in order: failed (job)
  • seen on other PRs agent-pane-scrollbar-full-height.test.ts a composer that grows and shrinks leaves the rows a reader reads where they were on every frame: failed (job)
  • seen on other PRs chiefPetCard.test.tsx the page shows None and every character, None chosen while the pet is off: failed (job)
  • seen on other PRs chiefPetCard.test.tsx picking a character shows the pet with it; None hides it: failed (job)
  • seen on other PRs chiefPetCard.test.tsx Show Pet and Hide Pet turn the pet on and off with its character kept: failed (job)
  • ... 1 more in the job logs
Matched log lines
web / react-apps-check (2): (fail) Chiefs lists every Chief: picture, name, role, backend and lock [453.21ms]
web / react-apps-check (3): (fail) the categories are the approved ones, in order [0.34ms]
web / react-apps-check (1): (fail) the page shows None and every character, None chosen while the pet is off [476.64ms]

Not re-run automatically: web / react-apps-check (2), web / react-apps-check (3), web / react-apps-check (1), web / react-apps-check are not machine failures.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

red: cmux-next checks (god files, concurrency, crash safety, l10n); base red: the same failure on the base 1c367bb; does not block
red: web / Web status; NEW: green on the base 1c367bb; do not merge until green; see lane-rules
red: web / react-apps-check; no finished base run on 1c367bb to compare; do not merge until green; see lane-rules
red: web / react-apps-check (1); no finished base run on 1c367bb to compare; do not merge until green; see lane-rules
red: web / react-apps-check (2); no finished base run on 1c367bb to compare; do not merge until green; see lane-rules
red: web / react-apps-check (3); no finished base run on 1c367bb to compare; do not merge until green; see lane-rules

CI fast guards failed on b2f24178bb (https://github.com/manaflow-ai/cmux/actions/runs/39590918970). It does not block the merge; a red guard merged into main breaks it for every open PR.
The log named no failed step; see the run.

Agents: python3 scripts/ci/guard_attribution.py fix applies the mechanical fixes locally.

Tour of b2f24178bb (run): no media. The tour did not run: only webview code changed (9 path(s)), which the gallery advisory run checks in Linux Chromium on the pull request (its artifact holds any captures); add the media-tour-mac label to tour it on a Mac.

@blacksmith-sh

blacksmith-sh Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Found 14 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmp62phg6ke/summary-fail.json (live):/summary-fail.json (live): View Logs
/tmp/tmpi66fjlcb/summary-missing.json (live):/summary-missing.json (live): View Logs
convention violations found (ERROR lines above)./
convention violations found (ERROR lines above).
View Logs
src/pages/settings/categories.test.ts/categories.test View Logs
src/pages/settings/categories.test.ts/categories.test View Logs
src/pages/settings/chiefPetCard.test.tsx/chiefPetCard.test.tsx View Logs
src/pages/settings/chiefPetCard.test.tsx/chiefPetCard.test.tsx View Logs
src/pages/settings/chiefsCard.test.tsx/chiefsCard.test.tsx View Logs
src/pages/settings/chiefsCard.test.tsx/chiefsCard.test.tsx View Logs
test/agent-pane-scrollbar-full-height.test.ts/agent-pane-scrollbar-full-height.test View Logs

...and 4 more test failures. View all on Blacksmith: run 39590918970, run 39590919111

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

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-d9b0q created for this PR by the cmux coordinator.

teamleaderleo and others added 3 commits October 21, 2026 00:55
…er, MultiEdit and path aliases

Review of #23161: a Write built from its input read as a new file even
when it overwrote one; a chat folder that is not a repository still sent
View changes to the folder's diff beside the chat; a /tmp vs /private/tmp
alias listed a file twice. Also covers MultiEdit, a later input replacing
an earlier one, and Undo staying off for a Write built from its input.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d24-cf0a-7373-a03a-75491e4d724a&host=cosmic-gray
… chat only in a repository

- A Write's input becomes a diff only when Claude Code's result says it
  created the file; an overwrite lists its path without counts, as
  before. A fragment never reads as a new file (toolFiles `created`).
- A later input replaces diffs built from an earlier one; a diff item in
  the content still wins over the input.
- View changes goes beside the chat only when the folder's git.status
  names a repository root and every changed file lies under it; else the
  turn's own diff opens in place (a non-repo folder showed the viewer's
  repository picker).
- A tool file a checkpoint file already matches (a /tmp vs /private/tmp
  alias) is not added again as outside the repository.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d24-cf0a-7373-a03a-75491e4d724a&host=cosmic-gray
@cursor

cursor Bot commented Oct 21, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (independent subagent, claude-opus-5-5): SHIP at b2f2417

Re-review of 51fb59b returned SHIP; b2f2417 is that commit plus a clean merge of feat-cmux-next (the PR's own diff is identical apart from hunk offsets; base's new background line in mergeToolItem sits beside the PR's change).

  • Blocker 1 from the first review (a Write over an existing file shown as all added) is fixed: a Write's input becomes a diff only when the result says "File created successfully", and diffs built from input are fragments, so Undo is never offered from them.
  • Blocker 2 (View changes in a non-repo chat folder opened the git diff viewer and its repo picker) is fixed: repositoryRoot reads git.status once per click, and a refusal, a timeout or a reply with no root opens the turn's own diff in place.
  • No regressions found in in-repo View changes, multi-file cards or the editedFiles.show modes. A single-file card's chevron and title never call the host.

Follow-ups, not blocking:

Agent session: cosmic-gray

@teamleaderleo
teamleaderleo merged commit 0284c98 into feat-cmux-next Oct 21, 2026
@teamleaderleo
teamleaderleo deleted the cmux/edit-card-expand branch October 21, 2026 12:12
teamleaderleo added a commit that referenced this pull request Oct 21, 2026
acpmux sends a Claude Write as a fragment with no old text until its result
confirms a create or carries the old text (#23187). One that stays a fragment
(an overwrite without originalFile, an oversized one, no result yet, a cut-off
adopted Write) read as a new file: "+N -0" on the Edited card, all added lines
in its inline diff and in View changes.

model.ts `contentsUnknown` names that diff (oldText null, fragment, not read
from the input). `turnFiles` leaves it out, so nothing counts, diffs or undoes
it, and `plainEditLabels` lists its path without counts, the path #23161 gives
an overwrite built from the input. The card keeps such a path when no listed
file is it, and once a checkpoint loads keeps an absolute path none of its
files is (a /tmp file), as `outsideRepository` does for diffs. Edit and
MultiEdit fragments keep their hunks and counts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d24-cf0a-7373-a03a-75491e4d724a&host=cosmic-gray
teamleaderleo added a commit that referenced this pull request Oct 21, 2026
…the tool calls' change

With the unknown Write left out of the turn's files, a loaded checkpoint
marked the file it rewrote as changed outside the tool calls ("Includes
changes outside tool calls"). diff.ts `turnPathsOnly` names the paths the
turn's edits changed without a counted diff (an edit with no diff, as #23161
lists, and a Write whose old contents are unknown); `turnDisplay` and
`turnCounts` take them so a checkpoint file there is not `outside`. The pane
passes them for View changes, the header's Changes and the card.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d24-cf0a-7373-a03a-75491e4d724a&host=cosmic-gray
teamleaderleo added a commit that referenced this pull request Oct 21, 2026
…s, chevron or Undo (#23419)

* test: a Write whose old contents are unknown lists without counts

A translator Write that stays a fragment (oldText null, `_meta.acpmux.fragment`)
reads today as a new file, "+9 -0", with a chevron. These cases pin the card,
its inline diff, Undo and View changes for it, a fragment Edit beside it, the
checkpoint-loaded case outside the repository, and the same Write once its
result confirmed a create.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d24-cf0a-7373-a03a-75491e4d724a&host=cosmic-gray

* cmux NEXT: a Write whose old contents are unknown lists without counts

acpmux sends a Claude Write as a fragment with no old text until its result
confirms a create or carries the old text (#23187). One that stays a fragment
(an overwrite without originalFile, an oversized one, no result yet, a cut-off
adopted Write) read as a new file: "+N -0" on the Edited card, all added lines
in its inline diff and in View changes.

model.ts `contentsUnknown` names that diff (oldText null, fragment, not read
from the input). `turnFiles` leaves it out, so nothing counts, diffs or undoes
it, and `plainEditLabels` lists its path without counts, the path #23161 gives
an overwrite built from the input. The card keeps such a path when no listed
file is it, and once a checkpoint loads keeps an absolute path none of its
files is (a /tmp file), as `outsideRepository` does for diffs. Edit and
MultiEdit fragments keep their hunks and counts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d24-cf0a-7373-a03a-75491e4d724a&host=cosmic-gray

* cmux NEXT: an unknown Write makes its whole file unknown; checkpoint keeps only paths outside the repository

Review follow-ups:
- A file a Write rewrote with unknown old contents is unknown as a whole: an
  Edit to the same file no longer lends it counts.
- A pending or failed Write lists nothing.
- Once the checkpoint loads, the card keeps a path without counts only when it
  lies outside the checkpoint's repository (turnCheckpoint.ts
  `outsideRepository`, now shared, with `turnCounts` naming the root), so an
  in-repo path the checkpoint skipped does not reappear.
- The row height estimate counts a path once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d24-cf0a-7373-a03a-75491e4d724a&host=cosmic-gray

* cmux NEXT: a checkpoint file a Write rewrote without counts is still the tool calls' change

With the unknown Write left out of the turn's files, a loaded checkpoint
marked the file it rewrote as changed outside the tool calls ("Includes
changes outside tool calls"). diff.ts `turnPathsOnly` names the paths the
turn's edits changed without a counted diff (an edit with no diff, as #23161
lists, and a Write whose old contents are unknown); `turnDisplay` and
`turnCounts` take them so a checkpoint file there is not `outside`. The pane
passes them for View changes, the header's Changes and the card.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d24-cf0a-7373-a03a-75491e4d724a&host=cosmic-gray

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

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