What this is

A builder-to-builder field note on one specific wall: automated keyboard-accessibility checks throw too many false positives on modern JavaScript / utility-CSS sites. Nothing here is new — axe's incomplete bucket, the ACT rule grammar, accessibility-tree snapshots, local vision-language models. It organizes what's already known rather than claiming anything new; the contribution is the sort order, two levers you can actually ship, and an honest map of where the evidence runs out. (Engineering experience, not a compliance or legal opinion — WCAG conformance carries legal weight in some contexts; check the primary sources and your own requirements.)

How to read the tags. The evidence here is thin — vendor docs, three preprints, one practitioner benchmark — so every load-bearing claim is tagged by what backs it, and each citation is a click-to-highlight jump into the source:

incomplete is a third bucket

The single most useful move rests on the most solid quote. axe-core reports two channels that pipelines routinely collapse into one: confirmed violations, and incomplete (Deque also calls these “needs review”). An incomplete just means “axe-core wasn't able to tell whether something was a violation or not with 100% certainty”1 sourced. That is undecided, not a verdict — it can hide a real violation as easily as a non-issue — and axe reserves its no-false-positives guarantee for the other bucket: “Because of axe-core's focus on zero false positives, we only include violations we're sure are actual violations”2 sourced. So an incomplete is not “a false positive”; it's a question the engine is handing you.

Most harnesses assert on violations and silently drop incomplete. On a static page that's tolerable. On a JS / utility-CSS site, the checks axe can't resolve with certainty — contrast computed over a gradient or a background image, say — pile up in incomplete, and dropping them silently is how a real issue slips through and how a non-issue gets miscounted as noise author's read. Treat it as a third bucket and route it:

const { violations, incomplete } = await axe.run(target);
report.fail(violations);     // confirmed  -> block the build
triage.enqueue(incomplete);  // undecided  -> human / AI-assisted review,
                             //               never auto-fail, never auto-pass

That one split turns a wall of red into two queues with different owners — and it's the spine the rest of this note hangs on. (Whether your false positives actually concentrate in incomplete rather than violations is an open question — see the gaps below.)

Three false positives wearing the same hat

“Too many false positives on JS/Tailwind sites” is usually three different failures that look identical in a report and need opposite responses. Sort by cause first:

The three look the same in a results list; only the first is the tool being unsure, and none of them is simply “the tool is wrong.”
Looks like a false positive, but it's…How to tellWhat to doBacked by
the tool declining to decideIt's in incomplete, not violations (e.g. contrast over a gradient) — axe couldn't reach certainty.Route to the triage queue above; confirm or dismiss by hand or with assistance, never auto-fail.sourced
a scan that ran too earlyRe-run after the view settles (hydration / async render done) and the finding clears.Gate the scan on a settled DOM; use the before/after-settle difference as a screen (below).open gap · author's read
the framework markup itselfPractitioners report it recurs across builds and clusters at the component level (dynamic ARIA, non-semantic nodes).Scope the check to the component; fix the contract — or accept it as a true finding.practitioner-reported

One concrete screen for the second row: run it twice and diff the violations. A finding present before the view settles and gone after is a strong candidate for a timing artifact rather than a real defect author's read. Treat it as a screen, not a proof: a clean re-run changes both the elapsed time and the run, so a finding that clears shows non-persistence, not timing-causation — and a settled re-run can also mask a genuinely transient violation. Neither the second nor third row is the tool being “wrong”; they're real signals about your build. (And an empty violations list was never a clean bill of health — “many accessibility problems can only be discovered through manual testing”3 sourced.)

Work backwards from examples: pin the expectation to a contract

The runnable version of “work backwards from examples” already ships. Playwright's accessibility-tree snapshots let you “assert the accessibility tree of a page against a predefined snapshot template”4 sourced — a declarative expectation you capture once from a known-good example and assert against thereafter. The catch is printed on the label: the docs call them “Not ideal for highly dynamic content where outputs change frequently or unpredictably.”5 sourced. So the boundary is sharp: declarative expectations hold on stable component contracts and degrade on exactly the dynamic, frequently-changing views where your false positives live author's read. Pin them to the components that are stable; keep the volatile views on the triage path above. The cost is honest — authoring and maintaining those contracts is real work, and it should narrow the noise by shrinking what you assert, not by making detection cleverer author's read — no source benchmarks the reduction.

