kibi-cli 2.38.0 → 2.40.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 (222) hide show
  1. package/dist/cli-json-command.d.ts.map +1 -1
  2. package/dist/cli-json-command.js +4 -0
  3. package/dist/cli-register-foundation.js +2 -2
  4. package/dist/cli-register-reporting.d.ts.map +1 -1
  5. package/dist/cli-register-reporting.js +1 -0
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +3 -0
  8. package/dist/commands/check.d.ts.map +1 -1
  9. package/dist/commands/check.js +33 -9
  10. package/dist/commands/coverage.d.ts +1 -0
  11. package/dist/commands/coverage.d.ts.map +1 -1
  12. package/dist/commands/coverage.js +40 -0
  13. package/dist/commands/doctor.d.ts +5 -0
  14. package/dist/commands/doctor.d.ts.map +1 -1
  15. package/dist/commands/doctor.js +29 -0
  16. package/dist/commands/init.d.ts.map +1 -1
  17. package/dist/commands/init.js +4 -0
  18. package/dist/commands/migrate-plan-record.d.ts +18 -0
  19. package/dist/commands/migrate-plan-record.d.ts.map +1 -0
  20. package/dist/commands/migrate-plan-record.js +112 -0
  21. package/dist/commands/migrate.d.ts +11 -2
  22. package/dist/commands/migrate.d.ts.map +1 -1
  23. package/dist/commands/migrate.js +60 -8
  24. package/dist/commands/prove.d.ts.map +1 -1
  25. package/dist/commands/prove.js +18 -3
  26. package/dist/commands/sync/manifest.d.ts.map +1 -1
  27. package/dist/commands/sync/manifest.js +17 -4
  28. package/dist/commands/sync/persistence.d.ts.map +1 -1
  29. package/dist/commands/sync/persistence.js +6 -0
  30. package/dist/commands/sync.d.ts.map +1 -1
  31. package/dist/commands/sync.js +8 -0
  32. package/dist/commands/telemetry.d.ts.map +1 -1
  33. package/dist/commands/telemetry.js +12 -2
  34. package/dist/extractors/markdown.d.ts +6 -0
  35. package/dist/extractors/markdown.d.ts.map +1 -1
  36. package/dist/extractors/markdown.js +21 -0
  37. package/dist/extractors/symbol-title-match.d.ts +31 -0
  38. package/dist/extractors/symbol-title-match.d.ts.map +1 -0
  39. package/dist/extractors/symbol-title-match.js +133 -0
  40. package/dist/extractors/symbols-coordinator.d.ts.map +1 -1
  41. package/dist/extractors/symbols-coordinator.js +81 -12
  42. package/dist/operations/bootstrap/discovery-evidence.d.ts.map +1 -1
  43. package/dist/operations/bootstrap/discovery-evidence.js +44 -2
  44. package/dist/operations/bootstrap/discovery.d.ts.map +1 -1
  45. package/dist/operations/bootstrap/discovery.js +1 -0
  46. package/dist/operations/bootstrap/guidance-actions.d.ts.map +1 -1
  47. package/dist/operations/bootstrap/guidance-actions.js +12 -1
  48. package/dist/operations/bootstrap/plugin-offers.d.ts +7 -1
  49. package/dist/operations/bootstrap/plugin-offers.d.ts.map +1 -1
  50. package/dist/operations/bootstrap/plugin-offers.js +73 -3
  51. package/dist/operations/modeling/logic-modeling.d.ts.map +1 -1
  52. package/dist/operations/modeling/logic-modeling.js +2 -1
  53. package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
  54. package/dist/operations/modeling/model-requirement.js +2 -1
  55. package/dist/operations/mutation/symbol-refresh.d.ts +2 -0
  56. package/dist/operations/mutation/symbol-refresh.d.ts.map +1 -1
  57. package/dist/operations/mutation/symbol-refresh.js +6 -1
  58. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  59. package/dist/operations/mutation/upsert.js +7 -0
  60. package/dist/operations/planning/compile-intent.d.ts.map +1 -1
  61. package/dist/operations/planning/compile-intent.js +2 -1
  62. package/dist/operations/proof/claim-bindings.d.ts +11 -0
  63. package/dist/operations/proof/claim-bindings.d.ts.map +1 -1
  64. package/dist/operations/proof/claim-bindings.js +144 -1
  65. package/dist/operations/proof/code-certificates.d.ts +10 -3
  66. package/dist/operations/proof/code-certificates.d.ts.map +1 -1
  67. package/dist/operations/proof/code-certificates.js +65 -13
  68. package/dist/operations/proof/code-languages.d.ts +104 -0
  69. package/dist/operations/proof/code-languages.d.ts.map +1 -0
  70. package/dist/operations/proof/code-languages.js +119 -0
  71. package/dist/operations/proof/code-models.d.ts +2 -0
  72. package/dist/operations/proof/code-models.d.ts.map +1 -1
  73. package/dist/operations/proof/code-models.js +11 -5
  74. package/dist/operations/proof/code-runner.d.ts +12 -9
  75. package/dist/operations/proof/code-runner.d.ts.map +1 -1
  76. package/dist/operations/proof/code-runner.js +81 -38
  77. package/dist/operations/proof/code-scope.d.ts +8 -0
  78. package/dist/operations/proof/code-scope.d.ts.map +1 -1
  79. package/dist/operations/proof/code-scope.js +30 -1
  80. package/dist/operations/proof/explain.d.ts +76 -0
  81. package/dist/operations/proof/explain.d.ts.map +1 -1
  82. package/dist/operations/proof/explain.js +228 -0
  83. package/dist/operations/proof/ingest-proof.d.ts +2 -0
  84. package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
  85. package/dist/operations/proof/ingest-proof.js +1 -0
  86. package/dist/operations/proof/java-package-shadow.d.ts +14 -0
  87. package/dist/operations/proof/java-package-shadow.d.ts.map +1 -0
  88. package/dist/operations/proof/java-package-shadow.js +389 -0
  89. package/dist/operations/proof/prolog-evaluator.d.ts +14 -0
  90. package/dist/operations/proof/prolog-evaluator.d.ts.map +1 -0
  91. package/dist/operations/proof/prolog-evaluator.js +247 -0
  92. package/dist/operations/proof/prolog-source-reader.d.ts +20 -0
  93. package/dist/operations/proof/prolog-source-reader.d.ts.map +1 -0
  94. package/dist/operations/proof/prolog-source-reader.js +1123 -0
  95. package/dist/operations/proof/source-code-readers.d.ts +6 -0
  96. package/dist/operations/proof/source-code-readers.d.ts.map +1 -1
  97. package/dist/operations/proof/source-code-readers.js +879 -75
  98. package/dist/operations/semantic-advisor/analyze-prose.d.ts +9 -1
  99. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  100. package/dist/operations/semantic-advisor/analyze-prose.js +21 -0
  101. package/dist/operations/semantic-advisor/case-preview.d.ts +24 -0
  102. package/dist/operations/semantic-advisor/case-preview.d.ts.map +1 -0
  103. package/dist/operations/semantic-advisor/case-preview.js +216 -0
  104. package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
  105. package/dist/operations/semantic-advisor/shared.js +3 -0
  106. package/dist/operations/semantic-advisor/types.d.ts +23 -0
  107. package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
  108. package/dist/plugins/approved-source-analyzers.generated.d.ts +15 -34
  109. package/dist/plugins/approved-source-analyzers.generated.d.ts.map +1 -1
  110. package/dist/plugins/approved-source-analyzers.generated.js +15 -34
  111. package/dist/plugins/plugin-install-check.d.ts +21 -0
  112. package/dist/plugins/plugin-install-check.d.ts.map +1 -0
  113. package/dist/plugins/plugin-install-check.js +62 -0
  114. package/dist/plugins/proof-reference-extractors.d.ts +20 -0
  115. package/dist/plugins/proof-reference-extractors.d.ts.map +1 -0
  116. package/dist/plugins/proof-reference-extractors.js +104 -0
  117. package/dist/plugins/reference-language-suggestion.d.ts +51 -0
  118. package/dist/plugins/reference-language-suggestion.d.ts.map +1 -0
  119. package/dist/plugins/reference-language-suggestion.js +277 -0
  120. package/dist/plugins/registry.d.ts.map +1 -1
  121. package/dist/plugins/registry.js +3 -1
  122. package/dist/plugins/source-analysis-service.d.ts.map +1 -1
  123. package/dist/plugins/source-analysis-service.js +4 -0
  124. package/dist/plugins/source-change-analysis.d.ts +26 -1
  125. package/dist/plugins/source-change-analysis.d.ts.map +1 -1
  126. package/dist/plugins/source-change-analysis.js +77 -5
  127. package/dist/plugins/source-classification.d.ts +2 -2
  128. package/dist/plugins/source-classification.d.ts.map +1 -1
  129. package/dist/plugins/source-classification.js +45 -1
  130. package/dist/public/operations/catalog.d.ts +62 -7
  131. package/dist/public/operations/catalog.d.ts.map +1 -1
  132. package/dist/public/operations/check-executor.d.ts.map +1 -1
  133. package/dist/public/operations/check-executor.js +3 -0
  134. package/dist/public/operations/evidence-floor.d.ts +8 -0
  135. package/dist/public/operations/evidence-floor.d.ts.map +1 -1
  136. package/dist/public/operations/evidence-floor.js +19 -1
  137. package/dist/public/operations/repair-plan.d.ts +46 -0
  138. package/dist/public/operations/repair-plan.d.ts.map +1 -1
  139. package/dist/public/operations/repair-plan.js +110 -1
  140. package/dist/public/operations/schema6-check-actions.js +1 -1
  141. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  142. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  143. package/dist/public/operations/specs/check-rules.generated.js +3 -1
  144. package/dist/public/operations/specs/check.d.ts +1 -1
  145. package/dist/public/operations/specs/mutation-schemas.d.ts +61 -6
  146. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  147. package/dist/public/operations/specs/mutation-schemas.js +30 -0
  148. package/dist/public/operations/specs/reporting.d.ts +8 -0
  149. package/dist/public/operations/specs/reporting.d.ts.map +1 -1
  150. package/dist/public/operations/specs/reporting.js +26 -3
  151. package/dist/public/operations/specs/semantic.d.ts.map +1 -1
  152. package/dist/public/operations/specs/semantic.js +2 -1
  153. package/dist/public/operations/specs/upsert.d.ts +61 -6
  154. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  155. package/dist/public/operations/symbol-coordinates-check.d.ts +11 -0
  156. package/dist/public/operations/symbol-coordinates-check.d.ts.map +1 -0
  157. package/dist/public/operations/symbol-coordinates-check.js +66 -0
  158. package/dist/public/proof-protocol.d.ts +31 -6
  159. package/dist/public/proof-protocol.d.ts.map +1 -1
  160. package/dist/public/proof-protocol.js +45 -15
  161. package/dist/public/proof-sources.d.ts +4 -2
  162. package/dist/public/proof-sources.d.ts.map +1 -1
  163. package/dist/public/proof-sources.js +43 -4
  164. package/dist/public/schemas/entity.d.ts.map +1 -1
  165. package/dist/public/schemas/entity.js +59 -0
  166. package/dist/public/skills/kibi-commit-review/SKILL.md +6 -2
  167. package/dist/public/skills/kibi-decisions/SKILL.md +7 -2
  168. package/dist/public/skills/kibi-decisions/resources/signoff-views.md +3 -1
  169. package/dist/public/skills/kibi-usage/SKILL.md +14 -3
  170. package/dist/public/skills/kibi-usage/resources/prolog-proofs.md +207 -0
  171. package/dist/public/skills/kibi-usage/resources/proof.md +44 -3
  172. package/dist/schemas/entity.schema.json +126 -6
  173. package/dist/search-answer.d.ts +3 -2
  174. package/dist/search-answer.d.ts.map +1 -1
  175. package/dist/search-answer.js +56 -3
  176. package/dist/traceability/analysis-gate.d.ts +3 -1
  177. package/dist/traceability/analysis-gate.d.ts.map +1 -1
  178. package/dist/traceability/analysis-gate.js +9 -1
  179. package/dist/traceability/impact-knowledge.d.ts.map +1 -1
  180. package/dist/traceability/impact-knowledge.js +2 -0
  181. package/dist/traceability/staged-file-coverage.d.ts.map +1 -1
  182. package/dist/traceability/staged-file-coverage.js +7 -2
  183. package/dist/traceability/symbol-extract.d.ts +17 -0
  184. package/dist/traceability/symbol-extract.d.ts.map +1 -1
  185. package/dist/traceability/symbol-extract.js +69 -15
  186. package/dist/traceability/temp-kb.d.ts.map +1 -1
  187. package/dist/traceability/temp-kb.js +11 -1
  188. package/dist/traceability/validate.d.ts.map +1 -1
  189. package/dist/traceability/validate.js +5 -7
  190. package/dist/types/entities.d.ts +12 -0
  191. package/dist/types/entities.d.ts.map +1 -1
  192. package/dist/usage-telemetry.d.ts +9 -0
  193. package/dist/usage-telemetry.d.ts.map +1 -1
  194. package/dist/usage-telemetry.js +50 -4
  195. package/dist/utils/first-sentence.d.ts +9 -0
  196. package/dist/utils/first-sentence.d.ts.map +1 -0
  197. package/dist/utils/first-sentence.js +52 -0
  198. package/dist/utils/rule-registry.generated.d.ts +11 -0
  199. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  200. package/dist/utils/rule-registry.generated.js +13 -0
  201. package/package.json +5 -5
  202. package/schema/entities.pl +12 -0
  203. package/src/public/operations/check-executor.ts +8 -0
  204. package/src/public/operations/evidence-floor.ts +29 -1
  205. package/src/public/operations/repair-plan.ts +152 -1
  206. package/src/public/operations/schema6-check-actions.ts +1 -1
  207. package/src/public/operations/specs/check-rules.generated.ts +3 -1
  208. package/src/public/operations/specs/mutation-schemas.ts +34 -0
  209. package/src/public/operations/specs/reporting.ts +38 -3
  210. package/src/public/operations/specs/semantic.ts +2 -1
  211. package/src/public/operations/symbol-coordinates-check.ts +79 -0
  212. package/src/public/proof-protocol-types.d.ts +22 -5
  213. package/src/public/proof-protocol.ts +78 -19
  214. package/src/public/proof-sources.ts +51 -3
  215. package/src/public/schemas/entity.ts +65 -0
  216. package/src/public/skills/kibi-commit-review/SKILL.md +6 -2
  217. package/src/public/skills/kibi-decisions/SKILL.md +7 -2
  218. package/src/public/skills/kibi-decisions/resources/signoff-views.md +3 -1
  219. package/src/public/skills/kibi-usage/SKILL.md +14 -3
  220. package/src/public/skills/kibi-usage/resources/prolog-proofs.md +207 -0
  221. package/src/public/skills/kibi-usage/resources/proof.md +44 -3
  222. package/src/schemas/entity.schema.json +126 -6
