Context
There is currently no undo/redo system. Sim implements undo/redo as a thin wrapper over the socket system — undo is just another edit that generates an inverse operation and sends it through the normal operation queue.
What to build
Per-user undo/redo stacks
- Each user maintains a local undo stack and redo stack
- Every operation records its inverse:
- Add node → inverse: Remove node (snapshot full node state)
- Remove node → inverse: Add node (restore from snapshot)
- Move node → inverse: Move node (original position)
- Update text → inverse: Update text (previous value)
- Add edge → inverse: Remove edge
- Remove edge → inverse: Add edge (snapshot edge)
Undo execution
Cmd+Z / Ctrl+Z: Pop from undo stack → push to redo stack → execute inverse op through the operation queue
Cmd+Shift+Z / Ctrl+Y: Pop from redo stack → push to undo stack → execute forward op through the operation queue
- Inverse operations flow through the normal WebSocket system — other users see the change in real-time
Coalescing consecutive ops
- Consecutive same-type operations should coalesce in the stack
- e.g., dragging a node through 50 positions → single undo entry (start position → end position)
- Typing in a text field → coalesce by time window or word boundary
Multiplayer-safe stack pruning
- When a remote user deletes an entity, prune any undo entries that reference it
- Example: User A has "add edge to Block X" in undo stack, User B deletes Block X → prune that entry
- Prevents executing inverse ops on entities that no longer exist
Circular recording prevention
- Mark undo/redo operations as
isUndo: true during execution
- These operations should NOT be recorded into the undo stack themselves
Current code references
frontend/src/canvas/model/useCanvasDocument.ts — command functions that would generate undo entries
frontend/src/canvas/hooks/useCanvasShortcutContainer.ts — keyboard shortcut handling (add Cmd+Z here)
Acceptance criteria
Context
There is currently no undo/redo system. Sim implements undo/redo as a thin wrapper over the socket system — undo is just another edit that generates an inverse operation and sends it through the normal operation queue.
What to build
Per-user undo/redo stacks
Undo execution
Cmd+Z/Ctrl+Z: Pop from undo stack → push to redo stack → execute inverse op through the operation queueCmd+Shift+Z/Ctrl+Y: Pop from redo stack → push to undo stack → execute forward op through the operation queueCoalescing consecutive ops
Multiplayer-safe stack pruning
Circular recording prevention
isUndo: trueduring executionCurrent code references
frontend/src/canvas/model/useCanvasDocument.ts— command functions that would generate undo entriesfrontend/src/canvas/hooks/useCanvasShortcutContainer.ts— keyboard shortcut handling (add Cmd+Z here)Acceptance criteria