kibi-cli 2.4.0 → 2.5.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 (352) 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 +0 -1
  24. package/dist/commands/migrate.d.ts.map +1 -1
  25. package/dist/commands/migrate.js +281 -14
  26. package/dist/commands/proof-compact.d.ts +9 -0
  27. package/dist/commands/proof-compact.d.ts.map +1 -0
  28. package/dist/commands/proof-compact.js +58 -0
  29. package/dist/commands/prove.d.ts +38 -0
  30. package/dist/commands/prove.d.ts.map +1 -1
  31. package/dist/commands/prove.js +222 -47
  32. package/dist/commands/sync/persistence.d.ts.map +1 -1
  33. package/dist/commands/sync/persistence.js +61 -16
  34. package/dist/commands/sync.d.ts +8 -0
  35. package/dist/commands/sync.d.ts.map +1 -1
  36. package/dist/commands/sync.js +42 -16
  37. package/dist/diagnostics.js +1 -1
  38. package/dist/engine-limits.d.ts +74 -0
  39. package/dist/engine-limits.d.ts.map +1 -0
  40. package/dist/engine-limits.js +201 -0
  41. package/dist/engine.d.ts +10 -0
  42. package/dist/engine.d.ts.map +1 -1
  43. package/dist/engine.js +57 -9
  44. package/dist/extractors/manifest.d.ts +8 -0
  45. package/dist/extractors/manifest.d.ts.map +1 -1
  46. package/dist/extractors/manifest.js +34 -5
  47. package/dist/extractors/markdown.d.ts +8 -0
  48. package/dist/extractors/markdown.d.ts.map +1 -1
  49. package/dist/extractors/markdown.js +57 -0
  50. package/dist/extractors/relationships.d.ts.map +1 -1
  51. package/dist/extractors/relationships.js +2 -0
  52. package/dist/intent-search.d.ts +4 -1
  53. package/dist/intent-search.d.ts.map +1 -1
  54. package/dist/intent-search.js +186 -33
  55. package/dist/operations/bootstrap/candidate-helpers.d.ts.map +1 -1
  56. package/dist/operations/bootstrap/candidate-helpers.js +8 -1
  57. package/dist/operations/bootstrap/candidates.d.ts.map +1 -1
  58. package/dist/operations/bootstrap/candidates.js +54 -38
  59. package/dist/operations/bootstrap/generate.d.ts +2 -0
  60. package/dist/operations/bootstrap/generate.d.ts.map +1 -1
  61. package/dist/operations/bootstrap/generate.js +87 -33
  62. package/dist/operations/bootstrap/intent-claims.d.ts.map +1 -1
  63. package/dist/operations/bootstrap/intent-claims.js +12 -4
  64. package/dist/operations/bootstrap/markdown-candidates.d.ts +2 -0
  65. package/dist/operations/bootstrap/markdown-candidates.d.ts.map +1 -1
  66. package/dist/operations/bootstrap/markdown-candidates.js +32 -10
  67. package/dist/operations/bootstrap/presentation.d.ts.map +1 -1
  68. package/dist/operations/bootstrap/presentation.js +6 -2
  69. package/dist/operations/bootstrap/requirement-claims.d.ts +1 -0
  70. package/dist/operations/bootstrap/requirement-claims.d.ts.map +1 -1
  71. package/dist/operations/bootstrap/requirement-claims.js +13 -1
  72. package/dist/operations/bootstrap/validation.d.ts +4 -0
  73. package/dist/operations/bootstrap/validation.d.ts.map +1 -0
  74. package/dist/operations/bootstrap/validation.js +20 -0
  75. package/dist/operations/migration/inventory-rederive.d.ts +81 -0
  76. package/dist/operations/migration/inventory-rederive.d.ts.map +1 -0
  77. package/dist/operations/migration/inventory-rederive.js +484 -0
  78. package/dist/operations/migration/kb-sources.d.ts +53 -0
  79. package/dist/operations/migration/kb-sources.d.ts.map +1 -0
  80. package/dist/operations/migration/kb-sources.js +233 -0
  81. package/dist/operations/migration/origin-backfill.d.ts +39 -0
  82. package/dist/operations/migration/origin-backfill.d.ts.map +1 -0
  83. package/dist/operations/migration/origin-backfill.js +164 -0
  84. package/dist/operations/migration/polarity-values.d.ts +10 -0
  85. package/dist/operations/migration/polarity-values.d.ts.map +1 -0
  86. package/dist/operations/migration/polarity-values.js +60 -0
  87. package/dist/operations/migration/schema6.d.ts +59 -0
  88. package/dist/operations/migration/schema6.d.ts.map +1 -0
  89. package/dist/operations/migration/schema6.js +379 -0
  90. package/dist/operations/migration/source-paths.d.ts +131 -0
  91. package/dist/operations/migration/source-paths.d.ts.map +1 -0
  92. package/dist/operations/migration/source-paths.js +308 -0
  93. package/dist/operations/migration/superseded-closure.d.ts +54 -0
  94. package/dist/operations/migration/superseded-closure.d.ts.map +1 -0
  95. package/dist/operations/migration/superseded-closure.js +187 -0
  96. package/dist/operations/modeling/logic-modeling.d.ts.map +1 -1
  97. package/dist/operations/modeling/logic-modeling.js +3 -5
  98. package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
  99. package/dist/operations/modeling/model-requirement.js +225 -67
  100. package/dist/operations/mutation/contradictions.d.ts +16 -0
  101. package/dist/operations/mutation/contradictions.d.ts.map +1 -1
  102. package/dist/operations/mutation/contradictions.js +32 -0
  103. package/dist/operations/mutation/delete.d.ts.map +1 -1
  104. package/dist/operations/mutation/delete.js +15 -7
  105. package/dist/operations/mutation/origin.d.ts +21 -0
  106. package/dist/operations/mutation/origin.d.ts.map +1 -0
  107. package/dist/operations/mutation/origin.js +78 -0
  108. package/dist/operations/mutation/plan-apply-journal.d.ts +182 -0
  109. package/dist/operations/mutation/plan-apply-journal.d.ts.map +1 -0
  110. package/dist/operations/mutation/plan-apply-journal.js +613 -0
  111. package/dist/operations/mutation/predicate-vocabulary-guard.d.ts +3 -1
  112. package/dist/operations/mutation/predicate-vocabulary-guard.d.ts.map +1 -1
  113. package/dist/operations/mutation/predicate-vocabulary-guard.js +13 -2
  114. package/dist/operations/mutation/relationships.d.ts +5 -5
  115. package/dist/operations/mutation/relationships.d.ts.map +1 -1
  116. package/dist/operations/mutation/relationships.js +31 -11
  117. package/dist/operations/mutation/serialization.d.ts.map +1 -1
  118. package/dist/operations/mutation/serialization.js +3 -1
  119. package/dist/operations/mutation/source-authoring.d.ts +6 -0
  120. package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
  121. package/dist/operations/mutation/source-authoring.js +7 -1
  122. package/dist/operations/mutation/types.d.ts +14 -0
  123. package/dist/operations/mutation/types.d.ts.map +1 -1
  124. package/dist/operations/mutation/upsert.d.ts +30 -3
  125. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  126. package/dist/operations/mutation/upsert.js +105 -35
  127. package/dist/operations/mutation/validate-upsert.d.ts +6 -0
  128. package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
  129. package/dist/operations/mutation/validate-upsert.js +34 -30
  130. package/dist/operations/planning/apply-plan.d.ts.map +1 -1
  131. package/dist/operations/planning/apply-plan.js +751 -144
  132. package/dist/operations/planning/compile-intent.d.ts +34 -1
  133. package/dist/operations/planning/compile-intent.d.ts.map +1 -1
  134. package/dist/operations/planning/compile-intent.js +314 -98
  135. package/dist/operations/proof/code-scope.d.ts +28 -0
  136. package/dist/operations/proof/code-scope.d.ts.map +1 -1
  137. package/dist/operations/proof/code-scope.js +72 -0
  138. package/dist/operations/proof/compact-receipts.d.ts +49 -0
  139. package/dist/operations/proof/compact-receipts.d.ts.map +1 -0
  140. package/dist/operations/proof/compact-receipts.js +160 -0
  141. package/dist/operations/proof/ingest-proof.d.ts +2 -0
  142. package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
  143. package/dist/operations/proof/ingest-proof.js +44 -23
  144. package/dist/operations/proof/prune-receipts.d.ts.map +1 -1
  145. package/dist/operations/proof/prune-receipts.js +5 -9
  146. package/dist/operations/proof/receipt-compaction.d.ts +48 -0
  147. package/dist/operations/proof/receipt-compaction.d.ts.map +1 -0
  148. package/dist/operations/proof/receipt-compaction.js +121 -0
  149. package/dist/operations/semantic-advisor/analysis-receipt.d.ts.map +1 -1
  150. package/dist/operations/semantic-advisor/analysis-receipt.js +12 -1
  151. package/dist/operations/semantic-advisor/analyze-prose.d.ts +2 -1
  152. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  153. package/dist/operations/semantic-advisor/analyze-prose.js +51 -5
  154. package/dist/operations/semantic-advisor/clauses.d.ts +1 -0
  155. package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
  156. package/dist/operations/semantic-advisor/clauses.js +11 -1
  157. package/dist/operations/semantic-advisor/conditional-rules.d.ts +33 -0
  158. package/dist/operations/semantic-advisor/conditional-rules.d.ts.map +1 -0
  159. package/dist/operations/semantic-advisor/conditional-rules.js +262 -0
  160. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts +3 -1
  161. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -1
  162. package/dist/operations/semantic-advisor/ingestion-boundary.js +14 -6
  163. package/dist/operations/semantic-advisor/plugin-orchestration.js +1 -1
  164. package/dist/prolog/codec.d.ts.map +1 -1
  165. package/dist/prolog/codec.js +2 -1
  166. package/dist/prolog.d.ts +9 -0
  167. package/dist/prolog.d.ts.map +1 -1
  168. package/dist/prolog.js +56 -10
  169. package/dist/proof/command-test-report.d.ts +74 -0
  170. package/dist/proof/command-test-report.d.ts.map +1 -0
  171. package/dist/proof/command-test-report.js +206 -0
  172. package/dist/public/branch-resolver.d.ts +1 -0
  173. package/dist/public/branch-resolver.d.ts.map +1 -1
  174. package/dist/public/branch-resolver.js +1 -0
  175. package/dist/public/entity-origin.d.ts +69 -0
  176. package/dist/public/entity-origin.d.ts.map +1 -0
  177. package/dist/public/entity-origin.js +142 -0
  178. package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
  179. package/dist/public/impact/full-kb-quality.js +1 -0
  180. package/dist/public/impact/requirement-quality.js +1 -1
  181. package/dist/public/operations/catalog.d.ts +130 -19
  182. package/dist/public/operations/catalog.d.ts.map +1 -1
  183. package/dist/public/operations/catalog.js +3 -0
  184. package/dist/public/operations/check-executor.d.ts.map +1 -1
  185. package/dist/public/operations/check-executor.js +8 -0
  186. package/dist/public/operations/contracts.d.ts +0 -5
  187. package/dist/public/operations/contracts.d.ts.map +1 -1
  188. package/dist/public/operations/contracts.js +63 -14
  189. package/dist/public/operations/discovery-entities.d.ts +15 -0
  190. package/dist/public/operations/discovery-entities.d.ts.map +1 -1
  191. package/dist/public/operations/discovery-entities.js +59 -0
  192. package/dist/public/operations/discovery-executors.d.ts +6 -1
  193. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  194. package/dist/public/operations/discovery-executors.js +65 -6
  195. package/dist/public/operations/index.d.ts +1 -0
  196. package/dist/public/operations/index.d.ts.map +1 -1
  197. package/dist/public/operations/index.js +1 -0
  198. package/dist/public/operations/migration-plan.d.ts +5 -0
  199. package/dist/public/operations/migration-plan.d.ts.map +1 -1
  200. package/dist/public/operations/migration-plan.js +26 -1
  201. package/dist/public/operations/node-ports.d.ts.map +1 -1
  202. package/dist/public/operations/node-ports.js +24 -3
  203. package/dist/public/operations/origin-review.d.ts +51 -0
  204. package/dist/public/operations/origin-review.d.ts.map +1 -0
  205. package/dist/public/operations/origin-review.js +307 -0
  206. package/dist/public/operations/predicate-schema-conformance.js +1 -1
  207. package/dist/public/operations/repair-plan.d.ts.map +1 -1
  208. package/dist/public/operations/repair-plan.js +4 -0
  209. package/dist/public/operations/result-envelope.d.ts.map +1 -1
  210. package/dist/public/operations/result-envelope.js +17 -5
  211. package/dist/public/operations/runtime-types.d.ts +9 -0
  212. package/dist/public/operations/runtime-types.d.ts.map +1 -1
  213. package/dist/public/operations/schema6-check-actions.d.ts +127 -0
  214. package/dist/public/operations/schema6-check-actions.d.ts.map +1 -0
  215. package/dist/public/operations/schema6-check-actions.js +575 -0
  216. package/dist/public/operations/source-path-dangling.d.ts +17 -0
  217. package/dist/public/operations/source-path-dangling.d.ts.map +1 -0
  218. package/dist/public/operations/source-path-dangling.js +66 -0
  219. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  220. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  221. package/dist/public/operations/specs/check-rules.generated.js +15 -1
  222. package/dist/public/operations/specs/check.d.ts +2 -2
  223. package/dist/public/operations/specs/check.js +1 -1
  224. package/dist/public/operations/specs/composite.d.ts +351 -0
  225. package/dist/public/operations/specs/composite.d.ts.map +1 -0
  226. package/dist/public/operations/specs/composite.js +96 -0
  227. package/dist/public/operations/specs/discovery.d.ts +8 -3
  228. package/dist/public/operations/specs/discovery.d.ts.map +1 -1
  229. package/dist/public/operations/specs/discovery.js +8 -3
  230. package/dist/public/operations/specs/modeling.d.ts +2 -2
  231. package/dist/public/operations/specs/modeling.js +2 -2
  232. package/dist/public/operations/specs/mutation-schemas.d.ts +73 -8
  233. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  234. package/dist/public/operations/specs/mutation-schemas.js +43 -7
  235. package/dist/public/operations/specs/mutation.d.ts +1 -1
  236. package/dist/public/operations/specs/mutation.js +1 -1
  237. package/dist/public/operations/specs/planning.d.ts +2 -2
  238. package/dist/public/operations/specs/planning.js +4 -4
  239. package/dist/public/operations/specs/reporting.d.ts.map +1 -1
  240. package/dist/public/operations/specs/reporting.js +13 -26
  241. package/dist/public/operations/specs/upsert.d.ts +79 -9
  242. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  243. package/dist/public/operations/specs/upsert.js +6 -1
  244. package/dist/public/operations/types.d.ts +1 -1
  245. package/dist/public/operations/types.d.ts.map +1 -1
  246. package/dist/public/proof-receipt.d.ts +1 -0
  247. package/dist/public/proof-receipt.d.ts.map +1 -1
  248. package/dist/public/schemas/entity.d.ts.map +1 -1
  249. package/dist/public/schemas/entity.js +52 -0
  250. package/dist/public/schemas/relationship.d.ts.map +1 -1
  251. package/dist/public/schemas/relationship.js +2 -0
  252. package/dist/public/skills/kibi-bootstrap/SKILL.md +6 -1
  253. package/dist/public/skills/kibi-bootstrap/resources/bootstrap.md +6 -0
  254. package/dist/public/skills/kibi-usage/SKILL.md +68 -18
  255. package/dist/public/skills/kibi-usage/resources/fact-lanes.md +5 -5
  256. package/dist/public/skills/kibi-usage/resources/kb-improvement.md +1 -1
  257. package/dist/public/skills/kibi-usage/resources/logic-ir.md +2 -2
  258. package/dist/public/skills/kibi-usage/resources/operation-access.md +25 -1
  259. package/dist/public/skills/kibi-usage/resources/ui-requirements.md +4 -4
  260. package/dist/public/skills/kibi-usage/resources/workflows.md +42 -25
  261. package/dist/public/telemetry-acceptance.d.ts +58 -2
  262. package/dist/public/telemetry-acceptance.d.ts.map +1 -1
  263. package/dist/public/telemetry-acceptance.js +136 -10
  264. package/dist/public/telemetry-remediation.d.ts.map +1 -1
  265. package/dist/public/telemetry-remediation.js +26 -10
  266. package/dist/relationships/shards.d.ts +13 -0
  267. package/dist/relationships/shards.d.ts.map +1 -1
  268. package/dist/relationships/shards.js +54 -28
  269. package/dist/runtime/cli-runtime.d.ts.map +1 -1
  270. package/dist/runtime/cli-runtime.js +44 -3
  271. package/dist/runtime/detached-snapshot.d.ts +38 -0
  272. package/dist/runtime/detached-snapshot.d.ts.map +1 -0
  273. package/dist/runtime/detached-snapshot.js +92 -0
  274. package/dist/schemas/entity.schema.json +122 -0
  275. package/dist/search-answer.d.ts +157 -0
  276. package/dist/search-answer.d.ts.map +1 -0
  277. package/dist/search-answer.js +846 -0
  278. package/dist/traceability/impact-knowledge.d.ts.map +1 -1
  279. package/dist/traceability/impact-knowledge.js +7 -0
  280. package/dist/traceability/symbol-extract.js +3 -3
  281. package/dist/traceability/temp-kb.d.ts.map +1 -1
  282. package/dist/traceability/temp-kb.js +12 -0
  283. package/dist/types/entities.d.ts +13 -0
  284. package/dist/types/entities.d.ts.map +1 -1
  285. package/dist/types/relationships.d.ts +1 -1
  286. package/dist/types/relationships.d.ts.map +1 -1
  287. package/dist/utils/branch-resolver.d.ts +37 -1
  288. package/dist/utils/branch-resolver.d.ts.map +1 -1
  289. package/dist/utils/branch-resolver.js +130 -3
  290. package/dist/utils/repo-relative-path.d.ts +18 -0
  291. package/dist/utils/repo-relative-path.d.ts.map +1 -0
  292. package/dist/utils/repo-relative-path.js +58 -0
  293. package/dist/utils/rule-registry.generated.d.ts +75 -3
  294. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  295. package/dist/utils/rule-registry.generated.js +89 -3
  296. package/dist/utils/schema-version.d.ts +1 -1
  297. package/dist/utils/schema-version.d.ts.map +1 -1
  298. package/dist/utils/schema-version.js +4 -3
  299. package/dist/utils/strict-modeling.d.ts +1 -1
  300. package/dist/utils/strict-modeling.d.ts.map +1 -1
  301. package/dist/utils/strict-modeling.js +23 -3
  302. package/package.json +3 -3
  303. package/schema/entities.pl +22 -0
  304. package/schema/relationships.pl +14 -0
  305. package/schema/validation.pl +45 -1
  306. package/src/public/branch-resolver.ts +1 -0
  307. package/src/public/entity-origin.ts +175 -0
  308. package/src/public/impact/full-kb-quality.ts +1 -0
  309. package/src/public/impact/requirement-quality.ts +1 -1
  310. package/src/public/operations/catalog.ts +3 -0
  311. package/src/public/operations/check-executor.ts +15 -0
  312. package/src/public/operations/contracts.ts +75 -15
  313. package/src/public/operations/discovery-entities.ts +74 -0
  314. package/src/public/operations/discovery-executors.ts +88 -10
  315. package/src/public/operations/index.ts +1 -0
  316. package/src/public/operations/migration-plan.ts +30 -1
  317. package/src/public/operations/node-ports.ts +24 -3
  318. package/src/public/operations/origin-review.ts +375 -0
  319. package/src/public/operations/predicate-schema-conformance.ts +1 -1
  320. package/src/public/operations/repair-plan.ts +4 -0
  321. package/src/public/operations/result-envelope.ts +18 -6
  322. package/src/public/operations/runtime-types.ts +9 -0
  323. package/src/public/operations/schema6-check-actions.ts +699 -0
  324. package/src/public/operations/source-path-dangling.ts +81 -0
  325. package/src/public/operations/specs/check-rules.generated.ts +15 -1
  326. package/src/public/operations/specs/check.ts +1 -1
  327. package/src/public/operations/specs/composite.ts +141 -0
  328. package/src/public/operations/specs/discovery.ts +9 -3
  329. package/src/public/operations/specs/modeling.ts +2 -2
  330. package/src/public/operations/specs/mutation-schemas.ts +49 -7
  331. package/src/public/operations/specs/mutation.ts +1 -1
  332. package/src/public/operations/specs/planning.ts +4 -4
  333. package/src/public/operations/specs/reporting.ts +13 -38
  334. package/src/public/operations/specs/upsert.ts +7 -1
  335. package/src/public/operations/types.ts +2 -0
  336. package/src/public/proof-receipt.ts +1 -0
  337. package/src/public/schemas/entity.ts +57 -0
  338. package/src/public/schemas/relationship.ts +2 -0
  339. package/src/public/skills/kibi-bootstrap/SKILL.md +6 -1
  340. package/src/public/skills/kibi-bootstrap/resources/bootstrap.md +6 -0
  341. package/src/public/skills/kibi-usage/SKILL.md +68 -18
  342. package/src/public/skills/kibi-usage/resources/fact-lanes.md +5 -5
  343. package/src/public/skills/kibi-usage/resources/kb-improvement.md +1 -1
  344. package/src/public/skills/kibi-usage/resources/logic-ir.md +2 -2
  345. package/src/public/skills/kibi-usage/resources/operation-access.md +25 -1
  346. package/src/public/skills/kibi-usage/resources/ui-requirements.md +4 -4
  347. package/src/public/skills/kibi-usage/resources/workflows.md +42 -25
  348. package/src/public/telemetry-acceptance-types.d.ts +4 -1
  349. package/src/public/telemetry-acceptance.ts +204 -10
  350. package/src/public/telemetry-remediation.ts +39 -10
  351. package/src/schemas/entity.schema.json +122 -0
  352. package/src/schemas/relationship.schema.json +2 -0
