high priority low complexity integration pending frontend specialist Tier 1

Acceptance Criteria

PlainLanguageErrorDisplay accepts a required `errorCode` String parameter and an optional `registry` parameter for dependency injection in tests
When a valid errorCode is provided, the widget resolves it via ErrorMessageRegistry.resolve(errorCode) and renders both the headline and action fields from the returned message object
When an unknown errorCode is provided (not found in the registry), the widget renders a predefined generic fallback message with both headline ('Something went wrong') and action ('Please try again or contact support') fields
Registry lookup is synchronous — no async gap between error state change and message display; no loading spinner or frame delay
The widget does NOT call setState or trigger a rebuild when the registry is queried — resolution happens in build()/didUpdateWidget() only
ErrorMessageRegistry.resolve() is called exactly once per errorCode value change, not on every rebuild
If errorCode is null or empty string, the widget renders nothing (SizedBox.shrink equivalent) without throwing
Fallback message is defined as a const in a single location (not duplicated across widget code)
Widget integrates cleanly with existing PlainLanguageErrorDisplay Semantics structure from task-005 — no Semantics regression
Widget compiles and renders correctly with both the real ErrorMessageRegistry singleton and a mock/stub registry

Technical Requirements

frameworks
Flutter
flutter_test
apis
ErrorMessageRegistry (internal foundation epic API)
data models
accessibility_preferences
performance requirements
Registry lookup must complete in O(1) — backed by a Map<String, ErrorMessage> or equivalent constant-time structure
No async operations in the resolution path — widget must render synchronously on first frame after errorCode is set
Widget rebuild triggered by errorCode change must not cause visible flash or layout shift
security requirements
Error codes must never expose internal system details (stack traces, SQL errors, API keys) in resolved messages
Registry entries validated at registration time — no runtime interpolation of user-controlled strings into message templates
ui components
PlainLanguageErrorDisplay
ErrorMessageRegistry

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Inject the registry via constructor to keep the widget testable: `PlainLanguageErrorDisplay({required String? errorCode, ErrorMessageRegistry? registry})` — default the registry parameter to `ErrorMessageRegistry.instance` inside the constructor body so production code is zero-boilerplate. Define a private const `_fallback = ErrorMessage(headline: '...', action: '...')` at the top of the file.

Resolve inside `build()` using a local variable (`final msg = (widget.errorCode != null ? registry.resolve(widget.errorCode!) : null) ?? _fallback`) so the resolution is purely functional with no side effects. Avoid `initState`/`didChangeDependencies` for the lookup — keeping it in `build()` means hot-reload and widget tree reconstruction work correctly without stale state.

If ErrorMessageRegistry is a singleton built on a `const Map`, the lookup is guaranteed O(1) with no locking concerns on the UI thread.

Testing Requirements

Write unit tests for the registry resolution logic (pure Dart, no Flutter widgets): (1) known code returns correct {headline, action} object, (2) unknown code returns the fallback object, (3) null/empty code returns null without throwing. Write widget tests using a stub registry: verify that with a known code the rendered Text widgets show the correct headline and action strings; verify that with an unknown code the fallback strings are rendered; verify that with a null code the widget tree is empty. Confirm no extra rebuild occurs by spying on build call count. All tests must pass with `flutter test` in CI.

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.