project-tiny-context-harness 0.8.4 → 0.8.5

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 (252) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +393 -371
  3. package/assets/README.md +573 -526
  4. package/assets/README.zh-CN.md +333 -311
  5. package/assets/agents/.gitkeep +1 -1
  6. package/assets/agents/AGENTS_CORE.md +44 -25
  7. package/assets/context_templates/architecture.md +28 -28
  8. package/assets/context_templates/area.md +34 -34
  9. package/assets/context_templates/context.toml +30 -30
  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 +32 -32
  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 +148 -125
  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-templates.js +1 -1
  43. package/dist/lib/design-resource-fact-enums.d.ts +20 -0
  44. package/dist/lib/design-resource-fact-enums.js +170 -0
  45. package/dist/lib/design-resource-fact-locator-extractors.d.ts +8 -0
  46. package/dist/lib/design-resource-fact-locator-extractors.js +108 -0
  47. package/dist/lib/design-resource-fact-locator-resolver.d.ts +3 -0
  48. package/dist/lib/design-resource-fact-locator-resolver.js +112 -0
  49. package/dist/lib/design-resource-fact-locator-validation.d.ts +5 -0
  50. package/dist/lib/design-resource-fact-locator-validation.js +16 -0
  51. package/dist/lib/design-resource-fact-manifest-catalog.d.ts +4 -0
  52. package/dist/lib/design-resource-fact-manifest-catalog.js +249 -0
  53. package/dist/lib/design-resource-fact-manifest-model.d.ts +91 -0
  54. package/dist/lib/design-resource-fact-manifest-model.js +21 -0
  55. package/dist/lib/design-resource-fact-manifest-shape-axes.d.ts +6 -0
  56. package/dist/lib/design-resource-fact-manifest-shape-axes.js +159 -0
  57. package/dist/lib/design-resource-fact-manifest-shape-evidence.d.ts +4 -0
  58. package/dist/lib/design-resource-fact-manifest-shape-evidence.js +59 -0
  59. package/dist/lib/design-resource-fact-manifest-shape-facts.d.ts +4 -0
  60. package/dist/lib/design-resource-fact-manifest-shape-facts.js +109 -0
  61. package/dist/lib/design-resource-fact-manifest-shape-inspector.d.ts +5 -0
  62. package/dist/lib/design-resource-fact-manifest-shape-inspector.js +144 -0
  63. package/dist/lib/design-resource-fact-manifest-shape.d.ts +7 -0
  64. package/dist/lib/design-resource-fact-manifest-shape.js +75 -0
  65. package/dist/lib/design-resource-fact-manifest-types.d.ts +3 -0
  66. package/dist/lib/design-resource-fact-manifest-types.js +3 -0
  67. package/dist/lib/design-resource-fact-manifest-universe.d.ts +5 -0
  68. package/dist/lib/design-resource-fact-manifest-universe.js +50 -0
  69. package/dist/lib/design-resource-fact-manifest-validation.d.ts +3 -0
  70. package/dist/lib/design-resource-fact-manifest-validation.js +106 -0
  71. package/dist/lib/design-resource-fact-policy.d.ts +18 -0
  72. package/dist/lib/design-resource-fact-policy.js +72 -1
  73. package/dist/lib/design-resource-fact-property-methods.d.ts +3 -0
  74. package/dist/lib/design-resource-fact-property-methods.js +158 -0
  75. package/dist/lib/design-resource-fact-shape-primitives.d.ts +3 -0
  76. package/dist/lib/design-resource-fact-shape-primitives.js +18 -0
  77. package/dist/lib/design-resource-fact-types.d.ts +164 -0
  78. package/dist/lib/design-resource-fact-types.js +1 -0
  79. package/dist/lib/design-resource-fact-universe-assets.d.ts +4 -0
  80. package/dist/lib/design-resource-fact-universe-assets.js +71 -0
  81. package/dist/lib/design-resource-fact-universe-catalog.d.ts +4 -0
  82. package/dist/lib/design-resource-fact-universe-catalog.js +151 -0
  83. package/dist/lib/design-resource-fact-universe-conditions.d.ts +2 -0
  84. package/dist/lib/design-resource-fact-universe-conditions.js +92 -0
  85. package/dist/lib/design-resource-fact-universe-facts.d.ts +4 -0
  86. package/dist/lib/design-resource-fact-universe-facts.js +108 -0
  87. package/dist/lib/design-resource-fact-universe-helpers.d.ts +30 -0
  88. package/dist/lib/design-resource-fact-universe-helpers.js +167 -0
  89. package/dist/lib/design-resource-fact-universe-inspector.d.ts +7 -0
  90. package/dist/lib/design-resource-fact-universe-inspector.js +119 -0
  91. package/dist/lib/design-resource-fact-universe-proof.d.ts +4 -0
  92. package/dist/lib/design-resource-fact-universe-proof.js +113 -0
  93. package/dist/lib/design-resource-fact-universe-subjects.d.ts +5 -0
  94. package/dist/lib/design-resource-fact-universe-subjects.js +97 -0
  95. package/dist/lib/design-resource-fact-universe-variations.d.ts +2 -0
  96. package/dist/lib/design-resource-fact-universe-variations.js +75 -0
  97. package/dist/lib/design-resource-fact-value-validation.d.ts +2 -0
  98. package/dist/lib/design-resource-fact-value-validation.js +80 -0
  99. package/dist/lib/design-resource-handoff-file-primitives.js +2 -0
  100. package/dist/lib/design-resource-handoff-file-validation.js +13 -100
  101. package/dist/lib/design-resource-handoff-policy.d.ts +1 -0
  102. package/dist/lib/design-resource-handoff-policy.js +118 -11
  103. package/dist/lib/design-resource-handoff-shape-evidence.js +46 -3
  104. package/dist/lib/design-resource-handoff-shape-primitives.d.ts +5 -0
  105. package/dist/lib/design-resource-handoff-shape-primitives.js +28 -0
  106. package/dist/lib/design-resource-handoff-shape-structure.js +143 -22
  107. package/dist/lib/design-resource-handoff-shape.js +25 -0
  108. package/dist/lib/design-resource-handoff-types.d.ts +97 -21
  109. package/dist/lib/design-resource-handoff-types.js +22 -0
  110. package/dist/lib/design-resource-handoff-validation-coverage.d.ts +1 -1
  111. package/dist/lib/design-resource-handoff-validation-coverage.js +145 -118
  112. package/dist/lib/design-resource-handoff-validation-fact-cells.d.ts +2 -0
  113. package/dist/lib/design-resource-handoff-validation-fact-cells.js +60 -0
  114. package/dist/lib/design-resource-handoff-validation-fact-records.d.ts +2 -0
  115. package/dist/lib/design-resource-handoff-validation-fact-records.js +90 -0
  116. package/dist/lib/design-resource-handoff-validation-facts.js +10 -94
  117. package/dist/lib/design-resource-handoff-validation-proofs.d.ts +2 -0
  118. package/dist/lib/design-resource-handoff-validation-proofs.js +67 -0
  119. package/dist/lib/design-resource-handoff-validation-resource-closure.d.ts +3 -0
  120. package/dist/lib/design-resource-handoff-validation-resource-closure.js +88 -0
  121. package/dist/lib/design-resource-handoff-validation-structure.js +43 -14
  122. package/dist/lib/design-resource-handoff-validation.js +32 -0
  123. package/dist/lib/design-resource-handoff-web-dependency-validation.d.ts +2 -1
  124. package/dist/lib/design-resource-handoff-web-dependency-validation.js +67 -7
  125. package/dist/lib/execution-target-capabilities.d.ts +1 -1
  126. package/dist/lib/execution-target-capabilities.js +14 -0
  127. package/dist/lib/long-task-activation-validation.js +6 -2
  128. package/dist/lib/long-task-applicability-shape.js +3 -3
  129. package/dist/lib/long-task-authoring-authority-preview.js +1 -0
  130. package/dist/lib/long-task-authority-policy.d.ts +1 -0
  131. package/dist/lib/long-task-authority-policy.js +1 -0
  132. package/dist/lib/long-task-authority.js +13 -0
  133. package/dist/lib/long-task-claim-definitions.js +13 -1
  134. package/dist/lib/long-task-claims.js +23 -1
  135. package/dist/lib/long-task-contract-types.d.ts +3 -0
  136. package/dist/lib/long-task-delivery-compiler.js +1 -0
  137. package/dist/lib/long-task-delivery-parser.js +11 -1
  138. package/dist/lib/long-task-delivery-types.d.ts +1 -0
  139. package/dist/lib/long-task-delivery-types.js +1 -0
  140. package/dist/lib/long-task-delivery-validation.js +17 -0
  141. package/dist/lib/long-task-design-resource-handoff.js +62 -38
  142. package/dist/lib/long-task-design-target-capabilities.d.ts +14 -0
  143. package/dist/lib/long-task-design-target-capabilities.js +126 -0
  144. package/dist/lib/long-task-evidence-capability-codec.d.ts +94 -0
  145. package/dist/lib/long-task-evidence-capability-codec.js +395 -22
  146. package/dist/lib/long-task-evidence-capability-policy.js +18 -0
  147. package/dist/lib/long-task-evidence-capability-runtime.js +78 -0
  148. package/dist/lib/long-task-evidence-capability-types.d.ts +114 -1
  149. package/dist/lib/long-task-outcome-parser.js +4 -0
  150. package/dist/lib/long-task-playwright-capability-records.d.ts +5 -0
  151. package/dist/lib/long-task-playwright-capability-records.js +146 -0
  152. package/dist/lib/long-task-playwright-case-evidence.d.ts +3 -2
  153. package/dist/lib/long-task-playwright-case-evidence.js +10 -79
  154. package/dist/lib/long-task-playwright-case-primitives.d.ts +28 -0
  155. package/dist/lib/long-task-playwright-case-primitives.js +143 -0
  156. package/dist/lib/long-task-playwright-evidence.d.ts +1 -1
  157. package/dist/lib/long-task-playwright-evidence.js +10 -75
  158. package/dist/lib/long-task-runner-freeze.d.ts +2 -2
  159. package/dist/lib/long-task-runner-freeze.js +15 -1
  160. package/dist/lib/long-task-runtime-types.d.ts +4 -1
  161. package/dist/lib/long-task-semantic-contract-types.d.ts +1 -1
  162. package/dist/lib/long-task-semantic-drift-migration.js +2 -2
  163. package/dist/lib/long-task-semantic-fact-binding-types.d.ts +57 -0
  164. package/dist/lib/long-task-semantic-fact-binding-types.js +1 -0
  165. package/dist/lib/long-task-semantic-fact-closure-primitives.d.ts +5 -0
  166. package/dist/lib/long-task-semantic-fact-closure-primitives.js +43 -0
  167. package/dist/lib/long-task-semantic-fact-closure.d.ts +13 -0
  168. package/dist/lib/long-task-semantic-fact-closure.js +48 -0
  169. package/dist/lib/long-task-semantic-fact-contract-closure.d.ts +4 -0
  170. package/dist/lib/long-task-semantic-fact-contract-closure.js +24 -0
  171. package/dist/lib/long-task-semantic-fact-contract-facts.d.ts +4 -0
  172. package/dist/lib/long-task-semantic-fact-contract-facts.js +30 -0
  173. package/dist/lib/long-task-semantic-fact-contract-proofs.d.ts +4 -0
  174. package/dist/lib/long-task-semantic-fact-contract-proofs.js +97 -0
  175. package/dist/lib/long-task-semantic-fact-evidence.d.ts +21 -0
  176. package/dist/lib/long-task-semantic-fact-evidence.js +165 -0
  177. package/dist/lib/long-task-semantic-fact-input-closure.d.ts +4 -0
  178. package/dist/lib/long-task-semantic-fact-input-closure.js +101 -0
  179. package/dist/lib/long-task-semantic-fact-provenance-closure.d.ts +4 -0
  180. package/dist/lib/long-task-semantic-fact-provenance-closure.js +140 -0
  181. package/dist/lib/long-task-semantic-fact-shape.d.ts +3 -0
  182. package/dist/lib/long-task-semantic-fact-shape.js +89 -0
  183. package/dist/lib/long-task-semantic-fact-value-closure.d.ts +3 -0
  184. package/dist/lib/long-task-semantic-fact-value-closure.js +110 -0
  185. package/dist/lib/long-task-shape-primitives.d.ts +2 -1
  186. package/dist/lib/long-task-shape-primitives.js +7 -0
  187. package/dist/lib/long-task-source-item-parser.js +25 -6
  188. package/dist/lib/long-task-source-target-continuity.js +4 -1
  189. package/dist/lib/long-task-source-target-index.d.ts +1 -1
  190. package/dist/lib/long-task-source-target-index.js +5 -1
  191. package/dist/lib/long-task-ui-design-policy.js +8 -4
  192. package/dist/lib/long-task-ui-surface-shape.js +83 -1
  193. package/dist/lib/long-task-ui-surface-types.d.ts +29 -0
  194. package/dist/lib/modularity.js +7 -1
  195. package/dist/lib/semantic-fact-base-types.d.ts +14 -0
  196. package/dist/lib/semantic-fact-base-types.js +1 -0
  197. package/dist/lib/semantic-fact-catalog.d.ts +8 -0
  198. package/dist/lib/semantic-fact-catalog.js +191 -0
  199. package/dist/lib/semantic-fact-condition-shape.d.ts +48 -0
  200. package/dist/lib/semantic-fact-condition-shape.js +111 -0
  201. package/dist/lib/semantic-fact-input-shape.d.ts +34 -0
  202. package/dist/lib/semantic-fact-input-shape.js +111 -0
  203. package/dist/lib/semantic-fact-inventory-types.d.ts +147 -0
  204. package/dist/lib/semantic-fact-inventory-types.js +1 -0
  205. package/dist/lib/semantic-fact-manifest-shape.d.ts +4 -0
  206. package/dist/lib/semantic-fact-manifest-shape.js +135 -0
  207. package/dist/lib/semantic-fact-manifest-types.d.ts +58 -0
  208. package/dist/lib/semantic-fact-manifest-types.js +19 -0
  209. package/dist/lib/semantic-fact-policy-authority.d.ts +8 -0
  210. package/dist/lib/semantic-fact-policy-authority.js +79 -0
  211. package/dist/lib/semantic-fact-policy-census.d.ts +2 -0
  212. package/dist/lib/semantic-fact-policy-census.js +80 -0
  213. package/dist/lib/semantic-fact-policy-condition-references.d.ts +7 -0
  214. package/dist/lib/semantic-fact-policy-condition-references.js +19 -0
  215. package/dist/lib/semantic-fact-policy-conditions.d.ts +2 -0
  216. package/dist/lib/semantic-fact-policy-conditions.js +105 -0
  217. package/dist/lib/semantic-fact-policy-facts.d.ts +3 -0
  218. package/dist/lib/semantic-fact-policy-facts.js +73 -0
  219. package/dist/lib/semantic-fact-policy-primitives.d.ts +26 -0
  220. package/dist/lib/semantic-fact-policy-primitives.js +169 -0
  221. package/dist/lib/semantic-fact-policy-proofs.d.ts +2 -0
  222. package/dist/lib/semantic-fact-policy-proofs.js +75 -0
  223. package/dist/lib/semantic-fact-policy-properties.d.ts +3 -0
  224. package/dist/lib/semantic-fact-policy-properties.js +84 -0
  225. package/dist/lib/semantic-fact-policy-units.d.ts +4 -0
  226. package/dist/lib/semantic-fact-policy-units.js +103 -0
  227. package/dist/lib/semantic-fact-policy.d.ts +17 -0
  228. package/dist/lib/semantic-fact-policy.js +41 -0
  229. package/dist/lib/semantic-fact-proof-shape.d.ts +51 -0
  230. package/dist/lib/semantic-fact-proof-shape.js +121 -0
  231. package/dist/lib/semantic-fact-proof-types.d.ts +74 -0
  232. package/dist/lib/semantic-fact-proof-types.js +1 -0
  233. package/dist/lib/semantic-fact-property-shape.d.ts +29 -0
  234. package/dist/lib/semantic-fact-property-shape.js +77 -0
  235. package/dist/lib/semantic-fact-shape-constants.d.ts +3 -0
  236. package/dist/lib/semantic-fact-shape-constants.js +38 -0
  237. package/dist/lib/semantic-fact-shape-primitives.d.ts +15 -0
  238. package/dist/lib/semantic-fact-shape-primitives.js +68 -0
  239. package/dist/lib/semantic-fact-source-parser.d.ts +9 -0
  240. package/dist/lib/semantic-fact-source-parser.js +46 -0
  241. package/dist/lib/semantic-fact-support-shape.d.ts +21 -0
  242. package/dist/lib/semantic-fact-support-shape.js +59 -0
  243. package/dist/lib/semantic-fact-types.d.ts +5 -0
  244. package/dist/lib/semantic-fact-types.js +5 -0
  245. package/dist/lib/semantic-fact-unit-shape.d.ts +34 -0
  246. package/dist/lib/semantic-fact-unit-shape.js +89 -0
  247. package/dist/lib/semantic-fact-value-shape.d.ts +12 -0
  248. package/dist/lib/semantic-fact-value-shape.js +39 -0
  249. package/dist/schemas/long-task-delivery-v2/long-task-delivery-v2.schema.json +1339 -131
  250. package/migrations/README.md +15 -15
  251. package/package.json +84 -84
  252. package/source-mappings.yaml +25 -25
@@ -0,0 +1,165 @@
1
+ import { canonicalValueJson, sha256Hex } from "./strict-codec.js";
2
+ export function validateSemanticFactEvidence(check, record, artifactHashes) {
3
+ const expectations = check.semantic_fact_expectations.filter((item) => item.assertion_ref === record.assertion_key);
4
+ if (expectations.length !== 1)
5
+ return expectations.length
6
+ ? "semantic_fact_expectation_duplicate"
7
+ : "semantic_fact_expectation_missing";
8
+ const expected = expectations[0];
9
+ const authorityError = validateSemanticFactEvidenceAuthority(check, record, expected);
10
+ if (authorityError)
11
+ return authorityError;
12
+ const artifactError = validateSemanticFactArtifacts(record, expected, artifactHashes);
13
+ if (artifactError)
14
+ return artifactError;
15
+ const observerError = validateSemanticFactObservers(record, expected, artifactHashes);
16
+ if (observerError)
17
+ return observerError;
18
+ if (record.verdict !== "passed" || record.comparison.passed !== true)
19
+ return "semantic_fact_failed";
20
+ return null;
21
+ }
22
+ function validateSemanticFactEvidenceAuthority(check, record, expected) {
23
+ if (!sameSemanticFactIdentity(record, expected))
24
+ return "semantic_fact_identity_mismatch";
25
+ if (record.target_ref !== check.execution_target.target_ref ||
26
+ expected.check_ref !== check.key)
27
+ return "semantic_fact_target_mismatch";
28
+ if (record.actual_observation.sensitivity !== expected.observation_sensitivity)
29
+ return "semantic_fact_sensitivity_mismatch";
30
+ if (!validSemanticFactRedaction(record.actual_observation.sensitivity, record.actual_observation.redaction))
31
+ return "semantic_fact_redaction_mismatch";
32
+ if (canonicalValueJson(record.expected) !==
33
+ canonicalValueJson(expected.expected))
34
+ return "semantic_fact_expected_value_mismatch";
35
+ if (!sameSemanticFactComparisonAuthority(record, expected))
36
+ return "semantic_fact_comparison_authority_mismatch";
37
+ if (record.comparison.result_sha256 !==
38
+ semanticFactComparisonResultIdentity({
39
+ fact_ref: record.fact_ref,
40
+ proof_ref: record.proof_ref,
41
+ target_ref: record.target_ref,
42
+ actual_value_sha256: record.actual_observation.value_sha256,
43
+ expected_value_sha256: expected.expected.sha256,
44
+ comparator: record.comparison.comparator,
45
+ mode: record.comparison.mode,
46
+ parameters_sha256: record.comparison.parameters.sha256,
47
+ tolerance_sha256: record.comparison.tolerance?.sha256 ?? null,
48
+ mask_sha256: record.comparison.mask?.sha256 ?? null,
49
+ passed: record.comparison.passed,
50
+ }))
51
+ return "semantic_fact_comparison_result_identity_mismatch";
52
+ if (record.comparison.comparator === "exact_value" &&
53
+ record.actual_observation.value_sha256 !== expected.expected.sha256)
54
+ return "semantic_fact_exact_value_mismatch";
55
+ if (canonicalValueJson(record.oracle) !== canonicalValueJson(expected.oracle) ||
56
+ canonicalValueJson(record.environment) !==
57
+ canonicalValueJson(expected.environment))
58
+ return "semantic_fact_oracle_environment_mismatch";
59
+ return null;
60
+ }
61
+ function sameSemanticFactIdentity(record, expected) {
62
+ return (record.manifest_ref === expected.manifest_ref &&
63
+ record.manifest_sha256 === expected.manifest_sha256 &&
64
+ record.outcome_ref === expected.outcome_ref &&
65
+ record.fact_ref === expected.fact_ref &&
66
+ record.proof_ref === expected.proof_ref &&
67
+ record.method === expected.method &&
68
+ record.subject_ref === expected.subject_ref &&
69
+ record.condition_ref === expected.condition_ref &&
70
+ record.property_ref === expected.property_ref);
71
+ }
72
+ function validSemanticFactRedaction(sensitivity, redaction) {
73
+ return ((sensitivity === "plain" && redaction === null) ||
74
+ (sensitivity === "protected" && redaction !== null));
75
+ }
76
+ function sameSemanticFactComparisonAuthority(record, expected) {
77
+ return (record.comparison.comparator === expected.comparison.comparator &&
78
+ record.comparison.mode === expected.comparison.mode &&
79
+ canonicalValueJson(record.comparison.parameters) ===
80
+ canonicalValueJson(expected.comparison.parameters) &&
81
+ canonicalValueJson(record.comparison.tolerance) ===
82
+ canonicalValueJson(expected.comparison.tolerance) &&
83
+ canonicalValueJson(record.comparison.mask) ===
84
+ canonicalValueJson(expected.comparison.mask));
85
+ }
86
+ function validateSemanticFactArtifacts(record, expected, artifactHashes) {
87
+ if (artifactHashes[record.actual_observation.artifact_path] !==
88
+ record.actual_observation.artifact_sha256)
89
+ return "semantic_fact_observation_artifact_mismatch";
90
+ if (artifactHashes[record.actual_environment.artifact_path] !==
91
+ record.actual_environment.artifact_sha256 ||
92
+ record.actual_environment.value_sha256 !==
93
+ expected.environment.definition.sha256)
94
+ return "semantic_fact_environment_observation_mismatch";
95
+ if (artifactHashes[record.comparison.artifact_path] !==
96
+ record.comparison.artifact_sha256)
97
+ return "semantic_fact_comparison_artifact_mismatch";
98
+ return null;
99
+ }
100
+ function validateSemanticFactObservers(record, expected, artifactHashes) {
101
+ if (!sameSet(record.observer_results.map((item) => item.target_ref), expected.observer_refs))
102
+ return "semantic_fact_observer_set_mismatch";
103
+ const observerObservations = new Set();
104
+ const primaryObservation = `${record.actual_observation.artifact_path}\0${canonicalValueJson(record.actual_observation.locator)}`;
105
+ for (const observer of record.observer_results) {
106
+ const observation = `${observer.artifact_path}\0${canonicalValueJson(observer.locator)}`;
107
+ if (observation === primaryObservation ||
108
+ observerObservations.has(observation))
109
+ return "semantic_fact_observer_observation_reused";
110
+ observerObservations.add(observation);
111
+ if (artifactHashes[observer.artifact_path] !== observer.artifact_sha256)
112
+ return "semantic_fact_observer_artifact_mismatch";
113
+ if (observer.passed !== true ||
114
+ (record.comparison.comparator === "exact_value" &&
115
+ observer.value_sha256 !== expected.expected.sha256))
116
+ return "semantic_fact_observer_failed";
117
+ if (observer.comparison_result_sha256 !==
118
+ semanticFactComparisonResultIdentity({
119
+ fact_ref: record.fact_ref,
120
+ proof_ref: record.proof_ref,
121
+ target_ref: observer.target_ref,
122
+ actual_value_sha256: observer.value_sha256,
123
+ expected_value_sha256: expected.expected.sha256,
124
+ comparator: record.comparison.comparator,
125
+ mode: record.comparison.mode,
126
+ parameters_sha256: record.comparison.parameters.sha256,
127
+ tolerance_sha256: record.comparison.tolerance?.sha256 ?? null,
128
+ mask_sha256: record.comparison.mask?.sha256 ?? null,
129
+ passed: observer.passed,
130
+ }))
131
+ return "semantic_fact_observer_comparison_identity_mismatch";
132
+ }
133
+ return null;
134
+ }
135
+ export function semanticFactComparisonResultIdentity(value) {
136
+ return sha256Hex(canonicalValueJson(value));
137
+ }
138
+ export function validateDistinctSemanticFactEvidence(records) {
139
+ const observations = new Set();
140
+ const comparisons = new Set();
141
+ const identities = new Set();
142
+ for (const record of records) {
143
+ if (record.capability !== "semantic_fact")
144
+ continue;
145
+ const identity = `${record.fact_ref}\0${record.proof_ref}`;
146
+ if (identities.has(identity))
147
+ return "semantic_fact_result_duplicate";
148
+ identities.add(identity);
149
+ const observation = `${record.actual_observation.artifact_path}\0${canonicalValueJson(record.actual_observation.locator)}`;
150
+ if (observations.has(observation))
151
+ return "semantic_fact_observation_reused";
152
+ observations.add(observation);
153
+ const comparison = `${record.comparison.artifact_path}\0${canonicalValueJson(record.comparison.locator)}`;
154
+ if (comparisons.has(comparison))
155
+ return "semantic_fact_comparison_reused";
156
+ comparisons.add(comparison);
157
+ }
158
+ return null;
159
+ }
160
+ function sameSet(left, right) {
161
+ return (left.length === right.length &&
162
+ new Set(left).size === left.length &&
163
+ left.every((item) => right.includes(item)));
164
+ }
165
+ export const typed_semantic_fact_runtime_evidence = "fact_ref+actual+comparison+verdict+oracle+environment";
@@ -0,0 +1,4 @@
1
+ import type { CompiledSourceItemV2 } from "./long-task-source-authority-types.js";
2
+ import type { SemanticFactManifestV1 } from "./semantic-fact-types.js";
3
+ export declare function collectDesignOwnedSemanticFactSourceItems(repository: string, sourcePaths: string[]): Promise<Set<string>>;
4
+ export declare function validateSemanticFactInputInventory(repository: string, sourceItems: CompiledSourceItemV2[], contextFiles: string[], manifest: SemanticFactManifestV1, designOwnedSourceItems: Set<string>): Promise<void>;
@@ -0,0 +1,101 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { containsDesignResourceHandoff, parseDesignResourceHandoffMarkdown, } from "./design-resource-handoff-parser.js";
4
+ import { assertSameSemanticFactClosureSet, semanticFactClosureInvalid, uniqueSemanticFactClosureValues, } from "./long-task-semantic-fact-closure-primitives.js";
5
+ import { validateSemanticFactProvenance } from "./long-task-semantic-fact-provenance-closure.js";
6
+ import { assertProtectedRepositoryFile } from "./long-task-protected-files.js";
7
+ import { sha256Hex } from "./strict-codec.js";
8
+ export async function collectDesignOwnedSemanticFactSourceItems(repository, sourcePaths) {
9
+ const result = new Set();
10
+ for (const sourcePath of sourcePaths) {
11
+ const file = await assertProtectedRepositoryFile(repository, path.resolve(repository, ...sourcePath.split("/")), `semantic_fact_design_source:${sourcePath}`);
12
+ const content = await readFile(file, "utf8");
13
+ if (!containsDesignResourceHandoff(content))
14
+ continue;
15
+ const parsed = parseDesignResourceHandoffMarkdown(sourcePath, content);
16
+ for (const key of parsed.source_item_keys)
17
+ result.add(key);
18
+ }
19
+ return result;
20
+ }
21
+ export async function validateSemanticFactInputInventory(repository, sourceItems, contextFiles, manifest, designOwnedSourceItems) {
22
+ const sourceItemByKey = new Map(sourceItems.map((item) => [item.key, item]));
23
+ const sourceInputs = manifest.inputs.filter((item) => item.kind === "source_item");
24
+ assertSameSemanticFactClosureSet(manifest.scope.source_item_refs, sourceItems.map((item) => item.key), "manifest_source_item_universe");
25
+ assertSameSemanticFactClosureSet(sourceInputs.map((item) => item.source_ref), sourceItems.map((item) => item.key), "input_source_item_universe");
26
+ validateSourceInputDigests(sourceInputs, sourceItemByKey, designOwnedSourceItems);
27
+ const contextInputs = manifest.inputs.filter((item) => item.kind === "context");
28
+ assertSameSemanticFactClosureSet(contextInputs.map((item) => item.source_ref), contextFiles, "input_context_universe");
29
+ for (const input of manifest.inputs)
30
+ await validateInput(repository, manifest, input, designOwnedSourceItems);
31
+ validateInputFactLineage(manifest, sourceInputs);
32
+ validateSemanticFactProvenance(manifest, sourceItems);
33
+ }
34
+ function validateSourceInputDigests(sourceInputs, sourceItemByKey, designOwnedSourceItems) {
35
+ for (const input of sourceInputs) {
36
+ const sourceItem = sourceItemByKey.get(input.source_ref);
37
+ if (input.sha256 !== sourceItem.text_sha256)
38
+ semanticFactClosureInvalid("input_source_item_digest_mismatch", `${input.key}:${input.source_ref}`);
39
+ const designOwned = designOwnedSourceItems.has(input.source_ref);
40
+ if (designOwned
41
+ ? !["ui_design", "non_ui_material"].includes(input.disposition)
42
+ : input.disposition !== "non_ui_material")
43
+ semanticFactClosureInvalid("material_source_item_disposition_mismatch", `${input.key}:${input.source_ref}:${input.disposition}:${designOwned ? "ui_design_or_non_ui_material" : "non_ui_material"}`);
44
+ }
45
+ }
46
+ async function validateInput(repository, manifest, input, designOwnedSourceItems) {
47
+ uniqueSemanticFactClosureValues(input.fact_refs, `input_fact_refs:${input.key}`);
48
+ uniqueSemanticFactClosureValues(input.basis_refs, `input_basis_refs:${input.key}`);
49
+ if (input.disposition === "non_ui_material"
50
+ ? !input.fact_refs.length
51
+ : input.fact_refs.length)
52
+ semanticFactClosureInvalid("input_fact_disposition_mismatch", `${input.key}:${input.disposition}`);
53
+ if (input.disposition !== "non_ui_material" && !input.rationale.trim())
54
+ semanticFactClosureInvalid("input_disposition_rationale_required", input.key);
55
+ if (["canonical_spec", "external_constraint", "delegated_instruction"].includes(input.kind) &&
56
+ input.disposition !== "non_ui_material")
57
+ semanticFactClosureInvalid("material_input_disposition_mismatch", `${input.key}:${input.kind}:${input.disposition}`);
58
+ const uiDesignInput = input.kind === "design_resource" ||
59
+ (input.kind === "source_item" &&
60
+ designOwnedSourceItems.has(input.source_ref));
61
+ if (uiDesignInput
62
+ ? !["ui_design", "non_ui_material"].includes(input.disposition)
63
+ : input.disposition === "ui_design")
64
+ semanticFactClosureInvalid("ui_design_input_kind_mismatch", `${input.key}:${input.kind}:${input.disposition}`);
65
+ if (input.disposition === "excluded_by_scope" &&
66
+ !manifest.scope.exclusions.some((exclusion) => exclusion.affected_refs.includes(input.key)))
67
+ semanticFactClosureInvalid("input_scope_exclusion_missing", input.key);
68
+ if (input.kind === "source_item")
69
+ return;
70
+ const file = await assertProtectedRepositoryFile(repository, path.resolve(repository, ...input.source_ref.split("/")), `semantic_fact_input:${input.key}`);
71
+ const digest = sha256Hex(await readFile(file));
72
+ if (digest !== input.sha256)
73
+ semanticFactClosureInvalid("input_resource_digest_mismatch", `${input.key}:${input.source_ref}`);
74
+ }
75
+ function validateInputFactLineage(manifest, sourceInputs) {
76
+ const facts = new Map(manifest.facts.map((item) => [item.key, item]));
77
+ for (const input of manifest.inputs)
78
+ for (const factRef of input.fact_refs)
79
+ if (!facts.has(factRef))
80
+ semanticFactClosureInvalid("input_fact_unknown", `${input.key}:${factRef}`);
81
+ else {
82
+ const fact = facts.get(factRef);
83
+ if (input.kind === "source_item"
84
+ ? !fact.source_item_refs.includes(input.source_ref)
85
+ : !fact.provenance.basis_refs.includes(input.key))
86
+ semanticFactClosureInvalid("input_fact_lineage_mismatch", `${input.key}:${factRef}`);
87
+ }
88
+ for (const fact of manifest.facts) {
89
+ const sourceInputRefs = fact.source_item_refs.map((sourceItemRef) => {
90
+ const input = sourceInputs.find((item) => item.source_ref === sourceItemRef);
91
+ if (!input)
92
+ semanticFactClosureInvalid("fact_source_input_missing", `${fact.key}:${sourceItemRef}`);
93
+ if (input.disposition !== "non_ui_material" ||
94
+ !input.fact_refs.includes(fact.key))
95
+ semanticFactClosureInvalid("fact_source_input_lineage_mismatch", `${fact.key}:${input.key}`);
96
+ return input.key;
97
+ });
98
+ if (!sourceInputRefs.length)
99
+ semanticFactClosureInvalid("fact_source_input_required", fact.key);
100
+ }
101
+ }
@@ -0,0 +1,4 @@
1
+ import type { CompiledSourceItemV2 } from "./long-task-source-authority-types.js";
2
+ import type { SemanticFactManifestV1 } from "./semantic-fact-types.js";
3
+ export declare function validateSemanticFactProvenance(manifest: SemanticFactManifestV1, sourceItems: CompiledSourceItemV2[]): void;
4
+ export declare function validateSemanticFactBasisClosure(manifest: SemanticFactManifestV1, sourceItems: CompiledSourceItemV2[]): void;
@@ -0,0 +1,140 @@
1
+ import { semanticFactClosureInvalid } from "./long-task-semantic-fact-closure-primitives.js";
2
+ export function validateSemanticFactProvenance(manifest, sourceItems) {
3
+ const sourceRefs = new Set(sourceItems.map((item) => item.key));
4
+ const inputByKey = new Map(manifest.inputs.map((item) => [item.key, item]));
5
+ const materialInputRefs = new Set(manifest.inputs
6
+ .filter((item) => item.disposition === "non_ui_material")
7
+ .map((item) => item.key));
8
+ const facts = new Map(manifest.facts.map((item) => [item.key, item]));
9
+ const isMaterialAuthority = (ref) => sourceRefs.has(ref) || materialInputRefs.has(ref);
10
+ for (const fact of manifest.facts)
11
+ validateFactAuthority(fact, facts, sourceRefs, inputByKey, isMaterialAuthority);
12
+ const grounded = new Map();
13
+ const visit = (factRef, active) => {
14
+ const cached = grounded.get(factRef);
15
+ if (cached !== undefined)
16
+ return cached;
17
+ if (active.has(factRef))
18
+ semanticFactClosureInvalid("fact_provenance_cycle", [...active, factRef].join("->"));
19
+ const fact = facts.get(factRef);
20
+ const next = new Set(active);
21
+ next.add(factRef);
22
+ const result = fact.provenance.basis_refs.some((ref) => isMaterialAuthority(ref) || (facts.has(ref) && visit(ref, next)));
23
+ grounded.set(factRef, result);
24
+ return result;
25
+ };
26
+ for (const fact of manifest.facts)
27
+ if (!visit(fact.key, new Set()))
28
+ semanticFactClosureInvalid("fact_provenance_ungrounded", fact.key);
29
+ }
30
+ function validateFactAuthority(fact, facts, sourceRefs, inputByKey, isMaterialAuthority) {
31
+ const authorityRef = fact.provenance.authority_ref;
32
+ if (!fact.provenance.basis_refs.includes(authorityRef))
33
+ semanticFactClosureInvalid("fact_authority_basis_missing", `${fact.key}:${authorityRef}`);
34
+ if (authorityRef === fact.key)
35
+ semanticFactClosureInvalid("fact_authority_self_reference", fact.key);
36
+ if (!isMaterialAuthority(authorityRef) && !facts.has(authorityRef))
37
+ semanticFactClosureInvalid("fact_authority_not_groundable", `${fact.key}:${authorityRef}`);
38
+ if (fact.provenance.kind !== "logically_derived" &&
39
+ !isMaterialAuthority(authorityRef))
40
+ semanticFactClosureInvalid("fact_direct_authority_required", `${fact.key}:${fact.provenance.kind}:${authorityRef}`);
41
+ if (sourceRefs.has(authorityRef) &&
42
+ !fact.source_item_refs.includes(authorityRef))
43
+ semanticFactClosureInvalid("fact_authority_source_lineage_mismatch", `${fact.key}:${authorityRef}`);
44
+ const authorityInput = inputByKey.get(authorityRef);
45
+ if (authorityInput && !authorityInput.fact_refs.includes(fact.key))
46
+ semanticFactClosureInvalid("fact_authority_input_lineage_mismatch", `${fact.key}:${authorityRef}`);
47
+ if (fact.provenance.kind === "explicitly_delegated" &&
48
+ authorityInput &&
49
+ authorityInput.kind !== "delegated_instruction" &&
50
+ authorityInput.kind !== "source_item")
51
+ semanticFactClosureInvalid("delegated_fact_authority_kind_mismatch", `${fact.key}:${authorityInput.kind}`);
52
+ if (fact.provenance.kind === "evidence_backed_preservation" &&
53
+ authorityInput &&
54
+ !["repository_preservation", "context", "source_item"].includes(authorityInput.kind))
55
+ semanticFactClosureInvalid("preservation_fact_authority_kind_mismatch", `${fact.key}:${authorityInput.kind}`);
56
+ }
57
+ export function validateSemanticFactBasisClosure(manifest, sourceItems) {
58
+ const known = semanticFactKnownBasisRefs(manifest, sourceItems);
59
+ const rows = [];
60
+ const collect = (label, values) => rows.push(...values.map((item) => ({
61
+ label: `${label}:${item.key}`,
62
+ refs: item.basis_refs,
63
+ })));
64
+ collect("scope_exclusion", manifest.scope.exclusions);
65
+ collect("input", manifest.inputs);
66
+ collect("census", manifest.inspector.census);
67
+ collect("family", manifest.family_dispositions);
68
+ collect("subject", manifest.subjects);
69
+ collect("relation", manifest.relations);
70
+ collect("population", manifest.populations);
71
+ collect("axis", manifest.axis_dispositions);
72
+ collect("axis_value", manifest.axis_dispositions.flatMap((item) => item.values));
73
+ collect("condition_rule", manifest.condition_rules);
74
+ collect("condition", manifest.conditions);
75
+ collect("condition_exclusion", manifest.condition_exclusions);
76
+ collect("property", manifest.property_dispositions);
77
+ collect("fact_cell", manifest.fact_cells);
78
+ addSpecialBasisRows(manifest, rows);
79
+ for (const row of rows)
80
+ for (const ref of row.refs)
81
+ if (!known.has(ref))
82
+ semanticFactClosureInvalid("basis_ref_unknown", `${row.label}:${ref}`);
83
+ }
84
+ function semanticFactKnownBasisRefs(manifest, sourceItems) {
85
+ return new Set([
86
+ manifest.key,
87
+ ...sourceItems.map((item) => item.key),
88
+ ...manifest.scope.exclusions.map((item) => item.key),
89
+ ...manifest.inputs.map((item) => item.key),
90
+ ...manifest.inspector.census.map((item) => item.key),
91
+ ...manifest.family_dispositions.map((item) => item.key),
92
+ ...manifest.subjects.map((item) => item.key),
93
+ ...manifest.relations.map((item) => item.key),
94
+ ...manifest.populations.map((item) => item.key),
95
+ ...manifest.axis_dispositions.map((item) => item.key),
96
+ ...manifest.axis_dispositions.flatMap((item) => item.values.map((value) => value.key)),
97
+ ...manifest.condition_rules.map((item) => item.key),
98
+ ...manifest.conditions.map((item) => item.key),
99
+ ...manifest.condition_exclusions.map((item) => item.key),
100
+ ...manifest.property_dispositions.map((item) => item.key),
101
+ ...manifest.fact_cells.map((item) => item.key),
102
+ ...manifest.facts.map((item) => item.key),
103
+ ...manifest.proof_obligations.map((item) => item.key),
104
+ ...manifest.oracles.map((item) => item.key),
105
+ ...manifest.environments.map((item) => item.key),
106
+ ...manifest.blockers.map((item) => item.key),
107
+ ]);
108
+ }
109
+ function addSpecialBasisRows(manifest, rows) {
110
+ for (const fact of manifest.facts)
111
+ rows.push({
112
+ label: `fact_provenance:${fact.key}`,
113
+ refs: fact.provenance.basis_refs,
114
+ });
115
+ for (const proof of manifest.proof_obligations)
116
+ rows.push({
117
+ label: `proof_counterfactual:${proof.key}`,
118
+ refs: proof.counterfactual.basis_refs,
119
+ });
120
+ for (const exclusion of manifest.scope.exclusions)
121
+ rows.push({
122
+ label: `scope_exclusion_affected:${exclusion.key}`,
123
+ refs: exclusion.affected_refs,
124
+ });
125
+ for (const population of manifest.populations)
126
+ rows.push({
127
+ label: `population_exclusions:${population.key}`,
128
+ refs: population.exclusion_refs,
129
+ });
130
+ for (const blocker of manifest.blockers)
131
+ rows.push({
132
+ label: `blocker_affected:${blocker.key}`,
133
+ refs: blocker.affected_refs,
134
+ });
135
+ for (const fact of manifest.facts)
136
+ rows.push({
137
+ label: `fact_authority:${fact.key}`,
138
+ refs: [fact.provenance.authority_ref],
139
+ });
140
+ }
@@ -0,0 +1,3 @@
1
+ import type { SemanticFactManifestRefV2, SemanticFactOutcomeBindingsV2 } from "./semantic-fact-types.js";
2
+ export declare function parseSemanticFactManifestRef(value: unknown, label: string): SemanticFactManifestRefV2;
3
+ export declare function parseSemanticFactOutcomeBindings(value: unknown, label: string): SemanticFactOutcomeBindingsV2;
@@ -0,0 +1,89 @@
1
+ import { array, EVIDENCE_CAPABILITIES, fail, literal, object, PROOF_SURFACES, repositoryFile, string, } from "./long-task-delivery-shape.js";
2
+ export function parseSemanticFactManifestRef(value, label) {
3
+ const row = object(value, label, ["key", "source_path", "sha256"]);
4
+ return {
5
+ key: semanticRef(row.key, `${label}.key`),
6
+ source_path: repositoryFile(row.source_path, `${label}.source_path`),
7
+ sha256: sha256(row.sha256, `${label}.sha256`),
8
+ };
9
+ }
10
+ export function parseSemanticFactOutcomeBindings(value, label) {
11
+ const row = object(value, label, ["manifest_ref", "facts", "proofs"]);
12
+ return {
13
+ manifest_ref: semanticRef(row.manifest_ref, `${label}.manifest_ref`),
14
+ facts: array(row.facts, `${label}.facts`).map((item, index) => {
15
+ const itemLabel = `${label}.facts[${index}]`;
16
+ const entry = object(item, itemLabel, [
17
+ "fact_ref",
18
+ "claim_ref",
19
+ "applicability_ref",
20
+ ]);
21
+ return {
22
+ fact_ref: semanticRef(entry.fact_ref, `${itemLabel}.fact_ref`),
23
+ claim_ref: semanticRef(entry.claim_ref, `${itemLabel}.claim_ref`),
24
+ applicability_ref: semanticRef(entry.applicability_ref, `${itemLabel}.applicability_ref`),
25
+ };
26
+ }),
27
+ proofs: array(row.proofs, `${label}.proofs`).map((item, index) => {
28
+ const itemLabel = `${label}.proofs[${index}]`;
29
+ const preliminary = object(item, itemLabel, [
30
+ "proof_ref",
31
+ "fact_ref",
32
+ "method",
33
+ "proof_surface",
34
+ "evidence_capabilities",
35
+ "authority",
36
+ ], ["check_ref", "assertion_ref", "confirmation_ref"]);
37
+ const authority = literal(preliminary.authority, ["machine", "external_confirmation"], `${itemLabel}.authority`);
38
+ if (authority === "machine") {
39
+ requireOwned(preliminary, itemLabel, ["check_ref", "assertion_ref"]);
40
+ forbidOwned(preliminary, itemLabel, ["confirmation_ref"]);
41
+ }
42
+ else {
43
+ requireOwned(preliminary, itemLabel, ["confirmation_ref"]);
44
+ forbidOwned(preliminary, itemLabel, ["check_ref", "assertion_ref"]);
45
+ }
46
+ const base = {
47
+ proof_ref: semanticRef(preliminary.proof_ref, `${itemLabel}.proof_ref`),
48
+ fact_ref: semanticRef(preliminary.fact_ref, `${itemLabel}.fact_ref`),
49
+ method: semanticRef(preliminary.method, `${itemLabel}.method`),
50
+ proof_surface: literal(preliminary.proof_surface, PROOF_SURFACES, `${itemLabel}.proof_surface`),
51
+ evidence_capabilities: array(preliminary.evidence_capabilities, `${itemLabel}.evidence_capabilities`).map((capability, capabilityIndex) => literal(capability, EVIDENCE_CAPABILITIES, `${itemLabel}.evidence_capabilities[${capabilityIndex}]`)),
52
+ };
53
+ return authority === "machine"
54
+ ? {
55
+ ...base,
56
+ authority,
57
+ check_ref: semanticRef(preliminary.check_ref, `${itemLabel}.check_ref`),
58
+ assertion_ref: semanticRef(preliminary.assertion_ref, `${itemLabel}.assertion_ref`),
59
+ }
60
+ : {
61
+ ...base,
62
+ authority,
63
+ confirmation_ref: semanticRef(preliminary.confirmation_ref, `${itemLabel}.confirmation_ref`),
64
+ };
65
+ }),
66
+ };
67
+ }
68
+ function semanticRef(value, label) {
69
+ const result = string(value, label);
70
+ if (!/^[a-z0-9][a-z0-9._:-]*$/u.test(result))
71
+ fail(label, "must be a stable lowercase semantic reference");
72
+ return result;
73
+ }
74
+ function sha256(value, label) {
75
+ const result = string(value, label);
76
+ if (!/^[a-f0-9]{64}$/u.test(result))
77
+ fail(label, "must be a lowercase SHA-256 digest");
78
+ return result;
79
+ }
80
+ function requireOwned(row, label, fields) {
81
+ const missing = fields.filter((field) => !Object.hasOwn(row, field));
82
+ if (missing.length)
83
+ fail(label, `missing keys: ${missing.join(",")}`);
84
+ }
85
+ function forbidOwned(row, label, fields) {
86
+ const present = fields.filter((field) => Object.hasOwn(row, field));
87
+ if (present.length)
88
+ fail(label, `forbidden keys: ${present.join(",")}`);
89
+ }
@@ -0,0 +1,3 @@
1
+ import type { CompiledSourceItemV2 } from "./long-task-source-authority-types.js";
2
+ import type { SemanticFactManifestV1 } from "./semantic-fact-types.js";
3
+ export declare function validateSemanticFactLocatedValues(repository: string, manifest: SemanticFactManifestV1, sourceItems: CompiledSourceItemV2[]): Promise<void>;
@@ -0,0 +1,110 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { resolveSemanticFactPointer, semanticFactClosureInvalid, } from "./long-task-semantic-fact-closure-primitives.js";
4
+ import { assertProtectedRepositoryFile } from "./long-task-protected-files.js";
5
+ import { canonicalValueJson, parseStrictYaml, sha256Hex, } from "./strict-codec.js";
6
+ export async function validateSemanticFactLocatedValues(repository, manifest, sourceItems) {
7
+ const values = collectLocatedValues(manifest);
8
+ const inputs = new Map(manifest.inputs.map((item) => [item.key, item]));
9
+ const sourceItemByKey = new Map(sourceItems.map((item) => [item.key, item]));
10
+ const resourceCache = new Map();
11
+ for (const entry of values) {
12
+ const located = entry.value;
13
+ if (located.representation === "digest_only")
14
+ continue;
15
+ const resolved = await resolveLocatedValue(repository, manifest, entry.label, located, inputs, sourceItemByKey, resourceCache);
16
+ if (resolved.external)
17
+ continue;
18
+ if (located.representation === "inline" &&
19
+ canonicalValueJson(resolved.value) !== canonicalValueJson(located.value))
20
+ semanticFactClosureInvalid("inline_value_locator_mismatch", entry.label);
21
+ const digest = sha256Hex(canonicalValueJson(resolved.value));
22
+ if (digest !== located.sha256)
23
+ semanticFactClosureInvalid("located_value_digest_mismatch", `${entry.label}:${located.sha256}:${digest}`);
24
+ }
25
+ }
26
+ function collectLocatedValues(manifest) {
27
+ return [
28
+ ...manifest.populations.map((item) => ({
29
+ label: `population:${item.key}:universe`,
30
+ value: item.universe,
31
+ })),
32
+ ...manifest.facts.map((item) => ({
33
+ label: `fact:${item.key}:expected`,
34
+ value: item.expected,
35
+ })),
36
+ ...manifest.proof_obligations.flatMap((item) => [
37
+ {
38
+ label: `proof:${item.key}:parameters`,
39
+ value: item.comparison.parameters,
40
+ },
41
+ ...(item.comparison.tolerance
42
+ ? [
43
+ {
44
+ label: `proof:${item.key}:tolerance`,
45
+ value: item.comparison.tolerance,
46
+ },
47
+ ]
48
+ : []),
49
+ ...(item.comparison.mask
50
+ ? [
51
+ {
52
+ label: `proof:${item.key}:mask`,
53
+ value: item.comparison.mask,
54
+ },
55
+ ]
56
+ : []),
57
+ ]),
58
+ ...manifest.environments.map((item) => ({
59
+ label: `environment:${item.key}`,
60
+ value: item.definition,
61
+ })),
62
+ ];
63
+ }
64
+ async function resolveLocatedValue(repository, manifest, label, located, inputs, sourceItemByKey, resourceCache) {
65
+ if (located.locator.kind === "manifest_pointer")
66
+ return {
67
+ external: false,
68
+ value: resolveSemanticFactPointer(manifest, located.locator.value, label),
69
+ };
70
+ const input = inputs.get(located.locator.material_ref);
71
+ if (!input)
72
+ semanticFactClosureInvalid("located_value_input_unknown", `${label}:${located.locator.material_ref}`);
73
+ if (located.locator.kind === "source_item") {
74
+ if (input.kind !== "source_item")
75
+ semanticFactClosureInvalid("located_value_source_item_kind_mismatch", label);
76
+ const sourceItem = sourceItemByKey.get(input.source_ref);
77
+ if (!sourceItem)
78
+ semanticFactClosureInvalid("located_value_source_item_unknown", label);
79
+ return { external: false, value: sourceItem.normalized_text };
80
+ }
81
+ const resource = await loadLocatedResource(repository, input.source_ref, label, located.locator.kind, resourceCache);
82
+ if (located.locator.kind === "whole_resource")
83
+ return { external: false, value: resource.raw };
84
+ if (located.locator.kind === "json_pointer" ||
85
+ located.locator.kind === "yaml_pointer" ||
86
+ located.locator.kind === "schema_pointer")
87
+ return {
88
+ external: false,
89
+ value: resolveSemanticFactPointer(resource.parsed, located.locator.value, label),
90
+ };
91
+ if (manifest.inspector.trust !== "named_external_tcb" ||
92
+ !manifest.inspector.capabilities.includes(`resolve.${located.locator.kind}`))
93
+ semanticFactClosureInvalid("located_value_external_resolver_required", `${label}:${located.locator.kind}`);
94
+ return { external: true, value: undefined };
95
+ }
96
+ async function loadLocatedResource(repository, sourceRef, label, locatorKind, cache) {
97
+ const cached = cache.get(sourceRef);
98
+ if (cached)
99
+ return cached;
100
+ const file = await assertProtectedRepositoryFile(repository, path.resolve(repository, ...sourceRef.split("/")), `semantic_fact_located_value:${label}`);
101
+ const raw = await readFile(file, "utf8");
102
+ let parsed = raw;
103
+ if (locatorKind === "json_pointer" || locatorKind === "schema_pointer")
104
+ parsed = JSON.parse(raw);
105
+ else if (locatorKind === "yaml_pointer")
106
+ parsed = parseStrictYaml(raw);
107
+ const resource = { raw, parsed };
108
+ cache.set(sourceRef, resource);
109
+ return resource;
110
+ }
@@ -13,8 +13,9 @@ export declare function repositoryCwd(value: unknown, label: string): string;
13
13
  export declare function repositorySourceRef(value: unknown, label: string): string;
14
14
  export declare function literal<T extends string>(value: unknown, allowed: readonly T[], label: string): T;
15
15
  export declare function key(value: unknown, label: string): string;
16
+ export declare function semanticRef(value: unknown, label: string): string;
16
17
  export declare function nullable<T>(value: unknown, parser: (value: unknown) => T): T | null;
17
18
  export declare const PROOF_SURFACES: readonly ["ui_browser", "runtime_behavior", "api_contract", "data_state", "security_boundary", "population_coverage", "implementation_structure"];
18
19
  export declare const JOURNEY_ROLES: readonly ["success", "degradation", "recovery", "stage_gate", "conformance"];
19
- export declare const EVIDENCE_CAPABILITIES: readonly ["presence", "interaction_trace", "state_delta", "cross_surface_consistency", "durable_readback", "boundary_invocation", "external_side_effect", "failure_injection", "visual_render", "design_conformance", "design_method", "target_runtime", "input_variation"];
20
+ export declare const EVIDENCE_CAPABILITIES: readonly ["presence", "interaction_trace", "state_delta", "cross_surface_consistency", "durable_readback", "boundary_invocation", "external_side_effect", "failure_injection", "visual_render", "design_conformance", "design_method", "semantic_fact", "target_runtime", "input_variation"];
20
21
  export declare function fail(label: string, message: string): never;