If you'd rather author those expectations in a shared grammar than a bespoke format, the W3C ACT Rules Format (version 1.1, a Recommendation since February 2026) is built for it: “The test rules can be used for developing automated testing tools and manual testing methodologies”6 sourced. Its core is an applicability (what a rule covers), an expectation (“description of the expected characteristics of the applicable rule content”7), and test cases (“sample code demonstrating passed, failed, and inapplicable rule conditions”8) sourced — your worked examples, formalized. It's a rule-authoring grammar, not a runnable noise-killer; adopting it doesn't make a scanner smarter.

Local AI: an annotator, not a judge

For the local-model step, one practitioner benchmark is directly on point. Testing local vision-language models for alt-text, “Among local options, the Llama variants and MiniCPM-V perform best”9, and “Both earned a B grade: they work reliably but sometimes miss important details”10 practitioner-reported. A usable starting point for this week's work — scoped to generating a candidate description, not deciding conformance.

Why that scoping matters is a documented failure mode — and the provenance has to be exact, because it's the easiest thing here to over-read. In a 2025 preprint benchmarking cloud models as judges for PDF accessibility, Claude-3.5 in particular “Claude-3.5 occasionally hallucinated alt text descriptions for images without alt text and then marked the document as Failed based on those hallucinated descriptions”11; and for undecidable cases, “all models except GPT-4-Turbo incorrectly classified documents as 'Failed', also due to predictions based on hallucinated descriptions”12 sourced — GPT-4-Turbo was the exception there, and the study's most accurate model. Be precise about what this is: cloud frontier models, on PDFs, acting as the judge. Whether the same silent failure shows up for a local model on a live DOM is author's read, not the study's finding — but the mechanism, a model inventing the evidence and then ruling on its own invention, is the one to engineer against.

So the line that keeps it useful is narrow: let the model annotate a finding the tool already localized, require that its cited evidence actually exists in the DOM before you trust the verdict, and don't make it the detector of record. A model can read structure well — ScreenAI is “a vision-language model that specializes in UI and infographics understanding”13 sourced — but reading structure is extraction, not adjudication.

Why a local model can't be your detector of record — yet

There's a cited, structural reason this is more than caution. A 2026 systematic review of LLMs for web accessibility finds that “most studies apply LLMs to text-centric and structurally explicit accessibility tasks, with WCAG serving as the primary reference framework and limited consideration of cognitive accessibility guidelines (COGA)”14 sourced. Scope it precisely: that is a gap in cognitive-accessibility coverage and in the labelled-data / annotation quality behind it — not a blanket ceiling on visual or DOM-level checking. But it's the concrete reason a small local model, trained on what little labelled accessibility data exists, makes a capable assistant and a poor authority for now.

The floor you already work to

Two baselines you know cold, stated only because they bound the exercise in both directions. Automated absence is not presence: “Absence of detected errors does not indicate that a page is accessible or conformant.”15 sourced. And the ceiling is structural — per W3C's evaluation methodology, “most accessibility checks are not fully automatable, evaluation tools can significantly assist evaluators”16, and as the PDF-benchmark paper puts it, “manual testing has become essential for identifying issues that automated tools cannot detect”17 sourced. Fewer findings isn't better; it's just quieter. (Which is the whole reason you built a keyboard harness: operability — “All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes”18 sourced — is a behavioral property a static scan can't confirm.)

Does any of this pay for itself — and the failure mode that bites back

