@verndale/accessibility-standards 2.0.0 → 3.0.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 (165) hide show
  1. package/OPERATING.md +1 -1
  2. package/README.md +1 -1
  3. package/dist/manifest.json +156 -116
  4. package/dist/profiles/ai-orchestration/coverage-manifest.json +702 -153
  5. package/dist/profiles/ai-orchestration/implementation/accessibility.md +523 -42
  6. package/dist/profiles/ai-orchestration/pattern-contracts.json +892 -306
  7. package/dist/profiles/ai-orchestration/patterns/accordion.md +6 -1
  8. package/dist/profiles/ai-orchestration/patterns/alert.md +6 -1
  9. package/dist/profiles/ai-orchestration/patterns/carousel.md +6 -1
  10. package/dist/profiles/ai-orchestration/patterns/checkbox.md +27 -0
  11. package/dist/profiles/ai-orchestration/patterns/combobox.md +6 -1
  12. package/dist/profiles/ai-orchestration/patterns/consequential-submission.md +8 -3
  13. package/dist/profiles/ai-orchestration/patterns/dialog.md +6 -1
  14. package/dist/profiles/ai-orchestration/patterns/disclosure.md +6 -1
  15. package/dist/profiles/ai-orchestration/patterns/dynamic-status.md +6 -1
  16. package/dist/profiles/ai-orchestration/patterns/field.md +7 -1
  17. package/dist/profiles/ai-orchestration/patterns/image.md +6 -1
  18. package/dist/profiles/ai-orchestration/patterns/listbox.md +6 -1
  19. package/dist/profiles/ai-orchestration/patterns/media-player.md +9 -1
  20. package/dist/profiles/ai-orchestration/patterns/menu-button.md +6 -1
  21. package/dist/profiles/ai-orchestration/patterns/menu.md +30 -0
  22. package/dist/profiles/ai-orchestration/patterns/pagination.md +6 -1
  23. package/dist/profiles/ai-orchestration/patterns/popover.md +7 -1
  24. package/dist/profiles/ai-orchestration/patterns/progress.md +7 -1
  25. package/dist/profiles/ai-orchestration/patterns/radio-group.md +27 -0
  26. package/dist/profiles/ai-orchestration/patterns/slider.md +31 -0
  27. package/dist/profiles/ai-orchestration/patterns/spinbutton.md +28 -0
  28. package/dist/profiles/ai-orchestration/patterns/tabs.md +6 -1
  29. package/dist/profiles/ai-orchestration/patterns/tooltip.md +6 -1
  30. package/dist/profiles/ai-orchestration/patterns/tree-view.md +31 -0
  31. package/dist/profiles/ai-orchestration/patterns/validation.md +7 -1
  32. package/dist/profiles/ai-orchestration/review/accessibility.md +14 -6
  33. package/dist/profiles/ai-orchestration/semantics/accessible-authentication.md +13 -0
  34. package/dist/profiles/ai-orchestration/semantics/accessible-name.md +8 -2
  35. package/dist/profiles/ai-orchestration/semantics/alert.md +7 -1
  36. package/dist/profiles/ai-orchestration/semantics/consequential-action.md +6 -2
  37. package/dist/profiles/ai-orchestration/semantics/consistent-help.md +13 -0
  38. package/dist/profiles/ai-orchestration/semantics/data-table.md +7 -2
  39. package/dist/profiles/ai-orchestration/semantics/dragging-alternative.md +13 -0
  40. package/dist/profiles/ai-orchestration/semantics/expanded-state.md +6 -1
  41. package/dist/profiles/ai-orchestration/semantics/focus.initial.md +4 -1
  42. package/dist/profiles/ai-orchestration/semantics/focus.return.md +4 -1
  43. package/dist/profiles/ai-orchestration/semantics/focus.visible.md +8 -2
  44. package/dist/profiles/ai-orchestration/semantics/form-error.md +8 -2
  45. package/dist/profiles/ai-orchestration/semantics/form-label.md +7 -1
  46. package/dist/profiles/ai-orchestration/semantics/form-required.md +7 -1
  47. package/dist/profiles/ai-orchestration/semantics/headings.md +7 -1
  48. package/dist/profiles/ai-orchestration/semantics/keyboard.escape.md +4 -1
  49. package/dist/profiles/ai-orchestration/semantics/keyboard.md +7 -1
  50. package/dist/profiles/ai-orchestration/semantics/landmarks.md +6 -1
  51. package/dist/profiles/ai-orchestration/semantics/live-status.md +7 -2
  52. package/dist/profiles/ai-orchestration/semantics/media-alternatives.md +11 -1
  53. package/dist/profiles/ai-orchestration/semantics/motion-control.md +8 -2
  54. package/dist/profiles/ai-orchestration/semantics/name-role-value.md +6 -2
  55. package/dist/profiles/ai-orchestration/semantics/native-dialog.md +7 -1
  56. package/dist/profiles/ai-orchestration/semantics/native-elements.md +5 -1
  57. package/dist/profiles/ai-orchestration/semantics/non-text-alternative.md +5 -1
  58. package/dist/profiles/ai-orchestration/semantics/redundant-entry.md +13 -0
  59. package/dist/profiles/ai-orchestration/semantics/roles-states-properties.md +6 -1
  60. package/dist/profiles/ai-orchestration/semantics/selected-state.md +6 -1
  61. package/dist/profiles/ai-orchestration/semantics/target-size.md +6 -2
  62. package/dist/profiles/ai-orchestration/semantics.json +826 -130
  63. package/dist/profiles/ai-orchestration/testing/accessibility.md +33 -3
  64. package/dist/profiles/ai-orchestration/ui-design-brain-bindings.json +287 -307
  65. package/dist/profiles/conductor/a11y-semantics.md +249 -10
  66. package/dist/profiles/conductor/accessibility-quality.md +275 -33
  67. package/dist/profiles/conductor/applicability-matrix.json +226 -269
  68. package/dist/profiles/conductor/coverage-manifest.json +702 -153
  69. package/dist/profiles/conductor/pattern-contracts.json +892 -306
  70. package/dist/profiles/conductor/patterns/accordion.json +35 -27
  71. package/dist/profiles/conductor/patterns/alert.json +29 -21
  72. package/dist/profiles/conductor/patterns/carousel.json +36 -28
  73. package/dist/profiles/conductor/patterns/checkbox.json +67 -0
  74. package/dist/profiles/conductor/patterns/combobox.json +37 -29
  75. package/dist/profiles/conductor/patterns/consequential-submission.json +34 -25
  76. package/dist/profiles/conductor/patterns/dialog.json +37 -29
  77. package/dist/profiles/conductor/patterns/disclosure.json +33 -25
  78. package/dist/profiles/conductor/patterns/dynamic-status.json +31 -22
  79. package/dist/profiles/conductor/patterns/field.json +41 -25
  80. package/dist/profiles/conductor/patterns/image.json +31 -22
  81. package/dist/profiles/conductor/patterns/listbox.json +35 -27
  82. package/dist/profiles/conductor/patterns/media-player.json +59 -29
  83. package/dist/profiles/conductor/patterns/menu-button.json +34 -26
  84. package/dist/profiles/conductor/patterns/menu.json +78 -0
  85. package/dist/profiles/conductor/patterns/pagination.json +34 -25
  86. package/dist/profiles/conductor/patterns/popover.json +42 -26
  87. package/dist/profiles/conductor/patterns/progress.json +38 -23
  88. package/dist/profiles/conductor/patterns/radio-group.json +69 -0
  89. package/dist/profiles/conductor/patterns/slider.json +84 -0
  90. package/dist/profiles/conductor/patterns/spinbutton.json +74 -0
  91. package/dist/profiles/conductor/patterns/tabs.json +34 -26
  92. package/dist/profiles/conductor/patterns/tooltip.json +31 -23
  93. package/dist/profiles/conductor/patterns/tree-view.json +77 -0
  94. package/dist/profiles/conductor/patterns/validation.json +42 -26
  95. package/dist/profiles/conductor/semantics.json +826 -130
  96. package/dist/profiles/conductor/ui-design-brain-bindings.json +287 -307
  97. package/dist/projection-manifest.json +120 -104
  98. package/dist/requirements-to-implementation.md +7 -1
  99. package/lib/build.mjs +3 -3
  100. package/lib/digest.mjs +8 -0
  101. package/lib/load.mjs +13 -0
  102. package/lib/provenance.mjs +2 -0
  103. package/lib/render.mjs +51 -7
  104. package/lib/sync.mjs +2 -2
  105. package/lib/validate.mjs +335 -33
  106. package/package.json +6 -2
  107. package/profiles/ai-orchestration/profile.json +1 -1
  108. package/profiles/ai-orchestration/templates/patterns/README.md +1 -1
  109. package/profiles/ai-orchestration/templates/review/README.md +1 -1
  110. package/profiles/ai-orchestration/templates/semantics/README.md +1 -1
  111. package/profiles/ai-orchestration/templates/testing/README.md +1 -1
  112. package/profiles/conductor/profile.json +1 -1
  113. package/profiles/conductor/templates/evidence/README.md +1 -1
  114. package/profiles/conductor/templates/patterns/README.md +1 -1
  115. package/profiles/conductor/templates/semantics/README.md +1 -1
  116. package/schemas/consumer-config.schema.json +1 -1
  117. package/schemas/contract.schema.json +1 -1
  118. package/schemas/manifest.schema.json +1 -1
  119. package/schemas/pattern.schema.json +98 -1
  120. package/schemas/profile.schema.json +1 -1
  121. package/schemas/projection-manifest.schema.json +6 -6
  122. package/schemas/semantic.schema.json +26 -1
  123. package/schemas/standards-reference.schema.json +105 -0
  124. package/schemas/wcag-coverage.schema.json +93 -0
  125. package/src/applicability/facts.yml +3 -5
  126. package/src/applicability/matrix.yml +5 -7
  127. package/src/applicability/ui-design-brain-bindings.yml +8 -22
  128. package/src/contract.yml +1 -1
  129. package/src/coverage/wcag-2.2.yml +68 -0
  130. package/src/patterns/disclosure/accordion.yml +1 -1
  131. package/src/patterns/disclosure/disclosure.yml +1 -1
  132. package/src/patterns/feedback/alert.yml +1 -1
  133. package/src/patterns/feedback/dynamic-status.yml +1 -1
  134. package/src/patterns/feedback/progress.yml +1 -1
  135. package/src/patterns/forms/consequential-submission.yml +1 -1
  136. package/src/patterns/forms/field.yml +1 -1
  137. package/src/patterns/forms/spinbutton.yml +1 -0
  138. package/src/patterns/forms/validation.yml +1 -1
  139. package/src/patterns/media/carousel.yml +1 -1
  140. package/src/patterns/media/image.yml +1 -1
  141. package/src/patterns/media/media-player.yml +1 -1
  142. package/src/patterns/navigation/menu-button.yml +1 -1
  143. package/src/patterns/navigation/menu.yml +1 -0
  144. package/src/patterns/navigation/pagination.yml +1 -1
  145. package/src/patterns/navigation/tabs.yml +1 -1
  146. package/src/patterns/navigation/tree-view.yml +1 -0
  147. package/src/patterns/overlays/dialog.yml +1 -1
  148. package/src/patterns/overlays/popover.yml +1 -1
  149. package/src/patterns/overlays/tooltip.yml +1 -1
  150. package/src/patterns/selection/checkbox.yml +1 -0
  151. package/src/patterns/selection/combobox.yml +1 -1
  152. package/src/patterns/selection/listbox.yml +1 -1
  153. package/src/patterns/selection/radio-group.yml +1 -0
  154. package/src/patterns/selection/slider.yml +1 -0
  155. package/src/semantics/accessible-names.yml +1 -1
  156. package/src/semantics/forms.yml +1 -1
  157. package/src/semantics/headings-landmarks.yml +1 -1
  158. package/src/semantics/keyboard-focus.yml +1 -1
  159. package/src/semantics/live-regions.yml +1 -1
  160. package/src/semantics/media.yml +1 -1
  161. package/src/semantics/native-elements.yml +1 -1
  162. package/src/semantics/roles-states-properties.yml +1 -1
  163. package/src/semantics/tables.yml +1 -1
  164. package/src/semantics/wcag-2.2.yml +1 -0
  165. package/src/sources.yml +1 -1
