diff --git a/.agent/skills/krow-mobile-architecture/SKILL.md b/.agent/skills/krow-mobile-architecture/SKILL.md index eccc0bb2..febe1686 100644 --- a/.agent/skills/krow-mobile-architecture/SKILL.md +++ b/.agent/skills/krow-mobile-architecture/SKILL.md @@ -511,7 +511,7 @@ Modular.to.popSafe(); // ❌ AVOID Modular.to.navigate('/home'); // No safety -Navigator.push(...); // No Modular integration +Navigator.push(...); // No Modular integration (except when popping a dialog). ``` ### Data Sharing Patterns diff --git a/.claude/agents/mobile-qa-analyst.md b/.claude/agents/mobile-qa-analyst.md index 78d4d9bf..f21ca49b 100644 --- a/.claude/agents/mobile-qa-analyst.md +++ b/.claude/agents/mobile-qa-analyst.md @@ -20,7 +20,7 @@ and load any additional skills as needed for specific review challenges. You are working within a Flutter monorepo (where features are organized into packages) using: - **Clean Architecture**: Presentation (Pages, BLoCs, Widgets) → Application (Use Cases) → Domain (Entities, Interfaces, Failures) ← Data (Implementations, Connectors) - **State Management**: Flutter BLoC/Cubit. BLoCs registered with `i.add()` (transient), never `i.addSingleton()`. `BlocProvider.value()` for shared BLoCs. -- **DI & Routing**: Flutter Modular. Safe navigation via `safeNavigate()`, `safePush()`, `popSafe()`. Never `Navigator.push()` directly. +- **DI & Routing**: Flutter Modular. Safe navigation via `safeNavigate()`, `safePush()`, `popSafe()`. Never `Navigator.push()` directly (except when popping a dialog). - **Error Handling**: `BlocErrorHandler` mixin with `_safeEmit()` to prevent StateError on disposed BLoCs. - **Backend**: Firebase Data Connect through `data_connect` package Connectors. `_service.run(() => connector.().execute())` for auth/token management. - **Session Management**: `SessionHandlerMixin` + `SessionListener` widget. @@ -110,8 +110,20 @@ Analyze code for: - Race conditions in concurrent requests - Missing `_service.run()` wrapper for Data Connect calls +### Background Tasks & WorkManager +When reviewing code that uses WorkManager or background task scheduling, check these edge cases: +- **App backgrounded**: Does the background task work when the app is in the background? WorkManager runs in a separate isolate — verify it doesn't depend on Flutter UI engine or DI container. +- **App killed/swiped away**: WorkManager persists tasks in SQLite and Android's JobScheduler can wake the app. Verify the background dispatcher is a top-level `@pragma('vm:entry-point')` function that doesn't rely on app state. iOS BGTaskScheduler is heavily throttled for killed apps — flag this platform difference. +- **Screen off / Doze mode**: Android batches tasks for battery efficiency. Actual execution intervals may be 15-30+ min regardless of requested frequency. Flag any code that assumes exact timing. +- **Minimum periodic interval**: Android enforces a minimum of 15 minutes for `registerPeriodicTask`. Any frequency below this is silently clamped. Flag code requesting shorter intervals as misleading. +- **Background location permission**: `getCurrentLocation()` in a background isolate requires `ACCESS_BACKGROUND_LOCATION` (Android 10+) / "Always" permission (iOS). Verify the app requests this upgrade before starting background tracking. Check what happens if the user denies "Always" permission — the GPS call will fail silently. +- **Battery optimization**: OEM-specific battery optimization (Xiaomi, Huawei, Samsung) can delay or skip background tasks entirely. Flag if there's no guidance to users about whitelisting the app. +- **Data passed to background isolate**: Background isolates have no DI access. Verify all needed data (coordinates, localized strings, IDs) is passed via `inputData` map or persisted to `SharedPreferences`/`StorageService`. Flag any hardcoded user-facing strings that should be localized. +- **Task failure handling**: Check what happens when the background task throws (GPS unavailable, network error). Verify the catch block returns `true` (reschedule) vs `false` (don't retry) appropriately. Check if repeated failures are tracked or silently swallowed. +- **Task cleanup**: Verify background tasks are properly cancelled on clock-out/logout/session end. Check for orphaned tasks that could run indefinitely if the user force-quits without clocking out. + ### Navigation & Routing (Flutter Modular) -- Direct `Navigator.push()` usage instead of `safeNavigate()`/`safePush()`/`popSafe()` +- Direct `Navigator.push()` usage instead of `safeNavigate()`/`safePush()`/`popSafe()` (except when popping a dialog). - Back button behavior edge cases - Deep link handling - State loss during navigation