Two questions a skeptical reader asks first. Does it pay? Honestly, unknown: the false-positive reduction from every lever here is unmeasured, manual testing stays essential, and maintaining declarative contracts is ongoing work. The case for these moves is that triage-routing and component contracts are cheap to try and easy to back out — not that they're proven to net positive author's read. What's the failure mode? Every move here quiets the tool, and a quieter tool raises the false-negative risk — the worse error on an accessibility surface. If the incomplete queue outgrows whoever reviews it, “route it to triage” becomes “route it to a graveyard,” and real violations sit there unread. Two guards worth budgeting for: staff triage as a real line item, and fingerprint incompletes so the same unresolved item collapses to one entry across CI runs instead of re-flooding the queue author's read. Stable fingerprints across runs are also what let you tell a genuinely new incomplete from yesterday's known one.

What nobody has measured (the most useful part)

On thin evidence, the honest gaps are worth more than confident prose. In priority order:

Evidence quality & limits

Evidence register

Every quotation was re-checked, verbatim, against its captured source at build time. Each source is labelled by type; “preprint” means not yet peer-reviewed. Citation links jump to and highlight the quoted passage in the source.

  1. 1. “axe-core wasn't able to tell whether something was a violation or not with 100% certainty” Deque / axe-core docs — Needs Review vs Incomplete Tool documentation
  2. 2. “Because of axe-core's focus on zero false positives, we only include violations we're sure are actual violations” Deque / axe-core docs — zero false positives Tool documentation
  3. 3. “many accessibility problems can only be discovered through manual testing” Playwright — Accessibility testing (docs) Tool documentation
  4. 4. “assert the accessibility tree of a page against a predefined snapshot template” Playwright — ARIA snapshots Tool documentation
  5. 5. “Not ideal for highly dynamic content where outputs change frequently or unpredictably.” Playwright — ARIA snapshots (dynamic-content caveat) Tool documentation
  6. 6. “The test rules can be used for developing automated testing tools and manual testing methodologies” W3C ACT Rules Format 1.1 (Recommendation) W3C standards / methodology
  7. 7. “description of the expected characteristics of the applicable rule content” W3C — Understanding ACT Rules (Expectations) W3C standards / methodology
  8. 8. “sample code demonstrating passed, failed, and inapplicable rule conditions” W3C — Understanding ACT Rules (Test Cases) W3C standards / methodology
  9. 9. “Among local options, the Llama variants and MiniCPM-V perform best” Comparing local LLMs for alt-text generation (Dries Buytaert) Practitioner benchmark
  10. 10. “Both earned a B grade: they work reliably but sometimes miss important details” Comparing local LLMs for alt-text generation — grading Practitioner benchmark
  11. 11. “Claude-3.5 occasionally hallucinated alt text descriptions for images without alt text and then marked the document as Failed based on those hallucinated descriptions” Benchmarking PDF Accessibility Evaluation (2025 preprint) — silent failure Preprint (not peer-reviewed)
  12. 12. “all models except GPT-4-Turbo incorrectly classified documents as 'Failed', also due to predictions based on hallucinated descriptions” Benchmarking PDF Accessibility Evaluation (2025) — Cannot-Tell mislabel Preprint (not peer-reviewed)
  13. 13. “a vision-language model that specializes in UI and infographics understanding” ScreenAI: A Vision-Language Model for UI and Infographics Understanding Preprint (not peer-reviewed)
  14. 14. “most studies apply LLMs to text-centric and structurally explicit accessibility tasks, with WCAG serving as the primary reference framework and limited consideration of cognitive accessibility guidelines (COGA)” LLMs for Web Accessibility: a Systematic Literature Review (2026) Preprint (not peer-reviewed)
  15. 15. “Absence of detected errors does not indicate that a page is accessible or conformant.” WebAIM Million 2026 Empirical report
  16. 16. “most accessibility checks are not fully automatable, evaluation tools can significantly assist evaluators” W3C WCAG-EM 1.0 (Evaluation Methodology, Working-Group Note) W3C standards / methodology
  17. 17. “manual testing has become essential for identifying issues that automated tools cannot detect” Benchmarking PDF Accessibility Evaluation (2025 preprint) Preprint (not peer-reviewed)
  18. 18. “All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes” WCAG 2.1 — SC 2.1.1 Keyboard (Level A) Normative (WCAG)