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

Merged
TE
15d ago
+578-19

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