kibi-cli 2.31.0 → 2.32.0

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 (226) 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/commands/check.d.ts +1 -0
  6. package/dist/commands/check.d.ts.map +1 -1
  7. package/dist/commands/check.js +14 -5
  8. package/dist/commands/discovery-table.d.ts.map +1 -1
  9. package/dist/commands/discovery-table.js +51 -4
  10. package/dist/commands/doctor.js +19 -4
  11. package/dist/commands/migrate.d.ts.map +1 -1
  12. package/dist/commands/migrate.js +89 -3
  13. package/dist/commands/prove.d.ts +48 -1
  14. package/dist/commands/prove.d.ts.map +1 -1
  15. package/dist/commands/prove.js +293 -8
  16. package/dist/commands/report.d.ts +1 -0
  17. package/dist/commands/report.d.ts.map +1 -1
  18. package/dist/commands/report.js +70 -5
  19. package/dist/commands/signoff.d.ts.map +1 -1
  20. package/dist/commands/signoff.js +21 -2
  21. package/dist/commands/sync/manifest.d.ts.map +1 -1
  22. package/dist/commands/sync/manifest.js +20 -4
  23. package/dist/commands/sync/persistence.d.ts.map +1 -1
  24. package/dist/commands/sync/persistence.js +16 -5
  25. package/dist/diagnostics.js +1 -1
  26. package/dist/engine.js +1 -1
  27. package/dist/extractors/markdown.d.ts +3 -1
  28. package/dist/extractors/markdown.d.ts.map +1 -1
  29. package/dist/extractors/markdown.js +17 -0
  30. package/dist/operations/bootstrap/candidate-helpers.d.ts +3 -0
  31. package/dist/operations/bootstrap/candidate-helpers.d.ts.map +1 -1
  32. package/dist/operations/bootstrap/candidate-helpers.js +4 -0
  33. package/dist/operations/migration/evidence-floor.d.ts +41 -0
  34. package/dist/operations/migration/evidence-floor.d.ts.map +1 -0
  35. package/dist/operations/migration/evidence-floor.js +230 -0
  36. package/dist/operations/migration/proof-contract-claims.d.ts +59 -0
  37. package/dist/operations/migration/proof-contract-claims.d.ts.map +1 -0
  38. package/dist/operations/migration/proof-contract-claims.js +182 -0
  39. package/dist/operations/migration/schema6.d.ts +6 -0
  40. package/dist/operations/migration/schema6.d.ts.map +1 -1
  41. package/dist/operations/migration/schema6.js +94 -0
  42. package/dist/operations/mutation/omitted-properties.d.ts +11 -0
  43. package/dist/operations/mutation/omitted-properties.d.ts.map +1 -0
  44. package/dist/operations/mutation/omitted-properties.js +76 -0
  45. package/dist/operations/mutation/serialization.d.ts.map +1 -1
  46. package/dist/operations/mutation/serialization.js +1 -0
  47. package/dist/operations/mutation/strict-fact.d.ts.map +1 -1
  48. package/dist/operations/mutation/strict-fact.js +6 -2
  49. package/dist/operations/mutation/symbol-granularity.d.ts.map +1 -1
  50. package/dist/operations/mutation/symbol-granularity.js +5 -3
  51. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  52. package/dist/operations/mutation/upsert.js +7 -1
  53. package/dist/operations/mutation/validation.d.ts +2 -0
  54. package/dist/operations/mutation/validation.d.ts.map +1 -1
  55. package/dist/operations/mutation/validation.js +4 -0
  56. package/dist/operations/proof/claim-bindings.d.ts +23 -0
  57. package/dist/operations/proof/claim-bindings.d.ts.map +1 -0
  58. package/dist/operations/proof/claim-bindings.js +211 -0
  59. package/dist/operations/proof/code-certificates.d.ts +135 -0
  60. package/dist/operations/proof/code-certificates.d.ts.map +1 -0
  61. package/dist/operations/proof/code-certificates.js +785 -0
  62. package/dist/operations/proof/code-scope.d.ts +11 -1
  63. package/dist/operations/proof/code-scope.d.ts.map +1 -1
  64. package/dist/operations/proof/code-scope.js +20 -2
  65. package/dist/operations/proof/compact-receipts.d.ts.map +1 -1
  66. package/dist/operations/proof/compact-receipts.js +4 -3
  67. package/dist/operations/proof/explain.d.ts +32 -0
  68. package/dist/operations/proof/explain.d.ts.map +1 -1
  69. package/dist/operations/proof/explain.js +91 -0
  70. package/dist/operations/proof/ingest-proof.d.ts +9 -1
  71. package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
  72. package/dist/operations/proof/ingest-proof.js +41 -2
  73. package/dist/operations/proof/receipt-compaction.d.ts +2 -0
  74. package/dist/operations/proof/receipt-compaction.d.ts.map +1 -1
  75. package/dist/operations/proof/receipt-compaction.js +6 -2
  76. package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
  77. package/dist/operations/semantic-advisor/shared.js +4 -0
  78. package/dist/operations/semantic-advisor/strict-rules.js +3 -3
  79. package/dist/operations/semantic-advisor/types.d.ts +2 -1
  80. package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
  81. package/dist/plugins/approved-source-analyzers.generated.d.ts +6 -6
  82. package/dist/plugins/approved-source-analyzers.generated.js +6 -6
  83. package/dist/proof/command-test-report.d.ts +4 -3
  84. package/dist/proof/command-test-report.d.ts.map +1 -1
  85. package/dist/proof/command-test-report.js +4 -10
  86. package/dist/proof/evaluate.d.ts.map +1 -1
  87. package/dist/proof/evaluate.js +18 -2
  88. package/dist/proof/inspect.d.ts.map +1 -1
  89. package/dist/proof/inspect.js +58 -0
  90. package/dist/proof/producers/playwright-reporter.d.ts +3 -0
  91. package/dist/proof/producers/playwright-reporter.d.ts.map +1 -1
  92. package/dist/proof/producers/playwright-reporter.js +25 -2
  93. package/dist/proof/step-runner.d.ts +36 -0
  94. package/dist/proof/step-runner.d.ts.map +1 -0
  95. package/dist/proof/step-runner.js +234 -0
  96. package/dist/public/evidence-levels.d.ts +12 -0
  97. package/dist/public/evidence-levels.d.ts.map +1 -0
  98. package/dist/public/evidence-levels.js +19 -0
  99. package/dist/public/impact/coverage-depth-quality.d.ts +7 -0
  100. package/dist/public/impact/coverage-depth-quality.d.ts.map +1 -1
  101. package/dist/public/impact/coverage-depth-quality.js +59 -0
  102. package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
  103. package/dist/public/impact/full-kb-quality.js +3 -1
  104. package/dist/public/operations/catalog.d.ts +167 -6
  105. package/dist/public/operations/catalog.d.ts.map +1 -1
  106. package/dist/public/operations/check-executor.d.ts +2 -0
  107. package/dist/public/operations/check-executor.d.ts.map +1 -1
  108. package/dist/public/operations/check-executor.js +6 -0
  109. package/dist/public/operations/evidence-floor.d.ts +48 -0
  110. package/dist/public/operations/evidence-floor.d.ts.map +1 -0
  111. package/dist/public/operations/evidence-floor.js +143 -0
  112. package/dist/public/operations/migration-plan.d.ts +19 -5
  113. package/dist/public/operations/migration-plan.d.ts.map +1 -1
  114. package/dist/public/operations/migration-plan.js +22 -5
  115. package/dist/public/operations/node-ports.d.ts.map +1 -1
  116. package/dist/public/operations/node-ports.js +4 -1
  117. package/dist/public/operations/proof-contract-claims.d.ts +26 -0
  118. package/dist/public/operations/proof-contract-claims.d.ts.map +1 -0
  119. package/dist/public/operations/proof-contract-claims.js +71 -0
  120. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  121. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  122. package/dist/public/operations/specs/check-rules.generated.js +3 -1
  123. package/dist/public/operations/specs/check.d.ts +1 -1
  124. package/dist/public/operations/specs/mutation-schemas.d.ts +157 -5
  125. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  126. package/dist/public/operations/specs/mutation-schemas.js +15 -2
  127. package/dist/public/operations/specs/proof.d.ts +9 -0
  128. package/dist/public/operations/specs/proof.d.ts.map +1 -1
  129. package/dist/public/operations/specs/reporting.d.ts.map +1 -1
  130. package/dist/public/operations/specs/reporting.js +19 -10
  131. package/dist/public/operations/specs/upsert.d.ts +157 -5
  132. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  133. package/dist/public/proof-certificates.d.ts +89 -0
  134. package/dist/public/proof-certificates.d.ts.map +1 -0
  135. package/dist/public/proof-certificates.js +207 -0
  136. package/dist/public/proof-protocol.d.ts +126 -3
  137. package/dist/public/proof-protocol.d.ts.map +1 -1
  138. package/dist/public/proof-protocol.js +239 -3
  139. package/dist/public/proof-receipt.d.ts +89 -6
  140. package/dist/public/proof-receipt.d.ts.map +1 -1
  141. package/dist/public/proof-receipt.js +83 -7
  142. package/dist/public/schemas/entity.d.ts.map +1 -1
  143. package/dist/public/schemas/entity.js +18 -1
  144. package/dist/public/skills/kibi-bootstrap/SKILL.md +2 -2
  145. package/dist/public/skills/kibi-commit-review/SKILL.md +4 -3
  146. package/dist/public/skills/kibi-commit-review/resources/staged-gate.md +6 -1
  147. package/dist/public/skills/kibi-decisions/SKILL.md +10 -2
  148. package/dist/public/skills/kibi-decisions/resources/decision-records.md +6 -1
  149. package/dist/public/skills/kibi-decisions/resources/signoff-views.md +3 -2
  150. package/dist/public/skills/kibi-freshness/SKILL.md +5 -1
  151. package/dist/public/skills/kibi-traceability/SKILL.md +11 -1
  152. package/dist/public/skills/kibi-usage/SKILL.md +6 -4
  153. package/dist/public/skills/kibi-usage/resources/proof.md +124 -19
  154. package/dist/public/skills/kibi-usage/resources/workflows.md +4 -4
  155. package/dist/report/html-report.css +38 -1
  156. package/dist/report/html-report.d.ts +8 -0
  157. package/dist/report/html-report.d.ts.map +1 -1
  158. package/dist/report/html-report.js +141 -6
  159. package/dist/report/report-view.d.ts +1 -1
  160. package/dist/report/report-view.d.ts.map +1 -1
  161. package/dist/report/report-view.js +7 -0
  162. package/dist/schemas/entity.schema.json +212 -4
  163. package/dist/search-answer.d.ts.map +1 -1
  164. package/dist/search-answer.js +1 -0
  165. package/dist/signoff/html.d.ts.map +1 -1
  166. package/dist/signoff/html.js +3 -0
  167. package/dist/signoff/markdown.d.ts.map +1 -1
  168. package/dist/signoff/markdown.js +3 -0
  169. package/dist/signoff/model.d.ts +20 -0
  170. package/dist/signoff/model.d.ts.map +1 -1
  171. package/dist/signoff/model.js +20 -1
  172. package/dist/traceability/impact-knowledge.d.ts.map +1 -1
  173. package/dist/traceability/impact-knowledge.js +1 -0
  174. package/dist/traceability/temp-kb.d.ts.map +1 -1
  175. package/dist/traceability/temp-kb.js +1 -0
  176. package/dist/types/entities.d.ts +4 -1
  177. package/dist/types/entities.d.ts.map +1 -1
  178. package/dist/utils/merge-driver-setup.d.ts +8 -1
  179. package/dist/utils/merge-driver-setup.d.ts.map +1 -1
  180. package/dist/utils/merge-driver-setup.js +23 -2
  181. package/dist/utils/rule-registry.generated.d.ts +10 -0
  182. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  183. package/dist/utils/rule-registry.generated.js +12 -0
  184. package/dist/utils/schema-version.d.ts +1 -1
  185. package/dist/utils/schema-version.d.ts.map +1 -1
  186. package/dist/utils/schema-version.js +5 -1
  187. package/package.json +6 -2
  188. package/schema/entities.pl +6 -0
  189. package/schema/validation.pl +4 -1
  190. package/src/public/evidence-levels.ts +23 -0
  191. package/src/public/impact/coverage-depth-quality.ts +73 -0
  192. package/src/public/impact/full-kb-quality.ts +6 -1
  193. package/src/public/operations/check-executor.ts +13 -0
  194. package/src/public/operations/evidence-floor.ts +203 -0
  195. package/src/public/operations/migration-plan.ts +39 -6
  196. package/src/public/operations/node-ports.ts +3 -1
  197. package/src/public/operations/proof-contract-claims.ts +103 -0
  198. package/src/public/operations/specs/check-rules.generated.ts +3 -1
  199. package/src/public/operations/specs/mutation-schemas.ts +17 -2
  200. package/src/public/operations/specs/reporting.ts +20 -10
  201. package/src/public/proof-certificates.ts +271 -0
  202. package/src/public/proof-protocol-types.d.ts +17 -1
  203. package/src/public/proof-protocol.ts +318 -3
  204. package/src/public/proof-receipt.ts +127 -7
  205. package/src/public/schemas/entity.ts +19 -1
  206. package/src/public/skills/kibi-bootstrap/SKILL.md +2 -2
  207. package/src/public/skills/kibi-commit-review/SKILL.md +4 -3
  208. package/src/public/skills/kibi-commit-review/resources/staged-gate.md +6 -1
  209. package/src/public/skills/kibi-decisions/SKILL.md +10 -2
  210. package/src/public/skills/kibi-decisions/resources/decision-records.md +6 -1
  211. package/src/public/skills/kibi-decisions/resources/signoff-views.md +3 -2
  212. package/src/public/skills/kibi-freshness/SKILL.md +5 -1
  213. package/src/public/skills/kibi-traceability/SKILL.md +11 -1
  214. package/src/public/skills/kibi-usage/SKILL.md +6 -4
  215. package/src/public/skills/kibi-usage/resources/proof.md +124 -19
  216. package/src/public/skills/kibi-usage/resources/workflows.md +4 -4
  217. package/src/schemas/entity.schema.json +212 -4
  218. package/dist/commands/proof-impact.d.ts +0 -7
  219. package/dist/commands/proof-impact.d.ts.map +0 -1
  220. package/dist/commands/proof-impact.js +0 -39
  221. package/dist/operations/proof/baseline-diff.d.ts +0 -41
  222. package/dist/operations/proof/baseline-diff.d.ts.map +0 -1
  223. package/dist/operations/proof/baseline-diff.js +0 -153
  224. package/dist/operations/proof/impact.d.ts +0 -51
  225. package/dist/operations/proof/impact.d.ts.map +0 -1
  226. package/dist/operations/proof/impact.js +0 -138
