kibi-cli 2.31.1 → 2.35.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. package/dist/cli-register-proof.d.ts.map +1 -1
  2. package/dist/cli-register-proof.js +19 -7
  3. package/dist/cli-register-reporting.d.ts.map +1 -1
  4. package/dist/cli-register-reporting.js +2 -0
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +5 -1
  7. package/dist/commands/check-generated.d.ts +5 -1
  8. package/dist/commands/check-generated.d.ts.map +1 -1
  9. package/dist/commands/check-generated.js +24 -35
  10. package/dist/commands/check.d.ts +1 -0
  11. package/dist/commands/check.d.ts.map +1 -1
  12. package/dist/commands/check.js +14 -5
  13. package/dist/commands/discovery-table.d.ts.map +1 -1
  14. package/dist/commands/discovery-table.js +51 -4
  15. package/dist/commands/doctor.js +19 -4
  16. package/dist/commands/init-helpers.d.ts.map +1 -1
  17. package/dist/commands/init-helpers.js +8 -5
  18. package/dist/commands/migrate.d.ts.map +1 -1
  19. package/dist/commands/migrate.js +109 -5
  20. package/dist/commands/prove.d.ts +48 -1
  21. package/dist/commands/prove.d.ts.map +1 -1
  22. package/dist/commands/prove.js +293 -8
  23. package/dist/commands/report.d.ts +1 -0
  24. package/dist/commands/report.d.ts.map +1 -1
  25. package/dist/commands/report.js +70 -5
  26. package/dist/commands/signoff.d.ts.map +1 -1
  27. package/dist/commands/signoff.js +20 -1
  28. package/dist/commands/sync/manifest.d.ts +10 -1
  29. package/dist/commands/sync/manifest.d.ts.map +1 -1
  30. package/dist/commands/sync/manifest.js +106 -17
  31. package/dist/commands/sync/persistence.d.ts.map +1 -1
  32. package/dist/commands/sync/persistence.js +16 -5
  33. package/dist/commands/sync.d.ts.map +1 -1
  34. package/dist/commands/sync.js +19 -0
  35. package/dist/diagnostics.js +1 -1
  36. package/dist/engine.js +1 -1
  37. package/dist/extractors/markdown.d.ts +4 -2
  38. package/dist/extractors/markdown.d.ts.map +1 -1
  39. package/dist/extractors/markdown.js +17 -0
  40. package/dist/extractors/symbol-coordinates.js +2 -2
  41. package/dist/extractors/symbols-coordinator.d.ts +2 -4
  42. package/dist/extractors/symbols-coordinator.d.ts.map +1 -1
  43. package/dist/extractors/symbols-coordinator.js +1 -2
  44. package/dist/operations/bootstrap/candidate-helpers.d.ts +3 -0
  45. package/dist/operations/bootstrap/candidate-helpers.d.ts.map +1 -1
  46. package/dist/operations/bootstrap/candidate-helpers.js +4 -0
  47. package/dist/operations/migration/evidence-floor.d.ts +41 -0
  48. package/dist/operations/migration/evidence-floor.d.ts.map +1 -0
  49. package/dist/operations/migration/evidence-floor.js +230 -0
  50. package/dist/operations/migration/proof-contract-claims.d.ts +72 -0
  51. package/dist/operations/migration/proof-contract-claims.d.ts.map +1 -0
  52. package/dist/operations/migration/proof-contract-claims.js +215 -0
  53. package/dist/operations/migration/schema6.d.ts +6 -0
  54. package/dist/operations/migration/schema6.d.ts.map +1 -1
  55. package/dist/operations/migration/schema6.js +92 -0
  56. package/dist/operations/migration/symbol-coordinates-refresh.d.ts +3 -2
  57. package/dist/operations/migration/symbol-coordinates-refresh.d.ts.map +1 -1
  58. package/dist/operations/migration/symbol-coordinates-refresh.js +4 -3
  59. package/dist/operations/migration/untrack-symbol-coordinates.d.ts +23 -0
  60. package/dist/operations/migration/untrack-symbol-coordinates.d.ts.map +1 -0
  61. package/dist/operations/migration/untrack-symbol-coordinates.js +67 -0
  62. package/dist/operations/modeling/requirement-modeler.d.ts.map +1 -1
  63. package/dist/operations/modeling/requirement-modeler.js +48 -1
  64. package/dist/operations/modeling/requirement-types.d.ts +2 -1
  65. package/dist/operations/modeling/requirement-types.d.ts.map +1 -1
  66. package/dist/operations/modeling/requirement-utils.d.ts +1 -1
  67. package/dist/operations/modeling/requirement-utils.d.ts.map +1 -1
  68. package/dist/operations/modeling/requirement-utils.js +8 -1
  69. package/dist/operations/mutation/omitted-properties.d.ts +11 -0
  70. package/dist/operations/mutation/omitted-properties.d.ts.map +1 -0
  71. package/dist/operations/mutation/omitted-properties.js +76 -0
  72. package/dist/operations/mutation/serialization.d.ts.map +1 -1
  73. package/dist/operations/mutation/serialization.js +1 -0
  74. package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
  75. package/dist/operations/mutation/source-authoring.js +39 -20
  76. package/dist/operations/mutation/strict-fact.d.ts.map +1 -1
  77. package/dist/operations/mutation/strict-fact.js +6 -2
  78. package/dist/operations/mutation/symbol-granularity.d.ts.map +1 -1
  79. package/dist/operations/mutation/symbol-granularity.js +5 -3
  80. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  81. package/dist/operations/mutation/upsert.js +7 -1
  82. package/dist/operations/mutation/validation.d.ts +2 -0
  83. package/dist/operations/mutation/validation.d.ts.map +1 -1
  84. package/dist/operations/mutation/validation.js +4 -0
  85. package/dist/operations/proof/claim-bindings.d.ts +41 -0
  86. package/dist/operations/proof/claim-bindings.d.ts.map +1 -0
  87. package/dist/operations/proof/claim-bindings.js +364 -0
  88. package/dist/operations/proof/code-certificates.d.ts +155 -0
  89. package/dist/operations/proof/code-certificates.d.ts.map +1 -0
  90. package/dist/operations/proof/code-certificates.js +894 -0
  91. package/dist/operations/proof/code-models.d.ts +96 -0
  92. package/dist/operations/proof/code-models.d.ts.map +1 -0
  93. package/dist/operations/proof/code-models.js +601 -0
  94. package/dist/operations/proof/code-runner.d.ts +40 -0
  95. package/dist/operations/proof/code-runner.d.ts.map +1 -0
  96. package/dist/operations/proof/code-runner.js +164 -0
  97. package/dist/operations/proof/code-scope.d.ts +14 -1
  98. package/dist/operations/proof/code-scope.d.ts.map +1 -1
  99. package/dist/operations/proof/code-scope.js +44 -2
  100. package/dist/operations/proof/compact-receipts.d.ts.map +1 -1
  101. package/dist/operations/proof/compact-receipts.js +4 -3
  102. package/dist/operations/proof/explain.d.ts +32 -0
  103. package/dist/operations/proof/explain.d.ts.map +1 -1
  104. package/dist/operations/proof/explain.js +91 -0
  105. package/dist/operations/proof/ingest-proof.d.ts +9 -1
  106. package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
  107. package/dist/operations/proof/ingest-proof.js +42 -2
  108. package/dist/operations/proof/receipt-compaction.d.ts +2 -0
  109. package/dist/operations/proof/receipt-compaction.d.ts.map +1 -1
  110. package/dist/operations/proof/receipt-compaction.js +6 -2
  111. package/dist/operations/proof/regular-language.d.ts +89 -0
  112. package/dist/operations/proof/regular-language.d.ts.map +1 -0
  113. package/dist/operations/proof/regular-language.js +943 -0
  114. package/dist/operations/proof/source-code-readers.d.ts +12 -0
  115. package/dist/operations/proof/source-code-readers.d.ts.map +1 -0
  116. package/dist/operations/proof/source-code-readers.js +699 -0
  117. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  118. package/dist/operations/semantic-advisor/analyze-prose.js +2 -1
  119. package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
  120. package/dist/operations/semantic-advisor/shared.js +4 -0
  121. package/dist/operations/semantic-advisor/strict-count-rules.d.ts.map +1 -1
  122. package/dist/operations/semantic-advisor/strict-count-rules.js +8 -2
  123. package/dist/operations/semantic-advisor/strict-rules.d.ts +8 -0
  124. package/dist/operations/semantic-advisor/strict-rules.d.ts.map +1 -1
  125. package/dist/operations/semantic-advisor/strict-rules.js +234 -4
  126. package/dist/operations/semantic-advisor/types.d.ts +3 -2
  127. package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
  128. package/dist/plugins/approved-source-analyzers.generated.d.ts +6 -6
  129. package/dist/plugins/approved-source-analyzers.generated.js +6 -6
  130. package/dist/prolog.d.ts.map +1 -1
  131. package/dist/prolog.js +13 -3
  132. package/dist/proof/command-test-report.d.ts +4 -3
  133. package/dist/proof/command-test-report.d.ts.map +1 -1
  134. package/dist/proof/command-test-report.js +4 -10
  135. package/dist/proof/evaluate.d.ts.map +1 -1
  136. package/dist/proof/evaluate.js +18 -2
  137. package/dist/proof/inspect.d.ts.map +1 -1
  138. package/dist/proof/inspect.js +58 -0
  139. package/dist/proof/producers/playwright-reporter.d.ts +3 -0
  140. package/dist/proof/producers/playwright-reporter.d.ts.map +1 -1
  141. package/dist/proof/producers/playwright-reporter.js +25 -2
  142. package/dist/proof/step-runner.d.ts +36 -0
  143. package/dist/proof/step-runner.d.ts.map +1 -0
  144. package/dist/proof/step-runner.js +234 -0
  145. package/dist/public/evidence-levels.d.ts +12 -0
  146. package/dist/public/evidence-levels.d.ts.map +1 -0
  147. package/dist/public/evidence-levels.js +19 -0
  148. package/dist/public/impact/coverage-depth-quality.d.ts +7 -0
  149. package/dist/public/impact/coverage-depth-quality.d.ts.map +1 -1
  150. package/dist/public/impact/coverage-depth-quality.js +59 -0
  151. package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
  152. package/dist/public/impact/full-kb-quality.js +3 -1
  153. package/dist/public/operations/catalog.d.ts +315 -11
  154. package/dist/public/operations/catalog.d.ts.map +1 -1
  155. package/dist/public/operations/check-executor.d.ts +2 -0
  156. package/dist/public/operations/check-executor.d.ts.map +1 -1
  157. package/dist/public/operations/check-executor.js +6 -0
  158. package/dist/public/operations/evidence-floor.d.ts +48 -0
  159. package/dist/public/operations/evidence-floor.d.ts.map +1 -0
  160. package/dist/public/operations/evidence-floor.js +143 -0
  161. package/dist/public/operations/migration-plan.d.ts +19 -5
  162. package/dist/public/operations/migration-plan.d.ts.map +1 -1
  163. package/dist/public/operations/migration-plan.js +22 -5
  164. package/dist/public/operations/node-ports.d.ts.map +1 -1
  165. package/dist/public/operations/node-ports.js +4 -1
  166. package/dist/public/operations/proof-contract-claims.d.ts +26 -0
  167. package/dist/public/operations/proof-contract-claims.d.ts.map +1 -0
  168. package/dist/public/operations/proof-contract-claims.js +71 -0
  169. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  170. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  171. package/dist/public/operations/specs/check-rules.generated.js +3 -1
  172. package/dist/public/operations/specs/check.d.ts +1 -1
  173. package/dist/public/operations/specs/composite.d.ts +16 -3
  174. package/dist/public/operations/specs/composite.d.ts.map +1 -1
  175. package/dist/public/operations/specs/modeling.d.ts +16 -3
  176. package/dist/public/operations/specs/modeling.d.ts.map +1 -1
  177. package/dist/public/operations/specs/modeling.js +22 -3
  178. package/dist/public/operations/specs/mutation-schemas.d.ts +289 -7
  179. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  180. package/dist/public/operations/specs/mutation-schemas.js +28 -4
  181. package/dist/public/operations/specs/proof.d.ts +9 -0
  182. package/dist/public/operations/specs/proof.d.ts.map +1 -1
  183. package/dist/public/operations/specs/reporting.d.ts.map +1 -1
  184. package/dist/public/operations/specs/reporting.js +19 -10
  185. package/dist/public/operations/specs/upsert.d.ts +289 -7
  186. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  187. package/dist/public/proof-certificates.d.ts +163 -0
  188. package/dist/public/proof-certificates.d.ts.map +1 -0
  189. package/dist/public/proof-certificates.js +419 -0
  190. package/dist/public/proof-protocol.d.ts +259 -3
  191. package/dist/public/proof-protocol.d.ts.map +1 -1
  192. package/dist/public/proof-protocol.js +524 -3
  193. package/dist/public/proof-receipt.d.ts +90 -6
  194. package/dist/public/proof-receipt.d.ts.map +1 -1
  195. package/dist/public/proof-receipt.js +88 -7
  196. package/dist/public/proof-sources.d.ts +102 -0
  197. package/dist/public/proof-sources.d.ts.map +1 -0
  198. package/dist/public/proof-sources.js +1292 -0
  199. package/dist/public/schemas/entity.d.ts.map +1 -1
  200. package/dist/public/schemas/entity.js +39 -2
  201. package/dist/public/skills/kibi-bootstrap/SKILL.md +2 -2
  202. package/dist/public/skills/kibi-commit-review/SKILL.md +8 -8
  203. package/dist/public/skills/kibi-commit-review/resources/staged-gate.md +12 -7
  204. package/dist/public/skills/kibi-decisions/SKILL.md +13 -2
  205. package/dist/public/skills/kibi-decisions/resources/decision-records.md +9 -1
  206. package/dist/public/skills/kibi-freshness/SKILL.md +5 -1
  207. package/dist/public/skills/kibi-traceability/SKILL.md +12 -1
  208. package/dist/public/skills/kibi-usage/SKILL.md +8 -4
  209. package/dist/public/skills/kibi-usage/resources/proof.md +221 -20
  210. package/dist/public/skills/kibi-usage/resources/workflows.md +4 -4
  211. package/dist/report/html-report.css +83 -11
  212. package/dist/report/html-report.d.ts +8 -0
  213. package/dist/report/html-report.d.ts.map +1 -1
  214. package/dist/report/html-report.js +214 -22
  215. package/dist/report/report-view.d.ts +2 -2
  216. package/dist/report/report-view.d.ts.map +1 -1
  217. package/dist/report/report-view.js +8 -0
  218. package/dist/schemas/entity.schema.json +404 -5
  219. package/dist/search-answer.d.ts.map +1 -1
  220. package/dist/search-answer.js +1 -0
  221. package/dist/signoff/html.d.ts.map +1 -1
  222. package/dist/signoff/html.js +3 -0
  223. package/dist/signoff/markdown.d.ts.map +1 -1
  224. package/dist/signoff/markdown.js +3 -0
  225. package/dist/signoff/model.d.ts +20 -0
  226. package/dist/signoff/model.d.ts.map +1 -1
  227. package/dist/signoff/model.js +20 -1
  228. package/dist/traceability/evidence-model.d.ts +13 -12
  229. package/dist/traceability/evidence-model.d.ts.map +1 -1
  230. package/dist/traceability/evidence-model.js +1 -1
  231. package/dist/traceability/impact-knowledge.d.ts.map +1 -1
  232. package/dist/traceability/impact-knowledge.js +1 -0
  233. package/dist/traceability/staged-diagnostics.d.ts.map +1 -1
  234. package/dist/traceability/staged-diagnostics.js +24 -20
  235. package/dist/traceability/staged-impact-contract.d.ts +4 -4
  236. package/dist/traceability/staged-impact-contract.js +9 -9
  237. package/dist/traceability/staged-symbols-manifest.d.ts +11 -3
  238. package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -1
  239. package/dist/traceability/staged-symbols-manifest.js +47 -140
  240. package/dist/traceability/temp-kb.d.ts.map +1 -1
  241. package/dist/traceability/temp-kb.js +1 -0
  242. package/dist/types/entities.d.ts +5 -2
  243. package/dist/types/entities.d.ts.map +1 -1
  244. package/dist/utils/merge-driver-setup.d.ts +8 -1
  245. package/dist/utils/merge-driver-setup.d.ts.map +1 -1
  246. package/dist/utils/merge-driver-setup.js +23 -2
  247. package/dist/utils/rule-registry.generated.d.ts +10 -0
  248. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  249. package/dist/utils/rule-registry.generated.js +12 -0
  250. package/dist/utils/schema-version.d.ts +1 -1
  251. package/dist/utils/schema-version.d.ts.map +1 -1
  252. package/dist/utils/schema-version.js +7 -1
  253. package/dist/utils/strict-modeling.d.ts +3 -2
  254. package/dist/utils/strict-modeling.d.ts.map +1 -1
  255. package/dist/utils/strict-modeling.js +37 -4
  256. package/dist/workspace-cwd.d.ts +15 -0
  257. package/dist/workspace-cwd.d.ts.map +1 -0
  258. package/dist/workspace-cwd.js +86 -0
  259. package/package.json +6 -2
  260. package/schema/entities.pl +6 -0
  261. package/schema/validation.pl +7 -2
  262. package/src/public/evidence-levels.ts +23 -0
  263. package/src/public/impact/coverage-depth-quality.ts +73 -0
  264. package/src/public/impact/full-kb-quality.ts +6 -1
  265. package/src/public/operations/check-executor.ts +13 -0
  266. package/src/public/operations/evidence-floor.ts +203 -0
  267. package/src/public/operations/migration-plan.ts +39 -6
  268. package/src/public/operations/node-ports.ts +3 -1
  269. package/src/public/operations/proof-contract-claims.ts +103 -0
  270. package/src/public/operations/specs/check-rules.generated.ts +3 -1
  271. package/src/public/operations/specs/modeling.ts +24 -5
  272. package/src/public/operations/specs/mutation-schemas.ts +30 -4
  273. package/src/public/operations/specs/reporting.ts +20 -10
  274. package/src/public/proof-certificates.ts +566 -0
  275. package/src/public/proof-protocol-types.d.ts +69 -1
  276. package/src/public/proof-protocol.ts +694 -3
  277. package/src/public/proof-receipt.ts +133 -7
  278. package/src/public/proof-sources.ts +1656 -0
  279. package/src/public/schemas/entity.ts +51 -3
  280. package/src/public/skills/kibi-bootstrap/SKILL.md +2 -2
  281. package/src/public/skills/kibi-commit-review/SKILL.md +8 -8
  282. package/src/public/skills/kibi-commit-review/resources/staged-gate.md +12 -7
  283. package/src/public/skills/kibi-decisions/SKILL.md +13 -2
  284. package/src/public/skills/kibi-decisions/resources/decision-records.md +9 -1
  285. package/src/public/skills/kibi-freshness/SKILL.md +5 -1
  286. package/src/public/skills/kibi-traceability/SKILL.md +12 -1
  287. package/src/public/skills/kibi-usage/SKILL.md +8 -4
  288. package/src/public/skills/kibi-usage/resources/proof.md +221 -20
  289. package/src/public/skills/kibi-usage/resources/workflows.md +4 -4
  290. package/src/schemas/entity.schema.json +404 -5
  291. package/dist/commands/proof-impact.d.ts +0 -7
  292. package/dist/commands/proof-impact.d.ts.map +0 -1
  293. package/dist/commands/proof-impact.js +0 -39
  294. package/dist/operations/proof/baseline-diff.d.ts +0 -41
  295. package/dist/operations/proof/baseline-diff.d.ts.map +0 -1
  296. package/dist/operations/proof/baseline-diff.js +0 -153
  297. package/dist/operations/proof/impact.d.ts +0 -51
  298. package/dist/operations/proof/impact.d.ts.map +0 -1
  299. package/dist/operations/proof/impact.js +0 -138
  300. package/dist/traceability/reviewed-coordinate-refresh.d.ts +0 -10
  301. package/dist/traceability/reviewed-coordinate-refresh.d.ts.map +0 -1
  302. package/dist/traceability/reviewed-coordinate-refresh.js +0 -49