@@ -1,115 +1,131 @@
1
1
  {
2
2
  "_generated": "GENERATED by @verndale/accessibility-standards; DO NOT EDIT",
3
- "package": "@verndale/accessibility-standards@2.0.0",
4
- "schema_version": 2,
5
- "source_digest": "e4bf4272751c21e417ddd3e6c52308bf804fab097629ba843964532e7f97d9f0",
3
+ "package": "@verndale/accessibility-standards@3.0.0",
6
4
  "profile_digests": {
7
- "ai-orchestration": "5865a240f47ed5756a8b7a03fddd28fd8734051b61194dd378064b764859d691",
8
- "conductor": "4840ac3a4910f8dc3a850df266a141e0e4df94ca3c8935ae4531c56f6be91e65"
9
- },
10
- "ui_design_brain": {
11
- "package": "@verndale/ui-design-brain",
12
- "package_version": "1.16.0",
13
- "catalog_authority_version": "1.15.1",
14
- "repository": "https://github.com/verndale/ui-design-brain",
15
- "manifest_path": "skills/ui-design-brain/catalog-manifest.json",
16
- "source_digest": "sha256:1eda596fe341786b5ada25742b6487bc06685fff17cbd582bc1b58302097e3ff",
17
- "manifest_digest": "sha256:63a0bc8d9537d6d4c0aef8fd8a539bf4a9181a50d0761bd63eae6fe59b4eddc9",
18
- "pattern_count": 80,
19
- "tracking_issue": "https://github.com/verndale/ui-design-brain/issues/47",
20
- "binding_digest": "3873c25694439e1ab07858aa84aecfa1be3467043559d0c94906c19e1025da64"
5
+ "ai-orchestration": "de396e9a23010dff2e8abf3ae7e8500153599583ffa31a595b3a94fbe9df3da4",
6
+ "conductor": "beadcb5fe8151303b3e3241de4fee0ece3be9ff2f4dbdb3a6f93a363b0a2d491"
21
7
  },
22
8
  "profiles": {
23
- "conductor": {
24
- "version": "2.0.0",
25
- "profile_digest": "4840ac3a4910f8dc3a850df266a141e0e4df94ca3c8935ae4531c56f6be91e65",
26
- "source_digest": "e4bf4272751c21e417ddd3e6c52308bf804fab097629ba843964532e7f97d9f0",
9
+ "ai-orchestration": {
27
10
  "outputs": {
28
- "semanticsJson": "01a742ca49cc6cfdc998b55a422683b5a8b6e08378bf7325542473e1e16c52da",
29
- "patternContracts": "d485b89e5ac30f7d2ab359a0abacd8913da2de3c4de9529d9fa61c1b72d257c8",
30
- "uiDesignBrainBindings": "8dfafdafbfb27cfb3317ebc0d0ad02dd1a8521d18694501f5fbb5e164332243e",
31
- "coverageManifest": "024a5e7b9a9a9c0dffffc9d399b7fda1e4b647b7a88db6bfe295918e3d5ecf1e",
32
- "semanticsMarkdown": "3869ce8b1c29cc508a276e1490c5deb7694379debb5006b7d195d34aa239f9f7",
33
- "qualityMarkdown": "bbed143f7e5efb8a5b836f2f626f58a0893465557539797a06ca343bd49e7307",
34
- "applicabilityMatrix": "da0a39ee0ab0f77267701e8d7116bbe5b7abf96e8c1b70505b7a60fe42b32878",
35
- "pattern:pattern.accordion": "f2a21368184e27b49204a6891abfc8b6f4f07782c2dd443311f907e7c8f3e215",
36
- "pattern:pattern.alert": "6251aa3085d1e1d721b007b6b4c997d03c424fd1ffbb05de1712a01152c159ed",
37
- "pattern:pattern.carousel": "b7c5be34fbdea95637afd20ef5177e38e46ebf3b61a37aa99180fc4191b75ea7",
38
- "pattern:pattern.combobox": "d483c608b8de22618d126f347e3e42068f767a7771b57cebcc16c47ab09c9fc0",
39
- "pattern:pattern.consequential-submission": "b295514dcecb9f9b5ed6296238430b81d471ca94798016048294a248b7ee264e",
40
- "pattern:pattern.dialog": "6ffb28b392b082cc1f52f504578d73ba1f88f933fe7a0e7ec63d56beb08d420e",
41
- "pattern:pattern.disclosure": "2807b0cffbce6228456d19562573ab0480aca41f36cefe4a41fa49fb8042d8c5",
42
- "pattern:pattern.dynamic-status": "d2fcebd347dd5715197ea61b126023c9e244009c2e06b7f96da5f4dfb09e5d4a",
43
- "pattern:pattern.field": "907f542ce3515b6e96a238c9d56d93e8716d73457c0d8b8b3e8f1ba3e23b8a36",
44
- "pattern:pattern.image": "efd1678a8a44b09d6a418782efea2e403bf2ee4c0581666f3623a9059a9f781b",
45
- "pattern:pattern.listbox": "a0009446593465c141e61ee747a23b21f0920c12a445796d2f58715d14db24b0",
46
- "pattern:pattern.media-player": "8f971f5da03b74e4bb21b2fc8031453773f3765064f8e6899a5a5b9607384944",
47
- "pattern:pattern.menu-button": "cf958ab413302b1ae14c85f4c42840424ea2dd26b3c9989770f6808c90a1ba0a",
48
- "pattern:pattern.pagination": "fbbf3fa001b57bfc48756cbe04f1b1c5d4f6d50344138354ce97d095ce1d1e04",
49
- "pattern:pattern.popover": "f118849c8b717c734d505ebbbc5f4b6bcd759e447093f1c87d48ca4973ce720b",
50
- "pattern:pattern.progress": "3769aee59bbda8b68b090ef15142c428d44da41334831d0c0f06f700e67a57d0",
51
- "pattern:pattern.tabs": "85771c7c03dff073cf7d02c9365ba8b4283347241f8e47c9ca1e68acc51267f5",
52
- "pattern:pattern.tooltip": "2d715d2ba2995dd6ae96ec8d33931825215bfc84058aba2db3ad76008e97d482",
53
- "pattern:pattern.validation": "a3cff1807eb1cb5cfad619c405293e330780463b9489d075265468ef922e7f8c"
54
- }
11
+ "coverageManifest": "d73cc0bf6d9c9ce52417ec0060a7aacfbaf4f09c00db1c24ce5fc4aa218889b4",
12
+ "implementation": "5cf5c4b4559c72cafc8e46972b17dc3b0d58ec9adedcb40364fabcefdc4e6cd6",
13
+ "pattern:pattern.accordion": "140df5b413e400a2b6ff9fbf1afd4edb3850cefba4fcd152c77d059bf9f04065",
14
+ "pattern:pattern.alert": "a85ce4945959aeed3a61751b76baf495e34e9600924548a0f3e1aec11de3b734",
15
+ "pattern:pattern.carousel": "0d9f3319aacad649b1a05871d3caa11252925b1647ac7139b9a769468c15428f",
16
+ "pattern:pattern.checkbox": "7ff85eaed1fee2fb1b7ce8f45816c50428007ab01d3f3060506306db834ec43f",
17
+ "pattern:pattern.combobox": "29db79e8519191c955559f82ba5102c81f3cefda86baf434616f933e09f82b11",
18
+ "pattern:pattern.consequential-submission": "20080773f56a0ae37a9ff95762ed8db1d4b3893f1557ea1feab0f47cf05234cd",
19
+ "pattern:pattern.dialog": "40d21d12bab5a0453a9647510450487ff34635313c83d9ac12633bdd9c104dae",
20
+ "pattern:pattern.disclosure": "ae01bd40b240d6c2c91740ea9669885643cecd7a69d894fd1abb50890b06c1d9",
21
+ "pattern:pattern.dynamic-status": "aad29c2730ea727e474433a0128fb586c9d0c1d90ad20f43fea74bbf8bb6043f",
22
+ "pattern:pattern.field": "e3660a18d4d089dee5fab1e232150abc80c03b42ae4f86d37be364c469714051",
23
+ "pattern:pattern.image": "58c35c44f34b4e8acad61e77af03d28ee2aacfa2f51d81bf8866c33e2ba45a8e",
24
+ "pattern:pattern.listbox": "2a9c9d384d4994c694f08166e8b71804e36da17922c9ebac4d568bb6c4c8d58a",
25
+ "pattern:pattern.media-player": "975cd1f90dcab17e78727926ae4b8eb5620196e2d83990a85870c589b626c4f6",
26
+ "pattern:pattern.menu": "0ae36c0198e7eccf718c99ca21ea406bc79b154d695401975e3af28a18aca2ad",
27
+ "pattern:pattern.menu-button": "5cfaa0a7776ac7db20be1efa3ae6c94528c6fe282795118b505217af558c741d",
28
+ "pattern:pattern.pagination": "f0149a9324652e3a227c90ccbe5d7621e8160dd4d92cc02366cb3bf534f8a801",
29
+ "pattern:pattern.popover": "f9b94943aec13fbbc02edb09b7e7ef8fcc62c636190513ffee174981664c3586",
30
+ "pattern:pattern.progress": "fe61012daaff53660a726f975a23a7c1d9d975463a2c287d4e5b882b242d4991",
31
+ "pattern:pattern.radio-group": "3877d9e11cc710235002853342e37cab44c1f1b246351fcb882aba711dc2fb04",
32
+ "pattern:pattern.slider": "86ab2a05481e3331967dd1f31c91dc5f4f15fcdf10877b7f9910f373394f0245",
33
+ "pattern:pattern.spinbutton": "f155e9985c8b541d871c562c7354db7927908247da09afe685fc1cf5bb5bc362",
34
+ "pattern:pattern.tabs": "929dac3d9e7e71c03d00343657a163d725527bea3c0d70298dbdbead76f282e7",
35
+ "pattern:pattern.tooltip": "c3cf52e114cc53a361df19f783bee5bc27622c7cee34b17848b8b0cf7918464b",
36
+ "pattern:pattern.tree-view": "3a7518f63566e264285f717cda0ab5b268e98bd735abfe1532fc14bfc56485dd",
37
+ "pattern:pattern.validation": "05d8a532afdd453e1ca4138fef33141dad8967fd03495dfe0e4945942162d402",
38
+ "patternContracts": "c3586ffd8ec971f256502673cf6c996327aa55d1b1586e6b2db5746543acc0f6",
39
+ "review": "be5f88eeadeeee32fdf51a550ec54756afdf37996932981c4678455ad47f3395",
40
+ "semantic:semantics.accessible-authentication": "e483616bae73e26786281e4b1e9d3d139ea98433b4fd1f87e02dae153d11bbdf",
41
+ "semantic:semantics.accessible-name": "913520df2cf1faa55955adae393a29df9218d8519f412bbf352f2f3b71104a24",
42
+ "semantic:semantics.alert": "57778a2c1c089a5450f0d583f27670e6279118240969607e7ef7b66659d80822",
43
+ "semantic:semantics.consequential-action": "11ae933d00621ca8ce4a05cb3a535f261628f8d3b696edf2e56f75be4bf956c2",
44
+ "semantic:semantics.consistent-help": "39867ac8e7141f493fd6043105ab6743f7927ae404a8caa3b48de6cf7ee352d6",
45
+ "semantic:semantics.data-table": "0e1ad4d8dfea8147758e939b880f1feacdacd8eab291c38f345ae47f6ff15a5b",
46
+ "semantic:semantics.dragging-alternative": "4f25d0be4a397ae82304c17f846b47fca993170bee914eced8a7f96af2c9739b",
47
+ "semantic:semantics.expanded-state": "bb8801bb39b9e9be0412d67f3c964c553b66e81ac7e237017606920b182e8637",
48
+ "semantic:semantics.focus.initial": "25d4e95b776b2dfb415b15f291ba7525ae96903d95c3d9debbd1240d71d6aace",
49
+ "semantic:semantics.focus.return": "8d5cd0764a3cb0ad2d9c40563b599e9984731bc1adf591db4147f704b45ab9d6",
50
+ "semantic:semantics.focus.visible": "5071997489606051bc66a54b355acbd4ad8aaa30d49fc1cb3d95e59ae2b00072",
51
+ "semantic:semantics.form-error": "e7cd06fafb5dd4fa5c401740e647f5685eae3b530f10f436b31b6cedae3d97fa",
52
+ "semantic:semantics.form-label": "f1df3bc8c6ad48e67f51fd39d42b1383ebe3e23ccf6600aa91dc852cc6425fa0",
53
+ "semantic:semantics.form-required": "28dad0b50391fe0b58c9c044e50a11071f401cf14d889a6b24e0095d93763f32",
54
+ "semantic:semantics.headings": "96cbe93559342e144612646980f5fb4f84601f54e0c8fb5f3caa67f80354873c",
55
+ "semantic:semantics.keyboard": "ecb9c9515ea57970ce1d5a442022073adaa8f65995f533981800b6a7e8a90db6",
56
+ "semantic:semantics.keyboard.escape": "566bc4e43cf7be94c6ad9916c20edc531b327977531a049bfb04d530881b0b54",
57
+ "semantic:semantics.landmarks": "557c8e27c9f75a067476f4216056413f1831eff64c51d0bfa6d777d4e4f73b10",
58
+ "semantic:semantics.live-status": "3c1ded3245cf644678bd97e597816849970a9c3c954af5fe5d699efb39fa8ffa",
59
+ "semantic:semantics.media-alternatives": "47c4a6b6a082724fc4d91c63460c033af27d150dbf4a581604f401bc79ffe372",
60
+ "semantic:semantics.motion-control": "b61372cfacd87f7b65ebbf8fc8e195d23c7ea3296635fc270e408ba96f0a1eb3",
61
+ "semantic:semantics.name-role-value": "ed12c0dd2725302514bc1a270a5630abdd13cb265391b08f22b534b6e744f04e",
62
+ "semantic:semantics.native-dialog": "000bfdd9441377f27649c66d9280ae4a50a61624fc4c6969b903c05980aa6147",
63
+ "semantic:semantics.native-elements": "9f590fa1bc3e05290b6980a9af1bb579dce349ed48505506edf94960e9b1d9bb",
64
+ "semantic:semantics.non-text-alternative": "237545fc85514bb1c3921ab9628e78e394f083fac02554dfa458a0dd09fd2aab",
65
+ "semantic:semantics.redundant-entry": "503b992920f7682e3297dd48329f6d3c8b7d29db6f74fa885caaea1b20e78ca9",
66
+ "semantic:semantics.roles-states-properties": "a6bbdfb68e7842b0e0822a9fe1af03b261c92a0a212ced3f9d3e5ed9dd946b6e",
67
+ "semantic:semantics.selected-state": "7e1f20c0b272f9e48cc1ca9c09ba6e5b87faff7920ae8622e9c034e7431e99c8",
68
+ "semantic:semantics.target-size": "3efa9512447acb589534cb9e94efcb637d3af1c61b1abb4a379de0e07f5abaeb",
69
+ "semanticsJson": "fcc51c4410854fb5691e2cea75f4d85c55b3501a7af62b3d299151d1bb111c78",
70
+ "testing": "50abad5a1fe8352d40653de9120690f656bf61a11404f66ed8bbc9bc8e210c3f",
71
+ "uiDesignBrainBindings": "c17c916026625d34224ffbedd43e934afd2aca5dc0d2cdcc363be710a15b9af6"
72
+ },
73
+ "profile_digest": "de396e9a23010dff2e8abf3ae7e8500153599583ffa31a595b3a94fbe9df3da4",
74
+ "source_digest": "708ac82783bfb5ebcce31e4dada15d8580863f5e37b32d1807adf61e415ed5af",
75
+ "version": "3.0.0"
55
76
  },
56
- "ai-orchestration": {
57
- "version": "2.0.0",
58
- "profile_digest": "5865a240f47ed5756a8b7a03fddd28fd8734051b61194dd378064b764859d691",
59
- "source_digest": "e4bf4272751c21e417ddd3e6c52308bf804fab097629ba843964532e7f97d9f0",
77
+ "conductor": {
60
78
  "outputs": {
61
- "semanticsJson": "9ae027223836e25f489ec19419e1e86f56c1e5547fcfd95934524c5c876a3727",
62
- "patternContracts": "85727b593ed71f835b08f9f669c2965f129fc9bde9535e038945639bbe2691d3",
63
- "uiDesignBrainBindings": "b2b7c56652f475d0ec21045bac23973b99892afaa3cf19175f30f27679e3b821",
64
- "coverageManifest": "1a786bc95d9c1364f39623c6d117290ade28cf8b64f4d1a864ef91d441175577",
65
- "semantic:semantics.accessible-name": "da61b27c4919ac6fa43f76e8d0cbfc249b78318fcac712007de003e7af56410c",
66
- "semantic:semantics.alert": "2f57e7b3d59f13ce67a33ee49c61493684a677fe55528b1619c4289cedc7c381",
67
- "semantic:semantics.consequential-action": "81e30ca1729a7a762233f22d97ee707b45de4f52d8ccbf78ccc3cc053b6534b4",
68
- "semantic:semantics.data-table": "b1318b1f995e862bca8547d461ace15f7c2723c395f205c1b6bd77424d4e527b",
69
- "semantic:semantics.expanded-state": "27397770b9ae8215c4819091566cc1f98fa0fb686667e1482e0ba6788b99e799",
70
- "semantic:semantics.focus.initial": "33a0bce21810515cc3ee16269e2baa25e65522ce02c24ffc969e4b0ac9f0c66b",
71
- "semantic:semantics.focus.return": "b3bc8ce5ddee7e5460fa5aa867cd036f3325fc22c36f1eee698add8319b6aadf",
72
- "semantic:semantics.focus.visible": "f604d785aebc8f679226c1796149de7e490dd737027fda7b3b718ff234c27caa",
73
- "semantic:semantics.form-error": "937229589788fc186f0ee37b783a436c0c8776f904710bf35cc977c1a2a12d79",
74
- "semantic:semantics.form-label": "ae0ebbad6cbcc798b864d51191eb98648c9708f0325d11105ed5cb955ec0e3aa",
75
- "semantic:semantics.form-required": "ff1fdf6935c334b67b5e93573641f7fa1790ca04bc48e5dceddd03a0e6ef26dd",
76
- "semantic:semantics.headings": "249d98e0039000d8eb50d27eb8e6d1763c87f18d0db4e95a3b5afc2e22596b94",
77
- "semantic:semantics.keyboard": "051b6d4969b5ae1b9b840281550aa7963f58e376ac21b1aa0aea7045deb6adb4",
78
- "semantic:semantics.keyboard.escape": "c220bb07fdd39fb2199eea5da556a2fa73bfa889a18ea7ddcf320f5f5881147a",
79
- "semantic:semantics.landmarks": "26632c7698f3ab0ca71fb8c9b8342c315eecbf32b6bf2e4a56c80a3d42ca2ca0",
80
- "semantic:semantics.live-status": "c3461d306ad5e0f8f82da708121e12ab428a58f9f877b6fc848877b511a60c36",
81
- "semantic:semantics.media-alternatives": "eb2213b669b8148df7538f1b36525ab6562e32ddd582dd60dbcd8b8d464d06bb",
82
- "semantic:semantics.motion-control": "94be66b49c38ef188a5f36a3d0d59e98ca05059c065aff2f810919630077cd9d",
83
- "semantic:semantics.name-role-value": "9084c7ab56477583ba6309ef14fe180113753c844b49defc1847edc7357beb6a",
84
- "semantic:semantics.native-dialog": "641786908012db2334163765ca5f5a9609f7cc24597f21a0b2ee1dc9bd6eccda",
85
- "semantic:semantics.native-elements": "80f3880f20b48d0a9093ed9a222d2582541078c86acc6c285b20bb34f8ca1f07",
86
- "semantic:semantics.non-text-alternative": "25e10174b18533468b1ffae301058c9779a2003d0fd1f98b43b79797936be4d4",
87
- "semantic:semantics.roles-states-properties": "8d256b4d55638a892cbf840f7d9aa8e55db0257868c7749eb257a340fac22ab9",
88
- "semantic:semantics.selected-state": "2e2a837ff4da0e1d612c4b9cee15ed0950bf6d664d2e961c93793b64f743863b",
89
- "semantic:semantics.target-size": "8f9347f58d8072c03a5212d68236bd99d587ced48e44887a08985293c9f9d627",
90
- "pattern:pattern.accordion": "4b1d07c2276a81bb118585219a944d06cbb353f13b28a1ea83505ef5089baab2",
91
- "pattern:pattern.alert": "a3f6e347473b618711f775dd1d89e035faac461e6a68177d42134077b8283279",
92
- "pattern:pattern.carousel": "a2a4f73cfe0adb4f475f1fbe3f08fac0f378822de1066f8a94d1863ca6ef6465",
93
- "pattern:pattern.combobox": "d97311b678818ad8ede386b2f18ad563610980141dc34c9996ac8ab88c448790",
94
- "pattern:pattern.consequential-submission": "cc7193c061ab3b59278d01b76c1e2f54251db6b0b3bdecda3ef0bd527d8518c2",
95
- "pattern:pattern.dialog": "0fc02366dc2e693c787965d5c972709d722adefca0a0c461a1d1d516df50d602",
96
- "pattern:pattern.disclosure": "cf01fb19afea58b3c966ceadc7b5fcc631cf2bd5804cd000f3d4341b70c412bf",
97
- "pattern:pattern.dynamic-status": "8278f088e60dfd372a7fac7c3711cad67029c21ae67e33198080d90271262190",
98
- "pattern:pattern.field": "781a032b12882fe851c4b791906f181bf85f03b821b140d15b057bc7ae29c930",
99
- "pattern:pattern.image": "505116e88f428a7f8226626d1a07beeec22c2680a76a0f5926f91651a7160d87",
100
- "pattern:pattern.listbox": "311336ad995113e6fbeec369e858a7766ccbb500d29984363b3c8f5f3bc2245f",
101
- "pattern:pattern.media-player": "59c6874976be4dcf34b61d3daf82800a48e3e652a4741273258f26c865525c8d",
102
- "pattern:pattern.menu-button": "c79a7f6e57bff5ef69a7e0f0913fa568f98117b6a4a8909325a20a014a82972e",
103
- "pattern:pattern.pagination": "6e65d3b1abbe2364d09fbf50280c4b1066d74f42480a4c673dc85867fa0692b5",
104
- "pattern:pattern.popover": "ca904615db90ff92d8cac4ab049e0e342e63b58ff1e20c6dd74f8e02c0adc097",
105
- "pattern:pattern.progress": "18a52401e52c950612a9f18615727e36f2032b534d47b3f46b3ccab9fde6035a",
106
- "pattern:pattern.tabs": "64b659b18811adee30e97acf83cf6f7da183026ebbd1ade08ccdad1b2ce5772c",
107
- "pattern:pattern.tooltip": "00a37a476f9fdc1c5ecddc2c37732212d78cc6406539f8fdaa88c65f5405912f",
108
- "pattern:pattern.validation": "953d5bf868564e676be5266a277cb79dbee36561203d44e0a6d6e8ae31523ad2",
109
- "implementation": "5a3e6ce540b60f84d0ce8b05fc78dce0636b5495744a178d38fca0b9cec05eee",
110
- "testing": "0f85884865c0adea464d891342404f8a116dab0e2d152946f14d46ff9248e8c4",
111
- "review": "8118ef477faf54650c01093f130e7609a9bdb2110bbbc875556800aea42941b0"
112
- }
79
+ "applicabilityMatrix": "1b291552fc9c68b47c6b0e1405383d985cb16440ddc4fc9d7ae5cff4d702a12b",
80
+ "coverageManifest": "3fb7b529742aced13d2131751e981245bb8b24e9cd92c1922a1abb2e08dedc7c",
81
+ "pattern:pattern.accordion": "bb57ae9764284d071e0defb7da1abcda61763519859b2c45c58f156e1d9960d3",
82
+ "pattern:pattern.alert": "39f5bfe252a411dbafcd36d7235b57a76dc2a7f06f3f1dc2f72701f3bd0dfa4a",
83
+ "pattern:pattern.carousel": "c8fa0182144708659d2973cc1a10070355359b3e5f933ac6319f88c4fe5c010e",
84
+ "pattern:pattern.checkbox": "93dc6bea171693d44b65313afa8094b2c77c4e11ef33d21902be77ca5d2e434c",
85
+ "pattern:pattern.combobox": "2707857425fd9883bebdce00ca0dea6d8d8efd877462f82a91a5458c8abe6b9e",
86
+ "pattern:pattern.consequential-submission": "a67bfb2ae388922f71e62c0add5182a8fb5a00957175820fadce0516ffd711b4",
87
+ "pattern:pattern.dialog": "fb2fc85e4052e0156e297aadd876cd384600b07757bc57cc21930a558ec6d172",
88
+ "pattern:pattern.disclosure": "450634c0b927a5d1d820d7b5a03ba1dc683d1a291073fdbd8b3ccc5e8b8fd4a1",
89
+ "pattern:pattern.dynamic-status": "8fa598a969c1f80910f7428b2eb3502b09149304bed06966f530b070753579d2",
90
+ "pattern:pattern.field": "952c2a7d58ff717bcbe1bda1a5809aa9b3cea66520bb2627ae9a2f0205255852",
91
+ "pattern:pattern.image": "c4241f03b32ee53e4f62ab82d5d245c44e194b0e369769f317f01662792f1425",
92
+ "pattern:pattern.listbox": "00332489c806fbba4ad6880fed50f840e7c44794673d21a278a7f96cb8c0a5d0",
93
+ "pattern:pattern.media-player": "0ace8c3e71a2e8aa325a83d83b09f8e8c3faec3ff02e9ed9edc8c5008f9f2f8d",
94
+ "pattern:pattern.menu": "3efc138301534537f6b84895de9443670452c6472b3e6453bdf92f5cd3a51d41",
95
+ "pattern:pattern.menu-button": "8c0d1fd3cf634be2c31e2d21aff50da7409061434e7823d788c9eb2b7963fc8d",
96
+ "pattern:pattern.pagination": "82c0f577d7fa21b7860bc2d2115d42e7b308dd4d970eff3d7632ddf38bb3686e",
97
+ "pattern:pattern.popover": "67228ac17c099febd1d2bf891c37a7e02a455dc828a83eb9fc29af8e79c03705",
98
+ "pattern:pattern.progress": "524eee0b64ebf1160ec034b87952765d6acafd9ad5f65813977dea73368d2724",
99
+ "pattern:pattern.radio-group": "22aadfaa4b6205c1247345077567aab299721ee00e0dd2b1c958157ffbc83159",
100
+ "pattern:pattern.slider": "87cf71e793553ee51cb1468d5a35369fb244a32937acc877ac907dacc7c88d26",
101
+ "pattern:pattern.spinbutton": "895d09a46586c26467eaf6f895a0d3122fe6b6955b99243568f7b747f4c8fd21",
102
+ "pattern:pattern.tabs": "b02286f1f003e7e65a07db6ddafc01e93a1012af38701a882abc94fbd051232c",
103
+ "pattern:pattern.tooltip": "96dbf72a9e0273c628fe8b17480bd7d05a0ea99e02af0f74b3735dd0c94e072b",
104
+ "pattern:pattern.tree-view": "3a9fe2da64711396af84e6723ea8712435d7415299d1a1fe96a91081f6eb6716",
105
+ "pattern:pattern.validation": "76a8524ffe6e8b73f9c6058850b6cff42fb00b0dfe7e2721cbf8717da7567386",
106
+ "patternContracts": "2835f0d1c5fa5ecbb97adab860eed0e449c20187a12b4e4e5de54df6511570af",
107
+ "qualityMarkdown": "a376d8ddb516d843bed87107cd1583fb4bbb247af9bd346c344003dca20b701e",
108
+ "semanticsJson": "23bd471fdd75e492ccdc88c92d30be394b886a5a0df63bd37ab26f3693fe7657",
109
+ "semanticsMarkdown": "42378774ccfdc2a25a3dc0449474343989efb0fd4bd30a9a329b30359bbf0226",
110
+ "uiDesignBrainBindings": "15a20525c2ce0e5aa014f14cb43cdeefef44334470035e629f39e29fc933d13b"
111
+ },
112
+ "profile_digest": "beadcb5fe8151303b3e3241de4fee0ece3be9ff2f4dbdb3a6f93a363b0a2d491",
113
+ "source_digest": "708ac82783bfb5ebcce31e4dada15d8580863f5e37b32d1807adf61e415ed5af",
114
+ "version": "3.0.0"
113
115
  }
116
+ },
117
+ "schema_version": 3,
118
+ "source_digest": "708ac82783bfb5ebcce31e4dada15d8580863f5e37b32d1807adf61e415ed5af",
119
+ "ui_design_brain": {
120
+ "binding_digest": "9c2e5264b3706778d800e6c8f7fb77ebceb34a8bb00937431cd42f5c0b2e9d39",
121
+ "catalog_authority_version": "1.15.1",
122
+ "manifest_digest": "sha256:63a0bc8d9537d6d4c0aef8fd8a539bf4a9181a50d0761bd63eae6fe59b4eddc9",
123
+ "manifest_path": "skills/ui-design-brain/catalog-manifest.json",
124
+ "package": "@verndale/ui-design-brain",
125
+ "package_version": "1.16.0",
126
+ "pattern_count": 80,
127
+ "repository": "https://github.com/verndale/ui-design-brain",
128
+ "source_digest": "sha256:1eda596fe341786b5ada25742b6487bc06685fff17cbd582bc1b58302097e3ff",
129
+ "tracking_issue": "https://github.com/verndale/ui-design-brain/issues/47"
114
130
  }
115
131
  }