@@ -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,52 @@ 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) cover every case and support
74
+ * proved evidence once Kibi re-checks the certificate the run left.
75
+ */
76
+ // implements REQ-kibi-code-proof-kinds
77
+ export const PROOF_KINDS = [
78
+ "e2e",
79
+ "example",
80
+ "property",
81
+ "exhaustive",
82
+ "typecheck",
83
+ "arithmetic",
84
+ "smt",
85
+ ] as const;
86
+
87
+ // implements REQ-kibi-code-proof-kinds
88
+ export const CERTIFICATE_PROOF_KINDS = [
89
+ "exhaustive",
90
+ "typecheck",
91
+ "arithmetic",
92
+ "smt",
93
+ ] as const;
94
+
95
+ // implements REQ-kibi-code-proof-kinds
96
+ export type ProofKind = (typeof PROOF_KINDS)[number];
97
+
98
+ // implements REQ-kibi-code-proof-kinds
99
+ export function isCertificateProofKind(kind: unknown): boolean {
100
+ return (CERTIFICATE_PROOF_KINDS as readonly unknown[]).includes(kind);
101
+ }
42
102
 
43
103
  export type {
44
104
  AttemptsStatus,
@@ -191,6 +251,13 @@ export const PROOF_RUN_ARTIFACT_SCHEMA = {
191
251
  type: "array",
192
252
  items: { type: "string", minLength: 1 },
193
253
  },
254
+ certificates: {
255
+ type: "array",
256
+ description:
257
+ "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.",
258
+ maxItems: 1000,
259
+ items: { type: "object", required: ["version", "kind", "test_id"] },
260
+ },
194
261
  },
