ultra11y 5.28.0 → 5.30.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.
@@ -10,7 +10,7 @@
10
10
  "name": "ultra11y",
11
11
  "source": "./",
12
12
  "description": "Automatic accessibility review of the code under change before every commit, push and pull request, plus full WCAG 2.2 AA / RGAA audits and conformance deliverables on demand.",
13
- "version": "5.28.0",
13
+ "version": "5.30.0",
14
14
  "author": { "name": "maxgfr" },
15
15
  "homepage": "https://github.com/maxgfr/ultra11y",
16
16
  "repository": "https://github.com/maxgfr/ultra11y",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ultra11y",
3
3
  "description": "Accessibility for WCAG 2.2 AA and country standards (RGAA…): an automatic review of the code under change before every commit, push and pull request, plus full audits and conformance deliverables on demand.",
4
- "version": "5.28.0",
4
+ "version": "5.30.0",
5
5
  "author": { "name": "maxgfr" },
6
6
  "homepage": "https://github.com/maxgfr/ultra11y",
7
7
  "repository": "https://github.com/maxgfr/ultra11y",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ultra11y",
3
3
  "description": "Accessibility for WCAG 2.2 AA and country standards (RGAA…): an automatic review of the code under change before every commit, push and pull request, plus full audits and conformance deliverables on demand.",
4
- "version": "5.28.0",
4
+ "version": "5.30.0",
5
5
  "author": { "name": "maxgfr", "url": "https://github.com/maxgfr" },
6
6
  "homepage": "https://github.com/maxgfr/ultra11y",
7
7
  "repository": "https://github.com/maxgfr/ultra11y",
@@ -27,7 +27,7 @@ import { fileURLToPath } from "node:url";
27
27
  // Ownership marker: `ultra11y install --opencode` refuses to overwrite a plugin file that
28
28
  // does not carry it, so a user's own ultra11y.js is never clobbered.
29
29
  const ULTRA11Y_OPENCODE_PLUGIN = "ULTRA11Y_OPENCODE_PLUGIN";
30
- const ULTRA11Y_PLUGIN_VERSION = "5.28.0";
30
+ const ULTRA11Y_PLUGIN_VERSION = "5.30.0";
31
31
 
32
32
  const here = dirname(fileURLToPath(import.meta.url));
33
33
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ultra11y",
3
- "version": "5.28.0",
3
+ "version": "5.30.0",
4
4
  "description": "Audit HTML/CSS/JSX against WCAG 2.2 AA and produce a dated compliance report, or author/review accessible markup (native-HTML-first). A skills.sh agent skill: an install-free static engine (bundled, no npm install) plus the agent's judgment, with check/verify gates against hallucinated non-conformities, and pluggable in-repo standards packs (RGAA France first; Section 508 & EN 301 549 next).",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.33.0",
@@ -57,6 +57,7 @@
57
57
  "verify:bundle": "node scripts/verify-skill-bundle.mjs",
58
58
  "check:build": "tsup && node scripts/copy-bundle.mjs && git diff --exit-code -- scripts/ultra11y.mjs skills/ultra11y/scripts/ultra11y.mjs skills/review-a11y/scripts/ultra11y.mjs dist && node scripts/build-extension-icons.mjs --check && node scripts/verify-skill-bundle.mjs && node scripts/sync-engine.mjs --check",
59
59
  "build:wcag": "node scripts/build-standards.mjs",
60
+ "check:standards": "node scripts/build-standards.mjs --check",
60
61
  "build:pack:rgaa": "node scripts/build-pack-rgaa.mjs",
61
62
  "check:pack:rgaa": "node scripts/build-pack-rgaa.mjs --check",
62
63
  "build:guidance:wcag": "node scripts/build-guidance-wcag.mjs",
@@ -42,6 +42,29 @@ function biomeFormat(text, relPath) {
42
42
  return execFileSync(BIOME, ["format", `--stdin-file-path=${relPath}`], { input: text, encoding: "utf8" });
43
43
  }
44
44
 
45
+ // CHECK MODE — the gate this generator was the only one of the three to lack.
46
+ //
47
+ // scripts/build-pack-rgaa.mjs and scripts/build-guidance-wcag.mjs both compare their
48
+ // generated text to the committed file and exit 1 on drift; this one only ever wrote. So a
49
+ // hand edit to src/data/wcag.json passed every gate and was found by the NIGHTLY refresh
50
+ // instead — on main, a day later, in a workflow nobody watches. Measured: SC 1.3.1 carried
51
+ // three presentational-* rules that RULE_SC_COVERAGE below never cited, and
52
+ // standards-refresh went red every night for two days before anyone read the log.
53
+ //
54
+ // Every write goes through `emit` so the check compares EXACTLY what a build would write —
55
+ // a check that recomputed the text a second way could agree with itself and still be wrong.
56
+ const CHECK = process.argv.includes("--check");
57
+ const drift = [];
58
+ function emit(relPath, text) {
59
+ const abs = join(root, relPath);
60
+ if (CHECK) {
61
+ if (!existsSync(abs) || readFileSync(abs, "utf8") !== text) drift.push(relPath);
62
+ return;
63
+ }
64
+ mkdirSync(dirname(abs), { recursive: true });
65
+ writeFileSync(abs, text);
66
+ }
67
+
45
68
  // ---------------------------------------------------------------------------
