kibi-cli 2.0.0 → 2.2.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 (377) hide show
  1. package/dist/cli-protocol.d.ts.map +1 -1
  2. package/dist/cli-protocol.js +3 -2
  3. package/dist/cli-register-proof.d.ts.map +1 -1
  4. package/dist/cli-register-proof.js +25 -1
  5. package/dist/cli-register-reporting.d.ts.map +1 -1
  6. package/dist/cli-register-reporting.js +6 -0
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +2 -0
  9. package/dist/commands/aggregated-checks.d.ts +7 -0
  10. package/dist/commands/aggregated-checks.d.ts.map +1 -1
  11. package/dist/commands/aggregated-checks.js +25 -1
  12. package/dist/commands/check-generated.d.ts +7 -0
  13. package/dist/commands/check-generated.d.ts.map +1 -0
  14. package/dist/commands/check-generated.js +192 -0
  15. package/dist/commands/check.d.ts.map +1 -1
  16. package/dist/commands/check.js +24 -15
  17. package/dist/commands/doctor.d.ts.map +1 -1
  18. package/dist/commands/doctor.js +227 -25
  19. package/dist/commands/engine.d.ts.map +1 -1
  20. package/dist/commands/engine.js +3 -1
  21. package/dist/commands/github-init.d.ts +1 -1
  22. package/dist/commands/github-init.d.ts.map +1 -1
  23. package/dist/commands/github-init.js +1 -1
  24. package/dist/commands/init-helpers.d.ts +17 -2
  25. package/dist/commands/init-helpers.d.ts.map +1 -1
  26. package/dist/commands/init-helpers.js +136 -30
  27. package/dist/commands/init.d.ts.map +1 -1
  28. package/dist/commands/init.js +110 -15
  29. package/dist/commands/proof-explain.d.ts +10 -0
  30. package/dist/commands/proof-explain.d.ts.map +1 -0
  31. package/dist/commands/proof-explain.js +45 -0
  32. package/dist/commands/proof-impact.d.ts +7 -0
  33. package/dist/commands/proof-impact.d.ts.map +1 -0
  34. package/dist/commands/proof-impact.js +39 -0
  35. package/dist/commands/proof-migrate-legacy.js +1 -1
  36. package/dist/commands/proof-prune.js +1 -1
  37. package/dist/commands/prove.d.ts.map +1 -1
  38. package/dist/commands/prove.js +14 -22
  39. package/dist/commands/report.d.ts.map +1 -1
  40. package/dist/commands/report.js +17 -2
  41. package/dist/commands/sync/cache.d.ts +20 -1
  42. package/dist/commands/sync/cache.d.ts.map +1 -1
  43. package/dist/commands/sync/cache.js +51 -2
  44. package/dist/commands/sync/discovery.d.ts.map +1 -1
  45. package/dist/commands/sync/discovery.js +1 -1
  46. package/dist/commands/sync/manifest.d.ts +1 -0
  47. package/dist/commands/sync/manifest.d.ts.map +1 -1
  48. package/dist/commands/sync/manifest.js +18 -16
  49. package/dist/commands/sync/persistence.d.ts.map +1 -1
  50. package/dist/commands/sync/persistence.js +14 -0
  51. package/dist/commands/sync.d.ts.map +1 -1
  52. package/dist/commands/sync.js +11 -3
  53. package/dist/engine.d.ts +29 -1
  54. package/dist/engine.d.ts.map +1 -1
  55. package/dist/engine.js +259 -89
  56. package/dist/env/bootstrap.d.ts +84 -0
  57. package/dist/env/bootstrap.d.ts.map +1 -0
  58. package/dist/env/bootstrap.js +310 -0
  59. package/dist/extractors/manifest.d.ts.map +1 -1
  60. package/dist/extractors/manifest.js +67 -29
  61. package/dist/extractors/markdown.d.ts +4 -0
  62. package/dist/extractors/markdown.d.ts.map +1 -1
  63. package/dist/extractors/markdown.js +33 -3
  64. package/dist/extractors/relationships.d.ts.map +1 -1
  65. package/dist/extractors/relationships.js +1 -0
  66. package/dist/extractors/symbols-coordinator.d.ts +8 -0
  67. package/dist/extractors/symbols-coordinator.d.ts.map +1 -1
  68. package/dist/extractors/symbols-coordinator.js +40 -0
  69. package/dist/extractors/symbols-ts.d.ts +8 -19
  70. package/dist/extractors/symbols-ts.d.ts.map +1 -1
  71. package/dist/extractors/symbols-ts.js +33 -503
  72. package/dist/intent-search.d.ts.map +1 -1
  73. package/dist/intent-search.js +68 -30
  74. package/dist/operations/bootstrap/generate.d.ts.map +1 -1
  75. package/dist/operations/bootstrap/generate.js +4 -3
  76. package/dist/operations/modeling/model-requirement.d.ts +1 -1
  77. package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
  78. package/dist/operations/modeling/model-requirement.js +179 -9
  79. package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
  80. package/dist/operations/modeling/predicate-applyplan.js +14 -2
  81. package/dist/operations/modeling/predicate-loader.d.ts.map +1 -1
  82. package/dist/operations/modeling/predicate-loader.js +24 -0
  83. package/dist/operations/modeling/predicate-types.d.ts +4 -0
  84. package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
  85. package/dist/operations/modeling/predicate-vocabulary.d.ts +54 -0
  86. package/dist/operations/modeling/predicate-vocabulary.d.ts.map +1 -0
  87. package/dist/operations/modeling/predicate-vocabulary.js +169 -0
  88. package/dist/operations/modeling/requirement-types.d.ts +5 -0
  89. package/dist/operations/modeling/requirement-types.d.ts.map +1 -1
  90. package/dist/operations/modeling/suggest-predicates.d.ts +1 -1
  91. package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
  92. package/dist/operations/modeling/suggest-predicates.js +30 -3
  93. package/dist/operations/modeling/vocabulary-alignment.d.ts +60 -0
  94. package/dist/operations/modeling/vocabulary-alignment.d.ts.map +1 -0
  95. package/dist/operations/modeling/vocabulary-alignment.js +178 -0
  96. package/dist/operations/mutation/contradictions.d.ts +3 -0
  97. package/dist/operations/mutation/contradictions.d.ts.map +1 -1
  98. package/dist/operations/mutation/contradictions.js +29 -0
  99. package/dist/operations/mutation/delete.d.ts.map +1 -1
  100. package/dist/operations/mutation/delete.js +33 -1
  101. package/dist/operations/mutation/predicate-vocabulary-guard.d.ts +8 -0
  102. package/dist/operations/mutation/predicate-vocabulary-guard.d.ts.map +1 -0
  103. package/dist/operations/mutation/predicate-vocabulary-guard.js +64 -0
  104. package/dist/operations/mutation/relationships.d.ts +1 -1
  105. package/dist/operations/mutation/relationships.d.ts.map +1 -1
  106. package/dist/operations/mutation/relationships.js +1 -0
  107. package/dist/operations/mutation/saga.d.ts +5 -0
  108. package/dist/operations/mutation/saga.d.ts.map +1 -1
  109. package/dist/operations/mutation/saga.js +10 -0
  110. package/dist/operations/mutation/serialization.d.ts.map +1 -1
  111. package/dist/operations/mutation/serialization.js +2 -0
  112. package/dist/operations/mutation/source-authoring.d.ts +6 -0
  113. package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
  114. package/dist/operations/mutation/source-authoring.js +65 -26
  115. package/dist/operations/mutation/strict-fact.d.ts.map +1 -1
  116. package/dist/operations/mutation/strict-fact.js +5 -0
  117. package/dist/operations/mutation/symbol-granularity.d.ts.map +1 -1
  118. package/dist/operations/mutation/symbol-granularity.js +9 -87
  119. package/dist/operations/mutation/types.d.ts +17 -0
  120. package/dist/operations/mutation/types.d.ts.map +1 -1
  121. package/dist/operations/mutation/upsert.d.ts +6 -0
  122. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  123. package/dist/operations/mutation/upsert.js +72 -4
  124. package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
  125. package/dist/operations/mutation/validate-upsert.js +24 -1
  126. package/dist/operations/mutation/validation.d.ts.map +1 -1
  127. package/dist/operations/mutation/validation.js +16 -3
  128. package/dist/operations/planning/apply-plan.d.ts.map +1 -1
  129. package/dist/operations/planning/apply-plan.js +61 -17
  130. package/dist/operations/planning/compile-intent.d.ts +49 -0
  131. package/dist/operations/planning/compile-intent.d.ts.map +1 -1
  132. package/dist/operations/planning/compile-intent.js +66 -4
  133. package/dist/operations/proof/baseline-diff.d.ts +41 -0
  134. package/dist/operations/proof/baseline-diff.d.ts.map +1 -0
  135. package/dist/operations/proof/baseline-diff.js +153 -0
  136. package/dist/operations/proof/code-scope.d.ts +17 -0
  137. package/dist/operations/proof/code-scope.d.ts.map +1 -0
  138. package/dist/operations/proof/code-scope.js +60 -0
  139. package/dist/operations/proof/explain.d.ts +75 -0
  140. package/dist/operations/proof/explain.d.ts.map +1 -0
  141. package/dist/operations/proof/explain.js +294 -0
  142. package/dist/operations/proof/impact.d.ts +45 -0
  143. package/dist/operations/proof/impact.d.ts.map +1 -0
  144. package/dist/operations/proof/impact.js +118 -0
  145. package/dist/operations/proof/ingest-proof.d.ts +4 -2
  146. package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
  147. package/dist/operations/proof/ingest-proof.js +251 -77
  148. package/dist/operations/proof/migrate-legacy-receipts.d.ts.map +1 -1
  149. package/dist/operations/proof/migrate-legacy-receipts.js +28 -22
  150. package/dist/operations/proof/prune-receipts.d.ts.map +1 -1
  151. package/dist/operations/proof/prune-receipts.js +8 -6
  152. package/dist/operations/proof/receipt-document.js +2 -2
  153. package/dist/operations/semantic-advisor/analysis-receipt.d.ts.map +1 -1
  154. package/dist/operations/semantic-advisor/analysis-receipt.js +3 -9
  155. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  156. package/dist/operations/semantic-advisor/analyze-prose.js +18 -67
  157. package/dist/operations/semantic-advisor/plugin-orchestration.d.ts +63 -0
  158. package/dist/operations/semantic-advisor/plugin-orchestration.d.ts.map +1 -0
  159. package/dist/operations/semantic-advisor/plugin-orchestration.js +489 -0
  160. package/dist/operations/semantic-advisor/predicate-rules-core.d.ts +15 -2
  161. package/dist/operations/semantic-advisor/predicate-rules-core.d.ts.map +1 -1
  162. package/dist/operations/semantic-advisor/predicate-rules-core.js +7 -140
  163. package/dist/operations/semantic-advisor/predicate-rules-launcher.d.ts +11 -12
  164. package/dist/operations/semantic-advisor/predicate-rules-launcher.d.ts.map +1 -1
  165. package/dist/operations/semantic-advisor/predicate-rules-launcher.js +6 -94
  166. package/dist/operations/semantic-advisor/predicate-rules-policy.d.ts +16 -0
  167. package/dist/operations/semantic-advisor/predicate-rules-policy.d.ts.map +1 -1
  168. package/dist/operations/semantic-advisor/predicate-rules-policy.js +7 -150
  169. package/dist/operations/semantic-advisor/predicate-rules-product-tail.d.ts +9 -0
  170. package/dist/operations/semantic-advisor/predicate-rules-product-tail.d.ts.map +1 -1
  171. package/dist/operations/semantic-advisor/predicate-rules-product-tail.js +7 -102
  172. package/dist/operations/semantic-advisor/predicate-rules-product.d.ts +13 -0
  173. package/dist/operations/semantic-advisor/predicate-rules-product.d.ts.map +1 -1
  174. package/dist/operations/semantic-advisor/predicate-rules-product.js +7 -133
  175. package/dist/operations/semantic-advisor/types.d.ts +1 -0
  176. package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
  177. package/dist/plugins/compose-ontology-packs.d.ts +51 -0
  178. package/dist/plugins/compose-ontology-packs.d.ts.map +1 -0
  179. package/dist/plugins/compose-ontology-packs.js +257 -0
  180. package/dist/plugins/compose-semantic-classifier.d.ts +47 -0
  181. package/dist/plugins/compose-semantic-classifier.d.ts.map +1 -0
  182. package/dist/plugins/compose-semantic-classifier.js +216 -0
  183. package/dist/plugins/compose-vocabulary-alignment.d.ts +23 -0
  184. package/dist/plugins/compose-vocabulary-alignment.d.ts.map +1 -0
  185. package/dist/plugins/compose-vocabulary-alignment.js +141 -0
  186. package/dist/plugins/external-allowlist.d.ts +17 -0
  187. package/dist/plugins/external-allowlist.d.ts.map +1 -0
  188. package/dist/plugins/external-allowlist.js +29 -0
  189. package/dist/plugins/index.d.ts +11 -0
  190. package/dist/plugins/index.d.ts.map +1 -0
  191. package/dist/plugins/index.js +37 -0
  192. package/dist/plugins/load-plugin.d.ts +19 -0
  193. package/dist/plugins/load-plugin.d.ts.map +1 -0
  194. package/dist/plugins/load-plugin.js +59 -0
  195. package/dist/plugins/project-config.d.ts +28 -0
  196. package/dist/plugins/project-config.d.ts.map +1 -0
  197. package/dist/plugins/project-config.js +90 -0
  198. package/dist/plugins/registry.d.ts +94 -0
  199. package/dist/plugins/registry.d.ts.map +1 -0
  200. package/dist/plugins/registry.js +359 -0
  201. package/dist/plugins/resolve-package.d.ts +47 -0
  202. package/dist/plugins/resolve-package.d.ts.map +1 -0
  203. package/dist/plugins/resolve-package.js +262 -0
  204. package/dist/plugins/source-analysis-service.d.ts +44 -0
  205. package/dist/plugins/source-analysis-service.d.ts.map +1 -0
  206. package/dist/plugins/source-analysis-service.js +232 -0
  207. package/dist/prolog/codec.d.ts.map +1 -1
  208. package/dist/prolog/codec.js +2 -0
  209. package/dist/prolog/janitor.d.ts.map +1 -1
  210. package/dist/prolog/janitor.js +1 -1
  211. package/dist/prolog/store-lock.d.ts +1 -1
  212. package/dist/prolog/store-lock.d.ts.map +1 -1
  213. package/dist/prolog.d.ts +36 -0
  214. package/dist/prolog.d.ts.map +1 -1
  215. package/dist/prolog.js +78 -9
  216. package/dist/proof/inspect.js +1 -1
  217. package/dist/proof/producers/playwright-case-id.js +2 -2
  218. package/dist/proof/producers/playwright-reporter.js +4 -4
  219. package/dist/public/diagnostic-usage.d.ts.map +1 -1
  220. package/dist/public/diagnostic-usage.js +7 -25
  221. package/dist/public/extractors/symbols-coordinator.d.ts +1 -1
  222. package/dist/public/extractors/symbols-coordinator.d.ts.map +1 -1
  223. package/dist/public/extractors/symbols-coordinator.js +1 -1
  224. package/dist/public/impact/analyzer.d.ts +1 -1
  225. package/dist/public/impact/analyzer.d.ts.map +1 -1
  226. package/dist/public/impact/analyzer.js +6 -4
  227. package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
  228. package/dist/public/impact/full-kb-quality.js +4 -12
  229. package/dist/public/operations/catalog.d.ts +39 -7
  230. package/dist/public/operations/catalog.d.ts.map +1 -1
  231. package/dist/public/operations/check-executor.d.ts.map +1 -1
  232. package/dist/public/operations/check-executor.js +11 -3
  233. package/dist/public/operations/check-helpers.d.ts +7 -1
  234. package/dist/public/operations/check-helpers.d.ts.map +1 -1
  235. package/dist/public/operations/check-helpers.js +22 -2
  236. package/dist/public/operations/contracts.d.ts.map +1 -1
  237. package/dist/public/operations/contracts.js +51 -12
  238. package/dist/public/operations/discovery-entities.d.ts +53 -1
  239. package/dist/public/operations/discovery-entities.d.ts.map +1 -1
  240. package/dist/public/operations/discovery-entities.js +219 -12
  241. package/dist/public/operations/discovery-executors.d.ts +1 -0
  242. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  243. package/dist/public/operations/discovery-executors.js +93 -59
  244. package/dist/public/operations/migration-plan.d.ts +2 -0
  245. package/dist/public/operations/migration-plan.d.ts.map +1 -1
  246. package/dist/public/operations/migration-plan.js +50 -0
  247. package/dist/public/operations/predicate-schema-conformance.d.ts +41 -0
  248. package/dist/public/operations/predicate-schema-conformance.d.ts.map +1 -0
  249. package/dist/public/operations/predicate-schema-conformance.js +242 -0
  250. package/dist/public/operations/prolog-json.d.ts +1 -1
  251. package/dist/public/operations/prolog-json.d.ts.map +1 -1
  252. package/dist/public/operations/prolog-json.js +16 -10
  253. package/dist/public/operations/result-envelope.d.ts +34 -1
  254. package/dist/public/operations/result-envelope.d.ts.map +1 -1
  255. package/dist/public/operations/result-envelope.js +78 -2
  256. package/dist/public/operations/runtime-types.d.ts +17 -2
  257. package/dist/public/operations/runtime-types.d.ts.map +1 -1
  258. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  259. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  260. package/dist/public/operations/specs/check-rules.generated.js +9 -1
  261. package/dist/public/operations/specs/check.d.ts +1 -1
  262. package/dist/public/operations/specs/discovery.d.ts +10 -1
  263. package/dist/public/operations/specs/discovery.d.ts.map +1 -1
  264. package/dist/public/operations/specs/discovery.js +10 -1
  265. package/dist/public/operations/specs/mutation-schemas.d.ts +27 -4
  266. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  267. package/dist/public/operations/specs/mutation-schemas.js +21 -3
  268. package/dist/public/operations/specs/proof.js +1 -1
  269. package/dist/public/operations/specs/reporting.d.ts +9 -0
  270. package/dist/public/operations/specs/reporting.d.ts.map +1 -1
  271. package/dist/public/operations/specs/reporting.js +48 -17
  272. package/dist/public/operations/specs/semantic.d.ts +1 -1
  273. package/dist/public/operations/specs/semantic.d.ts.map +1 -1
  274. package/dist/public/operations/specs/semantic.js +54 -4
  275. package/dist/public/operations/specs/upsert.d.ts +28 -5
  276. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  277. package/dist/public/operations/specs/upsert.js +1 -1
  278. package/dist/public/operations/symbol-repair-plan.d.ts.map +1 -1
  279. package/dist/public/operations/symbol-repair-plan.js +11 -4
  280. package/dist/public/operations/types.d.ts +5 -0
  281. package/dist/public/operations/types.d.ts.map +1 -1
  282. package/dist/public/proof-protocol.js +4 -4
  283. package/dist/public/schemas/entity.d.ts.map +1 -1
  284. package/dist/public/schemas/entity.js +22 -0
  285. package/dist/public/schemas/relationship.d.ts.map +1 -1
  286. package/dist/public/schemas/relationship.js +1 -0
  287. package/dist/public/skills/kibi-usage/SKILL.md +10 -3
  288. package/dist/public/skills/kibi-usage/resources/fact-lanes.md +4 -0
  289. package/dist/public/skills/kibi-usage/resources/proof.md +45 -0
  290. package/dist/public/skills/kibi-usage/resources/relationship-directions.md +35 -17
  291. package/dist/public/skills/kibi-usage/resources/source-authoring.md +36 -0
  292. package/dist/public/skills/kibi-usage/resources/workflows.md +52 -1
  293. package/dist/public/symbol-granularity.d.ts +1 -1
  294. package/dist/public/symbol-granularity.d.ts.map +1 -1
  295. package/dist/public/symbol-granularity.generated.d.ts.map +1 -1
  296. package/dist/public/symbol-granularity.generated.js +38 -5
  297. package/dist/public/telemetry-acceptance.d.ts.map +1 -1
  298. package/dist/public/telemetry-acceptance.js +21 -5
  299. package/dist/relationships/shards.d.ts +6 -0
  300. package/dist/relationships/shards.d.ts.map +1 -1
  301. package/dist/relationships/shards.js +26 -19
  302. package/dist/report/html-report.css +1239 -281
  303. package/dist/runtime/cli-runtime.d.ts.map +1 -1
  304. package/dist/runtime/cli-runtime.js +18 -0
  305. package/dist/schemas/entity.schema.json +32 -0
  306. package/dist/traceability/staged-diagnostics.d.ts +1 -1
  307. package/dist/traceability/staged-diagnostics.d.ts.map +1 -1
  308. package/dist/traceability/staged-entity-id-style.d.ts +12 -0
  309. package/dist/traceability/staged-entity-id-style.d.ts.map +1 -0
  310. package/dist/traceability/staged-entity-id-style.js +68 -0
  311. package/dist/traceability/symbol-extract.d.ts +24 -7
  312. package/dist/traceability/symbol-extract.d.ts.map +1 -1
  313. package/dist/traceability/symbol-extract.js +64 -208
  314. package/dist/traceability/temp-kb.d.ts.map +1 -1
  315. package/dist/traceability/temp-kb.js +8 -0
  316. package/dist/traceability/validate.js +1 -1
  317. package/dist/types/entities.d.ts +2 -0
  318. package/dist/types/entities.d.ts.map +1 -1
  319. package/dist/types/relationships.d.ts +1 -1
  320. package/dist/types/relationships.d.ts.map +1 -1
  321. package/dist/utils/entity-id-style.d.ts +27 -0
  322. package/dist/utils/entity-id-style.d.ts.map +1 -0
  323. package/dist/utils/entity-id-style.js +81 -0
  324. package/dist/utils/git-repository-context.d.ts +50 -0
  325. package/dist/utils/git-repository-context.d.ts.map +1 -0
  326. package/dist/utils/git-repository-context.js +259 -0
  327. package/dist/utils/rule-registry.d.ts +5 -0
  328. package/dist/utils/rule-registry.d.ts.map +1 -1
  329. package/dist/utils/rule-registry.generated.d.ts +42 -0
  330. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  331. package/dist/utils/rule-registry.generated.js +50 -0
  332. package/dist/utils/strict-modeling.d.ts +7 -0
  333. package/dist/utils/strict-modeling.d.ts.map +1 -1
  334. package/dist/utils/strict-modeling.js +11 -0
  335. package/package.json +14 -11
  336. package/schema/entities.pl +60 -1
  337. package/schema/relationships.pl +17 -4
  338. package/schema/validation.pl +118 -20
  339. package/src/public/diagnostic-usage.ts +16 -24
  340. package/src/public/extractors/symbols-coordinator.ts +1 -0
  341. package/src/public/impact/analyzer.ts +15 -12
  342. package/src/public/impact/full-kb-quality.ts +4 -16
  343. package/src/public/operations/check-executor.ts +13 -2
  344. package/src/public/operations/check-helpers.ts +29 -3
  345. package/src/public/operations/contracts.ts +59 -12
  346. package/src/public/operations/discovery-entities.ts +327 -12
  347. package/src/public/operations/discovery-executors.ts +110 -61
  348. package/src/public/operations/migration-plan.ts +57 -0
  349. package/src/public/operations/predicate-schema-conformance.ts +362 -0
  350. package/src/public/operations/prolog-json.ts +22 -8
  351. package/src/public/operations/result-envelope.ts +114 -2
  352. package/src/public/operations/runtime-types.ts +22 -3
  353. package/src/public/operations/specs/check-rules.generated.ts +9 -1
  354. package/src/public/operations/specs/discovery.ts +11 -1
  355. package/src/public/operations/specs/mutation-schemas.ts +23 -3
  356. package/src/public/operations/specs/proof.ts +1 -1
  357. package/src/public/operations/specs/reporting.ts +71 -24
  358. package/src/public/operations/specs/semantic.ts +79 -17
  359. package/src/public/operations/specs/upsert.ts +1 -1
  360. package/src/public/operations/symbol-repair-plan.ts +16 -7
  361. package/src/public/operations/types.ts +5 -0
  362. package/src/public/proof-fingerprint.ts +1 -1
  363. package/src/public/proof-protocol-types.d.ts +1 -1
  364. package/src/public/proof-protocol.ts +4 -4
  365. package/src/public/schemas/entity.ts +22 -0
  366. package/src/public/schemas/relationship.ts +1 -0
  367. package/src/public/skills/kibi-usage/SKILL.md +10 -3
  368. package/src/public/skills/kibi-usage/resources/fact-lanes.md +4 -0
  369. package/src/public/skills/kibi-usage/resources/proof.md +45 -0
  370. package/src/public/skills/kibi-usage/resources/relationship-directions.md +35 -17
  371. package/src/public/skills/kibi-usage/resources/source-authoring.md +36 -0
  372. package/src/public/skills/kibi-usage/resources/workflows.md +52 -1
  373. package/src/public/symbol-granularity.generated.ts +45 -12
  374. package/src/public/symbol-granularity.ts +3 -3
  375. package/src/public/telemetry-acceptance.ts +37 -6
  376. package/src/schemas/entity.schema.json +32 -0
  377. package/src/schemas/relationship.schema.json +1 -0