195
262
  additionalProperties: false,
196
263
  } as const;
@@ -218,6 +285,73 @@ export const PROOF_CONTRACT_SCHEMA = {
218
285
  },
219
286
  },
220
287
  success_policy: { type: "string", enum: [...SUCCESS_POLICIES] },
288
+ kind: {
289
+ type: "string",
290
+ enum: [...PROOF_KINDS],
291
+ description:
292
+ "What the checker establishes; absent means e2e. exhaustive, typecheck, arithmetic and smt must leave a kibi.code-certificate.v1 that Kibi re-checks before the receipt counts as proved.",
293
+ },
294
+ domain_source: {
295
+ type: "object",
296
+ description:
297
+ "exhaustive and typecheck: the symbol that defines the finite domain. 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.",
298
+ required: ["symbol_id"],
299
+ properties: {
300
+ symbol_id: { type: "string", minLength: 1 },
301
+ export: {
302
+ type: "string",
303
+ minLength: 1,
304
+ description:
305
+ "The name the domain is exported under in the symbol's source file, when the symbol's title is not that name.",
306
+ },
307
+ },
308
+ additionalProperties: false,
309
+ },
310
+ witness: {
311
+ type: "object",
312
+ description:
313
+ "typecheck: the repository-relative witness file Kibi compiles (an exhaustive switch ending in never, or a mapped type over the domain).",
314
+ required: ["path"],
315
+ properties: { path: { type: "string", minLength: 1 } },
316
+ additionalProperties: false,
317
+ },
318
+ proves: {
319
+ type: "array",
320
+ description:
321
+ "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 claim with no such derivation is only attested and never counts as proved.",
322
+ minItems: 1,
323
+ items: { type: "string", pattern: "^CLAIM-" },
324
+ uniqueItems: true,
325
+ },
326
+ value_source: {
327
+ type: "array",
328
+ description:
329
+ "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.",
330
+ minItems: 1,
331
+ items: {
332
+ type: "object",
333
+ required: ["symbol_id"],
334
+ properties: {
335
+ symbol_id: { type: "string", minLength: 1 },
336
+ export: { type: "string", minLength: 1 },
337
+ },
338
+ additionalProperties: false,
339
+ },
340
+ },
341
+ constraint_source: {
342
+ type: "object",
343
+ description:
344
+ "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.",
345
+ required: ["fact_ids"],
346
+ properties: {
347
+ fact_ids: {
348
+ type: "array",
349
+ minItems: 1,
350
+ items: { type: "string", minLength: 1 },
351
+ },
352
+ },
353
+ additionalProperties: false,
354
+ },
221
355
  },