@@ -2,8 +2,23 @@
2
2
  export const PROOF_RUN_VERSION = "kibi.proof-run.v1" as const;
3
3
  // implements REQ-kibi-verification-evidence-contract
4
4
  export const PROOF_CONTRACT_VERSION = "kibi.proof-contract.v1" as const;
5
- // implements REQ-kibi-verification-evidence-contract
6
- export const PROOF_RECEIPT_VERSION = "kibi.proof-receipt.v1" as const;
5
+ /**
6
+ * Receipts Kibi writes. v2 adds the contract's kind, the evidence level the
7
+ * receipt supports, and for certificate kinds the re-checked certificate.
8
+ */
9
+ // implements REQ-kibi-verification-evidence-contract, REQ-kibi-code-proof-kinds
10
+ export const PROOF_RECEIPT_VERSION = "kibi.proof-receipt.v2" as const;
11
+ /** Receipts written before v2; still read, as e2e evidence at tested. */
12
+ // implements REQ-kibi-code-proof-kinds
13
+ export const PROOF_RECEIPT_V1_VERSION = "kibi.proof-receipt.v1" as const;
14
+ // implements REQ-kibi-code-proof-kinds
15
+ export const PROOF_RECEIPT_VERSIONS = [
16
+ PROOF_RECEIPT_V1_VERSION,
17
+ PROOF_RECEIPT_VERSION,
18
+ ] as const;
19
+ /** The certificate a certificate-kind proof leaves for Kibi to re-check. */
20
+ // implements REQ-kibi-code-proof-kinds
21
+ export const CODE_CERTIFICATE_VERSION = "kibi.code-certificate.v1" as const;
7
22
  // implements REQ-kibi-verification-evidence-contract