@@ -20,11 +20,30 @@ import { existsSync, readFileSync, statSync } from "node:fs";
20
20
  import { createRequire } from "node:module";
21
21
  import * as path from "node:path";
22
22
  import { fileURLToPath } from "node:url";
23
+ import { bootstrapKibiEnvironment, secretSourceFromBootstrap, } from "../env/bootstrap.js";
24
+ import { describeConfiguredCapabilityPlugins, readProjectKibiConfig, } from "../plugins/project-config.js";
23
25
  import { buildMigrationPlan, migrationAction, } from "../public/operations/migration-plan.js";
26
+ import { resolveGitRepository, } from "../utils/git-repository-context.js";
24
27
  import { readKbManifestStatus } from "../utils/kb-manifest.js";
28
+ import { hasManagedHooks, outdatedManagedHooks } from "./init-helpers.js";
25
29
  import { planLegacyStorageMigration } from "./legacy-storage-migration.js";
30
+ /**
31
+ * First-party plugin diagnostics known without importing the package.
32
+ * Generic third-party plugins report package/capability/mode/declared only.
33
+ */
34
+ // implements REQ-kibi-env-bootstrap, REQ-capability-plugin-configuration-v1
35
+ const FIRST_PARTY_PLUGIN_SECRETS = {
36
+ "kibi-plugin-jev": ["TYPESAFE_API_KEY"],
37
+ };
38
+ /** Static Jev defaults — must stay aligned with kibi-plugin-jev (no import). */
39
+ const JEV_DEFAULT_MODEL = "jev-latest";
40
+ const JEV_MAX_TIMEOUT_MS = 120_000;
26
41
  // implements REQ-003
