high priority low complexity backend pending backend specialist Tier 5

Acceptance Criteria

NavigationAccessibilityService has a dispatchWarnings(List<AccessibilityViolation> violations) method (or equivalent)
In debug builds (kDebugMode == true), each violation produces a structured debugPrint line containing: route path, violation type name, and remediation hint
Output format is consistent and parseable: e.g., '[AccessibilityViolation] <routePath> | <violationType> | <remediationHint>'
In release builds (kDebugMode == false), the method body is entirely a no-op — zero console output, zero string concatenation, zero allocations
An empty violations list produces zero console output in both debug and release builds
The method is callable after any combination of verifyModalCloseActions(), verifyBackControls(), and verifyNoHorizontalSwipe()
A convenience method runAllChecksAndWarn() (or equivalent) exists that calls all three verifiers, collects violations, and dispatches them in a single call
Unit test confirms zero output in simulated release mode (kDebugMode=false path)
Unit test confirms structured output in debug mode for a list of mock violations
No third-party logging library introduced — only flutter/foundation debugPrint is used

Technical Requirements

frameworks
Flutter
apis
flutter/foundation (kDebugMode, debugPrint)
NavigationAccessibilityService internal API
data models
AccessibilityViolation (shared)
ViolationType (all variants)
performance requirements
In release builds, the method must compile to a no-op with zero runtime cost
Debug output for up to 50 violations must complete in under 10ms
security requirements
kDebugMode guard must be the outermost check — no string interpolation occurs before the guard
No PII from route widget parameters must appear in console output
Confirm via code review that tree-shaking eliminates the debug path in --release builds

Execution Context

Execution Tier
Tier 5

Tier 5 - 253 tasks

Can start after Tier 4 completes

Implementation Notes

The kDebugMode constant from flutter/foundation is a compile-time constant in release builds, so the Dart compiler and tree-shaker will eliminate the entire block — but only if the guard is structured as `if (kDebugMode) { ... }` and not stored in a variable first. Do not use `assert(() { ... }())` as this can behave differently from kDebugMode in profile mode.

For the runAllChecksAndWarn() convenience method, collect all three violation lists into a combined list and call dispatchWarnings once to allow a single summary header line before the individual violations. Consider prefixing each line with a severity indicator (🔴 for critical accessibility violations, 🟡 for high) — but only if the team's debug console convention already uses emoji; otherwise use plain ASCII prefixes like [CRITICAL] and [HIGH] to maintain consistency with the rest of the codebase.

Testing Requirements

Unit tests using flutter_test. Scenarios: (1) dispatchWarnings([]) in debug mode → zero debugPrint calls, (2) dispatchWarnings([violation]) in debug mode → one debugPrint call containing route path, violation type, and remediation hint, (3) dispatchWarnings([v1, v2, v3]) → three separate debugPrint calls, each containing correct violation data, (4) simulate release mode (override kDebugMode or extract the guard into a testable helper) → zero output for non-empty list, (5) runAllChecksAndWarn() with no violations → zero output, (6) runAllChecksAndWarn() with known mock violations from all three verifiers → correct combined output. Use a captured output buffer or a spy on debugPrint to assert output content without relying on stdout parsing.

Component
Navigation Accessibility Service
service medium
Epic Risks (2)
high impact medium prob dependency

Flutter's SemanticsController used in integration tests is an internal or semi-internal API that can break between Flutter stable releases. If the audit runner relies heavily on undocumented semantics tree traversal, a Flutter upgrade could silently disable the audit checks without a build failure, creating false confidence.

Mitigation & Contingency

Mitigation: Use only the public flutter_test accessibility APIs (meetsGuideline, SemanticsController.ensureSemantics) and wrap all SemanticsController calls in a versioned helper class with explicit assertions that the expected semantics tree shape is still available. Pin the Flutter SDK range in pubspec.yaml.

Contingency: If SemanticsController APIs break on a Flutter upgrade, fall back to widget-level golden tests that include the semantics tree snapshot, combined with manual Switch Access and VoiceOver QA checklists executed before each release.

low impact medium prob resource

Flutter integration tests that simulate Switch Access traversal on multiple screens can be slow (30–120 seconds per test flow), which may make the audit runner impractical to run on every CI commit if the test suite already has long run times.

Mitigation & Contingency

Mitigation: Scope the audit runner to a dedicated integration test target that runs on pull requests targeting main and on nightly builds, not on every push. Parallelise test shards in CI to keep wall-clock time acceptable. Profile audit run times during development and trim any flows that duplicate coverage.

Contingency: If CI run times exceed acceptable thresholds, split the audit runner into a fast smoke suite (touch targets and semantic labels only, runs on every PR) and a thorough traversal suite (Switch Access simulation, runs nightly), with the nightly failure blocking the release branch rather than every PR.