Build ScenarioRuleEngine evaluate() core algorithm
epic-scenario-based-follow-up-prompts-core-logic-task-005 — Implement the ScenarioRuleEngine.evaluate(activityMetadata, rules, promptHistory) method. The algorithm must check: contact type match, wellbeing flag conditions (any/all semantics), activity duration range, delay window eligibility (hours since activity end), and prompt cooldown guard via PromptHistoryRepository. Return EvaluationResult with matched rule or null with reason code. This is the highest-complexity component.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
Implement evaluate() as a method on a ScenarioRuleEngine class that takes PromptHistoryRepository as a constructor-injected dependency. Use the Chain of Responsibility pattern: define a private List
EvaluationReasonCode should be an enum with values: MATCHED, NO_RULES_CONFIGURED, NO_RULES_MATCHED, CONTACT_TYPE_MISMATCH, WELLBEING_FLAGS_NOT_MET, DURATION_OUT_OF_RANGE, DELAY_WINDOW_NOT_MET, COOLDOWN_ACTIVE. Store conditionTrace as a List
Testing Requirements
Write unit tests using flutter_test with a mocked PromptHistoryRepository. Test matrix must cover: contact type exact match, contact type wildcard, contact type mismatch; wellbeing 'any' semantics with one match, all match, no match; wellbeing 'all' semantics with partial match (should not match) and full match; duration at min boundary (inclusive), max boundary (inclusive), below min, above max; delay window within range, before min, after max; cooldown active (recent prompt exists), cooldown inactive (no recent prompt or expired); empty rules list; all conditions satisfied simultaneously. Use parameterized test cases (test.parametrize pattern) to cover boundary values. Target 100% branch coverage on the evaluate() method body.
Add a performance smoke test asserting evaluate() completes in under 200ms for a list of 50 rules.
The Rule Engine must support a flexible JSON rule schema that can express compound conditions (e.g., contact_type AND wellbeing_flag AND delay_days). Underestimating schema expressiveness may require breaking changes to the rule format after coordinators have already configured rules.
Mitigation & Contingency
Mitigation: Define and freeze the rule JSON schema (trigger_type enum, metadata_conditions structure, delay logic) before any implementation begins; validate schema against all known HLF scenarios documented in the feature spec.
Contingency: If schema changes are needed after deployment, implement a schema version field and a migration utility that upgrades stored rules to the new format without coordinator intervention.
Deep-link navigation to the activity wizard with pre-filled arguments may fail if the user's session has expired or if the wizard route is not yet mounted in the navigator stack, causing unhandled navigation exceptions.
Mitigation & Contingency
Mitigation: Implement session state check before navigation; if session is expired, redirect to biometric/login screen and store the pending deep-link URI for post-auth redirect using go_router's redirect mechanism.
Contingency: If post-auth redirect proves unreliable, fall back to navigating to the home screen with a visible action banner that re-triggers the wizard with pre-filled arguments.