27
42
  export async function doctorCommand(options = {}) {
43
+ // The repository context is per-diagnostic-run state: clearing here keeps
44
+ // repeated in-process invocations honest when core.hooksPath changes
45
+ // between runs, without introducing another ambient cache.
46
+ cachedRepositoryContext = undefined;
28
47
  const checks = [
29
48
  {
30
49
  name: "SWI-Prolog",
@@ -58,8 +77,19 @@ export async function doctorCommand(options = {}) {
58
77
  name: "post-rewrite hook",
59
78
  check: checkPostRewriteHook,
60
79
  },
80
+ {
81
+ name: "Kibi-managed hook sections",
82
+ check: checkManagedHookSections,
83
+ },
84
+ {
85
+ name: "Capability plugins",
86
+ check: checkCapabilityPlugins,
87
+ },
61
88
  ];
62
- const results = checks.map(({ name, check }) => ({ name, ...check() }));
89
+ const results = [];
90
+ for (const { name, check } of checks) {
91
+ results.push({ name, ...(await check()) });
92
+ }
63
93
  const allPassed = results.every((result) => result.passed);
64
94
  const runtime = await runtimeProvenance();
65
95
  const packageActions = await packageMigrationActions(runtime);
@@ -329,6 +359,107 @@ function checkSWIProlog() {
329
359
  };
330
360
  }
331
361
  }
