ultra11y 2.25.0 → 2.26.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/src/cli.ts CHANGED
@@ -3,6 +3,7 @@ import { join, relative, sep, dirname } from "node:path";
3
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
4
  import { VERSION, type Lang, type AuditResult, type DynamicResult, type SampleConfig, type Severity } from "./types.js";
5
5
  import { runAudit } from "./audit.js";
6
+ import { decide, type PreToolUsePayload } from "./hook.js";
6
7
  import { writeReport, untestedNeedsRendering, partialAuditBanner } from "./report.js";
7
8
  import { writePrd, prdUnits, type PrdFormat } from "./prd.js";
8
9
  import { ghAvailable, pushIssues, pushPrComment, pushSingleIssue } from "./gh.js";
@@ -81,6 +82,7 @@ Usage:
81
82
  ultra11y snapshot list [--root <dir>] [--json]
82
83
  ultra11y pages --in <audit.json> [--standard <pack>] [--json] [--lang auto|en|fr] (the per-page criterion grid)
83
84
  ultra11y mcp [--transport stdio|http] [--cwd <dir>] [--allow-write] [--port <n>] [--bind <addr>] [--allow-remote] [--allow-origin <o>] [--max-response-bytes <n>]
85
+ ultra11y hook --claude-code (internal: the plugin's PreToolUse hook; payload on stdin)
84
86
  ultra11y dev [--port <n>] [--root <dir>] [--standard <pack>] [--lang auto|en|fr] (dev side-car: live overlay + per-page dashboard)
85
87
  ultra11y dev --next [--port <n>] (write the Next overlay component, then wire one line into your layout)
86
88
 
@@ -221,6 +223,13 @@ Commands:
221
223
  --transport http listens on 127.0.0.1 (--port, --bind), and stays
222
224
  loopback-only unless you pass --allow-remote. Read-only by default:
223
225
  --allow-write opts into the commands that touch files.
226
+ hook INTERNAL — the decision half of the Claude Code plugin's PreToolUse
227
+ hook. Reads the payload on stdin; when a pending 'git commit', 'git
228
+ push' or 'gh pr create' carries findings >= the threshold, prints the
229
+ hook JSON that gets the review-a11y skill invoked, and prints nothing
230
+ otherwise. Threshold: ULTRA11Y_HOOK_FAIL_ON, else hook.failOn in
231
+ .ultra11yrc.json, else blocking. Disable with ULTRA11Y_HOOK=off or
232
+ SKIP_A11Y=1. Called by hooks/pre-tool-use.mjs, not by hand.
224
233
  pages The per-page criterion grid — RGAA is a per-page norm, the engine's
225
234
  verdict is scope-wide, and this bridges the two. One row per criterion
226
235
  (the pack's own under --standard), one column per page. Rebuilt from a
@@ -376,6 +385,7 @@ const COMMANDS = [
376
385
  "init",
377
386
  "pack",
378
387
  "orchestrate",
388
+ "hook",
379
389
  ] as const;
380
390
  type Command = (typeof COMMANDS)[number];
381
391
 
@@ -1079,6 +1089,25 @@ function cmdInit(p: ParsedArgs): number {
1079
1089
  return 0;
1080
1090
  }
1081
1091
 
1092
+ /** `hook --claude-code` — the decision half of the plugin's PreToolUse hook. Reads the
1093
+ * payload on stdin, prints the hook JSON when the pending commit/push/PR should get an
1094
+ * accessibility review first, and prints NOTHING otherwise. Not meant to be run by hand:
1095
+ * `hooks/pre-tool-use.mjs` is what Claude Code calls, and it only reaches here once its
1096
+ * cheap prefilter has passed. Always exits 0 — see src/hook.ts for why. */
1097
+ async function cmdHook(p: ParsedArgs): Promise<number> {
1098
+ if (p.flags["claude-code"] !== true) {
1099
+ console.error("ultra11y hook: expected `hook --claude-code` (the payload is read on stdin).");
1100
+ return 2;
1101
+ }
1102
+ try {
1103
+ const decision = decide(JSON.parse(await readStdin()) as PreToolUsePayload);
1104
+ if (decision) process.stdout.write(JSON.stringify(decision));
1105
+ } catch {
1106
+ /* unreadable payload, engine failure — stay silent rather than break a git flow */
1107
+ }
1108
+ return 0;
1109
+ }
1110
+
1082
1111
  function cmdCriteria(p: ParsedArgs): number {
1083
1112
  // --generate: emit the bundled WCAG references/criteria.md (no trailing newline; the
1084
1113
  // shell redirect / committed file owns that). Used by `pnpm run build:criteria`.
@@ -2359,6 +2388,8 @@ export async function main(argv: string[]): Promise<number> {
2359
2388
  return cmdOrchestrate(p);
2360
2389
  case "mcp":
2361
2390
  return cmdMcp(p);
2391
+ case "hook":
2392
+ return cmdHook(p);
2362
2393
  default:
2363
2394
  console.error(`ultra11y: "${p.command}" is not implemented yet`);
2364
2395
  return 1;
package/src/config.ts CHANGED
@@ -31,6 +31,10 @@ export interface Ultra11yConfig {
31
31
  // `note`. Applied AFTER packs are registered (registry.enableSecondaryMapping): a pack
32
32
  // ships the mapping DISABLED; this flips it on (or appends a new enabled one).
33
33
  secondaryMappings?: Array<{ standard: string; ruleId: string; criterion: string; note?: LocaleString }>;
34
+ // The Claude Code PreToolUse hook (src/hook.ts), shipped by the plugin. `failOn` is the
35
+ // severity at which a pending commit/push/PR asks the agent for a11y review; "off"
36
+ // disables the hook for this repo. Absent ⇒ "blocking", matching `init --hook`.
37
+ hook?: { failOn?: string };
34
38
  }
35
39
 
36
40
  export interface LoadResult {
package/src/hook.ts ADDED
Binary file
package/src/types.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  // Single source of truth for shared types + the embedded version. sync-version.mjs
2
2
  // rewrites VERSION at release time (kept in lockstep with package.json + SKILL.md).
3
- export const VERSION = "2.25.0";
3
+ export const VERSION = "2.26.0";
4
4
  export const SCHEMA_VERSION = 2;
5
5
 
6
6
  // Lang = the UI FRAME's language — the `L` localization tables each module (report,