@@ -1,10 +1,11 @@
1
1
  <!-- GENERATED by @verndale/accessibility-standards; DO NOT EDIT -->
2
- <!-- package: @verndale/accessibility-standards@2.0.0; schema: 2; source-digest: e4bf4272751c21e417ddd3e6c52308bf804fab097629ba843964532e7f97d9f0 -->
2
+ <!-- package: @verndale/accessibility-standards@3.0.0; schema: 3; source-digest: 708ac82783bfb5ebcce31e4dada15d8580863f5e37b32d1807adf61e415ed5af -->
3
3
  # Requirements to implementation
4
4
 
5
5
  - pattern.accordion → semantics.native-elements, semantics.accessible-name, semantics.expanded-state, semantics.keyboard, semantics.focus.visible → accordion-control, accordion-panel
6
6
  - pattern.alert → semantics.alert → alert-announcement
7
7
  - pattern.carousel → semantics.accessible-name, semantics.keyboard, semantics.focus.visible, semantics.motion-control, semantics.live-status → carousel-controls, carousel-rotation
8
+ - pattern.checkbox → semantics.accessible-name, semantics.focus.visible, semantics.form-label, semantics.keyboard, semantics.name-role-value, semantics.native-elements, semantics.roles-states-properties → checkbox-group-semantics, checkbox-state-machine
8
9
  - pattern.combobox → semantics.accessible-name, semantics.expanded-state, semantics.selected-state, semantics.keyboard, semantics.live-status → combobox-state-machine
