@adia-ai/a2ui-validator 0.7.26 → 0.7.28

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/CHANGELOG.md CHANGED
@@ -1,4 +1,14 @@
1
1
  # Changelog — @adia-ai/a2ui-validator
2
+ ## [0.7.28] — 2026-07-14
3
+
4
+ ### Maintenance
5
+ - **Lockstep version bump only.** No source changes in this package; bumped to maintain the 9-package version coherence enforced by `scripts/release/check-lockstep.mjs`. Substantive v0.7.28 work shipped in Chunk-zettel emits real component graphs (TKT-0009) + corpus admission-validation classes 1/3 fixed (TKT-0010) — see @adia-ai/a2ui-compose, @adia-ai/a2ui-corpus, @adia-ai/web-components CHANGELOGs. See `packages/a2ui/compose/CHANGELOG.md#0728--2026-07-14` for details.
6
+
7
+ ## [0.7.27] — 2026-07-12
8
+
9
+ ### Fixed
10
+ - **`interactiveHasLabel` accepts `aria-label` as an accessible name (TKT-0003).** The check only accepted `text`/`label`/`textContent`, which forced upstream transpilers to satisfy it by setting the VISIBLE `label` prop on controls already labelled by their wrapping `Field` — and the form controls render that attribute, so every transpiled form showed its labels twice. An `aria-label` is an accessible name; a Field-wrapped control needs no second visible one.
11
+ - **`noBareDivs` no longer hard-fails documents containing registered `Nav`/`Table` constructs.** The bare-HTML-type collision check lowercased registered A2UI type names onto the bare-tag set, so every document with a legitimate `Nav` or `Table` component could never validate. Registered types are now exempt.
2
12
 
3
13
  ## [0.7.26] — 2026-07-04
4
14
 
package/README.md CHANGED
@@ -97,6 +97,6 @@ score) and sum to 13: `wiringControllersExist` (3), `wiringHostsExist`
97
97
  ## Related
98
98
 
99
99
  - Spec: [`.claude/docs/specs/semantic-validator.md`](../../../.claude/docs/specs/semantic-validator.md) — canonical design narrative
100
- - Audit: [`.claude/docs/reports/audit-validator-2026-05-06.md`](../../../.claude/docs/reports/audit-validator-2026-05-06.md) — 226-line deep-dive with check-by-check rationale + recalibration notes
100
+ - Audit: `.claude/docs/reports/audit-validator-2026-05-06.md` — 226-line deep-dive with check-by-check rationale + recalibration notes
101
101
  - Repo: [`adiahealth/gen-ui-kit`](https://github.com/adiahealth/gen-ui-kit)
102
102
  - CHANGELOG: [`CHANGELOG.md`](./CHANGELOG.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adia-ai/a2ui-validator",
3
- "version": "0.7.26",
3
+ "version": "0.7.28",
4
4
  "description": "AdiaUI A2UI validator \u2014 JSON Schema structural validation plus catalog-aware semantic validation (component exists, props match YAML). Split out from the compose engine so non-compose tooling (tests, MCP validator tools, CI gates) can depend on validation without pulling the whole generator graph.",
5
5
  "type": "module",
6
6
  "main": "./index.js",
package/validator.js CHANGED
@@ -352,6 +352,10 @@ function checkNoBareDivs(components) {
352
352
  for (const comp of components) {
353
353
  const type = comp.component;
354
354
  if (!type) continue;
355
+ // Registered A2UI types are exempt: the lowercase collision used to
356
+ // hard-fail every document containing the legitimate `Nav` or `Table`
357
+ // constructs (they lowercase onto the bare-HTML set).
358
+ if (registry.has(type)) continue;
355
359
  if (bareTypes.has(type.toLowerCase())) {
356
360
  offenders.push(`"${type}" (id: ${comp.id})`);
357
361
  }
@@ -481,7 +485,13 @@ function checkIdUniqueness(components) {
481
485
  }
482
486
 
483
487
  /**
484
- * 12. interactiveHasLabel — interactive components must have a text, label, or textContent property.
488
+ * 12. interactiveHasLabel — interactive components must carry an
489
+ * accessible name: text, label, textContent, or aria-label. aria-label
490
+ * joined 2026-07-12 (TKT-0003): rejecting it forced the docs-transpiler
491
+ * to propagate a VISIBLE `label` onto controls already labelled by their
492
+ * wrapping Field — every transpiled form rendered its labels twice
493
+ * ("Workspace name Workspace name"). An aria-label IS an accessible
494
+ * name; a control inside a labelled Field needs no second visible one.
485
495
  */
486
496
  function checkInteractiveHasLabel(components) {
487
497
  const interactiveTypes = new Set(['Button', 'TextField', 'Select', 'Toggle', 'Check', 'Slider', 'Search']);
@@ -489,7 +499,8 @@ function checkInteractiveHasLabel(components) {
489
499
 
490
500
  for (const comp of components) {
491
501
  if (!interactiveTypes.has(comp.component)) continue;
492
- const hasLabel = comp.text != null || comp.label != null || comp.textContent != null;
502
+ const hasLabel = comp.text != null || comp.label != null || comp.textContent != null
503
+ || comp['aria-label'] != null;
493
504
  if (!hasLabel) {
494
505
  unlabeled.push(`"${comp.id}"`);
495
506
  }