project-tiny-context-harness 0.8.4 → 0.8.6

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 (254) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +394 -363
  3. package/assets/README.md +570 -514
  4. package/assets/README.zh-CN.md +331 -300
  5. package/assets/agents/.gitkeep +1 -1
  6. package/assets/agents/AGENTS_CORE.md +45 -25
  7. package/assets/context_templates/architecture.md +26 -25
  8. package/assets/context_templates/area.md +32 -31
  9. package/assets/context_templates/context.toml +30 -24
  10. package/assets/context_templates/deployment.md +35 -35
  11. package/assets/context_templates/global.md +57 -57
  12. package/assets/context_templates/product-surface-contract.md +70 -70
  13. package/assets/context_templates/screen-contract.md +189 -189
  14. package/assets/context_templates/verification.md +31 -30
  15. package/assets/github/.gitkeep +1 -1
  16. package/assets/github/harness.yml +39 -39
  17. package/assets/make/.gitkeep +1 -1
  18. package/assets/make/ty-context.mk +48 -48
  19. package/assets/skills/context_development_engineer/SKILL.md +155 -122
  20. package/assets/skills/context_full_project_export/SKILL.md +28 -28
  21. package/assets/skills/context_harness_upgrade/SKILL.md +60 -60
  22. package/assets/skills/context_product_plan/SKILL.md +99 -79
  23. package/assets/skills/context_surface_contract/SKILL.md +191 -191
  24. package/assets/skills/context_uiux_design/SKILL.md +171 -171
  25. package/assets/skills/design-resource-authoring/SKILL.md +86 -84
  26. package/assets/skills/design-resource-authoring/references/downstream-handoff.md +138 -123
  27. package/assets/skills/design-resource-authoring/references/open-design-provider.md +132 -127
  28. package/assets/skills/design-resource-authoring/references/resource-selection.md +181 -154
  29. package/assets/skills/design-system-authoring/SKILL.md +57 -57
  30. package/assets/skills/design-system-authoring/agents/openai.yaml +6 -6
  31. package/assets/skills/design-system-authoring/references/authority-adoption.md +48 -48
  32. package/assets/skills/design-system-authoring/references/open-design-design-system-provider.md +110 -110
  33. package/assets/skills/long-task-workflow/SKILL.md +98 -92
  34. package/assets/skills/long-task-workflow/agents/openai.yaml +3 -1
  35. package/assets/skills/long-task-workflow/references/authority-lifecycle.md +72 -72
  36. package/assets/skills/long-task-workflow/references/contract-authoring.md +122 -101
  37. package/assets/skills/long-task-workflow/references/evidence-design.md +82 -61
  38. package/assets/skills/long-task-workflow/references/source-authoring.md +109 -90
  39. package/assets/skills/source-plan-authoring/SKILL.md +14 -14
  40. package/assets/tools/validate_context.py +442 -442
  41. package/dist/commands/long-task-authoring.js +27 -2
  42. package/dist/lib/context-default-footprint.js +2 -0
  43. package/dist/lib/context-manifest.js +6 -0
  44. package/dist/lib/context-templates.js +1 -1
  45. package/dist/lib/design-resource-fact-enums.d.ts +20 -0
  46. package/dist/lib/design-resource-fact-enums.js +170 -0
  47. package/dist/lib/design-resource-fact-locator-extractors.d.ts +8 -0
  48. package/dist/lib/design-resource-fact-locator-extractors.js +108 -0
  49. package/dist/lib/design-resource-fact-locator-resolver.d.ts +3 -0
  50. package/dist/lib/design-resource-fact-locator-resolver.js +112 -0
  51. package/dist/lib/design-resource-fact-locator-validation.d.ts +5 -0
  52. package/dist/lib/design-resource-fact-locator-validation.js +16 -0
  53. package/dist/lib/design-resource-fact-manifest-catalog.d.ts +4 -0
  54. package/dist/lib/design-resource-fact-manifest-catalog.js +249 -0
  55. package/dist/lib/design-resource-fact-manifest-model.d.ts +91 -0
  56. package/dist/lib/design-resource-fact-manifest-model.js +21 -0
  57. package/dist/lib/design-resource-fact-manifest-shape-axes.d.ts +6 -0
  58. package/dist/lib/design-resource-fact-manifest-shape-axes.js +159 -0
  59. package/dist/lib/design-resource-fact-manifest-shape-evidence.d.ts +4 -0
  60. package/dist/lib/design-resource-fact-manifest-shape-evidence.js +59 -0
  61. package/dist/lib/design-resource-fact-manifest-shape-facts.d.ts +4 -0
  62. package/dist/lib/design-resource-fact-manifest-shape-facts.js +109 -0
  63. package/dist/lib/design-resource-fact-manifest-shape-inspector.d.ts +5 -0
  64. package/dist/lib/design-resource-fact-manifest-shape-inspector.js +144 -0
  65. package/dist/lib/design-resource-fact-manifest-shape.d.ts +7 -0
  66. package/dist/lib/design-resource-fact-manifest-shape.js +75 -0
  67. package/dist/lib/design-resource-fact-manifest-types.d.ts +3 -0
  68. package/dist/lib/design-resource-fact-manifest-types.js +3 -0
  69. package/dist/lib/design-resource-fact-manifest-universe.d.ts +5 -0
  70. package/dist/lib/design-resource-fact-manifest-universe.js +50 -0
  71. package/dist/lib/design-resource-fact-manifest-validation.d.ts +3 -0
  72. package/dist/lib/design-resource-fact-manifest-validation.js +106 -0
  73. package/dist/lib/design-resource-fact-policy.d.ts +18 -0
  74. package/dist/lib/design-resource-fact-policy.js +72 -1
  75. package/dist/lib/design-resource-fact-property-methods.d.ts +3 -0
  76. package/dist/lib/design-resource-fact-property-methods.js +158 -0
  77. package/dist/lib/design-resource-fact-shape-primitives.d.ts +3 -0
  78. package/dist/lib/design-resource-fact-shape-primitives.js +18 -0
  79. package/dist/lib/design-resource-fact-types.d.ts +164 -0
  80. package/dist/lib/design-resource-fact-types.js +1 -0
  81. package/dist/lib/design-resource-fact-universe-assets.d.ts +4 -0
  82. package/dist/lib/design-resource-fact-universe-assets.js +71 -0
  83. package/dist/lib/design-resource-fact-universe-catalog.d.ts +4 -0
  84. package/dist/lib/design-resource-fact-universe-catalog.js +151 -0
  85. package/dist/lib/design-resource-fact-universe-conditions.d.ts +2 -0
  86. package/dist/lib/design-resource-fact-universe-conditions.js +92 -0
  87. package/dist/lib/design-resource-fact-universe-facts.d.ts +4 -0
  88. package/dist/lib/design-resource-fact-universe-facts.js +108 -0
  89. package/dist/lib/design-resource-fact-universe-helpers.d.ts +30 -0
  90. package/dist/lib/design-resource-fact-universe-helpers.js +167 -0
  91. package/dist/lib/design-resource-fact-universe-inspector.d.ts +7 -0
  92. package/dist/lib/design-resource-fact-universe-inspector.js +119 -0
  93. package/dist/lib/design-resource-fact-universe-proof.d.ts +4 -0
  94. package/dist/lib/design-resource-fact-universe-proof.js +113 -0
  95. package/dist/lib/design-resource-fact-universe-subjects.d.ts +5 -0
  96. package/dist/lib/design-resource-fact-universe-subjects.js +97 -0
  97. package/dist/lib/design-resource-fact-universe-variations.d.ts +2 -0
  98. package/dist/lib/design-resource-fact-universe-variations.js +75 -0
  99. package/dist/lib/design-resource-fact-value-validation.d.ts +2 -0
  100. package/dist/lib/design-resource-fact-value-validation.js +80 -0
  101. package/dist/lib/design-resource-handoff-file-primitives.js +2 -0
  102. package/dist/lib/design-resource-handoff-file-validation.js +13 -100
  103. package/dist/lib/design-resource-handoff-policy.d.ts +1 -0
  104. package/dist/lib/design-resource-handoff-policy.js +118 -11
  105. package/dist/lib/design-resource-handoff-shape-evidence.js +46 -3
  106. package/dist/lib/design-resource-handoff-shape-primitives.d.ts +5 -0
  107. package/dist/lib/design-resource-handoff-shape-primitives.js +28 -0
  108. package/dist/lib/design-resource-handoff-shape-structure.js +143 -22
  109. package/dist/lib/design-resource-handoff-shape.js +25 -0
  110. package/dist/lib/design-resource-handoff-types.d.ts +97 -21
  111. package/dist/lib/design-resource-handoff-types.js +22 -0
  112. package/dist/lib/design-resource-handoff-validation-coverage.d.ts +1 -1
  113. package/dist/lib/design-resource-handoff-validation-coverage.js +145 -118
  114. package/dist/lib/design-resource-handoff-validation-fact-cells.d.ts +2 -0
  115. package/dist/lib/design-resource-handoff-validation-fact-cells.js +60 -0
  116. package/dist/lib/design-resource-handoff-validation-fact-records.d.ts +2 -0
  117. package/dist/lib/design-resource-handoff-validation-fact-records.js +90 -0
  118. package/dist/lib/design-resource-handoff-validation-facts.js +10 -94
  119. package/dist/lib/design-resource-handoff-validation-proofs.d.ts +2 -0
  120. package/dist/lib/design-resource-handoff-validation-proofs.js +67 -0
  121. package/dist/lib/design-resource-handoff-validation-resource-closure.d.ts +3 -0
  122. package/dist/lib/design-resource-handoff-validation-resource-closure.js +88 -0
  123. package/dist/lib/design-resource-handoff-validation-structure.js +43 -14
  124. package/dist/lib/design-resource-handoff-validation.js +32 -0
  125. package/dist/lib/design-resource-handoff-web-dependency-validation.d.ts +2 -1
  126. package/dist/lib/design-resource-handoff-web-dependency-validation.js +67 -7
  127. package/dist/lib/execution-target-capabilities.d.ts +1 -1
  128. package/dist/lib/execution-target-capabilities.js +14 -0
  129. package/dist/lib/long-task-activation-validation.js +6 -2
  130. package/dist/lib/long-task-applicability-shape.js +3 -3
  131. package/dist/lib/long-task-authoring-authority-preview.js +1 -0
  132. package/dist/lib/long-task-authority-policy.d.ts +1 -0
  133. package/dist/lib/long-task-authority-policy.js +1 -0
  134. package/dist/lib/long-task-authority.js +13 -0
  135. package/dist/lib/long-task-claim-definitions.js +13 -1
  136. package/dist/lib/long-task-claims.js +23 -1
  137. package/dist/lib/long-task-contract-types.d.ts +3 -0
  138. package/dist/lib/long-task-delivery-compiler.js +1 -0
  139. package/dist/lib/long-task-delivery-parser.js +11 -1
  140. package/dist/lib/long-task-delivery-types.d.ts +1 -0
  141. package/dist/lib/long-task-delivery-types.js +1 -0
  142. package/dist/lib/long-task-delivery-validation.js +17 -0
  143. package/dist/lib/long-task-design-resource-handoff.js +62 -38
  144. package/dist/lib/long-task-design-target-capabilities.d.ts +14 -0
  145. package/dist/lib/long-task-design-target-capabilities.js +126 -0
  146. package/dist/lib/long-task-evidence-capability-codec.d.ts +94 -0
  147. package/dist/lib/long-task-evidence-capability-codec.js +395 -22
  148. package/dist/lib/long-task-evidence-capability-policy.js +18 -0
  149. package/dist/lib/long-task-evidence-capability-runtime.js +78 -0
  150. package/dist/lib/long-task-evidence-capability-types.d.ts +114 -1
  151. package/dist/lib/long-task-outcome-parser.js +4 -0
  152. package/dist/lib/long-task-playwright-capability-records.d.ts +5 -0
  153. package/dist/lib/long-task-playwright-capability-records.js +146 -0
  154. package/dist/lib/long-task-playwright-case-evidence.d.ts +3 -2
  155. package/dist/lib/long-task-playwright-case-evidence.js +10 -79
  156. package/dist/lib/long-task-playwright-case-primitives.d.ts +28 -0
  157. package/dist/lib/long-task-playwright-case-primitives.js +143 -0
  158. package/dist/lib/long-task-playwright-evidence.d.ts +1 -1
  159. package/dist/lib/long-task-playwright-evidence.js +10 -75
  160. package/dist/lib/long-task-runner-freeze.d.ts +2 -2
  161. package/dist/lib/long-task-runner-freeze.js +15 -1
  162. package/dist/lib/long-task-runtime-types.d.ts +4 -1
  163. package/dist/lib/long-task-semantic-contract-types.d.ts +1 -1
  164. package/dist/lib/long-task-semantic-drift-migration.js +2 -2
  165. package/dist/lib/long-task-semantic-fact-binding-types.d.ts +57 -0
  166. package/dist/lib/long-task-semantic-fact-binding-types.js +1 -0
  167. package/dist/lib/long-task-semantic-fact-closure-primitives.d.ts +5 -0
  168. package/dist/lib/long-task-semantic-fact-closure-primitives.js +43 -0
  169. package/dist/lib/long-task-semantic-fact-closure.d.ts +13 -0
  170. package/dist/lib/long-task-semantic-fact-closure.js +48 -0
  171. package/dist/lib/long-task-semantic-fact-contract-closure.d.ts +4 -0
  172. package/dist/lib/long-task-semantic-fact-contract-closure.js +24 -0
  173. package/dist/lib/long-task-semantic-fact-contract-facts.d.ts +4 -0
  174. package/dist/lib/long-task-semantic-fact-contract-facts.js +30 -0
  175. package/dist/lib/long-task-semantic-fact-contract-proofs.d.ts +4 -0
  176. package/dist/lib/long-task-semantic-fact-contract-proofs.js +97 -0
  177. package/dist/lib/long-task-semantic-fact-evidence.d.ts +21 -0
  178. package/dist/lib/long-task-semantic-fact-evidence.js +165 -0
  179. package/dist/lib/long-task-semantic-fact-input-closure.d.ts +4 -0
  180. package/dist/lib/long-task-semantic-fact-input-closure.js +101 -0
  181. package/dist/lib/long-task-semantic-fact-provenance-closure.d.ts +4 -0
  182. package/dist/lib/long-task-semantic-fact-provenance-closure.js +140 -0
  183. package/dist/lib/long-task-semantic-fact-shape.d.ts +3 -0
  184. package/dist/lib/long-task-semantic-fact-shape.js +89 -0
  185. package/dist/lib/long-task-semantic-fact-value-closure.d.ts +3 -0
  186. package/dist/lib/long-task-semantic-fact-value-closure.js +110 -0
  187. package/dist/lib/long-task-shape-primitives.d.ts +2 -1
  188. package/dist/lib/long-task-shape-primitives.js +7 -0
  189. package/dist/lib/long-task-source-item-parser.js +25 -6
  190. package/dist/lib/long-task-source-target-continuity.js +4 -1
  191. package/dist/lib/long-task-source-target-index.d.ts +1 -1
  192. package/dist/lib/long-task-source-target-index.js +5 -1
  193. package/dist/lib/long-task-ui-design-policy.js +8 -4
  194. package/dist/lib/long-task-ui-surface-shape.js +83 -1
  195. package/dist/lib/long-task-ui-surface-types.d.ts +29 -0
  196. package/dist/lib/modularity.js +7 -1
  197. package/dist/lib/semantic-fact-base-types.d.ts +14 -0
  198. package/dist/lib/semantic-fact-base-types.js +1 -0
  199. package/dist/lib/semantic-fact-catalog.d.ts +8 -0
  200. package/dist/lib/semantic-fact-catalog.js +191 -0
  201. package/dist/lib/semantic-fact-condition-shape.d.ts +48 -0
  202. package/dist/lib/semantic-fact-condition-shape.js +111 -0
  203. package/dist/lib/semantic-fact-input-shape.d.ts +34 -0
  204. package/dist/lib/semantic-fact-input-shape.js +111 -0
  205. package/dist/lib/semantic-fact-inventory-types.d.ts +147 -0
  206. package/dist/lib/semantic-fact-inventory-types.js +1 -0
  207. package/dist/lib/semantic-fact-manifest-shape.d.ts +4 -0
  208. package/dist/lib/semantic-fact-manifest-shape.js +135 -0
  209. package/dist/lib/semantic-fact-manifest-types.d.ts +58 -0
  210. package/dist/lib/semantic-fact-manifest-types.js +19 -0
  211. package/dist/lib/semantic-fact-policy-authority.d.ts +8 -0
  212. package/dist/lib/semantic-fact-policy-authority.js +79 -0
  213. package/dist/lib/semantic-fact-policy-census.d.ts +2 -0
  214. package/dist/lib/semantic-fact-policy-census.js +80 -0
  215. package/dist/lib/semantic-fact-policy-condition-references.d.ts +7 -0
  216. package/dist/lib/semantic-fact-policy-condition-references.js +19 -0
  217. package/dist/lib/semantic-fact-policy-conditions.d.ts +2 -0
  218. package/dist/lib/semantic-fact-policy-conditions.js +105 -0
  219. package/dist/lib/semantic-fact-policy-facts.d.ts +3 -0
  220. package/dist/lib/semantic-fact-policy-facts.js +73 -0
  221. package/dist/lib/semantic-fact-policy-primitives.d.ts +26 -0
  222. package/dist/lib/semantic-fact-policy-primitives.js +169 -0
  223. package/dist/lib/semantic-fact-policy-proofs.d.ts +2 -0
  224. package/dist/lib/semantic-fact-policy-proofs.js +75 -0
  225. package/dist/lib/semantic-fact-policy-properties.d.ts +3 -0
  226. package/dist/lib/semantic-fact-policy-properties.js +84 -0
  227. package/dist/lib/semantic-fact-policy-units.d.ts +4 -0
  228. package/dist/lib/semantic-fact-policy-units.js +103 -0
  229. package/dist/lib/semantic-fact-policy.d.ts +17 -0
  230. package/dist/lib/semantic-fact-policy.js +41 -0
  231. package/dist/lib/semantic-fact-proof-shape.d.ts +51 -0
  232. package/dist/lib/semantic-fact-proof-shape.js +121 -0
  233. package/dist/lib/semantic-fact-proof-types.d.ts +74 -0
  234. package/dist/lib/semantic-fact-proof-types.js +1 -0
  235. package/dist/lib/semantic-fact-property-shape.d.ts +29 -0
  236. package/dist/lib/semantic-fact-property-shape.js +77 -0
  237. package/dist/lib/semantic-fact-shape-constants.d.ts +3 -0
  238. package/dist/lib/semantic-fact-shape-constants.js +38 -0
  239. package/dist/lib/semantic-fact-shape-primitives.d.ts +15 -0
  240. package/dist/lib/semantic-fact-shape-primitives.js +68 -0
  241. package/dist/lib/semantic-fact-source-parser.d.ts +9 -0
  242. package/dist/lib/semantic-fact-source-parser.js +46 -0
  243. package/dist/lib/semantic-fact-support-shape.d.ts +21 -0
  244. package/dist/lib/semantic-fact-support-shape.js +59 -0
  245. package/dist/lib/semantic-fact-types.d.ts +5 -0
  246. package/dist/lib/semantic-fact-types.js +5 -0
  247. package/dist/lib/semantic-fact-unit-shape.d.ts +34 -0
  248. package/dist/lib/semantic-fact-unit-shape.js +89 -0
  249. package/dist/lib/semantic-fact-value-shape.d.ts +12 -0
  250. package/dist/lib/semantic-fact-value-shape.js +39 -0
  251. package/dist/schemas/long-task-delivery-v2/long-task-delivery-v2.schema.json +1339 -131
  252. package/migrations/README.md +15 -15
  253. package/package.json +84 -84
  254. package/source-mappings.yaml +25 -25