8
23
  export const PROOF_INTEGRATION_VERSION = "kibi.proof-integration.v1" as const;
9
24
 
@@ -38,7 +53,63 @@ export const RUN_FAILURE_PHASES = [
38
53
  "infrastructure",
39
54
  ] as const;
40
55
 
41
- export const SUCCESS_POLICIES = ["all_required_first_attempt"] as const;
56
+ /**
57
+ * `all_required_first_attempt`: the whole run must pass and every obligation's
58
+ * own result must pass on its first attempt.
59
+ * `own_results_first_attempt`: a run whose only failures are other test cases
60
+ * (outcome `failed` in the execution phase) still proves an obligation whose
61
+ * own native-case result passed on its first attempt, so one unrelated
62
+ * failing case does not erase a suite's evidence. Aggregate-run obligations
63
+ * still need the whole run to pass.
64
+ */
65
+ export const SUCCESS_POLICIES = [
66
+ "all_required_first_attempt",
67
+ "own_results_first_attempt",
68
+ ] as const;
69
+
70
+ /**
71
+ * What a proof contract's checker establishes. Runner kinds (e2e, example,
72
+ * property) sample cases and support tested evidence; certificate kinds
73
+ * (exhaustive, typecheck, arithmetic, smt, rule, state_machine, regex,
74
+ * source) cover every case and support proved evidence once Kibi re-checks
75
+ * the certificate the run left. A source certificate is Kibi's own read of a
76
+ * project source (a JSON or YAML file, a glob, an OpenAPI document, the
77
+ * references the code makes, a data schema, a route table, a validator).
78
+ */
79
+ // implements REQ-kibi-code-proof-kinds
80
+ export const PROOF_KINDS = [
81
+ "e2e",
82
+ "example",
83
+ "property",
84
+ "exhaustive",
85
+ "typecheck",
86
+ "arithmetic",
87
+ "smt",
88
+ "rule",
89
+ "state_machine",
90
+ "regex",
91
+ "source",
92
+ ] as const;
93
+
94
+ // implements REQ-kibi-code-proof-kinds, REQ-kibi-non-numeric-proof-kinds, REQ-kibi-source-proof-kinds
95
+ export const CERTIFICATE_PROOF_KINDS = [
96
+ "exhaustive",
97
+ "typecheck",
98
+ "arithmetic",
99
+ "smt",
100
+ "rule",
101
+ "state_machine",
102
+ "regex",
103
+ "source",
104
+ ] as const;
105
+
106
+ // implements REQ-kibi-code-proof-kinds
107
+ export type ProofKind = (typeof PROOF_KINDS)[number];
108
+
109
+ // implements REQ-kibi-code-proof-kinds
110
+ export function isCertificateProofKind(kind: unknown): boolean {
111
+ return (CERTIFICATE_PROOF_KINDS as readonly unknown[]).includes(kind);
112
+ }
42
113
 
