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.
Files changed (36) hide show
  1. package/.agents/plugins/marketplace.json +12 -0
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/.claude-plugin/plugin.json +1 -1
  4. package/.codex-plugin/plugin.json +21 -0
  5. package/.opencode/plugins/ultra11y.js +102 -0
  6. package/README.md +34 -16
  7. package/hooks/hooks.json +1 -1
  8. package/hooks/pre-tool-use.mjs +19 -8
  9. package/package.json +6 -2
  10. package/scripts/sync-version.mjs +12 -4
  11. package/scripts/ultra11y.mjs +831 -150
  12. package/scripts/vendor/wcag-2.2-fr.json +1 -1
  13. package/scripts/vendor/wcag-2.2-sc-universe.json +1 -1
  14. package/scripts/verify-skill-bundle.mjs +134 -1
  15. package/skills/review-a11y/SKILL.md +5 -1
  16. package/skills/review-a11y/scripts/ultra11y.mjs +831 -150
  17. package/skills/ultra11y/SKILL.md +2 -1
  18. package/skills/ultra11y/references/automation.md +9 -4
  19. package/skills/ultra11y/references/harnesses.md +117 -0
  20. package/skills/ultra11y/scripts/ultra11y.mjs +831 -150
  21. package/src/cli.ts +116 -17
  22. package/src/data/wcag-universe.json +1 -1
  23. package/src/hook.ts +0 -0
  24. package/src/init.ts +26 -2
  25. package/src/install/agents-md.ts +78 -0
  26. package/src/install/claude-code.ts +61 -0
  27. package/src/install/codex.ts +166 -0
  28. package/src/install/index.ts +204 -0
  29. package/src/install/json-edit.ts +97 -0
  30. package/src/install/opencode.ts +90 -0
  31. package/src/install/paths.ts +132 -0
  32. package/src/install/text-edit.ts +54 -0
  33. package/src/types.ts +1 -1
  34. package/src/vendor/codeindex-engine.d.mts +3 -3
  35. package/src/vendor/codeindex-engine.mjs +23 -3
  36. package/src/vendor/engine.meta.json +5 -5
@@ -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.26.0
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 **Claude Code plugin hook** | the `review-a11y` **skill** | a pending commit / push / PR, inside an agent session | the AI agent, adjudicating |
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 Claude Code plugin hook — the agent review, unprompted
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`. Claude Code has no git event, so it listens on `PreToolUse`
29
- for the Bash tool and recognises the commands that **publish** work — `git commit` (scoped
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.