ultra11y 2.26.0 → 2.28.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/.agents/plugins/marketplace.json +12 -0
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +21 -0
- package/.opencode/plugins/ultra11y.js +102 -0
- package/README.md +34 -16
- package/hooks/hooks.json +1 -1
- package/hooks/pre-tool-use.mjs +19 -8
- package/package.json +6 -2
- package/scripts/sync-version.mjs +12 -4
- package/scripts/ultra11y.mjs +831 -150
- package/scripts/vendor/wcag-2.2-fr.json +1 -1
- package/scripts/vendor/wcag-2.2-sc-universe.json +1 -1
- package/scripts/verify-skill-bundle.mjs +134 -1
- package/skills/review-a11y/SKILL.md +5 -1
- package/skills/review-a11y/scripts/ultra11y.mjs +831 -150
- package/skills/ultra11y/SKILL.md +2 -1
- package/skills/ultra11y/references/automation.md +9 -4
- package/skills/ultra11y/references/harnesses.md +117 -0
- package/skills/ultra11y/scripts/ultra11y.mjs +831 -150
- package/src/cli.ts +116 -17
- package/src/data/wcag-universe.json +1 -1
- package/src/hook.ts +0 -0
- package/src/init.ts +26 -2
- package/src/install/agents-md.ts +78 -0
- package/src/install/claude-code.ts +61 -0
- package/src/install/codex.ts +166 -0
- package/src/install/index.ts +204 -0
- package/src/install/json-edit.ts +97 -0
- package/src/install/opencode.ts +90 -0
- package/src/install/paths.ts +132 -0
- package/src/install/text-edit.ts +54 -0
- package/src/types.ts +1 -1
- package/src/vendor/codeindex-engine.d.mts +3 -3
- package/src/vendor/codeindex-engine.mjs +23 -3
- package/src/vendor/engine.meta.json +5 -5
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 remediation backlog or GitHub issues; 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: 2.
|
|
7
|
+
version: 2.28.0
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# ultra11y — audit WCAG 2.2 AA and write accessible markup
|
|
@@ -84,6 +84,7 @@ Domain knowledge first, then the tooling. Read the one that matches the question
|
|
|
84
84
|
| `references/verify.md` | The `check`/`verify` gates |
|
|
85
85
|
| `references/false-positives.md` | Where a finding may still be wrong, and how to refute it |
|
|
86
86
|
| `references/rendered.md` · `references/automation.md` | Auditing produced HTML, captures, hooks and CI |
|
|
87
|
+
| `references/harnesses.md` | Where this runs: Claude Code, Codex CLI, OpenCode, and the AGENTS.md fallback |
|
|
87
88
|
| `references/ci.md` | `--format sarif\|github`: inline PR annotations, code scanning, job summary |
|
|
88
89
|
| `references/pages.md` | Page snapshots + the per-page criterion grid (`pages`), and its honesty rules |
|
|
89
90
|
| `references/e2e.md` | `render --e2e`: auditing a page during your Playwright/Cypress run |
|
|
@@ -16,21 +16,26 @@ node scripts/ultra11y.mjs init --baseline … # opt into the legacy regressio
|
|
|
16
16
|
|---|---|---|---|
|
|
17
17
|
| `init --hook` | the engine, mechanically | every `git commit` | the engine's `--fail-on` |
|
|
18
18
|
| `init --ci` | the engine, in CI | every pull request | the engine's `--fail-on` |
|
|
19
|
-
| the **
|
|
19
|
+
| the **agent-harness hook** | the `review-a11y` **skill** | a pending commit / push / PR, inside an agent session | the AI agent, adjudicating |
|
|
20
20
|
|
|
21
21
|
The first two block on what a machine can decide. The third exists because most of WCAG is
|
|
22
22
|
*judgment* — is this `alt` relevant, is this link's purpose clear — which no exit code
|
|
23
23
|
settles. See below.
|
|
24
24
|
|
|
25
|
-
## The
|
|
25
|
+
## The agent-harness hook — the agent review, unprompted
|
|
26
26
|
|
|
27
27
|
Shipped by the plugin (`hooks/hooks.json` → `hooks/pre-tool-use.mjs` → `ultra11y hook
|
|
28
|
-
--claude-code`), not by `init`.
|
|
29
|
-
for the
|
|
28
|
+
--claude-code`), not by `init`. **No** harness has a git event, so it listens on `PreToolUse`
|
|
29
|
+
for the shell tool and recognises the commands that **publish** work — `git commit` (scoped
|
|
30
30
|
to `--staged`), `git push` and `gh pr create` (scoped to `--since <default branch>`). When
|
|
31
31
|
the change carries findings at or above the threshold it returns `permissionDecision:
|
|
32
32
|
"deny"` with the findings attached, and the agent invokes `review-a11y` to adjudicate them.
|
|
33
33
|
|
|
34
|
+
The same file serves Claude Code and Codex (Codex exports `${CLAUDE_PLUGIN_ROOT}` and reads
|
|
35
|
+
the same envelope); OpenCode has no decision channel, so there the gate throws and the
|
|
36
|
+
findings arrive as the tool error. Per-harness install, deltas and off-switches:
|
|
37
|
+
**`references/harnesses.md`**.
|
|
38
|
+
|
|
34
39
|
Two invariants make it liveable:
|
|
35
40
|
|
|
36
41
|
- **It never fires twice for the same findings.** The finding set is fingerprinted per
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Where this runs — Claude Code, Codex CLI, OpenCode, and everything else
|
|
2
|
+
|
|
3
|
+
The skills speak in **actions** — run the engine, invoke the review skill, adjudicate the
|
|
4
|
+
findings. On each harness those resolve as below. Only the **deltas** are listed; anything
|
|
5
|
+
not mentioned here is identical everywhere, because the engine is one zero-dependency
|
|
6
|
+
bundle and the CLI it exposes is the same on all of them.
|
|
7
|
+
|
|
8
|
+
Two things are worth knowing before the table:
|
|
9
|
+
|
|
10
|
+
- **No harness has a git event.** None of them can hook "about to commit". So the automatic
|
|
11
|
+
review rides the *shell tool* on every one of them, recognising the commands that publish
|
|
12
|
+
work — `git commit`, `git push`, `gh pr create`. That is a deliberate design constraint,
|
|
13
|
+
not a Claude Code quirk.
|
|
14
|
+
- **A hook cannot force a skill to be invoked.** It blocks the command and hands over the
|
|
15
|
+
reason and the findings; the agent is what invokes `review-a11y`. In practice a motivated
|
|
16
|
+
block is enough — it is not a guarantee, on any harness.
|
|
17
|
+
|
|
18
|
+
## Claude Code
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
/plugin marketplace add maxgfr/ultra11y
|
|
22
|
+
/plugin install ultra11y@ultra11y
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The plugin carries both skills *and* the hook. `hooks/hooks.json` → `hooks/pre-tool-use.mjs`
|
|
26
|
+
→ `ultra11y hook --claude-code`. The engine resolves from `${CLAUDE_SKILL_DIR}/scripts/ultra11y.mjs`.
|
|
27
|
+
|
|
28
|
+
The review arrives as `permissionDecision: "deny"` on the pending command, with the findings
|
|
29
|
+
in `additionalContext`.
|
|
30
|
+
|
|
31
|
+
Skills only, no hook: `npx skills add maxgfr/ultra11y`. Gate only, for an npm install:
|
|
32
|
+
`ultra11y install --claude-code`.
|
|
33
|
+
|
|
34
|
+
## OpenAI Codex CLI
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
codex plugin marketplace add maxgfr/ultra11y
|
|
38
|
+
codex plugin add ultra11y@ultra11y
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Codex's hook engine is a near-clone of Claude Code's — same events, same payload fields,
|
|
42
|
+
same `hookSpecificOutput` envelope — and it exports `${CLAUDE_PLUGIN_ROOT}` alongside its own
|
|
43
|
+
`${PLUGIN_ROOT}`, so **`hooks/hooks.json` is shared verbatim** between the two.
|
|
44
|
+
|
|
45
|
+
The deltas that actually matter:
|
|
46
|
+
|
|
47
|
+
- Its shell tool is **`shell`**, not `Bash`, and its `command` is an **argv array**
|
|
48
|
+
(`["bash","-lc","git commit -m x"]`). `commandOf` in `src/hook.ts` extracts the script
|
|
49
|
+
argument rather than joining the array — joining would put `git` off a command position
|
|
50
|
+
and the gate would silently never fire.
|
|
51
|
+
- On `PreToolUse` Codex accepts **only** `permissionDecision: "deny"`, with a non-empty
|
|
52
|
+
reason. That is exactly and only what this engine emits, so the envelope needs no branch.
|
|
53
|
+
- `.codex-plugin/plugin.json` must not declare `hooks` — Codex's manifest validator rejects
|
|
54
|
+
any key outside its allowlist. `hooks/hooks.json` is found by convention at the plugin root.
|
|
55
|
+
- Hooks are behind a feature flag: **`[features] hooks = true`** in `~/.codex/config.toml`.
|
|
56
|
+
- Codex asks you to **trust** a hook command the first time it fires. Accept it, or review
|
|
57
|
+
it with `/hooks`.
|
|
58
|
+
|
|
59
|
+
Gate only, without the marketplace: `ultra11y install --codex` (it sets the feature flag and
|
|
60
|
+
copies both skills into `~/.codex/skills/`).
|
|
61
|
+
|
|
62
|
+
## OpenCode
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
ultra11y install --opencode
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
…or pin it in `~/.config/opencode/opencode.json`: `"plugin": ["ultra11y@latest"]`.
|
|
69
|
+
|
|
70
|
+
The delta: OpenCode has **no permission-decision channel**. Its plugin blocks a tool call by
|
|
71
|
+
throwing, so the review arrives as a **failed bash call whose error message carries the
|
|
72
|
+
findings**. Same content, different envelope — read the error, do not retry blindly.
|
|
73
|
+
|
|
74
|
+
Skills live under `~/.config/opencode/skills/`; the plugin also registers the bundled
|
|
75
|
+
`skills/` directory via `config.skills.paths`.
|
|
76
|
+
|
|
77
|
+
## Everything else (Cursor, Amp, Zed, Gemini CLI, Windsurf, aider…)
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
ultra11y install --agents-md
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Writes a managed block into the repository's `AGENTS.md`. Be clear-eyed about what that is:
|
|
84
|
+
there is no hook API, so **nothing is automatic**. The block makes the engine discoverable
|
|
85
|
+
and hands over the adjudication protocol. What actually enforces anything on these harnesses
|
|
86
|
+
is the repo's own gate — `ultra11y init --hook` (git pre-commit) and `ultra11y init --ci`.
|
|
87
|
+
|
|
88
|
+
There is also **MCP**, which carries the method where nothing else does — `SKILL.md` and
|
|
89
|
+
every `references/*.md` are exposed as `skill://` resources, plus three prompts
|
|
90
|
+
(`audit_wcag`, `adjudicate_criteria`, `review_diff_a11y`):
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
claude mcp add ultra11y -- npx -y ultra11y mcp
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
On a harness with no skill system at all, **reading `SKILL.md` directly with the file-read
|
|
97
|
+
tool is the blessed path**, not a workaround. Discover what exists by listing
|
|
98
|
+
`skills/*/SKILL.md` and reading the frontmatter.
|
|
99
|
+
|
|
100
|
+
## The matrix
|
|
101
|
+
|
|
102
|
+
| | skills | automatic review | how it blocks | MCP | repo gate |
|
|
103
|
+
|---|---|---|---|---|---|
|
|
104
|
+
| Claude Code | plugin / `skills add` | yes | `permissionDecision: "deny"` | yes | yes |
|
|
105
|
+
| Codex CLI | plugin / `skills add` | yes | `permissionDecision: "deny"` | yes | yes |
|
|
106
|
+
| OpenCode | plugin / `skills add` | yes | thrown tool error | yes | yes |
|
|
107
|
+
| Cursor, Amp, Zed, Gemini… | AGENTS.md | **no** | — | yes | yes |
|
|
108
|
+
|
|
109
|
+
`ultra11y status` reports which of these are actually wired on this machine — including the
|
|
110
|
+
one silent failure worth naming, a Codex hook sitting behind a disabled feature flag.
|
|
111
|
+
|
|
112
|
+
## Off-switches (identical everywhere)
|
|
113
|
+
|
|
114
|
+
They live in the engine, not in any harness, so one answer covers all of them:
|
|
115
|
+
`ULTRA11Y_HOOK_FAIL_ON=blocking|major|minor|off` (env, wins), then
|
|
116
|
+
`"hook": { "failOn": … }` in `.ultra11yrc.json`, else `blocking`. `SKIP_A11Y=1` bypasses
|
|
117
|
+
once; `ULTRA11Y_HOOK=off` disables the gate for the session.
|