ultra11y 4.2.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.
Files changed (48) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/.opencode/plugins/ultra11y.js +1 -1
  5. package/README.md +40 -4
  6. package/package.json +1 -1
  7. package/scripts/build-standards.mjs +290 -1
  8. package/scripts/ultra11y.mjs +4131 -786
  9. package/scripts/vendor/wcag-2.2-fr.json +945 -1
  10. package/scripts/vendor/wcag-2.2-sc-universe.json +1 -1
  11. package/scripts/vendor/wcag-2.2-text.json +749 -0
  12. package/skills/review-a11y/SKILL.md +1 -1
  13. package/skills/review-a11y/scripts/ultra11y.mjs +4131 -786
  14. package/skills/ultra11y/SKILL.md +13 -4
  15. package/skills/ultra11y/references/guidance.md +33 -7
  16. package/skills/ultra11y/references/harnesses.md +10 -0
  17. package/skills/ultra11y/references/mcp.md +215 -0
  18. package/skills/ultra11y/references/packs.md +8 -0
  19. package/skills/ultra11y/references/standards.md +18 -0
  20. package/skills/ultra11y/scripts/ultra11y.mjs +4131 -786
  21. package/src/adjudicate.ts +9 -15
  22. package/src/adjudication-data.ts +38 -0
  23. package/src/check.ts +51 -1
  24. package/src/cli.ts +6 -2
  25. package/src/config.ts +27 -4
  26. package/src/criteria-view.ts +463 -0
  27. package/src/criteria.ts +14 -11
  28. package/src/data/guidance/wcag.json +268 -0
  29. package/src/data/wcag-universe.json +1 -1
  30. package/src/data/wcag.json +1112 -55
  31. package/src/guidance/index.ts +11 -0
  32. package/src/guidance/resolve.ts +71 -0
  33. package/src/mcp/handlers.ts +160 -15
  34. package/src/mcp/prompts.ts +13 -2
  35. package/src/mcp/server.ts +18 -4
  36. package/src/mcp/standards-resources.ts +174 -0
  37. package/src/mcp/tools.ts +140 -6
  38. package/src/method-view.ts +227 -0
  39. package/src/prd.ts +5 -16
  40. package/src/standards/coverage.ts +237 -0
  41. package/src/standards/index.ts +1 -0
  42. package/src/standards/pack.ts +19 -0
  43. package/src/standards/registry.ts +115 -9
  44. package/src/types.ts +24 -1
  45. package/src/vendor/codeindex-engine.d.mts +324 -3
  46. package/src/vendor/codeindex-engine.mjs +1146 -175
  47. package/src/vendor/engine.meta.json +5 -5
  48. package/src/wcag.ts +21 -1
@@ -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.2.0
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. **The FINAL rendered semantic HTML must be correct.** The engine sees only source; a
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
- > 6. **Language**: ALWAYS pass `--lang` matching the language of your conversation with
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
- > 7. **Technical tokens stay in English, even in French prose.** In any French deliverable
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
- - **`criteria`** lookups for a pack criterion.
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? }`. The built-in RGAA
25
- guidance ships at `src/data/guidance/rgaa.json` (its entry ids mirror the SocialGouv rule
26
- files). Load external guidance with `--pack <dir>` (a `guidance.json` beside `pack.json`)
27
- or a `.ultra11yrc.json` `guidance` list. `pack check --guidance` validates that every
28
- entry resolves to a real criterion, maps to recognized WCAG SCs, and that every example
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