@verndale/accessibility-standards 1.0.0 → 2.0.1
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 +2 -0
- package/README.md +4 -0
- package/bin/accessibility-standards.mjs +1 -1
- package/dist/manifest.json +39 -21
- package/dist/profiles/ai-orchestration/coverage-manifest.json +109 -2
- package/dist/profiles/ai-orchestration/implementation/accessibility.md +334 -0
- package/dist/profiles/ai-orchestration/pattern-contracts.json +125 -39
- package/dist/profiles/ai-orchestration/patterns/accordion.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/alert.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/carousel.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/combobox.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/consequential-submission.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/dialog.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/disclosure.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/dynamic-status.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/field.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/image.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/listbox.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/media-player.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/menu-button.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/pagination.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/popover.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/progress.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/tabs.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/tooltip.md +9 -0
- package/dist/profiles/ai-orchestration/patterns/validation.md +9 -0
- package/dist/profiles/ai-orchestration/review/accessibility.md +8 -1
- package/dist/profiles/ai-orchestration/semantics/accessible-name.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/alert.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/consequential-action.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/data-table.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/expanded-state.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/focus.initial.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/focus.return.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/focus.visible.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/form-error.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/form-label.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/form-required.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/headings.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/keyboard.escape.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/keyboard.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/landmarks.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/live-status.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/media-alternatives.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/motion-control.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/name-role-value.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/native-dialog.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/native-elements.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/non-text-alternative.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/roles-states-properties.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/selected-state.md +1 -0
- package/dist/profiles/ai-orchestration/semantics/target-size.md +1 -0
- package/dist/profiles/ai-orchestration/semantics.json +48 -1
- package/dist/profiles/ai-orchestration/testing/accessibility.md +1 -1
- package/dist/profiles/ai-orchestration/ui-design-brain-bindings.json +856 -0
- package/dist/profiles/conductor/a11y-semantics.md +22 -1
- package/dist/profiles/conductor/accessibility-quality.md +314 -0
- package/dist/profiles/conductor/applicability-matrix.json +111 -28
- package/dist/profiles/conductor/coverage-manifest.json +109 -2
- package/dist/profiles/conductor/pattern-contracts.json +125 -39
- package/dist/profiles/conductor/patterns/accordion.json +13 -3
- package/dist/profiles/conductor/patterns/alert.json +13 -3
- package/dist/profiles/conductor/patterns/carousel.json +13 -3
- package/dist/profiles/conductor/patterns/combobox.json +13 -3
- package/dist/profiles/conductor/patterns/consequential-submission.json +13 -3
- package/dist/profiles/conductor/patterns/dialog.json +13 -3
- package/dist/profiles/conductor/patterns/disclosure.json +13 -3
- package/dist/profiles/conductor/patterns/dynamic-status.json +13 -3
- package/dist/profiles/conductor/patterns/field.json +23 -3
- package/dist/profiles/conductor/patterns/image.json +23 -3
- package/dist/profiles/conductor/patterns/listbox.json +13 -3
- package/dist/profiles/conductor/patterns/media-player.json +23 -3
- package/dist/profiles/conductor/patterns/menu-button.json +13 -3
- package/dist/profiles/conductor/patterns/pagination.json +13 -3
- package/dist/profiles/conductor/patterns/popover.json +13 -3
- package/dist/profiles/conductor/patterns/progress.json +13 -3
- package/dist/profiles/conductor/patterns/tabs.json +13 -3
- package/dist/profiles/conductor/patterns/tooltip.json +13 -3
- package/dist/profiles/conductor/patterns/validation.json +23 -3
- package/dist/profiles/conductor/semantics.json +48 -1
- package/dist/profiles/conductor/ui-design-brain-bindings.json +856 -0
- package/dist/projection-manifest.json +103 -78
- package/dist/requirements-to-implementation.md +2 -0
- package/lib/build-manifest.mjs +12 -6
- package/lib/build.mjs +19 -5
- package/lib/compile-applicability.mjs +131 -10
- package/lib/coverage.mjs +20 -0
- package/lib/index.mjs +1 -1
- package/lib/load.mjs +31 -1
- package/lib/provenance.mjs +49 -0
- package/lib/render.mjs +69 -29
- package/lib/sync.mjs +240 -26
- package/lib/validate.mjs +255 -24
- package/package.json +24 -11
- package/profiles/ai-orchestration/profile.json +1 -1
- package/profiles/conductor/profile.json +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/projection-manifest.schema.json +84 -1
- package/schemas/ui-design-brain-bindings.schema.json +86 -0
- package/src/applicability/facts.yml +29 -1
- package/src/applicability/matrix.yml +3 -2
- package/src/applicability/ui-design-brain-bindings.yml +210 -0
- package/src/contract.yml +1 -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/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/pagination.yml +1 -1
- package/src/patterns/navigation/tabs.yml +1 -1
- 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/combobox.yml +1 -1
- package/src/patterns/selection/listbox.yml +1 -1
|
@@ -1,89 +1,114 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"_generated": "GENERATED by @verndale/accessibility-standards; DO NOT EDIT",
|
|
3
|
+
"package": "@verndale/accessibility-standards@2.0.1",
|
|
4
|
+
"schema_version": 2,
|
|
5
|
+
"source_digest": "5123634b229ba2ada6a8270b53276f3074ed628c8d8a32db26b88ae7688df49b",
|
|
6
|
+
"profile_digests": {
|
|
7
|
+
"ai-orchestration": "f8485b4e166fe305a4a779a00700f8b9fc7e8b8f49904d24ddcdac016a5792a3",
|
|
8
|
+
"conductor": "069380251e64944daa1a46c330787d343ebba9fc6baa3432341b8d4d15c30c62"
|
|
9
|
+
},
|
|
10
|
+
"ui_design_brain": {
|
|
11
|
+
"package": "@verndale/ui-design-brain",
|
|
12
|
+
"package_version": "1.16.1",
|
|
13
|
+
"catalog_authority_version": "1.15.1",
|
|
14
|
+
"repository": "https://github.com/verndale/ui-design-brain",
|
|
15
|
+
"manifest_path": "skills/ui-design-brain/catalog-manifest.json",
|
|
16
|
+
"source_digest": "sha256:1eda596fe341786b5ada25742b6487bc06685fff17cbd582bc1b58302097e3ff",
|
|
17
|
+
"manifest_digest": "sha256:63a0bc8d9537d6d4c0aef8fd8a539bf4a9181a50d0761bd63eae6fe59b4eddc9",
|
|
18
|
+
"pattern_count": 80,
|
|
19
|
+
"tracking_issue": "https://github.com/verndale/ui-design-brain/issues/47",
|
|
20
|
+
"binding_digest": "1106453e9511c79726a7785fc814abae484050cdef6a4ee3161b2421e43e6283"
|
|
21
|
+
},
|
|
3
22
|
"profiles": {
|
|
4
23
|
"conductor": {
|
|
5
|
-
"version": "
|
|
24
|
+
"version": "2.0.1",
|
|
25
|
+
"profile_digest": "069380251e64944daa1a46c330787d343ebba9fc6baa3432341b8d4d15c30c62",
|
|
26
|
+
"source_digest": "5123634b229ba2ada6a8270b53276f3074ed628c8d8a32db26b88ae7688df49b",
|
|
6
27
|
"outputs": {
|
|
7
|
-
"semanticsJson": "
|
|
8
|
-
"patternContracts": "
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
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.
|
|
28
|
+
"semanticsJson": "8f2c6c0d83be1f20776b6c20fd1fb013a9e3563a615ef3d922d083e9441f5bf1",
|
|
29
|
+
"patternContracts": "02419b9385dcfca3e67b75c7ecf936f54afedcc713d845f6968dc03cb81026bf",
|
|
30
|
+
"uiDesignBrainBindings": "3cf7972c3effbbd37bda6c5d8c2cd3e28f94f840b091e59dc31d02356af4cb64",
|
|
31
|
+
"coverageManifest": "e3d3e2d3c253202b028bd0ad22c1cf22b128d693744dee7b4824c0ee49643308",
|
|
32
|
+
"semanticsMarkdown": "3b18070d880f077402bd17b416aeb583bfc5f8217b4aaa923c121c35fd0e06a3",
|
|
33
|
+
"qualityMarkdown": "1ff4349bf7f3580d1c293fce4400ae771829f4b21a4e5e50bd6f63a2a11cb7fa",
|
|
34
|
+
"applicabilityMatrix": "c0ac3e247d65f2fb87bedcda6351fd4de66179f9328b55dfc7bf1b07a4b2eb52",
|
|
35
|
+
"pattern:pattern.accordion": "0b20178cca1e99e638a428cafcb0e378993a45b90d7d414ffa3d0bbafb42eb2a",
|
|
36
|
+
"pattern:pattern.alert": "cd825fceb005f4fe3da3c26032820d89118a36386b08fa17f8ded15cec7a2e74",
|
|
37
|
+
"pattern:pattern.carousel": "4980c2bec6cf16cc6b86b8bf937f7509192e2171d19fe5affae1a4d9143fb2af",
|
|
38
|
+
"pattern:pattern.combobox": "37dc19cd53e38fc0a33f36f1c3d9345e89f2a44dfc594ef295a77ed048636702",
|
|
39
|
+
"pattern:pattern.consequential-submission": "c013711e800c8601fd16205bdf04c146340b4ca7a7e9c3aadac5694298f3bb5c",
|
|
40
|
+
"pattern:pattern.dialog": "ef4faa1ad8cb764f89503795a125fab13ccd90f7df6e8c1c9e19e619379cec1e",
|
|
41
|
+
"pattern:pattern.disclosure": "18d4aff26ec8425aebf4df695be2b3285bcfb27695e7da109d5be2e468d3872f",
|
|
42
|
+
"pattern:pattern.dynamic-status": "62fab323e37906975b49cbd49975087c14a49f07eab5c015ad4d04b0c4330ca9",
|
|
43
|
+
"pattern:pattern.field": "9c27beaf15d7d3dc6b75641f4b15c80fcfca3ba1d97c92404394f479c06b47eb",
|
|
44
|
+
"pattern:pattern.image": "f23a7d8ba3bf7c00743ea8b84cdc1fb651541144287877f5118a77e5a86ae875",
|
|
45
|
+
"pattern:pattern.listbox": "12b8bab35a5a0a84ebd282c8a6b0b807dda7fc6a873d9821a8de042a5e687341",
|
|
46
|
+
"pattern:pattern.media-player": "248fba4130e25d40d9abad883892e3df2a86fbc84e2030ee7b583ee6a7ea3e66",
|
|
47
|
+
"pattern:pattern.menu-button": "7237b478cd87a30bc9b1dfcddbd57b59458df567d8090aa3c686c6d703881b80",
|
|
48
|
+
"pattern:pattern.pagination": "ce72bc16035153887037b9ee33deeaf1a7f7a63a9a7968c9ae9324ebd364d03a",
|
|
49
|
+
"pattern:pattern.popover": "191cb777fc71fac1531714bf769d9d70ff320fb751b3794a89d9f050a14363a9",
|
|
50
|
+
"pattern:pattern.progress": "6d4eb86d28acbba1391d26b30df0551471633bbf8e10abc2217b0659fe71ef66",
|
|
51
|
+
"pattern:pattern.tabs": "1a71a5e43da742e635c5c5506f112652ad50ac479c471ab899db5bee037b4228",
|
|
52
|
+
"pattern:pattern.tooltip": "d0c96e6dc1488c4fbf0dae7c51ca60138ab9d03a8bd2dcf9752018c8cda34e03",
|
|
53
|
+
"pattern:pattern.validation": "0f82ee9d33bf07091db2c52da5da0e5b7cb319804cbaa2ec77b6d1bd34c95661"
|
|
32
54
|
}
|
|
33
55
|
},
|
|
34
56
|
"ai-orchestration": {
|
|
35
|
-
"version": "
|
|
57
|
+
"version": "2.0.1",
|
|
58
|
+
"profile_digest": "f8485b4e166fe305a4a779a00700f8b9fc7e8b8f49904d24ddcdac016a5792a3",
|
|
59
|
+
"source_digest": "5123634b229ba2ada6a8270b53276f3074ed628c8d8a32db26b88ae7688df49b",
|
|
36
60
|
"outputs": {
|
|
37
|
-
"semanticsJson": "
|
|
38
|
-
"patternContracts": "
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"semantic:semantics.
|
|
42
|
-
"semantic:semantics.
|
|
43
|
-
"semantic:semantics.
|
|
44
|
-
"semantic:semantics.
|
|
45
|
-
"semantic:semantics.
|
|
46
|
-
"semantic:semantics.focus.
|
|
47
|
-
"semantic:semantics.focus.
|
|
48
|
-
"semantic:semantics.
|
|
49
|
-
"semantic:semantics.form-
|
|
50
|
-
"semantic:semantics.form-
|
|
51
|
-
"semantic:semantics.
|
|
52
|
-
"semantic:semantics.
|
|
53
|
-
"semantic:semantics.keyboard
|
|
54
|
-
"semantic:semantics.
|
|
55
|
-
"semantic:semantics.
|
|
56
|
-
"semantic:semantics.
|
|
57
|
-
"semantic:semantics.
|
|
58
|
-
"semantic:semantics.
|
|
59
|
-
"semantic:semantics.
|
|
60
|
-
"semantic:semantics.native-
|
|
61
|
-
"semantic:semantics.
|
|
62
|
-
"semantic:semantics.
|
|
63
|
-
"semantic:semantics.
|
|
64
|
-
"semantic:semantics.
|
|
65
|
-
"
|
|
66
|
-
"pattern:pattern.
|
|
67
|
-
"pattern:pattern.
|
|
68
|
-
"pattern:pattern.
|
|
69
|
-
"pattern:pattern.
|
|
70
|
-
"pattern:pattern.
|
|
71
|
-
"pattern:pattern.
|
|
72
|
-
"pattern:pattern.
|
|
73
|
-
"pattern:pattern.
|
|
74
|
-
"pattern:pattern.
|
|
75
|
-
"pattern:pattern.
|
|
76
|
-
"pattern:pattern.
|
|
77
|
-
"pattern:pattern.
|
|
78
|
-
"pattern:pattern.
|
|
79
|
-
"pattern:pattern.
|
|
80
|
-
"pattern:pattern.
|
|
81
|
-
"pattern:pattern.
|
|
82
|
-
"pattern:pattern.
|
|
83
|
-
"pattern:pattern.
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
61
|
+
"semanticsJson": "d01d308e0bd62b2604b61e959165a6135d9b3efacf88f72536426e3de99c16be",
|
|
62
|
+
"patternContracts": "2c9753899b83f9bef94beb58bfeb65d23e1f723d88ea328a2eae92a563bea51d",
|
|
63
|
+
"uiDesignBrainBindings": "54cd18f5a4cb86eaad65a539e92df9ffbf49784140bf1f1afdf7b55e3deb970f",
|
|
64
|
+
"coverageManifest": "bcf084bd8bd2a376ca8e8510f6a836f3033c337bea9886a13f95f6413b73b9e1",
|
|
65
|
+
"semantic:semantics.accessible-name": "ac717e3e5b1f54a3759ee258426282c970799d821cbfec2573a256ef0f93d198",
|
|
66
|
+
"semantic:semantics.alert": "69df4f7ff7256991b36c437675dae3e2d8f2951648092e96eb2610e66c4c7b50",
|
|
67
|
+
"semantic:semantics.consequential-action": "f100811f576fe36b26897b7d5df6cc88f5cf9c03152f3fdd8ec5c9cf94d60877",
|
|
68
|
+
"semantic:semantics.data-table": "fe6f8035399b597497410ab71bab59cbc040b46d4707cbd68e70c3ed3ea25c7f",
|
|
69
|
+
"semantic:semantics.expanded-state": "0b5187a17e8bf5ba9708bbd2e5677c9000c9eb2e0b3e3145649f4c2cd0bc4fe4",
|
|
70
|
+
"semantic:semantics.focus.initial": "9cdfc4646eaa219d9408476d0601eeeec605933b82f46ab0bc1a62f291bdfeea",
|
|
71
|
+
"semantic:semantics.focus.return": "c927f19fd01da8cb94d7b68f8deff2ee0692588164f7e9d904ecfd8a69e7cc61",
|
|
72
|
+
"semantic:semantics.focus.visible": "7070e7d919760d4a696d9c144a2bdf03f06ab90ef04e76c1044d413ec9c65e74",
|
|
73
|
+
"semantic:semantics.form-error": "ede73a50abe3d9c9621ce9759db643b8a4adae88e7d18d05348355e03c89032f",
|
|
74
|
+
"semantic:semantics.form-label": "b9ad6a8d525ce254de1c5e35857a95995674874e34dcaeb3e3116c79c73d5e45",
|
|
75
|
+
"semantic:semantics.form-required": "f15b969fd6e1449dc40d598a24ecb9b47cd79f1d16d52f2de2b92b92a17ea004",
|
|
76
|
+
"semantic:semantics.headings": "675428ed4f6679d35d1aa4396b072e10567343f96eeb860187bd288e0939166d",
|
|
77
|
+
"semantic:semantics.keyboard": "a5bd02f15acc81ae986c21dbeebb892bce0ea077a190a10c3d8049980348fff2",
|
|
78
|
+
"semantic:semantics.keyboard.escape": "321aea514eb75bd60a7860e3c746948ba0a3b0b7c8cc24ae0ca6d8ff0d9b6ec1",
|
|
79
|
+
"semantic:semantics.landmarks": "858a12655a0d55c0c0a2b5d3c8cddc348c7684b4aa0d0d41f179bcdc922ec71b",
|
|
80
|
+
"semantic:semantics.live-status": "d640e1c350225a0e960184780ec8e7d8a9b9c351064a602225325fa76ed556e4",
|
|
81
|
+
"semantic:semantics.media-alternatives": "8a604ac5ed6a2538ef94147be0459c86d0e368b841cdfe5b4ef7d5d36a09704d",
|
|
82
|
+
"semantic:semantics.motion-control": "66e52b195c8f7dce3c45661aeffc614e67233576c287f9efdb4c30a6cabeb1d1",
|
|
83
|
+
"semantic:semantics.name-role-value": "63dbbf49b073516f58a9b9ab6d0f444cc7754d1ab088e7375f5727a190dd33d6",
|
|
84
|
+
"semantic:semantics.native-dialog": "66f01cf9749b53e451e87d0324cdb2f9ebd19b2d0420bc3be1bba7b8cf0a3fa3",
|
|
85
|
+
"semantic:semantics.native-elements": "117048ea93c2cd13348bc89979d632e42f6190d582e6d57cce0ab9c8b942d2f1",
|
|
86
|
+
"semantic:semantics.non-text-alternative": "6b94a2b3545e435848e9c0ca2e4244614596e4ca0ef93885b2906b18ddc3e6f2",
|
|
87
|
+
"semantic:semantics.roles-states-properties": "da19e87f357ddf83985135bd9a7792fc9468e0c9e1163af4d41f4ca99831e2bf",
|
|
88
|
+
"semantic:semantics.selected-state": "91aebde167d9d5691ff44f30dfbd49bf555c081b5c36d42f67d4d093f5c481e5",
|
|
89
|
+
"semantic:semantics.target-size": "8a6ceb67138b69a427ca4ff3a89124202d16b04c95060d7d6592c54c14b57455",
|
|
90
|
+
"pattern:pattern.accordion": "2a059b7a1a336c94e18bb9995f13b7209ef36071aaf90aa969663fa8ae6eb4ca",
|
|
91
|
+
"pattern:pattern.alert": "aa9264c94a707a79b303b8242c23f7ceb4d4375e86507101faa9b2ac933c1b1c",
|
|
92
|
+
"pattern:pattern.carousel": "3baa3ec97f1a787d356250830684501750ea9f77a3df4c1713fdbe194d9c586a",
|
|
93
|
+
"pattern:pattern.combobox": "36eeb654fe377713ab50510e8f16f96a0ca6575c87416f21282795878849755b",
|
|
94
|
+
"pattern:pattern.consequential-submission": "1f40622c73862eba814664e463dcab308b134d9142990ecabfb4a613ab9f20a3",
|
|
95
|
+
"pattern:pattern.dialog": "cad4742a336400fa7a0c6e98cc258c67f40c31a7c80e054a9817693d7f5837e1",
|
|
96
|
+
"pattern:pattern.disclosure": "3c03a9d3cc8e3830fc73a26c346a4de3fe33b658f8a4ff6052dae665c56a27df",
|
|
97
|
+
"pattern:pattern.dynamic-status": "dd408f622036523ae218a8f41aca2716c78b33b7bc38405286d090f906ff2eb5",
|
|
98
|
+
"pattern:pattern.field": "dbe384e20b6f18360916f82b622a33a89c9e617dbe2e701394621bc41cb63125",
|
|
99
|
+
"pattern:pattern.image": "586af652655d2c0204c825be3d3dce3790ad11bc21de752d97b9976f3b30c2cd",
|
|
100
|
+
"pattern:pattern.listbox": "b18043177f836822682697f3e9fe102da62d2522e540332bffe70b36b5320733",
|
|
101
|
+
"pattern:pattern.media-player": "5f768c253378354f3cace814229f91d868865226ccfc23f5d9960723fa993868",
|
|
102
|
+
"pattern:pattern.menu-button": "0085506dd790b9227e9184a73f9e543bb808db648c62946180f862af24ff15f6",
|
|
103
|
+
"pattern:pattern.pagination": "9070076beb3f8efc290b2a1f49621851c0c8f07d52eedd8d2b01e50f201e855f",
|
|
104
|
+
"pattern:pattern.popover": "c610acc17491133bddb5a2a22e40295baf576d288c7f1907bd4aafdde13d8ad4",
|
|
105
|
+
"pattern:pattern.progress": "f99175b95f7c211ca93af74e395487ec71f0c9e1a75ed77e81cd1302aa09bb0b",
|
|
106
|
+
"pattern:pattern.tabs": "3437f1ef34d0a3d5ce26832335141c0a33c955ef4b49b30b4bbc8241f504241b",
|
|
107
|
+
"pattern:pattern.tooltip": "90699272b0567fc8794db772874b92d83e98a3230611d2ff5130cdf9f4c5cf66",
|
|
108
|
+
"pattern:pattern.validation": "f6fe76815b12e3c3e51b3150290bcfb5e16ba9d394187b70e87e90d6cd30eda8",
|
|
109
|
+
"implementation": "66244ade0583c2aff561ef91d9deb77ab0fc7ee96abb83203d312746606cb360",
|
|
110
|
+
"testing": "2295b32e7d5d0cb74eb67100caeb26ec07ed0edc89f1bd603cb010c575220454",
|
|
111
|
+
"review": "f6cec148bc9e8901029afd56e759843728f7f884d73621f83aa8ac9be68971ae"
|
|
87
112
|
}
|
|
88
113
|
}
|
|
89
114
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
<!-- GENERATED by @verndale/accessibility-standards; DO NOT EDIT -->
|
|
2
|
+
<!-- package: @verndale/accessibility-standards@2.0.1; schema: 2; source-digest: 5123634b229ba2ada6a8270b53276f3074ed628c8d8a32db26b88ae7688df49b -->
|
|
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
|
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';
|
|
4
|
+
import { buildArtifacts, defaultPath, marker } from './render.mjs';
|
|
5
5
|
import { 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 = {
|
|
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
|
+
};
|
|
27
41
|
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'),
|
|
42
|
+
await writeFile(join(dist, 'projection-manifest.json'), `${JSON.stringify({ _generated: marker, package: manifest.package, schema_version: manifest.schema_version, source_digest: manifest.source_digest, profile_digests: manifest.profile_digests, ui_design_brain: manifest.ui_design_brain, profiles: profileManifests }, null, 2)}\n`);
|
|
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/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';
|
package/lib/load.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readdir, readFile } from 'node:fs/promises';
|
|
2
|
-
import { dirname, join } from 'node:path';
|
|
2
|
+
import { dirname, join, relative } from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
|
|
5
5
|
export const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
@@ -17,6 +17,24 @@ async function filesUnder(root) {
|
|
|
17
17
|
return nested.flat();
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
async function markdownFilesUnder(root) {
|
|
21
|
+
const entries = await readdir(root, { withFileTypes: true });
|
|
22
|
+
const nested = await Promise.all(entries.sort((a, b) => a.name.localeCompare(b.name)).map(async (entry) => {
|
|
23
|
+
const path = join(root, entry.name);
|
|
24
|
+
return entry.isDirectory() ? markdownFilesUnder(path) : path.endsWith('.md') ? [path] : [];
|
|
25
|
+
}));
|
|
26
|
+
return nested.flat();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function loadProfileTemplates(root, profile) {
|
|
30
|
+
const templatesRoot = join(root, 'profiles', profile, 'templates');
|
|
31
|
+
const templates = {};
|
|
32
|
+
for (const file of await markdownFilesUnder(templatesRoot)) {
|
|
33
|
+
templates[relative(templatesRoot, file).replaceAll('\\', '/')] = await readFile(file, 'utf8');
|
|
34
|
+
}
|
|
35
|
+
return templates;
|
|
36
|
+
}
|
|
37
|
+
|
|
20
38
|
export async function loadStandards(root = packageRoot) {
|
|
21
39
|
const semantics = [];
|
|
22
40
|
for (const file of await filesUnder(join(root, 'src', 'semantics'))) {
|
|
@@ -29,12 +47,24 @@ export async function loadStandards(root = packageRoot) {
|
|
|
29
47
|
for (const file of await filesUnder(join(root, 'src', 'foundations'))) foundations.push(await readJsonYaml(file));
|
|
30
48
|
const policies = [];
|
|
31
49
|
for (const file of await filesUnder(join(root, 'src', 'policies'))) policies.push(await readJsonYaml(file));
|
|
50
|
+
const profiles = {
|
|
51
|
+
conductor: JSON.parse(await readFile(join(root, 'profiles', 'conductor', 'profile.json'), 'utf8')),
|
|
52
|
+
'ai-orchestration': JSON.parse(await readFile(join(root, 'profiles', 'ai-orchestration', 'profile.json'), 'utf8')),
|
|
53
|
+
};
|
|
54
|
+
const profileTemplates = Object.fromEntries(await Promise.all(Object.keys(profiles).sort().map(async (profile) => [
|
|
55
|
+
profile,
|
|
56
|
+
await loadProfileTemplates(root, profile),
|
|
57
|
+
])));
|
|
32
58
|
return {
|
|
33
59
|
package: JSON.parse(await readFile(join(root, 'package.json'), 'utf8')),
|
|
60
|
+
contract: await readJsonYaml(join(root, 'src', 'contract.yml')),
|
|
34
61
|
sources: await readJsonYaml(join(root, 'src', 'sources.yml')),
|
|
35
62
|
facts: await readJsonYaml(join(root, 'src', 'applicability', 'facts.yml')),
|
|
36
63
|
matrix: await readJsonYaml(join(root, 'src', 'applicability', 'matrix.yml')),
|
|
64
|
+
uiDesignBrainBindings: await readJsonYaml(join(root, 'src', 'applicability', 'ui-design-brain-bindings.yml')),
|
|
37
65
|
evidence: await readJsonYaml(join(root, 'src', 'evidence', 'proof-routing.yml')),
|
|
66
|
+
profiles,
|
|
67
|
+
profileTemplates,
|
|
38
68
|
foundations, semantics, patterns, policies
|
|
39
69
|
};
|
|
40
70
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { digest } from './digest.mjs';
|
|
2
|
+
|
|
3
|
+
const byId = (left, right) => left.id.localeCompare(right.id);
|
|
4
|
+
|
|
5
|
+
function profileContractPayload(data, profile) {
|
|
6
|
+
const contract = data.profiles?.[profile];
|
|
7
|
+
const templates = data.profileTemplates?.[profile];
|
|
8
|
+
if (!contract || !templates) throw new Error(`Unknown profile contract: ${profile}`);
|
|
9
|
+
return { contract, templates };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function sourceContractPayload(data) {
|
|
13
|
+
return {
|
|
14
|
+
package: { name: data.package.name, version: data.package.version },
|
|
15
|
+
contract: data.contract,
|
|
16
|
+
sources: data.sources,
|
|
17
|
+
foundations: [...data.foundations].sort(byId),
|
|
18
|
+
semantics: [...data.semantics].sort(byId),
|
|
19
|
+
patterns: [...data.patterns].sort(byId),
|
|
20
|
+
policies: [...data.policies].sort(byId),
|
|
21
|
+
facts: data.facts,
|
|
22
|
+
matrix: data.matrix,
|
|
23
|
+
evidence: data.evidence,
|
|
24
|
+
ui_design_brain_bindings: data.uiDesignBrainBindings,
|
|
25
|
+
profiles: Object.fromEntries(Object.keys(data.profiles)
|
|
26
|
+
.sort()
|
|
27
|
+
.map((profile) => [profile, profileContractPayload(data, profile)])),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function sourceContractDigest(data) {
|
|
32
|
+
return digest(sourceContractPayload(data));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function profileContractDigest(data, profile) {
|
|
36
|
+
return digest(profileContractPayload(data, profile));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function projectionProvenance(data, profile) {
|
|
40
|
+
const profileContract = data.profiles[profile];
|
|
41
|
+
return {
|
|
42
|
+
package: `@verndale/accessibility-standards@${data.contract.package_version}`,
|
|
43
|
+
profile,
|
|
44
|
+
profile_version: profileContract.version,
|
|
45
|
+
profile_digest: profileContractDigest(data, profile),
|
|
46
|
+
schema_version: data.contract.schema_version,
|
|
47
|
+
source_digest: sourceContractDigest(data),
|
|
48
|
+
};
|
|
49
|
+
}
|