9
10
  - pattern.consequential-submission → semantics.consequential-action, semantics.form-error, semantics.keyboard → submission-safeguard
10
11
  - pattern.dialog → semantics.native-dialog, semantics.accessible-name, semantics.keyboard.escape, semantics.focus.initial, semantics.focus.return → dialog-semantics, dialog-focus-lifecycle
@@ -14,10 +15,15 @@
14
15
  - pattern.image → semantics.non-text-alternative → image-alternative
15
16
  - pattern.listbox → semantics.accessible-name, semantics.selected-state, semantics.keyboard, semantics.focus.visible → listbox-keyboard-model
16
17
  - pattern.media-player → semantics.media-alternatives, semantics.accessible-name, semantics.keyboard, semantics.focus.visible, semantics.motion-control → media-alternatives, media-controls
18
+ - pattern.menu → semantics.accessible-name, semantics.expanded-state, semantics.focus.initial, semantics.focus.return, semantics.focus.visible, semantics.keyboard, semantics.keyboard.escape, semantics.roles-states-properties → menu-composite-focus, menu-keyboard-model, menu-state-model
17
19
  - pattern.menu-button → semantics.accessible-name, semantics.expanded-state, semantics.keyboard, semantics.focus.initial, semantics.focus.return → menu-button-keyboard
