kibi-cli 2.4.0 → 2.5.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 (354) hide show
  1. package/dist/cli-json-command.d.ts +6 -0
  2. package/dist/cli-json-command.d.ts.map +1 -1
  3. package/dist/cli-json-command.js +37 -9
  4. package/dist/cli-operation-loader.d.ts.map +1 -1
  5. package/dist/cli-operation-loader.js +7 -0
  6. package/dist/cli-operation-metadata.d.ts +12 -4
  7. package/dist/cli-operation-metadata.d.ts.map +1 -1
  8. package/dist/cli-operation-metadata.js +14 -4
  9. package/dist/cli-protocol.d.ts +14 -0
  10. package/dist/cli-protocol.d.ts.map +1 -1
  11. package/dist/cli-protocol.js +31 -2
  12. package/dist/cli-register-proof.d.ts.map +1 -1
  13. package/dist/cli-register-proof.js +13 -0
  14. package/dist/commands/check.d.ts.map +1 -1
  15. package/dist/commands/check.js +11 -2
  16. package/dist/commands/discovery-shared.d.ts.map +1 -1
  17. package/dist/commands/discovery-shared.js +8 -2
  18. package/dist/commands/engine.d.ts.map +1 -1
  19. package/dist/commands/engine.js +4 -2
  20. package/dist/commands/gc.d.ts.map +1 -1
  21. package/dist/commands/gc.js +7 -0
  22. package/dist/commands/init-helpers.d.ts.map +1 -1
  23. package/dist/commands/init-helpers.js +38 -12
  24. package/dist/commands/init.d.ts.map +1 -1
  25. package/dist/commands/init.js +10 -15
  26. package/dist/commands/migrate.d.ts.map +1 -1
  27. package/dist/commands/migrate.js +281 -14
  28. package/dist/commands/proof-compact.d.ts +9 -0
  29. package/dist/commands/proof-compact.d.ts.map +1 -0
  30. package/dist/commands/proof-compact.js +58 -0
  31. package/dist/commands/prove.d.ts +38 -0
  32. package/dist/commands/prove.d.ts.map +1 -1
  33. package/dist/commands/prove.js +222 -47
  34. package/dist/commands/sync/persistence.d.ts.map +1 -1
  35. package/dist/commands/sync/persistence.js +61 -16
  36. package/dist/commands/sync.d.ts +8 -0
  37. package/dist/commands/sync.d.ts.map +1 -1
  38. package/dist/commands/sync.js +42 -16
  39. package/dist/diagnostics.js +1 -1
  40. package/dist/engine-limits.d.ts +74 -0
  41. package/dist/engine-limits.d.ts.map +1 -0
  42. package/dist/engine-limits.js +201 -0
  43. package/dist/engine.d.ts +10 -0
  44. package/dist/engine.d.ts.map +1 -1
  45. package/dist/engine.js +57 -9
  46. package/dist/extractors/manifest.d.ts +8 -0
  47. package/dist/extractors/manifest.d.ts.map +1 -1
  48. package/dist/extractors/manifest.js +34 -5
  49. package/dist/extractors/markdown.d.ts +8 -0
  50. package/dist/extractors/markdown.d.ts.map +1 -1
  51. package/dist/extractors/markdown.js +57 -0
  52. package/dist/extractors/relationships.d.ts.map +1 -1
  53. package/dist/extractors/relationships.js +2 -0
  54. package/dist/intent-search.d.ts +4 -1
  55. package/dist/intent-search.d.ts.map +1 -1
  56. package/dist/intent-search.js +186 -33
  57. package/dist/operations/bootstrap/candidate-helpers.d.ts.map +1 -1
  58. package/dist/operations/bootstrap/candidate-helpers.js +8 -1
  59. package/dist/operations/bootstrap/candidates.d.ts.map +1 -1
  60. package/dist/operations/bootstrap/candidates.js +54 -38
  61. package/dist/operations/bootstrap/generate.d.ts +2 -0
  62. package/dist/operations/bootstrap/generate.d.ts.map +1 -1
  63. package/dist/operations/bootstrap/generate.js +87 -33
  64. package/dist/operations/bootstrap/intent-claims.d.ts.map +1 -1
  65. package/dist/operations/bootstrap/intent-claims.js +12 -4
  66. package/dist/operations/bootstrap/markdown-candidates.d.ts +2 -0
  67. package/dist/operations/bootstrap/markdown-candidates.d.ts.map +1 -1
  68. package/dist/operations/bootstrap/markdown-candidates.js +32 -10
  69. package/dist/operations/bootstrap/presentation.d.ts.map +1 -1
  70. package/dist/operations/bootstrap/presentation.js +6 -2
  71. package/dist/operations/bootstrap/requirement-claims.d.ts +1 -0
  72. package/dist/operations/bootstrap/requirement-claims.d.ts.map +1 -1
  73. package/dist/operations/bootstrap/requirement-claims.js +13 -1
  74. package/dist/operations/bootstrap/validation.d.ts +4 -0
  75. package/dist/operations/bootstrap/validation.d.ts.map +1 -0
  76. package/dist/operations/bootstrap/validation.js +20 -0
  77. package/dist/operations/migration/inventory-rederive.d.ts +81 -0
  78. package/dist/operations/migration/inventory-rederive.d.ts.map +1 -0
  79. package/dist/operations/migration/inventory-rederive.js +484 -0
  80. package/dist/operations/migration/kb-sources.d.ts +53 -0
  81. package/dist/operations/migration/kb-sources.d.ts.map +1 -0
  82. package/dist/operations/migration/kb-sources.js +233 -0
  83. package/dist/operations/migration/origin-backfill.d.ts +39 -0
  84. package/dist/operations/migration/origin-backfill.d.ts.map +1 -0
  85. package/dist/operations/migration/origin-backfill.js +164 -0
  86. package/dist/operations/migration/polarity-values.d.ts +10 -0
  87. package/dist/operations/migration/polarity-values.d.ts.map +1 -0
  88. package/dist/operations/migration/polarity-values.js +60 -0
  89. package/dist/operations/migration/schema6.d.ts +59 -0
  90. package/dist/operations/migration/schema6.d.ts.map +1 -0
  91. package/dist/operations/migration/schema6.js +379 -0
  92. package/dist/operations/migration/source-paths.d.ts +131 -0
  93. package/dist/operations/migration/source-paths.d.ts.map +1 -0
  94. package/dist/operations/migration/source-paths.js +308 -0
  95. package/dist/operations/migration/superseded-closure.d.ts +54 -0
  96. package/dist/operations/migration/superseded-closure.d.ts.map +1 -0
  97. package/dist/operations/migration/superseded-closure.js +187 -0
  98. package/dist/operations/modeling/logic-modeling.d.ts.map +1 -1
  99. package/dist/operations/modeling/logic-modeling.js +3 -5
  100. package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
  101. package/dist/operations/modeling/model-requirement.js +225 -67
  102. package/dist/operations/mutation/contradictions.d.ts +16 -0
  103. package/dist/operations/mutation/contradictions.d.ts.map +1 -1
  104. package/dist/operations/mutation/contradictions.js +32 -0
  105. package/dist/operations/mutation/delete.d.ts.map +1 -1
  106. package/dist/operations/mutation/delete.js +15 -7
  107. package/dist/operations/mutation/origin.d.ts +21 -0
  108. package/dist/operations/mutation/origin.d.ts.map +1 -0
  109. package/dist/operations/mutation/origin.js +78 -0
  110. package/dist/operations/mutation/plan-apply-journal.d.ts +182 -0
  111. package/dist/operations/mutation/plan-apply-journal.d.ts.map +1 -0
  112. package/dist/operations/mutation/plan-apply-journal.js +613 -0
  113. package/dist/operations/mutation/predicate-vocabulary-guard.d.ts +3 -1
  114. package/dist/operations/mutation/predicate-vocabulary-guard.d.ts.map +1 -1
  115. package/dist/operations/mutation/predicate-vocabulary-guard.js +13 -2
  116. package/dist/operations/mutation/relationships.d.ts +5 -5
  117. package/dist/operations/mutation/relationships.d.ts.map +1 -1
  118. package/dist/operations/mutation/relationships.js +31 -11
  119. package/dist/operations/mutation/serialization.d.ts.map +1 -1
  120. package/dist/operations/mutation/serialization.js +3 -1
  121. package/dist/operations/mutation/source-authoring.d.ts +6 -0
  122. package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
  123. package/dist/operations/mutation/source-authoring.js +7 -1
  124. package/dist/operations/mutation/types.d.ts +14 -0
  125. package/dist/operations/mutation/types.d.ts.map +1 -1
  126. package/dist/operations/mutation/upsert.d.ts +30 -3
  127. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  128. package/dist/operations/mutation/upsert.js +105 -35
  129. package/dist/operations/mutation/validate-upsert.d.ts +6 -0
  130. package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
  131. package/dist/operations/mutation/validate-upsert.js +34 -30
  132. package/dist/operations/planning/apply-plan.d.ts.map +1 -1
  133. package/dist/operations/planning/apply-plan.js +753 -145
  134. package/dist/operations/planning/compile-intent.d.ts +34 -1
  135. package/dist/operations/planning/compile-intent.d.ts.map +1 -1
  136. package/dist/operations/planning/compile-intent.js +314 -98
  137. package/dist/operations/proof/code-scope.d.ts +28 -0
  138. package/dist/operations/proof/code-scope.d.ts.map +1 -1
  139. package/dist/operations/proof/code-scope.js +72 -0
  140. package/dist/operations/proof/compact-receipts.d.ts +49 -0
  141. package/dist/operations/proof/compact-receipts.d.ts.map +1 -0
  142. package/dist/operations/proof/compact-receipts.js +160 -0
  143. package/dist/operations/proof/ingest-proof.d.ts +2 -0
  144. package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
  145. package/dist/operations/proof/ingest-proof.js +44 -23
  146. package/dist/operations/proof/prune-receipts.d.ts.map +1 -1
  147. package/dist/operations/proof/prune-receipts.js +5 -9
  148. package/dist/operations/proof/receipt-compaction.d.ts +48 -0
  149. package/dist/operations/proof/receipt-compaction.d.ts.map +1 -0
  150. package/dist/operations/proof/receipt-compaction.js +121 -0
  151. package/dist/operations/semantic-advisor/analysis-receipt.d.ts.map +1 -1
  152. package/dist/operations/semantic-advisor/analysis-receipt.js +12 -1
  153. package/dist/operations/semantic-advisor/analyze-prose.d.ts +2 -1
  154. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  155. package/dist/operations/semantic-advisor/analyze-prose.js +51 -5
  156. package/dist/operations/semantic-advisor/clauses.d.ts +1 -0
  157. package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
  158. package/dist/operations/semantic-advisor/clauses.js +11 -1
  159. package/dist/operations/semantic-advisor/conditional-rules.d.ts +33 -0
  160. package/dist/operations/semantic-advisor/conditional-rules.d.ts.map +1 -0
  161. package/dist/operations/semantic-advisor/conditional-rules.js +262 -0
  162. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts +3 -1
  163. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -1
  164. package/dist/operations/semantic-advisor/ingestion-boundary.js +14 -6
  165. package/dist/operations/semantic-advisor/plugin-orchestration.js +1 -1
  166. package/dist/prolog/codec.d.ts.map +1 -1
  167. package/dist/prolog/codec.js +2 -1
  168. package/dist/prolog.d.ts +9 -0
  169. package/dist/prolog.d.ts.map +1 -1
  170. package/dist/prolog.js +56 -10
  171. package/dist/proof/command-test-report.d.ts +74 -0
  172. package/dist/proof/command-test-report.d.ts.map +1 -0
  173. package/dist/proof/command-test-report.js +206 -0
  174. package/dist/public/branch-resolver.d.ts +1 -0
  175. package/dist/public/branch-resolver.d.ts.map +1 -1
  176. package/dist/public/branch-resolver.js +1 -0
  177. package/dist/public/entity-origin.d.ts +69 -0
  178. package/dist/public/entity-origin.d.ts.map +1 -0
  179. package/dist/public/entity-origin.js +142 -0
  180. package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
  181. package/dist/public/impact/full-kb-quality.js +1 -0
  182. package/dist/public/impact/requirement-quality.js +1 -1
  183. package/dist/public/operations/catalog.d.ts +130 -19
  184. package/dist/public/operations/catalog.d.ts.map +1 -1
  185. package/dist/public/operations/catalog.js +3 -0
  186. package/dist/public/operations/check-executor.d.ts.map +1 -1
  187. package/dist/public/operations/check-executor.js +8 -0
  188. package/dist/public/operations/contracts.d.ts +0 -5
  189. package/dist/public/operations/contracts.d.ts.map +1 -1
  190. package/dist/public/operations/contracts.js +63 -14
  191. package/dist/public/operations/discovery-entities.d.ts +15 -0
  192. package/dist/public/operations/discovery-entities.d.ts.map +1 -1
  193. package/dist/public/operations/discovery-entities.js +59 -0
  194. package/dist/public/operations/discovery-executors.d.ts +6 -1
  195. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  196. package/dist/public/operations/discovery-executors.js +65 -6
  197. package/dist/public/operations/index.d.ts +1 -0
  198. package/dist/public/operations/index.d.ts.map +1 -1
  199. package/dist/public/operations/index.js +1 -0
  200. package/dist/public/operations/migration-plan.d.ts +5 -0
  201. package/dist/public/operations/migration-plan.d.ts.map +1 -1
  202. package/dist/public/operations/migration-plan.js +26 -1
  203. package/dist/public/operations/node-ports.d.ts.map +1 -1
  204. package/dist/public/operations/node-ports.js +24 -3
  205. package/dist/public/operations/origin-review.d.ts +51 -0
  206. package/dist/public/operations/origin-review.d.ts.map +1 -0
  207. package/dist/public/operations/origin-review.js +307 -0
  208. package/dist/public/operations/predicate-schema-conformance.js +1 -1
  209. package/dist/public/operations/repair-plan.d.ts.map +1 -1
  210. package/dist/public/operations/repair-plan.js +4 -0
  211. package/dist/public/operations/result-envelope.d.ts.map +1 -1
  212. package/dist/public/operations/result-envelope.js +17 -5
  213. package/dist/public/operations/runtime-types.d.ts +9 -0
  214. package/dist/public/operations/runtime-types.d.ts.map +1 -1
  215. package/dist/public/operations/schema6-check-actions.d.ts +127 -0
  216. package/dist/public/operations/schema6-check-actions.d.ts.map +1 -0
  217. package/dist/public/operations/schema6-check-actions.js +575 -0
  218. package/dist/public/operations/source-path-dangling.d.ts +17 -0
  219. package/dist/public/operations/source-path-dangling.d.ts.map +1 -0
  220. package/dist/public/operations/source-path-dangling.js +66 -0
  221. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  222. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  223. package/dist/public/operations/specs/check-rules.generated.js +15 -1
  224. package/dist/public/operations/specs/check.d.ts +2 -2
  225. package/dist/public/operations/specs/check.js +1 -1
  226. package/dist/public/operations/specs/composite.d.ts +351 -0
  227. package/dist/public/operations/specs/composite.d.ts.map +1 -0
  228. package/dist/public/operations/specs/composite.js +96 -0
  229. package/dist/public/operations/specs/discovery.d.ts +8 -3
  230. package/dist/public/operations/specs/discovery.d.ts.map +1 -1
  231. package/dist/public/operations/specs/discovery.js +8 -3
  232. package/dist/public/operations/specs/modeling.d.ts +2 -2
  233. package/dist/public/operations/specs/modeling.js +2 -2
  234. package/dist/public/operations/specs/mutation-schemas.d.ts +73 -8
  235. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  236. package/dist/public/operations/specs/mutation-schemas.js +43 -7
  237. package/dist/public/operations/specs/mutation.d.ts +1 -1
  238. package/dist/public/operations/specs/mutation.js +1 -1
  239. package/dist/public/operations/specs/planning.d.ts +2 -2
  240. package/dist/public/operations/specs/planning.js +4 -4
  241. package/dist/public/operations/specs/reporting.d.ts.map +1 -1
  242. package/dist/public/operations/specs/reporting.js +13 -26
  243. package/dist/public/operations/specs/upsert.d.ts +79 -9
  244. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  245. package/dist/public/operations/specs/upsert.js +6 -1
  246. package/dist/public/operations/types.d.ts +1 -1
  247. package/dist/public/operations/types.d.ts.map +1 -1
  248. package/dist/public/proof-receipt.d.ts +1 -0
  249. package/dist/public/proof-receipt.d.ts.map +1 -1
  250. package/dist/public/schemas/entity.d.ts.map +1 -1
  251. package/dist/public/schemas/entity.js +52 -0
  252. package/dist/public/schemas/relationship.d.ts.map +1 -1
  253. package/dist/public/schemas/relationship.js +2 -0
  254. package/dist/public/skills/kibi-bootstrap/SKILL.md +35 -67
  255. package/dist/public/skills/kibi-bootstrap/resources/bootstrap.md +6 -0
  256. package/dist/public/skills/kibi-usage/SKILL.md +68 -18
  257. package/dist/public/skills/kibi-usage/resources/fact-lanes.md +5 -5
  258. package/dist/public/skills/kibi-usage/resources/kb-improvement.md +1 -1
  259. package/dist/public/skills/kibi-usage/resources/logic-ir.md +2 -2
  260. package/dist/public/skills/kibi-usage/resources/operation-access.md +25 -1
  261. package/dist/public/skills/kibi-usage/resources/ui-requirements.md +4 -4
  262. package/dist/public/skills/kibi-usage/resources/workflows.md +42 -25
  263. package/dist/public/telemetry-acceptance.d.ts +58 -2
  264. package/dist/public/telemetry-acceptance.d.ts.map +1 -1
  265. package/dist/public/telemetry-acceptance.js +136 -10
  266. package/dist/public/telemetry-remediation.d.ts.map +1 -1
  267. package/dist/public/telemetry-remediation.js +26 -10
  268. package/dist/relationships/shards.d.ts +13 -0
  269. package/dist/relationships/shards.d.ts.map +1 -1
  270. package/dist/relationships/shards.js +54 -28
  271. package/dist/runtime/cli-runtime.d.ts.map +1 -1
  272. package/dist/runtime/cli-runtime.js +44 -3
  273. package/dist/runtime/detached-snapshot.d.ts +38 -0
  274. package/dist/runtime/detached-snapshot.d.ts.map +1 -0
  275. package/dist/runtime/detached-snapshot.js +92 -0
  276. package/dist/schemas/entity.schema.json +122 -0
  277. package/dist/search-answer.d.ts +157 -0
  278. package/dist/search-answer.d.ts.map +1 -0
  279. package/dist/search-answer.js +846 -0
  280. package/dist/traceability/impact-knowledge.d.ts.map +1 -1
  281. package/dist/traceability/impact-knowledge.js +7 -0
  282. package/dist/traceability/symbol-extract.js +3 -3
  283. package/dist/traceability/temp-kb.d.ts.map +1 -1
  284. package/dist/traceability/temp-kb.js +12 -0
  285. package/dist/types/entities.d.ts +13 -0
  286. package/dist/types/entities.d.ts.map +1 -1
  287. package/dist/types/relationships.d.ts +1 -1
  288. package/dist/types/relationships.d.ts.map +1 -1
  289. package/dist/utils/branch-resolver.d.ts +37 -1
  290. package/dist/utils/branch-resolver.d.ts.map +1 -1
  291. package/dist/utils/branch-resolver.js +130 -3
  292. package/dist/utils/repo-relative-path.d.ts +18 -0
  293. package/dist/utils/repo-relative-path.d.ts.map +1 -0
  294. package/dist/utils/repo-relative-path.js +58 -0
  295. package/dist/utils/rule-registry.generated.d.ts +75 -3
  296. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  297. package/dist/utils/rule-registry.generated.js +89 -3
  298. package/dist/utils/schema-version.d.ts +1 -1
  299. package/dist/utils/schema-version.d.ts.map +1 -1
  300. package/dist/utils/schema-version.js +4 -3
  301. package/dist/utils/strict-modeling.d.ts +1 -1
  302. package/dist/utils/strict-modeling.d.ts.map +1 -1
  303. package/dist/utils/strict-modeling.js +23 -3
  304. package/package.json +3 -3
  305. package/schema/entities.pl +22 -0
  306. package/schema/relationships.pl +14 -0
  307. package/schema/validation.pl +45 -1
  308. package/src/public/branch-resolver.ts +1 -0
  309. package/src/public/entity-origin.ts +175 -0
  310. package/src/public/impact/full-kb-quality.ts +1 -0
  311. package/src/public/impact/requirement-quality.ts +1 -1
  312. package/src/public/operations/catalog.ts +3 -0
  313. package/src/public/operations/check-executor.ts +15 -0
  314. package/src/public/operations/contracts.ts +75 -15
  315. package/src/public/operations/discovery-entities.ts +74 -0
  316. package/src/public/operations/discovery-executors.ts +88 -10
  317. package/src/public/operations/index.ts +1 -0
  318. package/src/public/operations/migration-plan.ts +30 -1
  319. package/src/public/operations/node-ports.ts +24 -3
  320. package/src/public/operations/origin-review.ts +375 -0
  321. package/src/public/operations/predicate-schema-conformance.ts +1 -1
  322. package/src/public/operations/repair-plan.ts +4 -0
  323. package/src/public/operations/result-envelope.ts +18 -6
  324. package/src/public/operations/runtime-types.ts +9 -0
  325. package/src/public/operations/schema6-check-actions.ts +699 -0
  326. package/src/public/operations/source-path-dangling.ts +81 -0
  327. package/src/public/operations/specs/check-rules.generated.ts +15 -1
  328. package/src/public/operations/specs/check.ts +1 -1
  329. package/src/public/operations/specs/composite.ts +141 -0
  330. package/src/public/operations/specs/discovery.ts +9 -3
  331. package/src/public/operations/specs/modeling.ts +2 -2
  332. package/src/public/operations/specs/mutation-schemas.ts +49 -7
  333. package/src/public/operations/specs/mutation.ts +1 -1
  334. package/src/public/operations/specs/planning.ts +4 -4
  335. package/src/public/operations/specs/reporting.ts +13 -38
  336. package/src/public/operations/specs/upsert.ts +7 -1
  337. package/src/public/operations/types.ts +2 -0
  338. package/src/public/proof-receipt.ts +1 -0
  339. package/src/public/schemas/entity.ts +57 -0
  340. package/src/public/schemas/relationship.ts +2 -0
  341. package/src/public/skills/kibi-bootstrap/SKILL.md +35 -67
  342. package/src/public/skills/kibi-bootstrap/resources/bootstrap.md +6 -0
  343. package/src/public/skills/kibi-usage/SKILL.md +68 -18
  344. package/src/public/skills/kibi-usage/resources/fact-lanes.md +5 -5
  345. package/src/public/skills/kibi-usage/resources/kb-improvement.md +1 -1
  346. package/src/public/skills/kibi-usage/resources/logic-ir.md +2 -2
  347. package/src/public/skills/kibi-usage/resources/operation-access.md +25 -1
  348. package/src/public/skills/kibi-usage/resources/ui-requirements.md +4 -4
  349. package/src/public/skills/kibi-usage/resources/workflows.md +42 -25
  350. package/src/public/telemetry-acceptance-types.d.ts +4 -1
  351. package/src/public/telemetry-acceptance.ts +204 -10
  352. package/src/public/telemetry-remediation.ts +39 -10
  353. package/src/schemas/entity.schema.json +122 -0
  354. package/src/schemas/relationship.schema.json +2 -0
