Suppressing noise — .wcagignore and false-positive dismissals
Not every finding needs a fix. Third-party component libraries, known audit-misfires, and out-of-scope routes all generate noise. Two complementary tools let you suppress it cleanly without hiding real issues.
The two suppression layers
| File | Granularity | When to use |
|---|---|---|
.wcagignore | Pattern-based (gitignore-style) — broad. Manually authored. Checked into git. | Whole categories of noise: third-party libraries, entire routes, rule families you've decided not to enforce. |
.wcag-audit/false-positives.json | Per-finding (rule + selector + primary class) — narrow. Written by wcag-audit dismiss. Persists across scans. | One-off false positives on a specific component you've verified is genuinely accessible. |
.wcagignore syntax
Create a .wcagignore file at your project root. The format is similar to .gitignore: one pattern per line, comments with #, blank lines ignored.
Pattern types
| Pattern | Matches | Example |
|---|---|---|
| bare glob (no prefix) | CSS class names | cl-* suppresses all findings on elements whose primary class starts with cl- |
class:<glob> | CSS class names (explicit) | class:foo-bar suppresses findings on .foo-bar elements |
selector:<glob> | Full CSS selector | selector:*.cl-* suppresses any element matching the selector pattern |
route:<glob> | URL path | route:/admin/* suppresses all findings on admin routes |
rule:<glob> | Rule ID | rule:focus-obscured-* suppresses all focus-obscured rule variants |
Multi-token AND matching
Multiple tokens on a single line are treated as AND conditions. A finding must match all tokens on the line to be suppressed.
# Suppress focus-obscured only on /admin routes (AND)
rule:focus-obscured route:/admin/*Example .wcagignore file
# ── Third-party libraries ──────────────────────────────────────────────────
# Clerk auth components (we don't own these)
class:cl-*
# Chakra UI and Material UI
class:chakra-*
class:MuiButton*
class:MuiInput*
# ── Routes we're not auditing ────────────────────────────────────────────────
# Admin panel — separate accessibility review process
route:/admin/*
# Storybook embedded previews
route:/storybook/*
# ── Rules we've intentionally scoped out ────────────────────────────────────
# motion-preference: we have a global prefers-reduced-motion stylesheet
rule:motion-preference-*
# ── Specific selectors ───────────────────────────────────────────────────────
# Legacy widget loaded via iframe — out of scope
selector:div#legacy-widget *wcag-audit dismiss — per-finding false positive
Use wcag-audit dismiss when a single specific finding is a false positive but the rule itself, the class, and the route should continue to be audited normally.
wcag-audit dismiss <rc-id> --reason "<substantive explanation>"$ wcag-audit dismiss rc-abc123 \
--reason "Button uses aria-label because visible text is a logo SVG; label is descriptive and tested with NVDA and VoiceOver"
✓ rc-abc123 dismissed — fingerprint saved to .wcag-audit/false-positives.jsonHow it works
- Reason must be ≥ 20 characters. This prevents dismissals like "no" or "skip" from accumulating silently.
- Writes a fingerprint to
.wcag-audit/false-positives.json. The fingerprint is a SHA-1 hash of the rule ID + normalized CSS selector + primary class, so it remains stable even when page content changes between scans. - LLM fix-pass agents call this automatically when they investigate a finding, reproduce the element, and determine the audit is misfiring. The reason they supply is included in the JSON for traceability.
- Surfaced in the next scan in a Previously marked false positives section of
WCAG_FIXES.prompt.md— so a future agent can review dismissals and flag any that look wrong.
// .wcag-audit/false-positives.json (excerpt)
[
{
"rcId": "rc-abc123",
"fingerprint": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
"rule": "button-name",
"selector": "button.logo-btn",
"primaryClass": "logo-btn",
"reason": "Button uses aria-label because visible text is a logo SVG; label is descriptive and tested with NVDA and VoiceOver",
"dismissedAt": "2026-05-08T10:23:00Z",
"dismissedBy": "user"
}
]When to use which
| Situation | Use |
|---|---|
| Whole third-party library (Clerk, Chakra UI, MUI Material) you don't own | .wcagignore with a class: or selector: pattern |
| Entire route that's out of scope (admin panel, legacy pages) | .wcagignore with a route: pattern |
| One specific rule firing on one specific component you've verified is accessible | wcag-audit dismiss <rc-id> --reason "..." |
| A rule consistently misfiring on your own code | Dismiss with reason, then file a bug so it can be fixed upstream |
| Entire rule family you've deliberately chosen not to enforce | .wcagignore with a rule: pattern |
What suppressed findings look like in the report
Suppressed findings do not silently disappear. Both .wcagignore matches and dismissed false positives appear in a dedicated footer section of the report and the prompt file. This means:
- Reviewers can audit the suppression list during PR review to ensure nothing was suppressed inappropriately.
- The count shown in CI output reflects actionable findings only, but the suppressed count is also reported so it's visible.
- False positives dismissed with LLM agents include the agent-supplied reason, making it easy to verify the judgment was sound.
✓ 47 routes audited
Actionable findings: 3
Suppressed (.wcagignore): 14 (8 class:cl-*, 6 route:/admin/*)
Dismissed (false-positives.json): 2
→ See WCAG_FIXES.prompt.md for details