18
20
  - pattern.pagination → semantics.native-elements, semantics.accessible-name, semantics.landmarks, semantics.focus.visible → pagination-current-page
19
21
  - pattern.popover → semantics.native-elements, semantics.accessible-name, semantics.keyboard.escape, semantics.focus.return → popover-dismissal
20
22
  - pattern.progress → semantics.name-role-value, semantics.live-status → progress-value
23
+ - pattern.radio-group → semantics.accessible-name, semantics.focus.visible, semantics.form-label, semantics.keyboard, semantics.native-elements, semantics.roles-states-properties → radio-group-keyboard-model, radio-group-labeling, radio-group-selection-model
24
+ - pattern.slider → semantics.accessible-name, semantics.dragging-alternative, semantics.focus.visible, semantics.keyboard, semantics.name-role-value, semantics.native-elements, semantics.roles-states-properties → slider-keyboard-model, slider-native-control-selection, slider-range-state, slider-touch-at-compatibility
25
+ - pattern.spinbutton → semantics.accessible-name, semantics.focus.visible, semantics.form-label, semantics.keyboard, semantics.name-role-value, semantics.native-elements, semantics.roles-states-properties → spinbutton-keyboard-model, spinbutton-native-control-selection, spinbutton-range-state, spinbutton-validation
21
26
  - pattern.tabs → semantics.accessible-name, semantics.selected-state, semantics.keyboard, semantics.focus.visible → tabs-keyboard-model