@@ -39,8 +39,13 @@ import {
39
39
  buildMigrationPlan,
40
40
  mergeMigrationPlans,
41
41
  } from "./migration-plan.js";
42
+ import { collectOriginReviewViolations } from "./origin-review.js";
42
43
  import { collectPredicateSchemaConformanceViolations } from "./predicate-schema-conformance.js";
43
44
  import type { OperationContext, PrologPort } from "./runtime-types.js";
45
+ import {
46
+ SOURCE_PATH_DANGLING_RULE,
47
+ collectSourcePathDanglingViolations,
48
+ } from "./source-path-dangling.js";
44
49
  import { collectSourceRelationshipParityViolations } from "./source-relationship-parity.js";
45
50
  import type { OperationResult } from "./types.js";
46
51
  import { readWorkspaceSnapshot } from "./workspace-snapshot.js";
@@ -211,11 +216,21 @@ export async function executeCheck(
211
216
  )
212
217
  ? await collectPredicateSchemaConformanceViolations(prolog)
213
218
  : [];
219
+ const sourcePathFindings = rulesAllowlist.has(SOURCE_PATH_DANGLING_RULE)
220
+ ? collectSourcePathDanglingViolations(workspaceRoot)
221
+ : [];
222
+ const originReviewFindings = await collectOriginReviewViolations(
223
+ prolog,
224
+ rulesAllowlist,
225
+ workspaceRoot,
226
+ );
214
227
  const partitioned = partitionCheckFindings([
215
228
  ...aggregatedFindings,
216
229
  ...queryPlanViolations,
217
230
  ...sourceRelationshipParityViolations,
231
+ ...sourcePathFindings,
218
232
  ...predicateConformanceFindings,
233
+ ...originReviewFindings,
219
234
  ]);