43
114
  export type {
44
115
  AttemptsStatus,
@@ -67,6 +138,12 @@ import type {
67
138
  ProofResult,
68
139
  ProofRunArtifact,
69
140
  } from "./proof-protocol-types.js";
141
+ import {
142
+ SOURCE_READERS,
143
+ type SourceSpec,
144
+ normalizeSourceSpec,
145
+ sourceSpecErrors,
146
+ } from "./proof-sources.js";
70
147
 
71
148
  export const PROOF_RESULT_SCHEMA = {
72
149
  type: "object",
@@ -191,6 +268,64 @@ export const PROOF_RUN_ARTIFACT_SCHEMA = {
191
268
  type: "array",
192
269
  items: { type: "string", minLength: 1 },
193
270
  },
271
+ certificates: {
272
+ type: "array",
273
+ description:
274
+ "kibi.code-certificate.v1 objects the run left for certificate-kind contracts, one per test. Kibi re-checks each before a receipt counts as proved.",
275
+ maxItems: 1000,
276
+ items: { type: "object", required: ["version", "kind", "test_id"] },
277
+ },
278
+ },
279
+ additionalProperties: false,
280
+ } as const;
281
+
282
+ const SOURCE_REFERENCE_SCHEMA = {
283
+ type: "object",
284
+ required: ["symbol_id"],
285
+ properties: {
286
+ symbol_id: { type: "string", minLength: 1 },
287
+ export: { type: "string", minLength: 1 },
288
+ },
289
+ additionalProperties: false,
290
+ } as const;
291
+
292
+ // implements REQ-kibi-source-proof-kinds
293
+ const SOURCE_SPEC_SCHEMA = {
294
+ type: "object",
295
+ description:
296
+ "A project source Kibi reads by itself. reader json or yaml: {file, path?, select?: keys|values|items}. glob: {pattern, capture?, ignore?} (capture true reads what each * matched). openapi: {file, select?: operations|unsecured_operations|security_schemes|responses}. references: {files, extract: env|imports|calls|string_args|thrown|property, callee?, key?, ignore?}. schema: {format: drizzle|prisma|sql, file (drizzle, prisma) or files (sql migrations), exports?, table?, select?: tables|columns|required_columns|nullable_columns|foreign_keys}. routes: {file, export, framework?: hono|express, path_prefix?, names_from?, select?: routes|middleware}. validator: {file, export, select?: fields|required_fields|optional_fields}. Paths are repository-relative. A member Kibi cannot read statically fails the read with its location.",
297
+ required: ["reader"],
298
+ properties: {
299
+ reader: { type: "string", enum: [...SOURCE_READERS] },
300
+ },
301
+ additionalProperties: true,
302
+ } as const;
303
+
304
+ const SOURCE_DOMAIN_SCHEMA = {
305
+ type: "object",
306
+ required: ["source"],
307
+ properties: { source: SOURCE_SPEC_SCHEMA },
308
+ additionalProperties: false,
309
+ } as const;
310
+
311
+ const PREDICATE_SOURCE_SCHEMA = {
312
+ type: "object",
313
+ required: ["symbol_id"],
314
+ properties: {
315
+ symbol_id: { type: "string", minLength: 1 },
316
+ export: {
317
+ type: "string",
318
+ minLength: 1,
319
+ description:
320
+ "The exported function's name in the symbol's source file. Without it Kibi reads the export named by the symbol's title.",
321
+ },
322
+ harness_for: {
323
+ type: "array",
324
+ minItems: 1,
325
+ items: { type: "string", minLength: 1 },
326
+ description:
327
+ "The predicate is a test harness that decides the predicate by driving these code symbols (for example by calling the handler with each role). The symbols must be covered_by the test; a claim the harness proves is bound with scope harness.",
328
+ },
194
329
  },
195
330
  additionalProperties: false,
196
331
  } as const;