22
27
  - pattern.tooltip → semantics.accessible-name, semantics.keyboard.escape → tooltip-description
28
+ - pattern.tree-view → semantics.accessible-name, semantics.expanded-state, semantics.focus.visible, semantics.keyboard, semantics.roles-states-properties, semantics.selected-state → tree-hierarchy-semantics, tree-keyboard-model, tree-selection-model
23
29
  - pattern.validation → semantics.form-error, semantics.live-status, semantics.focus.initial → validation-associations, error-summary
package/lib/build.mjs CHANGED
@@ -2,7 +2,7 @@ import { mkdir, rm, writeFile } from 'node:fs/promises';
2
2
  import { dirname, join } from 'node:path';
3
3
  import { loadStandards, packageRoot } from './load.mjs';
4
4
  import { buildArtifacts, defaultPath, marker } from './render.mjs';
5
- import { digest } from './digest.mjs';
5
+ import { canonicalize, digest } from './digest.mjs';
6
6
  import { profileContractDigest, sourceContractDigest } from './provenance.mjs';
7
7
  import { validateStandards } from './validate.mjs';
8
8
 
@@ -38,8 +38,8 @@ export async function buildDistribution(root = packageRoot) {
38
38
  ui_design_brain: { ...data.uiDesignBrainBindings.source, binding_digest: digest(data.uiDesignBrainBindings) },
39
39
  records: records.map((record) => ({ id: record.id, digest: digest(record) }))
40
40
  };
