ultra11y 4.3.0 → 4.4.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.opencode/plugins/ultra11y.js +1 -1
- package/README.md +40 -4
- package/package.json +1 -1
- package/scripts/build-standards.mjs +290 -1
- package/scripts/ultra11y.mjs +2675 -274
- package/scripts/vendor/wcag-2.2-fr.json +944 -0
- package/scripts/vendor/wcag-2.2-text.json +749 -0
- package/skills/review-a11y/SKILL.md +1 -1
- package/skills/review-a11y/scripts/ultra11y.mjs +2675 -274
- package/skills/ultra11y/SKILL.md +13 -4
- package/skills/ultra11y/references/guidance.md +33 -7
- package/skills/ultra11y/references/harnesses.md +10 -0
- package/skills/ultra11y/references/mcp.md +215 -0
- package/skills/ultra11y/references/packs.md +8 -0
- package/skills/ultra11y/references/standards.md +18 -0
- package/skills/ultra11y/scripts/ultra11y.mjs +2675 -274
- package/src/adjudicate.ts +9 -15
- package/src/adjudication-data.ts +38 -0
- package/src/check.ts +51 -1
- package/src/cli.ts +6 -2
- package/src/config.ts +27 -4
- package/src/criteria-view.ts +463 -0
- package/src/criteria.ts +14 -11
- package/src/data/guidance/wcag.json +268 -0
- package/src/data/wcag.json +1112 -55
- package/src/guidance/index.ts +11 -0
- package/src/guidance/resolve.ts +71 -0
- package/src/mcp/handlers.ts +160 -15
- package/src/mcp/prompts.ts +13 -2
- package/src/mcp/server.ts +18 -4
- package/src/mcp/standards-resources.ts +174 -0
- package/src/mcp/tools.ts +140 -6
- package/src/method-view.ts +227 -0
- package/src/prd.ts +5 -16
- package/src/standards/coverage.ts +237 -0
- package/src/standards/index.ts +1 -0
- package/src/standards/pack.ts +19 -0
- package/src/standards/registry.ts +115 -9
- package/src/types.ts +24 -1
- package/src/wcag.ts +21 -1
package/skills/ultra11y/SKILL.md
CHANGED
|
@@ -4,7 +4,7 @@ description: "Use to AUDIT existing HTML/CSS/JSX against WCAG 2.2 AA accessibili
|
|
|
4
4
|
when_to_use: "Invoke when the user asks for an accessibility AUDIT or a formal deliverable: audit a repo, site or page against WCAG 2.2 AA or a country standard (RGAA, Section 508, EN 301 549); produce a dated conformance report, a criterion grid, a PRD backlog, or tickets (GitHub/GitLab/Jira); author accessible markup from scratch; wire the repo gate (init --hook/--ci) or a rendered-DOM capture pipeline. For a review of the code UNDER CHANGE (diff, branch, PR), use the `review-a11y` skill instead."
|
|
5
5
|
license: MIT
|
|
6
6
|
metadata:
|
|
7
|
-
version: 4.
|
|
7
|
+
version: 4.4.0
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# ultra11y — audit WCAG 2.2 AA and write accessible markup
|
|
@@ -47,17 +47,25 @@ adjudicates. So the engine's clean run is a starting point, never a verdict —
|
|
|
47
47
|
> *judgment* criterion itself (`verify --manual`, gated), and the *rendering* criteria go to
|
|
48
48
|
> `scan`; any criterion still unproven stays "to assess manually" — no status without a
|
|
49
49
|
> recorded, justified verdict.
|
|
50
|
-
> 5. **
|
|
50
|
+
> 5. **Look the criterion up; never recall it.** `criteria [--standard <pack>] <id>` — or
|
|
51
|
+
> `ultra11y_criteria` over MCP — returns the criterion's own wording, its **numbered
|
|
52
|
+
> tests**, and the glossary definitions those tests cite. RGAA 8.3 is not "the page needs a
|
|
53
|
+
> `lang` attribute"; it is test `8.3.1` with two alternative conditions, and the glossary
|
|
54
|
+
> decides what its terms mean. An auditor block that cites `8.3.1` after reading it is
|
|
55
|
+
> grounded; one that cites it from memory is a guess wearing a reference. Before auditing
|
|
56
|
+
> against a country standard, run the plan (`ultra11y_method`): it tells you how many of its
|
|
57
|
+
> criteria no tool will decide for you — for RGAA, **58 of 106**. See `references/mcp.md`.
|
|
58
|
+
> 6. **The FINAL rendered semantic HTML must be correct.** The engine sees only source; a
|
|
51
59
|
> component library (DSFR/MUI…) or `.vue`/`.svelte`/`.astro` SFC hides the real markup, so
|
|
52
60
|
> a green source audit is not proof. Verify the produced semantic HTML — install the
|
|
53
61
|
> zero-touch **capture** harvester (`render --setup`) so every component your tests render
|
|
54
62
|
> is serialized to `.ultra11y/captures` and audited, with `audit --require-captures` gating
|
|
55
63
|
> the blind spots. See `references/automation.md` / `rendered.md`.
|
|
56
|
-
>
|
|
64
|
+
> 7. **Language**: ALWAYS pass `--lang` matching the language of your conversation with
|
|
57
65
|
> the user; ask the user when ambiguous. Without the flag the CLI auto-detects (repo
|
|
58
66
|
> `<html lang>` → the active standard's default locale → English) — a scripted/CI
|
|
59
67
|
> fallback, not a substitute for passing `--lang` yourself.
|
|
60
|
-
>
|
|
68
|
+
> 8. **Technical tokens stay in English, even in French prose.** In any French deliverable
|
|
61
69
|
> you write (report commentary, PRD, tracker tickets, judgment verdicts), attribute/
|
|
62
70
|
> element/role names and their values are code, not prose — never translate them:
|
|
63
71
|
> `aria-live` stays `aria-live` (never « région live »), same for `tabindex`, `alt`,
|
|
@@ -102,6 +110,7 @@ Domain knowledge first, then the tooling. Read the one that matches the question
|
|
|
102
110
|
| `references/prd.md` | The auditor block as a backlog (markdown) |
|
|
103
111
|
| `references/tickets.md` | Filing that backlog as tickets: GitHub, GitLab, Jira, and at which granularity |
|
|
104
112
|
| `references/standards.md` · `references/packs.md` · `references/guidance.md` | Country standards, authoring a pack, implementation guidance |
|
|
113
|
+
| `references/mcp.md` | **The standards as a rule engine**: look a criterion up instead of recalling it — its numbered tests, the terms it defines, the fix, and the work plan. As MCP tools and `std://` resources, or the same data on the CLI |
|
|
105
114
|
| `references/methodology.md` | Statuses, pass rate, severities, report format |
|
|
106
115
|
| `references/cross-file.md` | `--graph`: imports and cross-file rules |
|
|
107
116
|
| `references/orchestration.md` | Fanning the judgment phases out across subagents |
|
|
@@ -12,7 +12,8 @@ Guidance is looked up at **render time** by criterion / WCAG SC, so the canonica
|
|
|
12
12
|
|
|
13
13
|
- **`prd`** — each backlog item gains a before/after example and an effort estimate; the
|
|
14
14
|
`--format doc` PRD weaves it into the user stories and acceptance criteria.
|
|
15
|
-
- **`
|
|
15
|
+
- **`ultra11y_guidance`** over MCP — the direct lookup, by criterion.
|
|
16
|
+
- **`ultra11y_criteria`** with `include_guidance: true`, attached to the criterion.
|
|
16
17
|
|
|
17
18
|
Because attachment is presentation-only, guidance never marks anything conforming and
|
|
18
19
|
never invents a non-conformity — it is illustration, not detection.
|
|
@@ -21,12 +22,37 @@ never invents a non-conformity — it is illustration, not detection.
|
|
|
21
22
|
|
|
22
23
|
A guidance dataset is JSON: `{ pack, source, license, attribution, entries[] }`, where
|
|
23
24
|
each entry is `{ id, criterionId, wcag[], title, summary, impact?, examples[], reference }`
|
|
24
|
-
and an example is `{ lang: "html"|"jsx"|"css", bad?, good?, note? }`.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
entry resolves to a real criterion,
|
|
29
|
-
parses.
|
|
25
|
+
and an example is `{ lang: "html"|"jsx"|"css", bad?, good?, note? }`. Two ship built in:
|
|
26
|
+
`src/data/guidance/rgaa.json` (93 entries, ids mirroring the SocialGouv rule files) and
|
|
27
|
+
`src/data/guidance/wcag.json` (the WCAG-keyed set). Load external guidance with
|
|
28
|
+
`--pack <dir>` (a `guidance.json` beside `pack.json`) or a `.ultra11yrc.json` `guidance`
|
|
29
|
+
list. `pack check --guidance` validates that every entry resolves to a real criterion,
|
|
30
|
+
maps to recognized WCAG SCs, and that every example parses.
|
|
31
|
+
|
|
32
|
+
## Inheritance — why a new country pack is useful on day one
|
|
33
|
+
|
|
34
|
+
Every entry declares the WCAG success criteria it implements, and a lookup walks **every**
|
|
35
|
+
registered dataset. So a pack that ships no guidance of its own still gets examples, through
|
|
36
|
+
the criteria it maps onto — a freshly authored Section 508 or EN 301 549 pack inherits the
|
|
37
|
+
whole corpus the moment its `wcag[]` mappings exist.
|
|
38
|
+
|
|
39
|
+
Resolution order (first wins, deduped by entry id):
|
|
40
|
+
|
|
41
|
+
1. the pack's own entry for that criterion → `via: "pack"`, `inherited: false`
|
|
42
|
+
2. every entry keyed to each WCAG SC the criterion maps to, in the pack's own SC order →
|
|
43
|
+
`via: "wcag:<sc>"`, `inherited: true`
|
|
44
|
+
|
|
45
|
+
**The marking is the point.** An inherited example is not the national standard's own
|
|
46
|
+
doctrine, and a report that presented it as one would be making a claim nobody wrote. Every
|
|
47
|
+
surface carries `inherited` / `via`, and each entry also carries `languagesAvailable` — the
|
|
48
|
+
RGAA dataset is French-first, so an English caller must be told when an entry has no English
|
|
49
|
+
text rather than handed French silently.
|
|
50
|
+
|
|
51
|
+
`src/data/guidance/wcag.json` exists for the one thing no country dataset can supply: the
|
|
52
|
+
**ten AA criteria RGAA 4.1.2 never covered** — `1.2.4`, `2.3.1`, `2.4.5`, `2.4.11`, `2.5.7`,
|
|
53
|
+
`2.5.8`, `3.2.6`, `3.3.3`, `3.3.7`, `3.3.8`. Six were added in WCAG 2.2, after RGAA
|
|
54
|
+
(`wcagVersion: 2.1`) froze. With it in place, **no AA success criterion is without reachable
|
|
55
|
+
guidance**, for any pack.
|
|
30
56
|
|
|
31
57
|
## Honesty rule — guidance is NOT a free detector
|
|
32
58
|
|
|
@@ -91,8 +91,18 @@ every `references/*.md` are exposed as `skill://` resources, plus three prompts
|
|
|
91
91
|
|
|
92
92
|
```
|
|
93
93
|
claude mcp add ultra11y -- npx -y ultra11y mcp
|
|
94
|
+
|
|
95
|
+
# better: dedicate it to one project, so `cwd` is optional on every tool AND that
|
|
96
|
+
# project's own standards packs (.ultra11yrc.json) are loaded at startup
|
|
97
|
+
claude mcp add ultra11y -- npx -y ultra11y mcp --cwd /abs/path/to/project
|
|
94
98
|
```
|
|
95
99
|
|
|
100
|
+
It also carries the **standards themselves** — the reference block (`ultra11y_standards`,
|
|
101
|
+
`ultra11y_criteria`, `ultra11y_glossary`, `ultra11y_guidance`, `ultra11y_method`) and the
|
|
102
|
+
`std://` resources. That is the half that turns the server into a rule engine rather than a
|
|
103
|
+
linter: an agent can read a criterion's numbered tests and the terms it defines instead of
|
|
104
|
+
recalling them. See `references/mcp.md`.
|
|
105
|
+
|
|
96
106
|
On a harness with no skill system at all, **reading `SKILL.md` directly with the file-read
|
|
97
107
|
tool is the blessed path**, not a workaround. Discover what exists by listing
|
|
98
108
|
`skills/*/SKILL.md` and reading the frontmatter.
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# The standards as a rule engine — the MCP reference surface
|
|
2
|
+
|
|
3
|
+
The audit tools tell you what a page *does*. The reference tools tell you what the standard
|
|
4
|
+
*requires*. Without the second half an agent audits from memory, and a criterion recalled
|
|
5
|
+
from memory is how an invented non-conformity gets written.
|
|
6
|
+
|
|
7
|
+
This page is that second half: five read-only tools and a `std://` resource scheme that hand
|
|
8
|
+
you any registered standard's criteria, its normative wording, the terms it defines, the
|
|
9
|
+
before/after patterns that implement it, and an up-front plan for how much of it any tool can
|
|
10
|
+
decide at all.
|
|
11
|
+
|
|
12
|
+
Everything here works offline, from data vendored into the bundle. Nothing calls a network
|
|
13
|
+
service, and no key is needed.
|
|
14
|
+
|
|
15
|
+
## The one rule that makes it a rule engine
|
|
16
|
+
|
|
17
|
+
**Look the criterion up. Do not recall it.**
|
|
18
|
+
|
|
19
|
+
`ultra11y_criteria` returns the criterion's own words and its own numbered tests. RGAA 8.3 is
|
|
20
|
+
not "the page needs a lang attribute" — it is a numbered test with two alternative
|
|
21
|
+
conditions, and the glossary decides what its terms mean. An auditor block that cites
|
|
22
|
+
`8.3.1` after reading `8.3.1` is grounded; one that cites it from memory is a guess wearing a
|
|
23
|
+
reference.
|
|
24
|
+
|
|
25
|
+
## The five tools
|
|
26
|
+
|
|
27
|
+
| Tool | Answers |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `ultra11y_standards` | Which standards exist here, and how much of each any engine can decide |
|
|
30
|
+
| `ultra11y_criteria` | One criterion in full — wording, numbered tests, techniques, mapping, defined terms — or the index, or one theme |
|
|
31
|
+
| `ultra11y_glossary` | What a term the standard **defines** actually means, and which criteria it governs |
|
|
32
|
+
| `ultra11y_guidance` | The before/after implementation pattern for a criterion |
|
|
33
|
+
| `ultra11y_method` | The work plan: what the engine settles, what needs a render, what is yours |
|
|
34
|
+
|
|
35
|
+
All five are read-only and closed-world. All five take an **optional** `cwd` — they read the
|
|
36
|
+
standard, not your files. `cwd` still matters, because *which standards exist* is a fact
|
|
37
|
+
about a project (see **Packs are per-project** below).
|
|
38
|
+
|
|
39
|
+
### `ultra11y_criteria` — the lookup
|
|
40
|
+
|
|
41
|
+
```jsonc
|
|
42
|
+
{ "standard": "rgaa", "sc": "8.3", "lang": "fr" }
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Returns the criterion's theme, its localized title, its **numbered tests** (`8.3.1` and its
|
|
46
|
+
sub-conditions, verbatim), its W3C technique codes, the WCAG success criteria it maps to, the
|
|
47
|
+
**glossary definitions its tests cite**, the per-SC decision protocol, and a `coverage` block
|
|
48
|
+
saying what it would take to decide it. `text` is byte-identical to what
|
|
49
|
+
`criteria --standard rgaa 8.3` prints, so the two can never drift.
|
|
50
|
+
|
|
51
|
+
- `sc` and `criterion` are aliases. "8.3" is not a *success criterion*, and a worldwide tool
|
|
52
|
+
should not force a country criterion to be called one.
|
|
53
|
+
- Omit the id for the index; pass `theme: 8` for one theme.
|
|
54
|
+
- `glossary: "<term>"` looks a defined term up; `glossary: ""` lists them all.
|
|
55
|
+
- `include_guidance: true` attaches the before/after patterns (off by default — they are large).
|
|
56
|
+
|
|
57
|
+
For the WCAG core the same call returns the criterion's **normative text**, verbatim from the
|
|
58
|
+
W3C source, with its exceptions and notes kept as labelled lines, plus the WCAG terms that
|
|
59
|
+
wording links to. `lang: "fr"` resolves the W3C **authorized French translation** — title,
|
|
60
|
+
requirement prose and glossary together, never a French heading over English requirements.
|
|
61
|
+
|
|
62
|
+
### `ultra11y_method` — read this before auditing anything
|
|
63
|
+
|
|
64
|
+
The plan, derived rather than guessed. Every criterion of the standard lands in exactly one
|
|
65
|
+
**evidence tier**:
|
|
66
|
+
|
|
67
|
+
| Tier | What decides it | Who produces the evidence |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| `source` | an engine rule, from the source tree | `ultra11y_audit` |
|
|
70
|
+
| `cross-file` | an engine rule, across the dependency graph | `ultra11y_audit` with `graph: true` |
|
|
71
|
+
| `rendered-page` | computed styles, laid-out boxes, the screenshot | `ultra11y render` / `dev` / an E2E capture, then audit again |
|
|
72
|
+
| `browser` | a live rendered DOM | `ultra11y scan <target> --merge` (CLI — this server does not drive a browser) |
|
|
73
|
+
| `judgment` | a reading of meaning | `ultra11y_adjudicate`, then you |
|
|
74
|
+
| `out-of-scope` | nothing — every mapped SC is outside the AA core | declare it; never claim it |
|
|
75
|
+
|
|
76
|
+
The buckets **partition** the standard: 106 RGAA criteria in, 106 out. The classification is a
|
|
77
|
+
lookup over data the repo already ships — each criterion's declared rule applicability, the
|
|
78
|
+
WCAG automatability class, the pack's own judgment flags — never a regex over the wording of a
|
|
79
|
+
test.
|
|
80
|
+
|
|
81
|
+
Two counts are deliberately separate, and the distinction is easy to lose:
|
|
82
|
+
|
|
83
|
+
- **`sourceIsEnough`** — the source tree can prove it **conformant**.
|
|
84
|
+
- **`canFailFromSource`** — an engine rule can **fail** it, even though source cannot pass it.
|
|
85
|
+
|
|
86
|
+
RGAA 4.10 is flagged `judgment` (no tool may declare it conformant) and still carries
|
|
87
|
+
`autoplay-media`, which can fail it outright. Collapsing the two axes into one boolean throws
|
|
88
|
+
that coverage away.
|
|
89
|
+
|
|
90
|
+
The headline number for RGAA: **58 of its 106 criteria declare that no engine rule can
|
|
91
|
+
evidence them at all.** That is not a gap in the tool — it is the standard saying those are
|
|
92
|
+
yours. A plan that hides it reads as coverage that does not exist.
|
|
93
|
+
|
|
94
|
+
### `ultra11y_glossary` — the definitions are normative
|
|
95
|
+
|
|
96
|
+
A standard's tests lean constantly on terms it defines itself. RGAA ships 119; WCAG defines
|
|
97
|
+
101 of its own in English and 102 in the authorized French translation. "Relevant", "if necessary", "large scale", "pure decoration" mean what the
|
|
98
|
+
glossary says they mean, and that is what decides the verdict — not the everyday sense of the
|
|
99
|
+
word.
|
|
100
|
+
|
|
101
|
+
Each lookup also returns `citedBy`: the criteria whose tests actually cite that definition.
|
|
102
|
+
|
|
103
|
+
### `ultra11y_guidance` — illustration, never detection
|
|
104
|
+
|
|
105
|
+
The before/after pattern for a criterion: a non-compliant snippet, the compliant fix, the note
|
|
106
|
+
explaining the difference.
|
|
107
|
+
|
|
108
|
+
A criterion with no guidance of its own **inherits** what is keyed to the WCAG success
|
|
109
|
+
criteria it maps to, and every inherited entry is marked `inherited: true` with
|
|
110
|
+
`via: "wcag:<sc>"`. That is what makes a newly added country pack useful the day it lands —
|
|
111
|
+
but an inherited example is not the national standard's own doctrine, and a report must never
|
|
112
|
+
present it as one.
|
|
113
|
+
|
|
114
|
+
**Guidance never decides a verdict.** It illustrates. A pattern earns a detector only when it
|
|
115
|
+
is statically decidable *and* maps to a criterion in the WCAG 2.2 AA core; everything else
|
|
116
|
+
lives here. See `references/guidance.md` for the honesty rule in full.
|
|
117
|
+
|
|
118
|
+
## Packs are per-project
|
|
119
|
+
|
|
120
|
+
A standards pack is project configuration — it arrives with a `--pack` flag or a
|
|
121
|
+
`.ultra11yrc.json`. So a long-lived server serves many projects, and which standards exist
|
|
122
|
+
depends on whose project is asking.
|
|
123
|
+
|
|
124
|
+
- Every tool's `cwd` selects the project whose packs are visible. They are resolved once per
|
|
125
|
+
root and cached.
|
|
126
|
+
- Two projects may each define a different pack under the **same key** without either
|
|
127
|
+
shadowing the other.
|
|
128
|
+
- A project's `secondaryMappings` are applied to a **copy** of the built-in pack, never to the
|
|
129
|
+
shared one — one project cannot re-key RGAA for every other project the server is serving.
|
|
130
|
+
- A pack that does not validate is a **hard error**. The server refuses to answer for that
|
|
131
|
+
project rather than quietly answering about WCAG instead, because being answered about a
|
|
132
|
+
different standard than the one you asked about is the failure this tool exists to prevent.
|
|
133
|
+
|
|
134
|
+
`standard` therefore carries **no enum**. An enum pinned when the tool list was built would
|
|
135
|
+
reject a pack that is perfectly valid for the project being asked about. The handler
|
|
136
|
+
validates against the registry instead and names the standards it does know.
|
|
137
|
+
|
|
138
|
+
Start the server dedicated to one project when you can:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
claude mcp add ultra11y -- npx -y ultra11y mcp --cwd /abs/path/to/project
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## The `std://` resources
|
|
145
|
+
|
|
146
|
+
Documentation in MCP is a *resource*, not a tool call. `resources/list` carries a small,
|
|
147
|
+
bounded index per standard; the per-item URIs are **templates**, because enumerating RGAA's
|
|
148
|
+
106 criteria and 119 terms would bloat every client's listing and go stale the moment a
|
|
149
|
+
project's own pack registers.
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
std://rgaa/criteria the criterion index
|
|
153
|
+
std://rgaa/criteria/8.3 one criterion, in full
|
|
154
|
+
std://rgaa/themes/8 one theme
|
|
155
|
+
std://rgaa/glossary every term the standard defines
|
|
156
|
+
std://rgaa/glossary/lien one definition
|
|
157
|
+
std://rgaa/guidance/13.2 before/after patterns
|
|
158
|
+
std://rgaa/method the work plan
|
|
159
|
+
std://rgaa/pack.json the pack as loaded, with its licence and attribution
|
|
160
|
+
std://wcag/criteria/1.4.3 the same, for the worldwide core
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`resources/templates/list` declares the four templated forms.
|
|
164
|
+
|
|
165
|
+
A `std://` read carries no `cwd` of its own, so it resolves against the **server's** project
|
|
166
|
+
root — the same packs its tools serve, when you started it with `--cwd`. Without a default
|
|
167
|
+
project it sees the built-ins only. That is one more reason to dedicate the server.
|
|
168
|
+
|
|
169
|
+
A `std://` read never touches the filesystem: the `skill://` scheme and its realpath
|
|
170
|
+
containment live in a separate module, because a non-filesystem branch inside a
|
|
171
|
+
path-containment function is exactly where a traversal bug hides later.
|
|
172
|
+
|
|
173
|
+
## The gate that follows from all this
|
|
174
|
+
|
|
175
|
+
`ultra11y_check` refuses a criterion declared **conformant** whose evidence tier this audit
|
|
176
|
+
never ran. Claiming 1.4.3 Contrast conformant from a source-only audit is refused by name,
|
|
177
|
+
with the command that would produce the evidence.
|
|
178
|
+
|
|
179
|
+
Scoped tight, so it refuses only what is unambiguously wrong: it needs the audit in hand, it
|
|
180
|
+
reads only the engine-decided half of the conformity list, and an absent `pagesAudited` is
|
|
181
|
+
read as *unknown*, never as zero. An agent's own ruling is left alone — that claim is bound by
|
|
182
|
+
the semantic gate instead (`references/judgment.md`).
|
|
183
|
+
|
|
184
|
+
`not-tested` and `not-applicable` are exempt throughout, and for the same reason: they assert
|
|
185
|
+
nothing.
|
|
186
|
+
|
|
187
|
+
## Driving it as an RGAA rule engine
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
1. ultra11y_standards → confirm rgaa is loaded here
|
|
191
|
+
2. ultra11y_method { standard: "rgaa" } → 39 source · 4 rendered · 3 browser · 59 judgment · 1 out of scope
|
|
192
|
+
3. ultra11y_audit { cwd, graph: true } → settles the source tier
|
|
193
|
+
4. ultra11y render / scan --merge → produces the rendered and browser tiers
|
|
194
|
+
5. ultra11y_adjudicate { standard: "rgaa" } → the judgment tier, with its evidence
|
|
195
|
+
├─ ultra11y_criteria { standard:"rgaa", sc } → the numbered tests you rule against
|
|
196
|
+
├─ ultra11y_glossary { standard:"rgaa", term } → what its terms normatively mean
|
|
197
|
+
└─ ultra11y_guidance { standard:"rgaa", ... } → the fix to recommend
|
|
198
|
+
6. ultra11y_report { standard: "rgaa" } → the dated deliverable
|
|
199
|
+
7. ultra11y_check { standard: "rgaa" } → nothing claimed beyond the evidence
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Steps 2 and 5 are the ones that make it a rule engine rather than a linter. Skipping step 2
|
|
203
|
+
means auditing without knowing that 59 of 106 criteria were never going to be decided by a
|
|
204
|
+
tool; skipping the lookups in step 5 means ruling on criteria from memory.
|
|
205
|
+
|
|
206
|
+
**A criterion nobody tested is untested, never conformant.** Every tool description repeats
|
|
207
|
+
it, because the failure mode here is not a wrong answer — it is a confident silence.
|
|
208
|
+
|
|
209
|
+
## Related
|
|
210
|
+
|
|
211
|
+
- `references/harnesses.md` — wiring the server into Claude Code, Codex, OpenCode, Cursor
|
|
212
|
+
- `references/packs.md` — authoring and runtime-loading a country pack
|
|
213
|
+
- `references/guidance.md` — the guidance dataset and its honesty rule
|
|
214
|
+
- `references/standards.md` — the pack format, and adding your country
|
|
215
|
+
- `references/adjudication.md` — the decision protocol the judgment tier works from
|
|
@@ -18,6 +18,14 @@ node scripts/ultra11y.mjs report --in audit.json --standard section508 --pack ./
|
|
|
18
18
|
/ `guidance.json`), or a comma-separated list. Or declare it once in a `.ultra11yrc.json`
|
|
19
19
|
at the project root:
|
|
20
20
|
|
|
21
|
+
A pack loaded this way is a **first-class standard everywhere**, not just on the CLI: the
|
|
22
|
+
MCP server resolves each project's packs from its own `.ultra11yrc.json`, so
|
|
23
|
+
`ultra11y_criteria { standard: "<yourpack>" }`, `ultra11y_method`, `ultra11y_glossary` and
|
|
24
|
+
the `std://<yourpack>/…` resources all work the moment it validates. Two projects may define
|
|
25
|
+
different packs under the same key without either shadowing the other, and a project's
|
|
26
|
+
`secondaryMappings` are applied to a *copy* of a built-in pack, never to the shared one. See
|
|
27
|
+
`references/mcp.md`.
|
|
28
|
+
|
|
21
29
|
```json
|
|
22
30
|
{ "packs": ["./packs/section508.json"], "guidance": ["./packs/section508.guidance.json"], "standard": "section508" }
|
|
23
31
|
```
|
|
@@ -40,10 +40,28 @@ node scripts/ultra11y.mjs report --in audits/audit-latest.json --standard rgaa
|
|
|
40
40
|
node scripts/ultra11y.mjs criteria --standard rgaa --theme 1 # a pack theme
|
|
41
41
|
node scripts/ultra11y.mjs criteria --standard rgaa 8.3 # one pack criterion (shows its WCAG SCs)
|
|
42
42
|
node scripts/ultra11y.mjs check --report audits/rgaa-YYYY-MM-DD.md --standard rgaa
|
|
43
|
+
node scripts/ultra11y.mjs criteria --standard rgaa --glossary lien # a term the standard DEFINES
|
|
44
|
+
node scripts/ultra11y.mjs criteria --standard wcag --glossary "large scale" # the core defines its own terms too
|
|
43
45
|
```
|
|
44
46
|
|
|
45
47
|
An unknown `--standard` value errors out (never a silent fallback to WCAG).
|
|
46
48
|
|
|
49
|
+
**The core carries its own text, in both languages.** Each WCAG success criterion ships its
|
|
50
|
+
normative wording verbatim (exceptions and notes kept as labelled lines), the terms WCAG
|
|
51
|
+
defines, and the terms each criterion's wording links to. So `criteria 1.4.3` shows the
|
|
52
|
+
4.5:1 requirement and its three exceptions rather than only naming the criterion — the same
|
|
53
|
+
fidelity the RGAA pack has always had for its own criteria.
|
|
54
|
+
|
|
55
|
+
`--lang fr` resolves the **W3C authorized French translation** throughout: the title, the
|
|
56
|
+
requirement prose, and the glossary. There is no half-translated state where a French
|
|
57
|
+
heading sits over English requirements — the build fails rather than ship one. The two W3C
|
|
58
|
+
pages do not share definition slugs (the French page pluralizes many, and renames a few), so
|
|
59
|
+
each language keeps its own term list and its own glossary keys; a build guard rejects any
|
|
60
|
+
citation that does not resolve in its own language.
|
|
61
|
+
|
|
62
|
+
Over MCP the same data is `ultra11y_criteria` and `std://wcag/criteria/1.4.3`; see
|
|
63
|
+
`references/mcp.md`.
|
|
64
|
+
|
|
47
65
|
## Auditor vocabulary
|
|
48
66
|
|
|
49
67
|
The `prd` **auditor block** (the default output) and the **GitHub issues** it files are
|