@@ -218,6 +353,109 @@ export const PROOF_CONTRACT_SCHEMA = {
218
353
  },
219
354
  },
220
355
  success_policy: { type: "string", enum: [...SUCCESS_POLICIES] },
356
+ kind: {
357
+ type: "string",
358
+ enum: [...PROOF_KINDS],
359
+ description:
360
+ "What the checker establishes; absent means e2e. exhaustive, typecheck, arithmetic, smt, rule, state_machine and regex must leave a kibi.code-certificate.v1 that Kibi re-checks before the receipt counts as proved. source reads the contract's source itself: the run may leave {version, kind: source, test_id, source} or nothing, and Kibi stores its own read as the certificate.",
361
+ },
362
+ source: {
363
+ ...SOURCE_SPEC_SCHEMA,
364
+ description: `source: the project source a source proof reads. ${SOURCE_SPEC_SCHEMA.description}`,
365
+ },
366
+ domain_source: {
367
+ type: "object",
368
+ description:
369
+ "exhaustive and typecheck: the symbol that defines the finite domain (typecheck: also the type whose fields a required_fields fact names). state_machine: the transition table or next-state function. The proof must import it from its source file; a hand-listed domain downgrades the receipt to example. Kibi reads the export named `export`, or the symbol's title when `export` is absent.",
370
+ required: ["symbol_id"],
371
+ properties: {
372
+ symbol_id: { type: "string", minLength: 1 },
373
+ export: {
374
+ type: "string",
375
+ minLength: 1,
376
+ description:
377
+ "The name the domain is exported under in the symbol's source file, when the symbol's title is not that name.",
378
+ },
379
+ },
380
+ additionalProperties: false,
381
+ },
382
+ witness: {
383
+ type: "object",
384
+ description:
385
+ "typecheck: the repository-relative witness file Kibi compiles (an exhaustive switch ending in never, or a mapped type over the domain).",
386
+ required: ["path"],
387
+ properties: { path: { type: "string", minLength: 1 } },
388
+ additionalProperties: false,
389
+ },
390
+ proves: {
391
+ type: "array",
392
+ description:
393
+ "Certificate kinds: the requirement claim keys (CLAIM-...) this certificate proves. Each must be a modeled claim of a current requirement the test reaches through its scenarios. Kibi derives what the certificate must establish from the claim's grounding fact (a set fact for exhaustive or typecheck, a numeric fact for arithmetic or smt, a rule, predicate or set fact for rule and state_machine, a string fact for regex); a claim with no such derivation is only attested and never counts as proved.",
394
+ minItems: 1,
395
+ items: { type: "string", pattern: "^CLAIM-" },
396
+ uniqueItems: true,
397
+ },
398
+ value_source: {
399
+ type: "array",
400
+ description:
401
+ "arithmetic and smt: code constants the assumptions read. Kibi evaluates each export at ingest and requires the certificate to assume the variable equals that value, so the proof is about the code and not only the knowledge base. With measure count the value is the size of a list, set, map or object export, so a count claim reads the collection itself. An entry {source, measure: count} counts the members Kibi reads from a project source (routes, tables, environment variables).",
402
+ minItems: 1,
403
+ items: {
404
+ type: "object",
405
+ properties: {
406
+ symbol_id: { type: "string", minLength: 1 },
407
+ export: { type: "string", minLength: 1 },
408
+ source: SOURCE_SPEC_SCHEMA,
409
+ measure: {
410
+ type: "string",
411
+ enum: ["value", "count"],
412
+ description:
413
+ "value (default for an export): the export is a number. count (the only measure of a source): the number of members of a list, set, map or object export, or of a source.",
414
+ },
415
+ },
416
+ additionalProperties: false,
417
+ },
418
+ },
419
+ predicate_source: {
420
+ type: "object",
421
+ description:
422
+ "rule: the code function behind each predicate a claim's rule, predicate or set fact names, keyed by predicate name. Each export takes the predicate's arguments in order and returns a boolean; Kibi calls it on every combination of its argument domains.",
423
+ minProperties: 1,
424
+ additionalProperties: PREDICATE_SOURCE_SCHEMA,
425
+ },
426
+ domains: {
427
+ type: "object",
428
+ description:
429
+ "rule: the finite domain of each argument type, keyed by type name (an array, Set, Map or object export, or a Python list, set, dict or Enum), or {source} for the members Kibi reads from a project source (every route, every table, every environment variable). state_machine with a next-state function: the `state` and `event` domains it is called on.",
430
+ minProperties: 1,
431
+ additionalProperties: {
432
+ anyOf: [SOURCE_REFERENCE_SCHEMA, SOURCE_DOMAIN_SCHEMA],
433
+ },
434
+ },
435
+ initial_source: {
436
+ ...SOURCE_REFERENCE_SCHEMA,
437
+ description:
438
+ "state_machine: the export holding the initial state (or states), needed for initial_states and reachable_states facts.",
439
+ },
440
+ pattern_source: {
441
+ ...SOURCE_REFERENCE_SCHEMA,
442
+ description:
443
+ "regex: the export holding the code's pattern (a RegExp, or a Python re.Pattern) or string constant that a string fact is about.",
444
+ },
445
+ constraint_source: {
446
+ type: "object",
447
+ description:
448
+ "arithmetic and smt: the typed numeric property_value facts the certificate's assumptions come from. Kibi checks the assumptions (or the query's assertions) are exactly these facts' constraints, so the proof is about the knowledge base, not numbers the test chose.",
449
+ required: ["fact_ids"],
450
+ properties: {
451
+ fact_ids: {
452
+ type: "array",
453
+ minItems: 1,
454
+ items: { type: "string", minLength: 1 },
455
+ },
456
+ },
457
+ additionalProperties: false,
458
+ },
221
459
  },