41
- await writeFile(join(dist, 'manifest.json'), `${JSON.stringify(manifest, null, 2)}\n`);
42
- await writeFile(join(dist, 'projection-manifest.json'), `${JSON.stringify({ _generated: marker, package: manifest.package, schema_version: manifest.schema_version, source_digest: manifest.source_digest, profile_digests: manifest.profile_digests, ui_design_brain: manifest.ui_design_brain, profiles: profileManifests }, null, 2)}\n`);
41
+ await writeFile(join(dist, 'manifest.json'), `${JSON.stringify(canonicalize(manifest), null, 2)}\n`);
42
+ await writeFile(join(dist, 'projection-manifest.json'), `${JSON.stringify(canonicalize({ _generated: marker, package: manifest.package, schema_version: manifest.schema_version, source_digest: manifest.source_digest, profile_digests: manifest.profile_digests, ui_design_brain: manifest.ui_design_brain, profiles: profileManifests }), null, 2)}\n`);
43
43
  await writeFile(join(dist, 'requirements-to-implementation.md'), `<!-- ${marker} -->\n<!-- package: ${manifest.package}; schema: ${manifest.schema_version}; source-digest: ${manifest.source_digest} -->\n# Requirements to implementation\n\n${data.patterns.sort((a, b) => a.id.localeCompare(b.id)).map((pattern) => `- ${pattern.id} → ${pattern.requires.join(', ')} → ${pattern.implementation_outcomes.join(', ')}`).join('\n')}\n`);
44
44
  return { records: records.length, profiles: 2 };
45
45
  }
package/lib/digest.mjs CHANGED
@@ -6,6 +6,14 @@ export function stable(value) {
6
6
  return JSON.stringify(value);
7
7
  }
8
8
 
9
+ export function canonicalize(value) {
10
+ if (Array.isArray(value)) return value.map(canonicalize);
11
+ if (value && typeof value === 'object') {
12
+ return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalize(value[key])]));
13
+ }
14
+ return value;
15
+ }
16
+
9
17
  export function digest(value) {
10
18
  return createHash('sha256').update(typeof value === 'string' ? value : stable(value)).digest('hex');
11
19
  }
package/lib/load.mjs CHANGED
@@ -26,6 +26,17 @@ async function markdownFilesUnder(root) {
26
26
  return nested.flat();
27
27
  }
28
28
 
