critical priority medium complexity frontend pending frontend specialist Tier 1

Acceptance Criteria

on<WizardPaused> handler: when current state is WizardInProgress, emits WizardPaused with pausedStepIndex == currentStepIndex, draftFieldValues == current fieldValues, and pausedAt == DateTime.now()
on<WizardPaused> calls WizardDraftRepository.saveDraft(draft) before emitting the paused state
on<WizardResumed> handler: when current state is WizardPaused, emits WizardInProgress restoring currentStepIndex and fieldValues from the paused snapshot
on<WizardResumed> also calls WizardDraftRepository.saveDraft to update the draft's 'last resumed' timestamp
Firing WizardPaused when already in WizardPaused state is a no-op (does not emit a new state)
Firing WizardResumed when in WizardIdle state is a no-op (does not crash)
WizardDraftRepository is injected via constructor (not instantiated inside BLoC) to enable mocking in tests
All WizardDraftRepository calls are awaited correctly — use emit.call inside async handler
The draft snapshot includes all field values present at the moment of pause, not a subset
pausedAt timestamp uses UTC (DateTime.now().toUtc())

Technical Requirements

frameworks
Flutter
BLoC
performance requirements
Pause handler must complete in < 100ms excluding repository write time
Repository write is async but must not block UI thread — use async BLoC event handler pattern
security requirements
Draft field values written to repository must not include sensitive PII in plaintext if the wizard collects sensitive fields — apply field-level encryption if required by the wizard's content domain
WizardDraftRepository must not expose draft data to other users — drafts keyed by user ID

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Inject WizardDraftRepository as an abstract interface (abstract class or interface keyword in Dart) so tests can mock it without hitting local storage. The async BLoC event handler pattern in flutter_bloc uses `on((event, emit) async { ... })` — use this form for pause/resume since repository calls are async. Be careful not to call emit after the BLoC is closed (check isClosed before emitting in async handlers if the handler can be long-running).

The WizardDraft domain model should be a simple data class with: stepIndex, fieldValues (Map), pausedAt (DateTime), wizardId (String to differentiate multi-wizard apps). Define WizardDraft in lib/features/wizard/domain/wizard_draft.dart.

Testing Requirements

Unit tests using bloc_test. Test scenarios: (1) pause from WizardInProgress — verify WizardPaused state emitted and repository.saveDraft called with correct data; (2) resume from WizardPaused — verify WizardInProgress emitted with restored step and fields; (3) pause when already paused — verify no new state emitted; (4) resume when in WizardIdle — verify no crash, no state change; (5) repository throws on saveDraft — verify BLoC emits error state or handles gracefully without crashing. Mock WizardDraftRepository with Mockito or manual mock. Use bloc_test's `act` and `expect` helpers.

Component
Wizard State Manager
service medium
Epic Risks (4)
high impact medium prob technical

The WizardStateManager BLoC must guarantee that step transitions only occur on explicit user action, never automatically. Subtle reactive patterns in Bloc (e.g. stream listeners triggering add() calls) could inadvertently auto-advance the wizard, violating the core cognitive accessibility rule and creating a regression that is difficult to detect without dedicated tests.

Mitigation & Contingency

Mitigation: Write a dedicated unit test that subscribes to the BLoC stream and asserts no StepChanged event is emitted for 5 seconds after a state update, without an explicit user-sourced event being dispatched. Make this test part of the CI gate for the WizardStateManager.

Contingency: If an auto-advance regression is discovered post-integration, introduce a mandatory UserActionToken parameter on all step-transition events so the BLoC can structurally refuse transitions that do not originate from a user gesture handler.

medium impact medium prob integration

The ConfirmBeforeSubmitScreen requires deep-linking back to specific wizard steps for corrections. Implementing bidirectional navigation within a multi-step wizard while preserving all previously entered state is architecturally non-trivial and may conflict with the existing StatefulShellRoute navigation setup described in the app architecture.

Mitigation & Contingency

Mitigation: Design the ConfirmBeforeSubmitScreen's back-navigation links to dispatch a GoToStep event on the WizardStateManager rather than using GoRouter's pop() chain. This keeps navigation state entirely in the BLoC and avoids coupling to the router's stack semantics.

Contingency: If BLoC-driven step navigation proves incompatible with the router, implement the correction flow as a dedicated sub-route that pre-populates its form from the WizardStateManager's current draft, then merges the edited field back into the draft on completion before returning to the confirm screen.

medium impact medium prob technical

The CognitiveAccessibilityAudit utility must inspect live widget trees for violations such as icon-only buttons. Flutter's widget tree inspection APIs are available in test mode but have limitations in identifying semantic intent (e.g. distinguishing a decorative icon from a navigation button). False negatives could give a false sense of compliance.

Mitigation & Contingency

Mitigation: Augment the audit with a convention-based approach: require all navigation buttons to use a named wrapper widget (e.g. LabelledNavigationButton) that the audit can detect by type, rather than relying solely on widget-tree semantics analysis.

Contingency: If widget-tree detection proves insufficiently reliable, scope the CognitiveAccessibilityAudit to route-configuration analysis (verifying back navigation availability per route) and static analysis of wizard step count definitions via the CognitiveLoadRuleEngine, which provides deterministic results.

low impact high prob scope

The InlineContextualHelpWidget sources content from a bundled JSON asset via the HelpContentRegistry. If help texts are missing for newly added screens or fields (a likely scenario as the 61-feature app grows), the widget silently shows nothing, degrading the accessibility experience without any visible failure.

Mitigation & Contingency

Mitigation: Integrate a CognitiveAccessibilityAudit check that verifies every registered (screenId, fieldId) pair that requests help has a corresponding entry in the HelpContentRegistry bundle. Run this check in CI as part of the audit report.

Contingency: Add a debug-mode overlay that highlights fields with missing help entries using a visible warning indicator, making coverage gaps immediately obvious to developers during local development before they reach CI.