@@ -6,7 +6,7 @@
6
6
  * and respond to issues programmatically.
7
7
  */
8
8
  export function branchErrorToDiagnostic(
9
- // implements REQ-008
9
+ // implements REQ-branch-store-recovery-v4
10
10
  _code, message, branch) {
11
11
  return {
12
12
  category: "BRANCH_RESOLUTION_FAILURE",
@@ -0,0 +1,74 @@
1
+ /** Envelope error code for a read stopped at its limit. */
2
+ export declare const QUERY_LIMIT_EXCEEDED_CODE = "QUERY_LIMIT_EXCEEDED";
3
+ /** Environment opt-in for read limits on every engine client. */
4
+ export declare const ENGINE_READ_TIME_LIMIT_ENV = "KIBI_ENGINE_READ_TIME_LIMIT_MS";
5
+ export declare const ENGINE_READ_INFERENCE_LIMIT_ENV = "KIBI_ENGINE_READ_INFERENCE_LIMIT";
6
+ /**
7
+ * Upper bound for a requested time limit. The daemon's SWI process kills a
8
+ * query at 120 s and recycles the session; a bounded read must end first.
9
+ */
10
+ export declare const ENGINE_READ_TIME_LIMIT_CAP_MS = 115000;
11
+ export type EngineQueryLimits = Readonly<{
12
+ /** Wall-clock budget for the Prolog goal, in milliseconds. */
13
+ timeMs?: number;
14
+ /** Logical-inference budget for the Prolog goal. */
15
+ inferences?: number;
16
+ }>;
17
+ export type EngineLimitExceeded = Readonly<{
18
+ kind: "time" | "inferences";
19
+ limit: number;
20
+ }>;
21
+ /**
22
+ * Validate limits received over the engine socket. Out-of-range values are
23
+ * dropped (the read runs unbounded, as before); a time limit is capped below
24
+ * the hard per-query timeout.
25
+ */
26
+ export declare function normalizeQueryLimits(value: unknown): EngineQueryLimits | undefined;
27
+ /** Read limits configured through the environment, if any. */
28
+ export declare function queryLimitsFromEnv(env?: NodeJS.ProcessEnv): EngineQueryLimits | undefined;
29
+ /**
30
+ * Clauses the engine session defines at boot (and after a recycle) so a
31
+ * bounded read needs one call and one answer binding. Helper variables stay
32
+ * clause-local, so the toplevel prints only the goal's own bindings plus the
33
+ * outcome, whose compound value cannot be grouped with a goal's binding.
34
+ *
35
+ * A goal that swallows the limit exception itself (a catch-all inside a
36
+ * predicate) could otherwise return a partial answer or fail; measuring the
37
+ * elapsed time and inferences around the goal reports the limit regardless.
38
+ */
39
+ export declare const BOUNDED_READ_HELPER_DEFINITION: string;
40
+ /**
41
+ * Wrap a read-only goal in its limits. The goal's own variables keep their
42
+ * names, so its answer bindings are unchanged; the outcome arrives in the
43
+ * KibiReadOutcome binding that settleBoundedRead strips. The surrounding
44
+ * parentheses keep PrologProcess from caching a bounded answer.
45
+ */
46
+ export declare function boundedReadGoal(goal: string, limits: EngineQueryLimits): string;
47
+ type BoundedResult = {
48
+ readonly success: boolean;
49
+ readonly bindings: Readonly<Record<string, string>>;
50
+ readonly error?: string;
51
+ };
52
+ /**
53
+ * Turn a bounded read's answer back into the unbounded answer shape, or into
54
+ * an explicit limitExceeded failure when a limit stopped the goal.
55
+ */
56
+ export declare function settleBoundedRead<T extends BoundedResult>(result: T, limits: EngineQueryLimits): T | (BoundedResult & {
57
+ readonly limitExceeded: EngineLimitExceeded;
58
+ });
59
+ /** A read the engine stopped at its limit; never an empty answer. */
60
+ export declare class EngineQueryLimitError extends Error {
61
+ readonly limitExceeded: EngineLimitExceeded;
62
+ readonly code = "QUERY_LIMIT_EXCEEDED";
63
+ readonly retryable = false;
64
+ constructor(limitExceeded: EngineLimitExceeded);
65
+ }
66
+ /**
67
+ * The limit that stopped a read, from the typed error or from the message an
68
+ * executor rewrapped it into; null for every other error.
69
+ */
70
+ export declare function queryLimitExceededOf(error: unknown): EngineLimitExceeded | null;
71
+ /** Reject an engine answer that reports a limit hit. */
72
+ export declare function assertWithinQueryLimits(value: unknown): void;
73
+ export {};
74
+ //# sourceMappingURL=engine-limits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-limits.d.ts","sourceRoot":"","sources":["../src/engine-limits.ts"],"names":[],"mappings":"AA6BA,2DAA2D;AAE3D,eAAO,MAAM,yBAAyB,yBAAyB,CAAC;AAEhE,iEAAiE;AAEjE,eAAO,MAAM,0BAA0B,mCAAmC,CAAC;AAE3E,eAAO,MAAM,+BAA+B,qCACR,CAAC;AAErC;;;GAGG;AAEH,eAAO,MAAM,6BAA6B,SAAU,CAAC;AAIrD,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC,CAAC;AAGH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,IAAI,EAAE,MAAM,GAAG,YAAY,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAWH;;;;GAIG;AAEH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,GACb,iBAAiB,GAAG,SAAS,CAiB/B;AAED,8DAA8D;AAE9D,wBAAgB,kBAAkB,CAChC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,iBAAiB,GAAG,SAAS,CAW/B;AAED;;;;;;;;;GASG;AAEH,eAAO,MAAM,8BAA8B,QAI5B,CAAC;AAKhB;;;;;GAKG;AAEH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,iBAAiB,GACxB,MAAM,CAMR;AAED,KAAK,aAAa,GAAG;IACnB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF;;;GAGG;AAEH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,aAAa,EACvD,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,iBAAiB,GACxB,CAAC,GAAG,CAAC,aAAa,GAAG;IAAE,QAAQ,CAAC,aAAa,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAiBvE;AAiBD,qEAAqE;AAErE,qBAAa,qBAAsB,SAAQ,KAAK;IAIlC,QAAQ,CAAC,aAAa,EAAE,mBAAmB;IAHvD,QAAQ,CAAC,IAAI,0BAA6B;IAC1C,QAAQ,CAAC,SAAS,SAAS;gBAEN,aAAa,EAAE,mBAAmB;CAIxD;AAED;;;GAGG;AAEH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,GACb,mBAAmB,GAAG,IAAI,CAkB5B;AAED,wDAAwD;AAExD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAQ5D"}
@@ -0,0 +1,201 @@
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
+ /*
19
+ * Per-request bounds for read-only engine work.
20
+ *
21
+ * The engine serves every client from one serialized SWI-Prolog queue, and a
22
+ * goal already running inside SWI cannot be cancelled from outside. A read
23
+ * that carries limits runs under call_with_time_limit/2 and
24
+ * call_with_inference_limit/3, so a runaway read ends inside Prolog and frees
25
+ * the queue. Hitting a limit is reported explicitly (limitExceeded) and is
26
+ * never presented as an empty or partial answer.
27
+ */
28
+ /** Envelope error code for a read stopped at its limit. */
29
+ // implements REQ-core-engine-read-limits
30
+ export const QUERY_LIMIT_EXCEEDED_CODE = "QUERY_LIMIT_EXCEEDED";
31
+ /** Environment opt-in for read limits on every engine client. */
32
+ // implements REQ-core-engine-read-limits
33
+ export const ENGINE_READ_TIME_LIMIT_ENV = "KIBI_ENGINE_READ_TIME_LIMIT_MS";
34
+ // implements REQ-core-engine-read-limits
35
+ export const ENGINE_READ_INFERENCE_LIMIT_ENV = "KIBI_ENGINE_READ_INFERENCE_LIMIT";
36
+ /**
37
+ * Upper bound for a requested time limit. The daemon's SWI process kills a
38
+ * query at 120 s and recycles the session; a bounded read must end first.
39
+ */
40
+ // implements REQ-core-engine-read-limits
41
+ export const ENGINE_READ_TIME_LIMIT_CAP_MS = 115_000;
42
+ const ENGINE_READ_INFERENCE_LIMIT_CAP = 1_000_000_000_000;
43
+ function boundedInteger(value, max) {
44
+ return typeof value === "number" &&
45
+ Number.isSafeInteger(value) &&
46
+ value > 0 &&
47
+ value <= max
48
+ ? value
49
+ : undefined;
50
+ }
51
+ /**
52
+ * Validate limits received over the engine socket. Out-of-range values are
53
+ * dropped (the read runs unbounded, as before); a time limit is capped below
54
+ * the hard per-query timeout.
55
+ */
56
+ // implements REQ-core-engine-read-limits
57
+ export function normalizeQueryLimits(value) {
58
+ if (value === null || typeof value !== "object")
59
+ return undefined;
60
+ const raw = value;
61
+ const requestedTime = boundedInteger(raw.timeMs, Number.MAX_SAFE_INTEGER);
62
+ const timeMs = requestedTime === undefined
63
+ ? undefined
64
+ : Math.min(requestedTime, ENGINE_READ_TIME_LIMIT_CAP_MS);
65
+ const inferences = boundedInteger(raw.inferences, ENGINE_READ_INFERENCE_LIMIT_CAP);
66
+ if (timeMs === undefined && inferences === undefined)
67
+ return undefined;
68
+ return {
69
+ ...(timeMs !== undefined ? { timeMs } : {}),
70
+ ...(inferences !== undefined ? { inferences } : {}),
71
+ };
72
+ }
73
+ /** Read limits configured through the environment, if any. */
74
+ // implements REQ-core-engine-read-limits
75
+ export function queryLimitsFromEnv(env = process.env) {
76
+ const parse = (name) => {
77
+ const raw = env[name]?.trim();
78
+ if (!raw)
79
+ return undefined;
80
+ const parsed = Number(raw);
81
+ return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined;
82
+ };
83
+ return normalizeQueryLimits({
84
+ timeMs: parse(ENGINE_READ_TIME_LIMIT_ENV),
85
+ inferences: parse(ENGINE_READ_INFERENCE_LIMIT_ENV),
86
+ });
87
+ }
88
+ /**
89
+ * Clauses the engine session defines at boot (and after a recycle) so a
90
+ * bounded read needs one call and one answer binding. Helper variables stay
91
+ * clause-local, so the toplevel prints only the goal's own bindings plus the
92
+ * outcome, whose compound value cannot be grouped with a goal's binding.
93
+ *
94
+ * A goal that swallows the limit exception itself (a catch-all inside a
95
+ * predicate) could otherwise return a partial answer or fail; measuring the
96
+ * elapsed time and inferences around the goal reports the limit regardless.
97
+ */
98
+ // implements REQ-core-engine-read-limits
99
+ export const BOUNDED_READ_HELPER_DEFINITION = `(current_predicate(kibi_engine_bounded_read/4) -> true ; ${[
100
+ "assertz((kibi_engine_bounded_read(Goal, Seconds, Inferences, kibi_read_outcome(Outcome)) :- get_time(T0), statistics(inferences, I0), (catch(kibi_engine_bounded_call(Goal, Seconds, Inferences, Inner), time_limit_exceeded, Inner = time) -> Failed = false ; Failed = true), get_time(T1), statistics(inferences, I1), (Inner == time -> Outcome = time ; Inner == inferences -> Outcome = inferences ; number(Seconds), T1 - T0 >= Seconds -> Outcome = time ; integer(Inferences), I1 - I0 >= Inferences -> Outcome = inferences ; Failed == true -> fail ; Outcome = none)))",
101
+ "assertz((kibi_engine_bounded_call(Goal, Seconds, Inferences, Inner) :- (number(Seconds) -> call_with_time_limit(Seconds, kibi_engine_inference_call(Goal, Inferences, Inner)) ; kibi_engine_inference_call(Goal, Inferences, Inner))))",
102
+ "assertz((kibi_engine_inference_call(Goal, Inferences, Inner) :- (integer(Inferences) -> call_with_inference_limit(Goal, Inferences, Result), (Result == inference_limit_exceeded -> Inner = inferences ; Inner = none) ; once(Goal), Inner = none)))",
103
+ ].join(", ")})`;
104
+ /** Answer binding that carries a bounded read's outcome. */
105
+ const OUTCOME_BINDING = "KibiReadOutcome";
106
+ /**
107
+ * Wrap a read-only goal in its limits. The goal's own variables keep their
108
+ * names, so its answer bindings are unchanged; the outcome arrives in the
109
+ * KibiReadOutcome binding that settleBoundedRead strips. The surrounding
110
+ * parentheses keep PrologProcess from caching a bounded answer.
111
+ */
112
+ // implements REQ-core-engine-read-limits
113
+ export function boundedReadGoal(goal, limits) {
114
+ const seconds = limits.timeMs === undefined ? "none" : (limits.timeMs / 1000).toFixed(3);
115
+ const inferences = limits.inferences === undefined ? "none" : String(limits.inferences);
116
+ return `(kibi_engine_bounded_read((${goal}), ${seconds}, ${inferences}, ${OUTCOME_BINDING}))`;
117
+ }
118
+ /**
119
+ * Turn a bounded read's answer back into the unbounded answer shape, or into
120
+ * an explicit limitExceeded failure when a limit stopped the goal.
121
+ */
122
+ // implements REQ-core-engine-read-limits
123
+ export function settleBoundedRead(result, limits) {
124
+ if (!result.success)
125
+ return result;
126
+ const { [OUTCOME_BINDING]: rawOutcome, ...bindings } = result.bindings;
127
+ const outcome = rawOutcome?.match(/^kibi_read_outcome\((\w+)\)$/)?.[1];
128
+ const hit = outcome === "time" && limits.timeMs !== undefined
129
+ ? { kind: "time", limit: limits.timeMs }
130
+ : outcome === "inferences" && limits.inferences !== undefined
131
+ ? { kind: "inferences", limit: limits.inferences }
132
+ : null;
133
+ if (hit === null)
134
+ return { ...result, bindings };
135
+ return {
136
+ success: false,
137
+ bindings: {},
138
+ error: queryLimitMessage(hit),
139
+ limitExceeded: hit,
140
+ };
141
+ }
142
+ /**
143
+ * The message names the limit in a fixed form, so the signal survives an
144
+ * executor that rewraps the error with its own prefix.
145
+ */
146
+ function queryLimitMessage(hit) {
147
+ const budget = hit.kind === "time"
148
+ ? `time limit of ${hit.limit} ms (${ENGINE_READ_TIME_LIMIT_ENV})`
149
+ : `inference limit of ${hit.limit} (${ENGINE_READ_INFERENCE_LIMIT_ENV})`;
150
+ return `${QUERY_LIMIT_EXCEEDED_CODE}: read stopped at its ${budget} before computing an answer. Narrow the query or raise the limit.`;
151
+ }
152
+ const QUERY_LIMIT_MESSAGE = /QUERY_LIMIT_EXCEEDED: read stopped at its (time|inference) limit of (\d+)/;
153
+ /** A read the engine stopped at its limit; never an empty answer. */
154
+ // implements REQ-core-engine-read-limits
155
+ export class EngineQueryLimitError extends Error {
156
+ limitExceeded;
157
+ code = QUERY_LIMIT_EXCEEDED_CODE;
158
+ retryable = false;
159
+ constructor(limitExceeded) {
160
+ super(queryLimitMessage(limitExceeded));
161
+ this.limitExceeded = limitExceeded;
162
+ this.name = "EngineQueryLimitError";
163
+ }
164
+ }
165
+ /**
166
+ * The limit that stopped a read, from the typed error or from the message an
167
+ * executor rewrapped it into; null for every other error.
168
+ */
169
+ // implements REQ-core-engine-read-limits
170
+ export function queryLimitExceededOf(error) {
171
+ if (!(error instanceof Error))
172
+ return null;
173
+ const typed = error.limitExceeded;
174
+ if (error.code === QUERY_LIMIT_EXCEEDED_CODE &&
175
+ typed !== null &&
176
+ typeof typed === "object") {
177
+ const { kind, limit } = typed;
178
+ if ((kind === "time" || kind === "inferences") && typeof limit === "number")
179
+ return { kind, limit };
180
+ }
181
+ const match = error.message.match(QUERY_LIMIT_MESSAGE);
182
+ if (match?.[1] === undefined || match[2] === undefined)
183
+ return null;
184
+ return {
185
+ kind: match[1] === "time" ? "time" : "inferences",
186
+ limit: Number(match[2]),
187
+ };
188
+ }
189
+ /** Reject an engine answer that reports a limit hit. */
190
+ // implements REQ-core-engine-read-limits
191
+ export function assertWithinQueryLimits(value) {
192
+ if (value === null || typeof value !== "object")
193
+ return;
194
+ const hit = value.limitExceeded;
195
+ if (hit === null || typeof hit !== "object")
196
+ return;
197
+ const { kind, limit } = hit;
198
+ if ((kind !== "time" && kind !== "inferences") || typeof limit !== "number")
199
+ return;
200
+ throw new EngineQueryLimitError({ kind, limit });
201
+ }
package/dist/engine.d.ts CHANGED
@@ -1,8 +1,11 @@
1
+ import { type EngineQueryLimits } from "./engine-limits.js";
1
2
  import type { EngineAttachmentIdentity, EngineCommandV1 } from "./engine-types.js";
2
3
  import { PrologProcess } from "./prolog.js";
3
4
  import type { PrologQueryResult } from "./public/operations/runtime-types.js";
4
5
  import type { PrologEntityQueryInput, PrologEntityQueryResult, PrologSearchQueryInput, PrologSearchQueryResult } from "./public/operations/runtime-types.js";
5
6
  export type { EngineAttachmentIdentity, EngineCommandV1, EngineRequest, } from "./engine-types.js";
7
+ export { EngineQueryLimitError, QUERY_LIMIT_EXCEEDED_CODE, queryLimitExceededOf, } from "./engine-limits.js";
8
+ export type { EngineLimitExceeded, EngineQueryLimits, } from "./engine-limits.js";
6
9
  export declare const ENGINE_PROTOCOL_VERSION = 1;
7
10
  export declare const ENGINE_IDLE_TIMEOUT_MS: number;
8
11
  export declare const ENGINE_PACKAGE_VERSIONS: string;
@@ -46,6 +49,12 @@ export type EngineClientOptions = {
46
49
  readonly timeout?: number;
47
50
  /** Internal stop-before-publish client may attach while it owns the lease. */
48
51
  readonly allowPublicationLock?: boolean;
52
+ /**
53
+ * Bounds for this client's read-only requests. Defaults to
54
+ * KIBI_ENGINE_READ_TIME_LIMIT_MS / KIBI_ENGINE_READ_INFERENCE_LIMIT; null
55
+ * sends none (sync and other maintenance clients).
56
+ */
57
+ readonly readLimits?: EngineQueryLimits | null;
49
58
  };
50
59
  /** PrologPort-compatible client used by CLI and MCP operation runtimes. */
51
60
  export declare class EngineClient {
@@ -53,6 +62,7 @@ export declare class EngineClient {
53
62
  private readonly branch;
54
63
  private readonly timeout;
55
64
  private readonly allowPublicationLock;
65
+ private readonly readLimits;
56
66
  private socket;
57
67
  private daemon;
58
68
  private inputBuffer;
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
package/dist/engine.js CHANGED
@@ -13,6 +13,7 @@ import * as os from "node:os";
13
13
  import * as path from "node:path";
14
14
  import { performance } from "node:perf_hooks";
15
15
  import { fileURLToPath } from "node:url";
16
+ import { BOUNDED_READ_HELPER_DEFINITION, assertWithinQueryLimits, boundedReadGoal, normalizeQueryLimits, queryLimitsFromEnv, settleBoundedRead, } from "./engine-limits.js";
16
17
  import { writePerformanceTraceEvent } from "./performance-trace.js";
17
18
  import { PrologProcess, resolveKbPlPath } from "./prolog.js";
18
19
  import { parseEntityFromList, parseListOfLists } from "./prolog/codec.js";
@@ -22,6 +23,14 @@ import { queryEntityChunks } from "./public/operations/discovery-entities.js";
22
23
  import { isValidBranchName } from "./utils/branch-resolver.js";
23
24
  import { branchStorePath, ensureBranchStoreManifest, } from "./utils/branch-store-locator.js";
24
25
  import { canonicalFilesystemPath } from "./utils/canonical-path.js";
26
+ export { EngineQueryLimitError, QUERY_LIMIT_EXCEEDED_CODE, queryLimitExceededOf, } from "./engine-limits.js";
27
+ /** Request methods whose read-only work may carry per-request limits. */
28
+ const READ_LIMITED_METHODS = new Set([
29
+ "query",
30
+ "command",
31
+ "entities",
32
+ "search",
33
+ ]);
25
34
  export const ENGINE_PROTOCOL_VERSION = 1;
26
35
  export const ENGINE_IDLE_TIMEOUT_MS = 10 * 60 * 1000;
27
36
  export const ENGINE_PACKAGE_VERSIONS = process.env.KIBI_PACKAGE_VERSIONS ?? "unknown";
@@ -727,6 +736,7 @@ export class EngineClient {
727
736
  branch;
728
737
  timeout;
729
738
  allowPublicationLock;
739
+ readLimits;
730
740
  socket = null;
731
741
  daemon = null;
732
742
  inputBuffer = Buffer.alloc(0);
@@ -743,6 +753,10 @@ export class EngineClient {
743
753
  this.branch = options.branch;
744
754
  this.timeout = options.timeout ?? 120_000;
745
755
  this.allowPublicationLock = options.allowPublicationLock ?? false;
756
+ this.readLimits =
757
+ options.readLimits === undefined
758
+ ? queryLimitsFromEnv()
759
+ : (options.readLimits ?? undefined);
746
760
  }
747
761
  async start(allowSpawn = true) {
748
762
  const wasConnected = this.socket !== null && !this.socket.destroyed;
@@ -948,7 +962,11 @@ export class EngineClient {
948
962
  if (socket === null || socket.destroyed)
949
963
  throw new Error("Kibi engine is not connected");
950
964
  const id = ++this.requestId;
951
- return await new Promise((resolve, reject) => {
965
+ const limits = this.readLimits !== undefined &&
966
+ READ_LIMITED_METHODS.has(request.method)
967
+ ? { limits: this.readLimits }
968
+ : {};
969
+ const value = await new Promise((resolve, reject) => {
952
970
  this.pending.set(id, {
953
971
  resolve: resolve,
954
972
  reject,
@@ -957,6 +975,7 @@ export class EngineClient {
957
975
  try {
958
976
  socket.write(frame({
959
977
  ...request,
978
+ ...limits,
960
979
  id,
961
980
  protocolVersion: ENGINE_PROTOCOL_VERSION,
962
981
  packageVersions: ENGINE_PACKAGE_VERSIONS,
@@ -988,6 +1007,10 @@ export class EngineClient {
988
1007
  signal.addEventListener("abort", abort, { once: true });
989
1008
  }
990
1009
  });
1010
+ // A bounded read stopped at its limit has no answer; never let it pass
1011
+ // as an empty or failed lookup.
1012
+ assertWithinQueryLimits(value);
1013
+ return value;
991
1014
  }
992
1015
  finally {
993
1016
  release();
@@ -1621,6 +1644,20 @@ export async function runEngineDaemon(requestedOptions) {
1621
1644
  let queue = Promise.resolve();
1622
1645
  let idleCompactionQueued = false;
1623
1646
  const queryCache = new Map();
1647
+ // The bounded-read helper lives in the Prolog session; a recycled session
1648
+ // (new pid) defines it again before its first bounded read.
1649
+ let boundedReadHelperPid = null;
1650
+ const runBoundedRead = async (goal, limits) => {
1651
+ const pid = prolog.getPid();
1652
+ if (boundedReadHelperPid !== pid) {
1653
+ const defined = await prolog.query(BOUNDED_READ_HELPER_DEFINITION);
1654
+ if (!defined.success) {
1655
+ throw new Error(defined.error ?? "Failed to define the bounded-read helper");
1656
+ }
1657
+ boundedReadHelperPid = pid;
1658
+ }
1659
+ return settleBoundedRead(await prolog.query(boundedReadGoal(goal, limits)), limits);
1660
+ };
1624
1661
  let freshnessCache = null;
1625
1662
  const clients = new Set();
1626
1663
  let shuttingDown = false;
@@ -1727,6 +1764,11 @@ export async function runEngineDaemon(requestedOptions) {
1727
1764
  freshnessCache = null;
1728
1765
  attachedIdentity = readEngineAttachmentIdentity(branchPath);
1729
1766
  }
1767
+ // Read-only work runs inside the request's limits, when it has any.
1768
+ const readLimits = normalizeQueryLimits(request.limits);
1769
+ const runRead = (goal) => readLimits === undefined
1770
+ ? prolog.query(goal)
1771
+ : runBoundedRead(goal, readLimits);
1730
1772
  switch (request.method) {
1731
1773
  case "entities": {
1732
1774
  const limit = request.limit ?? 100;
@@ -1750,8 +1792,8 @@ export async function runEngineDaemon(requestedOptions) {
1750
1792
  const source = request.sourceFile === undefined
1751
1793
  ? "none"
1752
1794
  : `'${quoteProlog(request.sourceFile)}'`;
1753
- const result = await prolog.query(`kb_query_entities(${type}, ${id}, ${tags}, ${source}, ${limit}, ${offset}, Rows, Count)`);
1754
- if (!result.success) {
1795
+ const result = await runRead(`kb_query_entities(${type}, ${id}, ${tags}, ${source}, ${limit}, ${offset}, Rows, Count)`);
1796
+ if (!result.success && result.limitExceeded === undefined) {
1755
1797
  throw new Error(result.error ?? "Indexed entity query failed");
1756
1798
  }
1757
1799
  return result;
@@ -1773,8 +1815,8 @@ export async function runEngineDaemon(requestedOptions) {
1773
1815
  const type = request.type === undefined
1774
1816
  ? "none"
1775
1817
  : `'${quoteProlog(request.type)}'`;
1776
- const result = await prolog.query(`kb_search_entities(${type}, '${quoteProlog(request.searchQuery)}', ${limit}, ${offset}, Rows, Count)`);
1777
- if (!result.success) {
1818
+ const result = await runRead(`kb_search_entities(${type}, '${quoteProlog(request.searchQuery)}', ${limit}, ${offset}, Rows, Count)`);
1819
+ if (!result.success && result.limitExceeded === undefined) {
1778
1820
  throw new Error(result.error ?? "Indexed search candidate query failed");
1779
1821
  }
1780
1822
  return result;
@@ -1814,7 +1856,7 @@ export async function runEngineDaemon(requestedOptions) {
1814
1856
  }
1815
1857
  // Rule selection is intentionally resolved inside the engine. A
1816
1858
  // caller never supplies a Prolog goal over the command boundary.
1817
- return prolog.query("checks:check_all_json(JsonString)");
1859
+ return runRead("checks:check_all_json(JsonString)");
1818
1860
  }
1819
1861
  case "relationship": {
1820
1862
  if (!command.type || !command.from || !command.to) {
@@ -1888,7 +1930,7 @@ export async function runEngineDaemon(requestedOptions) {
1888
1930
  const source = command.sourceFile === undefined
1889
1931
  ? "none"
1890
1932
  : `'${quoteProlog(command.sourceFile)}'`;
1891
- return prolog.query(`kb_query_entities(${type}, ${id}, ${tags}, ${source}, ${command.limit}, ${command.offset}, Rows, Count)`);
1933
+ return runRead(`kb_query_entities(${type}, ${id}, ${tags}, ${source}, ${command.limit}, ${command.offset}, Rows, Count)`);
1892
1934
  }
1893
1935
  case "search": {
1894
1936
  if (!command.query.trim())
@@ -1903,7 +1945,7 @@ export async function runEngineDaemon(requestedOptions) {
1903
1945
  const type = command.type === undefined
1904
1946
  ? "none"
1905
1947
  : `'${quoteProlog(command.type)}'`;
1906
- return prolog.query(`kb_search_entities(${type}, '${quoteProlog(command.query)}', ${command.limit}, ${command.offset}, Rows, Count)`);
1948
+ return runRead(`kb_search_entities(${type}, '${quoteProlog(command.query)}', ${command.limit}, ${command.offset}, Rows, Count)`);
1907
1949
  }
1908
1950
  default:
1909
1951
  throw new Error("engine.command kind is unsupported");
@@ -1950,7 +1992,13 @@ export async function runEngineDaemon(requestedOptions) {
1950
1992
  return cached;
1951
1993
  }
1952
1994
  }
1953
- const result = await prolog.query(request.goal);
1995
+ // Writes and module loads always run to completion; a limit may
1996
+ // only stop a read.
1997
+ const boundable = !mutatingEngineGoal(request.goal) &&
1998
+ !/\b(?:use_module|consult|load_files|ensure_loaded)\s*\(/.test(request.goal);
1999
+ const result = boundable
2000
+ ? await runRead(request.goal)
2001
+ : await prolog.query(request.goal);
1954
2002
  session.recordModuleLoad(request.goal, result);
1955
2003
  if (result.success && mutatingEngineGoal(request.goal)) {
1956
2004
  fsyncJournaledBranchStore(branchPath);
@@ -1,3 +1,4 @@
1
+ import { type EntityOrigin } from "../public/entity-origin.js";
1
2
  export interface ExtractedEntity {
2
3
  id: string;
3
4
  type: string;
@@ -12,6 +13,7 @@ export interface ExtractedEntity {
12
13
  severity?: string;
13
14
  text_ref?: string;
14
15
  granularity_reason?: string;
16
+ origin?: EntityOrigin;
15
17
  }
16
18
  export interface ExtractedRelationship {
17
19
  type: string;
@@ -71,5 +73,11 @@ export interface ReceiptCodeScopeEntry {
71
73
  readonly symbolId: string;
72
74
  readonly sourceHash: string;
73
75
  }
76
+ /**
77
+ * Scope hash of a symbol whose recorded source file lies outside the
78
+ * repository. Only repository content can be compared between a CI checkout
79
+ * and a developer machine, so such a file is never read.
80
+ */
81
+ export declare const OUTSIDE_WORKSPACE_SCOPE_HASH = "outside-workspace";
74
82
  export declare function resolveBoundSymbolScope(manifestPath: string, symbolIds: readonly string[]): ReceiptCodeScopeEntry[];
75
83
  //# sourceMappingURL=manifest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/extractors/manifest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/extractors/manifest.ts"],"names":[],"mappings":"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"}
@@ -19,7 +19,9 @@ import { createHash } from "node:crypto";
19
19
  import { existsSync, readFileSync, statSync } from "node:fs";
20
20
  import * as path from "node:path";
21
21
  import { load as parseYAML } from "js-yaml";
22
+ import { normalizeEntityOrigin, } from "../public/entity-origin.js";
22
23
  import { DEFAULT_COORDINATES_PATH } from "../utils/manifest-paths.js";
24
+ import { normalizeRepoRelativePath } from "../utils/repo-relative-path.js";
23
25
  import { mergeCoordinatesWithManifest, parseCoordinateArtifact, } from "./symbol-coordinates.js";
24
26
  const VALID_RELATIONSHIP_TYPES = new Set([
25
27
  "depends_on",
@@ -38,6 +40,8 @@ const VALID_RELATIONSHIP_TYPES = new Set([
38
40
  "consumes",
39
41
  "supersedes",
40
42
  "restates",
43
+ "assumes",
44
+ "exempts",
41
45
  "relates_to",
42
46
  ]);
43
47
  const VALID_RELATIONSHIP_DIRECTIONS = [
@@ -62,6 +66,8 @@ const VALID_RELATIONSHIP_DIRECTIONS = [
62
66
  { type: "supersedes", from: "adr", to: "adr" },
63
67
  { type: "supersedes", from: "req", to: "req" },
64
68
  { type: "restates", from: "req", to: "req" },
69
+ { type: "assumes", from: "scenario", to: "fact" },
70
+ { type: "exempts", from: "req", to: "req" },
65
71
  ];
66
72
  const RELATIONSHIP_TYPE_DISPLAY_LIST = Array.from(VALID_RELATIONSHIP_TYPES)
67
73
  .sort()
@@ -183,6 +189,15 @@ export function extractManifestSymbolRecords(manifestSymbols, filePath) {
183
189
  throw new ManifestError("Missing required field: title", filePath);
184
190
  }
185
191
  const id = symbol.id || generateId(filePath, symbol.title);
192
+ // implements REQ-004
193
+ let origin;
194
+ if (symbol.origin !== undefined) {
195
+ const normalized = normalizeEntityOrigin(symbol.origin);
196
+ if ("error" in normalized) {
197
+ throw new ManifestError(`Invalid origin for symbol ${id}: ${normalized.error}`, filePath);
198
+ }
199
+ origin = normalized.origin;
200
+ }
186
201
  const entity = {
187
202
  id,
188
203
  type: "symbol",
@@ -199,6 +214,7 @@ export function extractManifestSymbolRecords(manifestSymbols, filePath) {
199
214
  ...(symbol.granularity_reason !== undefined
200
215
  ? { granularity_reason: symbol.granularity_reason }
201
216
  : {}),
217
+ ...(origin !== undefined ? { origin } : {}),
202
218
  ...(typeof symbol.symbol_kind === "string"
203
219
  ? { symbol_kind: symbol.symbol_kind }
204
220
  : {}),
@@ -386,23 +402,36 @@ function scopeFileHash(absolutePath) {
386
402
  scopeFileHashCache.set(absolutePath, { stamp, hash });
387
403
  return hash;
388
404
  }
405
+ /**
406
+ * Scope hash of a symbol whose recorded source file lies outside the
407
+ * repository. Only repository content can be compared between a CI checkout
408
+ * and a developer machine, so such a file is never read.
409
+ */
410
+ // implements REQ-kibi-fresh-verification-receipts-v2
411
+ export const OUTSIDE_WORKSPACE_SCOPE_HASH = "outside-workspace";
412
+ // implements REQ-kibi-fresh-verification-receipts-v2
389
413
  export function resolveBoundSymbolScope(manifestPath, symbolIds) {
390
414
  const wanted = [...new Set(symbolIds)];
391
415
  if (wanted.length === 0)
392
416
  return [];
393
417
  const sourceFiles = scopeSourceFiles(manifestPath);
394
418
  // The manifest lives at <workspace>/.kb/symbols.yaml; source files are
395
- // workspace-relative.
419
+ // workspace-relative. Every recorded path is normalized to its
420
+ // repo-relative form first, so `./a.ts`, `a\b.ts` and an absolute path
421
+ // inside this checkout hash the same file wherever the checkout lives.
396
422
  const workspaceRoot = path.dirname(path.dirname(path.resolve(manifestPath)));
397
423
  const scope = [];
398
424
  for (const symbolId of wanted) {
399
425
  const sourceFile = sourceFiles.get(symbolId);
400
426
  if (sourceFile === undefined)
401
427
  continue;
402
- const absolute = path.isAbsolute(sourceFile)
403
- ? sourceFile
404
- : path.resolve(workspaceRoot, sourceFile);
405
- scope.push({ symbolId, sourceHash: scopeFileHash(absolute) });
428
+ const relative = normalizeRepoRelativePath(workspaceRoot, sourceFile);
429
+ scope.push({
430
+ symbolId,
431
+ sourceHash: relative === null
432
+ ? OUTSIDE_WORKSPACE_SCOPE_HASH
433
+ : scopeFileHash(path.join(workspaceRoot, relative)),
434
+ });
406
435
  }
407
436
  scope.sort((left, right) => left.symbolId.localeCompare(right.symbolId));
408
437
  return scope;