Skip to content

app: fizzy.undo and fizzy.redo take a path and the step expected - #487

Merged
foxnne merged 1 commit into
mainfrom
app/undo-path-expect
Oct 17, 2026
Merged

foxnne merged 1 commit into
mainfrom
app/undo-path-expect

Conversation

@foxnne

@foxnne foxnne commented Oct 17, 2026

Copy link
Copy Markdown
Collaborator

Part of fizzyedit/plans#14 — plans/SHARED_HISTORY_PLAN.md step 5a, as amended for plans/CONTROL_SERVER_PLAN.md (fizzyedit/plans#24).

What changes

fizzy.undo and fizzy.redo take two optional arguments:

  • path: the open document to undo, which need not be the active one. It goes through the owner's historyLine and historyGoTo (text and pixi both have them), so nothing is focused and the document in front is untouched. An owner with no line undoes only the active document, as before.
  • expect: the step id the caller means, the last change for undo or the next one for redo. When another step is there instead, the call refuses and names it: "step 41 is not the one to undo: that is step 43, Draw, by the person. The document changed since; fix it forward." So a caller never takes back a step made since it looked.

Its answer is .{ .step, .title, .by }, where by is whose the step was: "the person", or an author's label (Host.stepAuthor, #474).

Keys, menus and the palette run Undo exactly as before (run, with its transport and key repeat). Only a call with arguments takes the new path.

This is the refusal the shared-history plan wanted from the agent plugin (fizzyedit/agent#21's undoesAnother). As a command, it holds for any caller, and over the control server it becomes a 409 from POST /commands/fizzy.undo with no agent code.

One trade-off. fizzy.undo/redo are now enabled while any document is open, as text's by-path commands are, because a call may name a document other than the active one. The command palette therefore shows Undo enabled when the active document has nothing to undo; running it then does nothing. The menus still grey it by the active document (menu_model.canUndo). An enabled check that sees the call's target is the control plan's open question ("Commands that take a document"), so it isn't decided here.

SDK impact

  • None. A doc comment on Plugin.historyGoTo notes that fizzy.undo reaches it; the fingerprint does not move (test-sdk-version passes).

Verified

  • Integration (headless: the whole editor comes up…), on the open text documents: an author acting as "Claude" writes into notes.txt by path while main.zig is in front.
    • A stale expect is refused, naming Claude, and changes nothing.
    • The right expect undoes it, answering .by = "Claude", and main.zig stays in front, untouched.
    • Redo and undo again by the same id work.
  • Gates on macOS: check-fmt, zig build test (573/574, 1 skipped), zig build test-integration (53/53 steps), check-web, test-sdk-version.

🤖 Generated with Claude Code

`fizzy.undo .{ .path, .expect }` undoes one step of any open document, not
only the active one, over its owner's `historyLine` and `historyGoTo`. With
`expect`, it takes only that step, and refuses (naming the step on top and
whose it is) when another has been made since, so a caller never takes back
someone else's change. It answers the step, its title and whose it was.
Keys, menus and the palette run Undo as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@foxnne
foxnne merged commit 3f7b2ff into main Oct 17, 2026
11 checks passed
@foxnne
foxnne deleted the app/undo-path-expect branch October 17, 2026 18:11
foxnne added a commit that referenced this pull request Oct 18, 2026
…do (#495)

Part of fizzyedit/plans#14 — `plans/SHARED_HISTORY_PLAN.md` step 5b
(after 5a, #487).

## What changes

Cmd-Z stays linear: it takes the last change, whoever made it. It now
says whose that is.

- **The Edit menu names it.** When the step Undo would take was made by
someone else, the row reads **"Undo Claude's Draw"**, and Redo likewise.
The person's own steps read "Undo", so working alone looks as it always
has. The title is dynamic, read when the menu opens; it reads the
owner's `historyLine` only once someone besides the person has acted on
the document (`Host.step_authors`).
- **The bubble after it has a Redo.** Pressing Undo (key or menu) on
someone else's step shows **"Undid Claude's Edit"** on the document's
pane, in place of the plain "Undo" its run would show, with a **Redo**
that puts the step back. Redo acts only while that step is still next to
redo.
- **`ActivityFeed.pushAction`.** A feed item may carry a button. It
alone takes clicks, on a small layer of its own, so the rest of the feed
still never covers the work. An item with a button stays 6 s instead of
2.4 s. `draw` returns the tag of the button pressed.
- **`Editor.stepToTake`** finds the step an undo or redo would take,
where it leaves the line, and its author. It is shared by the menu
title, the bubble and `fizzy.undo`'s `expect` (which #487 had inline).

Muting the run's own "Undo" reuses `Host.activity_muted` (the demo-seek
flag) for the duration of that one command. It is put back before the
feed draws, and the code says so.

## SDK impact

- [x] None (the fingerprint does not move; `test-sdk-version` passes).

## Verified

- **Integration** (`headless: the whole editor comes up…`): an author
labelled "Claude" writes into the document in front.
  - `stepToTake` names Claude.
- `editor.undo()` (Cmd-Z's path) restores the text, and the pane's last
feed item reads "Undid Claude's …" with a Redo tagged with that step.
  - Pressing it brings the text back.
- **Seen on macOS** in a sandbox fizzy built from this branch: an MCP
client named `claude-code` wrote into an open `note.txt`, then Cmd-Z was
pressed through the input tape.
- The pane showed **"Undid Claude's Edit · Redo"** above the history
transport.
- Clicking Redo at its spot brought Claude's line back (`text.read`: 3
lines again).
- The Edit menu's title was not looked at on screen; it is the same
lookup the test checks.
- Gates on macOS: `check-fmt`, `zig build test` (574/575, 1 skipped),
`zig build test-integration` (53/53 steps), `check-web`,
`test-sdk-version`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant