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,119 @@
1
+ import { resolveDesignResourceLocatorValue, validateDesignResourceLocatedDigest, } from "./design-resource-fact-locator-validation.js";
2
+ import { invalid, nonempty, refsKnown, sameSet, unique, validateBasis, } from "./design-resource-fact-universe-helpers.js";
3
+ export function validateManifestLineageNodes(manifest, census, resources, contents) {
4
+ const nodes = new Map(manifest.lineage_nodes.map((node) => [node.key, node]));
5
+ for (const node of manifest.lineage_nodes) {
6
+ unique(node.predecessor_refs, `manifest_lineage_predecessor_duplicate:${node.key}`);
7
+ refsKnown(node.predecessor_refs, nodes, "manifest_lineage_predecessor_unknown", node.key);
8
+ if (node.predecessor_refs.includes(node.key))
9
+ invalid("manifest_lineage_self_reference", node.key);
10
+ if (["base_token", "direct_value"].includes(node.kind) &&
11
+ node.predecessor_refs.length)
12
+ invalid("manifest_lineage_root_predecessor_forbidden", node.key);
13
+ if (!["base_token", "direct_value"].includes(node.kind) &&
14
+ node.predecessor_refs.length === 0)
15
+ invalid("manifest_lineage_predecessor_required", node.key);
16
+ nonempty(node.census_refs, `manifest_lineage_census_required:${node.key}`);
17
+ refsKnown(node.census_refs, census, "manifest_lineage_census_unknown", node.key);
18
+ for (const ref of node.census_refs)
19
+ if (!["token", "declaration"].includes(census.get(ref).kind))
20
+ invalid("manifest_lineage_census_kind_invalid", `${node.key}:${ref}:${census.get(ref).kind}`);
21
+ validateDesignResourceLocatedDigest(node.value, resources, contents, `manifest.lineage_node.${node.key}.value`);
22
+ }
23
+ validateLineageAcyclic(manifest, nodes);
24
+ }
25
+ function validateLineageAcyclic(manifest, nodes) {
26
+ for (const node of manifest.lineage_nodes) {
27
+ const visiting = new Set();
28
+ const visited = new Set();
29
+ const walk = (ref) => {
30
+ if (visiting.has(ref))
31
+ invalid("manifest_lineage_cycle", node.key);
32
+ if (visited.has(ref))
33
+ return;
34
+ visiting.add(ref);
35
+ for (const predecessor of nodes.get(ref).predecessor_refs)
36
+ walk(predecessor);
37
+ visiting.delete(ref);
38
+ visited.add(ref);
39
+ };
40
+ walk(node.key);
41
+ }
42
+ }
43
+ export function validateManifestInspector(manifest, handoff, target, resources, contents, sourceItems) {
44
+ const inspector = manifest.inspector;
45
+ validateInspectorIdentity(inspector);
46
+ if (inspector.entry_resource_ref !== target.source_profile.entry_resource_ref)
47
+ invalid("manifest_inspector_entry_mismatch", `${manifest.target_key}:${inspector.entry_resource_ref}:${target.source_profile.entry_resource_ref}`);
48
+ validateInspectorInputs(manifest, target, resources);
49
+ validateInspectorCensus(manifest, resources, contents, sourceItems);
50
+ const expectedInspectorIdentity = `${inspector.identity}@${inspector.version}`;
51
+ for (const resourceRef of target.resource_refs) {
52
+ const closure = handoff.resource_fact_closure.find((item) => item.resource_ref === resourceRef);
53
+ if (!closure || closure.inspection.inspector !== expectedInspectorIdentity)
54
+ invalid("manifest_resource_closure_inspector_mismatch", `${resourceRef}:${closure?.inspection.inspector ?? "missing"}:${expectedInspectorIdentity}`);
55
+ }
56
+ }
57
+ function validateInspectorIdentity(inspector) {
58
+ if (inspector.trust === "frozen_executable" &&
59
+ inspector.implementation_sha256 === null)
60
+ invalid("manifest_inspector_digest_required", inspector.identity);
61
+ if (inspector.trust === "named_external_tcb" &&
62
+ inspector.implementation_sha256 !== null)
63
+ invalid("manifest_external_inspector_digest_forbidden", inspector.identity);
64
+ nonempty(inspector.capability_refs, "manifest_inspector_capabilities_required");
65
+ unique(inspector.capability_refs, "manifest_inspector_capability_duplicate");
66
+ }
67
+ function validateInspectorInputs(manifest, target, resources) {
68
+ const manifestResourceRef = target.source_profile.fact_manifest_resource_ref;
69
+ const expectedInputs = target.resource_refs
70
+ .filter((ref) => ref !== manifestResourceRef)
71
+ .map((ref) => {
72
+ const resource = resources.get(ref);
73
+ return `${ref}\0${resource.path}\0${resource.sha256}`;
74
+ });
75
+ const actualInputs = manifest.inspector.input_resources.map((item) => `${item.resource_ref}\0${item.path}\0${item.sha256}`);
76
+ sameSet(actualInputs, expectedInputs, "manifest_inspector_input_resource_mismatch", manifest.target_key);
77
+ unique(manifest.inspector.input_resources.map((item) => item.resource_ref), "manifest_inspector_input_resource_duplicate");
78
+ }
79
+ function validateInspectorCensus(manifest, resources, contents, sourceItems) {
80
+ const inputRefs = new Set(manifest.inspector.input_resources.map((item) => item.resource_ref));
81
+ const censusByResource = new Map();
82
+ const censusFactRefs = new Set();
83
+ const censusFactCellRefs = new Set();
84
+ const facts = new Map(manifest.facts.map((fact) => [fact.key, fact]));
85
+ const factCells = new Map(manifest.fact_cells.map((cell) => [cell.key, cell]));
86
+ const censusEntries = new Map(manifest.inspector.census.map((entry) => [entry.key, entry]));
87
+ for (const entry of manifest.inspector.census) {
88
+ validateCensusEntry(entry, inputRefs, censusByResource, facts, factCells, censusEntries, resources, contents, sourceItems);
89
+ for (const ref of entry.fact_refs)
90
+ censusFactRefs.add(ref);
91
+ for (const ref of entry.fact_cell_refs)
92
+ censusFactCellRefs.add(ref);
93
+ }
94
+ for (const ref of inputRefs)
95
+ if (!censusByResource.has(ref))
96
+ invalid("manifest_census_resource_missing", ref);
97
+ sameSet([...censusFactRefs], manifest.facts.map((fact) => fact.key), "manifest_census_fact_set_mismatch", manifest.target_key);
98
+ sameSet([...censusFactCellRefs], manifest.fact_cells.map((cell) => cell.key), "manifest_census_fact_cell_set_mismatch", manifest.target_key);
99
+ }
100
+ function validateCensusEntry(entry, inputRefs, censusByResource, facts, factCells, censusEntries, resources, contents, sourceItems) {
101
+ validateBasis(entry, sourceItems, censusEntries, `manifest_census:${entry.key}`);
102
+ if (entry.basis_refs.includes(entry.key))
103
+ invalid("manifest_census_self_basis_forbidden", entry.key);
104
+ if (!inputRefs.has(entry.resource_ref))
105
+ invalid("manifest_census_resource_outside_inputs", `${entry.key}:${entry.resource_ref}`);
106
+ censusByResource.set(entry.resource_ref, (censusByResource.get(entry.resource_ref) ?? 0) + 1);
107
+ resolveDesignResourceLocatorValue({ resource_ref: entry.resource_ref, ...entry.locator }, resources.get(entry.resource_ref), contents.get(entry.resource_ref), `manifest.census.${entry.key}`);
108
+ unique(entry.fact_refs, `manifest_census_fact_ref_duplicate:${entry.key}`);
109
+ unique(entry.fact_cell_refs, `manifest_census_fact_cell_ref_duplicate:${entry.key}`);
110
+ refsKnown(entry.fact_refs, facts, "manifest_census_fact_ref_unknown", entry.key);
111
+ refsKnown(entry.fact_cell_refs, factCells, "manifest_census_fact_cell_ref_unknown", entry.key);
112
+ if (entry.disposition === "covered" &&
113
+ entry.fact_refs.length === 0 &&
114
+ entry.fact_cell_refs.length === 0)
115
+ invalid("manifest_census_covered_binding_required", entry.key);
116
+ if (entry.disposition === "non_material" &&
117
+ (entry.fact_refs.length > 0 || entry.fact_cell_refs.length > 0))
118
+ invalid("manifest_census_non_material_binding_forbidden", entry.key);
119
+ }
@@ -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 { DesignResourceHandoffTargetV1 } from "./design-resource-handoff-types.js";
4
+ export declare function validateManifestProofAndEvidence(manifest: DesignResourceObservableFactManifestV1, target: DesignResourceHandoffTargetV1, resources: Map<string, DesignResource>, contents: Map<string, Buffer>): void;
@@ -0,0 +1,113 @@
1
+ import { designFactComparatorSupportsMethod, designFactMethodIsCompatible, designFactOracleSupportsMethod, EXACT_TARGET_FULL_TARGET_METHODS, } from "./design-resource-fact-policy.js";
2
+ import { resolveDesignResourceLocatorValue, validateDesignResourceLocatedDigest, } from "./design-resource-fact-locator-validation.js";
3
+ import { invalid, nonempty, unique, } from "./design-resource-fact-universe-helpers.js";
4
+ export function validateManifestProofAndEvidence(manifest, target, resources, contents) {
5
+ validateOraclesAndEnvironments(manifest, resources, contents);
6
+ validateProofObligations(manifest, resources, contents);
7
+ validateExactTargetFullTargetProof(manifest, target);
8
+ validateEvidence(manifest, resources, contents);
9
+ }
10
+ function validateOraclesAndEnvironments(manifest, resources, contents) {
11
+ for (const oracle of manifest.oracles) {
12
+ nonempty(oracle.capability_refs, `manifest_oracle_capabilities_required:${oracle.key}`);
13
+ unique(oracle.capability_refs, `manifest_oracle_capability_duplicate:${oracle.key}`);
14
+ if (oracle.trust === "frozen_executable" && oracle.sha256 === null)
15
+ invalid("manifest_oracle_digest_required", oracle.key);
16
+ if (oracle.trust === "named_external_tcb" && oracle.sha256 !== null)
17
+ invalid("manifest_external_oracle_digest_forbidden", oracle.key);
18
+ }
19
+ for (const environment of manifest.environments)
20
+ validateDesignResourceLocatedDigest(environment.definition, resources, contents, `manifest.environment.${environment.key}`);
21
+ }
22
+ function validateProofObligations(manifest, resources, contents) {
23
+ const properties = new Map(manifest.properties.map((property) => [property.key, property]));
24
+ const oracles = new Map(manifest.oracles.map((item) => [item.key, item]));
25
+ const environments = new Map(manifest.environments.map((item) => [item.key, item]));
26
+ const proofMethodsByFact = new Map();
27
+ const factMethodIdentities = [];
28
+ for (const proof of manifest.proof_obligations) {
29
+ validateProof(proof, manifest, oracles, environments, resources, contents);
30
+ const identity = `${proof.fact_ref}\0${proof.method}`;
31
+ factMethodIdentities.push(identity);
32
+ const methods = proofMethodsByFact.get(proof.fact_ref) ?? new Set();
33
+ methods.add(proof.method);
34
+ proofMethodsByFact.set(proof.fact_ref, methods);
35
+ }
36
+ unique(factMethodIdentities, "manifest_fact_method_obligation_duplicate");
37
+ for (const fact of manifest.facts) {
38
+ const actualMethods = proofMethodsByFact.get(fact.key);
39
+ if (!actualMethods)
40
+ invalid("manifest_fact_proof_obligation_required", fact.key);
41
+ const requiredMethods = new Set(properties.get(fact.property_ref).required_methods);
42
+ if (fact.lineage.design_system_ref !== null &&
43
+ (fact.lineage.token_chain_refs.length > 0 ||
44
+ fact.lineage.override_chain_refs.length > 0))
45
+ requiredMethods.add("design_token");
46
+ for (const method of requiredMethods)
47
+ if (!actualMethods.has(method))
48
+ invalid("manifest_fact_required_proof_method_missing", `${fact.key}:${method}`);
49
+ }
50
+ }
51
+ function validateProof(proof, manifest, oracles, environments, resources, contents) {
52
+ const fact = manifest.facts.find((item) => item.key === proof.fact_ref);
53
+ if (!fact)
54
+ invalid("manifest_proof_fact_unknown", proof.key);
55
+ if (!designFactMethodIsCompatible(fact.dimension, proof.method))
56
+ invalid("manifest_proof_method_incompatible", `${proof.key}:${fact.dimension}:${proof.method}`);
57
+ if (!designFactComparatorSupportsMethod(proof.method, proof.comparison.comparator))
58
+ invalid("manifest_proof_comparator_method_incompatible", `${proof.key}:${proof.method}:${proof.comparison.comparator}`);
59
+ const oracle = oracles.get(proof.oracle_ref);
60
+ if (!oracle)
61
+ invalid("manifest_proof_oracle_unknown", proof.key);
62
+ if (!designFactOracleSupportsMethod(proof.method, oracle.capability_refs))
63
+ invalid("manifest_proof_oracle_capability_missing", `${proof.key}:${proof.oracle_ref}:${proof.method}`);
64
+ if (!environments.has(proof.environment_ref))
65
+ invalid("manifest_proof_environment_unknown", proof.key);
66
+ validateComparison(proof, resources, contents);
67
+ }
68
+ function validateComparison(proof, resources, contents) {
69
+ validateDesignResourceLocatedDigest(proof.comparison.parameters, resources, contents, `manifest.proof.${proof.key}.parameters`);
70
+ if (proof.comparison.mode === "exact") {
71
+ if (proof.comparison.tolerance !== null || proof.comparison.mask !== null)
72
+ invalid("manifest_exact_proof_tolerance_forbidden", proof.key);
73
+ }
74
+ else if (proof.comparison.tolerance === null)
75
+ invalid("manifest_tolerance_proof_tolerance_required", proof.key);
76
+ if (proof.comparison.tolerance)
77
+ validateDesignResourceLocatedDigest(proof.comparison.tolerance, resources, contents, `manifest.proof.${proof.key}.tolerance`);
78
+ if (proof.comparison.mask)
79
+ validateDesignResourceLocatedDigest(proof.comparison.mask, resources, contents, `manifest.proof.${proof.key}.mask`);
80
+ if (proof.comparison.mask !== null &&
81
+ proof.comparison.comparator !== "pixel_diff" &&
82
+ !proof.comparison.comparator.startsWith("custom."))
83
+ invalid("manifest_proof_mask_comparator_incompatible", `${proof.key}:${proof.comparison.comparator}`);
84
+ }
85
+ function validateExactTargetFullTargetProof(manifest, target) {
86
+ if (target.interpretation !== "exact_target")
87
+ return;
88
+ for (const condition of manifest.conditions)
89
+ for (const method of EXACT_TARGET_FULL_TARGET_METHODS)
90
+ if (!hasFullTargetProof(manifest, condition.key, method))
91
+ invalid("manifest_exact_target_full_target_proof_missing", `${target.key}:${condition.key}:${method}`);
92
+ }
93
+ function hasFullTargetProof(manifest, conditionRef, method) {
94
+ return manifest.proof_obligations.some((proof) => {
95
+ const fact = manifest.facts.find((item) => item.key === proof.fact_ref);
96
+ return (fact?.condition_ref === conditionRef &&
97
+ fact.observation_scope === "full_target" &&
98
+ proof.method === method);
99
+ });
100
+ }
101
+ function validateEvidence(manifest, resources, contents) {
102
+ const conditions = new Set(manifest.conditions.map((item) => item.key));
103
+ for (const evidenceItem of manifest.evidence) {
104
+ const resource = resources.get(evidenceItem.resource_ref);
105
+ const bytes = contents.get(evidenceItem.resource_ref);
106
+ if (!resource || !bytes)
107
+ invalid("manifest_evidence_resource_unknown", evidenceItem.key);
108
+ for (const conditionRef of evidenceItem.condition_refs)
109
+ if (!conditions.has(conditionRef))
110
+ invalid("manifest_evidence_condition_unknown", `${evidenceItem.key}:${conditionRef}`);
111
+ resolveDesignResourceLocatorValue({ resource_ref: evidenceItem.resource_ref, ...evidenceItem.locator }, resource, bytes, `manifest.evidence.${evidenceItem.key}`);
112
+ }
113
+ }
@@ -0,0 +1,5 @@
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
+ export declare function validateManifestDesignSystem(manifest: DesignResourceObservableFactManifestV1, handoff: DesignResourceHandoffV1, target: DesignResourceHandoffTargetV1, resources: Map<string, DesignResource>): void;
5
+ export declare function validateManifestSubjects(manifest: DesignResourceObservableFactManifestV1, census: Map<string, DesignResourceObservableFactManifestV1["inspector"]["census"][number]>): void;
@@ -0,0 +1,97 @@
1
+ import { invalid, nonempty, refsKnown, unique, } from "./design-resource-fact-universe-helpers.js";
2
+ export function validateManifestDesignSystem(manifest, handoff, target, resources) {
3
+ const snapshot = manifest.design_system;
4
+ const styleBearing = handoff.scope.style_dependency !== "non-fidelity";
5
+ if (styleBearing && snapshot.disposition !== "used")
6
+ invalid("manifest_design_system_required", manifest.target_key);
7
+ if (!styleBearing && snapshot.disposition !== "not_applicable")
8
+ invalid("manifest_design_system_not_applicable_required", manifest.target_key);
9
+ if (snapshot.id !== handoff.provenance.design_system_id)
10
+ invalid("manifest_design_system_id_mismatch", `${snapshot.id}:${handoff.provenance.design_system_id}`);
11
+ const resource = resources.get(snapshot.resource_ref);
12
+ if (!resource)
13
+ invalid("manifest_design_system_resource_unknown", snapshot.resource_ref);
14
+ if (!target.resource_refs.includes(snapshot.resource_ref))
15
+ invalid("manifest_design_system_resource_outside_target", `${target.key}:${snapshot.resource_ref}`);
16
+ if (resource.sha256 !== snapshot.sha256)
17
+ invalid("manifest_design_system_digest_mismatch", `${snapshot.resource_ref}:${snapshot.sha256}:${resource.sha256}`);
18
+ }
19
+ export function validateManifestSubjects(manifest, census) {
20
+ const subjects = new Map(manifest.subjects.map((subject) => [subject.key, subject]));
21
+ const roots = manifest.subjects.filter((subject) => subject.parent_ref === null &&
22
+ (subject.kind === "surface" || subject.kind === "flow"));
23
+ if (!roots.length)
24
+ invalid("manifest_subject_root_required", manifest.target_key);
25
+ for (const subject of manifest.subjects)
26
+ validateSubject(subject, subjects, census);
27
+ validateSubjectParentAcyclic(manifest, subjects);
28
+ }
29
+ function validateSubject(subject, subjects, census) {
30
+ nonempty(subject.census_refs, `manifest_subject_census_required:${subject.key}`);
31
+ refsKnown(subject.census_refs, census, "manifest_subject_census_unknown", subject.key);
32
+ if (subject.presence === "always" && subject.presence_rule_ref !== null)
33
+ invalid("manifest_always_presence_rule_forbidden", subject.key);
34
+ if (subject.presence !== "always" && subject.presence_rule_ref === null)
35
+ invalid("manifest_dynamic_presence_rule_required", subject.key);
36
+ validatePresenceAndPopulation(subject, census);
37
+ for (const ref of [
38
+ subject.parent_ref,
39
+ subject.instance_of_ref,
40
+ subject.override_of_ref,
41
+ subject.family_ref,
42
+ subject.portal_host_ref,
43
+ ])
44
+ if (ref !== null && !subjects.has(ref))
45
+ invalid("manifest_subject_relation_unknown", `${subject.key}:${ref}`);
46
+ if (subject.parent_ref === null &&
47
+ subject.kind !== "surface" &&
48
+ subject.kind !== "flow")
49
+ invalid("manifest_subject_parent_required", subject.key);
50
+ if (subject.presence === "portal" && subject.portal_host_ref === null)
51
+ invalid("manifest_portal_host_required", subject.key);
52
+ validateRelationSubject(subject, subjects);
53
+ }
54
+ function validatePresenceAndPopulation(subject, census) {
55
+ if (subject.presence_rule_ref !== null) {
56
+ const presenceRule = census.get(subject.presence_rule_ref);
57
+ if (!presenceRule)
58
+ invalid("manifest_presence_rule_census_unknown", `${subject.key}:${subject.presence_rule_ref}`);
59
+ if (!["declaration", "state", "dynamic_population"].includes(presenceRule.kind))
60
+ invalid("manifest_presence_rule_census_kind_invalid", `${subject.key}:${subject.presence_rule_ref}:${presenceRule.kind}`);
61
+ }
62
+ if (subject.presence === "virtualized" && subject.population_ref === null)
63
+ invalid("manifest_virtualized_population_required", subject.key);
64
+ if (subject.population_ref === null)
65
+ return;
66
+ const population = census.get(subject.population_ref);
67
+ if (!population)
68
+ invalid("manifest_population_census_unknown", `${subject.key}:${subject.population_ref}`);
69
+ if (population.kind !== "dynamic_population")
70
+ invalid("manifest_population_census_kind_invalid", `${subject.key}:${subject.population_ref}:${population.kind}`);
71
+ }
72
+ function validateRelationSubject(subject, subjects) {
73
+ if (subject.kind !== "relation") {
74
+ if (subject.relation_endpoints.length)
75
+ invalid("manifest_nonrelation_endpoints_forbidden", subject.key);
76
+ return;
77
+ }
78
+ if (subject.relation_endpoints.length < 2)
79
+ invalid("manifest_relation_endpoints_required", subject.key);
80
+ unique(subject.relation_endpoints.map((item) => item.role), `manifest_relation_endpoint_role_duplicate:${subject.key}`);
81
+ for (const endpoint of subject.relation_endpoints)
82
+ if (endpoint.subject_ref === subject.key ||
83
+ !subjects.has(endpoint.subject_ref))
84
+ invalid("manifest_relation_endpoint_invalid", `${subject.key}:${endpoint.role}:${endpoint.subject_ref}`);
85
+ }
86
+ function validateSubjectParentAcyclic(manifest, subjects) {
87
+ for (const subject of manifest.subjects) {
88
+ const visited = new Set();
89
+ let current = subject;
90
+ while (current?.parent_ref) {
91
+ if (visited.has(current.key))
92
+ invalid("manifest_subject_parent_cycle", subject.key);
93
+ visited.add(current.key);
94
+ current = subjects.get(current.parent_ref);
95
+ }
96
+ }
97
+ }
@@ -0,0 +1,2 @@
1
+ import { type DesignResourceObservableFactManifestV1 } from "./design-resource-fact-manifest-types.js";
2
+ export declare function validateManifestVariationUniverse(manifest: DesignResourceObservableFactManifestV1, census: Map<string, DesignResourceObservableFactManifestV1["inspector"]["census"][number]>, sourceItems: Map<string, string>): void;
@@ -0,0 +1,75 @@
1
+ import { DESIGN_RESOURCE_VARIATION_AXES, } from "./design-resource-fact-manifest-types.js";
2
+ import { axisFingerprint, cartesian, exactAxisPairs, groupBy, invalid, nonempty, refsKnown, sameSet, unique, validateBasis, variationValues, } from "./design-resource-fact-universe-helpers.js";
3
+ export function validateManifestVariationUniverse(manifest, census, sourceItems) {
4
+ const subjects = new Set(manifest.subjects.map((item) => item.key));
5
+ const variationsBySubject = groupBy(manifest.variations, (item) => item.subject_ref);
6
+ const axesBySubject = groupBy(manifest.variation_axis_dispositions, (item) => item.subject_ref);
7
+ const exclusionsBySubject = groupBy(manifest.variation_exclusions, (item) => item.subject_ref);
8
+ for (const subjectRef of subjects) {
9
+ validateSubjectVariations(subjectRef, variationsBySubject.get(subjectRef) ?? [], axesBySubject.get(subjectRef) ?? [], exclusionsBySubject.get(subjectRef) ?? [], census, sourceItems);
10
+ }
11
+ for (const ref of [
12
+ ...variationsBySubject.keys(),
13
+ ...axesBySubject.keys(),
14
+ ...exclusionsBySubject.keys(),
15
+ ])
16
+ if (!subjects.has(ref))
17
+ invalid("manifest_variation_subject_unknown", ref);
18
+ }
19
+ function validateSubjectVariations(subjectRef, variations, axes, exclusions, census, sourceItems) {
20
+ unique(axes.map((axis) => axis.axis), `manifest_variation_axis_duplicate:${subjectRef}`);
21
+ for (const axis of DESIGN_RESOURCE_VARIATION_AXES)
22
+ if (!axes.some((item) => item.axis === axis))
23
+ invalid("manifest_variation_standard_axis_missing", `${subjectRef}:${axis}`);
24
+ for (const axis of axes)
25
+ validateVariationAxis(axis, census, sourceItems);
26
+ const byAxis = new Map(axes.map((axis) => [axis.axis, axis]));
27
+ const actual = validateVariations(variations, byAxis);
28
+ const excluded = validateVariationExclusions(exclusions, census, sourceItems, actual);
29
+ const expected = cartesian(axes.map((axis) => axis.values.map((value) => [axis.axis, value.key]))).map(axisFingerprint);
30
+ sameSet([...actual.keys(), ...excluded.keys()], expected, "manifest_variation_universe_mismatch", subjectRef);
31
+ if (!actual.size)
32
+ invalid("manifest_subject_variation_required", subjectRef);
33
+ }
34
+ function validateVariationAxis(axis, census, sourceItems) {
35
+ validateBasis(axis, sourceItems, census, `manifest_variation_axis:${axis.key}`);
36
+ nonempty(axis.values, `manifest_variation_axis_values_required:${axis.key}`);
37
+ unique(axis.values.map((value) => value.key), `manifest_variation_axis_value_duplicate:${axis.key}`);
38
+ if (axis.disposition === "not_applicable" &&
39
+ (axis.values.length !== 1 || axis.values[0].key !== "not-applicable"))
40
+ invalid("manifest_variation_axis_not_applicable_invalid", axis.key);
41
+ for (const value of axis.values) {
42
+ if (axis.disposition === "applicable")
43
+ nonempty(value.census_refs, `manifest_variation_value_census_required:${axis.key}:${value.key}`);
44
+ refsKnown(value.census_refs, census, "manifest_variation_value_census_unknown", `${axis.key}:${value.key}`);
45
+ }
46
+ }
47
+ function validateVariations(variations, byAxis) {
48
+ const actual = new Map();
49
+ for (const variation of variations) {
50
+ const values = variationValues(variation);
51
+ for (const [axis, value] of values)
52
+ if (!byAxis.get(axis).values.some((candidate) => candidate.key === value))
53
+ invalid("manifest_variation_axis_value_unknown", `${variation.key}:${axis}:${value}`);
54
+ const fingerprint = axisFingerprint(values);
55
+ if (actual.has(fingerprint))
56
+ invalid("manifest_variation_combination_duplicate", `${actual.get(fingerprint)}:${variation.key}`);
57
+ actual.set(fingerprint, variation.key);
58
+ }
59
+ return actual;
60
+ }
61
+ function validateVariationExclusions(exclusions, census, sourceItems, actual) {
62
+ const excluded = new Map();
63
+ for (const row of exclusions) {
64
+ validateBasis(row, sourceItems, census, `manifest_variation_exclusion:${row.key}`);
65
+ if (row.disposition === "decision_required" ||
66
+ row.disposition === "unavailable")
67
+ invalid("manifest_variation_exclusion_unresolved", row.key);
68
+ const values = exactAxisPairs(row.axis_values, [...DESIGN_RESOURCE_VARIATION_AXES], `manifest_variation_exclusion:${row.key}`);
69
+ const fingerprint = axisFingerprint(values);
70
+ if (actual.has(fingerprint) || excluded.has(fingerprint))
71
+ invalid("manifest_variation_exclusion_duplicate", row.key);
72
+ excluded.set(fingerprint, row.key);
73
+ }
74
+ return excluded;
75
+ }
@@ -0,0 +1,2 @@
1
+ import type { DesignResourceValueKind } from "./design-resource-fact-manifest-types.js";
2
+ export declare function validateDesignResourceValueKind(kind: DesignResourceValueKind, value: Buffer, label: string): void;
@@ -0,0 +1,80 @@
1
+ import { invalidDesignResourceHandoff } from "./design-resource-handoff-validation-primitives.js";
2
+ const VALUE_VALIDATORS = {
3
+ boolean: (text) => /^(?:true|false)$/u.test(text),
4
+ color: (text) => !text.includes("|") &&
5
+ (/^#[a-f0-9]{3,8}$/iu.test(text) ||
6
+ /^(?:rgb|rgba|hsl|hsla|hwb|lab|lch|oklab|oklch|color|color-mix|light-dark|var)\(.+\)$/iu.test(text) ||
7
+ /^(?:transparent|currentcolor|[a-z]+)$/iu.test(text)),
8
+ digest: (text) => /^[a-f0-9]{64}$/u.test(text),
9
+ enum: (text) => /^[a-z0-9][a-z0-9._:-]*$/iu.test(text),
10
+ length: (text, structured) => isLength(text, structured),
11
+ list: (text, structured) => structured === null
12
+ ? !text.includes("|")
13
+ : Array.isArray(structured) || typeof structured === "object",
14
+ locator: () => true,
15
+ number: (text) => isFiniteNumber(text),
16
+ ratio: (text, structured) => isRatio(text, structured),
17
+ relation: (_text, structured) => isStructuredCollection(structured),
18
+ semantic: (text, structured) => structured !== null || /^[a-z0-9][a-z0-9._:-]*$/iu.test(text),
19
+ string: () => true,
20
+ timeline: (_text, structured) => isStructuredCollection(structured),
21
+ token_ref: (text, structured) => structured !== null ||
22
+ /^(?:--[a-z0-9_-]+|[a-z0-9][a-z0-9._/-]*)$/iu.test(text),
23
+ trace: (_text, structured) => isStructuredCollection(structured),
24
+ };
25
+ export function validateDesignResourceValueKind(kind, value, label) {
26
+ const text = value.toString("utf8").trim();
27
+ const structured = text ? parseStructuredValue(text) : null;
28
+ if (!text || !VALUE_VALIDATORS[kind](text, structured)) {
29
+ invalidDesignResourceHandoff("located_value_kind_mismatch", `${label}:${kind}`);
30
+ }
31
+ }
32
+ function parseStructuredValue(value) {
33
+ if (!value.startsWith("{") && !value.startsWith("["))
34
+ return null;
35
+ try {
36
+ return JSON.parse(value);
37
+ }
38
+ catch {
39
+ return null;
40
+ }
41
+ }
42
+ function isStructuredCollection(value) {
43
+ return value !== null && typeof value === "object";
44
+ }
45
+ function isFiniteNumber(value) {
46
+ if (!/^-?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/iu.test(value))
47
+ return false;
48
+ return Number.isFinite(Number(value));
49
+ }
50
+ function isLength(value, structured) {
51
+ if (structured &&
52
+ typeof structured === "object" &&
53
+ !Array.isArray(structured)) {
54
+ const row = structured;
55
+ return (typeof row.value === "number" &&
56
+ Number.isFinite(row.value) &&
57
+ typeof row.unit === "string" &&
58
+ /^[a-z%][a-z0-9%_-]*$/iu.test(row.unit));
59
+ }
60
+ return (/^(?:0|-?(?:\d+\.?\d*|\.\d+)(?:px|dp|sp|pt|pc|in|cm|mm|q|em|rem|ex|ch|cap|ic|lh|rlh|vw|vh|vi|vb|vmin|vmax|svw|svh|lvw|lvh|dvw|dvh|cqw|cqh|cqi|cqb|cqmin|cqmax|%))$/iu.test(value) ||
61
+ /^(?:calc|min|max|clamp|fit-content|var|env)\(.+\)$/iu.test(value) ||
62
+ /^(?:auto|min-content|max-content|stretch|normal|hairline)$/iu.test(value));
63
+ }
64
+ function isRatio(value, structured) {
65
+ if (isFiniteNumber(value))
66
+ return true;
67
+ if (/^-?(?:\d+\.?\d*|\.\d+)\s*\/\s*-?(?:\d+\.?\d*|\.\d+)$/u.test(value))
68
+ return true;
69
+ if (Array.isArray(structured)) {
70
+ return (structured.length === 2 &&
71
+ structured.every((item) => typeof item === "number" && Number.isFinite(item)));
72
+ }
73
+ if (!structured || typeof structured !== "object")
74
+ return false;
75
+ const row = structured;
76
+ return (typeof row.width === "number" &&
77
+ Number.isFinite(row.width) &&
78
+ typeof row.height === "number" &&
79
+ Number.isFinite(row.height));
80
+ }
@@ -9,6 +9,8 @@ export function isTextResource(resource) {
9
9
  [
10
10
  "application/javascript",
11
11
  "application/json",
12
+ "application/typescript",
12
13
  "application/xhtml+xml",
14
+ "image/svg+xml",
13
15
  ].includes(resource.media_type));
14
16
  }