362
+ /**
363
+ * Read-only view of package.json plugin activation.
364
+ * Does not import or execute plugin packages (no loadPluginPackage / dynamic import).
365
+ */
366
+ // implements REQ-capability-plugin-configuration-v1, REQ-kibi-env-bootstrap
367
+ function checkCapabilityPlugins() {
368
+ try {
369
+ const bootstrap = bootstrapKibiEnvironment();
370
+ const workspaceRoot = bootstrap.workspaceRoot;
371
+ const rows = describeConfiguredCapabilityPlugins(workspaceRoot);
372
+ if (rows.length === 0) {
373
+ return {
374
+ passed: true,
375
+ message: "None configured; builtin providers only",
376
+ };
377
+ }
378
+ const parts = rows.map((row) => `${row.package} ${row.capability} ${row.mode} declared=${row.declared ? "yes" : "no"}`);
379
+ if (rows.some((row) => !row.declared)) {
380
+ return {
381
+ passed: false,
382
+ message: parts.join("; "),
383
+ remediation: "Add the configured plugin package to dependencies, devDependencies, or optionalDependencies, or remove the kibi.plugins activation entry.",
384
+ };
385
+ }
386
+ const config = readProjectKibiConfig(workspaceRoot);
387
+ const packages = [
388
+ ...new Set((config.plugins ?? []).map((plugin) => plugin.package)),
389
+ ];
390
+ const missingSecrets = [];
391
+ const legacySecrets = [];
392
+ for (const packageName of packages) {
393
+ const secrets = FIRST_PARTY_PLUGIN_SECRETS[packageName] ?? [];
394
+ for (const secret of secrets) {
395
+ const source = formatSecretSourcePart(secret, bootstrap);
396
+ parts.push(`${secret}=${source}`);
397
+ if (source === "missing")
398
+ missingSecrets.push(secret);
399
+ if (source === "legacy_env")
400
+ legacySecrets.push(secret);
401
+ }
402
+ if (packageName === "kibi-plugin-jev") {
403
+ parts.push(...formatJevStaticConfigParts());
404
+ }
405
+ }
406
+ const message = parts.join("; ");
407
+ if (missingSecrets.length > 0) {
408
+ const jevMissing = missingSecrets.includes("TYPESAFE_API_KEY");
409
+ return {
410
+ passed: false,
411
+ message,
412
+ remediation: jevMissing
413
+ ? "Set `TYPESAFE_API_KEY` in `~/.config/kibi/env` (user-wide) or `<workspace>/.env.kibi` (project override), then restart long-running Kibi MCP/host processes."
414
+ : `Set missing plugin secret(s) (${missingSecrets.join(", ")}) in ~/.config/kibi/env or <workspace>/.env.kibi, then restart long-running Kibi MCP/host processes.`,
415
+ };
416
+ }
417
+ if (legacySecrets.length > 0) {
418
+ return {
419
+ passed: true,
420
+ message,
421
+ remediation: `Migrate ${legacySecrets.join(", ")} from legacy \`.env\` to \`~/.config/kibi/env\` or \`<workspace>/.env.kibi\`, then restart long-running Kibi MCP/host processes.`,
422
+ };
423
+ }
424
+ return {
425
+ passed: true,
426
+ message,
427
+ };
428
+ }
429
+ catch (error) {
430
+ const message = error instanceof Error ? error.message : String(error);
431
+ return {
432
+ passed: false,
433
+ message,
434
+ remediation: "Fix package.json kibi.plugins, then restart long-running Kibi MCP or client processes.",
435
+ };
436
+ }
437
+ }
438
+ function formatSecretSourcePart(secret, bootstrap) {
439
+ return secretSourceFromBootstrap(secret, bootstrap);
440
+ }
441
+ /**
442
+ * Static first-party Jev diagnostics — mirrors plugin resolve helpers without importing.
443
+ */
444
+ // implements REQ-kibi-env-bootstrap, REQ-capability-plugin-configuration-v1
445
+ function formatJevStaticConfigParts(env = process.env) {
446
+ const model = env.KIBI_JEV_MODEL?.trim() || JEV_DEFAULT_MODEL;
447
+ const raw = env.KIBI_JEV_TIMEOUT_MS;
448
+ if (raw === undefined || raw.trim() === "") {
449
+ return [`jev.model=${model}`, "jev.timeoutMs=default"];
450
+ }
451
+ const trimmed = raw.trim();
452
+ if (!/^[1-9]\d*$/.test(trimmed)) {
453
+ return [`jev.model=${model}`, "jev.timeoutMs=invalid"];
454
+ }
455
+ const timeoutMs = Number(trimmed);
456
+ if (!Number.isSafeInteger(timeoutMs) ||
457
+ timeoutMs < 1 ||
458
+ timeoutMs > JEV_MAX_TIMEOUT_MS) {
459
+ return [`jev.model=${model}`, "jev.timeoutMs=invalid"];
460
+ }
461
+ return [`jev.model=${model}`, `jev.timeoutMs=${String(timeoutMs)}`];
462
+ }
332
463
  function checkKbDirectory() {
333
464
  const kbDir = path.join(process.cwd(), ".kb");
334
465
  if (!existsSync(kbDir)) {
@@ -404,15 +535,86 @@ function checkGitRepository() {
404
535
  };
405
536
  }
406
537
  }