222
460
  additionalProperties: false,
223
461
  } as const;
@@ -479,6 +717,24 @@ export function proofRunArtifactErrors(value: unknown): string[] {
479
717
  )
480
718
  errors.push("artifact.diagnostics must be an array of non-empty strings");
481
719
  }
720
+ if (artifact.certificates !== undefined) {
721
+ if (!Array.isArray(artifact.certificates))
722
+ errors.push("artifact.certificates must be an array when present");
723
+ else
724
+ artifact.certificates.forEach((entry, index) => {
725
+ const row = record(entry);
726
+ if (
727
+ !row ||
728
+ !nonEmptyString(row.version) ||
729
+ !includes(CERTIFICATE_PROOF_KINDS, row.kind) ||
730
+ !nonEmptyString(row.test_id) ||
731
+ !isPlainJson(row)
732
+ )
733
+ errors.push(
734
+ `artifact.certificates[${index}] must be a JSON object with version, a certificate kind (${CERTIFICATE_PROOF_KINDS.join(", ")}) and test_id`,
735
+ );
736
+ });
737
+ }
482
738
  return errors;
483
739
  }
484
740
 
@@ -537,9 +793,444 @@ export function proofContractErrors(value: unknown): string[] {
537
793
  errors.push(
538
794
  `proof_contract.success_policy must be one of: ${SUCCESS_POLICIES.join(", ")}; received ${JSON.stringify(contract.success_policy ?? null)}`,
539
795
  );
796
+ errors.push(...proofContractKindErrors(contract));
540
797
  return errors;
541
798
  }
542
799
 
