high priority medium complexity testing pending testing specialist Tier 4

Acceptance Criteria

All text elements in both widgets have a contrast ratio of at least 4.5:1 against their background (WCAG 1.4.3 AA) โ€” verified with a color contrast tool (e.g., Colour Contrast Analyser or automated test)
All non-text icons that convey meaning (warning, error, check, progress states) have a contrast ratio of at least 3:1 against adjacent colors (WCAG 1.4.11 AA)
Amber/warning color token used in task-006 passes 3:1 contrast against the card background in both light and dark themes
Every interactive element (retry button, dismiss button) has a minimum touch target of 44ร—44 logical pixels (WCAG 2.5.5 AA)
Focus traversal order is logical (top-to-bottom, left-to-right) โ€” verified by tab-key traversal test in flutter_test using FocusTrap
All BLoC state transitions in AggregationProgressIndicator that change visible content are announced via Semantics liveRegion: true
Progress stage indicators have Semantics labels describing both the stage name and its status (e.g., 'Stage: Data validation โ€” Completed')
Warning section in AggregationSummaryWidget has Semantics role alert and is announced when it appears
No decorative icons have a semantic label โ€” they use excludeSemantics: true
Error state in AggregationProgressIndicator includes both an icon and text description โ€” not icon-only (WCAG 1.1.1)
All audit findings are documented in a brief inline code comment with WCAG criterion number, and all violations are fixed before task closure
Accessibility audit checklist document produced listing each criterion checked, result (pass/fail), and fix applied

Technical Requirements

frameworks
Flutter Semantics API
flutter_test SemanticsHandle
Flutter accessibility inspector (via flutter_driver or integration test)
performance requirements
Semantics wrappers must not introduce measurable frame time regression โ€” verify with Flutter DevTools timeline
security requirements
Semantic labels must not expose internal state identifiers or UUIDs โ€” use human-readable descriptions only
ui components
Semantics widget (Flutter core)
MergeSemantics for grouped elements
ExcludeSemantics for decorative elements
SizedBox / GestureDetector with minimum 44x44 constraints for touch targets

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

Approach the audit in two phases: (1) automated โ€” write flutter_test semantics assertions first to catch regressions; (2) manual โ€” use Xcode Accessibility Inspector or Android TalkBack to validate real screen reader behavior. For contrast ratio verification, extract all color token values from the design system and run them through contrast ratio calculation (luminance formula: WCAG 2.1 ยง1.4.3). Common Flutter accessibility pitfalls to check: IconButton default touch target is 48ร—48 (fine), but custom GestureDetector tap areas may be smaller โ€” wrap with ConstrainedBox(constraints: BoxConstraints(minWidth: 44, minHeight: 44)). For liveRegion announcements, ensure the Semantics container wrapping dynamic content has liveRegion: true AND is a direct ancestor of the content that changes.

Note: VoiceOver on iOS has known quirks with Flutter Semantics โ€” test on a real device or simulator, not just flutter_test. The amber warning color needs special attention โ€” amber on white commonly fails AA at smaller text sizes.

Testing Requirements

Accessibility tests using flutter_test SemanticsHandle: (1) enable semantics with tester.ensureSemantics(); (2) assert SemanticsNode labels for all progress stage indicators in active, completed, pending, error states; (3) assert liveRegion is true on dynamic state containers; (4) assert touch target sizes using tester.getSize() โ€” minimum Size(44, 44); (5) assert decorative icons have excludeSemantics or empty label. Manual audit step: use Flutter accessibility inspector in DevTools and VoiceOver (iOS simulator) to walk through both widgets in all BLoC states. Document each WCAG criterion result in the PR description. Include results for both light and dark themes.

Epic Risks (2)
medium impact high prob scope

For NHF with 1,400 local chapters, rendering a geographic breakdown as a flat list in the AggregationSummaryWidget would produce an unscrollable wall of data that is unusable on a mobile screen. Coordinators need to verify geographic completeness before export, but the raw chapter list is too long to review.

Mitigation & Contingency

Mitigation: Design the geographic distribution section as a collapsible two-level hierarchy: regions are shown expanded by default with their aggregate count, individual chapters are collapsed under each region and expandable on tap. Show only non-zero regions by default with a 'show empty regions' toggle.

Contingency: If the hierarchical display is too complex to implement before the submission deadline, fall back to a region-only summary view with a total count of active chapters per region and a note that chapter-level detail is available in the full export file.

medium impact medium prob technical

The aggregation BLoC must handle a multi-stage async pipeline with partial success states, warning accumulation across stages, and retry logic for individual failed stages. If the state model is too simplistic (e.g., loading/success/error), warning states and partial results will be lost on retry, confusing coordinators who see warnings disappear and reappear.

Mitigation & Contingency

Mitigation: Model the BLoC state as a rich sealed class hierarchy: AggregationIdle, AggregationRunning(stage, completedStages, accumulatedWarnings), AggregationComplete(result, warnings), AggregationFailed(failedStage, accumulatedWarnings, error). Accumulated warnings persist across retry attempts so coordinators see the full warning history.

Contingency: If state management complexity causes repeated bugs near the deadline, simplify to a single AggregationResult value object that captures success, warnings, and error as nullable fields, and drive both UI components from that single object rather than a live BLoC stream.