@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.
- package/OPERATING.md +3 -1
- package/README.md +4 -0
- package/bin/accessibility-standards.mjs +1 -1
- package/dist/manifest.json +159 -101
- package/dist/profiles/ai-orchestration/coverage-manifest.json +724 -68
- package/dist/profiles/ai-orchestration/implementation/accessibility.md +825 -10
- package/dist/profiles/ai-orchestration/pattern-contracts.json +1015 -343
- package/dist/profiles/ai-orchestration/patterns/accordion.md +14 -0
- package/dist/profiles/ai-orchestration/patterns/alert.md +14 -0
- package/dist/profiles/ai-orchestration/patterns/carousel.md +14 -0
- package/dist/profiles/ai-orchestration/patterns/checkbox.md +27 -0
- package/dist/profiles/ai-orchestration/patterns/combobox.md +14 -0
- package/dist/profiles/ai-orchestration/patterns/consequential-submission.md +15 -1
- package/dist/profiles/ai-orchestration/patterns/dialog.md +14 -0
- package/dist/profiles/ai-orchestration/patterns/disclosure.md +14 -0
- package/dist/profiles/ai-orchestration/patterns/dynamic-status.md +14 -0
- package/dist/profiles/ai-orchestration/patterns/field.md +15 -0
- package/dist/profiles/ai-orchestration/patterns/image.md +14 -0
- package/dist/profiles/ai-orchestration/patterns/listbox.md +14 -0
- package/dist/profiles/ai-orchestration/patterns/media-player.md +17 -0
- package/dist/profiles/ai-orchestration/patterns/menu-button.md +14 -0
- package/dist/profiles/ai-orchestration/patterns/menu.md +30 -0
- package/dist/profiles/ai-orchestration/patterns/pagination.md +14 -0
- package/dist/profiles/ai-orchestration/patterns/popover.md +15 -0
- package/dist/profiles/ai-orchestration/patterns/progress.md +15 -0
- package/dist/profiles/ai-orchestration/patterns/radio-group.md +27 -0
- package/dist/profiles/ai-orchestration/patterns/slider.md +31 -0
- package/dist/profiles/ai-orchestration/patterns/spinbutton.md +28 -0
- package/dist/profiles/ai-orchestration/patterns/tabs.md +14 -0
- package/dist/profiles/ai-orchestration/patterns/tooltip.md +14 -0
- package/dist/profiles/ai-orchestration/patterns/tree-view.md +31 -0
- package/dist/profiles/ai-orchestration/patterns/validation.md +15 -0
- package/dist/profiles/ai-orchestration/review/accessibility.md +21 -6
- package/dist/profiles/ai-orchestration/semantics/accessible-authentication.md +13 -0
- package/dist/profiles/ai-orchestration/semantics/accessible-name.md +8 -1
- package/dist/profiles/ai-orchestration/semantics/alert.md +7 -0
- package/dist/profiles/ai-orchestration/semantics/consequential-action.md +6 -1
- package/dist/profiles/ai-orchestration/semantics/consistent-help.md +13 -0
- package/dist/profiles/ai-orchestration/semantics/data-table.md +7 -1
- package/dist/profiles/ai-orchestration/semantics/dragging-alternative.md +13 -0
- package/dist/profiles/ai-orchestration/semantics/expanded-state.md +6 -0
- package/dist/profiles/ai-orchestration/semantics/focus.initial.md +4 -0
- package/dist/profiles/ai-orchestration/semantics/focus.return.md +4 -0
- package/dist/profiles/ai-orchestration/semantics/focus.visible.md +8 -1
- package/dist/profiles/ai-orchestration/semantics/form-error.md +8 -1
- package/dist/profiles/ai-orchestration/semantics/form-label.md +7 -0
- package/dist/profiles/ai-orchestration/semantics/form-required.md +7 -0
- package/dist/profiles/ai-orchestration/semantics/headings.md +7 -0
- package/dist/profiles/ai-orchestration/semantics/keyboard.escape.md +4 -0
- package/dist/profiles/ai-orchestration/semantics/keyboard.md +7 -0
- package/dist/profiles/ai-orchestration/semantics/landmarks.md +6 -0
- package/dist/profiles/ai-orchestration/semantics/live-status.md +7 -1
- package/dist/profiles/ai-orchestration/semantics/media-alternatives.md +11 -0
- package/dist/profiles/ai-orchestration/semantics/motion-control.md +8 -1
- package/dist/profiles/ai-orchestration/semantics/name-role-value.md +6 -1
- package/dist/profiles/ai-orchestration/semantics/native-dialog.md +7 -0
- package/dist/profiles/ai-orchestration/semantics/native-elements.md +5 -0
- package/dist/profiles/ai-orchestration/semantics/non-text-alternative.md +5 -0
- package/dist/profiles/ai-orchestration/semantics/redundant-entry.md +13 -0
- package/dist/profiles/ai-orchestration/semantics/roles-states-properties.md +6 -0
- package/dist/profiles/ai-orchestration/semantics/selected-state.md +6 -0
- package/dist/profiles/ai-orchestration/semantics/target-size.md +6 -1
- package/dist/profiles/ai-orchestration/semantics.json +843 -100
- package/dist/profiles/ai-orchestration/testing/accessibility.md +33 -3
- package/dist/profiles/ai-orchestration/ui-design-brain-bindings.json +836 -0
- package/dist/profiles/conductor/a11y-semantics.md +270 -10
- package/dist/profiles/conductor/accessibility-quality.md +557 -1
- package/dist/profiles/conductor/applicability-matrix.json +270 -230
- package/dist/profiles/conductor/coverage-manifest.json +724 -68
- package/dist/profiles/conductor/pattern-contracts.json +1015 -343
- package/dist/profiles/conductor/patterns/accordion.json +42 -24
- package/dist/profiles/conductor/patterns/alert.json +36 -18
- package/dist/profiles/conductor/patterns/carousel.json +43 -25
- package/dist/profiles/conductor/patterns/checkbox.json +67 -0
- package/dist/profiles/conductor/patterns/combobox.json +44 -26
- package/dist/profiles/conductor/patterns/consequential-submission.json +41 -22
- package/dist/profiles/conductor/patterns/dialog.json +44 -26
- package/dist/profiles/conductor/patterns/disclosure.json +40 -22
- package/dist/profiles/conductor/patterns/dynamic-status.json +38 -19
- package/dist/profiles/conductor/patterns/field.json +58 -22
- package/dist/profiles/conductor/patterns/image.json +48 -19
- package/dist/profiles/conductor/patterns/listbox.json +42 -24
- package/dist/profiles/conductor/patterns/media-player.json +76 -26
- package/dist/profiles/conductor/patterns/menu-button.json +41 -23
- package/dist/profiles/conductor/patterns/menu.json +78 -0
- package/dist/profiles/conductor/patterns/pagination.json +41 -22
- package/dist/profiles/conductor/patterns/popover.json +49 -23
- package/dist/profiles/conductor/patterns/progress.json +45 -20
- package/dist/profiles/conductor/patterns/radio-group.json +69 -0
- package/dist/profiles/conductor/patterns/slider.json +84 -0
- package/dist/profiles/conductor/patterns/spinbutton.json +74 -0
- package/dist/profiles/conductor/patterns/tabs.json +41 -23
- package/dist/profiles/conductor/patterns/tooltip.json +38 -20
- package/dist/profiles/conductor/patterns/tree-view.json +77 -0
- package/dist/profiles/conductor/patterns/validation.json +59 -23
- package/dist/profiles/conductor/semantics.json +843 -100
- package/dist/profiles/conductor/ui-design-brain-bindings.json +836 -0
- package/dist/projection-manifest.json +123 -82
- package/dist/requirements-to-implementation.md +8 -0
- package/lib/build-manifest.mjs +12 -6
- package/lib/build.mjs +21 -7
- package/lib/compile-applicability.mjs +131 -10
- package/lib/coverage.mjs +20 -0
- package/lib/digest.mjs +8 -0
- package/lib/index.mjs +1 -1
- package/lib/load.mjs +44 -1
- package/lib/provenance.mjs +51 -0
- package/lib/render.mjs +115 -31
- package/lib/sync.mjs +242 -28
- package/lib/validate.mjs +557 -24
- package/package.json +27 -10
- package/profiles/ai-orchestration/profile.json +1 -1
- package/profiles/ai-orchestration/templates/patterns/README.md +1 -1
- package/profiles/ai-orchestration/templates/review/README.md +1 -1
- package/profiles/ai-orchestration/templates/semantics/README.md +1 -1
- package/profiles/ai-orchestration/templates/testing/README.md +1 -1
- package/profiles/conductor/profile.json +1 -1
- package/profiles/conductor/templates/evidence/README.md +1 -1
- package/profiles/conductor/templates/patterns/README.md +1 -1
- package/profiles/conductor/templates/semantics/README.md +1 -1
- package/schemas/consumer-config.schema.json +1 -1
- package/schemas/contract.schema.json +1 -0
- package/schemas/manifest.schema.json +1 -1
- package/schemas/pattern.schema.json +98 -1
- package/schemas/profile.schema.json +1 -1
- package/schemas/projection-manifest.schema.json +84 -1
- package/schemas/semantic.schema.json +26 -1
- package/schemas/standards-reference.schema.json +105 -0
- package/schemas/ui-design-brain-bindings.schema.json +86 -0
- package/schemas/wcag-coverage.schema.json +93 -0
- package/src/applicability/facts.yml +27 -1
- package/src/applicability/matrix.yml +8 -9
- package/src/applicability/ui-design-brain-bindings.yml +196 -0
- package/src/contract.yml +1 -0
- package/src/coverage/wcag-2.2.yml +68 -0
- package/src/patterns/disclosure/accordion.yml +1 -1
- package/src/patterns/disclosure/disclosure.yml +1 -1
- package/src/patterns/feedback/alert.yml +1 -1
- package/src/patterns/feedback/dynamic-status.yml +1 -1
- package/src/patterns/feedback/progress.yml +1 -1
- package/src/patterns/forms/consequential-submission.yml +1 -1
- package/src/patterns/forms/field.yml +1 -1
- package/src/patterns/forms/spinbutton.yml +1 -0
- package/src/patterns/forms/validation.yml +1 -1
- package/src/patterns/media/carousel.yml +1 -1
- package/src/patterns/media/image.yml +1 -1
- package/src/patterns/media/media-player.yml +1 -1
- package/src/patterns/navigation/menu-button.yml +1 -1
- package/src/patterns/navigation/menu.yml +1 -0
- package/src/patterns/navigation/pagination.yml +1 -1
- package/src/patterns/navigation/tabs.yml +1 -1
- package/src/patterns/navigation/tree-view.yml +1 -0
- package/src/patterns/overlays/dialog.yml +1 -1
- package/src/patterns/overlays/popover.yml +1 -1
- package/src/patterns/overlays/tooltip.yml +1 -1
- package/src/patterns/selection/checkbox.yml +1 -0
- package/src/patterns/selection/combobox.yml +1 -1
- package/src/patterns/selection/listbox.yml +1 -1
- package/src/patterns/selection/radio-group.yml +1 -0
- package/src/patterns/selection/slider.yml +1 -0
- package/src/semantics/accessible-names.yml +1 -1
- package/src/semantics/forms.yml +1 -1
- package/src/semantics/headings-landmarks.yml +1 -1
- package/src/semantics/keyboard-focus.yml +1 -1
- package/src/semantics/live-regions.yml +1 -1
- package/src/semantics/media.yml +1 -1
- package/src/semantics/native-elements.yml +1 -1
- package/src/semantics/roles-states-properties.yml +1 -1
- package/src/semantics/tables.yml +1 -1
- package/src/semantics/wcag-2.2.yml +1 -0
- package/src/sources.yml +1 -1
|
@@ -1,90 +1,131 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
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
|
-
"
|
|
5
|
-
"version": "1.0.0",
|
|
9
|
+
"ai-orchestration": {
|
|
6
10
|
"outputs": {
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"pattern:pattern.
|
|
14
|
-
"pattern:pattern.
|
|
15
|
-
"pattern:pattern.
|
|
16
|
-
"pattern:pattern.
|
|
17
|
-
"pattern:pattern.
|
|
18
|
-
"pattern:pattern.
|
|
19
|
-
"pattern:pattern.
|
|
20
|
-
"pattern:pattern.
|
|
21
|
-
"pattern:pattern.
|
|
22
|
-
"pattern:pattern.
|
|
23
|
-
"pattern:pattern.
|
|
24
|
-
"pattern:pattern.
|
|
25
|
-
"pattern:pattern.
|
|
26
|
-
"pattern:pattern.
|
|
27
|
-
"pattern:pattern.
|
|
28
|
-
"pattern:pattern.
|
|
29
|
-
"pattern:pattern.
|
|
30
|
-
"pattern:pattern.
|
|
31
|
-
"pattern:pattern.
|
|
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
|
-
"
|
|
35
|
-
"version": "1.0.0",
|
|
77
|
+
"conductor": {
|
|
36
78
|
"outputs": {
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
package/lib/build-manifest.mjs
CHANGED
|
@@ -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.
|
|
9
|
+
package: `@verndale/accessibility-standards@${data.contract.package_version}`,
|
|
8
10
|
profile,
|
|
9
|
-
profile_version:
|
|
10
|
-
schema_version:
|
|
11
|
+
profile_version: data.profiles[profile].version,
|
|
12
|
+
schema_version: data.contract.schema_version,
|
|
11
13
|
digests: {
|
|
12
|
-
source:
|
|
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
|
-
|
|
17
|
-
|
|
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] = {
|
|
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 = {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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')
|
|
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 (
|
|
16
|
-
|
|
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')
|
|
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(
|
|
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) =>
|
|
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 ? (
|
|
43
|
-
resolution_state: observed ? (
|
|
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);
|
package/lib/coverage.mjs
ADDED
|
@@ -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';
|