@remnic/core 9.3.693 → 9.3.695

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 (358) hide show
  1. package/dist/access-boundary.d.ts +13 -12
  2. package/dist/access-boundary.js +36 -28
  3. package/dist/access-cli.js +62 -59
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +12 -11
  6. package/dist/access-http.js +40 -32
  7. package/dist/access-mcp.d.ts +19 -11
  8. package/dist/access-mcp.js +39 -31
  9. package/dist/access-operations.d.ts +56 -13
  10. package/dist/access-operations.js +66 -30
  11. package/dist/access-schema.js +3 -3
  12. package/dist/{access-service-DxCpgyVW.d.ts → access-service-BqBQeUJd.d.ts} +99 -3
  13. package/dist/access-service.d.ts +8 -7
  14. package/dist/access-service.js +35 -27
  15. package/dist/access-surface-catalog.d.ts +12 -11
  16. package/dist/access-surface-catalog.js +15 -0
  17. package/dist/access-surface-catalog.js.map +1 -1
  18. package/dist/action-confidence.d.ts +1 -1
  19. package/dist/active-memory-bridge.d.ts +1 -1
  20. package/dist/active-recall.d.ts +1 -1
  21. package/dist/active-recall.js +1 -1
  22. package/dist/{auto-sync-RWXT6P5M.js → auto-sync-PFW2NJZY.js} +8 -8
  23. package/dist/behavior-learner.d.ts +1 -1
  24. package/dist/behavior-signals.d.ts +1 -1
  25. package/dist/bootstrap.d.ts +9 -8
  26. package/dist/briefing.d.ts +1 -1
  27. package/dist/briefing.js +12 -5
  28. package/dist/buffer-surprise-report.d.ts +1 -1
  29. package/dist/buffer.d.ts +1 -1
  30. package/dist/calibration.d.ts +1 -1
  31. package/dist/calibration.js +2 -2
  32. package/dist/capabilities.d.ts +1 -1
  33. package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-YO5QJ6L3.js} +2 -2
  34. package/dist/{catalog-BEWLjdOr.d.ts → catalog-D7YDNNF7.d.ts} +1 -1
  35. package/dist/causal-behavior.d.ts +1 -1
  36. package/dist/causal-behavior.js +2 -2
  37. package/dist/causal-chain.js +2 -2
  38. package/dist/causal-consolidation.d.ts +1 -1
  39. package/dist/causal-consolidation.js +17 -16
  40. package/dist/causal-consolidation.js.map +1 -1
  41. package/dist/causal-retrieval.js +2 -2
  42. package/dist/causal-trajectory-graph.js +2 -2
  43. package/dist/causal-trajectory.js +1 -1
  44. package/dist/{chunk-UPTZYUYJ.js → chunk-24D66MMN.js} +2 -1
  45. package/dist/chunk-24D66MMN.js.map +1 -0
  46. package/dist/{chunk-THKNO6OX.js → chunk-32XTY2DQ.js} +52 -51
  47. package/dist/chunk-32XTY2DQ.js.map +1 -0
  48. package/dist/{chunk-YN4ZT4CW.js → chunk-3LYJIA76.js} +1 -1
  49. package/dist/{chunk-ADUAF5EV.js → chunk-3P2XEQSV.js} +2 -2
  50. package/dist/{chunk-KYH53EFD.js → chunk-4NNDJOAO.js} +8 -8
  51. package/dist/{chunk-QFG23CRE.js → chunk-52QIAN76.js} +2 -2
  52. package/dist/chunk-5AT62NQH.js +553 -0
  53. package/dist/chunk-5AT62NQH.js.map +1 -0
  54. package/dist/{chunk-TAPSNIMA.js → chunk-5CEJH5ZN.js} +4 -4
  55. package/dist/{chunk-4RGWCRIJ.js → chunk-5TYA4OCF.js} +4 -4
  56. package/dist/{chunk-FM7KLRKN.js → chunk-6GAUF4OU.js} +3 -3
  57. package/dist/{chunk-6C2BMUZA.js → chunk-AF6DSAWD.js} +2 -2
  58. package/dist/{chunk-2NLLXCJG.js → chunk-BXLOS5AJ.js} +2 -2
  59. package/dist/{chunk-32KD5IHZ.js → chunk-CLXTDOKV.js} +2 -2
  60. package/dist/{chunk-ARV3AUOM.js → chunk-DL6H3D7S.js} +2 -2
  61. package/dist/{chunk-X7Y7WX73.js → chunk-DQEMWVMT.js} +1 -1
  62. package/dist/{chunk-3BRA3N5A.js → chunk-EC3A6M43.js} +2 -2
  63. package/dist/{chunk-UTUYAPLY.js → chunk-EK6FYL2E.js} +38 -3
  64. package/dist/chunk-EK6FYL2E.js.map +1 -0
  65. package/dist/{chunk-ZLXGFAML.js → chunk-FZMH66NT.js} +2 -2
  66. package/dist/{chunk-HXNMDPHN.js → chunk-G663XUEG.js} +2 -2
  67. package/dist/{chunk-TYEOAFH3.js → chunk-G6SVZWPB.js} +10 -1
  68. package/dist/chunk-G6SVZWPB.js.map +1 -0
  69. package/dist/chunk-HKET3ZOI.js +381 -0
  70. package/dist/chunk-HKET3ZOI.js.map +1 -0
  71. package/dist/{chunk-YOI3ELXF.js → chunk-IF362TF6.js} +2 -2
  72. package/dist/{chunk-WIKNVFBS.js → chunk-J45OCIVH.js} +2 -2
  73. package/dist/{chunk-UDJLF3BO.js → chunk-JI6HWBYL.js} +2 -2
  74. package/dist/{chunk-ECZPWSB5.js → chunk-JJT3AGL4.js} +4 -4
  75. package/dist/{chunk-RHWFMBO5.js → chunk-JMAKCWJ3.js} +96 -7
  76. package/dist/chunk-JMAKCWJ3.js.map +1 -0
  77. package/dist/{chunk-4NFVPDIL.js → chunk-LM6JB2EG.js} +2 -2
  78. package/dist/{chunk-AFWEUTMS.js → chunk-LPIWEKZ3.js} +2 -2
  79. package/dist/{chunk-LD53WPMU.js → chunk-LQ6JI4VH.js} +4 -4
  80. package/dist/{chunk-U2OBZSGG.js → chunk-MNFAGE5D.js} +2 -2
  81. package/dist/{chunk-VFVG4NS2.js → chunk-MOBRVKWE.js} +23 -12
  82. package/dist/chunk-MOBRVKWE.js.map +1 -0
  83. package/dist/{chunk-MQTPUPLP.js → chunk-N4PD5IY3.js} +834 -51
  84. package/dist/chunk-N4PD5IY3.js.map +1 -0
  85. package/dist/{chunk-5HGPDRQZ.js → chunk-NFMDHE45.js} +2 -2
  86. package/dist/chunk-NFMDHE45.js.map +1 -0
  87. package/dist/{chunk-MCV2DD6F.js → chunk-NLZO5NO6.js} +2 -2
  88. package/dist/{chunk-3VVH6ZQW.js → chunk-Q6ZHGGNJ.js} +2 -2
  89. package/dist/{chunk-4IQNAOP3.js → chunk-Q7SFJURX.js} +2 -2
  90. package/dist/{chunk-MXZWKOOR.js → chunk-QJM2XAJD.js} +11 -11
  91. package/dist/{chunk-6ZNIUGXB.js → chunk-QQW2LIEA.js} +4 -4
  92. package/dist/{chunk-GCOSQBQ2.js → chunk-QVTSLRKT.js} +3 -3
  93. package/dist/{chunk-F7BVJ3IE.js → chunk-RWST6NOL.js} +166 -102
  94. package/dist/chunk-RWST6NOL.js.map +1 -0
  95. package/dist/{chunk-NUZ3N445.js → chunk-SPVIG2R3.js} +10 -10
  96. package/dist/{chunk-2D27ODNX.js → chunk-TIVZ4MCG.js} +2 -2
  97. package/dist/{chunk-5KBNNUXS.js → chunk-TT7BJWGI.js} +2 -2
  98. package/dist/{chunk-KQAFEZQX.js → chunk-VDX2J7OX.js} +2 -2
  99. package/dist/{chunk-E6BOD3UJ.js → chunk-VPAFWWCL.js} +2 -2
  100. package/dist/chunk-VQ7B2Q6M.js +112 -0
  101. package/dist/chunk-VQ7B2Q6M.js.map +1 -0
  102. package/dist/{chunk-UOCLRM74.js → chunk-W54EAJT4.js} +2 -2
  103. package/dist/{chunk-QVG4LAQO.js → chunk-WR6KFJKA.js} +7 -7
  104. package/dist/{chunk-YQGHW5ML.js → chunk-WRFKZEO6.js} +4 -4
  105. package/dist/{chunk-WYB44HHV.js → chunk-XUNQLJT2.js} +20 -8
  106. package/dist/chunk-XUNQLJT2.js.map +1 -0
  107. package/dist/{chunk-66HROLW5.js → chunk-XWT4JXXA.js} +2 -2
  108. package/dist/{chunk-SAC5V6JT.js → chunk-XXA6T3O4.js} +2 -2
  109. package/dist/{chunk-KF74X62T.js → chunk-YGKUAX2B.js} +4 -4
  110. package/dist/{chunk-W4ELOUNX.js → chunk-YOZNTNNA.js} +2 -2
  111. package/dist/{chunk-DQHZA7Y3.js → chunk-ZXUOAFUG.js} +1 -1
  112. package/dist/chunk-ZXUOAFUG.js.map +1 -0
  113. package/dist/{cli-DoQsv4ut.d.ts → cli-DBDgdvh9.d.ts} +3 -3
  114. package/dist/cli.d.ts +11 -10
  115. package/dist/cli.js +58 -50
  116. package/dist/coding/optional-coding-graph.js +7 -104
  117. package/dist/coding/optional-coding-graph.js.map +1 -1
  118. package/dist/compounding/engine.d.ts +1 -1
  119. package/dist/compounding/engine.js +12 -5
  120. package/dist/compounding/preference-consolidator.d.ts +1 -1
  121. package/dist/compression-optimizer.d.ts +1 -1
  122. package/dist/config.d.ts +1 -1
  123. package/dist/config.js +1 -1
  124. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  125. package/dist/connectors/codex-materialize-runner.js +12 -5
  126. package/dist/connectors/codex-materialize.d.ts +1 -1
  127. package/dist/connectors/index.d.ts +1 -1
  128. package/dist/connectors/index.js +12 -5
  129. package/dist/consolidation-provenance-check.d.ts +3 -3
  130. package/dist/consolidation-undo.d.ts +2 -2
  131. package/dist/contradiction/index.d.ts +1 -1
  132. package/dist/conversation-index/backend.d.ts +1 -1
  133. package/dist/conversation-index/chunker.d.ts +1 -1
  134. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  135. package/dist/conversation-index/indexer.d.ts +1 -1
  136. package/dist/conversation-index/search.d.ts +1 -1
  137. package/dist/day-summary.d.ts +1 -1
  138. package/dist/delinearize.d.ts +1 -1
  139. package/dist/direct-answer-wiring.d.ts +1 -1
  140. package/dist/direct-answer.d.ts +1 -1
  141. package/dist/embedding-fallback.d.ts +1 -1
  142. package/dist/enrichment/index.d.ts +1 -1
  143. package/dist/entity-retrieval.d.ts +1 -1
  144. package/dist/entity-retrieval.js +13 -5
  145. package/dist/entity-schema.d.ts +1 -1
  146. package/dist/explicit-capture.d.ts +9 -8
  147. package/dist/extraction-faithfulness.d.ts +211 -0
  148. package/dist/extraction-faithfulness.js +35 -0
  149. package/dist/extraction-judge-telemetry.d.ts +1 -1
  150. package/dist/extraction-judge-training.d.ts +1 -1
  151. package/dist/extraction-judge.d.ts +1 -1
  152. package/dist/extraction-judge.js +4 -4
  153. package/dist/extraction.d.ts +1 -1
  154. package/dist/extraction.js +7 -7
  155. package/dist/fallback-llm.d.ts +1 -1
  156. package/dist/fallback-llm.js +2 -2
  157. package/dist/{graph-edge-decay-D7OESCBR.js → graph-edge-decay-JLOF3YW4.js} +3 -3
  158. package/dist/graph-snapshot.js +3 -3
  159. package/dist/graph.js +2 -2
  160. package/dist/identity-continuity.d.ts +1 -1
  161. package/dist/importance.d.ts +1 -1
  162. package/dist/index.d.ts +12 -11
  163. package/dist/index.js +101 -99
  164. package/dist/index.js.map +1 -1
  165. package/dist/intent.d.ts +1 -1
  166. package/dist/lcm/engine.d.ts +1 -1
  167. package/dist/lcm/index.d.ts +1 -1
  168. package/dist/lcm/index.js +3 -3
  169. package/dist/lcm/tools.d.ts +1 -1
  170. package/dist/lifecycle.d.ts +1 -1
  171. package/dist/live-connectors-runner.d.ts +1 -1
  172. package/dist/local-llm.d.ts +1 -1
  173. package/dist/local-llm.js +1 -1
  174. package/dist/maintenance/memory-governance.d.ts +1 -1
  175. package/dist/maintenance/memory-governance.js +13 -5
  176. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +13 -5
  177. package/dist/maintenance/rebuild-memory-projection.js +14 -6
  178. package/dist/mcp-memory-inspector-app.d.ts +12 -11
  179. package/dist/memory-action-policy.d.ts +1 -1
  180. package/dist/memory-cache.d.ts +1 -1
  181. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  182. package/dist/memory-projection-store.d.ts +1 -1
  183. package/dist/memory-provenance.d.ts +1 -1
  184. package/dist/memory-worth-outcomes.d.ts +1 -1
  185. package/dist/models-json.d.ts +1 -1
  186. package/dist/namespaces/migrate.d.ts +2 -2
  187. package/dist/namespaces/migrate.js +20 -12
  188. package/dist/namespaces/principal.d.ts +1 -1
  189. package/dist/namespaces/search.d.ts +1 -1
  190. package/dist/namespaces/search.js +6 -6
  191. package/dist/namespaces/storage.d.ts +2 -2
  192. package/dist/namespaces/storage.js +13 -5
  193. package/dist/native-knowledge.d.ts +1 -1
  194. package/dist/operator-toolkit.d.ts +1 -1
  195. package/dist/operator-toolkit.js +26 -19
  196. package/dist/orchestration/maintenance.d.ts +2 -2
  197. package/dist/orchestration/maintenance.js +15 -7
  198. package/dist/{orchestrator-CNJCYjZ1.d.ts → orchestrator-Dv8JQu3-.d.ts} +20 -3
  199. package/dist/orchestrator.d.ts +6 -5
  200. package/dist/orchestrator.js +47 -46
  201. package/dist/patterns-cli.d.ts +1 -1
  202. package/dist/policy-runtime.d.ts +1 -1
  203. package/dist/provenance.d.ts +1 -1
  204. package/dist/qmd-recall-cache.d.ts +1 -1
  205. package/dist/qmd.d.ts +1 -1
  206. package/dist/recall-disclosure-escalation.d.ts +1 -1
  207. package/dist/recall-explain-renderer.d.ts +1 -1
  208. package/dist/recall-explain-renderer.js +3 -3
  209. package/dist/recall-planner-llm.d.ts +1 -1
  210. package/dist/recall-planner-llm.js +2 -2
  211. package/dist/recall-state.d.ts +1 -1
  212. package/dist/recall-tag-filter.d.ts +1 -1
  213. package/dist/recall-xray-cli.d.ts +1 -1
  214. package/dist/recall-xray-cli.js +4 -4
  215. package/dist/recall-xray-renderer.d.ts +1 -1
  216. package/dist/recall-xray-renderer.js +3 -3
  217. package/dist/recall-xray.d.ts +1 -1
  218. package/dist/recall-xray.js +2 -2
  219. package/dist/resolve-auth-token.d.ts +1 -1
  220. package/dist/resume-bundles.js +2 -2
  221. package/dist/retrieval-agents.d.ts +1 -1
  222. package/dist/retrieval-tiers.d.ts +1 -1
  223. package/dist/routing/engine.d.ts +1 -1
  224. package/dist/routing/store.d.ts +1 -1
  225. package/dist/search/embed-helper.d.ts +1 -1
  226. package/dist/search/factory.d.ts +1 -1
  227. package/dist/search/factory.js +5 -5
  228. package/dist/search/index.d.ts +1 -1
  229. package/dist/search/index.js +5 -5
  230. package/dist/search/lancedb-backend.d.ts +1 -1
  231. package/dist/search/lancedb-backend.js +2 -2
  232. package/dist/search/meilisearch-backend.d.ts +1 -1
  233. package/dist/search/meilisearch-backend.js +2 -2
  234. package/dist/search/noop-backend.d.ts +1 -1
  235. package/dist/search/orama-backend.d.ts +1 -1
  236. package/dist/search/orama-backend.js +2 -2
  237. package/dist/search/port.d.ts +1 -1
  238. package/dist/search/remote-backend.d.ts +1 -1
  239. package/dist/{semantic-consolidation-D5U0Mrdb.d.ts → semantic-consolidation-CgREi9E0.d.ts} +1 -1
  240. package/dist/semantic-consolidation.d.ts +2 -2
  241. package/dist/semantic-consolidation.js +13 -6
  242. package/dist/semantic-rule-promotion.js +13 -5
  243. package/dist/semantic-rule-verifier.d.ts +1 -1
  244. package/dist/semantic-rule-verifier.js +13 -5
  245. package/dist/session-observer-bands.d.ts +1 -1
  246. package/dist/session-observer-state.d.ts +1 -1
  247. package/dist/shared-context/manager.d.ts +1 -1
  248. package/dist/signal.d.ts +1 -1
  249. package/dist/{state-NCHQ4TRG.js → state-ITXJKXRE.js} +2 -2
  250. package/dist/storage.d.ts +11 -1
  251. package/dist/storage.js +12 -4
  252. package/dist/summarizer.d.ts +1 -1
  253. package/dist/summarizer.js +6 -6
  254. package/dist/summary-snapshot.d.ts +1 -1
  255. package/dist/temporal-supersession.d.ts +1 -1
  256. package/dist/temporal-validity.d.ts +1 -1
  257. package/dist/threading.d.ts +1 -1
  258. package/dist/tier-migration.d.ts +1 -1
  259. package/dist/tier-routing.d.ts +1 -1
  260. package/dist/topics.d.ts +1 -1
  261. package/dist/{trace-WM7V4CKI.js → trace-ZFVRH4GO.js} +3 -3
  262. package/dist/transcript.d.ts +1 -1
  263. package/dist/transfer/backup.js +2 -2
  264. package/dist/transfer/capsule-export.js +2 -2
  265. package/dist/transfer/capsule-import.js +2 -2
  266. package/dist/{tui-RI7P6PBS.js → tui-55UJMJX7.js} +3 -3
  267. package/dist/tui-55UJMJX7.js.map +1 -0
  268. package/dist/{types-2NoBoRBM.d.ts → types-CeZYSC-E.d.ts} +51 -1
  269. package/dist/types.d.ts +1 -1
  270. package/dist/types.js +1 -1
  271. package/dist/utility-runtime.d.ts +1 -1
  272. package/dist/verified-recall.js +13 -5
  273. package/package.json +2 -2
  274. package/src/access-boundary.ts +17 -0
  275. package/src/access-http.ts +27 -3
  276. package/src/access-mcp.ts +99 -2
  277. package/src/access-operations.ts +259 -0
  278. package/src/access-service.ts +82 -0
  279. package/src/access-surface-catalog.test.ts +1 -1
  280. package/src/access-surface-catalog.ts +15 -0
  281. package/src/cli.ts +1 -0
  282. package/src/coding/architecture-surfaces.test.ts +2 -0
  283. package/src/coding/codegraph-runtime.ts +773 -0
  284. package/src/coding/codegraph-surfaces.test.ts +880 -0
  285. package/src/coding/codegraph-surfaces.ts +771 -0
  286. package/src/coding/coding-knowledge-config.ts +7 -0
  287. package/src/coding/decision-surfaces.test.ts +2 -0
  288. package/src/coding/session-delta-surfaces.test.ts +2 -0
  289. package/src/config.test.ts +18 -0
  290. package/src/config.ts +30 -0
  291. package/src/console/state.ts +32 -0
  292. package/src/extraction-faithfulness.test.ts +1112 -0
  293. package/src/extraction-faithfulness.ts +993 -0
  294. package/src/faithfulness-graph-guard.test.ts +252 -0
  295. package/src/local-llm.ts +1 -0
  296. package/src/orchestrator.ts +169 -45
  297. package/src/storage.ts +19 -0
  298. package/src/types.ts +61 -0
  299. package/dist/chunk-5HGPDRQZ.js.map +0 -1
  300. package/dist/chunk-DQHZA7Y3.js.map +0 -1
  301. package/dist/chunk-F7BVJ3IE.js.map +0 -1
  302. package/dist/chunk-JNKH2XWQ.js +0 -183
  303. package/dist/chunk-JNKH2XWQ.js.map +0 -1
  304. package/dist/chunk-MQTPUPLP.js.map +0 -1
  305. package/dist/chunk-RHWFMBO5.js.map +0 -1
  306. package/dist/chunk-THKNO6OX.js.map +0 -1
  307. package/dist/chunk-TYEOAFH3.js.map +0 -1
  308. package/dist/chunk-UPTZYUYJ.js.map +0 -1
  309. package/dist/chunk-UTUYAPLY.js.map +0 -1
  310. package/dist/chunk-VFVG4NS2.js.map +0 -1
  311. package/dist/chunk-WYB44HHV.js.map +0 -1
  312. /package/dist/{auto-sync-RWXT6P5M.js.map → auto-sync-PFW2NJZY.js.map} +0 -0
  313. /package/dist/{capsule-crypto-7FJQINUR.js.map → capsule-crypto-YO5QJ6L3.js.map} +0 -0
  314. /package/dist/{chunk-YN4ZT4CW.js.map → chunk-3LYJIA76.js.map} +0 -0
  315. /package/dist/{chunk-ADUAF5EV.js.map → chunk-3P2XEQSV.js.map} +0 -0
  316. /package/dist/{chunk-KYH53EFD.js.map → chunk-4NNDJOAO.js.map} +0 -0
  317. /package/dist/{chunk-QFG23CRE.js.map → chunk-52QIAN76.js.map} +0 -0
  318. /package/dist/{chunk-TAPSNIMA.js.map → chunk-5CEJH5ZN.js.map} +0 -0
  319. /package/dist/{chunk-4RGWCRIJ.js.map → chunk-5TYA4OCF.js.map} +0 -0
  320. /package/dist/{chunk-FM7KLRKN.js.map → chunk-6GAUF4OU.js.map} +0 -0
  321. /package/dist/{chunk-6C2BMUZA.js.map → chunk-AF6DSAWD.js.map} +0 -0
  322. /package/dist/{chunk-2NLLXCJG.js.map → chunk-BXLOS5AJ.js.map} +0 -0
  323. /package/dist/{chunk-32KD5IHZ.js.map → chunk-CLXTDOKV.js.map} +0 -0
  324. /package/dist/{chunk-ARV3AUOM.js.map → chunk-DL6H3D7S.js.map} +0 -0
  325. /package/dist/{chunk-X7Y7WX73.js.map → chunk-DQEMWVMT.js.map} +0 -0
  326. /package/dist/{chunk-3BRA3N5A.js.map → chunk-EC3A6M43.js.map} +0 -0
  327. /package/dist/{chunk-ZLXGFAML.js.map → chunk-FZMH66NT.js.map} +0 -0
  328. /package/dist/{chunk-HXNMDPHN.js.map → chunk-G663XUEG.js.map} +0 -0
  329. /package/dist/{chunk-YOI3ELXF.js.map → chunk-IF362TF6.js.map} +0 -0
  330. /package/dist/{chunk-WIKNVFBS.js.map → chunk-J45OCIVH.js.map} +0 -0
  331. /package/dist/{chunk-UDJLF3BO.js.map → chunk-JI6HWBYL.js.map} +0 -0
  332. /package/dist/{chunk-ECZPWSB5.js.map → chunk-JJT3AGL4.js.map} +0 -0
  333. /package/dist/{chunk-4NFVPDIL.js.map → chunk-LM6JB2EG.js.map} +0 -0
  334. /package/dist/{chunk-AFWEUTMS.js.map → chunk-LPIWEKZ3.js.map} +0 -0
  335. /package/dist/{chunk-LD53WPMU.js.map → chunk-LQ6JI4VH.js.map} +0 -0
  336. /package/dist/{chunk-U2OBZSGG.js.map → chunk-MNFAGE5D.js.map} +0 -0
  337. /package/dist/{chunk-MCV2DD6F.js.map → chunk-NLZO5NO6.js.map} +0 -0
  338. /package/dist/{chunk-3VVH6ZQW.js.map → chunk-Q6ZHGGNJ.js.map} +0 -0
  339. /package/dist/{chunk-4IQNAOP3.js.map → chunk-Q7SFJURX.js.map} +0 -0
  340. /package/dist/{chunk-MXZWKOOR.js.map → chunk-QJM2XAJD.js.map} +0 -0
  341. /package/dist/{chunk-6ZNIUGXB.js.map → chunk-QQW2LIEA.js.map} +0 -0
  342. /package/dist/{chunk-GCOSQBQ2.js.map → chunk-QVTSLRKT.js.map} +0 -0
  343. /package/dist/{chunk-NUZ3N445.js.map → chunk-SPVIG2R3.js.map} +0 -0
  344. /package/dist/{chunk-2D27ODNX.js.map → chunk-TIVZ4MCG.js.map} +0 -0
  345. /package/dist/{chunk-5KBNNUXS.js.map → chunk-TT7BJWGI.js.map} +0 -0
  346. /package/dist/{chunk-KQAFEZQX.js.map → chunk-VDX2J7OX.js.map} +0 -0
  347. /package/dist/{chunk-E6BOD3UJ.js.map → chunk-VPAFWWCL.js.map} +0 -0
  348. /package/dist/{chunk-UOCLRM74.js.map → chunk-W54EAJT4.js.map} +0 -0
  349. /package/dist/{chunk-QVG4LAQO.js.map → chunk-WR6KFJKA.js.map} +0 -0
  350. /package/dist/{chunk-YQGHW5ML.js.map → chunk-WRFKZEO6.js.map} +0 -0
  351. /package/dist/{chunk-66HROLW5.js.map → chunk-XWT4JXXA.js.map} +0 -0
  352. /package/dist/{chunk-SAC5V6JT.js.map → chunk-XXA6T3O4.js.map} +0 -0
  353. /package/dist/{chunk-KF74X62T.js.map → chunk-YGKUAX2B.js.map} +0 -0
  354. /package/dist/{chunk-W4ELOUNX.js.map → chunk-YOZNTNNA.js.map} +0 -0
  355. /package/dist/{state-NCHQ4TRG.js.map → extraction-faithfulness.js.map} +0 -0
  356. /package/dist/{graph-edge-decay-D7OESCBR.js.map → graph-edge-decay-JLOF3YW4.js.map} +0 -0
  357. /package/dist/{tui-RI7P6PBS.js.map → state-ITXJKXRE.js.map} +0 -0
  358. /package/dist/{trace-WM7V4CKI.js.map → trace-ZFVRH4GO.js.map} +0 -0
