ultra11y 2.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +223 -0
- package/docker/Dockerfile +7 -0
- package/docker/package.json +9 -0
- package/docker/runner.mjs +23 -0
- package/package.json +73 -0
- package/scripts/bench.mjs +151 -0
- package/scripts/build-act-corpus.mjs +143 -0
- package/scripts/build-adjudication.mjs +503 -0
- package/scripts/build-pack-rgaa.mjs +397 -0
- package/scripts/build-standards.mjs +548 -0
- package/scripts/copy-bundle.mjs +39 -0
- package/scripts/import-pack.mjs +107 -0
- package/scripts/sync-engine.mjs +84 -0
- package/scripts/sync-version.mjs +43 -0
- package/scripts/ultra11y.mjs +52739 -0
- package/scripts/vendor/act-testcases.json +12297 -0
- package/scripts/vendor/rgaa/SOURCE.json +8 -0
- package/scripts/vendor/rgaa/criteres.json +4144 -0
- package/scripts/vendor/rgaa/glossaire.json +480 -0
- package/scripts/vendor/wcag-2.2-fr.json +82 -0
- package/scripts/vendor/wcag-2.2-sc-universe.json +950 -0
- package/scripts/vendor/wcag-2.2-sc.json +574 -0
- package/scripts/verify-rgaa-source.mjs +126 -0
- package/scripts/verify-skill-bundle.mjs +91 -0
- package/skills/review-a11y/SKILL.md +123 -0
- package/skills/review-a11y/scripts/ultra11y.mjs +52739 -0
- package/skills/ultra11y/SKILL.md +292 -0
- package/skills/ultra11y/references/act.md +163 -0
- package/skills/ultra11y/references/adjudication.md +599 -0
- package/skills/ultra11y/references/audit.md +100 -0
- package/skills/ultra11y/references/authoring.md +37 -0
- package/skills/ultra11y/references/automation.md +113 -0
- package/skills/ultra11y/references/correction.md +41 -0
- package/skills/ultra11y/references/criteria.md +129 -0
- package/skills/ultra11y/references/cross-file.md +82 -0
- package/skills/ultra11y/references/dynamic.md +152 -0
- package/skills/ultra11y/references/false-positives.md +81 -0
- package/skills/ultra11y/references/fix.md +46 -0
- package/skills/ultra11y/references/focus-and-logic.md +64 -0
- package/skills/ultra11y/references/forbidden-patterns.md +61 -0
- package/skills/ultra11y/references/forms-and-errors.md +147 -0
- package/skills/ultra11y/references/guidance.md +55 -0
- package/skills/ultra11y/references/judgment.md +90 -0
- package/skills/ultra11y/references/media-and-motion.md +116 -0
- package/skills/ultra11y/references/methodology.md +72 -0
- package/skills/ultra11y/references/naming.md +117 -0
- package/skills/ultra11y/references/orchestration.md +44 -0
- package/skills/ultra11y/references/packs.md +193 -0
- package/skills/ultra11y/references/prd.md +104 -0
- package/skills/ultra11y/references/rendered.md +110 -0
- package/skills/ultra11y/references/scale.md +49 -0
- package/skills/ultra11y/references/standards.md +97 -0
- package/skills/ultra11y/references/structure.md +138 -0
- package/skills/ultra11y/references/verify.md +88 -0
- package/skills/ultra11y/references/widgets.md +106 -0
- package/skills/ultra11y/scripts/ultra11y.mjs +52739 -0
- package/src/act.ts +441 -0
- package/src/adjudicate.ts +630 -0
- package/src/aria.ts +230 -0
- package/src/audit.ts +396 -0
- package/src/auditor.ts +399 -0
- package/src/autofill.ts +102 -0
- package/src/axe-map.ts +294 -0
- package/src/baseline.ts +75 -0
- package/src/capture.ts +182 -0
- package/src/check.ts +243 -0
- package/src/cli.ts +1927 -0
- package/src/color.ts +102 -0
- package/src/config.ts +182 -0
- package/src/crawl.ts +75 -0
- package/src/criteria.ts +183 -0
- package/src/data/adjudication.json +770 -0
- package/src/data/guidance/rgaa.json +2395 -0
- package/src/data/standards/rgaa.glossary.json +478 -0
- package/src/data/standards/rgaa.json +3454 -0
- package/src/data/wcag-universe.json +530 -0
- package/src/data/wcag.json +1178 -0
- package/src/discover.ts +203 -0
- package/src/fix/codemods.ts +76 -0
- package/src/fix/diff.ts +64 -0
- package/src/fix/edits.ts +126 -0
- package/src/fix.ts +215 -0
- package/src/gh.ts +214 -0
- package/src/glob.ts +206 -0
- package/src/graph/build.ts +114 -0
- package/src/graph/engine-resolve.ts +0 -0
- package/src/graph/graph.ts +126 -0
- package/src/graph/imports.ts +359 -0
- package/src/graph/resolve.ts +73 -0
- package/src/graph/tsconfig.ts +113 -0
- package/src/grounding.ts +119 -0
- package/src/guidance/index.ts +45 -0
- package/src/guidance/types.ts +36 -0
- package/src/init.ts +113 -0
- package/src/mcp/handlers.ts +388 -0
- package/src/mcp/http.ts +260 -0
- package/src/mcp/prompts.ts +183 -0
- package/src/mcp/protocol.ts +187 -0
- package/src/mcp/resources.ts +136 -0
- package/src/mcp/server.ts +228 -0
- package/src/mcp/stdio.ts +119 -0
- package/src/mcp/tools.ts +347 -0
- package/src/messages.ts +1011 -0
- package/src/name.ts +174 -0
- package/src/orchestrate-templates.ts +231 -0
- package/src/orchestrate.ts +186 -0
- package/src/output.ts +108 -0
- package/src/pack.ts +187 -0
- package/src/parse/html.ts +258 -0
- package/src/parse/jsx-ast.ts +67 -0
- package/src/parse/jsx-bridge.ts +247 -0
- package/src/parse/jsx.ts +19 -0
- package/src/parse/source.ts +75 -0
- package/src/prd.ts +406 -0
- package/src/project-lock.ts +42 -0
- package/src/render.ts +307 -0
- package/src/report.ts +399 -0
- package/src/rules/colors.ts +125 -0
- package/src/rules/cross-registry.ts +264 -0
- package/src/rules/cross-rule.ts +83 -0
- package/src/rules/forms.ts +590 -0
- package/src/rules/frames.ts +33 -0
- package/src/rules/headings.ts +227 -0
- package/src/rules/images.ts +200 -0
- package/src/rules/links.ts +193 -0
- package/src/rules/mandatory.ts +173 -0
- package/src/rules/multimedia.ts +77 -0
- package/src/rules/navigation.ts +190 -0
- package/src/rules/presentation.ts +75 -0
- package/src/rules/registry.ts +57 -0
- package/src/rules/rule.ts +122 -0
- package/src/rules/scripts-aria.ts +636 -0
- package/src/rules/tables.ts +264 -0
- package/src/rules/timing.ts +55 -0
- package/src/sample.ts +176 -0
- package/src/scan-local.ts +866 -0
- package/src/scan.ts +538 -0
- package/src/standards/derive.ts +195 -0
- package/src/standards/index.ts +31 -0
- package/src/standards/pack-rules.ts +111 -0
- package/src/standards/pack.ts +81 -0
- package/src/standards/registry.ts +100 -0
- package/src/standards/types.ts +202 -0
- package/src/standards/validate.ts +544 -0
- package/src/standards/vocabulary.ts +75 -0
- package/src/types.ts +355 -0
- package/src/util.ts +32 -0
- package/src/vendor/codeindex-engine.d.mts +1009 -0
- package/src/vendor/codeindex-engine.mjs +13701 -0
- package/src/vendor/engine.meta.json +9 -0
- package/src/verify.ts +275 -0
- package/src/wcag.ts +128 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ultra11y
|
|
3
|
+
description: "Use to AUDIT existing HTML/CSS/JSX against WCAG 2.2 AA accessibility and produce a dated auditor-conformance report, OR to AUTHOR/REVIEW accessible markup (native-HTML-first, ARIA last). An install-free engine (`node scripts/ultra11y.mjs`, no keys) runs 72 static checks tied to WCAG criteria โ alt/lang/title, unlabeled fields, empty links/buttons, tables, headings, ARIA vocabulary, label-in-name, autocomplete โ measured against the official W3C ACT corpus. The engine decides 3 of the 55 criteria; the AI agent adjudicates the 38 judgment ones from harvested evidence + a per-criterion decision protocol (`verify --manual`, gated, fannable via `orchestrate`), and the 14 rendering ones go to `scan` โ never silently conforming. Library/SFC code is audited as RENDERED captures (`render --setup`); country standards are pluggable packs (`--standard rgaa`, `scan --sample`). check/verify reject invented non-conformities. Triggers: 'audit WCAG/a11y', 'make accessible', 'fix a11y', 'audit RGAA'."
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
version: 2.22.0
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# ultra11y โ audit WCAG 2.2 AA and write accessible markup
|
|
10
|
+
|
|
11
|
+
On accessibility, an automated tool only sees part of the problem. `ultra11y` owns
|
|
12
|
+
that with a **division of labour**: the deterministic, install-free engine
|
|
13
|
+
(`node scripts/ultra11y.mjs <command>` โ no `npm install`, no key; the JSX/TSX parser
|
|
14
|
+
is embedded in the bundle) does the *mechanical* work โ detect the machine-checkable
|
|
15
|
+
non-conformities and tie each to the right **WCAG success criterion** โ and **the AI agent**
|
|
16
|
+
(Claude running this skill) *adjudicates the judgment criteria itself* โ alt relevance, link
|
|
17
|
+
purpose in context, reading order โ statically, from the evidence the engine harvests
|
|
18
|
+
(`verify --manual`), each verdict gated by `verify`/`check`. Only the truly **rendered-DOM**
|
|
19
|
+
criteria (computed contrast, visible focus, zoom/reflow, content-on-hover) fall to the `scan`
|
|
20
|
+
tier (axe-core in a real browser); a human is at most optional oversight. Gates stop any
|
|
21
|
+
hallucinated non-conformity from surviving, and nothing is ever silently "conforming".
|
|
22
|
+
|
|
23
|
+
**WCAG 2.2 Level AA is the worldwide core.** Country standards โ France's **RGAA**, the
|
|
24
|
+
US **Section 508**, the EU **EN 301 549** โ are pluggable *standards packs* that map their
|
|
25
|
+
criteria onto WCAG. Add `--standard rgaa` to re-key reports/criteria; **plug an external
|
|
26
|
+
pack at runtime** with `--pack ./pack.json` (or a `.ultra11yrc.json`), no rebuild; or
|
|
27
|
+
contribute your country (see `references/standards.md`). Packs (and their concrete
|
|
28
|
+
**implementation guidance** โ the RGAA SocialGouv/etalab good/bad patterns) can be
|
|
29
|
+
**AI-ingested** and gated by `pack check` so a fabricated mapping never passes โ see
|
|
30
|
+
`references/packs.md` and `references/guidance.md`.
|
|
31
|
+
|
|
32
|
+
**Most of the work is yours.** Of the 55 WCAG 2.2 AA success criteria, the engine can decide
|
|
33
|
+
**3** outright; **14** need a rendered page (`scan`) and **38** are judgment calls the agent
|
|
34
|
+
adjudicates. So the engine's clean run is a starting point, never a verdict โ and
|
|
35
|
+
`references/adjudication.md` is the page you actually work from.
|
|
36
|
+
|
|
37
|
+
> **Core rules:**
|
|
38
|
+
> 1. **Never invent a non-conformity**: every `NC` cites a real, resolvable element (`check` verifies it).
|
|
39
|
+
> 2. **Native HTML first, ARIA last**; never duplicate implicit semantics.
|
|
40
|
+
> 3. **Residual is explicit, never silently conforming**: the AI agent *adjudicates* every
|
|
41
|
+
> *judgment* criterion itself (`verify --manual`, gated), and the *rendering* criteria go to
|
|
42
|
+
> `scan`; any criterion still unproven stays "to assess manually" โ no status without a
|
|
43
|
+
> recorded, justified verdict.
|
|
44
|
+
> 4. **The FINAL rendered semantic HTML must be correct.** The engine sees only source; a
|
|
45
|
+
> component library (DSFR/MUIโฆ) or `.vue`/`.svelte`/`.astro` SFC hides the real markup, so
|
|
46
|
+
> a green source audit is not proof. Verify the produced semantic HTML โ install the
|
|
47
|
+
> zero-touch **capture** harvester (`render --setup`) so every component your tests render
|
|
48
|
+
> is serialized to `.ultra11y/captures` and audited, with `audit --require-captures` gating
|
|
49
|
+
> the blind spots. See `references/automation.md` / `rendered.md`.
|
|
50
|
+
> 5. **Language**: ALWAYS pass `--lang` matching the language of your conversation with
|
|
51
|
+
> the user; ask the user when ambiguous. Without the flag the CLI auto-detects (repo
|
|
52
|
+
> `<html lang>` โ the active standard's default locale โ English) โ a scripted/CI
|
|
53
|
+
> fallback, not a substitute for passing `--lang` yourself.
|
|
54
|
+
> 6. **Technical tokens stay in English, even in French prose.** In any French deliverable
|
|
55
|
+
> you write (report commentary, PRD, GitHub issues, judgment verdicts), attribute/
|
|
56
|
+
> element/role names and their values are code, not prose โ never translate them:
|
|
57
|
+
> `aria-live` stays `aria-live` (never ยซ rรฉgion live ยป), same for `tabindex`, `alt`,
|
|
58
|
+
> `role="alert"`, landmark role names. The engine's own fr catalog follows this; match
|
|
59
|
+
> it. Normative standard vocabulary (RGAA wording such as ยซ lien d'รฉvitement ยป) keeps
|
|
60
|
+
> its official French.
|
|
61
|
+
|
|
62
|
+
## The reference library
|
|
63
|
+
|
|
64
|
+
Domain knowledge first, then the tooling. Read the one that matches the question in front of you.
|
|
65
|
+
|
|
66
|
+
| Accessibility knowledge | |
|
|
67
|
+
|---|---|
|
|
68
|
+
| `references/adjudication.md` | How to decide each of the 52 criteria the engine hands you โ the decision rule, when NA is legitimate, the questions |
|
|
69
|
+
| `references/naming.md` | Accessible-name computation, 2.5.3 label-in-name, visually-hidden CSS, naming images/SVG/figures |
|
|
70
|
+
| `references/widgets.md` | ARIA APG composite patterns, keyboard contracts, focus management, SPA route changes, live regions |
|
|
71
|
+
| `references/forms-and-errors.md` | Labels and instructions, the `autocomplete` token list, error identification/suggestion/prevention, redundant entry, accessible authentication |
|
|
72
|
+
| `references/structure.md` | Headings, landmarks, lists and `dl`, simple and complex tables, meaningful sequence |
|
|
73
|
+
| `references/media-and-motion.md` | Captions/audio description/transcripts, pointer gestures, target size, orientation, reflow, reduced motion |
|
|
74
|
+
| `references/forbidden-patterns.md` | 15 anti-patterns: bad โ why โ native fix โ criterion |
|
|
75
|
+
| `references/focus-and-logic.md` | The focus/keyboard criteria you own, and how to reason about them |
|
|
76
|
+
| `references/criteria.md` | The 55 criteria: level, automatability class, engine rules, pack mapping (generated) |
|
|
77
|
+
| `references/act.md` | What the engine is measured to catch โ and what it demonstrably does not (generated) |
|
|
78
|
+
|
|
79
|
+
| Running the tool | |
|
|
80
|
+
|---|---|
|
|
81
|
+
| `references/audit.md` | The audit loop end to end, and the normative page sample |
|
|
82
|
+
| `references/judgment.md` | The adjudication + refutation worklists, verdict vocabulary, fail-closed fold |
|
|
83
|
+
| `references/verify.md` | The `check`/`verify` gates |
|
|
84
|
+
| `references/false-positives.md` | Where a finding may still be wrong, and how to refute it |
|
|
85
|
+
| `references/rendered.md` ยท `references/automation.md` | Auditing produced HTML, captures, hooks and CI |
|
|
86
|
+
| `references/dynamic.md` | The `scan` tier: runtimes, probes, authenticated pages |
|
|
87
|
+
| `references/scale.md` | Focusing an audit on a large repository |
|
|
88
|
+
| `references/fix.md` ยท `references/correction.md` | Applying fixes, by priority, without regressions |
|
|
89
|
+
| `references/prd.md` | The auditor block as a backlog, and GitHub issues |
|
|
90
|
+
| `references/standards.md` ยท `references/packs.md` ยท `references/guidance.md` | Country standards, authoring a pack, implementation guidance |
|
|
91
|
+
| `references/methodology.md` | Statuses, pass rate, severities, report format |
|
|
92
|
+
| `references/cross-file.md` | `--graph`: imports and cross-file rules |
|
|
93
|
+
| `references/orchestration.md` | Fanning the judgment phases out across subagents |
|
|
94
|
+
|
|
95
|
+
## Choose by situation
|
|
96
|
+
|
|
97
|
+
- **"Audit / compliance report"** โ `node scripts/ultra11y.mjs audit โฆ --json`, then
|
|
98
|
+
`report` (synthesis table + one **auditor conformance block** per NC criterion โ same
|
|
99
|
+
block `prd`/`--gh-issues` use), then `check`; read **`references/audit.md`**.
|
|
100
|
+
- **"Code rendered by a library (DSFR, MUIโฆ) or a `.vue`/`.svelte`/`.astro` SFC / avoid
|
|
101
|
+
false negatives"** โ audit the **produced HTML**, not the source template. Easiest:
|
|
102
|
+
install the zero-touch **capture** harvester (`render --setup`) so your tests serialize
|
|
103
|
+
every rendered component to `.ultra11y/captures` (auto-ingested, findings attributed to the
|
|
104
|
+
source component; `render --coverage` and `audit --require-captures` track blind spots). Or
|
|
105
|
+
`render` (buildโaudit recipe or SSR snapshot `--scaffold`) then `audit` on the output, and
|
|
106
|
+
`scan` for computed rendering. SFC-source findings are flagged `preliminary` (a
|
|
107
|
+
`scope.sourceTemplate` caveat); read **`references/rendered.md`**.
|
|
108
|
+
- **"A finding looks wrong / false positive on a component"** โ the engine auto-suppresses
|
|
109
|
+
most component false positives (slot/prop-injected names, component children, dynamic
|
|
110
|
+
bindings, conditional headings) and marks SFC/library-source findings `preliminary`;
|
|
111
|
+
confirm or refute the rest with `verify --apply`; read **`references/false-positives.md`**.
|
|
112
|
+
- **"Large repo / audit smartly"** โ focus: `--changed` (git diff), template
|
|
113
|
+
prioritization, dedup, `--max-files`; read **`references/scale.md`**.
|
|
114
|
+
- **"Cross-file analysis (tree + dependencies), JSX/TSX as a real AST"** โ
|
|
115
|
+
`audit --graph` resolves imports and applies cross-file rules (an icon-only component
|
|
116
|
+
used without a name, an anchor target in another fileโฆ), no browser; read
|
|
117
|
+
**`references/cross-file.md`**.
|
|
118
|
+
- **"Generate the fix markdown / PRDs (โ GitHub issues)"** โ `prd` (the SAME auditor
|
|
119
|
+
conformance block `report`'s NC section renders โ theme/criterion/test/WCAG+level/
|
|
120
|
+
finding/expected/verification in the active standard's vocabulary โ as a backlog);
|
|
121
|
+
`--split criterion`, `--format doc` for a product-requirements doc, `--format remediation`
|
|
122
|
+
for the legacy dev backlog, `--gh-issues` for one issue per criterion (that block as the
|
|
123
|
+
body) or `--gh-single` for a single consolidated issue via the `gh` CLI); read
|
|
124
|
+
**`references/prd.md`**.
|
|
125
|
+
- **"Plug or author a standards pack (RGAA & beyond), AI-ingest external rules"** โ
|
|
126
|
+
`--pack`/`.ultra11yrc.json` to load at runtime, `pack check` to gate it (the
|
|
127
|
+
anti-hallucination guardrail), `pack scaffold` to start one; concrete before/after
|
|
128
|
+
implementation guidance attaches to findings/PRD; read **`references/packs.md`** and
|
|
129
|
+
**`references/guidance.md`**.
|
|
130
|
+
- **"Adjudicate the judgment criteria (judgment phase)"** โ `verify --manual --in audit.json`
|
|
131
|
+
emits an ADJUDICATION worklist (`ADJUDICATE.todo.json` + `ADJUDICATE.md`), one item per
|
|
132
|
+
residual criterion, pre-loaded with the engine's harvested evidence (every alt, link text +
|
|
133
|
+
context, literal colour pairs, control labels, heading outline, ARIA state, tabindex,
|
|
134
|
+
lang-of-parts); the AI agent fills each `verdict` โ `C`/`NA` (with a `justification`), `NC`
|
|
135
|
+
(with a groundable finding), or `manual` (with a `reason`) โ then `verify --apply โฆ --in
|
|
136
|
+
audit.json` folds them back FAIL-CLOSED; read **`references/judgment.md`**.
|
|
137
|
+
- **"Many items to adjudicate/verify (fan the judgment out to subagents)"** โ
|
|
138
|
+
`orchestrate --run <dir>` emits, from the run's CURRENT worklists, one launchable
|
|
139
|
+
multi-agent workflow per ready phase + the `agents/<role>.md` dispatch contracts +
|
|
140
|
+
a sequential `RUNBOOK.md` โ the default execution path on a subagent-capable harness;
|
|
141
|
+
see **Orchestration โ route by harness** below.
|
|
142
|
+
- **"Focus, keyboard & interaction logic (the interaction-logic part)"** โ the engine marks
|
|
143
|
+
focus order/visible/trap and on-focus/on-input criteria as residual risks; the AI agent reads
|
|
144
|
+
the full component source and adjudicates the keyboard/focus behaviour (visible-focus and the
|
|
145
|
+
other rendered criteria go to `scan`); read **`references/focus-and-logic.md`**.
|
|
146
|
+
- **"Put the fixes in place"** โ `fix` (dry-run by default, `--write` applies the safe
|
|
147
|
+
codemods, proposes the rest without inventing anything); read **`references/fix.md`**.
|
|
148
|
+
- **"Fix by priority, no regressions (correction phase)"** โ `fix` (`--write`,
|
|
149
|
+
`--iterate`) + the `prd` backlog, blockingโmajorโminor; read **`references/correction.md`**.
|
|
150
|
+
- **"Automatic repo gate (hook / CI)"** โ `init --hook` writes a git pre-commit gate over
|
|
151
|
+
the **strict staged snapshot** (audits the exact index blobs, auto-applies safe fixes and
|
|
152
|
+
re-stages them, blocks only on judgment issues); `init --baseline`/`--ci` is the opt-in
|
|
153
|
+
"block only NEW non-conformities" variant. For library/SFC code, commit rendered
|
|
154
|
+
**captures** (`render --setup`) and stage them so the real semantic HTML is what's
|
|
155
|
+
checked (`audit --require-captures`); read **`references/automation.md`**.
|
|
156
|
+
- **"Make this code accessible / review it"** โ audit the snippet
|
|
157
|
+
(`audit - < component.html`) native-first; read **`references/authoring.md`** and
|
|
158
|
+
**`references/forbidden-patterns.md`**.
|
|
159
|
+
- **"What does criterion X mean"** โ `criteria` (e.g. `criteria 1.4.3`, or
|
|
160
|
+
`criteria --standard rgaa 8.3`); see **`references/criteria.md`**.
|
|
161
|
+
- **"How trustworthy is a given check / what does the engine NOT catch"** โ the engine is
|
|
162
|
+
scored against the **W3C ACT-Rules test corpus** (~1 100 third-party examples): which
|
|
163
|
+
checks are consistent, where recall is partial, which deviations are deliberate, and
|
|
164
|
+
which statically-decidable rules are still missing โ read **`references/act.md`**. Use it
|
|
165
|
+
to calibrate how much of a criterion the engine really settles before you adjudicate.
|
|
166
|
+
- **"Country standard (RGAA, Section 508, EN 301 549)"** โ `--standard <pack>` on
|
|
167
|
+
`report`/`prd`/`criteria`/`check`/`verify`; see **`references/standards.md`** and
|
|
168
|
+
**`references/methodology.md`**. **For a country-standard audit, PROPOSE the scan by
|
|
169
|
+
default**: such an audit is normatively defined over a declared page **sample**, and an
|
|
170
|
+
un-scanned `--standard rgaa` report is marked **partial** โ say so rather than implying
|
|
171
|
+
full coverage. The sample workflow (`sample check`, `scan --sample`, `--merge`) is in
|
|
172
|
+
**`references/audit.md`**.
|
|
173
|
+
- **"High-assurance audit"** โ `verify --report โฆ --semantic`; see **`references/verify.md`**.
|
|
174
|
+
- **"Check contrast / rendering (dynamic tier)"** โ `scan <url> --merge โฆ` runs axe-core in a
|
|
175
|
+
headless browser and, on the local runtime, probes focus visibility, 200% zoom, text
|
|
176
|
+
spacing and content-on-hover, with bounded stateful interactions and authenticated pages;
|
|
177
|
+
read **`references/dynamic.md`**.
|
|
178
|
+
|
|
179
|
+
## Orchestration โ route by harness
|
|
180
|
+
|
|
181
|
+
The judgment phases fan out: `ADJUDICATE.todo.json` (one item per residual criterion) and
|
|
182
|
+
`VERIFY.todo.json` (one entry per NC claim) are independent per-item worklists, and
|
|
183
|
+
`orchestrate --run <dir>` emits a launchable workflow, per-role dispatch contracts and a
|
|
184
|
+
sequential RUNBOOK from whichever worklists currently exist. Fan-out is an optimization,
|
|
185
|
+
never a requirement: the gates are harness-independent, every phase has a sequential
|
|
186
|
+
fallback with identical artifacts, and the fail-closed `verify --apply` fold always stays
|
|
187
|
+
with you. Read **`references/orchestration.md`** for the routing table and the rules.
|
|
188
|
+
|
|
189
|
+
## Command cheat sheet
|
|
190
|
+
|
|
191
|
+
The full surface is in `--help`; these are the lines you reach for.
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
node scripts/ultra11y.mjs audit "src/**/*.tsx" --graph --out audits --json # the default audit (AST + cross-file, persisted)
|
|
195
|
+
node scripts/ultra11y.mjs audit - < component.html # a snippet via stdin
|
|
196
|
+
node scripts/ultra11y.mjs audit --changed --json # only the git diff (large repo)
|
|
197
|
+
node scripts/ultra11y.mjs audit --staged --fail-on blocking # gate EXACTLY the staged snapshot (pre-commit)
|
|
198
|
+
node scripts/ultra11y.mjs audit "dist/**/*.html" # the RENDERED HTML (reliable for DSFR/MUIโฆ)
|
|
199
|
+
node scripts/ultra11y.mjs render --setup # install the capture harvester (tests โ .ultra11y/captures)
|
|
200
|
+
node scripts/ultra11y.mjs audit --require-captures # gate the components with no rendered capture
|
|
201
|
+
node scripts/ultra11y.mjs scan http://localhost:3000 --runtime local --cwd . --merge audits/audit-latest.json
|
|
202
|
+
node scripts/ultra11y.mjs verify --report audits/wcag-YYYY-MM-DD.md --in audits/audit-latest.json --manual --out audits
|
|
203
|
+
node scripts/ultra11y.mjs verify --apply audits/ADJUDICATE.todo.json --in audits/audit-latest.json --out audits
|
|
204
|
+
node scripts/ultra11y.mjs orchestrate --run audits # fan the judgment phases out (--eco for the sequential path)
|
|
205
|
+
node scripts/ultra11y.mjs report --in audits/audit-latest.json --out audits # โ audits/wcag-YYYY-MM-DD.md
|
|
206
|
+
node scripts/ultra11y.mjs prd --in audits/audit-latest.json --gh-issues # the same auditor block as a backlog
|
|
207
|
+
node scripts/ultra11y.mjs check --report audits/wcag-YYYY-MM-DD.md # integrity gate
|
|
208
|
+
node scripts/ultra11y.mjs criteria 1.4.3 # one success criterion (--list for all)
|
|
209
|
+
node scripts/ultra11y.mjs fix "src/**/*.html" --write --iterate # apply the safe codemods to a fixpoint
|
|
210
|
+
node scripts/ultra11y.mjs init --hook # pre-commit gate (--baseline for the regression variant)
|
|
211
|
+
node scripts/ultra11y.mjs pack check ./packs/section508.json # gate an (AI-)authored standards pack
|
|
212
|
+
```
|
|
213
|
+
Add `--standard rgaa` to `report`/`prd`/`criteria`/`check`/`verify` for a country standard,
|
|
214
|
+
`--pack ./pack.json` to load one at runtime, and `--json` anywhere for machine output.
|
|
215
|
+
`--lang` follows the conversation (pass it explicitly โ Core rule 5).
|
|
216
|
+
|
|
217
|
+
## The loop: audit โ render โ judge โ fix โ re-audit
|
|
218
|
+
|
|
219
|
+
To converge on conformance (not a single pass), chain the steps, letting the agent
|
|
220
|
+
drive the judgment and content stages:
|
|
221
|
+
|
|
222
|
+
1. **Audit** the source (`audit โฆ --graph`) for a first map; on library-rendered code,
|
|
223
|
+
**audit the render** (`render` โ build/SSR โ `audit`) for reliable verdicts (otherwise
|
|
224
|
+
the scope-risk note reminds you).
|
|
225
|
+
2. **Adjudicate & refute** with `verify`, two worklists. (a) `verify --manual --in audit.json`
|
|
226
|
+
emits `ADJUDICATE.todo.json` โ one item per residual *judgment* criterion, pre-loaded with the
|
|
227
|
+
engine's harvested evidence โ which the AI agent rules on (`C`/`NC`/`NA`, or `manual` with a
|
|
228
|
+
`reason` when it truly `needs-rendered-dom`), each verdict carrying a `justification` or a
|
|
229
|
+
groundable finding; `verify --apply โฆ --in audit.json` folds them back FAIL-CLOSED (agent NCs
|
|
230
|
+
become real `agent:<sc>` findings that re-render in ยง2). (b) `verify --report โฆ [--semantic]`
|
|
231
|
+
builds `VERIFY.todo.json` to **refute any `preliminary`/SFC/library-source finding** the
|
|
232
|
+
rendered DOM disproves (verdicts `supported`/`partial`/`refuted`/`unsupported`);
|
|
233
|
+
`verify --apply` drops the refuted/unsupported ones (the anti-hallucination gate). This
|
|
234
|
+
includes **focus & interaction logic** (read the full component source: keyboard
|
|
235
|
+
operability, focus order/visibility, traps, on-focus/on-input changes; see
|
|
236
|
+
`references/focus-and-logic.md`) and the per-rule traps in `references/false-positives.md`.
|
|
237
|
+
Both worklists fan out (`orchestrate --run <dir> --phase adjudicate|verify-report` โ
|
|
238
|
+
see **Orchestration โ route by harness**); the `--apply` fold always stays with you.
|
|
239
|
+
3. **Fix** by priority: `fix --write --iterate` for the mechanical part (anti-regression
|
|
240
|
+
gate), then hand-apply the judgment/content fixes (alt, labels, structure) guided by
|
|
241
|
+
`references/correction.md`.
|
|
242
|
+
4. **Re-audit** (on the render where relevant) and repeat.
|
|
243
|
+
5. **Deliver the auditor block.** `report` (compliance doc: synthesis + one auditor
|
|
244
|
+
conformance block โ theme/criterion/test/WCAG+level/finding/expected/verification โ
|
|
245
|
+
per NC criterion) and `prd` (the same blocks as an actionable backlog, `--gh-issues`
|
|
246
|
+
filing one GitHub issue per criterion with that identical block) are two views of the
|
|
247
|
+
ONE building block, in the language of this conversation (pass `--lang` explicitly โ
|
|
248
|
+
Core rule 5).
|
|
249
|
+
|
|
250
|
+
**Stop** when `check` and `verify --apply` are green again and only explicitly-named
|
|
251
|
+
residual risks remain. (To automate the outer cadence, the harness `/loop` command can
|
|
252
|
+
re-run this cycle.)
|
|
253
|
+
|
|
254
|
+
## Combining engine, judgment and residual risk
|
|
255
|
+
|
|
256
|
+
`audit` classes each criterion `C`/`NC`/`NA` for the static subset and `manual` for the rest,
|
|
257
|
+
each carrying an `automatability` class that says WHY it is manual and how to close it:
|
|
258
|
+
**`static`** (the engine decides), **`needs-rendering`** (`scan`), **`judgment`** (you, from
|
|
259
|
+
the harvested evidence and the decision protocol). Engine `NC`s are confirmed candidates
|
|
260
|
+
with a cited `file:line`; a `preliminary: true` finding (SFC/library source) is provisional โ
|
|
261
|
+
confirm it against the render or refute it. A criterion is never silently marked conforming:
|
|
262
|
+
the report is complete only when every applicable criterion is a justified `C`/`NC`/`NA` and
|
|
263
|
+
every residual risk is named. See **`references/methodology.md`**.
|
|
264
|
+
|
|
265
|
+
**Advisory recommendations are a distinct class.** A good-practice signal with NO failing
|
|
266
|
+
normative test renders under a dedicated section and can never flip a criterion to `NC` nor
|
|
267
|
+
enter `conformancePct`. An `NC` needs a `normativeRef`; a recommendation does not. Do not
|
|
268
|
+
promote one to the other โ see **`references/false-positives.md`**.
|
|
269
|
+
|
|
270
|
+
## Do not
|
|
271
|
+
|
|
272
|
+
- Invent a non-conformity the engine did not find and you cannot see (contrast on
|
|
273
|
+
**inline literal colours** is decided statically; **computed** contrast โ external CSS,
|
|
274
|
+
variables โ goes through `scan` (Docker tier) or is verified at render before being declared).
|
|
275
|
+
- Add ARIA that duplicates native semantics.
|
|
276
|
+
- Mark a rendering/judgment criterion "conforming" without a recorded, gated justification
|
|
277
|
+
(agent adjudication via `verify --manual`, or `scan` evidence).
|
|
278
|
+
- Hand-edit `references/criteria.md` (generated from the WCAG dataset via `criteria --generate`).
|
|
279
|
+
|
|
280
|
+
## Scope
|
|
281
|
+
|
|
282
|
+
Static engine: offline, deterministic, install-free; inputs are HTML + JSX/TSX (real AST,
|
|
283
|
+
cross-file analysis via `--graph`) + stdin. The **rendering** criteria (computed contrast,
|
|
284
|
+
reflow) are covered by the optional `scan` tier (axe-core, Docker **or** `--runtime local`).
|
|
285
|
+
The local runtime additionally **probes** focus visibility (2.4.7), 200% text zoom (1.4.4),
|
|
286
|
+
text spacing (1.4.12) and content-on-hover (1.4.13) โ observed in the rendered page, raised
|
|
287
|
+
as NC only when the failure is seen (a clean probe leaves the SC `manual`, never silently
|
|
288
|
+
conforming); reading order and alt relevance are the AI agent's judgment, adjudicated from the
|
|
289
|
+
harvested evidence and gated (`verify --manual`).
|
|
290
|
+
Data: WCAG 2.2 ยฉ
|
|
291
|
+
W3C (W3C Document License); the RGAA pack is RGAA 4.1.2 ยฉ DINUM, Licence Ouverte / Etalab
|
|
292
|
+
2.0 (see `NOTICE`).
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
<!-- GENERATED from the vendored W3C ACT corpus by `pnpm run build:act` โ do not edit by hand. -->
|
|
2
|
+
|
|
3
|
+
# ACT conformance โ how this engine scores against a corpus it did not write
|
|
4
|
+
|
|
5
|
+
The recall matrix in this repository proves that each rule fires on the defect written FOR it.
|
|
6
|
+
That is circular. The [W3C ACT-Rules Community Group](https://act-rules.github.io) publishes rules
|
|
7
|
+
with `passed` / `failed` / `inapplicable` examples authored independently of this project, so running
|
|
8
|
+
the engine over them measures something a self-authored fixture cannot.
|
|
9
|
+
|
|
10
|
+
**How to read this.** An ACT example asserts something about ITS OWN rule and nothing else, so each
|
|
11
|
+
case is judged only with the engine rules mapped to that ACT rule โ never with the whole engine.
|
|
12
|
+
Only normative findings count (an `advisory` recommendation never flips a criterion, so it cannot
|
|
13
|
+
fail a case either). Rules needing a rendered page or a human call are declared, not scored โ saying
|
|
14
|
+
so beats quietly scoring zero.
|
|
15
|
+
|
|
16
|
+
## Summary
|
|
17
|
+
|
|
18
|
+
| | |
|
|
19
|
+
|---|---|
|
|
20
|
+
| Corpus | 1134 examples across 91 ACT rules |
|
|
21
|
+
| Source | https://act-rules.github.io/testcases.json |
|
|
22
|
+
| Rules scored | **32** |
|
|
23
|
+
| Failed examples caught | **103 / 149** |
|
|
24
|
+
| Clean examples left alone | **291 / 291** โ no unexplained false positive |
|
|
25
|
+
| Consistent | 5 |
|
|
26
|
+
| Divergent (documented, 9 cases) | 3 |
|
|
27
|
+
| Partially consistent | 24 |
|
|
28
|
+
| **Inconsistent** | **0** |
|
|
29
|
+
| Declared gaps (static, not implemented) | 13 |
|
|
30
|
+
|
|
31
|
+
*Partially consistent* is the ACT Rules Format's own term for a tool that never reports a false
|
|
32
|
+
positive but does not catch everything โ it is a coverage statement, not an error. *Divergent* means
|
|
33
|
+
every deviation on that rule is listed below with the argument for it.
|
|
34
|
+
|
|
35
|
+
## Scored rules
|
|
36
|
+
|
|
37
|
+
| ACT rule | WCAG | Engine rules | Verdict | Caught |
|
|
38
|
+
|---|---|---|---|---|
|
|
39
|
+
| [Image has non-empty accessible name](https://act-rules.github.io/rules/23a2a8) | 1.1.1 | `img-alt-missing` | ๐จ partially consistent | 4/5 |
|
|
40
|
+
| [HTML page has non-empty title](https://act-rules.github.io/rules/2779a5) | 2.4.2 | `title-missing-empty` | ๐จ partially consistent | 4/5 |
|
|
41
|
+
| [Visible label is part of accessible name](https://act-rules.github.io/rules/2ee8b8) | 2.5.3 | `label-in-name-mismatch` | ๐ฆ divergent (documented) | 3/3 |
|
|
42
|
+
| [Id attribute value is unique](https://act-rules.github.io/rules/3ea0c8) | 4.1.1 | `duplicate-id` | โ
consistent | 3/3 |
|
|
43
|
+
| [Audio or video element that plays automatically has a control mechanism](https://act-rules.github.io/rules/4c31df) | โ | `autoplay-media` | ๐ฆ divergent (documented) | 5/5 |
|
|
44
|
+
| [Element with role attribute has required states and properties](https://act-rules.github.io/rules/4e8ab6) | 4.1.2 | `aria-required-attr` | ๐จ partially consistent | 1/2 |
|
|
45
|
+
| [Image button has non-empty accessible name](https://act-rules.github.io/rules/59796f) | 1.1.1, 4.1.2 | `input-image-alt-missing` | ๐จ partially consistent | 2/3 |
|
|
46
|
+
| [ARIA state or property is permitted](https://act-rules.github.io/rules/5c01ea) | โ | `aria-prohibited-attr` | ๐จ partially consistent | 0/2 |
|
|
47
|
+
| [ARIA attribute is defined in WAI-ARIA](https://act-rules.github.io/rules/5f99a7) | โ | `invalid-aria-attr` | โ
consistent | 2/2 |
|
|
48
|
+
| [Role attribute has valid value](https://act-rules.github.io/rules/674b10) | 1.3.1 | `invalid-aria-role` | โ
consistent | 2/2 |
|
|
49
|
+
| [ARIA state or property has valid value](https://act-rules.github.io/rules/6a7281) | โ | `invalid-aria-value`, `live-region-conflict` | ๐จ partially consistent | 9/10 |
|
|
50
|
+
| [Element with aria-hidden has no content in sequential focus navigation](https://act-rules.github.io/rules/6cfa84) | 4.1.2 | `aria-hidden-focusable` | ๐จ partially consistent | 5/6 |
|
|
51
|
+
| [Autocomplete attribute has valid value](https://act-rules.github.io/rules/73f2c2) | 1.3.5 | `autocomplete-token-invalid` | โ
consistent | 5/5 |
|
|
52
|
+
| [SVG element with explicit role has non-empty accessible name](https://act-rules.github.io/rules/7d6734) | 1.1.1 | `img-alt-missing` | ๐จ partially consistent | 2/4 |
|
|
53
|
+
| [Audio or video element avoids automatically playing audio](https://act-rules.github.io/rules/80f0bf) | 1.4.2 | `autoplay-media` | ๐ฆ divergent (documented) | 2/2 |
|
|
54
|
+
| [Object element rendering non-text content has non-empty accessible name](https://act-rules.github.io/rules/8fc3b6) | 1.1.1 | `object-embed-no-name` | ๐จ partially consistent | 2/4 |
|
|
55
|
+
| [Button has non-empty accessible name](https://act-rules.github.io/rules/97a4e1) | 4.1.2 | `button-empty-name`, `icon-only-control-unnamed` | ๐จ partially consistent | 4/5 |
|
|
56
|
+
| [Headers attribute specified on a cell refers to cells in the same table element](https://act-rules.github.io/rules/a25f45) | 1.3.1 | `headers-attr-dangling` | โ
consistent | 4/4 |
|
|
57
|
+
| [Meta viewport allows for zoom](https://act-rules.github.io/rules/b4f0c3) | 1.4.4 | `meta-viewport-zoom-block` | ๐จ partially consistent | 3/4 |
|
|
58
|
+
| [HTML page has lang attribute](https://act-rules.github.io/rules/b5c3f8) | 3.1.1 | `html-lang-missing` | ๐จ partially consistent | 3/4 |
|
|
59
|
+
| [ARIA required owned elements](https://act-rules.github.io/rules/bc4a75) | 1.3.1 | `aria-required-children` | ๐จ partially consistent | 3/7 |
|
|
60
|
+
| [Meta element has no refresh delay](https://act-rules.github.io/rules/bc659a) | 2.2.1, 2.2.4, 3.2.5 | `meta-refresh-redirect` | ๐จ partially consistent | 3/4 |
|
|
61
|
+
| [HTML page lang attribute has valid language tag](https://act-rules.github.io/rules/bf051a) | 3.1.1 | `lang-invalid` | ๐จ partially consistent | 1/4 |
|
|
62
|
+
| [Meta element has no refresh delay (no exception)](https://act-rules.github.io/rules/bisz58) | 2.2.4, 3.2.5 | `meta-refresh-redirect` | ๐จ partially consistent | 2/4 |
|
|
63
|
+
| [Link has non-empty accessible name](https://act-rules.github.io/rules/c487ae) | 2.4.4, 2.4.9, 4.1.2 | `link-empty-name`, `icon-only-control-unnamed` | ๐จ partially consistent | 7/11 |
|
|
64
|
+
| [Iframe element has non-empty accessible name](https://act-rules.github.io/rules/cae760) | 4.1.2 | `iframe-title-missing` | ๐จ partially consistent | 3/4 |
|
|
65
|
+
| [Table header cell has assigned cells](https://act-rules.github.io/rules/d0f69e) | 1.3.1 | `th-no-data-cells` | ๐จ partially consistent | 0/3 |
|
|
66
|
+
| [Element with lang attribute has valid language tag](https://act-rules.github.io/rules/de46e4) | 3.1.2 | `lang-invalid`, `inline-lang-change-missing` | ๐จ partially consistent | 6/9 |
|
|
67
|
+
| [Form field has non-empty accessible name](https://act-rules.github.io/rules/e086e5) | 4.1.2 | `control-label-missing` | ๐จ partially consistent | 4/7 |
|
|
68
|
+
| [Video element auditory content has captions](https://act-rules.github.io/rules/f51b46) | โ | `media-no-track` | ๐จ partially consistent | 0/4 |
|
|
69
|
+
| [ARIA required context role](https://act-rules.github.io/rules/ff89c9) | 1.3.1 | `aria-required-parent` | ๐จ partially consistent | 2/4 |
|
|
70
|
+
| [Heading has non-empty accessible name](https://act-rules.github.io/rules/ffd0e9) | 1.3.1 | `empty-heading` | ๐จ partially consistent | 7/8 |
|
|
71
|
+
|
|
72
|
+
### Notes and documented divergences
|
|
73
|
+
|
|
74
|
+
- **Visible label is part of accessible name** ยท reports on *Passed Example 6*: an icon FONT renders the text 'search' as a glyph, so the visible label is not the text in the DOM โ a fact only the rendered page carries
|
|
75
|
+
- **Audio or video element that plays automatically has a control mechanism** ยท reports on *Inapplicable Example 2*: the source cannot tell that the referenced media has no audio track
|
|
76
|
+
- **Audio or video element that plays automatically has a control mechanism** ยท reports on *Passed Example 3*: the pause mechanism is a custom button wired in JavaScript, not a native `controls` attribute
|
|
77
|
+
- **ARIA state or property is permitted** โ covers the name-prohibited roles; the full per-role permitted-attribute matrix is not encoded
|
|
78
|
+
- **Element with aria-hidden has no content in sequential focus navigation** ยท reports on *Passed Example 4*: a focus-sentinel link inside an aria-hidden wrapper: it IS reachable by Tab, and only a runtime focus handler bounces it back โ the same call axe-core makes
|
|
79
|
+
- **SVG element with explicit role has non-empty accessible name** โ role=img on <svg> is handled by the same rule
|
|
80
|
+
- **Audio or video element avoids automatically playing audio** ยท reports on *Inapplicable Example 2*: the source cannot tell that the referenced media file is silent
|
|
81
|
+
- **Audio or video element avoids automatically playing audio** ยท reports on *Passed Example 3*: the pause mechanism is a custom button wired in JavaScript, not a native `controls` attribute
|
|
82
|
+
- **Audio or video element avoids automatically playing audio** ยท reports on *Passed Example 2*: a #t= media fragment shortening playback below 3s is not resolvable from source
|
|
83
|
+
- **Meta element has no refresh delay (no exception)** โ this variant drops the >20h exception the engine honours, so long delays are knowingly not reported
|
|
84
|
+
- **Iframe element has non-empty accessible name** ยท reports on *Inapplicable Example 3*: a tabindex=-1 iframe is still exposed to assistive tech and still needs a title (RGAA 2.1 requires one unconditionally)
|
|
85
|
+
- **Table header cell has assigned cells** โ only the explicit `headers`-wired shape is decided; scope-based assignment needs a full table model
|
|
86
|
+
- **Element with lang attribute has valid language tag** ยท reports on *Inapplicable Example 2*: lang="" on an element carrying text declares no language for that text; ACT deems the rule inapplicable, this engine reports it under 3.1.2
|
|
87
|
+
- **Form field has non-empty accessible name** โ `placeholder-as-label` is deliberately NOT mapped: a placeholder does contribute to the accessible name, so ACT passes it โ ultra11y still reports it, as a stricter house rule under 3.3.2.
|
|
88
|
+
- **Video element auditory content has captions** โ presence of a caption track; whether the captions are accurate is a judgment call
|
|
89
|
+
|
|
90
|
+
## Declared gaps โ statically decidable, not implemented yet
|
|
91
|
+
|
|
92
|
+
| ACT rule | WCAG | Why it is not covered |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| [Document has heading for non-repeated content](https://act-rules.github.io/rules/047fe0) | โ | a heading for the non-repeated content (h1-missing is advisory, so it does not count) |
|
|
95
|
+
| [Letter spacing in style attributes is not !important](https://act-rules.github.io/rules/24afc2) | 1.4.12 | letter-spacing:!important in a style attribute |
|
|
96
|
+
| [Element with presentational children has no focusable content](https://act-rules.github.io/rules/307n5z) | 4.1.2 | presentational-children conflict |
|
|
97
|
+
| [Element marked as decorative is not exposed](https://act-rules.github.io/rules/46ca7f) | โ | an element marked decorative that is still exposed (focusable, or with a name) |
|
|
98
|
+
| [HTML page lang and xml:lang attributes have matching values](https://act-rules.github.io/rules/5b7ae0) | 3.1.1 | lang vs xml:lang mismatch |
|
|
99
|
+
| [Line height in style attributes is not !important](https://act-rules.github.io/rules/78fd32) | 1.4.12 | line-height:!important in a style attribute |
|
|
100
|
+
| [Word spacing in style attributes is not !important](https://act-rules.github.io/rules/9e45ec) | 1.4.12 | word-spacing:!important in a style attribute |
|
|
101
|
+
| [Document has a landmark with non-repeated content](https://act-rules.github.io/rules/b40fd1) | โ | ACT asks that the non-repeated content sit in SOME landmark โ a weaker claim than `missing-main-landmark`, which requires a <main>, so the two are not equivalent |
|
|
102
|
+
| [Bypass Blocks of Repeated Content](https://act-rules.github.io/rules/cf77f2) | 2.4.1 | presence of a bypass mechanism (landmark or skip link) |
|
|
103
|
+
| [Attribute is not duplicated](https://act-rules.github.io/rules/e6952f) | 4.1.1 | duplicate attributes are collapsed by the parser; needs a raw-source scan |
|
|
104
|
+
| [No keyboard shortcut uses only printable characters](https://act-rules.github.io/rules/ffbc54) | 2.1.4 | 2.1.4 single-character keyboard shortcuts |
|
|
105
|
+
| [Menuitem has non-empty accessible name](https://act-rules.github.io/rules/m6b1q3) | 4.1.2 | role-specific accessible name (menuitem) |
|
|
106
|
+
| [Document has an instrument to move focus to non-repeated content](https://act-rules.github.io/rules/ye5d6e) | โ | presence of a bypass instrument |
|
|
107
|
+
|
|
108
|
+
## Out of the static engine's reach โ routed, not ignored
|
|
109
|
+
|
|
110
|
+
| ACT rule | WCAG | Decided by |
|
|
111
|
+
|---|---|---|
|
|
112
|
+
| [Text has enhanced contrast](https://act-rules.github.io/rules/09o5cg) | 1.4.6 | rendered (`scan`) โ AAA enhanced contrast โ outside the AA core |
|
|
113
|
+
| [Scrollable element is keyboard accessible](https://act-rules.github.io/rules/0ssw9k) | 2.1.1, 2.1.3 | rendered (`scan`) |
|
|
114
|
+
| [HTML graphics contain no text](https://act-rules.github.io/rules/0va7u6) | 1.4.5, 1.4.9 | rendered (`scan`) โ text baked into a graphic |
|
|
115
|
+
| [Audio and visuals of video element have transcript](https://act-rules.github.io/rules/1a02b0) | 1.2.8 | judgment (agent) |
|
|
116
|
+
| [Video element visual content has audio description](https://act-rules.github.io/rules/1ea59c) | โ | judgment (agent) |
|
|
117
|
+
| [Video element visual content has strict accessible alternative](https://act-rules.github.io/rules/1ec09b) | 1.2.5 | judgment (agent) |
|
|
118
|
+
| [Audio element content has transcript](https://act-rules.github.io/rules/2eb176) | โ | judgment (agent) |
|
|
119
|
+
| [Error message describes invalid form field value](https://act-rules.github.io/rules/36b590) | 3.3.1 | judgment (agent) |
|
|
120
|
+
| [Block of repeated content is collapsible](https://act-rules.github.io/rules/3e12e1) | โ | rendered (`scan`) |
|
|
121
|
+
| [Iframe elements with identical accessible names have equivalent purpose](https://act-rules.github.io/rules/4b1c6c) | 4.1.2 | judgment (agent) |
|
|
122
|
+
| [Zoomed text node is not clipped with CSS overflow](https://act-rules.github.io/rules/59br37) | 1.4.4 | rendered (`scan`) โ clipping under zoom โ probed by scan --runtime local |
|
|
123
|
+
| [Link in context is descriptive](https://act-rules.github.io/rules/5effbb) | 2.4.4, 2.4.9 | judgment (agent) โ link purpose in context (2.4.4) |
|
|
124
|
+
| [Device motion based changes to the content can also be created from the user interface](https://act-rules.github.io/rules/7677a9) | 2.5.4 | judgment (agent) |
|
|
125
|
+
| [Focusable element has no keyboard trap](https://act-rules.github.io/rules/80af7b) | 2.1.2 | rendered (`scan`) |
|
|
126
|
+
| [Content has alternative for visual reference](https://act-rules.github.io/rules/9bd38c) | 1.3.3 | judgment (agent) โ sensory characteristics (1.3.3) |
|
|
127
|
+
| [DEPRECATED โ Image filename is accessible name for image](https://act-rules.github.io/rules/9eb3f6) | 1.1.1 | withdrawn upstream |
|
|
128
|
+
| [Focusable element has no keyboard trap via standard navigation](https://act-rules.github.io/rules/a1b64e) | โ | rendered (`scan`) |
|
|
129
|
+
| [Audio or video element that plays automatically has no audio that lasts more than 3 seconds](https://act-rules.github.io/rules/aaa1bf) | โ | rendered (`scan`) โ needs the media's duration |
|
|
130
|
+
| [Video element content is media alternative for text](https://act-rules.github.io/rules/ab4d13) | โ | judgment (agent) |
|
|
131
|
+
| [DEPRECATED โ Video element visual-only content has description track](https://act-rules.github.io/rules/ac7dc6) | โ | withdrawn upstream |
|
|
132
|
+
| [Audio element content is media alternative for text](https://act-rules.github.io/rules/afb423) | โ | judgment (agent) |
|
|
133
|
+
| [Text has minimum contrast](https://act-rules.github.io/rules/afw4f7) | 1.4.3, 1.4.6 | rendered (`scan`) โ computed contrast; only inline literal colour pairs are decided statically (contrast-literal) |
|
|
134
|
+
| [Link is descriptive](https://act-rules.github.io/rules/aizyf1) | 2.4.9 | judgment (agent) |
|
|
135
|
+
| [Iframe with negative tabindex has no interactive elements](https://act-rules.github.io/rules/akn7bn) | 2.1.1 | rendered (`scan`) โ needs the iframe's own document |
|
|
136
|
+
| [Links with identical accessible names have equivalent purpose](https://act-rules.github.io/rules/b20e66) | 2.4.9 | judgment (agent) |
|
|
137
|
+
| [Orientation of the page is not restricted using CSS transform property](https://act-rules.github.io/rules/b33eff) | 1.3.4 | rendered (`scan`) โ orientation lock via CSS transform |
|
|
138
|
+
| [Heading is descriptive](https://act-rules.github.io/rules/b49b2e) | 2.4.6 | judgment (agent) โ is the heading descriptive (2.4.6) |
|
|
139
|
+
| [Device motion based changes to the content can be disabled](https://act-rules.github.io/rules/c249d5) | 2.5.4 | judgment (agent) |
|
|
140
|
+
| [Video element visual-only content has accessible alternative](https://act-rules.github.io/rules/c3232f) | 1.2.1 | judgment (agent) |
|
|
141
|
+
| [HTML page title is descriptive](https://act-rules.github.io/rules/c4a8a4) | 2.4.2 | judgment (agent) |
|
|
142
|
+
| [Video element visual content has accessible alternative](https://act-rules.github.io/rules/c5a4ea) | 1.2.3, 1.2.5, 1.2.8 | judgment (agent) |
|
|
143
|
+
| [Form field label is descriptive](https://act-rules.github.io/rules/cc0f0a) | 2.4.6 | judgment (agent) |
|
|
144
|
+
| [Video element visual-only content has audio track alternative](https://act-rules.github.io/rules/d7ba54) | โ | judgment (agent) |
|
|
145
|
+
| [Audio element content has text alternative](https://act-rules.github.io/rules/e7aa44) | 1.2.1 | judgment (agent) |
|
|
146
|
+
| [Image not in the accessibility tree is decorative](https://act-rules.github.io/rules/e88epe) | 1.1.1 | judgment (agent) โ is the image genuinely decorative |
|
|
147
|
+
| [Video element auditory content has accessible alternative](https://act-rules.github.io/rules/eac66b) | 1.2.2 | judgment (agent) |
|
|
148
|
+
| [Focusable element has no keyboard trap via non-standard navigation](https://act-rules.github.io/rules/ebe86a) | โ | rendered (`scan`) |
|
|
149
|
+
| [Video element visual-only content has transcript](https://act-rules.github.io/rules/ee13b5) | โ | judgment (agent) |
|
|
150
|
+
| [Text content that changes automatically can be paused, stopped or hidden](https://act-rules.github.io/rules/efbfc7) | 2.2.2 | rendered (`scan`) |
|
|
151
|
+
| [DEPRECATED โ Video element visual content has description track](https://act-rules.github.io/rules/f196ce) | โ | withdrawn upstream |
|
|
152
|
+
| [Video element visual-only content is media alternative for text](https://act-rules.github.io/rules/fd26cf) | โ | judgment (agent) |
|
|
153
|
+
| [Links with identical accessible names and same context serve equivalent purpose](https://act-rules.github.io/rules/fd3a94) | 2.4.4, 2.4.9 | judgment (agent) |
|
|
154
|
+
| [HTML element language subtag matches language](https://act-rules.github.io/rules/off6ek) | 3.1.2 | judgment (agent) โ does the subtag match the actual text language |
|
|
155
|
+
| [Element in sequential focus order has visible focus](https://act-rules.github.io/rules/oj04fd) | 2.4.7 | rendered (`scan`) โ visible focus (2.4.7) โ probed by scan --runtime local |
|
|
156
|
+
| [Image accessible name is descriptive](https://act-rules.github.io/rules/qt1vmo) | 1.1.1 | judgment (agent) โ is the alt relevant (1.1.1) |
|
|
157
|
+
| [HTML page language subtag matches default language](https://act-rules.github.io/rules/ucwvc8) | 3.1.1 | judgment (agent) |
|
|
158
|
+
|
|
159
|
+
The corpus is vendored at `scripts/vendor/act-testcases.json` (refreshed by
|
|
160
|
+
`pnpm run build:act:refresh`, and daily by the act-refresh workflow) so the suite stays
|
|
161
|
+
offline and deterministic.
|
|
162
|
+
ACT-Rules Community Group test cases are ยฉ their contributors under the W3C Software and
|
|
163
|
+
Document License โ see `NOTICE`.
|