high priority low complexity frontend pending frontend specialist Tier 0

Acceptance Criteria

Widget accepts required parameters: headline (String), instruction (String)
Widget accepts optional parameters: onDismiss (VoidCallback?), icon (IconData? defaulting to Icons.error_outline)
Rendered output has exactly two visible text nodes: one for headline, one for instruction
Headline uses design token errorHeadlineTextStyle (from AccessibilityDesignTokenEnforcer); instruction uses errorBodyTextStyle
Error container background uses design token errorSurfaceColor; icon and headline color uses errorOnSurfaceColor
Semantics widget wraps the entire error block with liveRegion: true and label combining headline and instruction text for screen readers
Widget passes WCAG 2.2 AA contrast ratio (>= 4.5:1) for all text/background combinations when using error design tokens
If onDismiss is provided, a dismiss button (X icon) is rendered with Semantics label 'Dismiss error'
Widget does not contain any inline style strings — all styling via design token lookups
Widget renders without overflow on 320px minimum width
Widget is stateless (StatelessWidget) — no internal state management

Technical Requirements

frameworks
Flutter
data models
accessibility_preferences
performance requirements
Widget must build in a single frame — no async operations inside build()
No FutureBuilder or StreamBuilder — purely synchronous rendering
security requirements
Headline and instruction strings must be HTML-escaped before rendering if they contain user-supplied content
liveRegion: true must not announce PII — ensure error messages are generic and do not echo back user data
ui components
PlainLanguageErrorDisplay
Semantics (liveRegion)
AccessibilityDesignTokenEnforcer

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Create the widget at lib/features/wizard/widgets/plain_language_error_display.dart. Use Column with CrossAxisAlignment.start inside a Container styled with AccessibilityDesignTokenEnforcer.errorSurfaceColor. Wrap the entire Column in a Semantics widget: Semantics(liveRegion: true, label: '$headline. $instruction', child: ...).

The child widgets (headline Text, instruction Text) should have excludeSemantics: false (default) so they remain individually focusable by screen readers while the parent announces on appearance. For contrast compliance, reference the design token values in a comment — do not hardcode hex values. The dismiss button should use IconButton with Semantics(label: 'Dismiss error') wrapping or the tooltip parameter. Keep the widget under 60 lines — if it grows larger, extract a private _ErrorContent widget.

Testing Requirements

Widget tests using flutter_test. Test cases: (1) renders headline and instruction text correctly; (2) Semantics node has liveRegion: true; (3) dismiss button rendered when onDismiss provided; (4) dismiss button absent when onDismiss is null; (5) no overflow at 320px width using tester.binding.setSurfaceSize(); (6) icon defaults to Icons.error_outline when not provided; (7) custom icon renders when provided. Use tester.ensureSemantics() and tester.getSemantics(find.byType(PlainLanguageErrorDisplay)) to assert liveRegion. Total: minimum 7 test cases in test/widgets/plain_language_error_display_test.dart.

Component
Plain Language Error Display
ui low
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.