@verndale/accessibility-standards 1.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 (171) hide show
  1. package/OPERATING.md +3 -1
  2. package/README.md +4 -0
  3. package/bin/accessibility-standards.mjs +1 -1
  4. package/dist/manifest.json +159 -101
  5. package/dist/profiles/ai-orchestration/coverage-manifest.json +724 -68
  6. package/dist/profiles/ai-orchestration/implementation/accessibility.md +825 -10
  7. package/dist/profiles/ai-orchestration/pattern-contracts.json +1015 -343
  8. package/dist/profiles/ai-orchestration/patterns/accordion.md +14 -0
  9. package/dist/profiles/ai-orchestration/patterns/alert.md +14 -0
  10. package/dist/profiles/ai-orchestration/patterns/carousel.md +14 -0
  11. package/dist/profiles/ai-orchestration/patterns/checkbox.md +27 -0
  12. package/dist/profiles/ai-orchestration/patterns/combobox.md +14 -0
  13. package/dist/profiles/ai-orchestration/patterns/consequential-submission.md +15 -1
  14. package/dist/profiles/ai-orchestration/patterns/dialog.md +14 -0
  15. package/dist/profiles/ai-orchestration/patterns/disclosure.md +14 -0
  16. package/dist/profiles/ai-orchestration/patterns/dynamic-status.md +14 -0
  17. package/dist/profiles/ai-orchestration/patterns/field.md +15 -0
  18. package/dist/profiles/ai-orchestration/patterns/image.md +14 -0
  19. package/dist/profiles/ai-orchestration/patterns/listbox.md +14 -0
  20. package/dist/profiles/ai-orchestration/patterns/media-player.md +17 -0
  21. package/dist/profiles/ai-orchestration/patterns/menu-button.md +14 -0
  22. package/dist/profiles/ai-orchestration/patterns/menu.md +30 -0
  23. package/dist/profiles/ai-orchestration/patterns/pagination.md +14 -0
  24. package/dist/profiles/ai-orchestration/patterns/popover.md +15 -0
  25. package/dist/profiles/ai-orchestration/patterns/progress.md +15 -0
  26. package/dist/profiles/ai-orchestration/patterns/radio-group.md +27 -0
  27. package/dist/profiles/ai-orchestration/patterns/slider.md +31 -0
  28. package/dist/profiles/ai-orchestration/patterns/spinbutton.md +28 -0
  29. package/dist/profiles/ai-orchestration/patterns/tabs.md +14 -0
  30. package/dist/profiles/ai-orchestration/patterns/tooltip.md +14 -0
  31. package/dist/profiles/ai-orchestration/patterns/tree-view.md +31 -0
  32. package/dist/profiles/ai-orchestration/patterns/validation.md +15 -0
  33. package/dist/profiles/ai-orchestration/review/accessibility.md +21 -6
  34. package/dist/profiles/ai-orchestration/semantics/accessible-authentication.md +13 -0
  35. package/dist/profiles/ai-orchestration/semantics/accessible-name.md +8 -1
  36. package/dist/profiles/ai-orchestration/semantics/alert.md +7 -0
  37. package/dist/profiles/ai-orchestration/semantics/consequential-action.md +6 -1
  38. package/dist/profiles/ai-orchestration/semantics/consistent-help.md +13 -0
  39. package/dist/profiles/ai-orchestration/semantics/data-table.md +7 -1
  40. package/dist/profiles/ai-orchestration/semantics/dragging-alternative.md +13 -0
  41. package/dist/profiles/ai-orchestration/semantics/expanded-state.md +6 -0
  42. package/dist/profiles/ai-orchestration/semantics/focus.initial.md +4 -0
  43. package/dist/profiles/ai-orchestration/semantics/focus.return.md +4 -0
  44. package/dist/profiles/ai-orchestration/semantics/focus.visible.md +8 -1
  45. package/dist/profiles/ai-orchestration/semantics/form-error.md +8 -1
  46. package/dist/profiles/ai-orchestration/semantics/form-label.md +7 -0
  47. package/dist/profiles/ai-orchestration/semantics/form-required.md +7 -0
  48. package/dist/profiles/ai-orchestration/semantics/headings.md +7 -0
  49. package/dist/profiles/ai-orchestration/semantics/keyboard.escape.md +4 -0
  50. package/dist/profiles/ai-orchestration/semantics/keyboard.md +7 -0
  51. package/dist/profiles/ai-orchestration/semantics/landmarks.md +6 -0
  52. package/dist/profiles/ai-orchestration/semantics/live-status.md +7 -1
  53. package/dist/profiles/ai-orchestration/semantics/media-alternatives.md +11 -0
  54. package/dist/profiles/ai-orchestration/semantics/motion-control.md +8 -1
  55. package/dist/profiles/ai-orchestration/semantics/name-role-value.md +6 -1
  56. package/dist/profiles/ai-orchestration/semantics/native-dialog.md +7 -0
  57. package/dist/profiles/ai-orchestration/semantics/native-elements.md +5 -0
  58. package/dist/profiles/ai-orchestration/semantics/non-text-alternative.md +5 -0
  59. package/dist/profiles/ai-orchestration/semantics/redundant-entry.md +13 -0
  60. package/dist/profiles/ai-orchestration/semantics/roles-states-properties.md +6 -0
  61. package/dist/profiles/ai-orchestration/semantics/selected-state.md +6 -0
  62. package/dist/profiles/ai-orchestration/semantics/target-size.md +6 -1
  63. package/dist/profiles/ai-orchestration/semantics.json +843 -100
  64. package/dist/profiles/ai-orchestration/testing/accessibility.md +33 -3
  65. package/dist/profiles/ai-orchestration/ui-design-brain-bindings.json +836 -0
  66. package/dist/profiles/conductor/a11y-semantics.md +270 -10
  67. package/dist/profiles/conductor/accessibility-quality.md +557 -1
  68. package/dist/profiles/conductor/applicability-matrix.json +270 -230
  69. package/dist/profiles/conductor/coverage-manifest.json +724 -68
  70. package/dist/profiles/conductor/pattern-contracts.json +1015 -343
  71. package/dist/profiles/conductor/patterns/accordion.json +42 -24
  72. package/dist/profiles/conductor/patterns/alert.json +36 -18
  73. package/dist/profiles/conductor/patterns/carousel.json +43 -25
  74. package/dist/profiles/conductor/patterns/checkbox.json +67 -0
  75. package/dist/profiles/conductor/patterns/combobox.json +44 -26
  76. package/dist/profiles/conductor/patterns/consequential-submission.json +41 -22
  77. package/dist/profiles/conductor/patterns/dialog.json +44 -26
  78. package/dist/profiles/conductor/patterns/disclosure.json +40 -22
  79. package/dist/profiles/conductor/patterns/dynamic-status.json +38 -19
  80. package/dist/profiles/conductor/patterns/field.json +58 -22
  81. package/dist/profiles/conductor/patterns/image.json +48 -19
  82. package/dist/profiles/conductor/patterns/listbox.json +42 -24
  83. package/dist/profiles/conductor/patterns/media-player.json +76 -26
  84. package/dist/profiles/conductor/patterns/menu-button.json +41 -23
  85. package/dist/profiles/conductor/patterns/menu.json +78 -0
  86. package/dist/profiles/conductor/patterns/pagination.json +41 -22
  87. package/dist/profiles/conductor/patterns/popover.json +49 -23
  88. package/dist/profiles/conductor/patterns/progress.json +45 -20
  89. package/dist/profiles/conductor/patterns/radio-group.json +69 -0
  90. package/dist/profiles/conductor/patterns/slider.json +84 -0
  91. package/dist/profiles/conductor/patterns/spinbutton.json +74 -0
  92. package/dist/profiles/conductor/patterns/tabs.json +41 -23
  93. package/dist/profiles/conductor/patterns/tooltip.json +38 -20
  94. package/dist/profiles/conductor/patterns/tree-view.json +77 -0
  95. package/dist/profiles/conductor/patterns/validation.json +59 -23
  96. package/dist/profiles/conductor/semantics.json +843 -100
  97. package/dist/profiles/conductor/ui-design-brain-bindings.json +836 -0
  98. package/dist/projection-manifest.json +123 -82
  99. package/dist/requirements-to-implementation.md +8 -0
  100. package/lib/build-manifest.mjs +12 -6
  101. package/lib/build.mjs +21 -7
  102. package/lib/compile-applicability.mjs +131 -10
  103. package/lib/coverage.mjs +20 -0
  104. package/lib/digest.mjs +8 -0
  105. package/lib/index.mjs +1 -1
  106. package/lib/load.mjs +44 -1
  107. package/lib/provenance.mjs +51 -0
  108. package/lib/render.mjs +115 -31
  109. package/lib/sync.mjs +242 -28
  110. package/lib/validate.mjs +557 -24
  111. package/package.json +27 -10
  112. package/profiles/ai-orchestration/profile.json +1 -1
  113. package/profiles/ai-orchestration/templates/patterns/README.md +1 -1
  114. package/profiles/ai-orchestration/templates/review/README.md +1 -1
  115. package/profiles/ai-orchestration/templates/semantics/README.md +1 -1
  116. package/profiles/ai-orchestration/templates/testing/README.md +1 -1
  117. package/profiles/conductor/profile.json +1 -1
  118. package/profiles/conductor/templates/evidence/README.md +1 -1
  119. package/profiles/conductor/templates/patterns/README.md +1 -1
  120. package/profiles/conductor/templates/semantics/README.md +1 -1
  121. package/schemas/consumer-config.schema.json +1 -1
  122. package/schemas/contract.schema.json +1 -0
  123. package/schemas/manifest.schema.json +1 -1
  124. package/schemas/pattern.schema.json +98 -1
  125. package/schemas/profile.schema.json +1 -1
  126. package/schemas/projection-manifest.schema.json +84 -1
  127. package/schemas/semantic.schema.json +26 -1
  128. package/schemas/standards-reference.schema.json +105 -0
  129. package/schemas/ui-design-brain-bindings.schema.json +86 -0
  130. package/schemas/wcag-coverage.schema.json +93 -0
  131. package/src/applicability/facts.yml +27 -1
  132. package/src/applicability/matrix.yml +8 -9
  133. package/src/applicability/ui-design-brain-bindings.yml +196 -0
  134. package/src/contract.yml +1 -0
  135. package/src/coverage/wcag-2.2.yml +68 -0
  136. package/src/patterns/disclosure/accordion.yml +1 -1
  137. package/src/patterns/disclosure/disclosure.yml +1 -1
  138. package/src/patterns/feedback/alert.yml +1 -1
  139. package/src/patterns/feedback/dynamic-status.yml +1 -1
  140. package/src/patterns/feedback/progress.yml +1 -1
  141. package/src/patterns/forms/consequential-submission.yml +1 -1
  142. package/src/patterns/forms/field.yml +1 -1
  143. package/src/patterns/forms/spinbutton.yml +1 -0
  144. package/src/patterns/forms/validation.yml +1 -1
  145. package/src/patterns/media/carousel.yml +1 -1
  146. package/src/patterns/media/image.yml +1 -1
  147. package/src/patterns/media/media-player.yml +1 -1
  148. package/src/patterns/navigation/menu-button.yml +1 -1
  149. package/src/patterns/navigation/menu.yml +1 -0
  150. package/src/patterns/navigation/pagination.yml +1 -1
  151. package/src/patterns/navigation/tabs.yml +1 -1
  152. package/src/patterns/navigation/tree-view.yml +1 -0
  153. package/src/patterns/overlays/dialog.yml +1 -1
  154. package/src/patterns/overlays/popover.yml +1 -1
  155. package/src/patterns/overlays/tooltip.yml +1 -1
  156. package/src/patterns/selection/checkbox.yml +1 -0
  157. package/src/patterns/selection/combobox.yml +1 -1
  158. package/src/patterns/selection/listbox.yml +1 -1
  159. package/src/patterns/selection/radio-group.yml +1 -0
  160. package/src/patterns/selection/slider.yml +1 -0
  161. package/src/semantics/accessible-names.yml +1 -1
  162. package/src/semantics/forms.yml +1 -1
  163. package/src/semantics/headings-landmarks.yml +1 -1
  164. package/src/semantics/keyboard-focus.yml +1 -1
  165. package/src/semantics/live-regions.yml +1 -1
  166. package/src/semantics/media.yml +1 -1
  167. package/src/semantics/native-elements.yml +1 -1
  168. package/src/semantics/roles-states-properties.yml +1 -1
  169. package/src/semantics/tables.yml +1 -1
  170. package/src/semantics/wcag-2.2.yml +1 -0
  171. package/src/sources.yml +1 -1