222
356
  additionalProperties: false,
223
357
  } as const;
@@ -479,6 +613,24 @@ export function proofRunArtifactErrors(value: unknown): string[] {
479
613
  )
480
614
  errors.push("artifact.diagnostics must be an array of non-empty strings");
481
615
  }
616
+ if (artifact.certificates !== undefined) {
617
+ if (!Array.isArray(artifact.certificates))
618
+ errors.push("artifact.certificates must be an array when present");
619
+ else
620
+ artifact.certificates.forEach((entry, index) => {
621
+ const row = record(entry);
622
+ if (
623
+ !row ||
624
+ !nonEmptyString(row.version) ||
625
+ !includes(CERTIFICATE_PROOF_KINDS, row.kind) ||
626
+ !nonEmptyString(row.test_id) ||
627
+ !isPlainJson(row)
628
+ )
629
+ errors.push(
630
+ `artifact.certificates[${index}] must be a JSON object with version, a certificate kind (${CERTIFICATE_PROOF_KINDS.join(", ")}) and test_id`,
631
+ );
632
+ });
633
+ }
482
634
  return errors;
483
635
  }
484
636
 
@@ -537,9 +689,172 @@ export function proofContractErrors(value: unknown): string[] {
537
689
  errors.push(
538
690
  `proof_contract.success_policy must be one of: ${SUCCESS_POLICIES.join(", ")}; received ${JSON.stringify(contract.success_policy ?? null)}`,
539
691
  );
692
+ errors.push(...proofContractKindErrors(contract));
693
+ return errors;
694
+ }
695
+
696
+ // implements REQ-kibi-code-proof-kinds
697
+ function proofContractKindErrors(contract: Record<string, unknown>): string[] {
698
+ const errors: string[] = [];
699
+ const kind = contract.kind;
700
+ if (kind !== undefined && !includes(PROOF_KINDS, kind))
701
+ errors.push(
702
+ `proof_contract.kind must be one of: ${PROOF_KINDS.join(", ")}; received ${JSON.stringify(kind)}`,
703
+ );
704
+ const domain = contract.domain_source;
705
+ if (domain !== undefined) {
706
+ const row = record(domain);
707
+ if (
708
+ !row ||
709
+ !nonEmptyString(row.symbol_id) ||
710
+ (row.export !== undefined && !nonEmptyString(row.export)) ||
711
+ Object.keys(row).some((key) => key !== "symbol_id" && key !== "export")
712
+ )
713
+ errors.push(
714
+ "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",
715
+ );
716
+ } else if (kind === "exhaustive" || kind === "typecheck")
717
+ errors.push(
718
+ `proof_contract.domain_source is required for kind ${String(kind)}: name the symbol the proof reads its domain from`,
719
+ );
720
+ const witness = contract.witness;
721
+ if (witness !== undefined) {
722
+ const row = record(witness);
723
+ if (!row || !nonEmptyString(row.path) || Object.keys(row).length !== 1)
724
+ errors.push(
725
+ "proof_contract.witness must be {path} naming the repository-relative witness file",
726
+ );
727
+ } else if (kind === "typecheck")
728
+ errors.push(
729
+ "proof_contract.witness is required for kind typecheck: name the file the type checker compiles",
730
+ );
731
+ const source = contract.constraint_source;
732
+ if (source !== undefined) {
733
+ const row = record(source);
734
+ const ids = row?.fact_ids;
735
+ if (
736
+ !row ||
737
+ Object.keys(row).length !== 1 ||
738
+ !Array.isArray(ids) ||
739
+ ids.length === 0 ||
740
+ !ids.every(nonEmptyString)
741
+ )
742
+ errors.push(
743
+ "proof_contract.constraint_source must be {fact_ids: [FACT-...]} naming the facts the assumptions come from",
744
+ );
745
+ } else if (
746
+ (kind === "arithmetic" || kind === "smt") &&
747
+ contract.value_source === undefined
748
+ )
749
+ errors.push(
750
+ `proof_contract.constraint_source or value_source is required for kind ${String(kind)}: name the typed facts or code constants its assumptions come from`,
751
+ );
752
+ const valueSource = contract.value_source;
753
+ if (valueSource !== undefined) {
754
+ if (
755
+ !Array.isArray(valueSource) ||
756
+ valueSource.length === 0 ||
757
+ !valueSource.every((entry) => {
758
+ const row = record(entry);
759
+ return (
760
+ row !== null &&
761
+ nonEmptyString(row.symbol_id) &&
762
+ (row.export === undefined || nonEmptyString(row.export)) &&
763
+ Object.keys(row).every(
764
+ (key) => key === "symbol_id" || key === "export",
765
+ )
766
+ );
767
+ })
768
+ )
769
+ errors.push(
770
+ "proof_contract.value_source must be [{symbol_id, export?}] naming the code constants the assumptions read",
771
+ );
772
+ else if (kind !== "arithmetic" && kind !== "smt")
773
+ errors.push(
774
+ `proof_contract.value_source applies only to kind arithmetic or smt, not ${String(kind ?? "e2e")}`,
775
+ );
776
+ }
777
+ const proves = contract.proves;
778
+ if (proves !== undefined) {
779
+ if (
780
+ !Array.isArray(proves) ||
781
+ proves.length === 0 ||
782
+ !proves.every(
783
+ (key) => typeof key === "string" && /^CLAIM-[A-Za-z0-9]+$/.test(key),
784
+ ) ||
785
+ new Set(proves).size !== proves.length
786
+ )
787
+ errors.push(
788
+ "proof_contract.proves must be a non-empty list of distinct claim keys (CLAIM-...) the certificate proves",
789
+ );
790
+ else if (!isCertificateProofKind(kind))
791
+ errors.push(
792
+ `proof_contract.proves applies only to certificate kinds (exhaustive, typecheck, arithmetic, smt), not ${String(kind ?? "e2e")}`,
793
+ );
794
+ }
540
795
  return errors;
541
796
  }