220
235
  const violations: Violation[] = partitioned.violations;
221
236
 
@@ -429,8 +429,8 @@ export function nullableJsonSchema(
429
429
  * implementations. Every catalog entry therefore has a concrete payload
430
430
  * shape, while nested domain records can still evolve independently.
431
431
  */
432
- export const OPERATION_DATA_SCHEMAS: Readonly<
433
- Record<OperationName, OperationJsonSchema>
432
+ const BASE_DATA_SCHEMAS: Readonly<
433
+ Record<Exclude<OperationName, "kb_skills" | "kb_model">, OperationJsonSchema>
434
434
  > = {
435
435
  kb_skills_list: objectData({ skills: valueArray }, ["skills"]),
436
436
  kb_skills_load: objectData({
@@ -446,7 +446,13 @@ export const OPERATION_DATA_SCHEMAS: Readonly<
446
446
  "count",
447
447
  ]),
448
448
  kb_search: objectData(
449
- { results: valueArray, count: integerValue, queryAnalysis: recordValue },
449
+ {
450
+ results: valueArray,
451
+ count: integerValue,
452
+ truncated: booleanValue,
453
+ queryAnalysis: recordValue,
454
+ answer: recordValue,
455
+ },
450
456
  ["results", "count"],
451
457
  ),
452
458
  kb_status: objectData({
@@ -601,18 +607,36 @@ export const OPERATION_DATA_SCHEMAS: Readonly<
601
607
  semanticAdvisor: nullableJsonSchema(recordValue),
602
608
  normalizedPreview: nullableJsonSchema(recordValue),
603
609
  }),
604
- kb_upsert: objectData({
605
- created: integerValue,
606
- updated: integerValue,
607
- relationships_created: integerValue,
608
- warnings: valueArray,
609
- semanticAdvisor: recordValue,
610
- status: stringValue,
611
- effectFailures: recordArray,
612
- nextActions: recordArray,
613
- sourceWrites: recordArray,
614
- contradictionCheck: recordValue,
615
- }),
610
+ kb_upsert: {
611
+ description:
612
+ "Committed upsert payload, or the validation preview when dryRun:true wrote nothing.",
613
+ anyOf: [
614
+ objectData({
615
+ created: integerValue,
616
+ updated: integerValue,
617
+ relationships_created: integerValue,
618
+ warnings: valueArray,
619
+ semanticAdvisor: recordValue,
620
+ status: stringValue,
621
+ effectFailures: recordArray,
622
+ nextActions: recordArray,
623
+ sourceWrites: recordArray,
624
+ contradictionCheck: recordValue,
625
+ }),
626
+ objectData(
627
+ {
628
+ valid: booleanValue,
629
+ errors: valueArray,
630
+ warnings: valueArray,
631
+ semanticAdvisor: nullableJsonSchema(recordValue),
632
+ normalizedPreview: nullableJsonSchema(recordValue),
633
+ dryRun: { const: true },
634
+ skippedEffects: stringArray,
635
+ },
636
+ ["valid", "dryRun", "skippedEffects"],
637
+ ),
638
+ ],
639
+ },
616
640
  kb_delete: objectData({
617
641
  deleted: integerValue,
618
642
  relationships_deleted: integerValue,
@@ -722,6 +746,40 @@ export const OPERATION_DATA_SCHEMAS: Readonly<
722
746
  }),
723
747
  };
724
748
 
749
+ /** A composite operation returns the routed operation's payload plus the
750
+ * selector that chose it. */
751
+ function compositeData(
752
+ selector: "action" | "mode",
753
+ routes: Readonly<Record<string, OperationJsonSchema>>,
754
+ ): OperationJsonSchema {
755
+ return {
756
+ anyOf: Object.entries(routes).map(([choice, schema]) => ({
757
+ ...schema,
758
+ required: [selector, ...((schema.required as string[]) ?? [])],
759
+ properties: {
760
+ [selector]: { const: choice },
761
+ ...(schema.properties as Record<string, OperationJsonSchema>),
762
+ },
763
+ })),
764
+ };
765
+ }
766
+
767
+ export const OPERATION_DATA_SCHEMAS: Readonly<
768
+ Record<OperationName, OperationJsonSchema>
769
+ > = {
770
+ ...BASE_DATA_SCHEMAS,
771
+ kb_skills: compositeData("action", {
772
+ list: BASE_DATA_SCHEMAS.kb_skills_list,
773
+ load: BASE_DATA_SCHEMAS.kb_skills_load,
774
+ read: BASE_DATA_SCHEMAS.kb_skills_read,
775
+ }),
776
+ kb_model: compositeData("mode", {
777
+ analyze: BASE_DATA_SCHEMAS.kb_semantic_advisor,
778
+ requirement: BASE_DATA_SCHEMAS.kb_model_requirement,
779
+ predicates: BASE_DATA_SCHEMAS.kb_suggest_predicates,
780
+ }),
781
+ };
782
+
725
783
  type EffectOverrides = Readonly<{
726
784
  destructive?: boolean;
727
785
  retrySafety?: "safe" | "unsafe";
@@ -737,6 +795,7 @@ const EFFECT_OVERRIDES: Readonly<
737
795
  kb_skills_list: {},
738
796
  kb_skills_load: {},
739
797
  kb_skills_read: {},
798
+ kb_skills: {},
740
799
  kb_query: {},
741
800
  kb_search: {},
742
801
  kb_status: {},
@@ -747,6 +806,7 @@ const EFFECT_OVERRIDES: Readonly<
747
806
  kb_semantic_advisor: {},
748
807
  kb_model_requirement: {},
749
808
  kb_suggest_predicates: {},
809
+ kb_model: {},
750
810
  kb_plan_bootstrap: {},
751
811
  kb_validate_upsert: {},
752
812
  kb_upsert: {
@@ -404,6 +404,80 @@ export async function loadEntityIds(
404
404
  return parseAtomList(result.bindings.Ids ?? "[]").map(normalizeEntityId);
405
405
  }
406
406
 
407
+ /**
408
+ * Properties a projected entity row keeps: what intent ranking, result
409
+ * summaries and the search answer layer read. Large structured properties
410
+ * (receipt histories, proof contracts, semantic inventories, rule IR) are
411
+ * left in the store, as for search candidate rows.
412
+ */
413
+ // implements REQ-kibi-search-answer-layer-v2
414
+ export const ENTITY_ROW_KEYS = [
415
+ "id",
416
+ "title",
417
+ "status",
418
+ "priority",
419
+ "severity",
420
+ "owner",
421
+ "tags",
422
+ "source",
423
+ "sourceFile",
424
+ "sourceLine",
425
+ "sourceColumn",
426
+ "sourceEndLine",
427
+ "sourceEndColumn",
428
+ "source_line",
429
+ "source_end_line",
430
+ "updated_at",
431
+ "created_at",
432
+ "semantic_text",
433
+ "text_ref",
434
+ "fact_kind",
435
+ "expects",
436
+ "approved_by",
437
+ "approval_ref",
438
+ ] as const;
439
+
440
+ /** Upper bound on ids per batched row query, so one answer stays bounded. */
441
+ // implements REQ-kibi-search-answer-layer-v2
442
+ export const ENTITY_ROW_BATCH_LIMIT = 200;
443
+
444
+ // implements REQ-mcp-search-discovery, REQ-kibi-search-answer-layer-v2
445
+ export function entityRowsGoal(
446
+ ids: readonly string[],
447
+ keys: readonly string[] = ENTITY_ROW_KEYS,
448
+ ): string {
449
+ const idList = ids.map((id) => `'${escapeAtomContent(id)}'`).join(",");
450
+ const keyList = keys.map((key) => `'${escapeAtomContent(key)}'`).join(",");
451
+ return `findall([Id,Type,Row], (member(Id, [${idList}]), kb_entity(Id, Type, Props), findall(Key=Value, (member(Key=Value, Props), memberchk(Key, [${keyList}])), Row)), Results)`;
452
+ }
453
+
454
+ /**
455
+ * Projected rows for several entities in one Prolog query, in place of one
456
+ * `loadEntities({ id })` round trip per entity. Unknown ids are skipped.
457
+ */
458
+ // implements REQ-mcp-search-discovery, REQ-kibi-search-answer-layer-v2
459
+ export async function loadEntityRows(
460
+ prolog: Pick<PrologPort, "query">,
461
+ ids: readonly string[],
462
+ keys: readonly string[] = ENTITY_ROW_KEYS,
463
+ ): Promise<Record<string, unknown>[]> {
464
+ const unique = [...new Set(ids.filter((id) => id.length > 0))];
465
+ const rows: Record<string, unknown>[] = [];
466
+ for (let start = 0; start < unique.length; start += ENTITY_ROW_BATCH_LIMIT) {
467
+ const batch = unique.slice(start, start + ENTITY_ROW_BATCH_LIMIT);
468
+ const result = await prolog.query(entityRowsGoal(batch, keys));
469
+ if (!result.success) {
470
+ throw new Error(result.error || "Entity row query failed");
471
+ }
472
+ rows.push(
473
+ ...parseListOfLists(result.bindings.Results ?? "[]").map(
474
+ parseEntityFromList,
475
+ ),
476
+ );
477
+ }
478
+ return dedupeEntities(rows);
479
+ }
480
+
407
481
  /**
408
482
  * Replace projected search candidates with complete entities, one bounded
409
483
  * query per entity. Used only for the final result page when a caller asks
@@ -1,3 +1,4 @@
1
+ import path from "node:path";
1
2
  import { compilerFingerprintReason } from "../../commands/sync/cache.js";
2
3
  import { EngineClient } from "../../engine.js";
3
4
  import {
@@ -9,6 +10,8 @@ import {
9
10
  validateIntentSearchInput,
10
11
  } from "../../intent-search.js";
11
12
  import { classifyActivation } from "../../operations/bootstrap/activation.js";
13
+ import { SwiplResolutionError } from "../../prolog/swipl-resolver.js";
14
+ import { type SearchAnswer, buildSearchAnswer } from "../../search-answer.js";
12
15
  import { rankEntities } from "../../search-ranking.js";
13
16
  import type { SearchMatch } from "../../search-ranking.js";
14
17
  import { resolveBranchAttachment } from "../../utils/branch-resolver.js";
@@ -64,12 +67,15 @@ export type SearchInput = {
64
67
  readonly sourceLocations?: readonly SourceLocation[];
65
68
  readonly minScore?: number;
66
69
  readonly fields?: "summary" | "full";
70
+ readonly answer?: boolean;
67
71
  };
68
72
 
69
73
  export type SearchPayload = {
70
74
  readonly results: readonly (SearchMatch | IntentSearchMatch)[];
71
75
  readonly count: number;
76
+ readonly truncated?: boolean;
72
77
  readonly queryAnalysis?: IntentSearchAnalysis;
78
+ readonly answer?: SearchAnswer;
73
79
  };
74
80
 
75
81
  export type StatusInput = Readonly<Record<string, never>>;
@@ -94,7 +100,11 @@ export type StatusPayload = {
94
100
  readonly branchAttachment?: {
95
101
  readonly gitBranch: string;
96
102
  readonly kbBranch: string;
97
- readonly kind: "exact" | "explicit_override" | "legacy_compat";
103
+ readonly kind:
104
+ | "exact"
105
+ | "explicit_override"
106
+ | "legacy_compat"
107
+ | "detached_snapshot";
98
108
  readonly migrationRequired: boolean;
99
109
  };
100
110
  readonly proofSnapshotChanges?: readonly Record<string, unknown>[];
@@ -110,6 +120,9 @@ export type StatusPayload = {
110
120
  readonly schemaStatus?: MigrationConfigStatus;
111
121
  readonly migrationPlan?: MigrationPlan;
112
122
  readonly bootstrap?: {
123
+ readonly incompleteApplications?: readonly Readonly<
124
+ Record<string, unknown>
125
+ >[];
113
126
  readonly activationState: string;
114
127
  readonly activationMode: string;
115
128
  readonly planEligible: boolean;
@@ -244,11 +257,12 @@ export async function executeSearch(
244
257
  type,
245
258
  limit = 20,
246
259
  offset = 0,
247
- rankingMode = "legacy",
260
+ rankingMode = "intent-v1",
248
261
  semanticFacets,
249
262
  sourceLocations,
250
263
  minScore,
251
264
  fields = "summary",
265
+ answer,
252
266
  } = input;
253
267
  const trimmedQuery = query.trim();
254
268
  if (!trimmedQuery) {
@@ -278,21 +292,34 @@ export async function executeSearch(
278
292
  context.workspaceRoot,
279
293
  );
280
294
  const paginated = paginateResults(intentResult.matches, limit, offset);
295
+ // The answer layer summarizes the whole ranking, so it belongs to the
296
+ // first page only.
297
+ const answerLayer =
298
+ (answer ?? true) && offset === 0 && intentResult.matches.length > 0
299
+ ? await buildSearchAnswer(prolog, intentResult.matches, {
300
+ workspaceRoot: context.workspaceRoot,
301
+ branch: context.branchAttachment?.kbBranch ?? null,
302
+ })
303
+ : undefined;
304
+ // The structured payload carries every row; the text is a short
305
+ // human-readable digest instead of a second copy of the results.
281
306
  const text =
282
307
  intentResult.matches.length === 0
283
308
  ? `No intent search results for '${trimmedQuery}' (abstained).`
284
- : `Found ${intentResult.matches.length} intent search results for '${trimmedQuery}'. Showing ${paginated.length} (offset ${offset}, limit ${limit}): ${paginated
285
- .map(
286
- (match) =>
287
- `${String(match.entity.id ?? "")} [${match.reasons.join(", ")}]`,
288
- )
289
- .join(", ")}`;
309
+ : `Found ${intentResult.matches.length} intent search results for '${trimmedQuery}'${intentResult.analysis.ambiguous ? " (top matches are close; confirm before relying on one)" : ""}. Top: ${paginated
310
+ .slice(0, 5)
311
+ .map((match) => String(match.entity.id ?? ""))
312
+ .join(
313
+ ", ",
314
+ )}${answerLayer ? `. Governing: ${answerLayer.governing.map((req) => req.id).join(", ") || "none found"}` : ""}.`;
290
315
  return {
291
316
  content: [{ type: "text", text }],
292
317
  structuredContent: {
293
318
  results: await projectMatches(prolog, paginated, fields),
294
319
  count: intentResult.matches.length,
320
+ truncated: offset + paginated.length < intentResult.matches.length,
295
321
  queryAnalysis: intentResult.analysis,
322
+ ...(answerLayer ? { answer: answerLayer } : {}),
296
323
  },
297
324
  };
298
325
  }
@@ -327,6 +354,7 @@ export async function executeSearch(
327
354
  structuredContent: {
328
355
  results: await projectMatches(prolog, paginated, fields),
329
356
  count: matches.length,
357
+ truncated: offset + paginated.length < matches.length,
330
358
  },
331
359
  };
332
360
  } catch (error) {
@@ -408,7 +436,9 @@ export async function executeStatus(
408
436
  errorCode:
409
437
  error instanceof OperationJsonDecodeError
410
438
  ? error.code
411
- : "engine_status_unavailable",
439
+ : error instanceof SwiplResolutionError
440
+ ? error.code
441
+ : "engine_status_unavailable",
412
442
  detail: message,
413
443
  recoveryRequired: false,
414
444
  };
@@ -440,8 +470,13 @@ export async function executeStatus(
440
470
  detail:
441
471
  engineStatus.detail ??
442
472
  "The branch store is structurally readable but the engine status response is unavailable.",
473
+ // implements REQ-prolog-doctor-runtime-report
474
+ // A missing or unusable SWI-Prolog is not fixed by restarting the
475
+ // engine; point at the diagnostic that reports the resolution.
443
476
  remediation: {
444
- command_argv: ["kibi", "engine", "stop"],
477
+ command_argv: engineStatus.errorCode?.startsWith("swipl_")
478
+ ? ["kibi", "doctor"]
479
+ : ["kibi", "engine", "stop"],
445
480
  applyRequired: false,
446
481
  },
447
482
  }
@@ -519,11 +554,54 @@ export async function executeStatus(
519
554
  context,
520
555
  bootstrapSourceFiles,
521
556
  );
557
+ const incompleteApplications: Readonly<Record<string, unknown>>[] = [];
558
+ if (context.fs?.glob) {
559
+ // Scope the scan to recovery itself: workspace globs intentionally exclude
560
+ // compiled and recovery internals from source discovery.
561
+ const recoveryRoot = path.join(context.workspaceRoot, ".kb", "recovery");
562
+ const journals = await context.fs.glob(["bootstrap-*.json"], {
563
+ cwd: recoveryRoot,
564
+ });
565
+ for (const journalPath of journals) {
566
+ try {
567
+ const journal = JSON.parse(
568
+ await context.fs.readFile(path.resolve(recoveryRoot, journalPath)),
569
+ );
570
+ if (
571
+ journal.kind === "bootstrap" &&
572
+ ["rejected", "repair_required", "applying"].includes(journal.state)
573
+ )
574
+ incompleteApplications.push({
575
+ journalId: path.basename(journalPath, ".json"),
576
+ state: journal.state,
577
+ appliedActions: (journal.results ?? []).filter(
578
+ (row: { outcome?: string }) => row.outcome === "applied",
579
+ ).length,
580
+ failedActions: (journal.results ?? []).filter(
581
+ (row: { outcome?: string }) => row.outcome === "failed",
582
+ ),
583
+ nextOperation:
584
+ journal.state === "rejected"
585
+ ? "kb_plan_bootstrap"
586
+ : "kb_apply_plan",
587
+ });
588
+ } catch (error) {
589
+ incompleteApplications.push({
590
+ journalId: path.basename(journalPath, ".json"),
591
+ state: "unreadable",
592
+ detail: error instanceof Error ? error.message : String(error),
593
+ });
594
+ }
595
+ }
596
+ }
522
597
  const statusWithPlan: StatusPayload = {
523
598
  ...enrichedPayload,
524
599
  schemaStatus,
525
600
  migrationPlan,
526
601
  bootstrap: {
602
+ ...(incompleteApplications.length > 0
603
+ ? { incompleteApplications }
604
+ : {}),
527
605
  activationState: bootstrapActivation.activationState,
528
606
  activationMode: bootstrapActivation.activationMode,
529
607
  planEligible:
@@ -11,6 +11,7 @@ export * from "./migration-plan.js";
11
11
  export * from "./symbol-repair-plan.js";
12
12
  export * from "./specs/bootstrap.js";
13
13
  export * from "./specs/check.js";
14
+ export * from "./specs/composite.js";
14
15
  export * from "./specs/impact-review-preparation.js";
15
16
  export * from "./specs/discovery.js";
16
17
  export * from "./specs/modeling.js";
@@ -7,6 +7,10 @@ import {
7
7
  getSchemaVersionStatus,
8
8
  normalizeSchemaVersion,
9
9
  } from "../../utils/schema-version.js";
10
+ import {
11
+ lifecycleActionsFromViolations,
12
+ schema6ReviewActionsFromCheck,
13
+ } from "./schema6-check-actions.js";
10
14
 
11
15
  export const MIGRATION_PLAN_VERSION = "kibi.migration-plan.v2" as const;
12
16
 
@@ -286,6 +290,25 @@ export function mergeMigrationPlans(
286
290
  });
287
291
  }
288
292
 
293
+ /**
294
+ * The same plan without the actions whose code another planner owns, e.g.
295
+ * lifecycle repairs `kibi migrate` plans from authored sources.
296
+ */
297
+ // implements REQ-agent-guided-migration-orchestration
298
+ export function withoutActionCodes(
299
+ plan: MigrationPlan,
300
+ codes: ReadonlySet<string>,
301
+ ): MigrationPlan {
302
+ if (!plan.actions.some((action) => codes.has(action.code))) return plan;
303
+ return buildMigrationPlan({
304
+ expected: plan.expected,
305
+ evaluatedDomains: plan.scope.evaluatedDomains,
306
+ incompleteDomains: plan.scope.incompleteDomains,
307
+ actions: plan.actions.filter((action) => !codes.has(action.code)),
308
+ diagnostics: plan.diagnostics,
309
+ });
310
+ }
311
+
289
312
  function actionDefaults(input: Partial<MigrationAction>): MigrationAction {
290
313
  return {
291
314
  id: input.id ?? "migration-action-unknown",
@@ -370,13 +393,16 @@ function predicateSchemaAlignmentAction(
370
393
  /** Migration code for mechanical predicate namespace/alias repairs. */
371
394
  export const PREDICATE_SCHEMA_ALIGNMENT_CODE = "predicate_schema_alignment";
372
395
 
373
- // implements REQ-agent-guided-migration-orchestration, REQ-kibi-predicate-vocabulary-migration
396
+ // implements REQ-agent-guided-migration-orchestration, REQ-kibi-predicate-vocabulary-migration, REQ-cli-schema-migration
374
397
  export function buildActionsFromCheck(input: {
375
398
  violations?: readonly Readonly<Record<string, unknown>>[];
376
399
  qualityDiagnostics?: readonly Readonly<Record<string, unknown>>[];
377
400
  }): MigrationAction[] {
378
401
  const actions: MigrationAction[] = [];
402
+ const lifecycle = lifecycleActionsFromViolations(input.violations ?? []);
403
+ actions.push(...lifecycle.actions.map(migrationAction));
379
404
  for (const [index, violation] of (input.violations ?? []).entries()) {
405
+ if (lifecycle.consumed.has(index)) continue;
380
406
  const rule = typeof violation.rule === "string" ? violation.rule : "check";
381
407
  const entityId =
382
408
  typeof violation.entityId === "string" ? violation.entityId : "";
@@ -399,9 +425,12 @@ export function buildActionsFromCheck(input: {
399
425
  }),
400
426
  );
401
427
  }
428
+ const reviews = schema6ReviewActionsFromCheck(input.qualityDiagnostics ?? []);
429
+ actions.push(...reviews.actions.map(migrationAction));
402
430
  for (const [index, diagnostic] of (
403
431
  input.qualityDiagnostics ?? []
404
432
  ).entries()) {
433
+ if (reviews.consumed.has(index)) continue;
405
434
  const id = typeof diagnostic.id === "string" ? diagnostic.id : "quality";
406
435
  const entityId =
407
436
  typeof diagnostic.entityId === "string" ? diagnostic.entityId : "";
@@ -101,19 +101,26 @@ async function workspaceSnapshot(workspaceRoot: string) {
101
101
  ],
102
102
  { encoding: "buffer", maxBuffer: 64 * 1024 * 1024 },
103
103
  );
104
+ // The snapshot names each file by its repo-relative path in Unicode NFC, so
105
+ // a checkout whose filesystem reports decomposed names (macOS) hashes the
106
+ // same commit to the same snapshot as a Linux CI runner. The raw name is
107
+ // kept only to read the file.
104
108
  const paths = listed
105
109
  .toString("utf8")
106
110
  .split("\0")
107
111
  .filter(Boolean)
108
112
  .filter(includedSnapshotPath)
109
- .sort();
113
+ .map((raw) => ({ raw, key: raw.normalize("NFC") }))
114
+ .sort((left, right) =>
115
+ left.key < right.key ? -1 : left.key > right.key ? 1 : 0,
116
+ );
110
117
  const digest = createHash("sha256");
111
118
  digest.update("kibi.workspace-snapshot.v2\0");
112
- for (const relativePath of paths) {
119
+ for (const { raw, key: relativePath } of paths) {
113
120
  digest.update(relativePath);
114
121
  digest.update("\0");
115
122
  try {
116
- const content = await fs.readFile(path.join(workspaceRoot, relativePath));
123
+ const content = await fs.readFile(path.join(workspaceRoot, raw));
117
124
  digest.update(snapshotFileContent(relativePath, content));
118
125
  } catch (error) {
119
126
  const code =
@@ -188,6 +195,20 @@ export const nodeFilesystem: NodeFilesystemPort = {
188
195
  },
189
196
  stat: (filePath) => fs.stat(filePath),
190
197
  unlink: (filePath) => fs.unlink(filePath),
198
+ fsync: async (filePath) => {
199
+ // Windows cannot open a directory handle; directory entries are durable
200
+ // there once the rename returns.
201
+ if (process.platform === "win32") {
202
+ const stat = await fs.stat(filePath);
203
+ if (stat.isDirectory()) return;
204
+ }
205
+ const handle = await fs.open(filePath, "r");
206
+ try {
207
+ await handle.sync();
208
+ } finally {
209
+ await handle.close();
210
+ }
211
+ },
191
212
  glob: (patterns, options) =>
192
213
  fg([...patterns], {
193
214
  cwd: options.cwd,