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
@@ -5,6 +5,7 @@ const PROPERTY_VALUE_FIELDS = [
5
5
  "value_int",
6
6
  "value_number",
7
7
  "value_bool",
8
+ "value_set",
8
9
  ];
9
10
  // implements REQ-kibi-operation-interface-parity
10
11
  export function valueFieldHint(value) {
@@ -19,7 +20,10 @@ export function valueFieldHint(value) {
19
20
  if (typeof value === "string") {
20
21
  return `Use value_type: "string" plus value_string: ${JSON.stringify(value)}.`;
21
22
  }
22
- return "Use value_type plus exactly one of value_string, value_int, value_number, or value_bool.";
23
+ if (Array.isArray(value)) {
24
+ return `Use value_type: "set" plus value_set: ${JSON.stringify(value)}.`;
25
+ }
26
+ return "Use value_type plus exactly one of value_string, value_int, value_number, value_bool, or value_set.";
23
27
  }
24
28
  // implements REQ-kibi-operation-interface-parity
25
29
  export function factKindShapeHints(entity) {
@@ -38,7 +42,7 @@ export function factKindShapeHints(entity) {
38
42
  hints.push(`fact_kind 'property_value' requires ${missing.join(", ")}.`);
39
43
  }
40
44
  if (present.length !== 1) {
41
- hints.push("fact_kind 'property_value' requires exactly one typed value field: value_string, value_int, value_number, or value_bool.");
45
+ hints.push("fact_kind 'property_value' requires exactly one typed value field: value_string, value_int, value_number, value_bool, or value_set.");
42
46
  }
43
47
  if (hints.length > 0) {
44
48
  hints.push("Next action: use kb_model_requirement for prose claims, or provide subject_key, property_key, operator, value_type, and one value_* field in kb_upsert.properties.");
@@ -1 +1 @@
1
- {"version":3,"file":"symbol-granularity.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/symbol-granularity.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAajF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA0BpD;;;;GAIG;AAEH,eAAO,MAAM,4BAA4B,iCAAiC,CAAC;AA+B3E,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAC1C,aAAa,EAAE,SAAS,iBAAiB,EAAE,EAC3C,OAAO,EAAE,gBAAgB,EACzB,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,GAC3E,OAAO,CAAC,IAAI,CAAC,CAmDf"}
1
+ {"version":3,"file":"symbol-granularity.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/symbol-granularity.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAajF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA0BpD;;;;GAIG;AAEH,eAAO,MAAM,4BAA4B,iCAAiC,CAAC;AA+B3E,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAC1C,aAAa,EAAE,SAAS,iBAAiB,EAAE,EAC3C,OAAO,EAAE,gBAAgB,EACzB,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,GAC3E,OAAO,CAAC,IAAI,CAAC,CAoDf"}
@@ -1,7 +1,7 @@
1
1
  import { collectGranularityCandidates } from "kibi-plugin-builtin";
2
2
  import { InputError } from "../../cli-errors.js";
3
- import { resolveWorkspaceSourceAbsolute } from "../../utils/repo-relative-path.js";
4
3
  import { ALLOWED_GRANULARITY_REASONS_PROSE, coarseLinkBehavioralNames, getBehavioralSymbolNames, getNonBehavioralSymbolNames, inferSymbolRole, isAllowedGranularityReason, isTraceabilityRelationshipType, } from "../../public/symbol-granularity.js";
4
+ import { resolveWorkspaceSourceAbsolute } from "../../utils/repo-relative-path.js";
5
5
  function candidate(name, kind) {
6
6
  return { name, kind, role: inferSymbolRole(kind) };
7
7
  }
@@ -86,8 +86,10 @@ export async function validateSymbolGranularity(payload, relationships, context,
86
86
  // A declaration named like the symbol is coarse only through its own
87
87
  // behavioral members (a class and its public methods), the same test the
88
88
  // staged gate and `kibi check` apply; any other title is judged against
89
- // every behavioral declaration in the file.
90
- const behavioral = exact && (exact.kind !== "variable" || entity.symbol_role === "config")
89
+ // every behavioral declaration in the file. An exported constant is its
90
+ // own declaration with exact coordinates (a certificate proof's domain is
91
+ // one), so it is granular whatever its role.
92
+ const behavioral = exact
91
93
  ? coarseLinkBehavioralNames(entity.title, available)
92
94
  : getBehavioralSymbolNames(available);
93
95
  if (behavioral.length === 0)
@@ -1 +1 @@
1
- {"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/upsert.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/upsert.ts"],"names":[],"mappings":"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"}
@@ -16,6 +16,7 @@ import { assertLogicalGroundingClaimKeys, assertSemanticInventoryBoundary, } fro
16
16
  import { entityContextWarnings } from "./context-warning.js";
17
17
  import { buildUpsertCommitGoal, formatUpsertError } from "./contradictions.js";
18
18
  import { assertFirmDecisionUnchanged } from "./firm-decision-guard.js";
19
+ import { withStoredOmittedProperties } from "./omitted-properties.js";
19
20
  import { resolveUpsertOrigin } from "./origin.js";
20
21
  import { planRecoveryNotes, settlePendingPlanApplyJournals, withPlanRecoveryNotes, } from "./plan-apply-journal.js";
21
22
  import { assertPredicateArgumentVocabulary } from "./predicate-vocabulary-guard.js";
@@ -279,7 +280,12 @@ export async function validateUpsertForCommit(payload, context, options = {}) {
279
280
  // than later by the staged gate.
280
281
  if (checked.entity.sourceFile === undefined)
281
282
  await validateSymbolGranularity(checked.entity, checked.relationships, context, async () => staged?.entities.get(payload.id) ?? (await lookup.entity()));
282
- let input = await withStoredRequirementSemantics(payload, prolog, staged, lookup);
283
+ const withSemantics = await withStoredRequirementSemantics(payload, prolog, staged, lookup);
284
+ // An uncompiled file is judged as the writer will patch it (below), so only
285
+ // a compiled entity lends its omitted properties to the stored write.
286
+ let input = uncompiledSource === null
287
+ ? await withStoredOmittedProperties(withSemantics, lookup, staged)
288
+ : withSemantics;
283
289
  let validated = input === payload ? checked : validateUpsertInput(input, context.clock());
284
290
  if (uncompiledSource !== null)
285
291
  lookup = {
@@ -1,5 +1,7 @@
1
1
  import { isAllowedGranularityReason } from "../../public/symbol-granularity.js";
2
2
  import type { UpsertInput, ValidatedUpsert } from "./types.js";
3
+ /** Whether the upsert entity schema defines `key` as an entity property. */
4
+ export declare function isUpsertEntityProperty(key: string): boolean;
3
5
  export declare function validateUpsertInput(input: UpsertInput, now: Date): ValidatedUpsert;
4
6
  export { isAllowedGranularityReason };
5
7
  //# sourceMappingURL=validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/validation.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,0BAA0B,EAC3B,MAAM,oCAAoC,CAAC;AAU5C,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAqN/D,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,WAAW,EAClB,GAAG,EAAE,IAAI,GACR,eAAe,CA6DjB;AAED,OAAO,EAAE,0BAA0B,EAAE,CAAC"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/validation.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,0BAA0B,EAC3B,MAAM,oCAAoC,CAAC;AAU5C,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA2D/D,4EAA4E;AAC5E,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAK3D;AA4JD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,WAAW,EAClB,GAAG,EAAE,IAAI,GACR,eAAe,CA6DjB;AAED,OAAO,EAAE,0BAA0B,EAAE,CAAC"}
@@ -59,6 +59,10 @@ const DOCUMENT_TEXT_PROPERTIES = new Set([
59
59
  "summary",
60
60
  "details",
61
61
  ]);
62
+ /** Whether the upsert entity schema defines `key` as an entity property. */
63
+ export function isUpsertEntityProperty(key) {
64
+ return Object.hasOwn(upsertEntitySchema.properties, key);
65
+ }
62
66
  /** Every top-level entity key the upsert entity schema does not define. */
63
67
  function unknownEntityProperties(entity) {
64
68
  const known = upsertEntitySchema.properties;
@@ -0,0 +1,41 @@
1
+ import type { OperationContext } from "../../public/operations/runtime-types.js";
2
+ import type { ProofContract } from "../../public/proof-protocol.js";
3
+ import type { ClaimBinding } from "../../public/proof-receipt.js";
4
+ import { type CertificateVerdict } from "./code-certificates.js";
5
+ /**
6
+ * The type-level witness Kibi writes for a typecheck claim binding: it
7
+ * compiles only when the domain type has exactly the fact's members.
8
+ */
9
+ export declare function setEqualityWitness(importPath: string, members: readonly string[], membersType: string): string;
10
+ /**
11
+ * The type-level witness Kibi writes for a required_fields claim binding: it
12
+ * compiles only when every field is a required key of the type whose value
13
+ * can be neither undefined nor null. Each field has its own two lines (`key<i>`
14
+ * that the field exists, `required<i>` that it is required and non-null), so
15
+ * a failed compile says which fields break the claim.
16
+ */
17
+ export declare function requiredFieldsWitness(importPath: string, typeExpression: string, fields: readonly string[]): string;
18
+ /** Which fields a failed required-fields witness rejected, and how. */
19
+ export declare function requiredFieldsFailures(witness: string, fields: readonly string[], errorLines: readonly number[]): string[];
20
+ /**
21
+ * The evidence level a receipt records. A certificate that re-checks but
22
+ * derives none of the claims it names from the code proves nothing about
23
+ * the code, so the receipt supports tested, the level coverage reports. An
24
+ * intent-scope derivation rests on the knowledge base's own facts alone
25
+ * (the test read no value from the code), so it does not count either.
26
+ */
27
+ export declare function receiptEvidenceLevel(level: "proved" | "tested", bindings: readonly ClaimBinding[] | undefined): "proved" | "tested";
28
+ /**
29
+ * How a certificate binds to each claim its contract names in proves. Kibi
30
+ * derives what the certificate must establish from each claim's grounding
31
+ * fact (claim_obligations.pl) and checks the certificate against it; a claim
32
+ * whose fact has no derivation is only attested by the author. Returns
33
+ * undefined for a contract that names no claims.
34
+ */
35
+ export declare function judgeClaimBindings(context: OperationContext, input: Readonly<{
36
+ testId: string;
37
+ contract: ProofContract;
38
+ verdict: CertificateVerdict;
39
+ coveredBySymbols: readonly string[];
40
+ }>): Promise<ClaimBinding[] | undefined>;
41
+ //# sourceMappingURL=claim-bindings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim-bindings.d.ts","sourceRoot":"","sources":["../../../src/operations/proof/claim-bindings.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EACL,KAAK,kBAAkB,EAIxB,MAAM,wBAAwB,CAAC;AAgDhC;;;GAGG;AAEH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,WAAW,EAAE,MAAM,GAClB,MAAM,CAWR;AAgED;;;;;;GAMG;AAEH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,SAAS,MAAM,EAAE,GACxB,MAAM,CAgBR;AAED,uEAAuE;AACvE,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,MAAM,EAAE,CAaV;AA0JD;;;;;;GAMG;AAEH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,GAAG,QAAQ,EAC1B,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,SAAS,GAC5C,QAAQ,GAAG,QAAQ,CAQrB;AAED;;;;;;GAMG;AAEH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,QAAQ,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC,CAAC,GACD,OAAO,CAAC,YAAY,EAAE,GAAG,SAAS,CAAC,CA+FrC"}
@@ -0,0 +1,364 @@
1
+ /*
2
+ Kibi — repo-local, per-branch, queryable long-term memory for software projects
3
+ Copyright (C) 2026 Piotr Franczyk
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Affero General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Affero General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Affero General Public License
16
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+ import { randomBytes } from "node:crypto";
19
+ import { rmSync, writeFileSync } from "node:fs";
20
+ import path from "node:path";
21
+ import { runOperationJsonQuery, toPrologAtom, } from "../../public/operations/prolog-json.js";
22
+ import { compileWitness, loadSymbol, smtAssertion, } from "./code-certificates.js";
23
+ import { stringConstraintProblem } from "./code-models.js";
24
+ function record(value) {
25
+ return value !== null && typeof value === "object" && !Array.isArray(value)
26
+ ? value
27
+ : null;
28
+ }
29
+ function text(value) {
30
+ return typeof value === "string" ? value : "";
31
+ }
32
+ function sorted(values) {
33
+ return [...new Set(values)].sort();
34
+ }
35
+ function setDifference(code, fact) {
36
+ const factSet = new Set(fact);
37
+ const codeSet = new Set(code);
38
+ const missing = fact.filter((member) => !codeSet.has(member));
39
+ const extra = code.filter((member) => !factSet.has(member));
40
+ return [
41
+ missing.length > 0 ? `missing ${missing.slice(0, 5).join(", ")}` : "",
42
+ extra.length > 0 ? `not in the set ${extra.slice(0, 5).join(", ")}` : "",
43
+ ]
44
+ .filter(Boolean)
45
+ .join("; ");
46
+ }
47
+ /**
48
+ * The type-level witness Kibi writes for a typecheck claim binding: it
49
+ * compiles only when the domain type has exactly the fact's members.
50
+ */
51
+ // implements REQ-kibi-claim-bound-proofs
52
+ export function setEqualityWitness(importPath, members, membersType) {
53
+ const union = members.map((member) => JSON.stringify(member)).join(" | ");
54
+ return [
55
+ `import type * as domain from ${JSON.stringify(importPath)};`,
56
+ "type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;",
57
+ `type Members = ${membersType};`,
58
+ `const exact: Equals<Members, ${union}> = true;`,
59
+ "void exact;",
60
+ "export {};",
61
+ "",
62
+ ].join("\n");
63
+ }
64
+ /**
65
+ * How a domain export may spell its members as a type: a type alias or
66
+ * enum, a const array, the values of a string enum, or a const object's keys.
67
+ */
68
+ function membersTypeCandidates(exportName) {
69
+ const name = `domain.${exportName}`;
70
+ return [
71
+ name,
72
+ `(typeof ${name})[number]`,
73
+ `\`\${${name}}\``,
74
+ `keyof typeof ${name}`,
75
+ ];
76
+ }
77
+ async function typecheckSetProblem(context, contract, obligation) {
78
+ const domainId = contract.domain_source?.symbol_id ?? "";
79
+ const domain = await loadSymbol(context, domainId);
80
+ if (!domain || domain.sourceFile === "")
81
+ return `the domain_source symbol ${domainId} has no source file`;
82
+ const exportName = contract.domain_source?.export ?? domain.title;
83
+ const directory = path.dirname(domain.sourceFile);
84
+ const base = path.basename(domain.sourceFile).replace(/\.[cm]?[jt]sx?$/, "");
85
+ const witnessPath = path.join(directory, `.kibi-claim-witness-${randomBytes(6).toString("hex")}.ts`);
86
+ const absolute = path.resolve(context.workspaceRoot, witnessPath);
87
+ let lastReason = "";
88
+ try {
89
+ for (const membersType of membersTypeCandidates(exportName)) {
90
+ writeFileSync(absolute, setEqualityWitness(`./${base}.js`, obligation.members, membersType), "utf8");
91
+ const compiled = compileWitness(context.workspaceRoot, witnessPath);
92
+ if (compiled.ok)
93
+ return null;
94
+ lastReason = compiled.reason;
95
+ }
96
+ }
97
+ finally {
98
+ rmSync(absolute, { force: true });
99
+ }
100
+ return `${exportName} as a type is not exactly the fact's set {${obligation.members.join(", ")}}${lastReason ? ` (${lastReason.replace(/ the witness \S+/, " the set-equality witness")})` : ""}`;
101
+ }
102
+ function smtNegation(obligation) {
103
+ const assertion = smtAssertion(obligation.variable, obligation.value_type, {
104
+ operator: obligation.operator,
105
+ value: obligation.value,
106
+ });
107
+ // (assert X) -> (assert (not X))
108
+ return `(assert (not ${assertion.slice("(assert ".length, -1)}))`;
109
+ }
110
+ function constraintText(obligation) {
111
+ return `${obligation.variable} ${obligation.operator} ${obligation.value}`;
112
+ }
113
+ /**
114
+ * The type-level witness Kibi writes for a required_fields claim binding: it
115
+ * compiles only when every field is a required key of the type whose value
116
+ * can be neither undefined nor null. Each field has its own two lines (`key<i>`
117
+ * that the field exists, `required<i>` that it is required and non-null), so
118
+ * a failed compile says which fields break the claim.
119
+ */
120
+ // implements REQ-kibi-non-numeric-proof-kinds
121
+ export function requiredFieldsWitness(importPath, typeExpression, fields) {
122
+ return [
123
+ `import type * as domain from ${JSON.stringify(importPath)};`,
124
+ `type Shape = ${typeExpression};`,
125
+ "type HasKey<K extends PropertyKey> = K extends keyof Shape ? true : false;",
126
+ "type IsRequired<K extends PropertyKey> = K extends keyof Shape",
127
+ " ? {} extends Pick<Shape, K> ? false : undefined extends Shape[K] ? false : null extends Shape[K] ? false : true",
128
+ " : false;",
129
+ ...fields.flatMap((field, index) => [
130
+ `const key${index}: HasKey<${JSON.stringify(field)}> = true;`,
131
+ `const required${index}: IsRequired<${JSON.stringify(field)}> = true;`,
132
+ ]),
133
+ `void [${fields.map((_, index) => `key${index}, required${index}`).join(", ")}];`,
134
+ "export {};",
135
+ "",
136
+ ].join("\n");
137
+ }
138
+ /** Which fields a failed required-fields witness rejected, and how. */
139
+ export function requiredFieldsFailures(witness, fields, errorLines) {
140
+ const lines = witness.split("\n");
141
+ const failing = new Set(errorLines);
142
+ const lineOf = (prefix) => lines.findIndex((line) => line.startsWith(prefix));
143
+ const failures = [];
144
+ fields.forEach((field, index) => {
145
+ if (failing.has(lineOf(`const key${index}:`)))
146
+ failures.push(`${field} is not a field`);
147
+ else if (failing.has(lineOf(`const required${index}:`)))
148
+ failures.push(`${field} is optional or nullable`);
149
+ });
150
+ return failures;
151
+ }
152
+ async function requiredFieldsProblem(context, contract, fields) {
153
+ const domainId = contract.domain_source?.symbol_id ?? "";
154
+ const domain = await loadSymbol(context, domainId);
155
+ if (!domain || domain.sourceFile === "")
156
+ return `the domain_source symbol ${domainId} has no source file`;
157
+ const exportName = contract.domain_source?.export ?? domain.title;
158
+ const directory = path.dirname(domain.sourceFile);
159
+ const base = path.basename(domain.sourceFile).replace(/\.[cm]?[jt]sx?$/, "");
160
+ const witnessPath = path.join(directory, `.kibi-claim-witness-${randomBytes(6).toString("hex")}.ts`);
161
+ const absolute = path.resolve(context.workspaceRoot, witnessPath);
162
+ let lastReason = "";
163
+ let failures = [];
164
+ try {
165
+ for (const typeExpression of [
166
+ `domain.${exportName}`,
167
+ `InstanceType<typeof domain.${exportName}>`,
168
+ ]) {
169
+ const witness = requiredFieldsWitness(`./${base}.js`, typeExpression, fields);
170
+ writeFileSync(absolute, witness, "utf8");
171
+ const compiled = compileWitness(context.workspaceRoot, witnessPath);
172
+ if (compiled.ok)
173
+ return null;
174
+ lastReason = compiled.reason;
175
+ // The first type expression that names a real type decides which
176
+ // fields fail; the InstanceType form is only for classes.
177
+ const errorLines = compiled.errorLines ?? [];
178
+ const shapeLine = witness.split("\n").findIndex((line) => line.startsWith("type Shape"));
179
+ if (failures.length === 0 && !errorLines.includes(shapeLine))
180
+ failures = requiredFieldsFailures(witness, fields, errorLines);
181
+ }
182
+ }
183
+ finally {
184
+ rmSync(absolute, { force: true });
185
+ }
186
+ if (failures.length > 0)
187
+ return `${exportName} does not have every field of {${fields.join(", ")}} as a required, non-nullable field: ${failures.join("; ")}`;
188
+ return `${exportName} does not have every field of {${fields.join(", ")}} as a required, non-nullable field${lastReason ? ` (${lastReason.replace(/ the witness \S+/, " the required-fields witness")})` : ""}`;
189
+ }
190
+ /** The symbols a non-numeric certificate read, which must be in code scope. */
191
+ function modelSymbols(contract) {
192
+ return [
193
+ contract.domain_source?.symbol_id,
194
+ contract.initial_source?.symbol_id,
195
+ contract.pattern_source?.symbol_id,
196
+ ...Object.values(contract.domains ?? {}).map((row) => "symbol_id" in row ? row.symbol_id : undefined),
197
+ ...Object.values(contract.predicate_source ?? {}).flatMap((row) => [
198
+ row.symbol_id,
199
+ ...(row.harness_for ?? []),
200
+ ]),
201
+ ].filter((id) => typeof id === "string" && id !== "");
202
+ }
203
+ async function nonNumericProblem(context, contract, certificate, obligation, factId, coveredBy) {
204
+ const outside = modelSymbols(contract).find((id) => !coveredBy.has(id));
205
+ if (outside !== undefined)
206
+ return `the symbol ${outside} the certificate read is not in the receipt's code scope: link it covered_by the test so a change to it stales the proof`;
207
+ const obligationKind = text(obligation.kind);
208
+ if (obligationKind === "required_fields" && contract.kind === "typecheck")
209
+ return requiredFieldsProblem(context, contract, Array.isArray(obligation.members) ? obligation.members.map(String) : []);
210
+ if (obligationKind === "string_constraint")
211
+ return stringConstraintProblem(certificate, obligation, factId);
212
+ if (context.prolog === undefined)
213
+ return "no Prolog runtime is attached to model check the claim";
214
+ const checked = await runOperationJsonQuery(context.prolog, "claim_obligations.pl", `claim_obligations:claim_model_check_json(${toPrologAtom(contract.kind ?? "")}, ${toPrologAtom(JSON.stringify(obligation))}, ${toPrologAtom(JSON.stringify(certificate))}, JsonString)`, "Claim model check");
215
+ return checked.ok === true ? null : (checked.reason ?? "the model check failed");
216
+ }
217
+ const NON_NUMERIC_OBLIGATIONS = new Set([
218
+ "required_fields",
219
+ "string_constraint",
220
+ "rule_holds",
221
+ "predicate_holds",
222
+ "every_member",
223
+ "machine_set",
224
+ "machine_relation",
225
+ "set_relation",
226
+ "nullable_fields",
227
+ "route_middleware",
228
+ ]);
229
+ async function derivedProblem(context, contract, certificate, row, coveredBy) {
230
+ const obligation = record(row.obligation) ?? {};
231
+ const kind = contract.kind;
232
+ const factId = row.fact_id ?? "the grounding fact";
233
+ if (NON_NUMERIC_OBLIGATIONS.has(text(obligation.kind)))
234
+ return nonNumericProblem(context, contract, certificate, obligation, factId, coveredBy);
235
+ if (kind === "exhaustive" || kind === "typecheck") {
236
+ const set = obligation;
237
+ const domainId = contract.domain_source?.symbol_id ?? "";
238
+ if (!coveredBy.has(domainId))
239
+ return `the domain_source symbol ${domainId} is not in the receipt's code scope: link it covered_by the test so a change to the domain stales the proof`;
240
+ if (kind === "exhaustive") {
241
+ const members = record(certificate.domain)?.members;
242
+ const code = sorted(Array.isArray(members) ? members.map((member) => String(member)) : []);
243
+ const fact = sorted(set.members ?? []);
244
+ if (code.join("\u0000") !== fact.join("\u0000"))
245
+ return `the domain members Kibi read are not ${factId}'s set (${setDifference(code, fact)})`;
246
+ return null;
247
+ }
248
+ return typecheckSetProblem(context, contract, set);
249
+ }
250
+ const numeric = obligation;
251
+ if (kind === "arithmetic") {
252
+ const claim = record(certificate.claim) ?? {};
253
+ if (text(certificate.variable) !== numeric.variable ||
254
+ text(certificate.value_type) !== numeric.value_type ||
255
+ text(claim.operator) !== numeric.operator ||
256
+ Number(claim.value) !== numeric.value)
257
+ return `the certificate's claim is not ${factId}'s constraint (${constraintText(numeric)})`;
258
+ return null;
259
+ }
260
+ const query = text(certificate.query).replace(/\s+/g, " ");
261
+ const negation = smtNegation(numeric);
262
+ if (!query.includes(negation))
263
+ return `the query does not assert the negation of ${factId}'s constraint ${negation}`;
264
+ return null;
265
+ }
266
+ /**
267
+ * The evidence level a receipt records. A certificate that re-checks but
268
+ * derives none of the claims it names from the code proves nothing about
269
+ * the code, so the receipt supports tested, the level coverage reports. An
270
+ * intent-scope derivation rests on the knowledge base's own facts alone
271
+ * (the test read no value from the code), so it does not count either.
272
+ */
273
+ // implements REQ-kibi-claim-bound-proofs
274
+ export function receiptEvidenceLevel(level, bindings) {
275
+ if (level !== "proved" || bindings === undefined || bindings.length === 0)
276
+ return level;
277
+ return bindings.some((binding) => binding.binding === "derived" && binding.scope !== "intent")
278
+ ? "proved"
279
+ : "tested";
280
+ }
281
+ /**
282
+ * How a certificate binds to each claim its contract names in proves. Kibi
283
+ * derives what the certificate must establish from each claim's grounding
284
+ * fact (claim_obligations.pl) and checks the certificate against it; a claim
285
+ * whose fact has no derivation is only attested by the author. Returns
286
+ * undefined for a contract that names no claims.
287
+ */
288
+ // implements REQ-kibi-claim-bound-proofs, REQ-kibi-non-numeric-proof-kinds
289
+ export async function judgeClaimBindings(context, input) {
290
+ const keys = input.contract.proves ?? [];
291
+ if (keys.length === 0 || input.contract.kind === undefined)
292
+ return undefined;
293
+ if (context.prolog === undefined)
294
+ return keys.map((key) => ({
295
+ claim_key: key,
296
+ binding: "rejected",
297
+ reason: "no Prolog runtime is attached to resolve the claim",
298
+ }));
299
+ const rows = await runOperationJsonQuery(context.prolog, "claim_obligations.pl", `claim_obligations:test_claim_obligations_json(${toPrologAtom(input.testId)}, ${toPrologAtom(JSON.stringify(keys))}, ${toPrologAtom(input.contract.kind)}, JsonString)`, "Claim obligations");
300
+ const coveredBy = new Set(input.coveredBySymbols);
301
+ const valueSourced = (input.contract.value_source ?? []).length > 0 &&
302
+ (input.contract.value_source ?? []).every((source) => "source" in source || coveredBy.has(source.symbol_id));
303
+ // A rule decided by a test harness that drives the code is about the code
304
+ // through that harness, so its claims are bound with scope harness.
305
+ const harnessed = input.contract.kind === "rule" &&
306
+ Object.values(input.contract.predicate_source ?? {}).some((row) => (row.harness_for ?? []).length > 0);
307
+ const certificate = record(input.verdict.certificate) ?? {};
308
+ const bindings = [];
309
+ for (const row of rows) {
310
+ const base = {
311
+ claim_key: row.claim_key,
312
+ ...(row.requirement_id ? { requirement_id: row.requirement_id } : {}),
313
+ ...(row.fact_id ? { fact_id: row.fact_id } : {}),
314
+ };
315
+ if (row.result === "unresolved" || row.result === "incompatible") {
316
+ bindings.push({
317
+ ...base,
318
+ binding: "rejected",
319
+ reason: row.reason ?? "the claim cannot be proved by this certificate",
320
+ });
321
+ continue;
322
+ }
323
+ if (row.result === "attested") {
324
+ bindings.push({ ...base, binding: "attested", scope: "code" });
325
+ continue;
326
+ }
327
+ const obligation = record(row.obligation) ?? {};
328
+ if (input.verdict.evidence_level !== "proved") {
329
+ const recheck = `the certificate did not re-check${input.verdict.certificate_rejection ? `: ${input.verdict.certificate_rejection}` : ""}`;
330
+ // A typecheck claim is decided from the code alone, so when the
331
+ // author's witness fails, lead with what the code breaks (the field
332
+ // that is nullable, the member that is missing) rather than only
333
+ // "the type checker did not accept the witness".
334
+ const codeProblem = input.contract.kind === "typecheck" &&
335
+ input.verdict.certificate !== undefined
336
+ ? await derivedProblem(context, input.contract, certificate, row, coveredBy)
337
+ : null;
338
+ bindings.push({
339
+ ...base,
340
+ binding: "rejected",
341
+ obligation,
342
+ reason: codeProblem === null ? recheck : `${codeProblem} (${recheck})`,
343
+ });
344
+ continue;
345
+ }
346
+ const problem = await derivedProblem(context, input.contract, certificate, row, coveredBy);
347
+ const numeric = text(obligation.kind) === "numeric_constraint";
348
+ bindings.push(problem === null
349
+ ? {
350
+ ...base,
351
+ binding: "derived",
352
+ scope: numeric && !valueSourced
353
+ ? "intent"
354
+ : harnessed
355
+ ? "harness"
356
+ : input.contract.kind === "source"
357
+ ? "source"
358
+ : "code",
359
+ obligation,
360
+ }
361
+ : { ...base, binding: "rejected", obligation, reason: problem });
362
+ }
363
+ return bindings;
364
+ }