@@ -0,0 +1,151 @@
1
+ import { DESIGN_RESOURCE_STANDARD_PROPERTIES, DESIGN_RESOURCE_STANDARD_PROPERTY_BY_KEY, } from "./design-resource-fact-manifest-catalog.js";
2
+ import { designFactMethodIsCompatible } from "./design-resource-fact-policy.js";
3
+ import { factCellFingerprint, invalid, nonempty, refsKnown, sameSet, sameSetValue, unique, validateBasis, } from "./design-resource-fact-universe-helpers.js";
4
+ export function validateManifestPropertyCatalog(manifest, census) {
5
+ const properties = new Map(manifest.properties.map((property) => [property.key, property]));
6
+ for (const standard of DESIGN_RESOURCE_STANDARD_PROPERTIES) {
7
+ const actual = properties.get(standard.key);
8
+ if (!actual)
9
+ invalid("manifest_standard_property_missing", standard.key);
10
+ if (!actual.standard ||
11
+ actual.family !== standard.family ||
12
+ actual.dimension !== standard.dimension ||
13
+ actual.value_kind !== standard.value_kind ||
14
+ !sameSetValue(actual.required_methods, standard.required_methods) ||
15
+ !sameSetValue(actual.inspector_capability_refs, standard.inspector_capability_refs))
16
+ invalid("manifest_standard_property_definition_mismatch", standard.key);
17
+ }
18
+ for (const property of manifest.properties)
19
+ validateProperty(property, manifest, census);
20
+ }
21
+ function validateProperty(property, manifest, census) {
22
+ unique(property.required_methods, `manifest_property_required_method_duplicate:${property.key}`);
23
+ nonempty(property.required_methods, `manifest_property_required_method_required:${property.key}`);
24
+ for (const method of property.required_methods)
25
+ if (!designFactMethodIsCompatible(property.dimension, method))
26
+ invalid("manifest_property_required_method_incompatible", `${property.key}:${property.dimension}:${method}`);
27
+ unique(property.inspector_capability_refs, `manifest_property_capability_duplicate:${property.key}`);
28
+ nonempty(property.inspector_capability_refs, `manifest_property_capability_required:${property.key}`);
29
+ for (const capability of property.inspector_capability_refs)
30
+ if (!manifest.inspector.capability_refs.includes(capability))
31
+ invalid("manifest_inspector_property_capability_missing", `${property.key}:${capability}`);
32
+ if (property.standard) {
33
+ if (!DESIGN_RESOURCE_STANDARD_PROPERTY_BY_KEY.has(property.key))
34
+ invalid("manifest_unknown_standard_property", property.key);
35
+ }
36
+ else {
37
+ if (!property.key.startsWith("custom."))
38
+ invalid("manifest_custom_property_namespace_required", property.key);
39
+ nonempty(property.census_refs, `manifest_custom_property_census_required:${property.key}`);
40
+ }
41
+ refsKnown(property.census_refs, census, "manifest_property_census_unknown", property.key);
42
+ }
43
+ export function validateManifestCensusOwnership(manifest) {
44
+ const ownership = censusOwnershipSets(manifest);
45
+ for (const entry of manifest.inspector.census) {
46
+ if (entry.disposition !== "covered")
47
+ continue;
48
+ if (!censusEntryHasOwner(entry, ownership))
49
+ invalid("manifest_census_semantic_owner_missing", `${entry.key}:${entry.kind}`);
50
+ }
51
+ }
52
+ function censusOwnershipSets(manifest) {
53
+ return {
54
+ inspectorInputs: new Set(manifest.inspector.input_resources.map((item) => item.resource_ref)),
55
+ subject: new Set(manifest.subjects.flatMap((subject) => subject.census_refs)),
56
+ condition: new Set(manifest.axis_dispositions.flatMap((axis) => axis.values.flatMap((value) => value.census_refs))),
57
+ variation: new Set(manifest.variation_axis_dispositions.flatMap((axis) => axis.values.flatMap((value) => value.census_refs))),
58
+ property: new Set(manifest.properties.flatMap((property) => property.census_refs)),
59
+ lineage: new Set(manifest.lineage_nodes.flatMap((node) => node.census_refs)),
60
+ dynamic: new Set(manifest.subjects.flatMap((subject) => [subject.presence_rule_ref, subject.population_ref].filter((ref) => ref !== null))),
61
+ };
62
+ }
63
+ function censusEntryHasOwner(entry, sets) {
64
+ if (entry.kind === "resource")
65
+ return sets.inspectorInputs.has(entry.resource_ref);
66
+ if (entry.kind === "node")
67
+ return sets.subject.has(entry.key);
68
+ if (entry.kind === "declaration")
69
+ return [
70
+ sets.condition,
71
+ sets.variation,
72
+ sets.property,
73
+ sets.lineage,
74
+ sets.dynamic,
75
+ ].some((set) => set.has(entry.key));
76
+ if (entry.kind === "variant" ||
77
+ entry.kind === "state" ||
78
+ entry.kind === "interaction_phase")
79
+ return sets.variation.has(entry.key) || sets.dynamic.has(entry.key);
80
+ if (entry.kind === "token")
81
+ return sets.lineage.has(entry.key);
82
+ if (entry.kind === "custom_property")
83
+ return sets.property.has(entry.key) || sets.lineage.has(entry.key);
84
+ if (entry.kind === "asset_reference" || entry.kind === "relation")
85
+ return sets.subject.has(entry.key) || sets.property.has(entry.key);
86
+ return entry.kind === "dynamic_population" && sets.dynamic.has(entry.key);
87
+ }
88
+ export function validateManifestFactCells(manifest, sourceItems, census) {
89
+ const subjects = new Map(manifest.subjects.map((subject) => [subject.key, subject]));
90
+ const conditions = new Set(manifest.conditions.map((item) => item.key));
91
+ const variations = new Map(manifest.variations.map((item) => [item.key, item]));
92
+ const properties = new Set(manifest.properties.map((item) => item.key));
93
+ const actual = new Map();
94
+ const coveredFacts = [];
95
+ for (const cell of manifest.fact_cells) {
96
+ validateFactCellReferences(cell, manifest, subjects, conditions, variations, properties);
97
+ validateBasis(cell, sourceItems, census, `manifest_fact_cell:${cell.key}`);
98
+ const fingerprint = factCellFingerprint(cell);
99
+ if (actual.has(fingerprint))
100
+ invalid("manifest_fact_cell_duplicate", `${actual.get(fingerprint)}:${cell.key}`);
101
+ actual.set(fingerprint, cell.key);
102
+ validateFactCellDisposition(cell, coveredFacts);
103
+ }
104
+ sameSet([...actual.keys()], expectedFactCellFingerprints(manifest), "manifest_expected_fact_cell_universe_mismatch", manifest.target_key);
105
+ unique(coveredFacts, "manifest_fact_ref_reused_by_cells");
106
+ sameSet(coveredFacts, manifest.facts.map((fact) => fact.key), "manifest_expected_canonical_fact_set_mismatch", manifest.target_key);
107
+ }
108
+ function validateFactCellReferences(cell, manifest, subjects, conditions, variations, properties) {
109
+ const subject = subjects.get(cell.subject_ref);
110
+ const variation = variations.get(cell.variation_ref);
111
+ if (!subject)
112
+ invalid("manifest_fact_cell_subject_unknown", cell.key);
113
+ if (!subject.target_refs.includes(cell.target_ref))
114
+ invalid("manifest_fact_cell_target_outside_subject", cell.key);
115
+ if (cell.target_ref !== manifest.target_key)
116
+ invalid("manifest_fact_cell_target_mismatch", cell.key);
117
+ if (!conditions.has(cell.condition_ref))
118
+ invalid("manifest_fact_cell_condition_unknown", cell.key);
119
+ if (!variation || variation.subject_ref !== cell.subject_ref)
120
+ invalid("manifest_fact_cell_variation_mismatch", cell.key);
121
+ if (!properties.has(cell.property_ref))
122
+ invalid("manifest_fact_cell_property_unknown", cell.key);
123
+ }
124
+ function validateFactCellDisposition(cell, coveredFacts) {
125
+ if (cell.disposition === "covered") {
126
+ if (cell.fact_ref === null)
127
+ invalid("manifest_covered_fact_ref_required", cell.key);
128
+ coveredFacts.push(cell.fact_ref);
129
+ return;
130
+ }
131
+ if (cell.fact_ref !== null)
132
+ invalid("manifest_noncovered_fact_ref_forbidden", cell.key);
133
+ if (cell.disposition === "decision_required" ||
134
+ cell.disposition === "unavailable")
135
+ invalid("manifest_fact_cell_unresolved", cell.key);
136
+ }
137
+ function expectedFactCellFingerprints(manifest) {
138
+ const expected = [];
139
+ for (const subject of manifest.subjects)
140
+ for (const condition of manifest.conditions)
141
+ for (const variation of manifest.variations.filter((item) => item.subject_ref === subject.key))
142
+ for (const property of manifest.properties)
143
+ expected.push(factCellFingerprint({
144
+ subject_ref: subject.key,
145
+ target_ref: manifest.target_key,
146
+ condition_ref: condition.key,
147
+ variation_ref: variation.key,
148
+ property_ref: property.key,
149
+ }));
150
+ return expected;
151
+ }
@@ -0,0 +1,2 @@
1
+ import { type DesignResourceObservableFactManifestV1 } from "./design-resource-fact-manifest-types.js";
2
+ export declare function validateManifestConditionUniverse(manifest: DesignResourceObservableFactManifestV1, census: Map<string, DesignResourceObservableFactManifestV1["inspector"]["census"][number]>, sourceItems: Map<string, string>): void;
@@ -0,0 +1,92 @@
1
+ import { DESIGN_RESOURCE_STANDARD_CONDITION_AXES, } from "./design-resource-fact-manifest-types.js";
2
+ import { axisFingerprint, cartesian, conditionAxisValue, exactAxisPairs, invalid, nonempty, refsKnown, sameSet, unique, validateBasis, } from "./design-resource-fact-universe-helpers.js";
3
+ export function validateManifestConditionUniverse(manifest, census, sourceItems) {
4
+ const axes = manifest.axis_dispositions;
5
+ const byAxis = new Map(axes.map((axis) => [axis.axis, axis]));
6
+ for (const axis of DESIGN_RESOURCE_STANDARD_CONDITION_AXES)
7
+ if (!byAxis.has(axis))
8
+ invalid("manifest_standard_axis_missing", axis);
9
+ unique(axes.map((axis) => axis.axis), "manifest_axis_duplicate");
10
+ for (const axis of axes)
11
+ validateAxis(axis, manifest, census, sourceItems);
12
+ const fingerprints = validateConditions(manifest, axes, byAxis);
13
+ const excluded = validateConditionExclusions(manifest, axes, byAxis, fingerprints, census, sourceItems);
14
+ const expected = cartesian(axes.map((axis) => axis.values.map((value) => [axis.axis, value.key]))).map(axisFingerprint);
15
+ sameSet([...fingerprints.keys(), ...excluded.keys()], expected, "manifest_condition_universe_mismatch", manifest.target_key);
16
+ }
17
+ function validateAxis(axis, manifest, census, sourceItems) {
18
+ if (axis.target_ref !== manifest.target_key)
19
+ invalid("manifest_axis_target_mismatch", `${axis.key}:${axis.target_ref}:${manifest.target_key}`);
20
+ validateBasis(axis, sourceItems, census, `manifest_axis:${axis.key}`);
21
+ nonempty(axis.values, `manifest_axis_values_required:${axis.key}`);
22
+ unique(axis.values.map((value) => value.key), `manifest_axis_value_duplicate:${axis.key}`);
23
+ if (axis.disposition === "not_applicable" &&
24
+ (axis.values.length !== 1 || axis.values[0].key !== "not-applicable"))
25
+ invalid("manifest_axis_not_applicable_value_invalid", axis.key);
26
+ if (axis.disposition === "applicable" &&
27
+ axis.values.some((value) => value.key === "not-applicable"))
28
+ invalid("manifest_axis_applicable_value_invalid", axis.key);
29
+ for (const value of axis.values) {
30
+ if (axis.disposition === "applicable")
31
+ nonempty(value.census_refs, `manifest_axis_value_census_required:${axis.key}:${value.key}`);
32
+ refsKnown(value.census_refs, census, "manifest_axis_value_census_unknown", `${axis.key}:${value.key}`);
33
+ }
34
+ }
35
+ function validateConditions(manifest, axes, byAxis) {
36
+ const fingerprints = new Map();
37
+ const profileByAxisValue = new Map();
38
+ for (const condition of manifest.conditions) {
39
+ const values = axes.map((axis) => [axis.axis, conditionAxisValue(condition, axis.axis)]);
40
+ for (const [axis, value] of values)
41
+ if (!byAxis.get(axis).values.some((candidate) => candidate.key === value))
42
+ invalid("manifest_condition_axis_value_unknown", `${condition.key}:${axis}:${value}`);
43
+ const fingerprint = axisFingerprint(values);
44
+ if (fingerprints.has(fingerprint))
45
+ invalid("manifest_condition_combination_duplicate", `${fingerprints.get(fingerprint)}:${condition.key}`);
46
+ fingerprints.set(fingerprint, condition.key);
47
+ validateConditionProfiles(condition, profileByAxisValue);
48
+ }
49
+ return fingerprints;
50
+ }
51
+ function validateConditionProfiles(condition, profileByAxisValue) {
52
+ for (const [key, profile] of [
53
+ [
54
+ `viewport:${condition.viewport.key}`,
55
+ `${condition.viewport.width}:${condition.viewport.height}:${condition.viewport.unit}`,
56
+ ],
57
+ [`density:${condition.density.key}`, String(condition.density.pixel_ratio)],
58
+ [
59
+ `safe_area:${condition.safe_area.key}`,
60
+ `${condition.safe_area.top}:${condition.safe_area.right}:${condition.safe_area.bottom}:${condition.safe_area.left}:${condition.safe_area.unit}`,
61
+ ],
62
+ [
63
+ `text_scale:${condition.text_scale.key}`,
64
+ String(condition.text_scale.multiplier),
65
+ ],
66
+ ]) {
67
+ const previous = profileByAxisValue.get(key);
68
+ if (previous !== undefined && previous !== profile)
69
+ invalid("manifest_condition_profile_ambiguous", `${key}:${previous}:${profile}`);
70
+ profileByAxisValue.set(key, profile);
71
+ }
72
+ }
73
+ function validateConditionExclusions(manifest, axes, byAxis, fingerprints, census, sourceItems) {
74
+ const excluded = new Map();
75
+ for (const row of manifest.condition_exclusions) {
76
+ if (row.target_ref !== manifest.target_key)
77
+ invalid("manifest_condition_exclusion_target_mismatch", row.key);
78
+ validateBasis(row, sourceItems, census, `manifest_condition_exclusion:${row.key}`);
79
+ if (row.disposition === "decision_required" ||
80
+ row.disposition === "unavailable")
81
+ invalid("manifest_condition_exclusion_unresolved", row.key);
82
+ const values = exactAxisPairs(row.axis_values, axes.map((axis) => axis.axis), `manifest_condition_exclusion:${row.key}`);
83
+ for (const [axis, value] of values)
84
+ if (!byAxis.get(axis).values.some((candidate) => candidate.key === value))
85
+ invalid("manifest_condition_exclusion_value_unknown", `${row.key}:${axis}:${value}`);
86
+ const fingerprint = axisFingerprint(values);
87
+ if (fingerprints.has(fingerprint) || excluded.has(fingerprint))
88
+ invalid("manifest_condition_exclusion_duplicate", row.key);
89
+ excluded.set(fingerprint, row.key);
90
+ }
91
+ return excluded;
92
+ }
@@ -0,0 +1,4 @@
1
+ import type { DesignResourceObservableFactManifestV1 } from "./design-resource-fact-manifest-types.js";
2
+ import type { DesignResource } from "./design-resource-handoff-file-primitives.js";
3
+ import type { DesignResourceHandoffV1 } from "./design-resource-handoff-types.js";
4
+ export declare function validateManifestFacts(manifest: DesignResourceObservableFactManifestV1, handoff: DesignResourceHandoffV1, resources: Map<string, DesignResource>, contents: Map<string, Buffer>, sourceItems: Map<string, string>): void;
@@ -0,0 +1,108 @@
1
+ import { validateDesignResourceLocatedDigest, validateDesignResourceValueKind, } from "./design-resource-fact-locator-validation.js";
2
+ import { invalid, nonempty, refsKnown, stableJson, unique, } from "./design-resource-fact-universe-helpers.js";
3
+ export function validateManifestFacts(manifest, handoff, resources, contents, sourceItems) {
4
+ const cells = new Map(manifest.fact_cells.map((cell) => [cell.key, cell]));
5
+ const properties = new Map(manifest.properties.map((property) => [property.key, property]));
6
+ const evidence = new Map(manifest.evidence.map((item) => [item.key, item]));
7
+ const lineageNodes = new Map(manifest.lineage_nodes.map((item) => [item.key, item]));
8
+ for (const fact of manifest.facts) {
9
+ const property = validateFactIdentity(fact, cells, properties);
10
+ validateFactSourceAndEvidence(fact, evidence, sourceItems);
11
+ validateFactValue(fact, resources, contents);
12
+ validateFactLineage(fact, property.family, manifest, handoff, lineageNodes);
13
+ }
14
+ }
15
+ function validateFactIdentity(fact, cells, properties) {
16
+ const cell = cells.get(fact.cell_ref);
17
+ const property = properties.get(fact.property_ref);
18
+ if (!cell ||
19
+ cell.fact_ref !== fact.key ||
20
+ cell.subject_ref !== fact.subject_ref ||
21
+ cell.target_ref !== fact.target_ref ||
22
+ cell.condition_ref !== fact.condition_ref ||
23
+ cell.variation_ref !== fact.variation_ref ||
24
+ cell.property_ref !== fact.property_ref)
25
+ invalid("manifest_fact_cell_mismatch", fact.key);
26
+ if (!property ||
27
+ property.dimension !== fact.dimension ||
28
+ property.value_kind !== fact.value_kind)
29
+ invalid("manifest_fact_property_mismatch", fact.key);
30
+ return property;
31
+ }
32
+ function validateFactSourceAndEvidence(fact, evidence, sourceItems) {
33
+ nonempty(fact.evidence_refs, `manifest_fact_evidence_required:${fact.key}`);
34
+ nonempty(fact.source_item_refs, `manifest_fact_source_item_required:${fact.key}`);
35
+ unique(fact.evidence_refs, `manifest_fact_evidence_duplicate:${fact.key}`);
36
+ refsKnown(fact.evidence_refs, evidence, "manifest_fact_evidence_unknown", fact.key);
37
+ refsKnown(fact.source_item_refs, sourceItems, "manifest_fact_source_item_unknown", fact.key);
38
+ }
39
+ function validateFactValue(fact, resources, contents) {
40
+ const resolvedFactValue = validateDesignResourceLocatedDigest(fact.value, resources, contents, `manifest.fact.${fact.key}.value`);
41
+ validateDesignResourceValueKind(fact.value_kind, resolvedFactValue, `manifest.fact.${fact.key}.value`);
42
+ validateDesignResourceLocatedDigest(fact.lineage.resolved_value, resources, contents, `manifest.fact.${fact.key}.lineage.resolved_value`);
43
+ if (fact.value.sha256 !== fact.lineage.resolved_value.sha256 ||
44
+ stableJson(fact.value.locator) !==
45
+ stableJson(fact.lineage.resolved_value.locator))
46
+ invalid("manifest_fact_resolved_value_mismatch", fact.key);
47
+ }
48
+ function validateFactLineage(fact, family, manifest, handoff, nodes) {
49
+ if (handoff.scope.style_dependency !== "non-fidelity" &&
50
+ ["typography", "color", "decoration", "icon"].includes(family) &&
51
+ fact.lineage.design_system_ref === null)
52
+ invalid("manifest_style_fact_design_system_lineage_required", fact.key);
53
+ if (fact.lineage.conflict_status === "none" &&
54
+ fact.lineage.conflict_resolution !== "")
55
+ invalid("manifest_fact_conflict_resolution_forbidden", fact.key);
56
+ if (fact.lineage.conflict_status === "resolved" &&
57
+ !fact.lineage.conflict_resolution.trim())
58
+ invalid("manifest_fact_conflict_resolution_required", fact.key);
59
+ if (fact.lineage.design_system_ref !== null &&
60
+ fact.lineage.design_system_ref !== manifest.design_system.id)
61
+ invalid("manifest_fact_design_system_lineage_mismatch", fact.key);
62
+ validateLineageRefs(fact, nodes);
63
+ validateLineageChain(fact, nodes);
64
+ }
65
+ function validateLineageRefs(fact, nodes) {
66
+ unique(fact.lineage.token_chain_refs, `manifest_fact_token_chain_duplicate:${fact.key}`);
67
+ unique(fact.lineage.override_chain_refs, `manifest_fact_override_chain_duplicate:${fact.key}`);
68
+ refsKnown(fact.lineage.token_chain_refs, nodes, "manifest_fact_token_lineage_unknown", fact.key);
69
+ refsKnown(fact.lineage.override_chain_refs, nodes, "manifest_fact_override_lineage_unknown", fact.key);
70
+ for (const ref of fact.lineage.token_chain_refs)
71
+ if (![
72
+ "base_token",
73
+ "alias_token",
74
+ "semantic_token",
75
+ "component_token",
76
+ ].includes(nodes.get(ref).kind))
77
+ invalid("manifest_fact_token_lineage_kind_invalid", `${fact.key}:${ref}`);
78
+ for (const ref of fact.lineage.override_chain_refs)
79
+ if (![
80
+ "platform_override",
81
+ "mode_override",
82
+ "state_override",
83
+ "instance_override",
84
+ "slot_override",
85
+ "direct_value",
86
+ ].includes(nodes.get(ref).kind))
87
+ invalid("manifest_fact_override_lineage_kind_invalid", `${fact.key}:${ref}`);
88
+ }
89
+ function validateLineageChain(fact, nodes) {
90
+ const chain = [
91
+ ...fact.lineage.token_chain_refs,
92
+ ...fact.lineage.override_chain_refs,
93
+ ];
94
+ if (fact.lineage.design_system_ref === null && chain.length)
95
+ invalid("manifest_fact_lineage_without_design_system", fact.key);
96
+ if (fact.lineage.design_system_ref !== null && chain.length === 0)
97
+ invalid("manifest_fact_design_system_chain_required", fact.key);
98
+ for (let index = 1; index < chain.length; index += 1)
99
+ if (!nodes.get(chain[index]).predecessor_refs.includes(chain[index - 1]))
100
+ invalid("manifest_fact_lineage_chain_disconnected", `${fact.key}:${chain[index - 1]}:${chain[index]}`);
101
+ if (!chain.length)
102
+ return;
103
+ const effective = nodes.get(chain.at(-1)).value;
104
+ if (effective.sha256 !== fact.lineage.resolved_value.sha256 ||
105
+ stableJson(effective.locator) !==
106
+ stableJson(fact.lineage.resolved_value.locator))
107
+ invalid("manifest_fact_lineage_effective_value_mismatch", fact.key);
108
+ }
@@ -0,0 +1,30 @@
1
+ import { type DesignResourceObservableFactManifestV1, type DesignResourceSubjectVariationV1, type DesignResourceVariationAxis } from "./design-resource-fact-manifest-types.js";
2
+ export declare function manifestIdentityDigest(rows: ReadonlyArray<unknown>): string;
3
+ export declare function manifestCollectionRows(manifest: DesignResourceObservableFactManifestV1): Map<string, ReadonlyArray<unknown>>;
4
+ export declare function conditionAxisValue(condition: DesignResourceObservableFactManifestV1["conditions"][number], axis: string): string;
5
+ export declare function variationValues(variation: DesignResourceSubjectVariationV1): Array<readonly [DesignResourceVariationAxis, string]>;
6
+ export declare function factCellFingerprint(cell: {
7
+ subject_ref: string;
8
+ target_ref: string;
9
+ condition_ref: string;
10
+ variation_ref: string;
11
+ property_ref: string;
12
+ }): string;
13
+ export declare function validateBasis(row: {
14
+ source_item_refs: string[];
15
+ basis_refs: string[];
16
+ }, sourceItems: Map<string, string>, census: Map<string, unknown>, label: string): void;
17
+ export declare function exactAxisPairs<T extends string>(pairs: Array<{
18
+ axis_ref: T | string;
19
+ value_ref: string;
20
+ }>, expectedAxes: readonly T[] | string[], detail: string): Array<readonly [string, string]>;
21
+ export declare function axisFingerprint(values: Array<readonly [string, string]>): string;
22
+ export declare function cartesian<T>(groups: T[][]): T[][];
23
+ export declare function groupBy<T>(rows: T[], key: (row: T) => string): Map<string, T[]>;
24
+ export declare function refsKnown<T>(refs: string[], known: Map<string, T>, code: string, detail: string): void;
25
+ export declare function nonempty(values: unknown[], code: string): void;
26
+ export declare function unique(values: string[], code: string): void;
27
+ export declare function sameSet(actual: string[], expected: string[], code: string, detail: string): void;
28
+ export declare function sameSetValue(left: readonly string[], right: readonly string[]): boolean;
29
+ export declare function stableJson(value: unknown): string;
30
+ export declare function invalid(code: string, detail: string): never;
@@ -0,0 +1,167 @@
1
+ import { DESIGN_RESOURCE_STANDARD_CONDITION_AXES, } from "./design-resource-fact-manifest-types.js";
2
+ import { invalidDesignResourceHandoff } from "./design-resource-handoff-validation-primitives.js";
3
+ import { sha256Hex } from "./strict-codec.js";
4
+ export function manifestIdentityDigest(rows) {
5
+ return sha256Hex(rows
6
+ .map((row) => stableJson(row))
7
+ .sort()
8
+ .join("\n"));
9
+ }
10
+ export function manifestCollectionRows(manifest) {
11
+ return new Map([
12
+ ["inspector_inputs", manifest.inspector.input_resources],
13
+ ["inspector_census", manifest.inspector.census],
14
+ ["axis_dispositions", manifest.axis_dispositions],
15
+ ["condition_exclusions", manifest.condition_exclusions],
16
+ ["conditions", manifest.conditions],
17
+ ["subjects", manifest.subjects],
18
+ ["variation_axis_dispositions", manifest.variation_axis_dispositions],
19
+ ["variation_exclusions", manifest.variation_exclusions],
20
+ ["variations", manifest.variations],
21
+ ["properties", manifest.properties],
22
+ ["lineage_nodes", manifest.lineage_nodes],
23
+ ["fact_cells", manifest.fact_cells],
24
+ ["facts", manifest.facts],
25
+ ["evidence", manifest.evidence],
26
+ ["proof_obligations", manifest.proof_obligations],
27
+ ["oracles", manifest.oracles],
28
+ ["environments", manifest.environments],
29
+ ["asset_bindings", manifest.asset_bindings],
30
+ ["acceptance_blockers", manifest.acceptance_blockers],
31
+ ]);
32
+ }
33
+ export function conditionAxisValue(condition, axis) {
34
+ const standard = {
35
+ platform: condition.platform,
36
+ os_version: condition.os_version,
37
+ device_profile: condition.device_profile,
38
+ form_factor: condition.form_factor,
39
+ viewport: condition.viewport.key,
40
+ orientation: condition.orientation,
41
+ density: condition.density.key,
42
+ safe_area: condition.safe_area.key,
43
+ window_state: condition.window_state,
44
+ fold_state: condition.fold_state,
45
+ display_mode: condition.display_mode,
46
+ color_scheme: condition.color_scheme,
47
+ locale: condition.locale,
48
+ language: condition.language,
49
+ script: condition.script,
50
+ direction: condition.direction,
51
+ pseudo_localization: condition.pseudo_localization,
52
+ content_case: condition.content_case,
53
+ data_case: condition.data_case,
54
+ text_scale: condition.text_scale.key,
55
+ input_method: condition.input_method,
56
+ assistive_technology: condition.assistive_technology,
57
+ motion: condition.motion,
58
+ transparency: condition.transparency,
59
+ contrast: condition.contrast,
60
+ bold_text: condition.bold_text,
61
+ button_shapes: condition.button_shapes,
62
+ system_ui: condition.system_ui,
63
+ ime: condition.ime,
64
+ permission: condition.permission,
65
+ capability: condition.capability,
66
+ connectivity: condition.connectivity,
67
+ lifecycle: condition.lifecycle,
68
+ };
69
+ if (DESIGN_RESOURCE_STANDARD_CONDITION_AXES.includes(axis))
70
+ return standard[axis];
71
+ const custom = condition.custom_axes.filter((item) => item.axis_ref === axis);
72
+ if (custom.length !== 1)
73
+ invalid("manifest_condition_custom_axis_missing_or_duplicate", `${condition.key}:${axis}`);
74
+ return custom[0].value_ref;
75
+ }
76
+ export function variationValues(variation) {
77
+ return [
78
+ ["variant", variation.variant],
79
+ ["state", variation.state],
80
+ ["interaction_phase", variation.interaction_phase],
81
+ ["presence_phase", variation.presence_phase],
82
+ ["instance_case", variation.instance_case],
83
+ ];
84
+ }
85
+ export function factCellFingerprint(cell) {
86
+ return [
87
+ cell.subject_ref,
88
+ cell.target_ref,
89
+ cell.condition_ref,
90
+ cell.variation_ref,
91
+ cell.property_ref,
92
+ ].join("\0");
93
+ }
94
+ export function validateBasis(row, sourceItems, census, label) {
95
+ nonempty(row.source_item_refs, `${label}:source_item_refs_required`);
96
+ nonempty(row.basis_refs, `${label}:basis_refs_required`);
97
+ unique(row.source_item_refs, `${label}:source_item_ref_duplicate`);
98
+ unique(row.basis_refs, `${label}:basis_ref_duplicate`);
99
+ refsKnown(row.source_item_refs, sourceItems, "manifest_source_item_unknown", label);
100
+ for (const ref of row.basis_refs)
101
+ if (!sourceItems.has(ref) && !census.has(ref))
102
+ invalid("manifest_basis_ref_unknown", `${label}:${ref}`);
103
+ }
104
+ export function exactAxisPairs(pairs, expectedAxes, detail) {
105
+ unique(pairs.map((pair) => pair.axis_ref), `${detail}:axis_duplicate`);
106
+ sameSet(pairs.map((pair) => pair.axis_ref), [...expectedAxes], "manifest_combination_axes_mismatch", detail);
107
+ const byAxis = new Map(pairs.map((pair) => [String(pair.axis_ref), pair.value_ref]));
108
+ return [...expectedAxes].map((axis) => [String(axis), byAxis.get(String(axis))]);
109
+ }
110
+ export function axisFingerprint(values) {
111
+ return values
112
+ .map(([axis, value]) => `${axis}=${value}`)
113
+ .sort()
114
+ .join("\0");
115
+ }
116
+ export function cartesian(groups) {
117
+ let result = [[]];
118
+ for (const group of groups)
119
+ result = result.flatMap((prefix) => group.map((item) => [...prefix, item]));
120
+ return result;
121
+ }
122
+ export function groupBy(rows, key) {
123
+ const result = new Map();
124
+ for (const row of rows) {
125
+ const value = key(row);
126
+ const group = result.get(value) ?? [];
127
+ group.push(row);
128
+ result.set(value, group);
129
+ }
130
+ return result;
131
+ }
132
+ export function refsKnown(refs, known, code, detail) {
133
+ for (const ref of refs)
134
+ if (!known.has(ref))
135
+ invalid(code, `${detail}:${ref}`);
136
+ }
137
+ export function nonempty(values, code) {
138
+ if (!values.length)
139
+ invalid(code, "");
140
+ }
141
+ export function unique(values, code) {
142
+ if (new Set(values).size !== values.length)
143
+ invalid(code, values.join(","));
144
+ }
145
+ export function sameSet(actual, expected, code, detail) {
146
+ if (!sameSetValue(actual, expected))
147
+ invalid(code, `${detail}:${[...new Set(actual)].sort().join(",")}:${[...new Set(expected)].sort().join(",")}`);
148
+ }
149
+ export function sameSetValue(left, right) {
150
+ const actual = [...new Set(left)].sort();
151
+ const expected = [...new Set(right)].sort();
152
+ return (actual.length === expected.length &&
153
+ actual.every((item, index) => item === expected[index]));
154
+ }
155
+ export function stableJson(value) {
156
+ if (Array.isArray(value))
157
+ return `[${value.map((item) => stableJson(item)).join(",")}]`;
158
+ if (value && typeof value === "object")
159
+ return `{${Object.entries(value)
160
+ .sort(([left], [right]) => left.localeCompare(right))
161
+ .map(([key, entry]) => `${JSON.stringify(key)}:${stableJson(entry)}`)
162
+ .join(",")}}`;
163
+ return JSON.stringify(value);
164
+ }
165
+ export function invalid(code, detail) {
166
+ invalidDesignResourceHandoff(code, detail);
167
+ }
@@ -0,0 +1,7 @@
1
+ import type { DesignResourceObservableFactManifestV1 } from "./design-resource-fact-manifest-types.js";
2
+ import type { DesignResource } from "./design-resource-handoff-file-primitives.js";
3
+ import type { DesignResourceHandoffTargetV1, DesignResourceHandoffV1 } from "./design-resource-handoff-types.js";
4
+ type Census = Map<string, DesignResourceObservableFactManifestV1["inspector"]["census"][number]>;
5
+ export declare function validateManifestLineageNodes(manifest: DesignResourceObservableFactManifestV1, census: Census, resources: Map<string, DesignResource>, contents: Map<string, Buffer>): void;
6
+ export declare function validateManifestInspector(manifest: DesignResourceObservableFactManifestV1, handoff: DesignResourceHandoffV1, target: DesignResourceHandoffTargetV1, resources: Map<string, DesignResource>, contents: Map<string, Buffer>, sourceItems: Map<string, string>): void;
7
+ export {};