29
+ async function loadSchemas(root) {
30
+ const schemasRoot = join(root, 'schemas');
31
+ const names = (await readdir(schemasRoot))
32
+ .filter((name) => name.endsWith('.schema.json'))
33
+ .sort();
34
+ return Object.fromEntries(await Promise.all(names.map(async (name) => [
35
+ name,
36
+ JSON.parse(await readFile(join(schemasRoot, name), 'utf8')),
37
+ ])));
38
+ }
39
+
29
40
  async function loadProfileTemplates(root, profile) {
30
41
  const templatesRoot = join(root, 'profiles', profile, 'templates');
31
42
  const templates = {};
@@ -59,10 +70,12 @@ export async function loadStandards(root = packageRoot) {
59
70
  package: JSON.parse(await readFile(join(root, 'package.json'), 'utf8')),
60
71
  contract: await readJsonYaml(join(root, 'src', 'contract.yml')),
61
72
  sources: await readJsonYaml(join(root, 'src', 'sources.yml')),
73
+ wcagCoverage: await readJsonYaml(join(root, 'src', 'coverage', 'wcag-2.2.yml')),
62
74
  facts: await readJsonYaml(join(root, 'src', 'applicability', 'facts.yml')),
63
75
  matrix: await readJsonYaml(join(root, 'src', 'applicability', 'matrix.yml')),
64
76
  uiDesignBrainBindings: await readJsonYaml(join(root, 'src', 'applicability', 'ui-design-brain-bindings.yml')),
65
77
  evidence: await readJsonYaml(join(root, 'src', 'evidence', 'proof-routing.yml')),
78
+ schemas: await loadSchemas(root),
66
79
  profiles,
67
80
  profileTemplates,
68
81
  foundations, semantics, patterns, policies
@@ -14,6 +14,7 @@ export function sourceContractPayload(data) {
14
14
  package: { name: data.package.name, version: data.package.version },
15
15
  contract: data.contract,
16
16
  sources: data.sources,
17
+ wcag_2_2: data.wcagCoverage,
17
18
  foundations: [...data.foundations].sort(byId),
18
19
  semantics: [...data.semantics].sort(byId),
19
20
  patterns: [...data.patterns].sort(byId),
@@ -21,6 +22,7 @@ export function sourceContractPayload(data) {
21
22
  facts: data.facts,
22
23
  matrix: data.matrix,
23
24
  evidence: data.evidence,
25
+ schemas: data.schemas,
24
26
  ui_design_brain_bindings: data.uiDesignBrainBindings,
25
27
  profiles: Object.fromEntries(Object.keys(data.profiles)
26
28
  .sort()
package/lib/render.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  import { compileApplicability, resolutionStates, triggerStates } from './compile-applicability.mjs';
2
2
  import { buildLaneCoverage } from './coverage.mjs';
3
- import { digest } from './digest.mjs';
3
+ import { canonicalize, digest } from './digest.mjs';
4
4
  import { projectionProvenance } from './provenance.mjs';
5
5
 
6
6
  export const marker = 'GENERATED by @verndale/accessibility-standards; DO NOT EDIT';
7
7
 
8
8
  function json(payload, provenance) {
9
- return `${JSON.stringify({ _generated: marker, _provenance: provenance, ...payload }, null, 2)}\n`;
9
+ return `${JSON.stringify(canonicalize({ _generated: marker, _provenance: provenance, ...payload }), null, 2)}\n`;
10
10
  }
11
11
 
12
12
  function markdownDocument(title, content, provenance) {
@@ -17,12 +17,41 @@ function markdown(title, records, body, provenance) {
17
17
  return markdownDocument(title, records.map(body).join('\n\n'), provenance);
18
18
  }
19
19
 
20
+ function markdownText(value) {
21
+ return String(value)
22
+ .replaceAll('\\', '\\\\')
23
+ .replace(/([\[\]`*_{}])/g, '\\$1')
24
+ .replace(/\r?\n/g, ' ');
25
+ }
26
+
27
+ function markdownUrl(value) {
28
+ return `<${String(value).replace(/[<>\s]/g, (character) => encodeURIComponent(character))}>`;
29
+ }
30
+
31
+ function tableCell(value) {
32
+ return String(value)
33
+ .replaceAll('&', '&amp;')
34
+ .replaceAll('\\', '&#92;')
35
+ .replaceAll('<', '&lt;')
36
+ .replaceAll('>', '&gt;')
37
+ .replace(/\r\n?|\n/g, '<br>')
38
+ .replaceAll('|', '\\|');
39
+ }
40
+
41
+ function embeddedJson(value) {
42
+ return JSON.stringify(canonicalize(value)).replaceAll('`', '\\u0060');
43
+ }
44
+
45
+ function standardsReferences(refs) {
46
+ return refs.map((ref) => `- [${markdownText(`${ref.authority} ${ref.identifier}`)}](${markdownUrl(ref.url)})${ref.level ? ` (Level ${ref.level})` : ''} — ${ref.normative ? 'normative' : 'informative'}`).join('\n');
47
+ }
48
+
20
49
  function semanticSection(item) {
21
- return `## ${item.id}\n\n${item.requirement}\n\nProof: ${item.proof.join(', ')}.`;
50
+ return `## ${item.id}\n\n${item.requirement}\n\nStandards:\n${standardsReferences(item.standards_refs)}\n\nProof: ${item.proof.join(', ')}.`;
22
51
  }
23
52
 
24
53
  function patternSection(item) {
25
- return `## ${item.id}\n\nRequires: ${item.requires.join(', ')}.\n\nScope: ${item.scope}.\n\nBehavior:\n${item.behavior.map((line) => `- ${line}`).join('\n')}\n\nProduct decisions: ${item.product_decisions.join(', ')}.\n\nFunctional Spec bindings: ${item.functional_spec_bindings.join(', ')}.\n\nImplementation outcomes: ${item.implementation_outcomes.join(', ')}.\n\nEvidence: ${item.evidence_routes.join(', ')}.`;
54
+ return `## ${item.id}\n\nStandards:\n${standardsReferences(item.standards_refs)}\n\nRequires: ${item.requires.join(', ')}.\n\nActivation: \`${embeddedJson(item.activation)}\`\n\nScope: ${item.scope}.\n\nBehavior:\n${item.behavior.map((line) => `- ${line}`).join('\n')}\n\nProduct decisions: ${item.product_decisions.join(', ')}.\n\nFunctional Spec bindings: ${item.functional_spec_bindings.join(', ')}.\n\nImplementation outcomes: ${item.implementation_outcomes.join(', ')}.\n\nEvidence: ${item.evidence_routes.join(', ')}.`;
26
55
  }
27
56
 
28
57
  function requirementSection(item) {
@@ -30,11 +59,23 @@ function requirementSection(item) {
30
59
  }
31
60
 
32
61
  function applicabilitySection(item) {
33
- return `## ${item.id}\n\nWhen: \`${JSON.stringify(item.when)}\`\n\nOutcomes: ${item.outcomes.join(', ')}.\n\nEvidence: ${item.evidence.join(', ')}.`;
62
+ return `## ${item.id}\n\nWhen: \`${embeddedJson(item.when)}\`\n\nOutcomes: ${item.outcomes.join(', ')}.\n\nEvidence: ${item.evidence.join(', ')}.`;
34
63
  }
35
64
 
36
65
  function evidenceSection(data) {
37
- return `## Evidence routing\n\n${data.evidence.rule}\n\n${Object.entries(data.evidence.proof_kinds).map(([id, route]) => `- ${id}: ${route.purpose}; capability: ${route.required_capability}`).join('\n')}`;
66
+ const routes = Object.entries(data.evidence.proof_kinds).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0);
67
+ return `## Evidence routing\n\n${data.evidence.rule}\n\n${routes.map(([id, route]) => `- ${id}: ${route.purpose}; capability: ${route.required_capability}`).join('\n')}`;
68
+ }
69
+
70
+ function wcagCoverageSection(coverage) {
71
+ const counts = Object.fromEntries(['covered', 'partial', 'gap'].map((status) => [status, coverage.criteria.filter((criterion) => criterion.status === status).length]));
72
+ const rows = coverage.criteria.map((criterion) => {
73
+ const semantics = criterion.semantic_ids.length ? criterion.semantic_ids.join(', ') : '—';
74
+ const note = criterion.note ?? '—';
75
+ return `| ${[criterion.id, criterion.title, criterion.level, criterion.status, semantics, note].map(tableCell).join(' | ')} |`;
76
+ });
77
+ const deferred = coverage.deferred_patterns.map(({ id, reason }) => `- ${markdownText(id)}: ${markdownText(reason)}`).join('\n');
78
+ return `## WCAG 2.2 Level A/AA coverage\n\nCoverage is criterion-level traceability, not a conformance claim: ${counts.covered} covered, ${counts.partial} partial, and ${counts.gap} gaps.\n\n| Criterion | Title | Level | Status | Semantic IDs | Note |\n| --- | --- | --- | --- | --- | --- |\n${rows.join('\n')}\n\n### Deferred APG patterns\n\n${deferred}`;
38
79
  }
39
80
 
40
81
  export function buildArtifacts(data, profile) {
@@ -57,13 +98,15 @@ export function buildArtifacts(data, profile) {
57
98
  projected_ids: ids,
58
99
  ui_pattern_ids: uiPatternIds,
59
100
  ui_design_brain: { ...data.uiDesignBrainBindings.source, binding_digest: bindingDigest },
60
- lane_coverage: laneCoverage
101
+ lane_coverage: laneCoverage,
102
+ wcag_2_2: data.wcagCoverage
61
103
  }, provenance));
62
104
  if (profile === 'conductor') {
63
105
  const authoritySections = [
64
106
  ...foundations.map(requirementSection),
65
107
  ...semantics.map(semanticSection),
66
108
  ...policies.map(requirementSection),
109
+ wcagCoverageSection(data.wcagCoverage),
67
110
  ].join('\n\n');
68
111
  const qualitySections = [
69
112
  ...patterns.map(patternSection),
@@ -83,6 +126,7 @@ export function buildArtifacts(data, profile) {
83
126
  ...patterns.map(patternSection),
84
127
  ...compiled.map(applicabilitySection),
85
128
  ...policies.map(requirementSection),
129
+ wcagCoverageSection(data.wcagCoverage),
86
130
  evidenceSection(data),
87
131
  ].join('\n\n');
88
132
  artifacts.set('implementation', markdownDocument('Accessibility implementation contract', implementationSections, provenance));
package/lib/sync.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { access, lstat, mkdir, mkdtemp, readFile, rename, rm, writeFile } from 'node:fs/promises';
2
2
  import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
3
3
  import { buildProjectionManifest } from './build-manifest.mjs';
4
- import { digest } from './digest.mjs';
4
+ import { canonicalize, digest } from './digest.mjs';
5
5
  import { loadStandards, packageRoot } from './load.mjs';
6
6
  import { buildArtifacts, defaultPath, marker } from './render.mjs';
7
7
  import { validateStandards } from './validate.mjs';
@@ -60,7 +60,7 @@ export async function projection({
60
60
  .sort(([left], [right]) => left.localeCompare(right)),
61
61
  );
62
62
  manifest.manifest_digest = digest(manifest);
63
- artifacts.set(sourceKey, `${JSON.stringify(manifest, null, 2)}\n`);
63
+ artifacts.set(sourceKey, `${JSON.stringify(canonicalize(manifest), null, 2)}\n`);
64
64
  if (check) return checkProjection(artifacts, paths);
65
65
  if (ifNeeded && await projectionMatches(artifacts, paths)) return { changed: false, files: paths.size };
66
66
  const removals = await protectManagedFiles(paths, sourcePath, outputRoot);