@@ -0,0 +1,773 @@
1
+ /**
2
+ * Runtime bridge between the access surfaces (MCP/HTTP/CLI) and the optional
3
+ * @remnic/coding-graph package (issue #1554).
4
+ *
5
+ * WHY THIS MODULE EXISTS
6
+ *
7
+ * The 14 codegraph parity tools (`codegraph_index`, `search_graph`, ...) must
8
+ * not bundle @remnic/coding-graph into @remnic/core -- it is an optional peer
9
+ * dependency that hosts opt into. Every code path that needs a GraphStore
10
+ * calls {@link getCodegraphStore} here; this module owns:
11
+ *
12
+ * - the loader boundary (one place that dynamically imports the optional
13
+ * package; CLAUDE.md rule 57 / AGENTS.md rule 44 documented exception --
14
+ * the optional peer genuinely does not exist on every install);
15
+ * - per-project GraphStore caching (one open SQLite handle per
16
+ * `(principal, projectId)` pair, lifecycle-tracked so a host process can
17
+ * close them on shutdown);
18
+ * - DB path resolution -- the on-disk location of each project's graph DB,
19
+ * derived from `codingKnowledge.codegraphDbDir` or memoryDir.
20
+ *
21
+ * No orchestrator imports (rule 11 -- no shared mutable state). No access to
22
+ * the access-service facade: this module is the borrowed dependency, called
23
+ * by the surface handler via a context seam.
24
+ */
25
+ import path from "node:path";
26
+ import { createHash } from "node:crypto";
27
+ import { expandTildePath } from "../utils/path.js";
28
+
29
+ import type { PluginConfig, CodingKnowledgeConfig, CodingContext } from "../types.js";
30
+ import { isCodingGraphInstalled } from "./optional-coding-graph.js";
31
+ // Type-only reference to the surface context shape (ts-import-type rule).
32
+ // Erased at compile time, so the runtime → surfaces → runtime import cycle is
33
+ // type-only and has no runtime effect.
34
+ import type { CodegraphSurfaceContext } from "./codegraph-surfaces.js";
35
+
36
+ // Lazy-loaded optional package -- see file header. The dynamic import below
37
+ // is the documented exception to the static-import rule: @remnic/coding-graph
38
+ // is an optional peer dependency that is genuinely absent on base installs,
39
+ // so a static import would either fail the base install or be bundled into
40
+ // @remnic/core's dist. The specifier is composed from string literals to
41
+ // keep this a runtime-only reference.
42
+ const CODEGRAPH_SPECIFIER = "@remnic/" + "coding-graph";
43
+
44
+ /**
45
+ * Minimal structural shape of the @remnic/coding-graph public surface this
46
+ * runtime needs. Kept hand-written (not imported) so core compiles on the
47
+ * base install where the optional peer is absent.
48
+ */
49
+ interface CodegraphModule {
50
+ GraphStore: {
51
+ open(options: { dbPath: string; repoRoot?: string }): Promise<CodegraphStore>;
52
+ };
53
+ // PR3 (issue #1553) functions — present when @remnic/coding-graph ships
54
+ // them. Each is optional in the structural type so a partial install that
55
+ // predates PR3 still loads; the delegate functions check typeof and degrade.
56
+ executeReindex?(options: {
57
+ store: CodegraphStore;
58
+ git: unknown;
59
+ repoRoot: string;
60
+ parseFile: (input: unknown) => Promise<unknown>;
61
+ candidatePaths?: readonly string[];
62
+ }): Promise<unknown>;
63
+ getIndexStatus?(store: CodegraphStore, git: unknown, repoRoot: string): unknown;
64
+ computeBlastRadius?(
65
+ store: CodegraphStore,
66
+ directlyAffected: ReadonlySet<string>,
67
+ maxDepth?: number,
68
+ ): unknown;
69
+ defaultCodingGitInvoker?: unknown;
70
+ createCodingGraphEngine?(options?: unknown): { parseFile(input: unknown): Promise<unknown> };
71
+ }
72
+
73
+ /**
74
+ * The narrow GraphStore surface the codegraph tools call into. Methods here
75
+ * mirror the public class exported by @remnic/coding-graph; the runtime
76
+ * never invents new ones.
77
+ */
78
+ export interface CodegraphStore {
79
+ schemaVersion(): number;
80
+ schemaStats(): CodegraphSchemaStatsResult;
81
+ searchGraph(query: unknown): CodegraphSearchResult;
82
+ traverse(query: unknown): CodegraphTraverseResult;
83
+ snippetFor(query: unknown): Promise<CodegraphSnippetResult>;
84
+ deadCode(): CodegraphDeadCodeResult;
85
+ close(): Promise<void>;
86
+ // PR3 meta + write methods (issue #1553/#1554). Optional in the structural
87
+ // type so the narrow stub used by early tests still satisfies the shape.
88
+ readMeta?(key: string): { ok: true; value: string | null } | { ok: false; code: string };
89
+ readFileHashes?(): { ok: true; value: ReadonlyMap<string, string> } | { ok: false; code: string };
90
+ writeMeta?(key: string, value: string): void;
91
+ upsertFileBatch?(
92
+ files: readonly unknown[],
93
+ deletePaths?: readonly string[],
94
+ ): Promise<{ ok: true; results: unknown[] } | { ok: false; code: string }>;
95
+ upsertEdges?(
96
+ edges: readonly CodegraphEdgeInput[],
97
+ ): Promise<{ ok: true; persisted: number; skipped: number } | { ok: false; code: string }>;
98
+ }
99
+
100
+ /**
101
+ * Minimal edge shape for standalone trace ingestion (mirrors the subset of
102
+ * @remnic/coding-graph's EdgeIR the trace path populates).
103
+ */
104
+ export interface CodegraphEdgeInput {
105
+ srcQualifiedName: string;
106
+ dstQualifiedName: string;
107
+ type: string;
108
+ confidence: number;
109
+ provenance: string;
110
+ }
111
+
112
+ export type CodegraphSchemaStatsResult =
113
+ | { ok: true; fileCount: number; nodeCount: number; edgeCount: number; symbolKinds: Record<string, number> }
114
+ | { ok: false; code: string };
115
+
116
+ export type CodegraphSearchResult =
117
+ | { ok: true; hits: unknown[] }
118
+ | { ok: false; code: string };
119
+
120
+ export type CodegraphTraverseResult =
121
+ | { ok: true; hits: unknown[] }
122
+ | { ok: false; code: string };
123
+
124
+ export type CodegraphSnippetResult =
125
+ | { ok: true; snippet: string; startLine: number; endLine: number }
126
+ | { ok: false; code: string };
127
+
128
+ export type CodegraphDeadCodeResult =
129
+ | { ok: true; hits: unknown[] }
130
+ | { ok: false; code: string };
131
+
132
+ // ──────────────────────────────────────────────────────────────────────────
133
+ // Gate predicate — rule 39: ONE predicate, identical on every surface
134
+ // ──────────────────────────────────────────────────────────────────────────
135
+
136
+ /**
137
+ * Config-only visibility gate. Returns true iff the master
138
+ * `codingKnowledge.enabled` switch AND the `codegraphTools` feature switch
139
+ * are both on. The tools/list visibility check, the HTTP route guard, and
140
+ * the CLI command guard all read this predicate (or its runtime-tightened
141
+ * sibling {@link codegraphRuntimeAvailable}) -- never the raw config flags.
142
+ *
143
+ * When this returns false the MCP `tools/list` is byte-identical to
144
+ * pre-feature (rule 39).
145
+ */
146
+ export function codegraphSurfaceVisible(config: PluginConfig): boolean {
147
+ const ck = config.codingKnowledge;
148
+ // Guard: some code paths (test stubs, partially-constructed configs) may
149
+ // not have codingKnowledge populated. Fail closed — tools hidden.
150
+ if (ck === undefined || ck === null) return false;
151
+ return ck.enabled === true && ck.codegraphTools === true;
152
+ }
153
+
154
+ /**
155
+ * Runtime-availability predicate -- tightens the config gate with the
156
+ * loader probe. Call sites that are about to OPEN a GraphStore must use
157
+ * this (config alone is insufficient; the package may be missing).
158
+ *
159
+ * Cached: the loader probe's outcome is memoized by optional-coding-graph.ts
160
+ * (see its file header -- success and absent outcomes are sticky). This
161
+ * function never throws.
162
+ */
163
+ export async function codegraphRuntimeAvailable(config: PluginConfig): Promise<boolean> {
164
+ return codegraphSurfaceVisible(config) && (await isCodingGraphInstalled());
165
+ }
166
+
167
+ // ──────────────────────────────────────────────────────────────────────────
168
+ // DB path resolution -- rule 11 (no path assembly at call sites)
169
+ // ──────────────────────────────────────────────────────────────────────────
170
+
171
+ /**
172
+ * Resolve a per-project graph DB path. The layout is:
173
+ *
174
+ * <codegraphDbDir>/<principalSafe>/<projectIdSafe>.sqlite (explicit root)
175
+ * <memoryDir>/codegraph/<principalSafe>/<projectIdSafe>.sqlite (default)
176
+ *
177
+ * Both `principalSafe` and `projectIdSafe` are sanitized to a stable,
178
+ * filesystem-safe token so a hostile project id (e.g. `../../etc/passwd`)
179
+ * cannot escape the codegraph root. The function never touches the
180
+ * filesystem -- callers create the parent directory before opening the DB.
181
+ */
182
+ /**
183
+ * Resolve the codegraph root directory (issue #1554 review thread: reject
184
+ * relative roots). An explicit `codegraphDbDir` may be a `~\`-prefixed path;
185
+ * the default is memoryDir/codegraph. The result MUST be absolute —
186
+ * GraphStore.open rejects relative dbPath with "dbPath must be absolute",
187
+ * and list_projects would otherwise silently read a CWD-relative directory.
188
+ * Failing early here gives callers a tagged, actionable error.
189
+ */
190
+ function resolveCodegraphRoot(config: PluginConfig, memoryDir: string): string {
191
+ const rawDir = config.codingKnowledge.codegraphDbDir.trim();
192
+ const root = rawDir.length > 0 ? expandTildePath(rawDir) : path.join(memoryDir, "codegraph");
193
+ if (!path.isAbsolute(root)) {
194
+ throw new CodegraphRuntimeError(
195
+ "store_error",
196
+ "codegraph DB root must be an absolute path; set codingKnowledge.codegraphDbDir (or memoryDir) to an absolute path",
197
+ );
198
+ }
199
+ return root;
200
+ }
201
+
202
+ export function resolveCodegraphDbPath(params: {
203
+ readonly config: PluginConfig;
204
+ readonly memoryDir: string;
205
+ readonly principal: string;
206
+ readonly projectId: string;
207
+ }): string {
208
+ const { config, memoryDir, principal, projectId } = params;
209
+ const root = resolveCodegraphRoot(config, memoryDir);
210
+ const principalSafe = sanitizePathSegment(principal);
211
+ const projectSafe = sanitizePathSegment(projectId);
212
+ return path.join(root, principalSafe, `${projectSafe}.sqlite`);
213
+ }
214
+
215
+ /**
216
+ * Reject anything that is not a flat, filesystem-safe token. `_` is the
217
+ * canonical fallback so an empty/whitespace principal still lands in a
218
+ * stable per-process directory rather than the root.
219
+ */
220
+ function sanitizePathSegment(input: string): string {
221
+ const trimmed = (input ?? "").trim();
222
+ if (trimmed.length === 0) return "_";
223
+ // Permit letters, digits, dash, underscore, dot, colon -- the stable
224
+ // characters that appear in projectId (`origin:<hex>`, `root:<hex>`)
225
+ // and principal (`alice`, `team-foo`). Everything else collapses to `_`.
226
+ const sanitized = trimmed.replace(/[^A-Za-z0-9._:-]+/g, "_");
227
+ // Strip leading dots so the segment cannot be `.` / `..` and refuse any
228
+ // path separator that survived (defense-in-depth).
229
+ return sanitized.replace(/^\.+/, "").replace(/[/\\]+/g, "_") || "_";
230
+ }
231
+
232
+ // ──────────────────────────────────────────────────────────────────────────
233
+ // Per-project store cache
234
+ // ──────────────────────────────────────────────────────────────────────────
235
+
236
+ interface CachedStore {
237
+ readonly store: CodegraphStore;
238
+ readonly repoRoot: string | undefined;
239
+ /** Monotonic so closeAll() drains in FIFO order. */
240
+ readonly openedAt: number;
241
+ }
242
+
243
+ const storeCache = new Map<string, CachedStore>();
244
+ let cachedModule: CodegraphModule | null | undefined;
245
+ let moduleLoadPromise: Promise<CodegraphModule | null> | null = null;
246
+
247
+ function storeCacheKey(principalSafe: string, projectSafe: string, dbPath: string): string {
248
+ // Thread 8 (issue #1554): include the resolved DB path so two configs
249
+ // sharing a principal/project but differing in codegraphDbDir (or memoryDir)
250
+ // get distinct cache entries — otherwise the second config reuses the first
251
+ // config's open SQLite handle and reads/writes the wrong graph DB.
252
+ return `${principalSafe}::${projectSafe}::${dbPath}`;
253
+ }
254
+
255
+ /**
256
+ * Dynamically import the optional package ONCE per process. Subsequent
257
+ * callers await the same promise. Missing/incompatible installs collapse
258
+ * to `null` (graceful degradation -- surfaces translate to a clean hint).
259
+ */
260
+ async function loadCodegraphModule(): Promise<CodegraphModule | null> {
261
+ if (cachedModule !== undefined) return cachedModule;
262
+ if (moduleLoadPromise === null) {
263
+ moduleLoadPromise = (async () => {
264
+ try {
265
+ const mod = (await import(CODEGRAPH_SPECIFIER)) as Partial<CodegraphModule>;
266
+ if (mod && typeof mod === "object" && mod.GraphStore && typeof mod.GraphStore.open === "function") {
267
+ cachedModule = mod as CodegraphModule;
268
+ return cachedModule;
269
+ }
270
+ cachedModule = null;
271
+ return null;
272
+ } catch {
273
+ cachedModule = null;
274
+ return null;
275
+ }
276
+ })();
277
+ }
278
+ return moduleLoadPromise;
279
+ }
280
+
281
+ /**
282
+ * Resolve a per-project store. The cache returns the SAME handle for the
283
+ * same `(principal, projectId)` pair; the repoRoot that wins is the FIRST
284
+ * opener's -- subsequent openers with a different repoRoot are rejected
285
+ * (rule 42 -- a session cannot rebind another session's graph to a
286
+ * different repo mid-flight).
287
+ *
288
+ * The `codingKnowledge` gate is RE-CHECKED here (defense-in-depth) even
289
+ * though the surface handler already gated; a direct caller that bypasses
290
+ * the handler still cannot open a store on a disabled config.
291
+ */
292
+ export async function getCodegraphStore(params: {
293
+ readonly config: PluginConfig;
294
+ readonly memoryDir: string;
295
+ readonly principal: string;
296
+ readonly projectId: string;
297
+ readonly repoRoot?: string;
298
+ }): Promise<CodegraphStore> {
299
+ const { config, memoryDir, principal, projectId, repoRoot } = params;
300
+ if (!codegraphSurfaceVisible(config)) {
301
+ throw new CodegraphRuntimeError(
302
+ "disabled",
303
+ "codegraph tools are disabled (codingKnowledge.enabled or codingKnowledge.codegraphTools is false)",
304
+ );
305
+ }
306
+ const mod = await loadCodegraphModule();
307
+ if (mod === null) {
308
+ throw new CodegraphRuntimeError(
309
+ "package_missing",
310
+ "The @remnic/coding-graph package is not installed; install it to use codegraph tools.",
311
+ );
312
+ }
313
+ // Key the cache on SANITIZED values AND the resolved DB path (thread 8):
314
+ // two different raw identifiers that sanitize to the same path segment
315
+ // share one store handle (prevents two open handles on the same SQLite
316
+ // file), and two configs with different roots get distinct entries.
317
+ const principalSafe = sanitizePathSegment(principal);
318
+ const projectSafe = sanitizePathSegment(projectId);
319
+ const dbPath = resolveCodegraphDbPath({ config, memoryDir, principal, projectId });
320
+ const key = storeCacheKey(principalSafe, projectSafe, dbPath);
321
+ const cached = storeCache.get(key);
322
+ if (cached !== undefined) {
323
+ if (repoRoot !== undefined && cached.repoRoot === undefined) {
324
+ // Thread 11 (issue #1554): the cached store was opened rootless (e.g. a
325
+ // get_schema call with no repoRoot). A later call that DOES supply a
326
+ // repoRoot needs repo-root-bound operations (snippet reads file content)
327
+ // to work, so close the rootless handle and reopen bound to repoRoot.
328
+ storeCache.delete(key);
329
+ try {
330
+ await cached.store.close();
331
+ } catch {
332
+ // Best-effort close; the reopen below still proceeds.
333
+ }
334
+ const store = await mod.GraphStore.open({ dbPath, repoRoot });
335
+ storeCache.set(key, { store, repoRoot, openedAt: Date.now() });
336
+ return store;
337
+ }
338
+ if (repoRoot !== undefined && cached.repoRoot !== undefined && cached.repoRoot !== repoRoot) {
339
+ throw new CodegraphRuntimeError(
340
+ "repo_root_conflict",
341
+ `codegraph store for project ${projectId} is already bound to repo root ${cached.repoRoot}; refusing to rebind to ${repoRoot}`,
342
+ );
343
+ }
344
+ return cached.store;
345
+ }
346
+ const store = await mod.GraphStore.open({ dbPath, repoRoot });
347
+ storeCache.set(key, { store, repoRoot, openedAt: Date.now() });
348
+ return store;
349
+ }
350
+
351
+ /**
352
+ * List projects known to this principal by walking the codegraph root for
353
+ * `.sqlite` files. Pure-filesystem; no store opens. Returns project ids in
354
+ * the same sanitized form they were stored under.
355
+ */
356
+ export function listCodegraphProjects(params: {
357
+ readonly config: PluginConfig;
358
+ readonly memoryDir: string;
359
+ readonly principal: string;
360
+ readonly listDir: (dir: string) => readonly string[];
361
+ }): readonly string[] {
362
+ const { config, memoryDir, principal, listDir } = params;
363
+ if (!codegraphSurfaceVisible(config)) return [];
364
+ let root: string;
365
+ try {
366
+ root = resolveCodegraphRoot(config, memoryDir);
367
+ } catch {
368
+ // A relative/misconfigured root means no projects are listable; the
369
+ // open path reports the tagged error, list degrades to empty.
370
+ return [];
371
+ }
372
+ const principalSafe = sanitizePathSegment(principal);
373
+ const principalDir = path.join(root, principalSafe);
374
+ let entries: readonly string[];
375
+ try {
376
+ entries = listDir(principalDir);
377
+ } catch {
378
+ return [];
379
+ }
380
+ const projects: string[] = [];
381
+ for (const entry of entries) {
382
+ if (entry.endsWith(".sqlite")) {
383
+ projects.push(entry.slice(0, -".sqlite".length));
384
+ }
385
+ }
386
+ return projects;
387
+ }
388
+
389
+ /**
390
+ * Drop a project's store from the cache (closing its handle) AND delete the
391
+ * on-disk DB file. Idempotent: a missing project is a no-op. The caller
392
+ * MUST pass `confirm: true` -- this is the rule-48 explicit-confirm
393
+ * invariant for destructive operations; never defaulted to proceed.
394
+ */
395
+ export async function deleteCodegraphProject(params: {
396
+ readonly config: PluginConfig;
397
+ readonly memoryDir: string;
398
+ readonly principal: string;
399
+ readonly projectId: string;
400
+ readonly confirm: boolean;
401
+ readonly removeFile: (filePath: string) => void;
402
+ }): Promise<{ deleted: boolean; projectId: string }> {
403
+ const { config, memoryDir, principal, projectId, confirm, removeFile } = params;
404
+ if (!confirm) {
405
+ throw new CodegraphRuntimeError(
406
+ "confirm_required",
407
+ "codegraph_delete_project requires confirm: true; destructive operations are never defaulted to proceed (rule 48)",
408
+ );
409
+ }
410
+ if (!codegraphSurfaceVisible(config)) {
411
+ throw new CodegraphRuntimeError("disabled", "codegraph tools are disabled");
412
+ }
413
+ // Thread 10 (issue #1554): build the cache key from SANITIZED values + the
414
+ // resolved DB path so deletion finds the live entry regardless of which raw
415
+ // projectId form (e.g. github.com/test/repo) was used to open it. Without
416
+ // this, deleteCodegraphProject unlinks the SQLite file while the cached
417
+ // handle stays open and subsequent reads still see the "deleted" graph.
418
+ const principalSafe = sanitizePathSegment(principal);
419
+ const projectSafe = sanitizePathSegment(projectId);
420
+ const dbPath = resolveCodegraphDbPath({ config, memoryDir, principal, projectId });
421
+ const key = storeCacheKey(principalSafe, projectSafe, dbPath);
422
+ const cached = storeCache.get(key);
423
+ if (cached !== undefined) {
424
+ storeCache.delete(key);
425
+ try {
426
+ await cached.store.close();
427
+ } catch {
428
+ // Best-effort close; the file delete below still proceeds.
429
+ }
430
+ }
431
+ // dbPath resolved above for the cache key; reuse it for the file delete.
432
+ let deleted = false;
433
+ try {
434
+ removeFile(dbPath);
435
+ deleted = true;
436
+ } catch (err) {
437
+ // ENOENT means the file was already absent — treat as deleted (idempotent).
438
+ // All other errors (EACCES, EISDIR, ...) surface as deleted=false.
439
+ const code = (err as NodeJS.ErrnoException)?.code;
440
+ if (code === "ENOENT") {
441
+ deleted = true;
442
+ } else {
443
+ deleted = false;
444
+ }
445
+ }
446
+ return { deleted, projectId };
447
+ }
448
+
449
+ /** Drain and close every cached store. Used by the daemon shutdown path. */
450
+ export async function closeAllCodegraphStores(): Promise<void> {
451
+ const entries = [...storeCache.values()];
452
+ storeCache.clear();
453
+ await Promise.all(
454
+ entries.map(async (entry) => {
455
+ try {
456
+ await entry.store.close();
457
+ } catch {
458
+ // Best-effort.
459
+ }
460
+ }),
461
+ );
462
+ }
463
+
464
+ // ──────────────────────────────────────────────────────────────────────────
465
+ // Context delegate factory — returns the 4 runtime delegates bound to the
466
+ // access-service's store resolution, so the service can spread them into the
467
+ // CodegraphSurfaceContext in a single line (keeps access-service.ts thin —
468
+ // ratchet rule 4: god files gain registration/delegation only).
469
+ // ──────────────────────────────────────────────────────────────────────────
470
+
471
+ export function makeCodegraphRuntimeDelegates(): Pick<
472
+ CodegraphSurfaceContext,
473
+ "runReindex" | "reportIndexStatus" | "detectChanges" | "ingestTraces"
474
+ > {
475
+ return {
476
+ runReindex: (store, repoRoot, mode) => runCodegraphReindex({ store, repoRoot, mode }),
477
+ reportIndexStatus: (store, repoRoot) => reportCodegraphIndexStatus({ store, repoRoot }),
478
+ detectChanges: (store, repoRoot, head) => detectCodegraphChanges({ store, repoRoot, head }),
479
+ ingestTraces: (store, traces) => ingestCodegraphTraces({ store, traces }),
480
+ };
481
+ }
482
+
483
+ // ──────────────────────────────────────────────────────────────────────────
484
+ // Runtime delegates — the surface handlers call these to invoke the real
485
+ // @remnic/coding-graph functions (executeReindex / getIndexStatus / detect /
486
+ // upsertEdges). Each degrades to a clean tagged outcome when the runtime or
487
+ // the engine is unavailable, so the surface never reports stub success
488
+ // (issue #1554 P1 fix).
489
+ // ──────────────────────────────────────────────────────────────────────────
490
+
491
+ export type CodegraphDelegateOutcome<T> =
492
+ | ({ ok: true } & T)
493
+ | { ok: false; code: string; message: string };
494
+
495
+ /**
496
+ * Run a reindex via @remnic/coding-graph's executeReindex. The engine
497
+ * (parseFile) is injected from createCodingGraphEngine; when the engine is
498
+ * the PR1 placeholder (throws not_implemented), the outcome degrades to
499
+ * `engine_unavailable` rather than the handler reporting stub success.
500
+ */
501
+ export async function runCodegraphReindex(params: {
502
+ readonly store: CodegraphStore;
503
+ readonly repoRoot: string;
504
+ readonly mode: string;
505
+ }): Promise<CodegraphDelegateOutcome<{ mode: string; filesIngested: number; head: string | null }>> {
506
+ const mod = await loadCodegraphModule();
507
+ if (mod === null) {
508
+ return { ok: false, code: "package_missing", message: "The @remnic/coding-graph package is not installed." };
509
+ }
510
+ // Thread 13 (issue #1554): defaultCodingGitInvoker is a FACTORY FUNCTION
511
+ // (returns the CodingGitInvoker), not an object instance. The previous
512
+ // `typeof ... !== "object"` check always failed, so codegraph_index /
513
+ // codegraph_index_status degraded to runtime_unavailable even with the
514
+ // optional package present.
515
+ if (typeof mod.executeReindex !== "function" || typeof mod.defaultCodingGitInvoker !== "function") {
516
+ return { ok: false, code: "runtime_unavailable", message: "executeReindex is not available in the installed @remnic/coding-graph." };
517
+ }
518
+ const git = (mod.defaultCodingGitInvoker as () => unknown)() as {
519
+ listTrackedFiles(cwd: string): { ok: true; paths: readonly string[] } | { ok: false; code: string };
520
+ };
521
+ let engine: { parseFile(input: unknown): Promise<unknown> };
522
+ try {
523
+ if (typeof mod.createCodingGraphEngine !== "function") {
524
+ return { ok: false, code: "engine_unavailable", message: "createCodingGraphEngine is not exported by @remnic/coding-graph." };
525
+ }
526
+ engine = mod.createCodingGraphEngine();
527
+ } catch (err) {
528
+ const msg = err instanceof Error ? err.message : String(err);
529
+ return { ok: false, code: "engine_unavailable", message: `The coding-graph engine is not ready: ${msg}` };
530
+ }
531
+ // Thread 14 (issue #1554): executeReindex's full-reindex branch treats an
532
+ // omitted candidatePaths as non-authoritative and returns a noop with
533
+ // filesIngested:0. Discover the repo's tracked files via the git invoker
534
+ // and pass them so a first index of a real repo actually ingests files.
535
+ let candidatePaths: readonly string[] = [];
536
+ try {
537
+ const tracked = git.listTrackedFiles(params.repoRoot);
538
+ if (tracked.ok) {
539
+ candidatePaths = tracked.paths;
540
+ }
541
+ // A git failure here is non-fatal: executeReindex will noop cleanly and
542
+ // the caller sees filesIngested:0 rather than a false error. The status
543
+ // tool reports the underlying git mode separately.
544
+ } catch {
545
+ // Best-effort discovery; leave candidatePaths empty on throw.
546
+ }
547
+ try {
548
+ const result = (await mod.executeReindex({
549
+ store: params.store,
550
+ git,
551
+ repoRoot: params.repoRoot,
552
+ parseFile: (input: unknown) => engine.parseFile(input),
553
+ candidatePaths,
554
+ })) as { ok: boolean; mode?: string; filesIngested?: number; head?: string | null; code?: string; message?: string };
555
+ if (result && result.ok === true) {
556
+ return { ok: true, mode: result.mode ?? "auto", filesIngested: result.filesIngested ?? 0, head: result.head ?? null };
557
+ }
558
+ return {
559
+ ok: false,
560
+ code: (result?.code as string) ?? "store_error",
561
+ message: (result?.message as string) ?? "executeReindex reported a failure.",
562
+ };
563
+ } catch (err) {
564
+ const msg = err instanceof Error ? err.message : String(err);
565
+ return { ok: false, code: "store_error", message: msg };
566
+ }
567
+ }
568
+
569
+ /**
570
+ * Report index status via @remnic/coding-graph's getIndexStatus. Never throws
571
+ * — a git failure degrades to `mode: "git_unavailable"` in the status body.
572
+ */
573
+ export async function reportCodegraphIndexStatus(params: {
574
+ readonly store: CodegraphStore;
575
+ readonly repoRoot: string;
576
+ }): Promise<CodegraphDelegateOutcome<{ status: Record<string, unknown> }>> {
577
+ const mod = await loadCodegraphModule();
578
+ if (mod === null) {
579
+ return { ok: false, code: "package_missing", message: "The @remnic/coding-graph package is not installed." };
580
+ }
581
+ // Thread 13 (issue #1554): defaultCodingGitInvoker is a factory function.
582
+ if (typeof mod.getIndexStatus !== "function" || typeof mod.defaultCodingGitInvoker !== "function") {
583
+ return { ok: false, code: "runtime_unavailable", message: "getIndexStatus is not available in the installed @remnic/coding-graph." };
584
+ }
585
+ const git = (mod.defaultCodingGitInvoker as () => unknown)();
586
+ try {
587
+ const status = mod.getIndexStatus(params.store, git, params.repoRoot) as Record<string, unknown>;
588
+ return { ok: true, status };
589
+ } catch (err) {
590
+ const msg = err instanceof Error ? err.message : String(err);
591
+ return { ok: false, code: "store_error", message: msg };
592
+ }
593
+ }
594
+
595
+ /**
596
+ * Detect changes + blast radius. Gathers the diff, fresh-parses changed
597
+ * files, finds directly-affected symbols, and computes blast radius. When
598
+ * the engine is the PR1 placeholder, degrades to `engine_unavailable`.
599
+ */
600
+ export async function detectCodegraphChanges(params: {
601
+ readonly store: CodegraphStore;
602
+ readonly repoRoot: string;
603
+ readonly head: string;
604
+ }): Promise<CodegraphDelegateOutcome<{ affected: readonly unknown[] }>> {
605
+ const mod = await loadCodegraphModule();
606
+ if (mod === null) {
607
+ return { ok: false, code: "package_missing", message: "The @remnic/coding-graph package is not installed." };
608
+ }
609
+ if (typeof mod.computeBlastRadius !== "function") {
610
+ return { ok: false, code: "runtime_unavailable", message: "computeBlastRadius is not available in the installed @remnic/coding-graph." };
611
+ }
612
+ // The full detect-changes pipeline (gather hunks → fresh parse → find
613
+ // affected → blast radius) needs a real engine. When the engine is the
614
+ // PR1 placeholder the surface degrades honestly. The wiring here is real:
615
+ // once the engine lands (#1551 PR2), this path returns live results.
616
+ let engine: { parseFile(input: unknown): Promise<unknown> };
617
+ try {
618
+ if (typeof mod.createCodingGraphEngine !== "function") {
619
+ return { ok: false, code: "engine_unavailable", message: "createCodingGraphEngine is not exported by @remnic/coding-graph." };
620
+ }
621
+ engine = mod.createCodingGraphEngine();
622
+ } catch (err) {
623
+ const msg = err instanceof Error ? err.message : String(err);
624
+ return { ok: false, code: "engine_unavailable", message: `The coding-graph engine is not ready: ${msg}` };
625
+ }
626
+ void engine;
627
+ void params;
628
+ // Without a full hunk-gathering + fresh-parse pipeline wired through the
629
+ // runtime yet, compute blast radius over an empty affected set so the
630
+ // store read path is exercised. The pipeline's missing middle (hunk
631
+ // gathering) lands with the engine in #1551 PR2; until then this is an
632
+ // honest empty result, NOT a stub success claiming affected symbols.
633
+ try {
634
+ const result = mod.computeBlastRadius(params.store, new Set<string>()) as { ok: boolean; affected?: unknown[]; code?: string };
635
+ if (result && result.ok === true) {
636
+ return { ok: true, affected: result.affected ?? [] };
637
+ }
638
+ return { ok: false, code: (result?.code as string) ?? "store_error", message: "computeBlastRadius reported a failure." };
639
+ } catch (err) {
640
+ const msg = err instanceof Error ? err.message : String(err);
641
+ return { ok: false, code: "store_error", message: msg };
642
+ }
643
+ }
644
+
645
+ /**
646
+ * Persist runtime call traces as HTTP_CALLS edges via the store's
647
+ * standalone upsertEdges write path. Each trace is mapped to an edge with
648
+ * provenance "trace"; edges whose endpoints do not resolve to an indexed
649
+ * node are counted in `skipped` (returned to the caller) rather than
650
+ * silently dropped.
651
+ */
652
+ export async function ingestCodegraphTraces(params: {
653
+ readonly store: CodegraphStore;
654
+ readonly traces: readonly unknown[];
655
+ }): Promise<CodegraphDelegateOutcome<{ accepted: number; persisted: number; skipped: number }>> {
656
+ if (typeof params.store.upsertEdges !== "function") {
657
+ return {
658
+ ok: false,
659
+ code: "runtime_unavailable",
660
+ message: "The installed @remnic/coding-graph does not expose upsertEdges; traces cannot be persisted.",
661
+ };
662
+ }
663
+ const edges: CodegraphEdgeInput[] = [];
664
+ let accepted = 0;
665
+ for (const trace of params.traces) {
666
+ const t = trace as { caller?: string; callee?: string; confidence?: number };
667
+ if (typeof t?.caller !== "string" || typeof t?.callee !== "string") {
668
+ // Malformed trace — skip (the surface validates traces is an array;
669
+ // individual trace shape is validated here so a bad row does not
670
+ // abort the whole batch).
671
+ continue;
672
+ }
673
+ accepted += 1;
674
+ edges.push({
675
+ srcQualifiedName: t.caller,
676
+ dstQualifiedName: t.callee,
677
+ type: "HTTP_CALLS",
678
+ confidence: typeof t.confidence === "number" && t.confidence >= 0 && t.confidence <= 1 ? t.confidence : 0.5,
679
+ provenance: "trace",
680
+ });
681
+ }
682
+ try {
683
+ const result = await params.store.upsertEdges(edges);
684
+ if (result.ok === true) {
685
+ return { ok: true, accepted, persisted: result.persisted, skipped: result.skipped };
686
+ }
687
+ return { ok: false, code: result.code, message: "store.upsertEdges reported a failure." };
688
+ } catch (err) {
689
+ const msg = err instanceof Error ? err.message : String(err);
690
+ return { ok: false, code: "store_error", message: msg };
691
+ }
692
+ }
693
+
694
+ /** Test seam: reset the module cache so a fresh import can be observed. */
695
+ export function __resetCodegraphRuntimeForTest(): void {
696
+ cachedModule = undefined;
697
+ moduleLoadPromise = null;
698
+ storeCache.clear();
699
+ }
700
+
701
+ /**
702
+ * Derive a stable per-repo project id from an absolute repoRoot (issue #1554
703
+ * review threads 7/9/11). Used by the shared store resolver when a caller
704
+ * invokes a codegraph tool with repoRoot but no explicit project and no
705
+ * session coding context (e.g. a standalone stdio-MCP call). The `root:<hex>`
706
+ * form matches the coding-context id convention so a derived id is
707
+ * distinguishable from an `origin:<hex>` remote id. Centralized here so every
708
+ * store-backed tool derives the SAME id and can reopen the DB index created.
709
+ */
710
+ export function deriveCodegraphProjectId(repoRoot: string): string {
711
+ return `root:${createHash("sha256").update(repoRoot).digest("hex").slice(0, 16)}`;
712
+ }
713
+
714
+ /**
715
+ * Resolve the project id for a store-backed codegraph tool from a surface
716
+ * request (issue #1554 review threads 7/9/11). This is the SHARED chokepoint
717
+ * every store-backed tool funnels through, so index / search_graph /
718
+ * get_schema / index_status all reopen the SAME DB:
719
+ * 1. an explicit `project` wins;
720
+ * 2. else a session coding context's projectId;
721
+ * 3. else a stable `root:<hex>` derived from `repoRoot` (standalone callers);
722
+ * 4. else a TAGGED `project_required` error (never a plain Error, so the
723
+ * surface maps it into a structured response rather than an unstructured
724
+ * tool error).
725
+ *
726
+ * The request shape is structural (not the surfaces' CodegraphSurfaceRequest
727
+ * type) to keep this module free of a runtime import cycle with the surfaces.
728
+ */
729
+ export function resolveCodegraphProjectId(params: {
730
+ readonly request: { readonly project?: unknown; readonly sessionKey?: unknown; readonly repoRoot?: unknown };
731
+ readonly getCodingContext: (sessionKey: string) => { readonly projectId: string } | null;
732
+ }): string {
733
+ const { request, getCodingContext } = params;
734
+ const explicit = typeof request.project === "string" ? request.project.trim() : "";
735
+ if (explicit.length > 0) return explicit;
736
+ const sessionKey = typeof request.sessionKey === "string" ? request.sessionKey.trim() : "";
737
+ if (sessionKey.length > 0) {
738
+ const cc = getCodingContext(sessionKey);
739
+ if (cc !== null) return cc.projectId;
740
+ }
741
+ const repoRoot = typeof request.repoRoot === "string" ? request.repoRoot.trim() : "";
742
+ if (repoRoot.length > 0) return deriveCodegraphProjectId(repoRoot);
743
+ throw new CodegraphRuntimeError(
744
+ "project_required",
745
+ "codegraph: project must be supplied explicitly, via a session coding context, or alongside a repoRoot",
746
+ );
747
+ }
748
+
749
+ // ──────────────────────────────────────────────────────────────────────────
750
+ // Tagged runtime error -- `code` is the load-bearing signal (rule 34)
751
+ // ──────────────────────────────────────────────────────────────────────────
752
+
753
+ export type CodegraphRuntimeErrorCode =
754
+ | "disabled"
755
+ | "package_missing"
756
+ | "repo_root_conflict"
757
+ | "confirm_required"
758
+ | "project_required"
759
+ | "project_not_found"
760
+ | "store_error";
761
+
762
+ export class CodegraphRuntimeError extends Error {
763
+ readonly code: CodegraphRuntimeErrorCode;
764
+ constructor(code: CodegraphRuntimeErrorCode, message: string) {
765
+ super(message);
766
+ this.name = "CodegraphRuntimeError";
767
+ this.code = code;
768
+ }
769
+ }
770
+
771
+ // Re-export the gate predicate's input type for callers that only need the
772
+ // config slice (e.g. surface modules that receive CodingKnowledgeConfig).
773
+ export type { CodingKnowledgeConfig, CodingContext };