high priority medium complexity infrastructure pending infrastructure specialist Tier 1

Acceptance Criteria

The module identifies all interactive SemanticsNode instances (or widget tree nodes with tap/gesture handlers) and records their rendered size in logical pixels (dp)
Any interactive control smaller than 24×24 dp is flagged as a WCAG 2.2 AA hard violation
Any interactive control between 24×24 dp and 44×44 dp is flagged as a WCAG 2.5.8 advisory warning (preferred target not met)
Controls that meet the 44×44 dp preferred target are marked as passing
The report includes: widget type, widget key (if set), nearest ancestor route name, measured size, violation level, and a suggested fix (e.g., 'wrap with SizedBox(width: 44, height: 44)')
The module is runnable both as a standalone Dart tool (static analysis of widget factory sizes) and as a flutter_test integration test (runtime measurement via tester.getSize())
All existing interactive controls in the app's reusable widget library (AppButton, AppTextField, bottom nav items, modal close button) are assessed and any violations addressed before the module ships
The output report is appended to the same `.wcag/` directory used by the contrast checker (task-012) and follows the same JSON structure convention

Technical Requirements

frameworks
Flutter
flutter_test
Dart
data models
TouchTargetResult (widgetType, widgetKey, routeName, measuredSize, minimumRequired, preferredTarget, violationLevel, suggestedFix)
WCAGReport (shared with contrast checker: violations, warnings, passes, summary)
performance requirements
Runtime measurement mode (flutter_test integration) must complete all interactive-control size checks within the test timeout (default 30 s for the full suite)
Static analysis mode must complete in under 5 seconds
ui components
AppButton
AppTextField
AccessibleBottomNavigation tab items
AccessibleModalSheet close button
All gesture-detected widgets (GestureDetector, InkWell, IconButton)

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Implement as two complementary strategies: (A) a flutter_test helper `TouchTargetValidator.checkAll(tester)` that finds all `SemanticsNode` objects with `SemanticsFlag.isButton`, `isFocusable`, `hasEnabledState`, or gesture actions, calls `tester.getSize()` on the corresponding widget, and records results; (B) a static manifest approach where each reusable widget declares its minimum size as a const, and the Dart CLI tool checks these declarations against WCAG thresholds without needing a running app. Prefer strategy A for integration tests and strategy B for CI pre-build checks. For strategy A, use `tester.semantics` to walk the semantics tree: `tester.semantics.debugSemantics` gives the root node; recursively collect nodes where `node.getSemanticsData().flags` includes any interactive flag. Map each SemanticsNode back to a widget by using `find.bySemanticsLabel` or `find.byKey` with the node's key.

Reuse the `WCAGReport` data model and JSON serialisation from task-012 so both validators contribute to a unified report. Add a `check:wcag-touch-targets` CI target that fails on hard violations (< 24 dp) and warns on advisory issues (24–44 dp).

Testing Requirements

Write flutter_test widget tests that: (1) mount an AppButton with a known constrained size below 24 dp and assert the validator flags it as a hard violation; (2) mount an AppButton at 36×36 dp and assert it is flagged as an advisory warning; (3) mount an AppButton at 44×44 dp and assert it passes; (4) mount a non-interactive Text widget and assert it is not included in the results; (5) assert the JSON report for a known widget set matches a snapshot. Use `tester.getSize(find.byType(AppButton))` for runtime measurement. Also write pure unit tests for the violation classification logic (< 24 → violation, 24–44 → warning, ≥ 44 → pass) with no widget pumping required. Aim for ≥ 90% branch coverage across both measurement and classification paths.

Component
WCAG 2.2 AA Compliance Checker
infrastructure medium
Epic Risks (3)
high impact high prob integration

Flutter does not natively enforce a focus trap within a bottom sheet or modal dialog in the semantic tree — VoiceOver and TalkBack can navigate outside the sheet to background content. Implementing a reliable focus trap requires overriding the semantic tree, which may conflict with the existing modal helper infrastructure in the app and require changes to shared components beyond this feature's scope.

Mitigation & Contingency

Mitigation: Prototype the focus trap on the first modal sheet implementation before building the remaining sheets. Evaluate Flutter's ExcludeSemantics and BlockSemantics widgets as the trap mechanism, and coordinate with the team owning the shared modal helpers to agree on a non-breaking integration point before writing production code.

Contingency: If a complete semantic focus trap cannot be implemented without breaking existing modal patterns, implement a partial solution using FocusScope with autofocus on the modal's first element and a prominent 'Return to main content' semantic action, documenting the deviation from WCAG 2.4.3 with a scheduled remediation item.

high impact medium prob technical

The activity wizard uses BLoC state management and the UI rebuilds the entire step widget subtree on transition. If the semantic tree is traversed by VoiceOver before the build cycle settles, focus may land on a stale or partially rendered step, causing the wrong step label or progress value to be announced. This is particularly problematic for blind users who cannot visually verify the announcement against the screen.

Mitigation & Contingency

Mitigation: Coordinate ActivityWizardStepSemantics with FocusManagementService (from the core services epic) to delay focus placement until the post-build callback confirms the new step's semantic tree is complete. Write integration tests using the AccessibilityTestHarness that assert the full announcement sequence across all five wizard steps.

Contingency: If post-build focus delay is insufficient due to async BLoC emission timing, add an explicit semantic notification barrier in the wizard cubit that emits a 'step ready' event only after the new widget tree has been marked as built, decoupling the announcement trigger from the raw state transition.

medium impact medium prob scope

Automated WCAG contrast ratio checking on widget tree snapshots may produce false positives for gradient backgrounds, dark-mode overrides, or design token overrides that are resolved at runtime but appear as unresolvable colours at static analysis time. Excessive false positives would erode team trust in the CI gate, leading to suppression rules that also mask real violations.

Mitigation & Contingency

Mitigation: Scope the WCAGComplianceChecker to check only solid-colour backgrounds in the first iteration, explicitly excluding gradients from contrast checks with documented rationale. Design the check output to distinguish 'undetermined' (gradient/unknown) from 'fail' (solid colour below threshold) so the team can take targeted action on genuine failures only.

Contingency: If false positive rates exceed 20% of reported violations during initial CI runs, switch the CI gate from a hard build failure to a warning annotation on the pull request, combined with a mandatory manual review step, until the checker's rule set has been tuned to match actual design token values.