When deleting a connected node, clearStaleInputImages calls updateNodeData
on target nodes to clear stale input images. Each updateNodeData call was
creating a debounced undo snapshot, resulting in 3-4 undos needed instead
of 1. Now updateNodeData skips undo tracking when nodeRemoveCheckpointActive
is true, since the node removal checkpoint already captured full pre-deletion state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When deleting a node via the canvas (Delete key), React Flow fires
onNodesChange(remove) then onEdgesChange(remove) synchronously.
Previously this created two undo entries, requiring two undos and
leaving an intermediate state with orphaned edges.
Now onNodesChange sets a microtask-scoped flag that tells onEdgesChange
to skip its checkpoint, collapsing both into a single undo entry.
Added integration test verifying single-undo restores node + edges.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Captures snapshots before all undoable mutations (add/remove nodes,
connect/remove edges, paste, group operations, edge style, drag start).
Data edits are debounced (500ms). Execution outputs are not undoable.
History depth: 50 entries. Cleared on load/clear workflow.
Keyboard shortcuts added to WorkflowCanvas and shortcuts dialog.
15 integration tests covering all undo/redo scenarios through the store.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>