Add custom lint rules for design token enforcement
epic-visual-design-accessibility-foundation-task-007 — Extend the Flutter Accessibility Lint Configuration with custom lint rules (or analyzer plugins) that reject hardcoded hex color values and require all color references to route through the DesignTokenProvider. This prevents bypass of the manifest-declared contrast guarantees at development time.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 5 - 253 tasks
Can start after Tier 4 completes
Implementation Notes
The lightest-weight approach is the `custom_lint` package (pub.dev), which lets you write lint rules as plain Dart without the full analyzer plugin boilerplate. Create a new Dart package (e.g., `packages/likeperson_lints`) with `custom_lint_builder` as a dependency. Implement a `DartLintRule` subclass that visits `InstanceCreationExpression` and `PrefixedIdentifier` AST nodes, checking for `Color` constructor calls and `Colors.*` references. Use `context.addError()` with a `Fix` suggestion pointing to `DesignTokenProvider`.
Add the package to the app's `dev_dependencies` and register it in `analysis_options.yaml` under `custom_lint > rules`. Exclude `lib/core/design_tokens/design_token_provider.dart` via the `exclude` list. This approach is preferred over a full analyzer plugin because it does not require `dart pub publish` and works with `dart analyze` in CI out of the box.
Testing Requirements
Write unit tests for the custom lint rule using the `custom_lint` test utilities (`testLint`). Test cases must cover: (1) Color literal in a widget file triggers error, (2) Color literal inside DesignTokenProvider file is suppressed, (3) DesignTokenProvider.of(context).primary usage passes with no diagnostic, (4) Colors.transparent used as a special case — decide policy and enforce it. Target 100% branch coverage on the rule visitor logic.
The WCAG 2.2 relative luminance formula requires gamma-corrected sRGB calculations. Floating-point rounding differences between Dart and reference implementations could produce off-by-one classifications for near-threshold color pairs, resulting in pairs that just pass or just fail in CI but behave differently at runtime.
Mitigation & Contingency
Mitigation: Implement the algorithm directly from the WCAG 2.2 specification using the exact linearisation constants. Validate the Dart implementation against the W3C reference test vectors and against a known-good JavaScript implementation for at least 50 color pairs spanning the compliance boundaries.
Contingency: If discrepancies are found, add a configurable tolerance margin (e.g., ±0.005 on the ratio) and flag near-threshold pairs as warnings rather than hard failures, escalating to the design team for manual review.
The token manifest is a static data file. If developers add new color tokens to the design-token-provider without updating the manifest, the manifest becomes stale and the CI validator produces false negatives — passing builds that contain unvalidated color pairs.
Mitigation & Contingency
Mitigation: Add a CI step that cross-references every token constant exported by the design-token-provider against the manifest at build time, failing if any token is present in the provider but absent from the manifest. Document this requirement clearly in the contributing guide.
Contingency: If drift is detected post-merge, run a full manifest regeneration script and treat the resulting manifest diff as a blocking pull request with mandatory accessibility review.
The flutter_accessibility_lints package (or custom lint rules) may produce false positives on patterns the team deliberately uses — for example, decorative icon widgets that intentionally omit semantic labels. Excessive false positives will lead developers to add blanket ignore comments, undermining the entire lint strategy.
Mitigation & Contingency
Mitigation: Audit the full lint rule set against the existing codebase before enabling rules. Create a documented list of approved ignore-comment patterns with mandatory justification comments. Restrict ignore patterns to decorative-only contexts.
Contingency: If false positive rates exceed 10% of lint output, disable the highest-noise individual rules and replace them with targeted custom lint rules scoped to the specific patterns the team controls.