542
797
 
798
+ /**
799
+ * The optional contract fields beyond the v1 core, copied only when present
800
+ * so existing contracts keep their hash.
801
+ */
802
+ // implements REQ-kibi-code-proof-kinds
803
+ export function optionalProofContractFields(
804
+ contract: Record<string, unknown>,
805
+ ): Pick<
806
+ ProofContract,
807
+ | "kind"
808
+ | "domain_source"
809
+ | "witness"
810
+ | "constraint_source"
811
+ | "value_source"
812
+ | "proves"
813
+ > {
814
+ const fields: {
815
+ kind?: ProofKind;
816
+ domain_source?: { symbol_id: string; export?: string };
817
+ witness?: { path: string };
818
+ constraint_source?: { fact_ids: string[] };
819
+ value_source?: { symbol_id: string; export?: string }[];
820
+ proves?: string[];
821
+ } = {};
822
+ if (typeof contract.kind === "string")
823
+ fields.kind = contract.kind as ProofKind;
824
+ const domain = record(contract.domain_source);
825
+ if (domain && typeof domain.symbol_id === "string")
826
+ fields.domain_source = {
827
+ symbol_id: domain.symbol_id,
828
+ ...(typeof domain.export === "string" ? { export: domain.export } : {}),
829
+ };
830
+ const witness = record(contract.witness);
831
+ if (witness && typeof witness.path === "string")
832
+ fields.witness = { path: witness.path };
833
+ const source = record(contract.constraint_source);
834
+ if (source && Array.isArray(source.fact_ids))
835
+ fields.constraint_source = {
836
+ fact_ids: source.fact_ids.filter(
837
+ (id): id is string => typeof id === "string",
838
+ ),
839
+ };
840
+ if (Array.isArray(contract.value_source))
841
+ fields.value_source = contract.value_source
842
+ .map((entry) => record(entry))
843
+ .filter(
844
+ (row): row is Record<string, unknown> =>
845
+ row !== null && typeof row.symbol_id === "string",
846
+ )
847
+ .map((row) => ({
848
+ symbol_id: String(row.symbol_id),
849
+ ...(typeof row.export === "string" ? { export: row.export } : {}),
850
+ }));
851
+ if (Array.isArray(contract.proves))
852
+ fields.proves = contract.proves.filter(
853
+ (key): key is string => typeof key === "string",
854
+ );
855
+ return fields;
856
+ }
857
+
543
858
  export function proofBindingsErrors(value: unknown): string[] {
544
859
  if (!Array.isArray(value))
545
860
  return ["proof_bindings must be an array of binding objects"];
@@ -4,14 +4,33 @@ import {
4
4
  proofContractHash,
5
5
  } from "./proof-fingerprint.js";
6
6
  import {
7
+ PROOF_KINDS,
7
8
  PROOF_RECEIPT_VERSION,
9
+ PROOF_RECEIPT_VERSIONS,
8
10
  PROOF_RESULT_OUTCOMES,
9
11
  PROOF_RUN_OUTCOMES,
10
12
  type ProofContract,
13
+ type ProofKind,
14
+ isCertificateProofKind,
11
15
  } from "./proof-protocol.js";
12
16
 
13
17
  export const PROOF_RECEIPT_MAX_AGE_SECONDS = 7 * 24 * 60 * 60;
14
18
 
19
+ /**
20
+ * How a certificate binds to a claim its contract names in proves: derived
21
+ * (Kibi checked it against the claim's fact; the only verdict that proves),
22
+ * attested (the fact has no derivation; the author vouches) or rejected.
23
+ */
24
+ // implements REQ-kibi-claim-bound-proofs
25
+ export const CLAIM_BINDING_VERDICTS = [
26
+ "derived",
27
+ "attested",
28
+ "rejected",
29
+ ] as const;
30
+
31
+ // implements REQ-kibi-claim-bound-proofs
32
+ export type ClaimBindingVerdict = (typeof CLAIM_BINDING_VERDICTS)[number];
33
+
15
34
  export const PROOF_RECEIPT_OUTCOMES = [
16
35
  "passed",
17
36
  "failed",
@@ -25,7 +44,7 @@ export const PROOF_RECEIPT_OUTCOMES = [
25
44
  export const PROOF_RECEIPT_SCHEMA = {
26
45
  type: "object",
27
46
  description:
28
- "Kibi-derived kibi.proof-receipt.v1. Receipts are never caller-authored; kb_ingest_proof derives them from kibi.proof-run.v1 artifacts.",
47
+ "Kibi-derived kibi.proof-receipt.v2 (kibi.proof-receipt.v1 entries are still read). Receipts are never caller-authored; kb_ingest_proof derives them from kibi.proof-run.v1 artifacts.",
29
48
  required: [
30
49
  "version",
31
50
  "receipt_id",
@@ -47,7 +66,7 @@ export const PROOF_RECEIPT_SCHEMA = {
47
66
  "proof_results",
48
67
  ],
49
68
  properties: {
50
- version: { type: "string", const: PROOF_RECEIPT_VERSION },
69
+ version: { type: "string", enum: [...PROOF_RECEIPT_VERSIONS] },
51
70
  receipt_id: {
52
71
  type: "string",
53
72
  pattern: "^PR-[A-Za-z0-9][A-Za-z0-9._:-]{7,127}$",
@@ -144,6 +163,33 @@ export const PROOF_RECEIPT_SCHEMA = {
144
163
  additionalProperties: false,
145
164
  },
146
165
  },
166
+ kind: { type: "string", enum: [...PROOF_KINDS] },
167
+ evidence_level: { type: "string", enum: ["proved", "tested"] },
168
+ certificate: { type: "object" },
169
+ certificate_digest: { type: "string", pattern: "^[a-f0-9]{64}$" },
170
+ certificate_rejection: { type: "string", minLength: 1 },
171
+ claim_bindings: {
172
+ type: "array",
173
+ description:
174
+ "Certificate kinds: how the certificate binds to each claim its contract names in proves, judged at ingest. derived means Kibi derived the certificate's obligation from the claim's grounding fact and the certificate satisfies it; attested means no derivation exists and the author vouches for it (never proved); rejected names why.",
175
+ items: {
176
+ type: "object",
177
+ required: ["claim_key", "binding"],
178
+ properties: {
179
+ claim_key: { type: "string", minLength: 1 },
180
+ requirement_id: { type: "string", minLength: 1 },
181
+ fact_id: { type: "string", minLength: 1 },
182
+ binding: {
183
+ type: "string",
184
+ enum: [...CLAIM_BINDING_VERDICTS],
185
+ },
186
+ scope: { type: "string", enum: ["code", "intent"] },
187
+ obligation: { type: "object" },
188
+ reason: { type: "string", minLength: 1 },
189
+ },
190
+ additionalProperties: false,
191
+ },
192
+ },
147
193
  gaps: {
148
194
  type: "array",
149
195
  items: {
@@ -162,7 +208,7 @@ export const PROOF_RECEIPT_SCHEMA = {
162
208
  } as const;
163
209
 
164
210
  export type ProofReceipt = Readonly<{
165
- version: typeof PROOF_RECEIPT_VERSION;
211
+ version: (typeof PROOF_RECEIPT_VERSIONS)[number];
166
212
  receipt_id: string;
167
213
  test_id: string;
168
214
  scope: "unit" | "integration" | "end_to_end";
@@ -201,6 +247,27 @@ export type ProofReceipt = Readonly<{
201
247
  readonly target: string;
202
248
  readonly reason: string;
203
249
  }[];
250
+ /** v2: what the contract's checker establishes. */
251
+ kind?: ProofKind;
252
+ /** v2: proved only for a passed certificate kind whose certificate re-checked. */
253
+ evidence_level?: "proved" | "tested";
254
+ certificate?: Readonly<Record<string, unknown>>;
255
+ certificate_digest?: string;
256
+ certificate_rejection?: string;
257
+ /** Certificate kinds: the binding to each claim the contract names in proves. */
258
+ claim_bindings?: readonly ClaimBinding[];
259
+ }>;
260
+
261
+ /** How one certificate binds to one requirement claim, judged at ingest. */
262
+ // implements REQ-kibi-claim-bound-proofs
263
+ export type ClaimBinding = Readonly<{
264
+ claim_key: string;
265
+ requirement_id?: string;
266
+ fact_id?: string;
267
+ binding: ClaimBindingVerdict;
268
+ scope?: "code" | "intent";
269
+ obligation?: Readonly<Record<string, unknown>>;
270
+ reason?: string;
204
271
  }>;
205
272
 
206
273
  export function finishedAtPrecedesStartedAt(
@@ -285,14 +352,17 @@ function validFingerprintComponents(value: unknown): boolean {
285
352
  );
286
353
  }
287
354
 
288
- /** Structural validation of one kibi.proof-receipt.v1 entry. */
355
+ /** Structural validation of one kibi.proof-receipt.v1 or v2 entry. */
289
356
  export function validProofReceiptShape(
290
357
  testId: string,
291
358
  receipt: unknown,
292
359
  ): boolean {
293
360
  const row = isRecord(receipt) ? receipt : null;
294
361
  if (!row) return false;
295
- if (row.version !== PROOF_RECEIPT_VERSION) return false;
362
+ if (!(PROOF_RECEIPT_VERSIONS as readonly unknown[]).includes(row.version))
363
+ return false;
364
+ if (row.version === PROOF_RECEIPT_VERSION && !validV2Fields(row))
365
+ return false;
296
366
  if (
297
367
  typeof row.receipt_id !== "string" ||
298
368
  !/^PR-[A-Za-z0-9][A-Za-z0-9._:-]{7,127}$/.test(row.receipt_id)
@@ -358,9 +428,59 @@ export function validProofReceiptShape(
358
428
  return !finishedAtPrecedesStartedAt(startedAt, finishedAt);
359
429
  }
360
430
 
431
+ // implements REQ-kibi-code-proof-kinds
432
+ function validV2Fields(row: Record<string, unknown>): boolean {
433
+ if (!(PROOF_KINDS as readonly unknown[]).includes(row.kind)) return false;
434
+ if (row.evidence_level !== "proved" && row.evidence_level !== "tested")
435
+ return false;
436
+ if (
437
+ row.evidence_level === "proved" &&
438
+ (row.outcome !== "passed" ||
439
+ !isCertificateProofKind(row.kind) ||
440
+ !isRecord(row.certificate) ||
441
+ !hex64(row.certificate_digest) ||
442
+ row.certificate_rejection !== undefined)
443
+ )
444
+ return false;
445
+ if (row.certificate !== undefined && !isRecord(row.certificate)) return false;
446
+ if (row.certificate_digest !== undefined && !hex64(row.certificate_digest))
447
+ return false;
448
+ if (
449
+ row.certificate_rejection !== undefined &&
450
+ !nonEmptyString(row.certificate_rejection)
451
+ )
452
+ return false;
453
+ if (
454
+ row.claim_bindings !== undefined &&
455
+ !validClaimBindings(row.claim_bindings)
456
+ )
457
+ return false;
458
+ return true;
459
+ }
460
+
461
+ // implements REQ-kibi-claim-bound-proofs
462
+ function validClaimBindings(value: unknown): boolean {
463
+ return (
464
+ Array.isArray(value) &&
465
+ value.every(
466
+ (entry) =>
467
+ isRecord(entry) &&
468
+ nonEmptyString(entry.claim_key) &&
469
+ (CLAIM_BINDING_VERDICTS as readonly unknown[]).includes(
470
+ entry.binding,
471
+ ) &&
472
+ (entry.scope === undefined ||
473
+ entry.scope === "code" ||
474
+ entry.scope === "intent") &&
475
+ (entry.obligation === undefined || isRecord(entry.obligation)) &&
476
+ (entry.reason === undefined || nonEmptyString(entry.reason)),
477
+ )
478
+ );
479
+ }
480
+
361
481
  /**
362
482
  * Full-history validation for proof_receipts: unique ids, per-test binding,
363
- * supported scope, ordered timestamps, and structurally valid v1 entries.
483
+ * supported scope, ordered timestamps, and structurally valid v1 or v2 entries.
364
484
  */
365
485
  export function proofReceiptHistoryErrors(
366
486
  testId: string,
@@ -388,7 +508,7 @@ export function proofReceiptHistoryErrors(
388
508
  }
389
509
  if (!validProofReceiptShape(testId, receipt)) {
390
510
  errors.push(
391
- `${prefix} must be a structurally valid kibi.proof-receipt.v1 bound to '${testId}'`,
511
+ `${prefix} must be a structurally valid kibi.proof-receipt.v2 (or v1) bound to '${testId}'`,
392
512
  );
393
513
  continue;
394
514
  }
@@ -17,6 +17,7 @@
17
17
  */
18
18
 
19
19
  import { ENTITY_ORIGIN_SCHEMA } from "../entity-origin.js";
20
+ import { EVIDENCE_LEVELS } from "../evidence-levels.js";
20
21
  import {
21
22
  PROOF_BINDINGS_SCHEMA,
22
23
  PROOF_CONTRACT_SCHEMA,
@@ -364,6 +365,12 @@ const entitySchema: Record<string, unknown> = {
364
365
  description:
365
366
  "Requirement and ADR only. How firmly the decision was made. firm: a human stated it as a rule; it needs a ref (origin.ref, or approval_ref on a requirement) to their words, and only a human may change it. default: a delegated or agent choice; a later agent may supersede it with evidence. exploratory: a flagged guess, expected to be revisited. When absent, it reads as default if an agent wrote the entity (origin.kind agent) and as firm otherwise (a person's, imported or migrated decision); set it explicitly when recording a decision.",
366
367
  },
368
+ required_evidence: {
369
+ type: "string",
370
+ enum: [...EVIDENCE_LEVELS],
371
+ description:
372
+ "Requirement-only. The weakest evidence level this current requirement accepts; the evidence-floor check rule fails while its computed evidence level is lower. proved: a re-checkable certificate covers every case. tested: fresh passing E2E receipts cover every linked scenario. asserted: a person stands behind it. unverified: no floor. When absent, it is tested for a firm requirement and unverified otherwise.",
373
+ },
367
374
  expects: {
368
375
  type: "string",
369
376
  enum: ["success", "rejection", "error"],
@@ -543,8 +550,17 @@ const entitySchema: Record<string, unknown> = {
543
550
  subject_key: { type: "string" },
544
551
  property_key: { type: "string" },
545
552
  operator: { type: "string", enum: ["eq", "neq", "lt", "lte", "gt", "gte"] },
546
- value_type: { type: "string", enum: ["string", "int", "number", "bool"] },
553
+ value_type: {
554
+ type: "string",
555
+ enum: ["string", "int", "number", "bool", "set"],
556
+ },
547
557
  value_string: { type: "string" },
558
+ value_set: {
559
+ type: "array",
560
+ items: { type: "string", minLength: 1 },
561
+ minItems: 1,
562
+ uniqueItems: true,
563
+ },
548
564
  value_int: { type: "integer" },
549
565
  value_number: { type: "number" },
550
566
  value_bool: { type: "boolean" },
@@ -643,6 +659,7 @@ const entitySchema: Record<string, unknown> = {
643
659
  { required: ["value_int"] },
644
660
  { required: ["value_number"] },
645
661
  { required: ["value_bool"] },
662
+ { required: ["value_set"] },
646
663
  { required: ["unit"] },
647
664
  { required: ["scope"] },
648
665
  { required: ["polarity"] },
@@ -715,6 +732,7 @@ const entitySchema: Record<string, unknown> = {
715
732
  { required: ["approval_ref"] },
716
733
  { required: ["rationale"] },
717
734
  { required: ["exempts_claims"] },
735
+ { required: ["required_evidence"] },
718
736
  ],
719
737
  },
720
738
  },
@@ -2,7 +2,7 @@
2
2
  id: kibi-bootstrap
3
3
  name: kibi-bootstrap
4
4
  description: "Use for any Kibi bootstrap or onboarding task: seeding a new or thin knowledge base; reviewing a bootstrap or onboarding plan, preview, or evidence; judging approval readiness or coverage; diagnosing a blocked, partial, or failed bootstrap or its repair; applying an approved bootstrap plan; or asking the human which knowledge sources hold intent. Covers kb_status first, source interview, cited intent claims, read-only kb_plan_bootstrap preview, explicit approval, exact-plan kb_apply_plan, and repair-safe close-out."
5
- version: 3.16.0
5
+ version: 3.17.0
6
6
  kibiCompatibility: ">=1.0.0"
7
7
  tags:
8
8
  - kibi
@@ -43,7 +43,7 @@ Seed branch-local Kibi knowledge from cited product intent, without creating a p
43
43
  9. **Read back** with `kb_query` and `kb_search` to confirm writes and citations.
44
44
  10. **Close out** with `kb_check`, then `kb_status`.
45
45
  11. **Deepen.** Bootstrap is complete; the KB is now half-way, holding cited `req` entries and review facts but no scenarios, tests or predicates. Load `kibi-usage` and continue in the normal Kibi workflow, one area at a time, telling the human what you author:
46
- - **Unplanned claims.** For every claim suppressed as `invalid_write` and every `sourceOnlySignals` entry ("Author requirement …"), restate the claim's statement and citation (`sourceId:reference`), model it with `kb_model` (`mode: "requirement"`, or `mode: "predicates"` for domain claims), and write the result with `kb_upsert` (`dryRun: true` first) with `origin: {kind: "import", ref: "<sourceId:reference>"}` and `firmness: "firm"`, as the plan does for the claims it writes. Without an explicit origin `kb_upsert` records the requirement as the agent's own `default` choice, which a later agent may supersede without asking.
46
+ - **Unplanned claims.** For every claim suppressed as `invalid_write` and every `sourceOnlySignals` entry ("Author requirement …"), restate the claim's statement and citation (`sourceId:reference`), model it with `kb_model` (`mode: "requirement"`, or `mode: "predicates"` for domain claims), and write the result with `kb_upsert` (`dryRun: true` first) with `origin: {kind: "import", ref: "<sourceId:reference>"}` and `firmness: "firm"` and `required_evidence: "asserted"`, as the plan does for the claims it writes; raise the floor (drop `required_evidence`) only once an end-to-end proof covers the requirement. Without an explicit origin `kb_upsert` records the requirement as the agent's own `default` choice, which a later agent may supersede without asking.
47
47
  - **Scenarios.** Write scenarios from the cited ticket's acceptance criteria, one scenario per criterion, not bulk drafts from the requirement title; ask the human when the source states none. Give each a plain title, the scenario prose in `document.body` (never in `properties`), and `assumes` links to the `property_value` facts whose values the scenario relies on. Set `expects` only when the scenario links `assumes` facts (or its criterion names concrete values that become them); `expects` without `assumes` only yields a feasibility-unknown warning, so a draft tagged `needs-human-review` omits `expects`. Then link the requirement with `specified_by` (upsert the `req` with its stored `title`, a `status` and that relationship only). Example: criterion "Given an annotation in draft state, when the user deletes it, the draft is cleared" becomes `{"type":"scenario","id":"SCEN-annotation-delete-clears-draft","properties":{"title":"Deleting a draft annotation clears the draft","status":"active","expects":"success"},"document":{"body":"Given an annotation in draft state, when the user deletes it, then the draft is cleared and nothing is published.\n\nThe acceptance criterion comes from the cited ticket; reviewers asked for it so a deleted draft never reappears after reload.\n"},"relationships":[{"type":"assumes","from":"SCEN-annotation-delete-clears-draft","to":"FACT-annotation-state-draft"}]}`, where the assumed fact is a `property_value` (`annotation.state` `eq` `draft`). Link existing tests that exercise it; never invent test evidence.
48
48
  - **Predicates.** Run `kb_model` with `mode: "predicates"` and `requirementId` on each persisted requirement and apply a returned plan with `requires_predicate` to its `relationshipTarget` (the planned `FACT-PRED-…` id, never a `SUGGEST-…` candidate id), or record the `review:ontology-gap` observation it returns, with its prose in `document.body`. A non-empty `existingGrounding` means the bootstrap already grounded that claim: on `replace_grounding` leave it unless the human wants the `replacementPlan` swap; on `provide_argument_bindings` retry with the listed arguments bound; on `record_ontology_gap` still write the returned gap observation, which is not a grounding link. Count what `kb_query` shows afterwards, not the calls you made.
49
49
  - **Unrecorded ambiguity.** Record any conflict or open question you found but did not declare in step 3 as a cited `fact_kind: observation` tagged `review:conflict` or `review:open-question`.
@@ -2,7 +2,7 @@
2
2
  id: kibi-commit-review
3
3
  name: kibi-commit-review
4
4
  description: "Use when kibi check --staged or the Kibi pre-commit hook blocks a commit (kibi_impact_evidence_missing, symbols_manifest_stale, symbol_granularity_violation, symbol-coverage, kibi check-generated drift, Staged impact review failed), or when preparing a commit or pull-request impact review. Covers reading the per-file Detail lines, authoring .kb/symbols.yaml symbol entries through kb_upsert, kibi sync --refresh-symbol-coordinates, staging the tracked Kibi evidence with git add, kb_prepare_impact_review for a staged or diff scope, the kibi signoff requirements summary to show before a commit, and how merge commits and migration renames are judged."
5
- version: 1.2.0
5
+ version: 1.2.2
6
6
  kibiCompatibility: ">=1.0.0"
7
7
  tags:
8
8
  - kibi
@@ -85,8 +85,9 @@ requirement with its statement (before and after for a rewrite), firmness,
85
85
  origin, scenarios and proof state. Put it in your reply unchanged (in the
86
86
  messaging tool's message when replies go through one), then add one or two
87
87
  sentences on why the requirements changed. Offer the full page with
88
- `kibi signoff --format html --open`, or attach or publish
89
- `.kb/briefs/signoff/latest.html` when your host can carry a file or a page;
88
+ `kibi signoff --format html --open`, or publish `.kb/briefs/signoff/latest.html`
89
+ as a rendered page when your host has a page tool (the Artifact tool in Claude
90
+ apps); never attach the `.html` as a file, which chat apps show as raw source;
90
91
  past 15 requirements the Markdown stops and only the page lists them all.
91
92
  Host details: `kibi-decisions`, `resources/signoff-views.md`. `--no-proof` skips the proof lookup, which reads coverage and is slow
92
93
  on a large knowledge base. The summary is not an approval: never set