46
69
  // Refresh mode: parse a w3c/wcag checkout into the vendored SC snapshot.
47
70
  // SC numbers are positional within guidelines/index.html (principle → guideline →
@@ -623,6 +646,7 @@ const RULE_SC_COVERAGE = {
623
646
  "sortable-header-no-aria-sort", "nav-landmark-missing", "nav-landmark-unnamed", "aria-required-parent",
624
647
  "headers-attr-dangling", "th-no-data-cells",
625
648
  "radio-checkbox-group-ungrouped", "table-empty-data-cell", "css-generated-content-informative",
649
+ "presentational-element", "presentational-attribute", "presentational-spacing",
626
650
  ],
627
651
  "1.3.5": ["field-purpose-incomplete", "autocomplete-token-invalid"],
628
652
  "1.4.2": ["autoplay-media"],
@@ -708,8 +732,7 @@ function buildUniverse(shipped) {
708
732
  provenance: univ.provenance,
709
733
  criteria,
710
734
  };
711
- mkdirSync(DATA, { recursive: true });
712
- writeFileSync(join(DATA, "wcag-universe.json"), biomeFormat(JSON.stringify(out, null, 2) + "\n", "src/data/wcag-universe.json"));
735
+ emit("src/data/wcag-universe.json", biomeFormat(JSON.stringify(out, null, 2) + "\n", "src/data/wcag-universe.json"));
713
736
 
714
737
  const coreIds = new Set(criteria.filter((c) => c.status === "core-AA").map((c) => c.id));
715
738
  const shippedIds = new Set(shipped.map((c) => c.sc));
@@ -724,6 +747,7 @@ function buildUniverse(shipped) {
724
747
  }
725
748
  const tally = { "core-AA": 0, "out-of-core": 0, removed: 0 };
726
749
  for (const c of criteria) tally[c.status]++;
750
+ if (CHECK) return;
727
751
  console.log(
728
752
  `build-standards: ${criteria.length} WCAG 2.x SCs classified — core-AA ${tally["core-AA"]}, out-of-core ${tally["out-of-core"]}, removed ${tally.removed} → src/data/wcag-universe.json`,
729
753
  );
@@ -839,8 +863,7 @@ function build() {
839
863
  // resolve in either language off one list.
840
864
  glossaryFr: frGlossary,
841
865
  };
842
- mkdirSync(DATA, { recursive: true });
843
- writeFileSync(join(DATA, "wcag.json"), biomeFormat(JSON.stringify(out, null, 2) + "\n", "src/data/wcag.json"));
866
+ emit("src/data/wcag.json", biomeFormat(JSON.stringify(out, null, 2) + "\n", "src/data/wcag.json"));
844
867
 
845
868
  // --- guards
846
869
  const all = new Set(criteria.map((c) => c.sc));
@@ -863,6 +886,7 @@ function build() {
863
886
 
864
887
  const tally = { static: 0, "needs-rendering": 0, judgment: 0 };
865
888
  for (const c of criteria) tally[c.automatability]++;
889
+ if (CHECK) return void buildUniverse(criteria);
866
890
  console.log(`build-standards: ${criteria.length} WCAG 2.2 A/AA criteria → src/data/wcag.json`);
867
891
  console.log(`build-standards: automatability — static ${tally.static}, needs-rendering ${tally["needs-rendering"]}, judgment ${tally.judgment}`);
868
892
  console.log(`build-standards: seeded techniques from ${sources.length ? sources.map((s) => s.replace(root + "/", "")).join(", ") : "(no pack found — empty)"}`);
@@ -872,12 +896,26 @@ function build() {
872
896
 
873
897
  async function main() {
874
898
  const refreshIdx = process.argv.indexOf("--refresh");
899
+ // A check that first goes and fetches is not a check: it would compare the committed
900
+ // dataset against a source that moved under it, and call an upstream change a local drift.
901
+ // `--check` reads the vendored snapshots and nothing else.
902
+ const refreshing = refreshIdx !== -1 || process.argv.some((a) => a.startsWith("--refresh-"));
903
+ if (CHECK && refreshing) {
904
+ console.error("build-standards --check: --check is offline by construction; it cannot be combined with a --refresh flag.");
905
+ process.exit(1);
906
+ }
875
907
  if (refreshIdx !== -1) deriveSnapshot(process.argv[refreshIdx + 1]);
876
908
  if (process.argv.includes("--refresh-universe")) await deriveUniverse();
877
909
  if (process.argv.includes("--refresh-core")) refreshCore();
878
910
  if (process.argv.includes("--refresh-fr")) await deriveFr();
879
911
  if (process.argv.includes("--refresh-text")) await deriveText();
880
912
  build();
913
+ if (!CHECK) return;
914
+ if (drift.length) {
915
+ console.error(`build-standards --check: OUT OF DATE vs the vendored source — re-run \`pnpm run build:wcag\`: ${drift.join(", ")}`);
916
+ process.exit(1);
917
+ }
918
+ console.log("build-standards --check: src/data/wcag.json and src/data/wcag-universe.json match the vendored source.");
881
919
  }
882
920
 
883
921
  main().catch((e) => {