Define navigation state data models and interfaces
epic-navigation-and-gesture-accessibility-foundation-task-001 — Define the core Dart data models and interfaces for navigation state persistence: TabIndex value object, NavigationStackSnapshot, and NavigationStateRecord. These models will be used by both the repository and the tab state manager, so they must be finalized before any persistence or state logic is written.
Acceptance Criteria
Technical Requirements
Implementation Notes
Prefer using freezed for value object boilerplate (== , copyWith, toJson) to reduce hand-written code and future maintenance. If freezed is not already a project dependency, a simple immutable class with const constructor and manual == / hashCode override is acceptable. Define the abstract interface using Dart abstract class (not mixin) so it can be implemented by multiple storage backends in future. Use List
Keep the barrel file import-clean: only export public types, not internal helpers. These models become the contract between the repository (task-002) and the BLoC/Cubit (task-004 onward), so agree on the serialization format with the team before merging.
Testing Requirements
Write pure Dart unit tests (no Flutter widgets needed) covering: (1) TabIndex.fromInt(0..4) succeeds, (2) TabIndex.fromInt(-1) and fromInt(5) throw ArgumentError, (3) NavigationStackSnapshot.toJson() / fromJson() round-trip, (4) NavigationStateRecord.toJson() / fromJson() round-trip with all 5 tabs populated, (5) equality: two instances with identical data are equal (==). No mocking required. Target 100% line coverage for the models file.
StatefulShellRoute branch navigator state can interact unexpectedly with GoRouter's imperative navigation (go, push, replace), causing state snapshots to desync from actual route stacks. This could manifest as a user returning to a tab and seeing a different screen than expected, breaking the core motor-fatigue promise.
Mitigation & Contingency
Mitigation: Write integration tests that simulate cross-tab navigation with nested pushes before any UI layer is built. Pin go_router to a tested minor version and review the StatefulShellRoute changelog before upgrading.
Contingency: If branch navigator state consistently desyncs, fall back to a manual stack snapshot strategy using a custom NavigatorObserver that records and replays navigation events independently of StatefulShellRoute internals.
Persisted navigation stacks in shared_preferences can become stale or corrupt if route paths are renamed during development, causing app crashes or infinite redirect loops on cold start for users who have an old snapshot.
Mitigation & Contingency
Mitigation: Version the persisted schema with a format key. On app start, validate that all stored route paths exist in the current route config before restoring; silently discard invalid entries rather than crashing.
Contingency: Implement a safe-mode cold start that skips state restoration after a detected crash (via a dirty-launch flag written at startup and cleared on successful first frame), falling back to the default root tab.