# Quickstart: Undo/Redo **Feature**: 037-undo-redo **Date**: 2026-03-26 ## Overview This feature adds undo/redo to all encounter state changes using the memento (snapshot) pattern. Each action captures the pre-action encounter state onto an undo stack. Undo restores the previous state; redo re-applies an undone state. ## Implementation Layers ### Domain (`packages/domain/src/undo-redo.ts`) Pure functions for stack management: - `pushUndo(state, snapshot)` — push snapshot, cap at 50, clear redo - `undo(state, currentEncounter)` — pop undo, push current to redo - `redo(state, currentEncounter)` — pop redo, push current to undo - `clearHistory()` — reset both stacks All functions take and return immutable data. No I/O. ### Application (`packages/application/src/`) Use cases that orchestrate domain calls via store ports: - `undoUseCase(encounterStore, undoRedoStore)` — execute undo - `redoUseCase(encounterStore, undoRedoStore)` — execute redo New port interface `UndoRedoStore` in `ports.ts`: - `get(): UndoRedoState` - `save(state: UndoRedoState): void` ### Web Adapter (`apps/web/src/`) **Hook (`use-encounter.ts`)**: Wraps every action callback to capture pre-action snapshot. Exposes `undo()`, `redo()`, `canUndo`, `canRedo`. **Persistence (`persistence/undo-redo-storage.ts`)**: Save/load undo/redo stacks to localStorage keys `"initiative:encounter:undo"` and `"initiative:encounter:redo"`. **UI (`components/turn-navigation.tsx`)**: Undo/Redo buttons in the top bar, inboard of the turn step buttons, disabled when stack is empty. **Keyboard (`hooks/use-undo-redo-shortcuts.ts`)**: Global keydown listener for Ctrl+Z / Ctrl+Shift+Z (Cmd on Mac). Suppressed when text input has focus. ## Key Design Decisions 1. **Memento over Command**: Full encounter snapshots, not inverse events. Simpler at encounter scale (~2-5 KB per snapshot). 2. **Capture in hook, not domain**: Snapshot capture happens in the adapter layer. Domain and application layers are unaware of undo/redo. 3. **React state for stacks**: Enables reactive button disabled states without manual re-render triggers. 4. **Clear is not undoable**: Both stacks reset on encounter clear (per spec). ## Testing Strategy - **Domain tests**: Pure function tests for stack operations (push, pop, cap, clear, undo/redo roundtrip). - **Application tests**: Use case tests with mock stores. - **Integration**: Spec acceptance scenarios mapped to test cases (undo restores state, redo reapplies, new action clears redo, keyboard suppression during input focus).