@@ -279,21 +279,29 @@ export const PROOF_RUN_ARTIFACT_SCHEMA = {
279
279
  additionalProperties: false,
280
280
  } as const;
281
281
 
282
+ const ARG_SCHEMA = {
283
+ type: "integer",
284
+ minimum: 1,
285
+ description:
286
+ "A SWI-Prolog predicate's argument (1-based) whose solutions Kibi reads, when the predicate takes more than one argument (operator/2 with arg 1 lists each operator's name).",
287
+ } as const;
288
+
282
289
  const SOURCE_REFERENCE_SCHEMA = {
283
290
  type: "object",
284
291
  required: ["symbol_id"],
285
292
  properties: {
286
293
  symbol_id: { type: "string", minLength: 1 },
287
294
  export: { type: "string", minLength: 1 },
295
+ arg: ARG_SCHEMA,
288
296
  },
289
297
  additionalProperties: false,
290
298
  } as const;
291
299
 
292
- // implements REQ-kibi-source-proof-kinds
300
+ // implements REQ-kibi-source-proof-kinds, REQ-kibi-prolog-source-readers
293
301
  const SOURCE_SPEC_SCHEMA = {
294
302
  type: "object",
295
303
  description:
296
- "A project source Kibi reads by itself. reader json or yaml: {file, path?, select?: keys|values|items}. glob: {pattern, capture?, ignore?} (capture true reads what each * matched). openapi: {file, select?: operations|unsecured_operations|security_schemes|responses}. references: {files, extract: env|imports|calls|string_args|thrown|property, callee?, key?, ignore?}. schema: {format: drizzle|prisma|sql, file (drizzle, prisma) or files (sql migrations), exports?, table?, select?: tables|columns|required_columns|nullable_columns|foreign_keys}. routes: {file, export, framework?: hono|express, path_prefix?, names_from?, select?: routes|middleware}. validator: {file, export, select?: fields|required_fields|optional_fields}. Paths are repository-relative. A member Kibi cannot read statically fails the read with its location.",
304
+ "A project source Kibi reads by itself. reader json or yaml: {file, path?, select?: keys|values|items}. glob: {pattern, capture?, ignore?} (capture true reads what each * matched). openapi: {file, select?: operations|unsecured_operations|security_schemes|responses}. references: {files, extract: env|imports|calls|string_args|thrown|property, callee?, key?, ignore?} over TypeScript, JavaScript, Python and SWI-Prolog files. schema: {format: drizzle|prisma|sql, file (drizzle, prisma) or files (sql migrations), exports?, table?, select?: tables|columns|required_columns|nullable_columns|foreign_keys}. routes: {file, export, framework?: hono|express, path_prefix?, names_from?, select?: routes|middleware}. validator: {file, export, select?: fields|required_fields|optional_fields}. prolog: {file, functor: Name/Arity, arg?} reads one argument of every fact with that functor in a SWI-Prolog file (requires/1 in pack.pl), without running it. Paths are repository-relative. A member Kibi cannot read statically fails the read with its location.",
297
305
  required: ["reader"],
298
306
  properties: {
299
307
  reader: { type: "string", enum: [...SOURCE_READERS] },
@@ -382,6 +390,7 @@ export const PROOF_CONTRACT_SCHEMA = {
382
390
  description:
383
391
  "exhaustive: when the export is a list of records, the field of each record that names a domain member (a catalog's name).",
384
392
  },
393
+ arg: ARG_SCHEMA,
385
394
  },
386
395
  additionalProperties: false,
387
396
  },