@@ -1,90 +1,131 @@
1
1
  {
2
- "package": "@verndale/accessibility-standards@1.0.0",
2
+ "_generated": "GENERATED by @verndale/accessibility-standards; DO NOT EDIT",
3
+ "package": "@verndale/accessibility-standards@3.0.0",
4
+ "profile_digests": {
5
+ "ai-orchestration": "de396e9a23010dff2e8abf3ae7e8500153599583ffa31a595b3a94fbe9df3da4",
6
+ "conductor": "beadcb5fe8151303b3e3241de4fee0ece3be9ff2f4dbdb3a6f93a363b0a2d491"
7
+ },
3
8
  "profiles": {
4
- "conductor": {
5
- "version": "1.0.0",
9
+ "ai-orchestration": {
6
10
  "outputs": {
7
- "semanticsJson": "42611a6f9f7152ee8a9d2fe39dc59e80e7088835f7d4f11ee67d8876d33af3a0",
8
- "patternContracts": "2944b4161b4072550916e0cad7ab0daca8704f92a0db5928980a3f3fbd4077a7",
9
- "coverageManifest": "dd422be52e03889dd1d88d3aeb84de7d95173f9dc14c0a65117dec5c0747cca4",
10
- "semanticsMarkdown": "5a4745e6e318cca8ff7300447bb04ef8963416c5f0a1c4d69037a59208e8555f",
11
- "qualityMarkdown": "bb0facb2ea463432481b5ee1b6a96fe5aaf11880c5ae0668c554b43117cf8284",
12
- "applicabilityMatrix": "cc7bd706a9f73a38ed7e101d9a6d58901d55cdc5a4551c52df53dcbb1fc30225",
13
- "pattern:pattern.accordion": "ec254a0aaf01372c6d326df9e2747a6fdadeb505801921069e19f9a76f7224d9",
14
- "pattern:pattern.alert": "743f7059d8c4c74344c1774962aa7ae111ac251e1688ae34b312d398e4ded68c",
15
- "pattern:pattern.carousel": "0072641c7995fc74952061afc3b4e20ce8205db92304b9708cd3ad5314b750cb",
16
- "pattern:pattern.combobox": "427024d4c9e5fde9d72c101d480bb24f6c4fa29d2beed087d4e8e3bb93a463d9",
17
- "pattern:pattern.consequential-submission": "4f32ab0f6a86c168d28d5653c6d40444d0f9d0c1285661282c97f93aac86b7ab",
18
- "pattern:pattern.dialog": "3f7b778be6cc0cc368d6a9feae73876f5c1f0739c411c1978eac186c6a8478bf",
19
- "pattern:pattern.disclosure": "12ea9bc2b9d037314c4477aa40f8d8ad176482238162da1a04864d16fd2d19f1",
20
- "pattern:pattern.dynamic-status": "3f8ac01ba98b1a056b82d03e39e1cc735cf4a89ba14ef7cc00a8886950e9a771",
21
- "pattern:pattern.field": "e3eafe382fc919420d9f75ec37a3b99ab9be4d1ed8c154efe2e1a5499cc28d19",
22
- "pattern:pattern.image": "0faf65bbbaaee23387dfe7f1de973e1f4da24fba50248e19fdbfac6bdefe904b",
23
- "pattern:pattern.listbox": "6a7f3a99752a2c2684671d4db746b5bccf90d45b37bb2de2f4488829e339743b",
24
- "pattern:pattern.media-player": "7eb5372c93adbb649845e79a9a7437472dc3b2bf75f3ddc4da725136faa907ea",
25
- "pattern:pattern.menu-button": "9615bcb307f5aa35dbec8161e5fcdedb52c3125df8fb967e6360c04d5a15231b",
26
- "pattern:pattern.pagination": "bf3c9ebae1ec36d91d7d9e9cb6c2ccc8d95daf07bc4a323cf2bbaef8823986c7",
27
- "pattern:pattern.popover": "766ea35bff5fd3ca8a89c62cafc25c319a50bfdacc9cdcd39950b58ef010f756",
28
- "pattern:pattern.progress": "3fd8e767744cb778aac8a86e0e320144fc7ddd17f46b5ec3bf607ec573f96042",
29
- "pattern:pattern.tabs": "5fb87a74409e85044a76a236af1019b793d9ee5eafd8d34d9628b5bd7e864bf6",
30
- "pattern:pattern.tooltip": "b56513f93ee194eb38536cb82712817d98c55a6268dd5bd4ae962336e5e66b64",
31
- "pattern:pattern.validation": "ba8fd3aced80af3e5e3a28d062f8f8e58f5586c00ce2e2b82b3aa155faf6f2ff"
32
- }
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"
33
76
  },
34
- "ai-orchestration": {
35
- "version": "1.0.0",
77
+ "conductor": {
36
78
  "outputs": {
37
- "semanticsJson": "42611a6f9f7152ee8a9d2fe39dc59e80e7088835f7d4f11ee67d8876d33af3a0",
38
- "patternContracts": "2944b4161b4072550916e0cad7ab0daca8704f92a0db5928980a3f3fbd4077a7",
39
- "coverageManifest": "dd422be52e03889dd1d88d3aeb84de7d95173f9dc14c0a65117dec5c0747cca4",
40
- "semantic:semantics.accessible-name": "0c39e1d1fafabdf30d14ed94cd4e06161fcc1d0ac07ad3554c5c795d4bbac762",
41
- "semantic:semantics.alert": "d079bb0ea1612ba3828eebc344a9c0d49655166212e98453c0eb7b8059d01f8c",
42
- "semantic:semantics.consequential-action": "79d1ec9c2119cee11be28ffde458217e8666c7804c392a61bbc220fc2121cef5",
43
- "semantic:semantics.data-table": "16ed84e97d8d6b1bc9704f874927225c3a3992045ac8aaf3b9704d4fb45fe788",
44
- "semantic:semantics.expanded-state": "d2a3e60714bd36234a874ad32c6334152ea924983fb16a847689f71353725717",
45
- "semantic:semantics.focus.initial": "a8b7b3a59da2eac1516f7315b3e6876fa4462b650065f85ba38db942edc7c296",
46
- "semantic:semantics.focus.return": "ce71ad35ce7d65b1bec1a010baefae49e058e6b310e4204e1eaf3df4255474e2",
47
- "semantic:semantics.focus.visible": "0e8a9d6d8820756b3693521d98057fe07f77c0233320f9e06d72b5ce21f0fbaf",
48
- "semantic:semantics.form-error": "ffd1b4d19d696cb5f93faca86641834742f57d1fe12b8c7e3741b2ee505196a0",
49
- "semantic:semantics.form-label": "16e5410b9911dcd4ba205c7082402a0115881650b4fcb31a4b95bb2ee98b9938",
50
- "semantic:semantics.form-required": "3bdb58565de8b36f313f2610c8bae700f01ec3c2e9084ab0c6e080eacc6a17f1",
51
- "semantic:semantics.headings": "bda060974cb9b2c60a2cc725564eff6998592647bc0149374501caa456bd39bb",
52
- "semantic:semantics.keyboard": "702e79e65248ee4147194ab5325de90d6197bd54c3c832d2d36977d5c1b37223",
53
- "semantic:semantics.keyboard.escape": "6318353a5ed5dbd179199b50590c48db9408f92b9546fa4e3f28656964a8bb4f",
54
- "semantic:semantics.landmarks": "7f7ef886b9b66286870b29bfef92665488a8016a161ae8c1b306f9fb0700047c",
55
- "semantic:semantics.live-status": "f174ca78b509e9dfe070610ca174f2f7893f9098d97beb96fa34673c1a026b80",
56
- "semantic:semantics.media-alternatives": "3b396a45778e19073cf25651a79b1be2eac84a9b67c822d961547e5121439b67",
57
- "semantic:semantics.motion-control": "dc944ee6ae6d948a543a33dc86f62277b337211544c1981332a67867ca2180eb",
58
- "semantic:semantics.name-role-value": "1018827e63d16427e6a42b40908737d433235999a96b73d8842d0937e6855aac",
59
- "semantic:semantics.native-dialog": "3b8326bc9e7c0e10a8382c1baf8d0ca0b3afb81a6c9f5521339bb9615bc9c9c4",
60
- "semantic:semantics.native-elements": "852c7d44d101e84fb05ccd6e9d2eb7107f7f083712382d8b960ac3fa2434090d",
61
- "semantic:semantics.non-text-alternative": "4e45ef4c751502936b4f00453f048717e9ad551fefac71c798984aee89c7ecb3",
62
- "semantic:semantics.roles-states-properties": "a970228c27d39fce6395d786db60efd5081bf5373530b7b6bfec46c2ae47c394",
63
- "semantic:semantics.selected-state": "044b6902dd98327069301b066d5cc88e71767a698f3f9b32f56f6016d4d72935",
64
- "semantic:semantics.target-size": "4cd61e2e7b3ae90bc63271e7959c4af983049b189019a3681c59610176d1adc5",
65
- "pattern:pattern.accordion": "d551bf7a2258cca79f306d9edf6a24e2955d2d025f8314dfedc3e5389db5ae44",
66
- "pattern:pattern.alert": "a16c54025010343e93bf4fc0dd18286f53e4be9cd07d61be70d6b06a18df0ffc",
67
- "pattern:pattern.carousel": "259d27e48064979080ebe333b673300425cf884ecce8b02eca6c2c2a56a1127c",
68
- "pattern:pattern.combobox": "df92de73df4847ec283f8776dc2fdd85fd15bd0b3c8d05df416e40cede9f26af",
69
- "pattern:pattern.consequential-submission": "21e49bb0e290b7dea77553df6d29bcfdb34950d07ba1ef4e7cf1a8b79fe03098",
70
- "pattern:pattern.dialog": "aaca16e959dcaf603ee2abbb6b18d4df9594821ce8a96f821f4e5cf0f7db2cac",
71
- "pattern:pattern.disclosure": "0477a611b9afbfca8e78d55c78812f5014375022a9c272886fbff2c026699804",
72
- "pattern:pattern.dynamic-status": "cc009834aca59e79c940339b5a2eefb4bc8d501f45c7d54c7441d92740ae0d62",
73
- "pattern:pattern.field": "18796141e47668682ffb430d2bd39b043fbb98bce80958e5c4761f066b058701",
74
- "pattern:pattern.image": "eb3d93a2d889f0603002cf4d8f79e467be08687d6e4bc2b7a9229452c74eb3f2",
75
- "pattern:pattern.listbox": "764b873185a1c4b3d16c1940057b440a8f5e47a8329312c43ec60470a009d759",
76
- "pattern:pattern.media-player": "813a828908f79eb0703a5a150bcea29ee41cceca93e1f66a106abc9a78fb1eb9",
77
- "pattern:pattern.menu-button": "a4fb849f4c73c6b0f57f5c0fb2f7384fc4860514cf599313142196b6a57488f8",
78
- "pattern:pattern.pagination": "2e3f8e6cc49ed52e5c60bde08acbae8da2e0964a6c71b4d5914e165f7e6dfdd9",
79
- "pattern:pattern.popover": "5fcace9fa64700c72296dad857ee2e3025f774b915c4a6694e99772b296ade2f",
80
- "pattern:pattern.progress": "7a417350fcabfb2ec9bed8b51c3e7440412d2922ac1c7e005c61dd6ebcaf2fef",
81
- "pattern:pattern.tabs": "d944fea00a8b169de2b68772f7a61085c8adbbbe6976689b3b984fc74d2d9919",
82
- "pattern:pattern.tooltip": "94986056a2ad50dc3c7128c8667f8252b4f5a2b4452ef370b902f85a25bce7bd",
83
- "pattern:pattern.validation": "f5445a62766a133dbdc2ec505f9a8d8f35f23deb3ba4c41b76d80c87875966fc",
84
- "implementation": "9dc92bd2c2f625a4e1c15cdf3b194e344bf3e1a4b0f166a47a0241a534d6bfb0",
85
- "testing": "238ee503005595fb0beec9e512b04ab1edba337c399d83cd5e3f391577d188be",
86
- "review": "a0e3ec20d8ade44bef4fc2fa9fcb6925617c105d0b674a3af284044f1e2fe2a8"
87
- }
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"
88
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"
89
130
  }
90
131
  }
@@ -1,8 +1,11 @@
1
+ <!-- GENERATED by @verndale/accessibility-standards; DO NOT EDIT -->
2
+ <!-- package: @verndale/accessibility-standards@3.0.0; schema: 3; source-digest: 708ac82783bfb5ebcce31e4dada15d8580863f5e37b32d1807adf61e415ed5af -->
1
3
  # Requirements to implementation
2
4
 
3
5
  - pattern.accordion → semantics.native-elements, semantics.accessible-name, semantics.expanded-state, semantics.keyboard, semantics.focus.visible → accordion-control, accordion-panel
4
6
  - pattern.alert → semantics.alert → alert-announcement
5
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
6
9
  - pattern.combobox → semantics.accessible-name, semantics.expanded-state, semantics.selected-state, semantics.keyboard, semantics.live-status → combobox-state-machine
7
10
  - pattern.consequential-submission → semantics.consequential-action, semantics.form-error, semantics.keyboard → submission-safeguard
8
11
  - pattern.dialog → semantics.native-dialog, semantics.accessible-name, semantics.keyboard.escape, semantics.focus.initial, semantics.focus.return → dialog-semantics, dialog-focus-lifecycle
@@ -12,10 +15,15 @@
12
15
  - pattern.image → semantics.non-text-alternative → image-alternative
13
16
  - pattern.listbox → semantics.accessible-name, semantics.selected-state, semantics.keyboard, semantics.focus.visible → listbox-keyboard-model
14
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
15
19
  - pattern.menu-button → semantics.accessible-name, semantics.expanded-state, semantics.keyboard, semantics.focus.initial, semantics.focus.return → menu-button-keyboard
16
20
  - pattern.pagination → semantics.native-elements, semantics.accessible-name, semantics.landmarks, semantics.focus.visible → pagination-current-page
17
21
  - pattern.popover → semantics.native-elements, semantics.accessible-name, semantics.keyboard.escape, semantics.focus.return → popover-dismissal
18
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
19
26
  - pattern.tabs → semantics.accessible-name, semantics.selected-state, semantics.keyboard, semantics.focus.visible → tabs-keyboard-model
20
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
21
29
  - pattern.validation → semantics.form-error, semantics.live-status, semantics.focus.initial → validation-associations, error-summary
@@ -1,20 +1,26 @@
1
+ import { buildLaneCoverage } from './coverage.mjs';
1
2
  import { digest } from './digest.mjs';
3
+ import { profileContractDigest, sourceContractDigest } from './provenance.mjs';
2
4
 
3
5
  export function buildProjectionManifest({ data, profile, config, routes, artifacts }) {
4
6
  const records = [...data.foundations, ...data.semantics, ...data.patterns, ...data.policies];
5
7
  return {
6
8
  _generated: 'GENERATED by @verndale/accessibility-standards; DO NOT EDIT',
7
- package: `@verndale/accessibility-standards@${data.package.version}`,
9
+ package: `@verndale/accessibility-standards@${data.contract.package_version}`,
8
10
  profile,
9
- profile_version: '1.0.0',
10
- schema_version: 1,
11
+ profile_version: data.profiles[profile].version,
12
+ schema_version: data.contract.schema_version,
11
13
  digests: {
12
- source: digest({ records, matrix: data.matrix, evidence: data.evidence }),
14
+ source: sourceContractDigest(data),
15
+ profile: profileContractDigest(data, profile),
16
+ ui_design_brain_bindings: digest(data.uiDesignBrainBindings),
13
17
  config: digest(config),
14
18
  routes: digest(routes)
15
19
  },
16
- projected_ids: [...new Set([...data.semantics, ...data.patterns, ...data.matrix.rows].map(({ id }) => id))].sort(),
17
- lane_coverage: Object.fromEntries(['unit', 'axe', 'e2e', 'human'].map((lane) => [lane, records.filter((item) => item.proof?.includes(lane) || item.evidence_routes?.includes(lane)).map(({ id }) => id).sort()])),
20
+ ui_design_brain: { ...data.uiDesignBrainBindings.source, binding_digest: digest(data.uiDesignBrainBindings) },
21
+ ui_pattern_ids: data.uiDesignBrainBindings.bindings.map(({ ui_pattern_id }) => ui_pattern_id),
22
+ projected_ids: [...new Set([...records, ...data.matrix.rows].map(({ id }) => id))].sort(),
23
+ lane_coverage: buildLaneCoverage(data),
18
24
  output_digests: Object.fromEntries([...artifacts].map(([key, content]) => [key, digest(content)]).sort(([a], [b]) => a.localeCompare(b)))
19
25
  };
20
26
  }
package/lib/build.mjs CHANGED
@@ -1,8 +1,9 @@
1
1
  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
- import { buildArtifacts, defaultPath } from './render.mjs';
5
- import { digest } from './digest.mjs';
4
+ import { buildArtifacts, defaultPath, marker } from './render.mjs';
5
+ import { canonicalize, digest } from './digest.mjs';
6
+ import { profileContractDigest, sourceContractDigest } from './provenance.mjs';
6
7
  import { validateStandards } from './validate.mjs';
7
8
 
8
9
  export async function buildDistribution(root = packageRoot) {
@@ -20,12 +21,25 @@ export async function buildDistribution(root = packageRoot) {
20
21
  await writeFile(path, content);
21
22
  outputDigests[key] = digest(content);
22
23
  }
23
- profileManifests[profile] = { version: '1.0.0', outputs: outputDigests };
24
+ profileManifests[profile] = {
25
+ version: data.profiles[profile].version,
26
+ profile_digest: profileContractDigest(data, profile),
27
+ source_digest: sourceContractDigest(data),
28
+ outputs: outputDigests,
29
+ };
24
30
  }
25
31
  const records = [...data.foundations, ...data.semantics, ...data.patterns, ...data.policies].sort((a, b) => a.id.localeCompare(b.id));
26
- const manifest = { package: `@verndale/accessibility-standards@${data.package.version}`, schema_version: 1, records: records.map((record) => ({ id: record.id, digest: digest(record) })) };
27
- await writeFile(join(dist, 'manifest.json'), `${JSON.stringify(manifest, null, 2)}\n`);
28
- await writeFile(join(dist, 'projection-manifest.json'), `${JSON.stringify({ package: manifest.package, profiles: profileManifests }, null, 2)}\n`);
29
- await writeFile(join(dist, 'requirements-to-implementation.md'), `# 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`);
32
+ const manifest = {
33
+ _generated: marker,
34
+ package: `@verndale/accessibility-standards@${data.contract.package_version}`,
35
+ schema_version: data.contract.schema_version,
36
+ source_digest: sourceContractDigest(data),
37
+ profile_digests: Object.fromEntries(Object.keys(data.profiles).sort().map((profile) => [profile, profileContractDigest(data, profile)])),
38
+ ui_design_brain: { ...data.uiDesignBrainBindings.source, binding_digest: digest(data.uiDesignBrainBindings) },
39
+ records: records.map((record) => ({ id: record.id, digest: digest(record) }))
40
+ };
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
+ 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`);
30
44
  return { records: records.length, profiles: 2 };
31
45
  }
@@ -1,6 +1,59 @@
1
1
  const OPS = new Set(['all', 'any', 'not', 'equals', 'contains', 'exists']);
2
+ const FACT_TYPES = new Set(['boolean', 'string', 'array']);
3
+
4
+ function isRecord(value) {
5
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
6
+ }
7
+
8
+ function assertExactKeys(value, expected, label) {
9
+ if (!isRecord(value)) throw new Error(`${label} requires an object operand`);
10
+ const actual = Object.keys(value).sort();
11
+ const required = [...expected].sort();
12
+ if (JSON.stringify(actual) !== JSON.stringify(required)) {
13
+ throw new Error(`${label} requires exactly ${required.join(', ')}`);
14
+ }
15
+ }
16
+
17
+ function assertValueType(value, fact, definition, op) {
18
+ if (!FACT_TYPES.has(definition.type)) throw new Error(`Fact ${fact} has unsupported type ${definition.type ?? '<missing>'}`);
19
+ if (op === 'contains') {
20
+ if (definition.type !== 'array' && definition.type !== 'string') throw new Error(`contains is not valid for ${definition.type} fact ${fact}`);
21
+ const expected = definition.type === 'array' ? definition.items : 'string';
22
+ if (expected !== 'string') throw new Error(`Fact ${fact} has unsupported array item type ${expected ?? '<missing>'}`);
23
+ if (typeof value !== expected) throw new Error(`${op} value for ${fact} must be ${expected}`);
24
+ return;
25
+ }
26
+ if (definition.type === 'array') {
27
+ if (definition.items !== 'string') throw new Error(`Fact ${fact} has unsupported array item type ${definition.items ?? '<missing>'}`);
28
+ if (!Array.isArray(value) || value.some((item) => typeof item !== definition.items)) throw new Error(`${op} value for ${fact} must be an array of ${definition.items}`);
29
+ return;
30
+ }
31
+ if (typeof value !== definition.type) throw new Error(`${op} value for ${fact} must be ${definition.type}`);
32
+ }
33
+
34
+ function assertObservedValueType(value, fact, definition) {
35
+ if (!isRecord(definition) || !FACT_TYPES.has(definition.type)) throw new Error(`Fact ${fact} has unsupported type ${definition?.type ?? '<missing>'}`);
36
+ if (definition.type === 'array') {
37
+ if (definition.items !== 'string') throw new Error(`Fact ${fact} has unsupported array item type ${definition.items ?? '<missing>'}`);
38
+ if (!Array.isArray(value) || value.some((item) => typeof item !== definition.items)) throw new Error(`Observed value for ${fact} must be an array of ${definition.items}`);
39
+ return;
40
+ }
41
+ if (typeof value !== definition.type) throw new Error(`Observed value for ${fact} must be ${definition.type}`);
42
+ }
43
+
44
+ export function validateFactValues(catalog, values) {
45
+ if (!isRecord(values)) throw new Error('Applicability fact values must be an object');
46
+ const facts = catalog?.facts;
47
+ if (!isRecord(facts)) throw new Error('Applicability fact catalog must be an object');
48
+ for (const [fact, value] of Object.entries(values)) {
49
+ if (value === undefined) continue;
50
+ if (!facts[fact]) throw new Error(`Unknown observed applicability fact: ${fact}`);
51
+ assertObservedValueType(value, fact, facts[fact]);
52
+ }
53
+ }
2
54
 
3
55
  export function validateExpression(expression, facts) {
56
+ if (!isRecord(expression)) throw new Error('Applicability expression must be an object');
4
57
  const keys = Object.keys(expression ?? {});
5
58
  if (keys.length !== 1 || !OPS.has(keys[0])) throw new Error(`Unsupported applicability expression: ${keys.join(',') || '<empty>'}`);
6
59
  const [op] = keys;
@@ -10,10 +63,17 @@ export function validateExpression(expression, facts) {
10
63
  operand.forEach((item) => validateExpression(item, facts));
11
64
  return;
12
65
  }
13
- if (op === 'not') return validateExpression(operand, facts);
66
+ if (op === 'not') {
67
+ if (!isRecord(operand)) throw new Error('not requires an applicability expression');
68
+ return validateExpression(operand, facts);
69
+ }
70
+ assertExactKeys(operand, op === 'exists' ? ['fact'] : ['fact', 'value'], op);
14
71
  const fact = operand?.fact;
15
- if (!fact || !facts[fact]) throw new Error(`Unknown applicability fact: ${fact ?? '<missing>'}`);
16
- if (op !== 'exists' && !Object.hasOwn(operand, 'value')) throw new Error(`${op} requires value`);
72
+ if (typeof fact !== 'string' || !facts?.[fact]) throw new Error(`Unknown applicability fact: ${fact ?? '<missing>'}`);
73
+ const definition = facts[fact];
74
+ if (!isRecord(definition) || !FACT_TYPES.has(definition.type)) throw new Error(`Fact ${fact} has unsupported type ${definition?.type ?? '<missing>'}`);
75
+ if (definition.type === 'array' && definition.items !== 'string') throw new Error(`Fact ${fact} has unsupported array item type ${definition.items ?? '<missing>'}`);
76
+ if (op !== 'exists') assertValueType(operand.value, fact, definition, op);
17
77
  }
18
78
 
19
79
  export function evaluate(expression, values) {
@@ -23,29 +83,90 @@ export function evaluate(expression, values) {
23
83
  if (op === 'not') return !evaluate(operand, values);
24
84
  const observed = values[operand.fact];
25
85
  if (op === 'exists') return observed !== undefined && observed !== null;
26
- if (op === 'equals') return observed === operand.value;
86
+ if (op === 'equals') {
87
+ if (Array.isArray(observed) && Array.isArray(operand.value)) {
88
+ return observed.length === operand.value.length && observed.every((value, index) => value === operand.value[index]);
89
+ }
90
+ return observed === operand.value;
91
+ }
27
92
  if (op === 'contains') {
28
- if (Array.isArray(operand.value)) return operand.value.includes(observed);
29
93
  if (Array.isArray(observed)) return observed.includes(operand.value);
30
- return typeof observed === 'string' && observed.includes(String(operand.value));
94
+ return typeof observed === 'string' && observed.includes(operand.value);
31
95
  }
32
96
  throw new Error(`Unsupported operator: ${op}`);
33
97
  }
34
98
 
99
+ export function resolveUiPatternBindings(contract, facts, values = {}) {
100
+ validateFactValues(facts, values);
101
+ const observed = values['component.ui_pattern_ids'];
102
+ if (observed === undefined || observed === null) {
103
+ return {
104
+ source: contract.source,
105
+ ui_pattern_ids: [],
106
+ semantic_ids: [],
107
+ pattern_ids: [],
108
+ baseline_only_ui_pattern_ids: [],
109
+ candidate_evaluations: []
110
+ };
111
+ }
112
+ if (!Array.isArray(observed) || observed.some((value) => typeof value !== 'string' || !value)) {
113
+ throw new Error('component.ui_pattern_ids must be an array of non-empty canonical UI Design Brain slugs');
114
+ }
115
+ const uiPatternIds = [...new Set(observed)];
116
+ const byUiPatternId = new Map(contract.bindings.map((binding) => [binding.ui_pattern_id, binding]));
117
+ const unknown = uiPatternIds.filter((id) => !byUiPatternId.has(id));
118
+ if (unknown.length) throw new Error(`Unknown UI Design Brain pattern IDs: ${unknown.join(', ')}`);
119
+
120
+ const patternIds = new Set();
121
+ const semanticIds = new Set();
122
+ const baselineOnly = [];
123
+ const candidateEvaluations = [];
124
+ for (const uiPatternId of uiPatternIds) {
125
+ const binding = byUiPatternId.get(uiPatternId);
126
+ for (const semanticId of binding.baseline_semantic_ids ?? []) semanticIds.add(semanticId);
127
+ for (const patternId of binding.pattern_ids ?? []) patternIds.add(patternId);
128
+ if (binding.classification === 'baseline-only') baselineOnly.push(uiPatternId);
129
+ for (const candidate of binding.candidates ?? []) {
130
+ const requiredFacts = referencedFacts(candidate.when).sort();
131
+ const missingFacts = requiredFacts.filter((fact) => values[fact] === undefined);
132
+ const applicable = !missingFacts.length && evaluate(candidate.when, values);
133
+ if (applicable) patternIds.add(candidate.pattern_id);
134
+ candidateEvaluations.push({
135
+ ui_pattern_id: uiPatternId,
136
+ pattern_id: candidate.pattern_id,
137
+ discriminator_facts: requiredFacts,
138
+ missing_facts: missingFacts,
139
+ trigger_state: missingFacts.length ? 'candidate' : applicable ? 'applicable' : 'not_applicable',
140
+ resolution_state: missingFacts.length ? 'needs_input' : applicable ? 'resolved' : 'skipped'
141
+ });
142
+ }
143
+ }
144
+ return {
145
+ source: contract.source,
146
+ ui_pattern_ids: uiPatternIds,
147
+ semantic_ids: [...semanticIds].sort(),
148
+ pattern_ids: [...patternIds].sort(),
149
+ baseline_only_ui_pattern_ids: baselineOnly,
150
+ candidate_evaluations: candidateEvaluations
151
+ };
152
+ }
153
+
35
154
  export function compileApplicability(matrix, facts, values = {}) {
155
+ validateFactValues(facts, values);
36
156
  return matrix.rows.map((row, index) => {
37
157
  validateExpression(row.when, facts.facts);
38
- const observed = referencedFacts(row.when).every((fact) => Object.hasOwn(values, fact));
158
+ const observed = referencedFacts(row.when).every((fact) => values[fact] !== undefined);
159
+ const applicable = observed && evaluate(row.when, values);
39
160
  return {
40
161
  ...row,
41
162
  order: index,
42
- trigger_state: observed ? (evaluate(row.when, values) ? 'applicable' : 'not_applicable') : 'unobserved',
43
- resolution_state: observed ? (evaluate(row.when, values) ? 'needs_confirmation' : 'skipped') : 'needs_input'
163
+ trigger_state: observed ? (applicable ? 'applicable' : 'not_applicable') : 'unobserved',
164
+ resolution_state: observed ? (applicable ? 'resolved' : 'skipped') : 'needs_input'
44
165
  };
45
166
  });
46
167
  }
47
168
 
48
- function referencedFacts(expression) {
169
+ export function referencedFacts(expression) {
49
170
  const [op, operand] = Object.entries(expression)[0];
50
171
  if (op === 'all' || op === 'any') return [...new Set(operand.flatMap(referencedFacts))];
51
172
  if (op === 'not') return referencedFacts(operand);
@@ -0,0 +1,20 @@
1
+ export function buildLaneCoverage(data) {
2
+ return Object.fromEntries(
3
+ Object.keys(data.evidence.proof_kinds)
4
+ .sort()
5
+ .map((lane) => [
6
+ lane,
7
+ [...new Set([
8
+ ...data.semantics
9
+ .filter((item) => item.proof.includes(lane))
10
+ .map(({ id }) => id),
11
+ ...data.patterns
12
+ .filter((item) => item.evidence_routes.includes(lane))
13
+ .map(({ id }) => id),
14
+ ...data.matrix.rows
15
+ .filter((item) => item.evidence.includes(lane))
16
+ .flatMap((item) => item.outcomes),
17
+ ])].sort(),
18
+ ]),
19
+ );
20
+ }
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/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { compileApplicability, evaluate, resolutionStates, triggerStates } from './compile-applicability.mjs';
1
+ export { compileApplicability, evaluate, referencedFacts, resolveUiPatternBindings, resolutionStates, triggerStates } from './compile-applicability.mjs';
2
2
  export { loadStandards } from './load.mjs';
3
3
  export { projection } from './sync.mjs';
4
4
  export { validateStandards } from './validate.mjs';