Files
initiative/specs/023-clear-encounter/research.md

41 lines
3.0 KiB
Markdown

# Research: 023-clear-encounter
## R1: Empty Encounter State in Domain
**Decision**: Introduce a `clearEncounter` domain function that returns an empty encounter (`{ combatants: [], activeIndex: 0, roundNumber: 1 }`) directly, bypassing `createEncounter()` which enforces the at-least-one-combatant invariant.
**Rationale**: The domain already handles empty combatant lists at runtime — `removeCombatant` can produce an encounter with 0 combatants (tested in AS-5 of remove-combatant tests). The `createEncounter` invariant prevents *construction* of empty encounters but the `Encounter` type itself has no minimum constraint. A dedicated `clearEncounter` function makes the intent explicit.
**Alternatives considered**:
- Relax `createEncounter()` to allow empty combatants — rejected because it would weaken the invariant for normal encounter creation flows.
- Use a separate `EmptyEncounter` type — rejected as over-engineering; the existing `Encounter` type already supports the shape.
## R2: Persistence of Cleared State
**Decision**: Update `loadEncounter()` to handle empty combatant arrays by constructing the empty encounter directly (without routing through `createEncounter()`). The existing `saveEncounter()` serializes the empty encounter as normal JSON.
**Rationale**: The spec requires cleared state to persist across page refreshes (FR-007). If we remove the localStorage key, `initializeEncounter()` falls back to the demo encounter, which violates the requirement. Storing and loading the empty encounter is the simplest approach.
**Alternatives considered**:
- Remove localStorage key + add a "cleared" flag — rejected as unnecessary complexity.
- Store a sentinel JSON value — rejected as non-standard and fragile.
## R3: Confirmation UI Pattern
**Decision**: Use browser-native `window.confirm()` for the destructive action confirmation.
**Rationale**: No dialog component currently exists in the project. Building a custom dialog for a single confirmation prompt would be over-engineering for MVP. Browser `confirm()` is synchronous, universally supported, and clearly communicates the destructive nature of the action. The confirmation logic lives in the adapter layer (React hook or component), keeping the domain pure.
**Alternatives considered**:
- Custom AlertDialog component (shadcn-style) — rejected for MVP; can be added later if a richer confirmation UX is needed.
## R4: Clear Button Placement
**Decision**: Add a clear/reset button in the TurnNavigation component, near the existing round/turn controls.
**Rationale**: The TurnNavigation bar is the encounter-level control area (advance turn, retreat turn, round counter). A "clear encounter" action is encounter-level, so it belongs here. Placing it near the round counter reinforces that it resets the entire encounter state.
**Alternatives considered**:
- ActionBar (bottom) — rejected; ActionBar is for adding combatants, not encounter-level management.
- Separate menu/dropdown — rejected as over-engineering for a single action.