* fix: guard debounced desktop selection update
Avoid dereferencing a cleared selection from the delayed
macOS metrics callback and add a regression test that
covers the stale-timer path.
* chore: clean up analyzer warnings
Remove redundant default arguments in tests and apply the
missing trailing comma required by the current lint rules.
Multi-step redo was broken because `getUndoHistoryItem()` cleared the
redo stack whenever the last undo item was sealed — even during redo
operations. After the first redo, the 50ms debounce timer would seal
the item, causing the next redo to wipe the remaining redo history.
Refactored the undo/redo system with:
- `TransactionSource` enum (userEdit, undo, redo, none) replacing
boolean flag combinations in ApplyOptions
- `UndoManager.record()` with symmetric paths for each source:
- userEdit: groups into unsealed items, clears redo on branch
- undo: pushes directly to redo stack
- redo: pushes directly to undo stack (sealed), no redo clear
- Deprecated `getUndoHistoryItem()` and legacy boolean flags