Skip to content

docs(openspec): propose undo grouping by browser task - #201

Open
ilyamore88 wants to merge 3 commits into
mainfrom
claude/undo-grouping-proposal
Open

ilyamore88 wants to merge 3 commits into
mainfrom
claude/undo-grouping-proposal

Conversation

@ilyamore88

@ilyamore88 ilyamore88 commented Oct 10, 2026 •

Copy link
Copy Markdown
Member

What

Planning only. This PR adds the undo-group-by-task OpenSpec change. It contains no code changes. It is the bottom of a stack: this ← #203 (implementation) ← #191 (clipboard paste proposal).

It changes only UndoRedoManager in core. Local model events are buffered for the current browser task (the end of the task is detected with setTimeout(0)):

  • One event in the task (a keystroke): batched exactly as today, so typing behaviour is unchanged.
  • Several events in the task (Enter split, paste, conversion): the open step is closed, and the task's events start a new step together.
  • undo() and redo() record any events still buffered before acting. destroy() also clears the task timer.
  • Fix: undo/redo of block insertions and removals currently throws, because block events carry one block while the model expects a list. The undo manager wraps the block in a one-item list (design.md, D5).

There is no public API, no event-payload change and no change in the model.

Why

Core undo currently merges only consecutive text inserts or removals in one input. Any action with several model changes becomes several undo steps. Pressing Enter mid-paragraph is two steps today: splitBlock emits TextRemoved and then BlockAdded. The upcoming paste would be three or more. All of these actions run synchronously in one browser task, so grouping by task fixes them in one place, without plugins or tools having to mark their changes.

Notes for reviewers

  • Explicit api.document.group(fn) was the first draft. It was rejected for now: it needs public API, a groupId on model events and about 24 model changes, and it doesn't fix Enter. It stays available if async actions (for example file upload) ever need to be one step (design.md, Alternatives).
  • Typing over a selection. A multi-change step can still be continued by typing under the existing text rule, so "replace selection and keep typing" undoes as one step. Earlier typing never merges into it (D2).
  • Existing quirk the design relies on. The DataNodeAddedEvents that BlockNode dispatches in a microtask during construction have no userId, so undo never records them. That is what keeps redo from throwing AlreadyExistingKeyError. A test pins this (R2).
  • Collaboration. collaboration-manager's undo/redo is unchanged, so multi-change actions still undo in several steps when collaboration is enabled. This is listed as follow-up.
  • The change is not archived. The implementation is in feat(core): group undo steps by browser task #203.

Add the undo-grouping OpenSpec change: api.document.group(fn) and group
ids on model events so a multi-operation action (e.g. paste) is a single
undo step. Prerequisite for clipboard paste (#137).
@ilyamore88
ilyamore88 added this pull request to stack #202 October 10, 2026 11:49
@ilyamore88 ilyamore88 changed the title claude/undo grouping proposal docs(openspec): propose undo grouping Oct 10, 2026
Replace the explicit api.document.group(fn) + groupId design with implicit
grouping in core's UndoRedoManager: local events of one browser task are
buffered and become one undo step when the task made several changes.
No public API, no model or event-payload changes. Rename the change to
undo-group-by-task.
@ilyamore88 ilyamore88 changed the title docs(openspec): propose undo grouping docs(openspec): propose undo grouping by browser task Oct 10, 2026
@ilyamore88
ilyamore88 marked this pull request as ready for review October 10, 2026 12:06
Block events carry a single serialized block while the model's
insertData/removeData expect a list, so undoing any block add/remove throws.
Add the fix (wrap in a one-item list in UndoRedoManager) to the proposal,
design, core spec and tasks.
@ilyamore88
ilyamore88 removed this pull request from stack #202 October 10, 2026 12:25
@ilyamore88
ilyamore88 added this pull request to stack #204 October 10, 2026 12:26
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