800
+ // implements REQ-kibi-code-proof-kinds
801
+ function proofContractKindErrors(contract: Record<string, unknown>): string[] {
802
+ const errors: string[] = [];
803
+ const kind = contract.kind;
804
+ if (kind !== undefined && !includes(PROOF_KINDS, kind))
805
+ errors.push(
806
+ `proof_contract.kind must be one of: ${PROOF_KINDS.join(", ")}; received ${JSON.stringify(kind)}`,
807
+ );
808
+ const domain = contract.domain_source;
809
+ if (domain !== undefined) {
810
+ const row = record(domain);
811
+ if (
812
+ !row ||
813
+ !nonEmptyString(row.symbol_id) ||
814
+ (row.export !== undefined && !nonEmptyString(row.export)) ||
815
+ Object.keys(row).some((key) => key !== "symbol_id" && key !== "export")
816
+ )
817
+ errors.push(
818
+ "proof_contract.domain_source must be {symbol_id, export?} naming the symbol that defines the domain and, when its title is not the export name, the export to read",
819
+ );
820
+ } else if (kind === "exhaustive" || kind === "typecheck")
821
+ errors.push(
822
+ `proof_contract.domain_source is required for kind ${String(kind)}: name the symbol the proof reads its domain from`,
823
+ );
824
+ const witness = contract.witness;
825
+ if (witness !== undefined) {
826
+ const row = record(witness);
827
+ if (!row || !nonEmptyString(row.path) || Object.keys(row).length !== 1)
828
+ errors.push(
829
+ "proof_contract.witness must be {path} naming the repository-relative witness file",
830
+ );
831
+ } else if (kind === "typecheck")
832
+ errors.push(
833
+ "proof_contract.witness is required for kind typecheck: name the file the type checker compiles",
834
+ );
835
+ const source = contract.constraint_source;
836
+ if (source !== undefined) {
837
+ const row = record(source);
838
+ const ids = row?.fact_ids;
839
+ if (
840
+ !row ||
841
+ Object.keys(row).length !== 1 ||
842
+ !Array.isArray(ids) ||
843
+ ids.length === 0 ||
844
+ !ids.every(nonEmptyString)
845
+ )
846
+ errors.push(
847
+ "proof_contract.constraint_source must be {fact_ids: [FACT-...]} naming the facts the assumptions come from",
848
+ );
849
+ } else if (
850
+ (kind === "arithmetic" || kind === "smt") &&
851
+ contract.value_source === undefined
852
+ )
853
+ errors.push(
854
+ `proof_contract.constraint_source or value_source is required for kind ${String(kind)}: name the typed facts or code constants its assumptions come from`,
855
+ );
856
+ const valueSource = contract.value_source;
857
+ if (valueSource !== undefined) {
858
+ if (Array.isArray(valueSource))
859
+ valueSource.forEach((entry, index) => {
860
+ const row = record(entry);
861
+ if (row === null || row.source === undefined) return;
862
+ errors.push(
863
+ ...sourceSpecErrors(
864
+ row.source,
865
+ `proof_contract.value_source[${index}].source`,
866
+ ),
867
+ );
868
+ if (row.symbol_id !== undefined || row.export !== undefined)
869
+ errors.push(
870
+ `proof_contract.value_source[${index}] names a source, so it takes no symbol_id or export`,
871
+ );
872
+ if (row.measure !== undefined && row.measure !== "count")
873
+ errors.push(
874
+ `proof_contract.value_source[${index}].measure must be count for a source: Kibi counts the members it reads`,
875
+ );
876
+ });
877
+ if (
878
+ !Array.isArray(valueSource) ||
879
+ valueSource.length === 0 ||
880
+ !valueSource.every((entry) => {
881
+ const row = record(entry);
882
+ if (row !== null && row.source !== undefined) return true;
883
+ return (
884
+ row !== null &&
885
+ nonEmptyString(row.symbol_id) &&
886
+ (row.export === undefined || nonEmptyString(row.export)) &&
887
+ (row.measure === undefined ||
888
+ row.measure === "value" ||
889
+ row.measure === "count") &&
890
+ Object.keys(row).every(
891
+ (key) =>
892
+ key === "symbol_id" || key === "export" || key === "measure",
893
+ )
894
+ );
895
+ })
896
+ )
897
+ errors.push(
898
+ "proof_contract.value_source must be [{symbol_id, export?, measure?: value|count} or {source, measure?: count}] naming the code constants or project sources the assumptions read",
899
+ );
900
+ else if (kind !== "arithmetic" && kind !== "smt")
901
+ errors.push(
902
+ `proof_contract.value_source applies only to kind arithmetic or smt, not ${String(kind ?? "e2e")}`,
903
+ );
904
+ }
905
+ errors.push(...nonNumericContractErrors(contract));
906
+ errors.push(...sourceContractErrors(contract));
907
+ const proves = contract.proves;
908
+ if (proves !== undefined) {
909
+ if (
910
+ !Array.isArray(proves) ||
911
+ proves.length === 0 ||
912
+ !proves.every(
913
+ (key) => typeof key === "string" && /^CLAIM-[A-Za-z0-9]+$/.test(key),
914
+ ) ||
915
+ new Set(proves).size !== proves.length
916
+ )
917
+ errors.push(
918
+ "proof_contract.proves must be a non-empty list of distinct claim keys (CLAIM-...) the certificate proves",
919
+ );
920
+ else if (!isCertificateProofKind(kind))
921
+ errors.push(
922
+ `proof_contract.proves applies only to certificate kinds (${CERTIFICATE_PROOF_KINDS.join(", ")}), not ${String(kind ?? "e2e")}`,
923
+ );
924
+ }
925
+ return errors;
926
+ }
927
+
928
+ function isSourceReference(value: unknown): boolean {
929
+ const row = record(value);
930
+ return (
931
+ row !== null &&
932
+ nonEmptyString(row.symbol_id) &&
933
+ (row.export === undefined || nonEmptyString(row.export)) &&
934
+ Object.keys(row).every((key) => key === "symbol_id" || key === "export")
935
+ );
936
+ }
937
+
938
+ function isSourceMap(
939
+ value: unknown,
940
+ accepts: (entry: unknown) => boolean = isSourceReference,
941
+ ): boolean {
942
+ const row = record(value);
943
+ return (
944
+ row !== null &&
945
+ Object.keys(row).length > 0 &&
946
+ Object.entries(row).every(
947
+ ([key, entry]) => key.trim() !== "" && accepts(entry),
948
+ )
949
+ );
950
+ }
951
+
952
+ function isPredicateReference(value: unknown): boolean {
953
+ const row = record(value);
954
+ if (row === null || row.harness_for === undefined)
955
+ return isSourceReference(value);
956
+ const { harness_for: harness, ...reference } = row;
957
+ return (
958
+ isSourceReference(reference) &&
959
+ Array.isArray(harness) &&
960
+ harness.length > 0 &&
961
+ harness.every(nonEmptyString)
962
+ );
963
+ }
964
+
965
+ function isSourceDomain(value: unknown): boolean {
966
+ const row = record(value);
967
+ return (
968
+ row !== null && Object.keys(row).length === 1 && row.source !== undefined
969
+ );
970
+ }
971
+
972
+ /**
973
+ * The source kind and the source-backed rule domains: a well-formed source
974
+ * spec, required for kind source and only there.
975
+ */
976
+ // implements REQ-kibi-source-proof-kinds
977
+ function sourceContractErrors(contract: Record<string, unknown>): string[] {
978
+ const errors: string[] = [];
979
+ const kind = contract.kind;
980
+ if (contract.source !== undefined) {
981
+ errors.push(...sourceSpecErrors(contract.source, "proof_contract.source"));
982
+ if (kind !== "source")
983
+ errors.push(
984
+ `proof_contract.source applies only to kind source, not ${String(kind ?? "e2e")}`,
985
+ );
986
+ } else if (kind === "source")
987
+ errors.push(
988
+ "proof_contract.source is required for kind source: name the project source Kibi reads (reader json, yaml, glob, openapi, references, schema, routes or validator)",
989
+ );
990
+ const domains = record(contract.domains);
991
+ for (const [type, entry] of Object.entries(domains ?? {}))
992
+ if (isSourceDomain(entry)) {
993
+ errors.push(
994
+ ...sourceSpecErrors(
995
+ record(entry)?.source,
996
+ `proof_contract.domains.${type}.source`,
997
+ ),
998
+ );
999
+ if (kind !== "rule")
1000
+ errors.push(
1001
+ `proof_contract.domains.${type}.source applies only to kind rule: a state machine's domains are the code's`,
1002
+ );
1003
+ }
1004
+ return errors;
1005
+ }
1006
+
1007
+ /**
1008
+ * The contract fields of the rule, state_machine and regex kinds: where the
1009
+ * code Kibi evaluates lives, and only on the kinds that read it.
1010
+ */
1011
+ // implements REQ-kibi-non-numeric-proof-kinds
1012
+ function nonNumericContractErrors(contract: Record<string, unknown>): string[] {
1013
+ const errors: string[] = [];
1014
+ const kind = contract.kind;
1015
+ const only = (field: string, kinds: readonly string[]) => {
1016
+ if (contract[field] !== undefined && !kinds.includes(String(kind)))
1017
+ errors.push(
1018
+ `proof_contract.${field} applies only to kind ${kinds.join(" or ")}, not ${String(kind ?? "e2e")}`,
1019
+ );
1020
+ };
1021
+ if (
1022
+ contract.predicate_source !== undefined &&
1023
+ !isSourceMap(contract.predicate_source, isPredicateReference)
1024
+ )
1025
+ errors.push(
1026
+ "proof_contract.predicate_source must map each predicate name to {symbol_id, export?, harness_for?} naming the function that decides it",
1027
+ );
1028
+ if (
1029
+ contract.domains !== undefined &&
1030
+ !isSourceMap(
1031
+ contract.domains,
1032
+ (entry) => isSourceReference(entry) || isSourceDomain(entry),
1033
+ )
1034
+ )
1035
+ errors.push(
1036
+ "proof_contract.domains must map each argument type to {symbol_id, export?} naming the export that lists its values, or {source} naming the project source Kibi reads them from",
1037
+ );
1038
+ for (const field of ["initial_source", "pattern_source"])
1039
+ if (contract[field] !== undefined && !isSourceReference(contract[field]))
1040
+ errors.push(
1041
+ `proof_contract.${field} must be {symbol_id, export?} naming the export Kibi reads`,
1042
+ );
1043
+ only("predicate_source", ["rule"]);
1044
+ only("domains", ["rule", "state_machine"]);
1045
+ only("initial_source", ["state_machine"]);
1046
+ only("pattern_source", ["regex"]);
1047
+ if (kind === "rule") {
1048
+ if (contract.predicate_source === undefined)
1049
+ errors.push(
1050
+ "proof_contract.predicate_source is required for kind rule: name the function behind each predicate the claims use",
1051
+ );
1052
+ if (contract.domains === undefined)
1053
+ errors.push(
1054
+ "proof_contract.domains is required for kind rule: name the export listing each argument type's values",
1055
+ );
1056
+ }
1057
+ if (kind === "state_machine") {
1058
+ if (contract.domain_source === undefined)
1059
+ errors.push(
1060
+ "proof_contract.domain_source is required for kind state_machine: name the transition table or next-state function",
1061
+ );
1062
+ const domains = record(contract.domains);
1063
+ if (
1064
+ domains !== null &&
1065
+ (Object.keys(domains).length !== 2 ||
1066
+ domains.state === undefined ||
1067
+ domains.event === undefined)
1068
+ )
1069
+ errors.push(
1070
+ "proof_contract.domains for kind state_machine must name exactly the state and event domains a next-state function is called on",
1071
+ );
1072
+ }
1073
+ if (kind === "regex" && contract.pattern_source === undefined)
1074
+ errors.push(
1075
+ "proof_contract.pattern_source is required for kind regex: name the export holding the pattern or string",
1076
+ );
1077
+ return errors;
1078
+ }
1079
+
1080
+ /**
1081
+ * The optional contract fields beyond the v1 core, copied only when present
1082
+ * so existing contracts keep their hash.
1083
+ */
1084
+ // implements REQ-kibi-code-proof-kinds
1085
+ export function optionalProofContractFields(
1086
+ contract: Record<string, unknown>,
1087
+ ): Pick<
1088
+ ProofContract,
1089
+ | "kind"
1090
+ | "domain_source"
1091
+ | "witness"
1092
+ | "constraint_source"
1093
+ | "value_source"
1094
+ | "proves"
1095
+ | "predicate_source"
1096
+ | "domains"
1097
+ | "initial_source"
1098
+ | "pattern_source"
1099
+ | "source"
1100
+ > {
1101
+ const fields: {
1102
+ kind?: ProofKind;
1103
+ domain_source?: { symbol_id: string; export?: string };
1104
+ witness?: { path: string };
1105
+ constraint_source?: { fact_ids: string[] };
1106
+ value_source?: ValueSourceEntry[];
1107
+ proves?: string[];
1108
+ predicate_source?: Record<string, PredicateReference>;
1109
+ domains?: Record<string, SourceReference | { source: SourceSpec }>;
1110
+ initial_source?: SourceReference;
1111
+ pattern_source?: SourceReference;
1112
+ source?: SourceSpec;
1113
+ } = {};
1114
+ if (typeof contract.kind === "string")
1115
+ fields.kind = contract.kind as ProofKind;
1116
+ const domain = record(contract.domain_source);
1117
+ if (domain && typeof domain.symbol_id === "string")
1118
+ fields.domain_source = {
1119
+ symbol_id: domain.symbol_id,
1120
+ ...(typeof domain.export === "string" ? { export: domain.export } : {}),
1121
+ };
1122
+ const witness = record(contract.witness);
1123
+ if (witness && typeof witness.path === "string")
1124
+ fields.witness = { path: witness.path };
1125
+ const source = record(contract.constraint_source);
1126
+ if (source && Array.isArray(source.fact_ids))
1127
+ fields.constraint_source = {
1128
+ fact_ids: source.fact_ids.filter(
1129
+ (id): id is string => typeof id === "string",
1130
+ ),
1131
+ };
1132
+ if (Array.isArray(contract.value_source))
1133
+ fields.value_source = contract.value_source
1134
+ .map((entry) => record(entry))
1135
+ .map((row): ValueSourceEntry | null => {
1136
+ if (row === null) return null;
1137
+ const spec = normalizeSourceSpec(row.source);
1138
+ if (spec !== undefined) return { source: spec, measure: "count" };
1139
+ if (typeof row.symbol_id !== "string") return null;
1140
+ return {
1141
+ symbol_id: row.symbol_id,
1142
+ ...(typeof row.export === "string" ? { export: row.export } : {}),
1143
+ ...(row.measure === "value" || row.measure === "count"
1144
+ ? { measure: row.measure }
1145
+ : {}),
1146
+ };
1147
+ })
1148
+ .filter((row): row is ValueSourceEntry => row !== null);
1149
+ if (Array.isArray(contract.proves))
1150
+ fields.proves = contract.proves.filter(
1151
+ (key): key is string => typeof key === "string",
1152
+ );
1153
+ const predicates = predicateMap(contract.predicate_source);
1154
+ if (predicates !== undefined) fields.predicate_source = predicates;
1155
+ const domains = domainMap(contract.domains);
1156
+ if (domains !== undefined) fields.domains = domains;
1157
+ const spec = normalizeSourceSpec(contract.source);
1158
+ if (spec !== undefined) fields.source = spec;
1159
+ const initial = sourceReference(contract.initial_source);
1160
+ if (initial !== undefined) fields.initial_source = initial;
1161
+ const pattern = sourceReference(contract.pattern_source);
1162
+ if (pattern !== undefined) fields.pattern_source = pattern;
1163
+ return fields;
1164
+ }
1165
+
1166
+ type SourceReference = { symbol_id: string; export?: string };
1167
+ type PredicateReference = SourceReference & { harness_for?: string[] };
1168
+ type ValueSourceEntry =
1169
+ | { symbol_id: string; export?: string; measure?: "value" | "count" }
1170
+ | { source: SourceSpec; measure: "count" };
1171
+
1172
+ function predicateMap(
1173
+ value: unknown,
1174
+ ): Record<string, PredicateReference> | undefined {
1175
+ const row = record(value);
1176
+ if (!row) return undefined;
1177
+ const out: Record<string, PredicateReference> = {};
1178
+ for (const [key, entry] of Object.entries(row)) {
1179
+ const reference = sourceReference(entry);
1180
+ if (reference === undefined) continue;
1181
+ const harness = record(entry)?.harness_for;
1182
+ out[key] = Array.isArray(harness)
1183
+ ? {
1184
+ ...reference,
1185
+ harness_for: harness.filter(
1186
+ (id): id is string => typeof id === "string",
1187
+ ),
1188
+ }
1189
+ : reference;
1190
+ }
1191
+ return Object.keys(out).length > 0 ? out : undefined;
1192
+ }
1193
+
1194
+ function domainMap(
1195
+ value: unknown,
1196
+ ): Record<string, SourceReference | { source: SourceSpec }> | undefined {
1197
+ const row = record(value);
1198
+ if (!row) return undefined;
1199
+ const out: Record<string, SourceReference | { source: SourceSpec }> = {};
1200
+ for (const [key, entry] of Object.entries(row)) {
1201
+ const spec = normalizeSourceSpec(record(entry)?.source);
1202
+ if (spec !== undefined) {
1203
+ out[key] = { source: spec };
1204
+ continue;
1205
+ }
1206
+ const reference = sourceReference(entry);
1207
+ if (reference !== undefined) out[key] = reference;
1208
+ }
1209
+ return Object.keys(out).length > 0 ? out : undefined;
1210
+ }
1211
+
1212
+ function sourceReference(value: unknown): SourceReference | undefined {
1213
+ const row = record(value);
1214
+ if (!row || typeof row.symbol_id !== "string") return undefined;
1215
+ return {
1216
+ symbol_id: row.symbol_id,
1217
+ ...(typeof row.export === "string" ? { export: row.export } : {}),
1218
+ };
1219
+ }
1220
+
1221
+ function sourceMap(
1222
+ value: unknown,
1223
+ ): Record<string, SourceReference> | undefined {
1224
+ const row = record(value);
1225
+ if (!row) return undefined;
1226
+ const out: Record<string, SourceReference> = {};
1227
+ for (const [key, entry] of Object.entries(row)) {
1228
+ const reference = sourceReference(entry);
1229
+ if (reference !== undefined) out[key] = reference;
1230
+ }
1231
+ return Object.keys(out).length > 0 ? out : undefined;
1232
+ }
1233
+
543
1234
  export function proofBindingsErrors(value: unknown): string[] {
544
1235
  if (!Array.isArray(value))
545
1236
  return ["proof_bindings must be an array of binding objects"];