5.5 KiB
Feature Specification: Persist Encounter
Feature Branch: 008-persist-encounter
Created: 2026-03-05
Status: Draft
Input: User description: "Persist the encounter in browser localStorage so the current encounter survives page reloads."
User Scenarios & Testing (mandatory)
User Story 1 - Encounter Survives Page Reload (Priority: P1)
A user is managing a combat encounter (combatants added, initiative set, turns advanced). They accidentally refresh the page or their browser restarts. When the page reloads, the encounter is restored exactly as it was -- same combatants, same initiative values, same active turn, same round number.
Why this priority: This is the core value of the feature. Without persistence, all encounter progress is lost on any page navigation or reload, which is the primary pain point.
Independent Test: Can be fully tested by setting up an encounter, refreshing the page, and verifying all encounter state is preserved.
Acceptance Scenarios:
- Given an encounter with combatants, initiative values, active turn, and round number, When the user reloads the page, Then the encounter is restored with all state intact (combatants, initiative, active index, round number).
- Given an encounter that has been modified (combatant added, removed, renamed, or initiative changed), When the user reloads the page, Then the latest state is reflected.
- Given the user advances the turn multiple times, When the user reloads the page, Then the active turn and round number are preserved.
User Story 2 - Fresh Start with No Saved Data (Priority: P2)
A first-time user opens the application with no previously saved encounter. The application shows the default demo encounter so the user can immediately start exploring.
Why this priority: Ensures backward compatibility and a smooth first-use experience.
Independent Test: Can be tested by clearing browser storage and loading the application, verifying the demo encounter appears.
Acceptance Scenarios:
- Given no saved encounter exists in the browser, When the user opens the application, Then the default demo encounter is displayed.
- Given saved encounter data has been manually cleared from the browser, When the user opens the application, Then the default demo encounter is displayed.
User Story 3 - Graceful Handling of Corrupt Data (Priority: P3)
Saved data may become invalid (e.g., manually edited in dev tools, schema changes between versions). The application handles this gracefully rather than crashing.
Why this priority: Protects the user experience from edge cases that would otherwise render the app unusable without manual intervention.
Independent Test: Can be tested by writing malformed data to the storage key and loading the application.
Acceptance Scenarios:
- Given the saved encounter data is malformed or unparseable, When the user opens the application, Then the default demo encounter is displayed and the corrupt data is discarded.
- Given the saved data is missing required fields, When the user opens the application, Then the default demo encounter is displayed.
Edge Cases
- What happens when browser storage quota is exceeded? The application continues to function normally; persistence silently fails without disrupting the user's current session.
- What happens when browser storage is unavailable (e.g., private browsing in some browsers)? The application falls back to in-memory-only behavior, functioning identically to the current experience.
- What happens when the user has multiple browser tabs open? MVP baseline does not include cross-tab synchronization. Each tab operates independently; the last tab to save wins.
Requirements (mandatory)
Functional Requirements
- FR-001: System MUST save the full encounter state (combatants, activeIndex, roundNumber) to browser storage after every state change.
- FR-002: System MUST restore the saved encounter state when the application loads, if valid saved data exists.
- FR-003: System MUST fall back to the default demo encounter when no saved data exists or saved data is invalid.
- FR-004: System MUST NOT crash or show an error to the user when storage is unavailable or data is corrupt.
- FR-005: System MUST preserve combatant identity (IDs, names, initiative values) across reloads.
- FR-006: System MUST preserve the active turn position and round number across reloads.
Key Entities
- Persisted Encounter: A serialized representation of the Encounter (combatants with IDs, names, and initiative values; activeIndex; roundNumber) stored in the browser.
Success Criteria (mandatory)
Measurable Outcomes
- SC-001: Users can reload the page and see their encounter fully restored within 1 second, with zero data loss.
- SC-002: First-time users see the demo encounter immediately on first visit with no extra steps.
- SC-003: 100% of corrupt or missing data scenarios result in a usable application (demo encounter displayed), never a crash or blank screen.
Assumptions
- The encounter state is small enough that serialization/deserialization has negligible performance impact.
- A single browser storage key is sufficient for the MVP (one encounter at a time).
- Cross-tab synchronization is not required for the MVP baseline.
- The ID counter for new combatants must also be persisted or derived from existing state so that new combatants added after a reload do not collide with existing IDs.