@@ -411,6 +420,7 @@ export const PROOF_CONTRACT_SCHEMA = {
411
420
  properties: {
412
421
  symbol_id: { type: "string", minLength: 1 },
413
422
  export: { type: "string", minLength: 1 },
423
+ arg: ARG_SCHEMA,
414
424
  source: SOURCE_SPEC_SCHEMA,
415
425
  measure: {
416
426
  type: "string",
@@ -819,17 +829,30 @@ function proofContractKindErrors(contract: Record<string, unknown>): string[] {
819
829
  !nonEmptyString(row.symbol_id) ||
820
830
  (row.export !== undefined && !nonEmptyString(row.export)) ||
821
831
  (row.field !== undefined && !nonEmptyString(row.field)) ||
832
+ (row.arg !== undefined && !isArgIndex(row.arg)) ||
822
833
  Object.keys(row).some(
823
- (key) => key !== "symbol_id" && key !== "export" && key !== "field",
834
+ (key) =>
835
+ key !== "symbol_id" &&
836
+ key !== "export" &&
837
+ key !== "field" &&
838
+ key !== "arg",
824
839
  )
825
840
  )
826
841
  errors.push(
827
- "proof_contract.domain_source must be {symbol_id, export?, field?} naming the symbol that defines the domain, the export to read when its title is not the export name, and the record field that names each member",
842
+ "proof_contract.domain_source must be {symbol_id, export?, field?, arg?} naming the symbol that defines the domain, the export to read when its title is not the export name, the record field that names each member, and for a SWI-Prolog predicate the argument (1-based) that names it",
843
+ );
844
+ else if (row.field !== undefined && row.arg !== undefined)
845
+ errors.push(
846
+ "proof_contract.domain_source takes field (a record field) or arg (a Prolog argument), not both",
828
847
  );
829
848
  else if (row.field !== undefined && kind !== "exhaustive")
830
849
  errors.push(
831
850
  `proof_contract.domain_source.field applies only to kind exhaustive, not ${String(kind ?? "e2e")}`,
832
851
  );
852
+ else if (row.arg !== undefined && kind !== "exhaustive")
853
+ errors.push(
854
+ `proof_contract.domain_source.arg applies only to kind exhaustive, not ${String(kind ?? "e2e")}`,
855
+ );
833
856
  } else if (kind === "exhaustive" || kind === "typecheck")
834
857
  errors.push(
835
858
  `proof_contract.domain_source is required for kind ${String(kind)}: name the symbol the proof reads its domain from`,
@@ -878,9 +901,13 @@ function proofContractKindErrors(contract: Record<string, unknown>): string[] {
878
901
  `proof_contract.value_source[${index}].source`,
879
902
  ),
880
903
  );
881
- if (row.symbol_id !== undefined || row.export !== undefined)
904
+ if (
905
+ row.symbol_id !== undefined ||
906
+ row.export !== undefined ||
907
+ row.arg !== undefined
908
+ )
882
909
  errors.push(
883
- `proof_contract.value_source[${index}] names a source, so it takes no symbol_id or export`,
910
+ `proof_contract.value_source[${index}] names a source, so it takes no symbol_id, export or arg`,
884
911
  );
885
912
  if (row.measure !== undefined && row.measure !== "count")
886
913
  errors.push(
@@ -897,18 +924,22 @@ function proofContractKindErrors(contract: Record<string, unknown>): string[] {
897
924
  row !== null &&
898
925
  nonEmptyString(row.symbol_id) &&
899
926
  (row.export === undefined || nonEmptyString(row.export)) &&
927
+ (row.arg === undefined || isArgIndex(row.arg)) &&
900
928
  (row.measure === undefined ||
901
929
  row.measure === "value" ||
902
930
  row.measure === "count") &&
903
931
  Object.keys(row).every(
904
932
  (key) =>
905
- key === "symbol_id" || key === "export" || key === "measure",
933
+ key === "symbol_id" ||
934
+ key === "export" ||
935
+ key === "arg" ||
936
+ key === "measure",
906
937
  )
907
938
  );
908
939
  })
909
940
  )
