--- phase: 02-provider-migration task: 0 total_tasks: 5 status: planned last_updated: 2026-02-10 --- Phase 2 planning is COMPLETE. All planning artifacts (research, context, 2 plans) are written and verified. No execution has started yet. Ready to execute. - /gsd:discuss-phase 2 — Context gathered, user decisions locked in 02-CONTEXT.md - /gsd:plan-phase 2 — Research completed (02-RESEARCH.md), 2 plans created and checker-verified - 02-01-PLAN.md: Provider infrastructure (Wave 1, 3 tasks) — GpsDataManager ChangeNotifier refactor, SettingsProvider, OverlayProvider - 02-02-PLAN.md: MultiProvider wiring + screen migration (Wave 2, 2 tasks) — main.dart rewrite, SpeedometerScreen full migration - Checker passed after 1 revision (trip tracking absence acknowledged, verification concretized) - Execute Plan 02-01 (Wave 1): Add provider/shared_preferences deps, refactor GpsDataManager, create SettingsProvider, create OverlayProvider - Execute Plan 02-02 (Wave 2): Wire MultiProvider in main.dart, migrate SpeedometerScreen from setState to Consumer/Selector - Verify phase completion against success criteria - GpsDataManager extends ChangeNotifier directly (stays in services/, not moved to providers/) - Singleton pattern removed — all access via Provider BuildContext - SettingsProvider = theme + units combined (not separate providers) - OverlayProvider centralizes ALL overlay management (show/close, messaging, status checking) - OverlayProvider uses ChangeNotifierProxyProvider2 depending on GpsDataManager + SettingsProvider - GPS stream subscription in OverlayProvider: listens continuously, skips sends via if-check when inactive - Heartbeat/polling stripped to simple boolean — Phase 3 builds proper detection - Big bang migration — no temporary setState/Provider coexistence - Trip tracking code: confirmed absent from codebase, no removal needed - SharedPreferences pre-initialized in async main() before runApp() - Permission handling kept procedural in GpsDataManager.initialize() None. Plans are verified and ready for execution. This is a Provider migration for a GPS speedometer Flutter app. The app has a single main screen (SpeedometerScreen) with 11 setState calls that need replacing with Consumer/Selector widgets. The overlay runs in a separate isolate and communicates via FlutterOverlayWindow.shareData — it cannot access Provider, so overlay_screen.dart is unchanged. Key architectural insight: GpsDataManager already has broadcast streams, so adding ChangeNotifier is additive (notifyListeners alongside existing stream). OverlayProvider subscribes to the stream directly. The screen uses Selector widgets for granular rebuilds (speed display independent of theme changes). The research identified 7 pitfalls, most critical being "ChangeNotifier after dispose" from async GPS callbacks — all providers use _isDisposed guards. Run: /gsd:execute-phase 2 This will execute Wave 1 (02-01-PLAN.md) first, then Wave 2 (02-02-PLAN.md). Wave 1 creates provider infrastructure. Wave 2 wires it all together and migrates the screen.