538
+ // Hook health must be diagnosed against the hooks directory Git actually
539
+ // executes (resolved via git rev-parse --git-path hooks, honoring
540
+ // core.hooksPath and linked worktrees), not against <cwd>/.git/hooks.
541
+ // implements REQ-git-hook-effective-install
542
+ let cachedRepositoryContext;
543
+ function doctorRepositoryContext() {
544
+ const cwd = process.cwd();
545
+ if (cachedRepositoryContext?.cwd !== cwd) {
546
+ const resolution = resolveGitRepository(cwd);
547
+ cachedRepositoryContext = {
548
+ cwd,
549
+ context: resolution.status === "ok" ? resolution.context : null,
550
+ };
551
+ }
552
+ return cachedRepositoryContext.context;
553
+ }
554
+ function effectiveHooksDir() {
555
+ const context = doctorRepositoryContext();
556
+ return (context?.effectiveHooksDir ?? path.join(process.cwd(), ".git", "hooks"));
557
+ }
558
+ function shellQuote(value) {
559
+ return `'${value.replace(/'/g, `'\\''`)}'`;
560
+ }
561
+ function remediationHookPaths(...hooks) {
562
+ const dir = effectiveHooksDir();
563
+ return `Run: chmod +x ${hooks.map((hook) => shellQuote(path.join(dir, hook))).join(" ")}`;
564
+ }
565
+ function hooksPathSuffix() {
566
+ const context = doctorRepositoryContext();
567
+ if (!context?.hooksPathConfig)
568
+ return "";
569
+ const origin = context.hooksPathOrigin
570
+ ? ` from ${context.hooksPathOrigin}`
571
+ : "";
572
+ return ` (core.hooksPath=${context.hooksPathConfig}${origin})`;
573
+ }
574
+ /**
575
+ * Kibi-managed hook sections must match what this CLI installs. A section
576
+ * written by an older CLI keeps running while silently lacking newer gates
577
+ * (the pre-commit `check-generated` step, for example), and the other hook
578
+ * checks only confirm that kibi is invoked at all.
579
+ */
580
+ // implements REQ-cli-doctor
581
+ function checkManagedHookSections() {
582
+ const hooksDir = effectiveHooksDir();
583
+ let outdated;
584
+ try {
585
+ if (!hasManagedHooks(hooksDir)) {
586
+ return { passed: true, message: "Not installed (optional)" };
587
+ }
588
+ outdated = outdatedManagedHooks(hooksDir);
589
+ }
590
+ catch {
591
+ return {
592
+ passed: false,
593
+ message: "Unable to read hook content",
594
+ remediation: "Run: kibi init",
595
+ };
596
+ }
597
+ if (outdated.length > 0) {
598
+ return {
599
+ passed: false,
600
+ message: `Outdated for this Kibi CLI: ${outdated.join(", ")} (installed by a different version; newer gates may be missing)${hooksPathSuffix()}`,
601
+ remediation: "Run: kibi init to refresh the kibi-managed hook sections",
602
+ };
603
+ }
604
+ return { passed: true, message: "Current for this Kibi CLI" };
605
+ }
407
606
  function checkGitHooks() {
408
- const postCheckoutPath = path.join(process.cwd(), ".git/hooks/post-checkout");
409
- const postMergePath = path.join(process.cwd(), ".git/hooks/post-merge");
607
+ const postCheckoutPath = path.join(effectiveHooksDir(), "post-checkout");
608
+ const postMergePath = path.join(effectiveHooksDir(), "post-merge");
609
+ const preCommitPath = path.join(effectiveHooksDir(), "pre-commit");
410
610
  const postCheckoutExists = existsSync(postCheckoutPath);
411
611
  const postMergeExists = existsSync(postMergePath);
412
- if (!postCheckoutExists && !postMergeExists) {
612
+ // An existing pre-commit is hard enforcement; the companions being absent
613
+ // must not downgrade the summary to "optional".
614
+ if (!postCheckoutExists && !postMergeExists && !existsSync(preCommitPath)) {
413
615
  return {
414
616
  passed: true,
415
- message: "Not installed (optional)",
617
+ message: `Not installed (optional)${hooksPathSuffix()}`,
416
618
  };
417
619
  }
418
620
  if (postCheckoutExists && postMergeExists) {
@@ -424,13 +626,13 @@ function checkGitHooks() {
424
626
  if (checkoutExecutable && mergeExecutable) {
425
627
  return {
426
628
  passed: true,
427
- message: "Installed and executable",
629
+ message: `Installed and executable${hooksPathSuffix()}`,
428
630
  };
429
631
  }
430
632
  return {
431
633
  passed: false,
432
- message: "Installed but not executable",
433
- remediation: "Run: chmod +x .git/hooks/post-checkout .git/hooks/post-merge",
634
+ message: `Installed but not executable${hooksPathSuffix()}`,
635
+ remediation: remediationHookPaths("post-checkout", "post-merge"),
434
636
  };
435
637
  }
436
638
  catch (error) {
@@ -442,20 +644,20 @@ function checkGitHooks() {
442
644
  }
443
645
  return {
444
646
  passed: false,
445
- message: "Partially installed",
647
+ message: `Partially installed${hooksPathSuffix()}`,
446
648
  remediation: "Run: kibi init",
447
649
  };
448
650
  }
449
651
  function checkPreCommitHook() {
450
- const postCheckoutPath = path.join(process.cwd(), ".git/hooks/post-checkout");
451
- const postMergePath = path.join(process.cwd(), ".git/hooks/post-merge");
452
- const preCommitPath = path.join(process.cwd(), ".git/hooks/pre-commit");
652
+ const postCheckoutPath = path.join(effectiveHooksDir(), "post-checkout");
653
+ const postMergePath = path.join(effectiveHooksDir(), "post-merge");
654
+ const preCommitPath = path.join(effectiveHooksDir(), "pre-commit");
453
655
  const postCheckoutExists = existsSync(postCheckoutPath);
454
656
  const postMergeExists = existsSync(postMergePath);
455
- if (!postCheckoutExists && !postMergeExists) {
657
+ if (!postCheckoutExists && !postMergeExists && !existsSync(preCommitPath)) {
456
658
  return {
457
659
  passed: true,
458
- message: "Not installed (optional)",
660
+ message: `Not installed (optional)${hooksPathSuffix()}`,
459
661
  };
460
662
  }
461
663
  const preCommitExists = existsSync(preCommitPath);
@@ -499,7 +701,7 @@ function checkPreCommitHook() {
499
701
  }
500
702
  return {
501
703
  passed: true,
502
- message: "Installed and executable (resolves kibi CLI; uses 'kibi check --staged')",
704
+ message: `Installed and executable (resolves kibi CLI; uses 'kibi check --staged')${hooksPathSuffix()}`,
503
705
  };
504
706
  }
505
707
  // Warn but pass if using legacy kibi check without --staged
@@ -511,8 +713,8 @@ function checkPreCommitHook() {
511
713
  }
512
714
  return {
513
715
  passed: false,
514
- message: "Installed but not executable",
515
- remediation: "Run: chmod +x .git/hooks/pre-commit",
716
+ message: `Installed but not executable${hooksPathSuffix()}`,
717
+ remediation: remediationHookPaths("pre-commit"),
516
718
  };
517
719
  }
518
720
  catch (error) {
@@ -524,15 +726,15 @@ function checkPreCommitHook() {
524
726
  }
525
727
  }
526
728
  function checkPostRewriteHook() {
527
- const postCheckoutPath = path.join(process.cwd(), ".git/hooks/post-checkout");
528
- const postMergePath = path.join(process.cwd(), ".git/hooks/post-merge");
529
- const postRewritePath = path.join(process.cwd(), ".git/hooks/post-rewrite");
729
+ const postCheckoutPath = path.join(effectiveHooksDir(), "post-checkout");
730
+ const postMergePath = path.join(effectiveHooksDir(), "post-merge");
731
+ const postRewritePath = path.join(effectiveHooksDir(), "post-rewrite");
530
732
  const postCheckoutExists = existsSync(postCheckoutPath);
531
733
  const postMergeExists = existsSync(postMergePath);
532
- if (!postCheckoutExists && !postMergeExists) {
734
+ if (!postCheckoutExists && !postMergeExists && !existsSync(postRewritePath)) {
533
735
  return {
534
736
  passed: true,
535
- message: "Not installed (optional)",
737
+ message: `Not installed (optional)${hooksPathSuffix()}`,
536
738
  };
537
739
  }
538
740
  const postRewriteExists = existsSync(postRewritePath);
@@ -568,13 +770,13 @@ function checkPostRewriteHook() {
568
770
  }
569
771
  return {
570
772
  passed: true,
571
- message: "Installed and executable",
773
+ message: `Installed and executable${hooksPathSuffix()}`,
572
774
  };
573
775
  }
574
776
  return {
575
777
  passed: false,
576
- message: "Installed but not executable",
577
- remediation: "Run: chmod +x .git/hooks/post-rewrite",
778
+ message: `Installed but not executable${hooksPathSuffix()}`,
779
+ remediation: remediationHookPaths("post-rewrite"),
578
780
  };
579
781
  }
580
782
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/commands/engine.ts"],"names":[],"mappings":"AAkCA,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CA4BzD;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAWvD;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAE1D;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AAEH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAyCf;AAED,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkB3D;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAClD,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAWhB"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/commands/engine.ts"],"names":[],"mappings":"AAkCA,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CA4BzD;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAWvD;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAE1D;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AAEH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA2Cf;AAED,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkB3D;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAClD,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAWhB"}
@@ -96,7 +96,9 @@ export async function engineJanitorCommand(options) {
96
96
  return;
97
97
  }
98
98
  for (const finding of findings) {
99
- const holder = "pid" in finding && finding.pid !== undefined ? ` pid=${finding.pid}` : "";
99
+ const holder = "pid" in finding && finding.pid !== undefined
100
+ ? ` pid=${finding.pid}`
101
+ : "";
100
102
  const workspace = finding.kind === "store-lock" && finding.workspaceRoot !== undefined
101
103
  ? ` workspace=${finding.workspaceRoot}`
102
104
  : "";
@@ -2,7 +2,7 @@ export declare const GITHUB_REPORT_WORKFLOW_RELPATH = ".github/workflows/kibi-re
2
2
  export declare const GITHUB_BADGE_WORKFLOW_RELPATH = ".github/workflows/kibi-badge.yml";
3
3
  export declare const GITHUB_PAGES_NAMESPACE = "kibi-report";
4
4
  export declare const KIBI_BADGE_ALT = "Kibi requirement health";
5
- export declare const KIBI_METRIC_DOCS_URL = "https://github.com/Looted/kibi/blob/develop/docs/github-integration.md#what-the-badge-means";
5
+ export declare const KIBI_METRIC_DOCS_URL = "https://looted.github.io/kibi/guide/github-integration.html#what-the-badge-means";
6
6
  export declare const PLACEHOLDER_OWNER = "OWNER";
7
7
  export declare const PLACEHOLDER_REPO = "REPOSITORY";
8
8
  export type GitHubRepo = Readonly<{
@@ -1 +1 @@
1
- {"version":3,"file":"github-init.d.ts","sourceRoot":"","sources":["../../src/commands/github-init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"github-init.d.ts","sourceRoot":"","sources":["../../src/commands/github-init.ts"],"names":[],"mappings":"AA0BA,eAAO,MAAM,8BAA8B,sCACN,CAAC;AACtC,eAAO,MAAM,6BAA6B,qCAAqC,CAAC;AAChF,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AACpD,eAAO,MAAM,cAAc,4BAA4B,CAAC;AACxD,eAAO,MAAM,oBAAoB,qFACmD,CAAC;AACrF,eAAO,MAAM,iBAAiB,UAAU,CAAC;AACzC,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAM7C,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb,CAAC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEpD,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;AACvE,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,WAAW,GACX,SAAS,GACT,sBAAsB,CAAC;AAC3B,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,WAAW,CAAC;AAE3D,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;IAC3C,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,SAAS,EAAE,oBAAoB,CAAC;IAChC,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC;CAC9B,CAAC,CAAC;AAGH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,kBAAkB,GACvB,MAAM,CAER;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAS3E;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CA+BrE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,eAAe,CAUjE;AAED,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,MAAM,CAER;AAED,wBAAgB,oBAAoB,IAAI,eAAe,CAKtD;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAMnE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQhE;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,GACpB,MAAM,CAuBR;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,CAiBvD;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,SAAS,SAAS,EAAE,GAC5B,UAAU,GAAG,SAAS,CASxB;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,kBAAkB,EACxB,QAAQ,EAAE,MAAM,GACf,mBAAmB,CAcrB;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CAa3E;AAGD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,qBAAqB,EAC9B,IAAI,GAAE,cAAmB,GACxB,oBAAoB,CAsDtB;AAsDD,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,KAAK,EAAE,MAAM,GACZ,MAAM,CAMR"}
@@ -25,7 +25,7 @@ export const GITHUB_REPORT_WORKFLOW_RELPATH = ".github/workflows/kibi-report.yml
25
25
  export const GITHUB_BADGE_WORKFLOW_RELPATH = ".github/workflows/kibi-badge.yml";
26
26
  export const GITHUB_PAGES_NAMESPACE = "kibi-report";
27
27
  export const KIBI_BADGE_ALT = "Kibi requirement health";
28
- export const KIBI_METRIC_DOCS_URL = "https://github.com/Looted/kibi/blob/develop/docs/github-integration.md#what-the-badge-means";
28
+ export const KIBI_METRIC_DOCS_URL = "https://looted.github.io/kibi/guide/github-integration.html#what-the-badge-means";
29
29
  export const PLACEHOLDER_OWNER = "OWNER";
30
30
  export const PLACEHOLDER_REPO = "REPOSITORY";
31
31
  const README_CANDIDATES = ["README.md", "readme.md", "Readme.md"];
@@ -4,6 +4,21 @@ export declare function createManifestFile(kbDir: string): void;
4
4
  export declare function updateGitIgnore(cwd: string): void;
5
5
  export declare function ensureSymbolsManifestFile(cwd: string): void;
6
6
  export declare function copySchemaFiles(kbDir: string, schemaSourceDir: string): Promise<void>;
7
- export declare function installHook(hookPath: string, content: string): void;
8
- export declare function installGitHooks(gitDir: string): void;
7
+ export type InstallHookResult = "installed" | "updated" | "skipped-foreign" | "skipped-symlink" | "skipped-unsupported";
8
+ export declare function installHook(hookPath: string, content: string): InstallHookResult;
9
+ export interface GitHookInstallResult {
10
+ hook: "pre-commit" | "post-checkout" | "post-merge" | "post-rewrite";
11
+ result: InstallHookResult;
12
+ }
13
+ /**
14
+ * Installed kibi-managed hooks whose managed section differs from what this
15
+ * CLI installs, such as a pre-commit gate written before `check-generated`
16
+ * joined it. User-authored hooks without kibi markers are not reported.
17
+ */
18
+ export declare function outdatedManagedHooks(hooksDir: string): string[];
19
+ /** Whether any hook in the directory carries a kibi-managed section. */
20
+ export declare function hasManagedHooks(hooksDir: string): boolean;
21
+ export declare function installGitHooks(hooksDir: string, options?: {
22
+ hooksPathOrigin?: string | null;
23
+ }): GitHookInstallResult[];
9
24
  //# sourceMappingURL=init-helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"init-helpers.d.ts","sourceRoot":"","sources":["../../src/commands/init-helpers.ts"],"names":[],"mappings":"AAkIA,wBAAsB,gBAAgB,CACpC,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,MAAM,CAAC,CASjB;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,GACpB,IAAI,CAUN;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAGtD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CA6BjD;AAiDD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAU3D;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAYf;AASD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAkCnE;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAiBpD"}
1
+ {"version":3,"file":"init-helpers.d.ts","sourceRoot":"","sources":["../../src/commands/init-helpers.ts"],"names":[],"mappings":"AAyIA,wBAAsB,gBAAgB,CACpC,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,MAAM,CAAC,CASjB;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,GACpB,IAAI,CAUN;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAGtD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CA6BjD;AAkDD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAU3D;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAYf;AASD,MAAM,MAAM,iBAAiB,GACzB,WAAW,GACX,SAAS,GACT,iBAAiB,GACjB,iBAAiB,GACjB,qBAAqB,CAAC;AAoB1B,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,iBAAiB,CAyEnB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,YAAY,GAAG,eAAe,GAAG,YAAY,GAAG,cAAc,CAAC;IACrE,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAiBD;;;;GAIG;AAEH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAU/D;AAED,wEAAwE;AAExE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQzD;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GAChD,oBAAoB,EAAE,CA8CxB"}
@@ -15,7 +15,7 @@
15
15
  You should have received a copy of the GNU Affero General Public License
16
16
  along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
  */
18
- import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync, } from "node:fs";
18
+ import { chmodSync, copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, writeFileSync, } from "node:fs";
19
19
  import * as path from "node:path";
20
20
  import fg from "fast-glob";
21
21
  import { getBranchDiagnostic, resolveActiveBranch, } from "../utils/branch-resolver.js";
@@ -61,13 +61,17 @@ old_ref=$1
61
61
  new_ref=$2
62
62
  branch_flag=$3
63
63
 
64
+ # File checkouts never refresh the KB; skip binary resolution so sandboxed
65
+ # test workspaces without an installed kibi CLI can restore tracked files.
66
+ if [ "$branch_flag" != "1" ]; then
67
+ exit 0
68
+ fi
69
+
64
70
  ${KIBI_BIN_RESOLVER}
65
71
 
66
- if [ "$branch_flag" = "1" ]; then
67
- # Branch stores are derived from the checked-out tracked sources. Never copy
68
- # the old branch's compiled store during checkout.
69
- "$KIBI_BIN" sync
70
- fi
72
+ # Branch stores are derived from the checked-out tracked sources. Never copy
73
+ # the old branch's compiled store during checkout.
74
+ "$KIBI_BIN" sync
71
75
  `;
72
76
  const POST_MERGE_HOOK = `#!/bin/sh
73
77
  # post-merge hook for kibi
@@ -102,13 +106,14 @@ const PRE_COMMIT_HOOK = `#!/bin/sh
102
106
  # Behavior-changing source edits require staged Kibi impact evidence
103
107
  # (KB entity docs under .kb/, authored symbols metadata, or refreshed
104
108
  # symbol coordinates). Test-only and docs-only edits are exempt.
105
- # Refresh with:
106
- # kibi sync --refresh-symbol-coordinates && git add .kb/symbol-coordinates.yaml .kb/symbols.yaml
109
+ # Generated manifests are checked against the exact staged snapshot before
110
+ # traceability validation. The check never stages files on the user's behalf.
107
111
 
108
112
  set -e
109
113
 
110
114
  ${KIBI_BIN_RESOLVER}
111
115
 
116
+ "$KIBI_BIN" check-generated --staged --changed-only
112
117
  "$KIBI_BIN" check --staged
113
118
  `;
114
119
  export async function getCurrentBranch(cwd = process.cwd()) {
@@ -168,6 +173,7 @@ const CANONICAL_DERIVED_GITIGNORE_ENTRIES = [
168
173
  ".kb/briefs/",
169
174
  ".kb/migrations/",
170
175
  ".kb/usage.log",
176
+ ".env.kibi",
171
177
  ];
172
178
  /**
173
179
  * Pre-canonical Kibi init wrote a blanket `.kb/` fence and then
@@ -230,41 +236,141 @@ const KIBI_HOOK_END = "# END kibi-managed";
230
236
  function escapeRegex(s) {
231
237
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
232
238
  }
239
+ function hookIntegrationRecipe(hook) {
240
+ // Recipes must reproduce the exact checks the Kibi template runs for that
241
+ // hook, with failure propagation, or the delegation is weaker than the
242
+ // template it replaces.
243
+ switch (hook) {
244
+ case "pre-commit":
245
+ return "delegate from that hook with 'kibi check-generated --staged --changed-only && kibi check --staged' (both commands must succeed; '&&' propagates the first failure)";
246
+ case "post-checkout":
247
+ return "delegate from that hook to 'kibi sync' on branch checkouts (the template skips file checkouts)";
248
+ case "post-merge":
249
+ return "delegate from that hook to 'kibi sync'";
250
+ case "post-rewrite":
251
+ return "delegate from that hook to 'kibi sync' after rebase/amend rewrites";
252
+ default:
253
+ return "delegate to the matching Kibi template command";
254
+ }
255
+ }
233
256
  export function installHook(hookPath, content) {
234
257
  // implements REQ-008
258
+ // implements REQ-git-hook-effective-install
235
259
  const kibiSection = `${KIBI_HOOK_BEGIN}\n${content}\n${KIBI_HOOK_END}`;
236
- if (existsSync(hookPath)) {
260
+ let hookStats;
261
+ try {
262
+ hookStats = lstatSync(hookPath);
263
+ }
264
+ catch (error) {
265
+ if (error.code === "ENOENT" ||
266
+ error.code === "ENOTDIR") {
267
+ // Missing hook: create it through the parent directory. Refuse when an
268
+ // ancestor is itself a symlink whose target leaves the resolved path
269
+ // (realpath is checked by the caller's hooks-dir guard).
270
+ writeFileSync(hookPath, `#!/bin/sh\n${kibiSection}\n`, { mode: 0o755 });
271
+ chmodSync(hookPath, 0o755);
272
+ return "installed";
273
+ }
274
+ console.error(`! Unable to inspect ${hookPath}: ${error.message}; leaving it untouched.`);
275
+ return "skipped-unsupported";
276
+ }
277
+ if (hookStats.isSymbolicLink()) {
278
+ // Never follow a symlinked hook: read/write/chmod would modify an
279
+ // arbitrary target outside our guard. Dangling symlinks are treated the
280
+ // same (the intended target must not be auto-created either).
281
+ return "skipped-symlink";
282
+ }
283
+ if (!hookStats.isFile()) {
284
+ return "skipped-unsupported";
285
+ }
286
+ try {
237
287
  const existing = readFileSync(hookPath, "utf8");
238
288
  if (existing.includes(KIBI_HOOK_BEGIN) &&
239
289
  existing.includes(KIBI_HOOK_END)) {
240
290
  // Replace only the kibi-managed section, preserving any user-authored content
241
291
  const updated = existing.replace(new RegExp(`${escapeRegex(KIBI_HOOK_BEGIN)}[\\s\\S]*?${escapeRegex(KIBI_HOOK_END)}`), kibiSection);
242
292
  writeFileSync(hookPath, updated, { mode: 0o755 });
293
+ chmodSync(hookPath, 0o755);
294
+ return "updated";
243
295
  }
244
- else if (existing.trim().length > 0) {
245
- return;
246
- }
247
- else {
248
- const shebang = existing.startsWith("#!/") ? "" : "#!/bin/sh\n";
249
- writeFileSync(hookPath, `${shebang}${existing.trimEnd()}\n${kibiSection}\n`, { mode: 0o755 });
296
+ if (existing.trim().length > 0) {
297
+ // A hook we did not write: never overwrite foreign enforcement.
298
+ return "skipped-foreign";
250
299
  }
300
+ const shebang = existing.startsWith("#!/") ? "" : "#!/bin/sh\n";
301
+ writeFileSync(hookPath, `${shebang}${existing.trimEnd()}\n${kibiSection}\n`, { mode: 0o755 });
302
+ chmodSync(hookPath, 0o755);
303
+ return "installed";
251
304
  }
252
- else {
253
- writeFileSync(hookPath, `#!/bin/sh\n${kibiSection}\n`, { mode: 0o755 });
305
+ catch (error) {
306
+ console.error(`! Unable to read ${hookPath}: ${error.message}; leaving it untouched.`);
307
+ return "skipped-unsupported";
254
308
  }
255
- // Explicitly ensure hook is executable
256
- chmodSync(hookPath, 0o755);
257
309
  }
258
- export function installGitHooks(gitDir) {
259
- const hooksDir = path.join(gitDir, "hooks");
310
+ /** Kibi-managed hooks in install order, with the template each one installs. */
311
+ const MANAGED_HOOK_TEMPLATES = [
312
+ ["post-checkout", POST_CHECKOUT_HOOK],
313
+ ["post-merge", POST_MERGE_HOOK],
314
+ ["post-rewrite", POST_REWRITE_HOOK],
315
+ ["pre-commit", PRE_COMMIT_HOOK],
316
+ ];
317
+ function managedHookBody(template) {
318
+ return template.replace("#!/bin/sh\n", "");
319
+ }
320
+ /**
321
+ * Installed kibi-managed hooks whose managed section differs from what this
322
+ * CLI installs, such as a pre-commit gate written before `check-generated`
323
+ * joined it. User-authored hooks without kibi markers are not reported.
324
+ */
325
+ // implements REQ-cli-doctor
326
+ export function outdatedManagedHooks(hooksDir) {
327
+ const managed = new RegExp(`${escapeRegex(KIBI_HOOK_BEGIN)}\\n([\\s\\S]*?)\\n${escapeRegex(KIBI_HOOK_END)}`);
328
+ return MANAGED_HOOK_TEMPLATES.filter(([hook, template]) => {
329
+ const hookPath = path.join(hooksDir, hook);
330
+ if (!existsSync(hookPath))
331
+ return false;
332
+ const section = managed.exec(readFileSync(hookPath, "utf8"));
333
+ return section !== null && section[1] !== managedHookBody(template);
334
+ }).map(([hook]) => hook);
335
+ }
336
+ /** Whether any hook in the directory carries a kibi-managed section. */
337
+ // implements REQ-cli-doctor
338
+ export function hasManagedHooks(hooksDir) {
339
+ return MANAGED_HOOK_TEMPLATES.some(([hook]) => {
340
+ const hookPath = path.join(hooksDir, hook);
341
+ return (existsSync(hookPath) &&
342
+ readFileSync(hookPath, "utf8").includes(KIBI_HOOK_BEGIN));
343
+ });
344
+ }
345
+ export function installGitHooks(hooksDir, options = {}) {
346
+ // implements REQ-git-hook-effective-install
260
347
  mkdirSync(hooksDir, { recursive: true });
261
- const postCheckoutPath = path.join(hooksDir, "post-checkout");
262
- const postMergePath = path.join(hooksDir, "post-merge");
263
- const postRewritePath = path.join(hooksDir, "post-rewrite");
264
- const preCommitPath = path.join(hooksDir, "pre-commit");
265
- installHook(postCheckoutPath, POST_CHECKOUT_HOOK.replace("#!/bin/sh\n", ""));
266
- installHook(postMergePath, POST_MERGE_HOOK.replace("#!/bin/sh\n", ""));
267
- installHook(postRewritePath, POST_REWRITE_HOOK.replace("#!/bin/sh\n", ""));
268
- installHook(preCommitPath, PRE_COMMIT_HOOK.replace("#!/bin/sh\n", ""));
269
- console.log("✓ Installed git hooks (pre-commit, post-checkout, post-merge, post-rewrite)");
348
+ const results = MANAGED_HOOK_TEMPLATES.map(([hook, template]) => ({
349
+ hook,
350
+ result: installHook(path.join(hooksDir, hook), managedHookBody(template)),
351
+ }));
352
+ for (const { hook, result } of results) {
353
+ if (result === "skipped-foreign") {
354
+ console.log(`! ${hook}: existing non-Kibi hook left untouched; Kibi enforcement is NOT installed for this hook. To integrate: ${hookIntegrationRecipe(hook)}.`);
355
+ }
356
+ else if (result === "skipped-symlink") {
357
+ console.log(`! ${hook}: hook is a symlink; Kibi never edits symlink targets. Manage the target manually (${hookIntegrationRecipe(hook)}).`);
358
+ }
359
+ else if (result === "skipped-unsupported") {
360
+ console.log(`! ${hook}: hook path is not a regular file; left untouched.`);
361
+ }
362
+ }
363
+ const installedOrUpdated = results.filter((entry) => entry.result === "installed" || entry.result === "updated");
364
+ if (installedOrUpdated.length > 0) {
365
+ console.log(`✓ Installed/updated Kibi git hooks at ${hooksDir} (${installedOrUpdated.map((entry) => entry.hook).join(", ")})`);
366
+ }
367
+ else {
368
+ console.log(`! No Kibi git hooks installed at ${hooksDir} (all hooks were skipped).`);
369
+ }
370
+ if (options.hooksPathOrigin) {
371
+ // Configuration/location reporting stays neutral about what happened:
372
+ // the per-hook lines and the aggregate above carry the install verdict.
373
+ console.log(`! core.hooksPath is configured (${options.hooksPathOrigin}); the effective hooks directory for THIS checkout is ${hooksDir}. Git resolves a relative hooks path separately under every worktree, so coverage of other worktrees is INCOMPLETE/UNVERIFIED: commit a versioned launcher that delegates to kibi, or run 'kibi init' in each checkout. Kibi will not change core.hooksPath.`);
374
+ }
375
+ return results;
270
376
  }