910
941
  errors.push(
911
- "proof_contract.value_source must be [{symbol_id, export?, measure?: value|count} or {source, measure?: count}] naming the code constants or project sources the assumptions read",
942
+ "proof_contract.value_source must be [{symbol_id, export?, arg?, measure?: value|count} or {source, measure?: count}] naming the code constants or project sources the assumptions read",
912
943
  );
913
944
  else if (kind !== "arithmetic" && kind !== "smt")
914
945
  errors.push(
@@ -938,13 +969,23 @@ function proofContractKindErrors(contract: Record<string, unknown>): string[] {
938
969
  return errors;
939
970
  }
940
971
 
941
- function isSourceReference(value: unknown): boolean {
972
+ function isArgIndex(value: unknown): boolean {
973
+ return typeof value === "number" && Number.isInteger(value) && value >= 1;
974
+ }
975
+
976
+ function isSourceReference(
977
+ value: unknown,
978
+ options: Readonly<{ arg?: boolean }> = { arg: true },
979
+ ): boolean {
942
980
  const row = record(value);
943
981
  return (
944
982
  row !== null &&
945
983
  nonEmptyString(row.symbol_id) &&
946
984
  (row.export === undefined || nonEmptyString(row.export)) &&
947
- Object.keys(row).every((key) => key === "symbol_id" || key === "export")
985
+ (row.arg === undefined || (options.arg === true && isArgIndex(row.arg))) &&
986
+ Object.keys(row).every(
987
+ (key) => key === "symbol_id" || key === "export" || key === "arg",
988
+ )
948
989
  );
949
990
  }
950
991
 
@@ -964,11 +1005,12 @@ function isSourceMap(
964
1005
 
965
1006
  function isPredicateReference(value: unknown): boolean {
966
1007
  const row = record(value);
1008
+ // A predicate is called with every argument, so it projects none.
967
1009
  if (row === null || row.harness_for === undefined)
968
- return isSourceReference(value);
1010
+ return isSourceReference(value, { arg: false });
969
1011
  const { harness_for: harness, ...reference } = row;
970
1012
  return (
971
- isSourceReference(reference) &&
1013
+ isSourceReference(reference, { arg: false }) &&
972
1014
  Array.isArray(harness) &&
973
1015
  harness.length > 0 &&
974
1016
  harness.every(nonEmptyString)
@@ -998,7 +1040,7 @@ function sourceContractErrors(contract: Record<string, unknown>): string[] {
998
1040
  );
999
1041
  } else if (kind === "source")
1000
1042
  errors.push(
1001
- "proof_contract.source is required for kind source: name the project source Kibi reads (reader json, yaml, glob, openapi, references, schema, routes or validator)",
1043
+ "proof_contract.source is required for kind source: name the project source Kibi reads (reader json, yaml, glob, openapi, references, schema, routes, validator or prolog)",
1002
1044
  );
1003
1045
  const domains = record(contract.domains);
1004
1046
  for (const [type, entry] of Object.entries(domains ?? {}))
@@ -1046,12 +1088,12 @@ function nonNumericContractErrors(contract: Record<string, unknown>): string[] {
1046
1088
  )
1047
1089
  )
1048
1090
  errors.push(
1049
- "proof_contract.domains must map each argument type to {symbol_id, export?} naming the export that lists its values, or {source} naming the project source Kibi reads them from",
1091
+ "proof_contract.domains must map each argument type to {symbol_id, export?, arg?} naming the export (or SWI-Prolog predicate and argument) that lists its values, or {source} naming the project source Kibi reads them from",
1050
1092
  );
1051
1093
  for (const field of ["initial_source", "pattern_source"])
1052
1094
  if (contract[field] !== undefined && !isSourceReference(contract[field]))
1053
1095
  errors.push(
1054
- `proof_contract.${field} must be {symbol_id, export?} naming the export Kibi reads`,
1096
+ `proof_contract.${field} must be {symbol_id, export?, arg?} naming the export (or SWI-Prolog predicate and argument) Kibi reads`,
1055
1097
  );
1056
1098
  only("predicate_source", ["rule"]);
1057
1099
  only("domains", ["rule", "state_machine"]);
@@ -1113,7 +1155,12 @@ export function optionalProofContractFields(
1113
1155
  > {
1114
1156
  const fields: {
1115
1157
  kind?: ProofKind;
1116
- domain_source?: { symbol_id: string; export?: string; field?: string };
1158
+ domain_source?: {
1159
+ symbol_id: string;
1160
+ export?: string;
1161
+ field?: string;
1162
+ arg?: number;
1163
+ };
1117
1164
  witness?: { path: string };
1118
1165
  constraint_source?: { fact_ids: string[] };
1119
1166
  value_source?: ValueSourceEntry[];
@@ -1132,6 +1179,7 @@ export function optionalProofContractFields(
1132
1179
  symbol_id: domain.symbol_id,
1133
1180
  ...(typeof domain.export === "string" ? { export: domain.export } : {}),
1134
1181
  ...(typeof domain.field === "string" ? { field: domain.field } : {}),
1182
+ ...(isArgIndex(domain.arg) ? { arg: domain.arg as number } : {}),
1135
1183
  };
1136
1184
  const witness = record(contract.witness);
1137
1185
  if (witness && typeof witness.path === "string")
@@ -1154,6 +1202,7 @@ export function optionalProofContractFields(
1154
1202
  return {
1155
1203
  symbol_id: row.symbol_id,
1156
1204
  ...(typeof row.export === "string" ? { export: row.export } : {}),
1205
+ ...(isArgIndex(row.arg) ? { arg: row.arg as number } : {}),
1157
1206
  ...(row.measure === "value" || row.measure === "count"
1158
1207
  ? { measure: row.measure }
1159
1208
  : {}),
@@ -1177,10 +1226,19 @@ export function optionalProofContractFields(
1177
1226
  return fields;
1178
1227
  }
1179
1228
 
1180
- type SourceReference = { symbol_id: string; export?: string };
1181
- type PredicateReference = SourceReference & { harness_for?: string[] };
1229
+ type SourceReference = { symbol_id: string; export?: string; arg?: number };
1230
+ type PredicateReference = {
1231
+ symbol_id: string;
1232
+ export?: string;
1233
+ harness_for?: string[];
1234
+ };
1182
1235
  type ValueSourceEntry =
1183
- | { symbol_id: string; export?: string; measure?: "value" | "count" }
1236
+ | {
1237
+ symbol_id: string;
1238
+ export?: string;
1239
+ arg?: number;
1240
+ measure?: "value" | "count";
1241
+ }
1184
1242
  | { source: SourceSpec; measure: "count" };
1185
1243
 
1186
1244
  function predicateMap(
@@ -1229,6 +1287,7 @@ function sourceReference(value: unknown): SourceReference | undefined {
1229
1287
  return {
1230
1288
  symbol_id: row.symbol_id,
1231
1289
  ...(typeof row.export === "string" ? { export: row.export } : {}),
1290
+ ...(isArgIndex(row.arg) ? { arg: row.arg as number } : {}),
1232
1291
  };
1233
1292
  }
1234
1293
 
@@ -22,8 +22,9 @@
22
22
  * JSON or YAML file, the files a glob matches, an OpenAPI document, the
23
23
  * references the code makes (environment variables, imports, calls, string
24
24
  * arguments, thrown error codes, property values), a data schema (drizzle,
25
- * Prisma or SQL migrations), a web app's route table (Hono, Express) and a
26
- * validator object (zod and anything with safeParse).
25
+ * Prisma or SQL migrations), a web app's route table (Hono, Express), a
26
+ * validator object (zod and anything with safeParse) and the facts of a
27
+ * SWI-Prolog file (a pack's requires/1).
27
28
  *
28
29
  * Every reader is exact or refuses: a member Kibi cannot read statically (a
29
30
  * computed environment variable name, a dynamic import, an ALTER TABLE form
@@ -47,6 +48,7 @@ export const SOURCE_READERS = [
47
48
  "schema",
48
49
  "routes",
49
50
  "validator",
51
+ "prolog",
50
52
  ] as const;
51
53
 
52
54
  export type SourceReader = (typeof SOURCE_READERS)[number];
@@ -148,6 +150,7 @@ const KEYS: Readonly<Record<SourceReader, readonly string[]>> = {
148
150
  "select",
149
151
  ],
150
152
  validator: ["reader", "file", "export", "select"],
153
+ prolog: ["reader", "file", "functor", "arg"],
151
154
  };
152
155
 
153
156
  function record(value: unknown): Record<string, unknown> | null {
@@ -322,6 +325,23 @@ export function sourceSpecErrors(value: unknown, label: string): string[] {
322
325
  `${label}.export is required for reader validator: name the object schema`,
323
326
  );
324
327
  break;
328
+ case "prolog":
329
+ file("file", true);
330
+ if (
331
+ typeof row.functor !== "string" ||
332
+ !/^[a-z][A-Za-z0-9_]*\/(?:0|[1-9][0-9]*)$/.test(row.functor)
333
+ )
334
+ errors.push(
335
+ `${label}.functor is required for reader prolog: name the facts read as Name/Arity (requires/1)`,
336
+ );
337
+ if (
338
+ row.arg !== undefined &&
339
+ !(Number.isInteger(row.arg) && (row.arg as number) >= 1)
340
+ )
341
+ errors.push(
342
+ `${label}.arg must be the 1-based argument of each fact that holds the member`,
343
+ );
344
+ break;
325
345
  }
326
346
  return errors;
327
347
  }
@@ -352,15 +372,28 @@ export function matchWorkspaceFiles(
352
372
  workspaceRoot: string,
353
373
  patterns: readonly string[],
354
374
  ignore: readonly string[] = [],
375
+ caseSensitive = true,
355
376
  ): string[] {
377
+ // A symbolic link to a file is read as that file (git and compilers read
378
+ // it so); links to folders are not walked.
356
379
  return fg
357
380
  .sync([...patterns], {
358
381
  cwd: workspaceRoot,
359
382
  ignore: [...DEFAULT_IGNORE, ...ignore],
383
+ caseSensitiveMatch: caseSensitive,
360
384
  dot: true,
361
- onlyFiles: true,
385
+ onlyFiles: false,
386
+ markDirectories: true,
362
387
  followSymbolicLinks: false,
363
388
  })
389
+ .filter((file) => {
390
+ if (file.endsWith("/")) return false;
391
+ try {
392
+ return statSync(path.join(workspaceRoot, file)).isFile();
393
+ } catch {
394
+ return false;
395
+ }
396
+ })
364
397
  .map((file) => file.split(path.sep).join("/"))
365
398
  .sort();
366
399
  }
@@ -451,6 +484,9 @@ export function sourceDependencies(
451
484
  addFile(String(spec.file));
452
485
  for (const file of globList(spec.names_from)) addFile(file);
453
486
  break;
487
+ case "prolog":
488
+ addFile(String(spec.file));
489
+ break;
454
490
  }
455
491
  if (
456
492
  spec.reader === "routes" ||
@@ -1617,6 +1653,14 @@ export async function readSource(
1617
1653
  ok: true,
1618
1654
  model: { members: sortedUnique(evaluated.members ?? []) },
1619
1655
  };
1656
+ if (spec.reader === "prolog")
1657
+ return {
1658
+ ok: true,
1659
+ model: {
1660
+ members: sortedUnique(evaluated.members ?? []),
1661
+ sequence: evaluated.sequence ?? [],
1662
+ },
1663
+ };
1620
1664
  if (spec.reader === "routes") {
1621
1665
  const routes = selectedRoutes(spec, evaluated.routes ?? []).sort((a, b) =>
1622
1666
  `${a.path} ${a.method}` < `${b.path} ${b.method}` ? -1 : 1,
@@ -1644,6 +1688,8 @@ export type SourceCodeEvaluation =
1644
1688
  | {
1645
1689
  ok: true;
1646
1690
  members?: string[];
1691
+ /** The prolog reader's members in file order, duplicates kept. */
1692
+ sequence?: string[];
1647
1693
  entities?: SourceEntity[];
1648
1694
  routes?: SourceRoute[];
1649
1695
  }
@@ -1671,6 +1717,8 @@ export function describeSource(spec: SourceSpec): string {
1671
1717
  return `routes of ${spec.export} in ${spec.file}${spec.path_prefix ? ` under ${spec.path_prefix}` : ""}`;
1672
1718
  case "validator":
1673
1719
  return `validator ${spec.export} in ${spec.file}`;
1720
+ case "prolog":
1721
+ return `${spec.functor} facts in ${spec.file}${spec.arg ? ` (argument ${spec.arg})` : ""}`;
1674
1722
  }
1675
1723
  }
1676
1724
 
@@ -411,6 +411,20 @@ const entitySchema: Record<string, unknown> = {
411
411
  description:
412
412
  "Requirement-only. Optional reference to the approval decision record (ticket, ADR or review link) for an exception requirement.",
413
413
  },
414
+ failure_side_waiver: {
415
+ type: "string",
416
+ minLength: 1,
417
+ pattern: "\\S",
418
+ description:
419
+ "Requirement-only. Why the requirement has no failure side to test: its claims state a capability or an output shape, so there is no input or attempt for Kibi to refuse. Waives the happy_path_only gap once failure_side_waiver_approved_by is set.",
420
+ },
421
+ failure_side_waiver_approved_by: {
422
+ type: "string",
423
+ minLength: 1,
424
+ pattern: "\\S",
425
+ description:
426
+ "Requirement-only. The person who accepted failure_side_waiver. Without it the waiver is reported as awaiting approval and the gap stays open.",
427
+ },
414
428
  rationale: {
415
429
  type: "string",
416
430
  minLength: 1,
@@ -497,6 +511,23 @@ const entitySchema: Record<string, unknown> = {
497
511
  semantic_key: { type: "string" },
498
512
  payload_hash: { type: "string" },
499
513
  reason: { type: "string" },
514
+ // The advisor's hint for a quantified clause, kept so its receipt
515
+ // propositions can be copied into the inventory unchanged.
516
+ dimension: {
517
+ type: "object",
518
+ required: ["quantifier", "rewrites"],
519
+ properties: {
520
+ quantifier: { type: "string", minLength: 1 },
521
+ rewrites: {
522
+ type: "array",
523
+ items: {
524
+ type: "string",
525
+ enum: ["bound", "rule", "count", "set"],
526
+ },
527
+ },
528
+ },
529
+ additionalProperties: false,
530
+ },
500
531
  },
501
532
  additionalProperties: false,
502
533
  },
@@ -606,6 +637,34 @@ const entitySchema: Record<string, unknown> = {
606
637
  canonical_key: { type: "string" },
607
638
  claim_key: { type: "string", pattern: "^CLAIM-[A-F0-9]{16}$" },
608
639
  claim_text: { type: "string" },
640
+ dimension_waiver: {
641
+ type: "string",
642
+ minLength: 1,
643
+ pattern: "\\S",
644
+ description:
645
+ "Fact-only. Why the quantifier word in claim_text (each, every, all, or a cardinality bound) ranges over nothing, so the claim needs no count, set or rule. Waives dimension_unrepresented for the claim once dimension_waiver_approved_by is set.",
646
+ },
647
+ dimension_waiver_approved_by: {
648
+ type: "string",
649
+ minLength: 1,
650
+ pattern: "\\S",
651
+ description:
652
+ "Fact-only. The person who accepted dimension_waiver. Without it the waiver is reported as awaiting approval and the gap stays open.",
653
+ },
654
+ case_waiver: {
655
+ type: "string",
656
+ minLength: 1,
657
+ pattern: "\\S",
658
+ description:
659
+ "Fact-only. Why the edge cases Kibi derives from this fact (the value past a bound, a value outside a set) are covered some other way or cannot occur. Waives uncovered_case for the fact once case_waiver_approved_by is set.",
660
+ },
661
+ case_waiver_approved_by: {
662
+ type: "string",
663
+ minLength: 1,
664
+ pattern: "\\S",
665
+ description:
666
+ "Fact-only. The person who accepted case_waiver. Without it the waiver is reported as awaiting approval and the gap stays open.",
667
+ },
609
668
  predicate_name: { type: "string" },
610
669
  predicate_namespace: { type: "string" },
611
670
  predicate_arity: { type: "integer", minimum: 1 },
@@ -699,6 +758,10 @@ const entitySchema: Record<string, unknown> = {
699
758
  { required: ["canonical_key"] },
700
759
  { required: ["claim_key"] },
701
760
  { required: ["claim_text"] },
761
+ { required: ["dimension_waiver"] },
762
+ { required: ["dimension_waiver_approved_by"] },
763
+ { required: ["case_waiver"] },
764
+ { required: ["case_waiver_approved_by"] },
702
765
  { required: ["predicate_name"] },
703
766
  { required: ["predicate_namespace"] },
704
767
  { required: ["predicate_arity"] },
@@ -760,6 +823,8 @@ const entitySchema: Record<string, unknown> = {
760
823
  { required: ["proof_exempt_reason"] },
761
824
  { required: ["approved_by"] },
762
825
  { required: ["approval_ref"] },
826
+ { required: ["failure_side_waiver"] },
827
+ { required: ["failure_side_waiver_approved_by"] },
763
828
  { required: ["rationale"] },
764
829
  { required: ["exempts_claims"] },
765
830
  { required: ["required_evidence"] },
@@ -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, staging the tracked Kibi evidence with git add (symbol coordinates are derived and never staged), 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.3.0
5
+ version: 1.4.0
6
6
  kibiCompatibility: ">=1.0.0"
7
7
  tags:
8
8
  - kibi
@@ -91,7 +91,11 @@ apps); never attach the `.html` as a file, which chat apps show as raw source;
91
91
  past 15 requirements the Markdown stops and only the page lists them all.
92
92
  Host details: `kibi-decisions`, `resources/signoff-views.md`. `--no-proof` skips the proof lookup, which reads coverage and is slow
93
93
  on a large knowledge base. The summary is not an approval: never set
94
- `approved_by` or `origin.ref` from it.
94
+ `approved_by` or `origin.ref` from it. Show it before you open or merge the
95
+ pull request. When the person answers, record their answer in the same
96
+ change (their name in `approved_by`, their words in `origin.ref` or
97
+ `approval_ref`) and push it to the same pull request; never move a signoff,
98
+ firmness or waiver approval into a separate pull request.
95
99
 
96
100
  ## Impact reviews
97
101
 
@@ -2,7 +2,7 @@
2
2
  id: kibi-decisions
3
3
  name: kibi-decisions
4
4
  description: "Use when the person states a rule or decision (must, never, always, from now on, we decided), when a Kibi hook asks to confirm or warns about an edit to code that implements a firm requirement, when the Stop hook says source files changed but nothing was recorded, when kb_check quotes requirement_statement_unverified, or when a request conflicts with a recorded requirement or ADR. Covers reading firmness and origin, recording a person's rule as firm with origin.ref, superseding with a Why this changed section, the kb_compile_intent unresolved/reviewCandidates/conflictReviews loop, asking before overriding a firm rule, and putting decisions to the person as one numbered kibi signoff --questions view."
5
- version: 1.4.0
5
+ version: 1.5.0
6
6
  kibiCompatibility: ">=1.0.0"
7
7
  tags:
8
8
  - kibi
@@ -115,7 +115,12 @@ again until none is open, then record each rule with their words in
115
115
  `origin.ref`. Fields and outputs: `resources/signoff-views.md`.
116
116
 
117
117
  Never invent words for `origin.ref`, never set `approved_by` yourself, and
118
- mark your own picks `default` and guesses `exploratory`. Payload shapes,
118
+ mark your own picks `default` and guesses `exploratory`. Once the person has
119
+ answered, recording their answer (their name in `approved_by` or a
120
+ `*_waiver_approved_by` field, their words in `origin.ref` or `approval_ref`)
121
+ is yours to do: put it on the branch of the change it approves and push it to
122
+ that pull request, never to a separate one. Ask before you open or merge the
123
+ pull request, so the answer lands in it. Payload shapes,
119
124
  refusal messages and the `kb_compile_intent` review loop are in
120
125
  `resources/decision-records.md`.
121
126
 
@@ -51,7 +51,9 @@ writes and opens the page; `--format json` prints the view.
51
51
  The person answers by number ("1 yes, 2 exploratory, 3 reword: ..."). Copy
52
52
  each answer into `answer`, render again, and record the rules only once every
53
53
  question is answered. An answer is the person's words: quote it in
54
- `origin.ref`; a view itself is never an approval.
54
+ `origin.ref`; a view itself is never an approval. Record the answers on the
55
+ branch of the change they approve and push them to its pull request, never to
56
+ a separate one.
55
57
 
56
58
  ## Summary contents
57
59
 
@@ -2,7 +2,7 @@
2
2
  id: kibi-usage
3
3
  name: Kibi Usage
4
4
  description: Use Kibi's source-first, exact-Git, migration-aware, proof-aware operations safely across MCP or the trusted local CLI, including partial completion repair.
5
- version: 2.36.0
5
+ version: 2.40.1
6
6
  kibiCompatibility: ">=1.0.0"
7
7
  tags:
8
8
  - kibi
@@ -20,6 +20,7 @@ resources:
20
20
  - resources/fact-lanes.md
21
21
  - resources/workflows.md
22
22
  - resources/proof.md
23
+ - resources/prolog-proofs.md
23
24
  - resources/ui-requirements.md
24
25
  - resources/logic-ir.md
25
26
  - resources/kb-improvement.md
@@ -94,8 +95,10 @@ it is a pointer to the knowledge, never proof. Each line answers one question:
94
95
  requirement first. Read the lead requirement with `kb_query({id})` before
95
96
  changing behavior; add `includeBody: true` to see its authored prose, and
96
97
  fix a stale sentence there with `kb_upsert` `document.body`.
97
- - `REQ-… must keep true: FACT-…` (edit only): the ground facts the lead
98
- requirement requires. An edit that breaks one of them is a requirement
98
+ - `REQ-… must keep true: <claim>` (edit only): what the lead requirement
99
+ requires, as the claims its facts model (with the operator and members,
100
+ such as "The greet function must not call console.log") or, without
101
+ them, its own statement. An edit that breaks one of them is a requirement
99
102
  change: ask before changing the rule (see Decision firmness), and never
100
103
  code around the fact.
101
104
  - `Decision: ADR-…` (edit only): the decision behind the lead requirement.
@@ -372,6 +375,14 @@ human sets `approved_by`; `kb_check` flags approvals an agent recorded without
372
375
  corroboration. Never fill in an approval yourself. Record why a requirement
373
376
  exists in `rationale`, or link the ADR that explains it.
374
377
 
378
+ A signoff belongs to the change it approves. Ask for it before you open or
379
+ merge the pull request, and when the person answers, record their answer
380
+ (`approved_by` or a `*_waiver_approved_by` field set to them, their words in
381
+ `origin.ref` or `approval_ref`) on the same branch and push it to the same pull
382
+ request. Writing down an answer the person gave is not approving it yourself.
383
+ Never open a separate pull request only to carry a signoff, firmness or waiver
384
+ approval.
385
+
375
386
  ## Decision firmness
376
387
 
377
388
  Requirements and ADRs carry `firmness`, which says what you may do with them.