Scaffold Scheduler Service skeleton and interfaces
epic-scenario-based-follow-up-prompts-scheduler-and-ui-task-001 — Create the Dart class skeleton for the Scenario Prompt Scheduler Service including abstract interfaces, dependency injection wiring via Riverpod, and stub method signatures for fetchActivities, runRuleEngine, deduplicateHistory, dispatchNotification, and recordDelivery.
Acceptance Criteria
Technical Requirements
Implementation Notes
Place the service files at `lib/features/scenario_prompts/services/scenario_prompt_scheduler_service.dart` (abstract class + impl) and `lib/features/scenario_prompts/services/scenario_prompt_scheduler_provider.dart` (Riverpod provider). Define domain types in `lib/features/scenario_prompts/models/`: `ActivityRecord`, `SchedulingContext`, `RuleEngineResult`, `NotificationPayload`, `DeliveryRecord`. Use Riverpod's `@riverpod` code generation annotation if the project already uses it — check existing providers for the pattern in use. For the abstract interface, prefer `abstract interface class` (Dart 3 syntax) over `abstract class` to signal that this is a pure interface contract.
Keep the constructor of `ScenarioPromptSchedulerServiceImpl` taking only the dependencies it will need (Supabase client, notification service ref) so future implementors do not need to refactor the constructor signature.
Testing Requirements
Unit tests for this scaffold task are limited to compilation and structural validation: (1) a test that instantiates a `MockScenarioPromptSchedulerService` (hand-written mock implementing the abstract class) and verifies each method can be called and returns a Future; (2) a test that verifies the Riverpod provider resolves without throwing when given a valid ProviderContainer with required dependency overrides. Use `flutter_test` package. Full method-level tests will be added in subsequent tasks when stub bodies are replaced with real implementations.
If the scheduler runs concurrently (e.g., two overlapping cron invocations due to edge function retry), duplicate prompts could be dispatched before the first run's history records are committed, breaking the deduplication guarantee.
Mitigation & Contingency
Mitigation: Use a Postgres advisory lock or unique constraint on (user_id, scenario_id, activity_ref) in the prompt history table to make concurrent writes idempotent; design the scheduler to check history inside a transaction.
Contingency: If concurrency issues persist in production, add a distributed lock via Supabase Edge Function concurrency limit (max_instances=1) for the evaluation function as a hard guard.
Coordinators may find scenario configuration unclear if trigger conditions are expressed as raw JSON or technical terminology, leading to misconfiguration and irrelevant prompts being sent to peer mentors.
Mitigation & Contingency
Mitigation: Design the ScenarioConfigurationScreen to display human-readable descriptions of each template's trigger condition (e.g., 'Send 3 days after first contact if wellbeing concern was flagged') rather than raw rule properties; validate with an HLF coordinator in a design review before implementation.
Contingency: If coordinators still misconfigure rules after launch, add a preview mode that shows a simulated prompt based on a test activity before the rule is enabled.