@remnic/core 9.45.3 → 9.45.4

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 (747) hide show
  1. package/dist/abort-error.d.ts +2 -1
  2. package/dist/abort-error.js +3 -1
  3. package/dist/access-admin-ops-surface.d.ts +14 -10
  4. package/dist/access-admin-ops-surface.js +84 -76
  5. package/dist/access-audit.js +2 -2
  6. package/dist/access-authorization-probe.d.ts +14 -10
  7. package/dist/access-authorization-probe.js +85 -77
  8. package/dist/access-boundary.d.ts +15 -11
  9. package/dist/access-boundary.js +84 -76
  10. package/dist/access-citation-namespace.js +2 -2
  11. package/dist/access-cli.js +193 -181
  12. package/dist/access-cli.js.map +1 -1
  13. package/dist/access-coding-context-resolution.d.ts +16 -0
  14. package/dist/access-coding-context-resolution.js +13 -0
  15. package/dist/access-coding-context-resolution.js.map +1 -0
  16. package/dist/access-extraction-force-flush.d.ts +14 -10
  17. package/dist/access-extraction-force-flush.js +84 -76
  18. package/dist/access-health-types.d.ts +2 -1
  19. package/dist/access-http-lcm-compaction.d.ts +16 -12
  20. package/dist/access-http-lcm-compaction.js +3 -3
  21. package/dist/access-http-lifecycle-flush.d.ts +14 -10
  22. package/dist/access-http-lifecycle-flush.js +2 -2
  23. package/dist/access-http-offline-stream.d.ts +123 -0
  24. package/dist/access-http-offline-stream.js +10 -0
  25. package/dist/access-http-offline-stream.js.map +1 -0
  26. package/dist/access-http-query.js +84 -76
  27. package/dist/access-http.d.ts +15 -10
  28. package/dist/access-http.js +105 -92
  29. package/dist/access-identity-continuity-surface.d.ts +9 -8
  30. package/dist/access-identity-continuity-surface.js +84 -76
  31. package/dist/access-lcm-surface.d.ts +14 -10
  32. package/dist/access-lcm-surface.js +84 -76
  33. package/dist/access-mcp-output-schemas.js +1 -1
  34. package/dist/access-mcp.d.ts +14 -10
  35. package/dist/access-mcp.js +95 -83
  36. package/dist/access-memory-search-fanout.d.ts +3 -2
  37. package/dist/{access-namespace-preflight-5yZ4g6F8.d.ts → access-namespace-preflight-CWUDwB4M.d.ts} +1 -1
  38. package/dist/access-namespace-preflight.d.ts +4 -3
  39. package/dist/access-namespace-preflight.js +84 -76
  40. package/dist/access-observe-helpers.d.ts +1 -0
  41. package/dist/access-observe-helpers.js +1 -1
  42. package/dist/access-observe-write-surface.d.ts +16 -10
  43. package/dist/access-observe-write-surface.js +84 -76
  44. package/dist/access-offline-manifest.d.ts +104 -0
  45. package/dist/access-offline-manifest.js +45 -0
  46. package/dist/access-offline-manifest.js.map +1 -0
  47. package/dist/access-operations-batch.js +86 -78
  48. package/dist/access-operations.d.ts +15 -11
  49. package/dist/access-operations.js +91 -80
  50. package/dist/access-recall-concurrency.d.ts +16 -26
  51. package/dist/access-recall-concurrency.js +86 -77
  52. package/dist/access-recall-response.d.ts +18 -14
  53. package/dist/access-recall-response.js +84 -76
  54. package/dist/access-recall-surface.d.ts +29 -24
  55. package/dist/access-recall-surface.js +84 -76
  56. package/dist/access-schema.js +3 -3
  57. package/dist/{access-service-CiJRsgAB.d.ts → access-service-CsU-ljFD.d.ts} +25 -16
  58. package/dist/access-service-helpers.d.ts +14 -10
  59. package/dist/access-service.d.ts +14 -10
  60. package/dist/access-service.js +84 -76
  61. package/dist/access-surface-catalog.d.ts +14 -10
  62. package/dist/access-surface-catalog.js +4 -0
  63. package/dist/access-surface-catalog.js.map +1 -1
  64. package/dist/access-wearables-meetings-surface.d.ts +4 -3
  65. package/dist/action-confidence.d.ts +2 -1
  66. package/dist/active-memory-bridge.d.ts +2 -1
  67. package/dist/active-recall.d.ts +2 -1
  68. package/dist/active-recall.js +10 -8
  69. package/dist/active-recall.js.map +1 -1
  70. package/dist/adapters/index.js +7 -7
  71. package/dist/adapters/registry.js +3 -3
  72. package/dist/{auto-sync-5OE5QOZB.js → auto-sync-UPTUVE4X.js} +6 -6
  73. package/dist/behavior-learner.d.ts +2 -1
  74. package/dist/behavior-learner.js +1 -1
  75. package/dist/behavior-signals.d.ts +2 -1
  76. package/dist/bootstrap.d.ts +9 -8
  77. package/dist/briefing.d.ts +3 -2
  78. package/dist/briefing.js +23 -22
  79. package/dist/buffer-surprise-report.d.ts +2 -1
  80. package/dist/buffer-turn-helpers.d.ts +2 -1
  81. package/dist/buffer.d.ts +3 -2
  82. package/dist/buffer.js +12 -11
  83. package/dist/bulk-import/index.d.ts +4 -3
  84. package/dist/calibration.d.ts +2 -1
  85. package/dist/capabilities.d.ts +2 -1
  86. package/dist/{capsule-merge-IDWJPCWK.js → capsule-merge-Q6AR3XL7.js} +67 -54
  87. package/dist/capsule-merge-Q6AR3XL7.js.map +1 -0
  88. package/dist/{catalog-scBmy0sO.d.ts → catalog-bctMURhN.d.ts} +1 -1
  89. package/dist/causal-behavior.d.ts +2 -1
  90. package/dist/causal-behavior.js +2 -2
  91. package/dist/causal-chain.js +2 -2
  92. package/dist/causal-consolidation.d.ts +2 -1
  93. package/dist/causal-consolidation.js +27 -26
  94. package/dist/causal-consolidation.js.map +1 -1
  95. package/dist/causal-retrieval.js +2 -2
  96. package/dist/causal-trajectory-graph.d.ts +2 -1
  97. package/dist/causal-trajectory.js +1 -1
  98. package/dist/{chunk-VUPTKTDV.js → chunk-2MRHJNWL.js} +3 -3
  99. package/dist/{chunk-JBPKEARU.js → chunk-2QSZNTDO.js} +7 -7
  100. package/dist/{chunk-5IVLTFOV.js → chunk-44N6ESJ4.js} +2 -2
  101. package/dist/{chunk-WOCNN776.js → chunk-4POAMKV6.js} +100 -41
  102. package/dist/chunk-4POAMKV6.js.map +1 -0
  103. package/dist/{chunk-HO3QBJEY.js → chunk-5546W5SI.js} +2 -2
  104. package/dist/{chunk-U7GW7NE7.js → chunk-5CEECY6P.js} +10 -10
  105. package/dist/{chunk-4UH4BTGK.js → chunk-5SNZSWWR.js} +82 -82
  106. package/dist/{chunk-6CZPDBJS.js → chunk-5U7ID3EZ.js} +3 -3
  107. package/dist/{chunk-GF22HWS2.js → chunk-6NNNURLK.js} +7 -7
  108. package/dist/chunk-773TRRGT.js +36 -0
  109. package/dist/chunk-773TRRGT.js.map +1 -0
  110. package/dist/chunk-7CITSYSH.js +242 -0
  111. package/dist/chunk-7CITSYSH.js.map +1 -0
  112. package/dist/{chunk-227UFSEQ.js → chunk-7RZJWZ46.js} +5 -5
  113. package/dist/{chunk-E5UK4VPE.js → chunk-7SHJHPTY.js} +5 -5
  114. package/dist/{chunk-UVIKWC7M.js → chunk-7YERSTN7.js} +17 -17
  115. package/dist/{chunk-DLVPUX7U.js → chunk-7YKVM5H3.js} +8 -6
  116. package/dist/chunk-7YKVM5H3.js.map +1 -0
  117. package/dist/{chunk-3CE77VAP.js → chunk-A4JMGKCD.js} +87 -74
  118. package/dist/chunk-A4JMGKCD.js.map +1 -0
  119. package/dist/chunk-A5KNZSNA.js +26 -0
  120. package/dist/chunk-A5KNZSNA.js.map +1 -0
  121. package/dist/{chunk-S2NCTZGJ.js → chunk-AJQ57VV3.js} +15 -15
  122. package/dist/chunk-AJQ57VV3.js.map +1 -0
  123. package/dist/{chunk-CUM2BBPN.js → chunk-AUMWZSE7.js} +19 -10
  124. package/dist/chunk-AUMWZSE7.js.map +1 -0
  125. package/dist/{chunk-XYTOI63Z.js → chunk-BGHFOD5A.js} +19 -11
  126. package/dist/chunk-BGHFOD5A.js.map +1 -0
  127. package/dist/{chunk-BUE5E2HL.js → chunk-BGLY7EEM.js} +5 -314
  128. package/dist/chunk-BGLY7EEM.js.map +1 -0
  129. package/dist/chunk-BIPBQQFI.js +44 -0
  130. package/dist/chunk-BIPBQQFI.js.map +1 -0
  131. package/dist/{chunk-S5SLVSVY.js → chunk-BQIFZ2MP.js} +5 -5
  132. package/dist/chunk-BTTPKDIL.js +34 -0
  133. package/dist/{chunk-PVGDJXVK.js.map → chunk-BTTPKDIL.js.map} +1 -1
  134. package/dist/{chunk-E53DSZEN.js → chunk-C26TE27X.js} +3 -3
  135. package/dist/{chunk-LZ4LDKHZ.js → chunk-CLB32OHM.js} +6 -6
  136. package/dist/{chunk-Q6IP2ARR.js → chunk-CSOYVTRX.js} +2 -2
  137. package/dist/{chunk-XOQSEF7X.js → chunk-CVILPI77.js} +6 -6
  138. package/dist/chunk-D3I2MCN7.js +29 -0
  139. package/dist/chunk-D3I2MCN7.js.map +1 -0
  140. package/dist/{chunk-A5OJCXZL.js → chunk-DSUAAZZX.js} +15 -4
  141. package/dist/chunk-DSUAAZZX.js.map +1 -0
  142. package/dist/{chunk-HREE4JHI.js → chunk-DYVMXPCF.js} +486 -287
  143. package/dist/chunk-DYVMXPCF.js.map +1 -0
  144. package/dist/{chunk-J7VGGECD.js → chunk-DZPFMQZ7.js} +1 -1
  145. package/dist/chunk-DZPFMQZ7.js.map +1 -0
  146. package/dist/{chunk-PDLBLTOK.js → chunk-EITZHSX6.js} +9 -9
  147. package/dist/{chunk-D3J5SLQK.js → chunk-EJHEWCGQ.js} +81 -20
  148. package/dist/chunk-EJHEWCGQ.js.map +1 -0
  149. package/dist/{chunk-WUNIWKY4.js → chunk-ELIL2A37.js} +6 -6
  150. package/dist/{chunk-E6PNLPGJ.js → chunk-FZP32336.js} +806 -470
  151. package/dist/chunk-FZP32336.js.map +1 -0
  152. package/dist/{chunk-HZFHQ4AQ.js → chunk-G7A5HLUS.js} +23 -17
  153. package/dist/chunk-G7A5HLUS.js.map +1 -0
  154. package/dist/{chunk-CINZGPSJ.js → chunk-GUMZC2BO.js} +2 -2
  155. package/dist/{chunk-H24WNPA2.js → chunk-GWFSVJ4P.js} +3 -3
  156. package/dist/{chunk-7XC2HX75.js → chunk-GYPQL6XN.js} +157 -16
  157. package/dist/chunk-GYPQL6XN.js.map +1 -0
  158. package/dist/{chunk-TSH56VPU.js → chunk-HAYSYUAB.js} +2 -2
  159. package/dist/{chunk-TDHTVMPG.js → chunk-HFPASSFV.js} +7 -2
  160. package/dist/chunk-HFPASSFV.js.map +1 -0
  161. package/dist/chunk-J2WC5LF4.js +395 -0
  162. package/dist/chunk-J2WC5LF4.js.map +1 -0
  163. package/dist/{chunk-PKNLM44P.js → chunk-JH6BPLOP.js} +9 -9
  164. package/dist/{chunk-KXB4VXHY.js → chunk-JIYDRBVZ.js} +2 -2
  165. package/dist/chunk-JV3C2MNQ.js +74 -0
  166. package/dist/chunk-JV3C2MNQ.js.map +1 -0
  167. package/dist/{chunk-AV5ZEH4M.js → chunk-KVJRXN2E.js} +2 -2
  168. package/dist/{chunk-JVLCVFQ4.js → chunk-KXEFRMCF.js} +3 -3
  169. package/dist/{chunk-WFTIGIIS.js → chunk-L6CQ7WIW.js} +5 -5
  170. package/dist/{chunk-EJUEXZHX.js → chunk-LLJMAULE.js} +2 -2
  171. package/dist/{chunk-N5Z4EVOR.js → chunk-LNEWDF2A.js} +36 -11
  172. package/dist/chunk-LNEWDF2A.js.map +1 -0
  173. package/dist/{chunk-AS7YMSL6.js → chunk-M23RF3LJ.js} +4 -4
  174. package/dist/{chunk-UYLMNVY6.js → chunk-MDISBSYA.js} +16 -9
  175. package/dist/chunk-MDISBSYA.js.map +1 -0
  176. package/dist/{chunk-3F2LKUMU.js → chunk-NIS256NW.js} +2 -2
  177. package/dist/{chunk-YIAA2X3D.js → chunk-NK5RGJ65.js} +3 -3
  178. package/dist/chunk-NLDVVWCL.js +84 -0
  179. package/dist/chunk-NLDVVWCL.js.map +1 -0
  180. package/dist/{chunk-OQ5PRDDS.js → chunk-NTOIP2E6.js} +6 -6
  181. package/dist/{chunk-HLPD7B7P.js → chunk-NUEQKLNB.js} +2 -2
  182. package/dist/{chunk-4J7G5SY4.js → chunk-NZBZ7IS2.js} +72 -24
  183. package/dist/chunk-NZBZ7IS2.js.map +1 -0
  184. package/dist/{chunk-3TBLDMJA.js → chunk-O4KMGRXE.js} +5 -2
  185. package/dist/chunk-O4KMGRXE.js.map +1 -0
  186. package/dist/{chunk-33PLLLL7.js → chunk-P7NGM24P.js} +6 -6
  187. package/dist/{chunk-7TWUCYER.js → chunk-PNRA7FAD.js} +7 -7
  188. package/dist/{chunk-5I4M26Q7.js → chunk-QBSFOKY6.js} +4 -4
  189. package/dist/{chunk-QJAQNXWI.js → chunk-QCECHYZL.js} +76 -79
  190. package/dist/chunk-QCECHYZL.js.map +1 -0
  191. package/dist/{chunk-P4DRWEYC.js → chunk-QVSBTCVP.js} +2 -2
  192. package/dist/{chunk-AAIUERNB.js → chunk-R5RFK3CB.js} +6 -6
  193. package/dist/{chunk-WDISJRMG.js → chunk-RMMVQQA6.js} +2 -2
  194. package/dist/{chunk-KWMXR7XS.js → chunk-S2V7RUCL.js} +8 -1
  195. package/dist/{chunk-KWMXR7XS.js.map → chunk-S2V7RUCL.js.map} +1 -1
  196. package/dist/{chunk-5SM35XZR.js → chunk-S5NZBKKQ.js} +2 -2
  197. package/dist/{chunk-VNA7W7QF.js → chunk-SVH57F5Z.js} +12 -4
  198. package/dist/chunk-SVH57F5Z.js.map +1 -0
  199. package/dist/{chunk-WIPEXG6R.js → chunk-SXIMQLGV.js} +2 -2
  200. package/dist/{chunk-RVLJEII5.js → chunk-SYUBB3WM.js} +256 -187
  201. package/dist/chunk-SYUBB3WM.js.map +1 -0
  202. package/dist/{chunk-OAEQLRCY.js → chunk-TN76AKO3.js} +5 -5
  203. package/dist/{chunk-QN25OCUF.js → chunk-TQ4GD737.js} +5 -5
  204. package/dist/{chunk-VCD4PSK2.js → chunk-TQZ4DVBC.js} +7 -4
  205. package/dist/chunk-TQZ4DVBC.js.map +1 -0
  206. package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
  207. package/dist/{chunk-DNWXFTLD.js → chunk-TYISDI6B.js} +2 -2
  208. package/dist/{chunk-4LMA77JH.js → chunk-U2VLVBBH.js} +3 -3
  209. package/dist/{chunk-5ZE7QHTK.js → chunk-ULVR5KG7.js} +5 -5
  210. package/dist/{chunk-NVRYW264.js → chunk-UQWIKLQK.js} +18 -15
  211. package/dist/chunk-UQWIKLQK.js.map +1 -0
  212. package/dist/{chunk-YV32N67O.js → chunk-URS5GSM7.js} +1 -1
  213. package/dist/chunk-URS5GSM7.js.map +1 -0
  214. package/dist/{chunk-4B77XSG5.js → chunk-UV72DEZD.js} +5 -5
  215. package/dist/{chunk-S2BBISHU.js → chunk-VANZKHTN.js} +3 -3
  216. package/dist/chunk-VHFXP27N.js +250 -0
  217. package/dist/chunk-VHFXP27N.js.map +1 -0
  218. package/dist/{chunk-3Y224NYC.js → chunk-VYISFWVX.js} +2 -2
  219. package/dist/{chunk-TIHMZFIV.js → chunk-W3IC7QOY.js} +3 -3
  220. package/dist/{chunk-NRV4Y3PM.js → chunk-W4FBGYGK.js} +1 -1
  221. package/dist/{chunk-P2BM76KT.js → chunk-WAS4HV46.js} +174 -43
  222. package/dist/chunk-WAS4HV46.js.map +1 -0
  223. package/dist/{chunk-57QKLRBV.js → chunk-WB7JSQCP.js} +2 -1
  224. package/dist/chunk-WB7JSQCP.js.map +1 -0
  225. package/dist/chunk-WGP57SR3.js +68 -0
  226. package/dist/chunk-WGP57SR3.js.map +1 -0
  227. package/dist/{chunk-ECK75GDJ.js → chunk-WQIHRA5F.js} +43 -24
  228. package/dist/chunk-WQIHRA5F.js.map +1 -0
  229. package/dist/{chunk-MU7ZHSZE.js → chunk-WZFAPHIK.js} +2 -2
  230. package/dist/{chunk-T2TTP3KU.js → chunk-X4IDNPOS.js} +2 -2
  231. package/dist/{chunk-BLAKS3CP.js → chunk-XL3TATMJ.js} +3 -3
  232. package/dist/{chunk-W4XJFLAL.js → chunk-XPRJSHNI.js} +2 -2
  233. package/dist/{chunk-5TFP4CUL.js → chunk-XQ3HXAQH.js} +14 -11
  234. package/dist/chunk-XQ3HXAQH.js.map +1 -0
  235. package/dist/{chunk-VWAXN2BN.js → chunk-XSFHWBQO.js} +93 -31
  236. package/dist/chunk-XSFHWBQO.js.map +1 -0
  237. package/dist/{chunk-DL7ZD3JH.js → chunk-XTAUXTDO.js} +14 -9
  238. package/dist/chunk-XTAUXTDO.js.map +1 -0
  239. package/dist/{chunk-JE7EK33X.js → chunk-Y7HRYCNW.js} +2 -2
  240. package/dist/{chunk-E6EE5B67.js → chunk-YK6BDDHP.js} +4 -4
  241. package/dist/{chunk-ES36HTSC.js → chunk-YLHM5BQQ.js} +3 -3
  242. package/dist/{chunk-RN7DY3FC.js → chunk-YMAQDHQM.js} +31 -12
  243. package/dist/chunk-YMAQDHQM.js.map +1 -0
  244. package/dist/{chunk-ULARSG5Z.js → chunk-YN6ASZUG.js} +10 -8
  245. package/dist/{chunk-ULARSG5Z.js.map → chunk-YN6ASZUG.js.map} +1 -1
  246. package/dist/{chunk-IKKWIPYN.js → chunk-YYQAKIDJ.js} +37 -1
  247. package/dist/chunk-YYQAKIDJ.js.map +1 -0
  248. package/dist/{chunk-BJKPPZ6Z.js → chunk-ZFGZ6PZ2.js} +2 -2
  249. package/dist/{chunk-CJ2ZR7UA.js → chunk-ZI32MKDW.js} +267 -214
  250. package/dist/chunk-ZI32MKDW.js.map +1 -0
  251. package/dist/{chunk-64UDOIMI.js → chunk-ZLQ37WJX.js} +2 -2
  252. package/dist/chunk-ZMAYKGPN.js +351 -0
  253. package/dist/chunk-ZMAYKGPN.js.map +1 -0
  254. package/dist/{cli-BUGN3d6_.d.ts → cli-BBHDtG36.d.ts} +5 -5
  255. package/dist/cli.d.ts +16 -12
  256. package/dist/cli.js +138 -124
  257. package/dist/compounding/engine.d.ts +3 -2
  258. package/dist/compounding/engine.js +24 -23
  259. package/dist/compounding/preference-consolidator.d.ts +2 -1
  260. package/dist/compression-optimizer.d.ts +2 -1
  261. package/dist/config.d.ts +2 -1
  262. package/dist/config.js +10 -8
  263. package/dist/connectors/codex-materialize-runner.d.ts +2 -1
  264. package/dist/connectors/codex-materialize-runner.js +23 -22
  265. package/dist/connectors/codex-materialize.d.ts +2 -1
  266. package/dist/connectors/index.d.ts +2 -1
  267. package/dist/connectors/index.js +26 -25
  268. package/dist/consolidation-provenance-check.d.ts +3 -2
  269. package/dist/consolidation-provenance-check.js +4 -4
  270. package/dist/consolidation-undo.d.ts +3 -2
  271. package/dist/consolidation-undo.js +10 -7
  272. package/dist/consolidation-undo.js.map +1 -1
  273. package/dist/contradiction/index.d.ts +3 -2
  274. package/dist/converge-config.d.ts +2 -1
  275. package/dist/convergence-refresh.d.ts +4 -3
  276. package/dist/convergence-refresh.js +27 -26
  277. package/dist/conversation-index/backend.d.ts +2 -1
  278. package/dist/conversation-index/backend.js +2 -2
  279. package/dist/conversation-index/chunker.d.ts +2 -1
  280. package/dist/conversation-index/faiss-adapter.d.ts +2 -1
  281. package/dist/conversation-index/indexer.d.ts +2 -1
  282. package/dist/conversation-index/search.d.ts +2 -1
  283. package/dist/corpus-watermark.d.ts +2 -1
  284. package/dist/corpus-watermark.js +42 -41
  285. package/dist/day-summary.d.ts +2 -1
  286. package/dist/delinearize.d.ts +2 -1
  287. package/dist/direct-answer-wiring.d.ts +2 -1
  288. package/dist/direct-answer-wiring.js +2 -2
  289. package/dist/direct-answer.d.ts +2 -1
  290. package/dist/embedding-fallback.d.ts +2 -1
  291. package/dist/embedding-fallback.js +2 -2
  292. package/dist/enrichment/index.d.ts +2 -1
  293. package/dist/entity-retrieval-boundaries.js +1 -1
  294. package/dist/entity-retrieval.d.ts +3 -2
  295. package/dist/entity-retrieval.js +24 -23
  296. package/dist/entity-schema.d.ts +2 -1
  297. package/dist/explicit-capture.d.ts +9 -8
  298. package/dist/explicit-capture.js +11 -9
  299. package/dist/external-wiki-access.d.ts +127 -0
  300. package/dist/external-wiki-access.js +186 -0
  301. package/dist/external-wiki-access.js.map +1 -0
  302. package/dist/external-wiki-cli.d.ts +13 -0
  303. package/dist/external-wiki-cli.js +96 -0
  304. package/dist/external-wiki-cli.js.map +1 -0
  305. package/dist/external-wiki-collection-registration.d.ts +39 -0
  306. package/dist/external-wiki-collection-registration.js +79 -0
  307. package/dist/external-wiki-collection-registration.js.map +1 -0
  308. package/dist/external-wiki-collection.d.ts +50 -0
  309. package/dist/external-wiki-collection.js +387 -0
  310. package/dist/external-wiki-collection.js.map +1 -0
  311. package/dist/external-wiki-config.d.ts +13 -0
  312. package/dist/external-wiki-config.js +13 -0
  313. package/dist/external-wiki-config.js.map +1 -0
  314. package/dist/external-wiki-guard.d.ts +11 -0
  315. package/dist/external-wiki-guard.js +18 -0
  316. package/dist/external-wiki-guard.js.map +1 -0
  317. package/dist/external-wiki-mcp-tools.d.ts +123 -0
  318. package/dist/external-wiki-mcp-tools.js +8 -0
  319. package/dist/external-wiki-mcp-tools.js.map +1 -0
  320. package/dist/external-wiki-search.d.ts +42 -0
  321. package/dist/external-wiki-search.js +11 -0
  322. package/dist/external-wiki-search.js.map +1 -0
  323. package/dist/external-wiki.d.ts +43 -0
  324. package/dist/external-wiki.js +16 -0
  325. package/dist/external-wiki.js.map +1 -0
  326. package/dist/extraction-error-classification.d.ts +2 -1
  327. package/dist/extraction-faithfulness.d.ts +2 -1
  328. package/dist/extraction-judge-telemetry.d.ts +2 -1
  329. package/dist/extraction-judge-training.d.ts +2 -1
  330. package/dist/extraction-judge.d.ts +2 -1
  331. package/dist/extraction-liveness.d.ts +2 -1
  332. package/dist/extraction-source-grounding-helpers.d.ts +5 -3
  333. package/dist/extraction-source-grounding-helpers.js +1 -1
  334. package/dist/extraction-source-grounding-rules.d.ts +2 -1
  335. package/dist/extraction-source-grounding-rules.js +2 -2
  336. package/dist/extraction-source-grounding.d.ts +2 -1
  337. package/dist/extraction-source-grounding.js +5 -5
  338. package/dist/extraction.d.ts +2 -1
  339. package/dist/extraction.js +45 -43
  340. package/dist/fallback-llm.d.ts +2 -1
  341. package/dist/graph-dashboard-diff.d.ts +2 -1
  342. package/dist/graph-dashboard-key.d.ts +2 -1
  343. package/dist/graph-dashboard-parser.d.ts +2 -1
  344. package/dist/graph-edge-reinforcement.d.ts +2 -1
  345. package/dist/graph-snapshot.d.ts +2 -1
  346. package/dist/graph.d.ts +2 -1
  347. package/dist/harmonic-retrieval.js +2 -2
  348. package/dist/importance.d.ts +2 -1
  349. package/dist/importers/index.d.ts +2 -1
  350. package/dist/in-flight-reads.d.ts +2 -1
  351. package/dist/index.d.ts +362 -350
  352. package/dist/index.js +291 -259
  353. package/dist/intent.d.ts +2 -1
  354. package/dist/lcm/engine.d.ts +2 -1
  355. package/dist/lcm/engine.js +3 -3
  356. package/dist/lcm/index.d.ts +2 -1
  357. package/dist/lcm/index.js +8 -8
  358. package/dist/lcm/tools.d.ts +2 -1
  359. package/dist/lifecycle.d.ts +2 -1
  360. package/dist/live-connectors-runner.d.ts +2 -1
  361. package/dist/local-llm.d.ts +2 -1
  362. package/dist/local-llm.js +2 -2
  363. package/dist/local-model-endpoint.d.ts +2 -1
  364. package/dist/maintenance/memory-governance.d.ts +2 -1
  365. package/dist/maintenance/memory-governance.js +24 -23
  366. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +3 -2
  367. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +24 -23
  368. package/dist/maintenance/rebuild-memory-projection.d.ts +3 -2
  369. package/dist/maintenance/rebuild-memory-projection.js +26 -25
  370. package/dist/{maintenance-LbuS2rUA.d.ts → maintenance-D2mveyCd.d.ts} +3 -3
  371. package/dist/mcp-memory-inspector-app.d.ts +14 -10
  372. package/dist/mcp-read-only-tools.js +1 -1
  373. package/dist/memory-action-policy.d.ts +2 -1
  374. package/dist/memory-cache.d.ts +2 -1
  375. package/dist/memory-lifecycle-ledger-utils.d.ts +2 -1
  376. package/dist/memory-projection-store.d.ts +2 -1
  377. package/dist/memory-provenance.d.ts +2 -1
  378. package/dist/memory-worth-outcomes.d.ts +3 -2
  379. package/dist/models-json.d.ts +2 -1
  380. package/dist/namespaces/migrate.d.ts +4 -3
  381. package/dist/namespaces/migrate.js +40 -39
  382. package/dist/namespaces/principal.d.ts +2 -1
  383. package/dist/namespaces/search.d.ts +2 -1
  384. package/dist/namespaces/search.js +18 -18
  385. package/dist/namespaces/storage.d.ts +4 -3
  386. package/dist/namespaces/storage.js +23 -22
  387. package/dist/native-knowledge.d.ts +2 -1
  388. package/dist/offline-sync-impression-drain.d.ts +2 -1
  389. package/dist/offline-sync-impression-drain.js +11 -9
  390. package/dist/offline-sync.d.ts +29 -3
  391. package/dist/offline-sync.js +6 -2
  392. package/dist/operator-doctor-corpus.d.ts +2 -1
  393. package/dist/operator-doctor-corpus.js +45 -44
  394. package/dist/operator-doctor-replica.d.ts +2 -1
  395. package/dist/operator-doctor-replica.js +3 -3
  396. package/dist/operator-toolkit.d.ts +4 -3
  397. package/dist/operator-toolkit.js +59 -55
  398. package/dist/orchestration/compression-guideline-coordinator.d.ts +3 -2
  399. package/dist/orchestration/maintenance.d.ts +5 -4
  400. package/dist/orchestration/maintenance.js +36 -33
  401. package/dist/{orchestrator-rHiWt32X.d.ts → orchestrator-DJYlwiUv.d.ts} +14 -7
  402. package/dist/orchestrator.d.ts +9 -8
  403. package/dist/orchestrator.js +201 -189
  404. package/dist/page-versioning.js +3 -3
  405. package/dist/patterns-cli.d.ts +2 -1
  406. package/dist/{pipeline-W_97O8BV.d.ts → pipeline-CNjY4wk3.d.ts} +1 -1
  407. package/dist/policy-runtime.d.ts +2 -1
  408. package/dist/policy-runtime.js +1 -1
  409. package/dist/proactive-contention.d.ts +2 -1
  410. package/dist/provenance.d.ts +2 -1
  411. package/dist/provenance.js +2 -2
  412. package/dist/{qmd-LWtMofAf.d.ts → qmd-C0UDZidt.d.ts} +9 -7
  413. package/dist/qmd-preflight.d.ts +5 -4
  414. package/dist/qmd-preflight.js +2 -2
  415. package/dist/qmd-recall-cache.d.ts +2 -1
  416. package/dist/qmd.d.ts +4 -3
  417. package/dist/qmd.js +5 -5
  418. package/dist/recall-concurrency-config.d.ts +2 -1
  419. package/dist/recall-disclosure-escalation.d.ts +2 -1
  420. package/dist/recall-explain-renderer.d.ts +2 -1
  421. package/dist/recall-explain-renderer.js +3 -3
  422. package/dist/recall-memory-map.d.ts +2 -1
  423. package/dist/recall-planner-llm.d.ts +2 -1
  424. package/dist/recall-state.d.ts +2 -1
  425. package/dist/recall-tag-filter.d.ts +2 -1
  426. package/dist/recall-timings.d.ts +2 -1
  427. package/dist/recall-xray-cli.d.ts +2 -1
  428. package/dist/recall-xray-cli.js +4 -4
  429. package/dist/recall-xray-renderer.d.ts +2 -1
  430. package/dist/recall-xray-renderer.js +3 -3
  431. package/dist/recall-xray.d.ts +8 -1
  432. package/dist/recall-xray.js +2 -2
  433. package/dist/reconcile/cursor.d.ts +12 -2
  434. package/dist/reconcile/cursor.js +46 -7
  435. package/dist/reconcile/cursor.js.map +1 -1
  436. package/dist/reconcile/manifest.d.ts +9 -2
  437. package/dist/reconcile/manifest.js +15 -268
  438. package/dist/reconcile/manifest.js.map +1 -1
  439. package/dist/reconcile/plan.d.ts +4 -1
  440. package/dist/reconcile/plan.js +4 -4
  441. package/dist/replay/normalizers/chatgpt.d.ts +2 -1
  442. package/dist/replay/normalizers/claude.d.ts +2 -1
  443. package/dist/replay/normalizers/openclaw.d.ts +2 -1
  444. package/dist/replay/normalizers/shared.d.ts +2 -1
  445. package/dist/replay/runner.d.ts +2 -1
  446. package/dist/replay/types.d.ts +2 -1
  447. package/dist/replica-divergence.d.ts +2 -1
  448. package/dist/replica-divergence.js +2 -2
  449. package/dist/replica-peers-config.d.ts +2 -1
  450. package/dist/resolve-auth-token.d.ts +2 -1
  451. package/dist/resume-bundles.js +12 -10
  452. package/dist/retrieval-agents.d.ts +4 -3
  453. package/dist/retrieval-agents.js +2 -2
  454. package/dist/retrieval-tiers.d.ts +2 -1
  455. package/dist/routing/engine.d.ts +2 -1
  456. package/dist/routing/store.d.ts +2 -1
  457. package/dist/salvage-envelope.d.ts +2 -1
  458. package/dist/schemas.d.ts +32 -32
  459. package/dist/{scope-profiles-BiQKOE-p.d.ts → scope-profiles-BJzp2F5A.d.ts} +1 -1
  460. package/dist/search/embed-helper.d.ts +2 -1
  461. package/dist/search/embed-helper.js +3 -3
  462. package/dist/search/factory.d.ts +4 -2
  463. package/dist/search/factory.js +20 -18
  464. package/dist/search/index.d.ts +2 -1
  465. package/dist/search/index.js +22 -22
  466. package/dist/search/lancedb-backend.d.ts +2 -1
  467. package/dist/search/lancedb-backend.js +4 -4
  468. package/dist/search/meilisearch-backend.d.ts +2 -1
  469. package/dist/search/meilisearch-backend.js +4 -4
  470. package/dist/search/noop-backend.d.ts +2 -1
  471. package/dist/search/orama-backend.d.ts +2 -1
  472. package/dist/search/orama-backend.js +4 -4
  473. package/dist/search/port.d.ts +18 -1
  474. package/dist/search/port.js +1 -1
  475. package/dist/search/remote-backend.d.ts +2 -1
  476. package/dist/search/remote-backend.js +2 -2
  477. package/dist/secure-store/index.js +2 -2
  478. package/dist/{semantic-consolidation-dHYCyqgh.d.ts → semantic-consolidation-D4KAZO2G.d.ts} +1 -1
  479. package/dist/semantic-consolidation.d.ts +3 -2
  480. package/dist/semantic-consolidation.js +25 -24
  481. package/dist/semantic-rule-promotion.js +23 -22
  482. package/dist/semantic-rule-verifier.d.ts +2 -1
  483. package/dist/semantic-rule-verifier.js +24 -23
  484. package/dist/{service-DJG3KCQ4.d.ts → service-BeDxSqE-.d.ts} +2 -2
  485. package/dist/session-observer-bands.d.ts +2 -1
  486. package/dist/session-observer-state.d.ts +2 -1
  487. package/dist/shared-context/manager.d.ts +2 -1
  488. package/dist/shared-context/manager.js +2 -2
  489. package/dist/signal.d.ts +2 -1
  490. package/dist/source-agent-qualifier.d.ts +2 -1
  491. package/dist/source-agent-qualifier.js +42 -40
  492. package/dist/{storage-F9FVh-w9.d.ts → storage-DfjxusTE.d.ts} +24 -12
  493. package/dist/storage.d.ts +3 -2
  494. package/dist/storage.js +25 -24
  495. package/dist/summarizer.d.ts +2 -1
  496. package/dist/summarizer.js +5 -5
  497. package/dist/summary-snapshot.d.ts +2 -1
  498. package/dist/temporal-supersession.d.ts +3 -2
  499. package/dist/temporal-timeline-recall.d.ts +2 -1
  500. package/dist/temporal-validity.d.ts +2 -1
  501. package/dist/threading.d.ts +2 -1
  502. package/dist/tier-migration.d.ts +3 -2
  503. package/dist/tier-routing.d.ts +2 -1
  504. package/dist/tool-scoped-memory.d.ts +5 -1
  505. package/dist/tool-scoped-memory.js +3 -1
  506. package/dist/topics.d.ts +2 -1
  507. package/dist/transcript.d.ts +2 -1
  508. package/dist/transfer/capsule-import.js +4 -4
  509. package/dist/transfer/types.d.ts +12 -12
  510. package/dist/trust-score-stage.d.ts +2 -1
  511. package/dist/trust-score.d.ts +2 -1
  512. package/dist/{types-rEwubvim.d.ts → types-yX_FwERf.d.ts} +8 -1
  513. package/dist/types.d.ts +2 -1
  514. package/dist/types.js +1 -1
  515. package/dist/utility-runtime.d.ts +2 -1
  516. package/dist/verified-recall.js +24 -23
  517. package/dist/write-envelope.d.ts +2 -1
  518. package/package.json +2 -2
  519. package/src/abort-error.ts +17 -0
  520. package/src/access-admin-ops-surface.ts +1 -0
  521. package/src/access-boundary.ts +1 -0
  522. package/src/access-coding-context-resolution.ts +42 -0
  523. package/src/access-extraction-force-flush.ts +38 -2
  524. package/src/access-http-lcm-compaction.ts +5 -2
  525. package/src/access-http-offline-stream.ts +79 -0
  526. package/src/access-http.test.ts +310 -3
  527. package/src/access-http.ts +85 -21
  528. package/src/access-mcp-output-schemas.ts +36 -0
  529. package/src/access-mcp.test.ts +95 -1
  530. package/src/access-mcp.ts +7 -9
  531. package/src/access-observe-helpers.ts +64 -22
  532. package/src/access-observe-write-surface.ts +8 -0
  533. package/src/access-offline-manifest.ts +54 -0
  534. package/src/access-operations-batch.ts +3 -3
  535. package/src/access-operations.ts +13 -7
  536. package/src/access-recall-concurrency.ts +3 -27
  537. package/src/access-recall-surface.ts +3 -0
  538. package/src/access-service-health.test.ts +32 -7
  539. package/src/access-service-namespace.test.ts +55 -0
  540. package/src/access-service-observe-idempotency.test.ts +34 -2
  541. package/src/access-service-observe-lcm-parity.test.ts +138 -3
  542. package/src/access-service-observe-scope.test.ts +160 -1
  543. package/src/access-service-offline-file-content.test.ts +345 -1
  544. package/src/access-service.ts +86 -59
  545. package/src/access-surface-catalog.ts +4 -0
  546. package/src/admin/admin-surfaces.ts +2 -0
  547. package/src/binary-lifecycle/pipeline.test.ts +106 -1
  548. package/src/binary-lifecycle/pipeline.ts +3 -0
  549. package/src/coding/git-context.test.ts +47 -0
  550. package/src/coding/git-context.ts +129 -27
  551. package/src/config.test.ts +24 -0
  552. package/src/config.ts +9 -12
  553. package/src/connector-provenance.test.ts +101 -0
  554. package/src/consolidation-undo.ts +3 -0
  555. package/src/convergence-refresh.ts +14 -2
  556. package/src/correction/correction-access-wiring.ts +9 -7
  557. package/src/correction/correction-executor.test.ts +206 -2
  558. package/src/correction/correction-executor.ts +29 -20
  559. package/src/correction/correction-planner.test.ts +36 -0
  560. package/src/correction/correction-planner.ts +9 -15
  561. package/src/correction/correction-service.ts +3 -1
  562. package/src/correction/correction-storage-integration.test.ts +77 -0
  563. package/src/correction/correction-surfaces.test.ts +41 -28
  564. package/src/correction/passive-capture.test.ts +59 -0
  565. package/src/correction/passive-capture.ts +4 -1
  566. package/src/entity-retrieval-boundaries.ts +17 -4
  567. package/src/entity-retrieval.ts +27 -6
  568. package/src/external-wiki-access.test.ts +65 -0
  569. package/src/external-wiki-access.ts +31 -0
  570. package/src/external-wiki-cli.ts +92 -0
  571. package/src/external-wiki-collection-registration.test.ts +163 -0
  572. package/src/external-wiki-collection-registration.ts +101 -0
  573. package/src/external-wiki-collection.test.ts +502 -0
  574. package/src/external-wiki-collection.ts +503 -0
  575. package/src/external-wiki-config.test.ts +135 -0
  576. package/src/external-wiki-config.ts +100 -0
  577. package/src/external-wiki-guard.ts +83 -0
  578. package/src/external-wiki-mcp-tools.ts +23 -0
  579. package/src/external-wiki-search.test.ts +301 -0
  580. package/src/external-wiki-search.ts +362 -0
  581. package/src/external-wiki.test.ts +240 -0
  582. package/src/external-wiki.ts +453 -0
  583. package/src/extraction-scope-source-agent.test.ts +21 -0
  584. package/src/extraction-source-grounding-helpers.ts +243 -53
  585. package/src/extraction-source-grounding-rules.ts +133 -39
  586. package/src/extraction-source-grounding.test.ts +363 -33
  587. package/src/extraction-timeout.test.ts +1 -0
  588. package/src/extraction-watermark.test.ts +150 -7
  589. package/src/extraction.ts +8 -1
  590. package/src/index.ts +8 -0
  591. package/src/mcp-read-only-tools.ts +1 -0
  592. package/src/offline-sync.test.ts +194 -0
  593. package/src/offline-sync.ts +217 -13
  594. package/src/orchestration/external-wiki-recall-guard.test.ts +94 -0
  595. package/src/orchestration/extraction-persist.ts +19 -2
  596. package/src/orchestration/extraction-run-helpers.ts +37 -19
  597. package/src/orchestration/extraction-run.test.ts +171 -2
  598. package/src/orchestration/extraction-run.ts +11 -13
  599. package/src/orchestration/extraction-watermark.ts +106 -17
  600. package/src/orchestration/generic-recall-paths.ts +14 -0
  601. package/src/orchestration/orchestrator-helpers.ts +2 -0
  602. package/src/orchestration/orchestrator-init.ts +9 -0
  603. package/src/orchestration/recall-internal-deps.ts +6 -0
  604. package/src/orchestration/recall-internal.ts +154 -33
  605. package/src/orchestration/recall-rerank-coordinator.ts +60 -25
  606. package/src/orchestration/recall-search-pipeline.test.ts +75 -1
  607. package/src/orchestration/recall-search-pipeline.ts +50 -10
  608. package/src/orchestrator-convergence-refresh.test.ts +36 -2
  609. package/src/orchestrator.ts +13 -3
  610. package/src/page-versioning.ts +5 -19
  611. package/src/procedural/procedure-recall.ts +5 -1
  612. package/src/provenance-surfaces.test.ts +3 -0
  613. package/src/qmd-client.test.ts +78 -17
  614. package/src/qmd.test.ts +24 -0
  615. package/src/qmd.ts +224 -315
  616. package/src/recall-explain-renderer.ts +3 -0
  617. package/src/recall-rerank-coordinator.test.ts +61 -0
  618. package/src/recall-xray-renderer.test.ts +6 -0
  619. package/src/recall-xray.test.ts +88 -1
  620. package/src/recall-xray.ts +15 -0
  621. package/src/reconcile/cursor.test.ts +48 -0
  622. package/src/reconcile/cursor.ts +58 -11
  623. package/src/reconcile/manifest.test.ts +4 -0
  624. package/src/reconcile/manifest.ts +41 -51
  625. package/src/reconcile/plan.test.ts +4 -0
  626. package/src/reconcile/plan.ts +28 -16
  627. package/src/search/factory.ts +6 -6
  628. package/src/search/port.ts +25 -9
  629. package/src/secure-store/secure-fs.ts +20 -12
  630. package/src/secure-store/secure-store.test.ts +41 -2
  631. package/src/spaces/index.test.ts +61 -2
  632. package/src/spaces/index.ts +44 -18
  633. package/src/storage/entity-alias-config.ts +97 -0
  634. package/src/storage/entity-canonical-id-lock.ts +53 -23
  635. package/src/storage/entity-canonical-id-migration.ts +53 -22
  636. package/src/storage/entity-canonical-id-references.ts +3 -0
  637. package/src/storage/entity-id-safety.ts +7 -0
  638. package/src/storage/entity-store.ts +6 -2
  639. package/src/storage/memory-frontmatter-metadata.ts +4 -9
  640. package/src/storage/memory-migration-serialization.ts +10 -15
  641. package/src/storage/tombstone-blocked-capture-mutation.ts +52 -64
  642. package/src/storage/tombstone-blocked-capture-sync.ts +244 -199
  643. package/src/storage-deletion-revisions.test.ts +91 -0
  644. package/src/storage-fact-hash-index-defer.test.ts +446 -163
  645. package/src/storage.ts +534 -245
  646. package/src/tool-scoped-memory.ts +10 -0
  647. package/src/transfer/capsule-import.ts +13 -0
  648. package/src/transfer/capsule-merge.ts +13 -0
  649. package/src/trust-score-recall-paths.test.ts +75 -1
  650. package/src/types.ts +7 -3
  651. package/dist/capsule-merge-IDWJPCWK.js.map +0 -1
  652. package/dist/chunk-3CE77VAP.js.map +0 -1
  653. package/dist/chunk-3TBLDMJA.js.map +0 -1
  654. package/dist/chunk-4J7G5SY4.js.map +0 -1
  655. package/dist/chunk-57QKLRBV.js.map +0 -1
  656. package/dist/chunk-5TFP4CUL.js.map +0 -1
  657. package/dist/chunk-7XC2HX75.js.map +0 -1
  658. package/dist/chunk-A5OJCXZL.js.map +0 -1
  659. package/dist/chunk-BUE5E2HL.js.map +0 -1
  660. package/dist/chunk-CJ2ZR7UA.js.map +0 -1
  661. package/dist/chunk-CUM2BBPN.js.map +0 -1
  662. package/dist/chunk-D3J5SLQK.js.map +0 -1
  663. package/dist/chunk-DL7ZD3JH.js.map +0 -1
  664. package/dist/chunk-DLVPUX7U.js.map +0 -1
  665. package/dist/chunk-E6PNLPGJ.js.map +0 -1
  666. package/dist/chunk-ECK75GDJ.js.map +0 -1
  667. package/dist/chunk-HREE4JHI.js.map +0 -1
  668. package/dist/chunk-HZFHQ4AQ.js.map +0 -1
  669. package/dist/chunk-IKKWIPYN.js.map +0 -1
  670. package/dist/chunk-J7VGGECD.js.map +0 -1
  671. package/dist/chunk-N5Z4EVOR.js.map +0 -1
  672. package/dist/chunk-NVRYW264.js.map +0 -1
  673. package/dist/chunk-P2BM76KT.js.map +0 -1
  674. package/dist/chunk-PVGDJXVK.js +0 -21
  675. package/dist/chunk-QJAQNXWI.js.map +0 -1
  676. package/dist/chunk-RN7DY3FC.js.map +0 -1
  677. package/dist/chunk-RVLJEII5.js.map +0 -1
  678. package/dist/chunk-S2NCTZGJ.js.map +0 -1
  679. package/dist/chunk-TDHTVMPG.js.map +0 -1
  680. package/dist/chunk-UYLMNVY6.js.map +0 -1
  681. package/dist/chunk-VCD4PSK2.js.map +0 -1
  682. package/dist/chunk-VNA7W7QF.js.map +0 -1
  683. package/dist/chunk-VWAXN2BN.js.map +0 -1
  684. package/dist/chunk-WOCNN776.js.map +0 -1
  685. package/dist/chunk-XYTOI63Z.js.map +0 -1
  686. package/dist/chunk-YV32N67O.js.map +0 -1
  687. /package/dist/{auto-sync-5OE5QOZB.js.map → auto-sync-UPTUVE4X.js.map} +0 -0
  688. /package/dist/{chunk-VUPTKTDV.js.map → chunk-2MRHJNWL.js.map} +0 -0
  689. /package/dist/{chunk-JBPKEARU.js.map → chunk-2QSZNTDO.js.map} +0 -0
  690. /package/dist/{chunk-5IVLTFOV.js.map → chunk-44N6ESJ4.js.map} +0 -0
  691. /package/dist/{chunk-HO3QBJEY.js.map → chunk-5546W5SI.js.map} +0 -0
  692. /package/dist/{chunk-U7GW7NE7.js.map → chunk-5CEECY6P.js.map} +0 -0
  693. /package/dist/{chunk-4UH4BTGK.js.map → chunk-5SNZSWWR.js.map} +0 -0
  694. /package/dist/{chunk-6CZPDBJS.js.map → chunk-5U7ID3EZ.js.map} +0 -0
  695. /package/dist/{chunk-GF22HWS2.js.map → chunk-6NNNURLK.js.map} +0 -0
  696. /package/dist/{chunk-227UFSEQ.js.map → chunk-7RZJWZ46.js.map} +0 -0
  697. /package/dist/{chunk-E5UK4VPE.js.map → chunk-7SHJHPTY.js.map} +0 -0
  698. /package/dist/{chunk-UVIKWC7M.js.map → chunk-7YERSTN7.js.map} +0 -0
  699. /package/dist/{chunk-S5SLVSVY.js.map → chunk-BQIFZ2MP.js.map} +0 -0
  700. /package/dist/{chunk-E53DSZEN.js.map → chunk-C26TE27X.js.map} +0 -0
  701. /package/dist/{chunk-LZ4LDKHZ.js.map → chunk-CLB32OHM.js.map} +0 -0
  702. /package/dist/{chunk-Q6IP2ARR.js.map → chunk-CSOYVTRX.js.map} +0 -0
  703. /package/dist/{chunk-XOQSEF7X.js.map → chunk-CVILPI77.js.map} +0 -0
  704. /package/dist/{chunk-PDLBLTOK.js.map → chunk-EITZHSX6.js.map} +0 -0
  705. /package/dist/{chunk-WUNIWKY4.js.map → chunk-ELIL2A37.js.map} +0 -0
  706. /package/dist/{chunk-CINZGPSJ.js.map → chunk-GUMZC2BO.js.map} +0 -0
  707. /package/dist/{chunk-H24WNPA2.js.map → chunk-GWFSVJ4P.js.map} +0 -0
  708. /package/dist/{chunk-TSH56VPU.js.map → chunk-HAYSYUAB.js.map} +0 -0
  709. /package/dist/{chunk-PKNLM44P.js.map → chunk-JH6BPLOP.js.map} +0 -0
  710. /package/dist/{chunk-KXB4VXHY.js.map → chunk-JIYDRBVZ.js.map} +0 -0
  711. /package/dist/{chunk-AV5ZEH4M.js.map → chunk-KVJRXN2E.js.map} +0 -0
  712. /package/dist/{chunk-JVLCVFQ4.js.map → chunk-KXEFRMCF.js.map} +0 -0
  713. /package/dist/{chunk-WFTIGIIS.js.map → chunk-L6CQ7WIW.js.map} +0 -0
  714. /package/dist/{chunk-EJUEXZHX.js.map → chunk-LLJMAULE.js.map} +0 -0
  715. /package/dist/{chunk-AS7YMSL6.js.map → chunk-M23RF3LJ.js.map} +0 -0
  716. /package/dist/{chunk-3F2LKUMU.js.map → chunk-NIS256NW.js.map} +0 -0
  717. /package/dist/{chunk-YIAA2X3D.js.map → chunk-NK5RGJ65.js.map} +0 -0
  718. /package/dist/{chunk-OQ5PRDDS.js.map → chunk-NTOIP2E6.js.map} +0 -0
  719. /package/dist/{chunk-HLPD7B7P.js.map → chunk-NUEQKLNB.js.map} +0 -0
  720. /package/dist/{chunk-33PLLLL7.js.map → chunk-P7NGM24P.js.map} +0 -0
  721. /package/dist/{chunk-7TWUCYER.js.map → chunk-PNRA7FAD.js.map} +0 -0
  722. /package/dist/{chunk-5I4M26Q7.js.map → chunk-QBSFOKY6.js.map} +0 -0
  723. /package/dist/{chunk-P4DRWEYC.js.map → chunk-QVSBTCVP.js.map} +0 -0
  724. /package/dist/{chunk-AAIUERNB.js.map → chunk-R5RFK3CB.js.map} +0 -0
  725. /package/dist/{chunk-WDISJRMG.js.map → chunk-RMMVQQA6.js.map} +0 -0
  726. /package/dist/{chunk-5SM35XZR.js.map → chunk-S5NZBKKQ.js.map} +0 -0
  727. /package/dist/{chunk-WIPEXG6R.js.map → chunk-SXIMQLGV.js.map} +0 -0
  728. /package/dist/{chunk-OAEQLRCY.js.map → chunk-TN76AKO3.js.map} +0 -0
  729. /package/dist/{chunk-QN25OCUF.js.map → chunk-TQ4GD737.js.map} +0 -0
  730. /package/dist/{chunk-7K5Q6COX.js.map → chunk-TVVEYCNW.js.map} +0 -0
  731. /package/dist/{chunk-DNWXFTLD.js.map → chunk-TYISDI6B.js.map} +0 -0
  732. /package/dist/{chunk-4LMA77JH.js.map → chunk-U2VLVBBH.js.map} +0 -0
  733. /package/dist/{chunk-5ZE7QHTK.js.map → chunk-ULVR5KG7.js.map} +0 -0
  734. /package/dist/{chunk-4B77XSG5.js.map → chunk-UV72DEZD.js.map} +0 -0
  735. /package/dist/{chunk-S2BBISHU.js.map → chunk-VANZKHTN.js.map} +0 -0
  736. /package/dist/{chunk-3Y224NYC.js.map → chunk-VYISFWVX.js.map} +0 -0
  737. /package/dist/{chunk-TIHMZFIV.js.map → chunk-W3IC7QOY.js.map} +0 -0
  738. /package/dist/{chunk-NRV4Y3PM.js.map → chunk-W4FBGYGK.js.map} +0 -0
  739. /package/dist/{chunk-MU7ZHSZE.js.map → chunk-WZFAPHIK.js.map} +0 -0
  740. /package/dist/{chunk-T2TTP3KU.js.map → chunk-X4IDNPOS.js.map} +0 -0
  741. /package/dist/{chunk-BLAKS3CP.js.map → chunk-XL3TATMJ.js.map} +0 -0
  742. /package/dist/{chunk-W4XJFLAL.js.map → chunk-XPRJSHNI.js.map} +0 -0
  743. /package/dist/{chunk-JE7EK33X.js.map → chunk-Y7HRYCNW.js.map} +0 -0
  744. /package/dist/{chunk-E6EE5B67.js.map → chunk-YK6BDDHP.js.map} +0 -0
  745. /package/dist/{chunk-ES36HTSC.js.map → chunk-YLHM5BQQ.js.map} +0 -0
  746. /package/dist/{chunk-BJKPPZ6Z.js.map → chunk-ZFGZ6PZ2.js.map} +0 -0
  747. /package/dist/{chunk-64UDOIMI.js.map → chunk-ZLQ37WJX.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/external-wiki-search.ts"],"sourcesContent":["import path from \"node:path\";\nimport type { CitationEntry } from \"./citations.js\";\nimport {\n type ExternalWikiCatalogEntry,\n type ExternalWikiRoot,\n loadExternalWikiCatalog,\n readExternalWikiPage,\n} from \"./external-wiki.js\";\n\nexport type { ExternalWikiRoot } from \"./external-wiki.js\";\n\nconst DEFAULT_LIMIT = 6;\nconst MAX_LIMIT = 20;\nconst DEFAULT_MAX_CHARS_PER_HIT = 1_000;\nconst MAX_CHARS_PER_HIT = 8_000;\nconst DEFAULT_MAX_CANDIDATE_FILES = 100;\nconst MAX_CANDIDATE_FILES = 100;\n\nexport interface ExternalWikiSearchInput {\n readonly query: string;\n readonly limit?: number;\n readonly wikiId?: string;\n readonly maxCharsPerHit?: number;\n}\n\ninterface ExternalWikiSnippet {\n readonly text: string;\n readonly lineStart: number;\n readonly lineEnd: number;\n}\n\nexport interface ExternalWikiSearchHit {\n readonly wikiId: string;\n readonly title: string;\n readonly path: string;\n readonly snippet: string;\n readonly score: number;\n readonly rank: number;\n readonly citations: readonly CitationEntry[];\n readonly indexBlurb?: string;\n}\n\nexport interface ExternalWikiSearchResult {\n readonly query: string;\n readonly hits: readonly ExternalWikiSearchHit[];\n readonly count: number;\n readonly degradedWikiIds: readonly string[];\n}\n\nexport interface ExternalWikiCandidate {\n readonly path: string;\n readonly score?: number;\n}\n\nexport interface ExternalWikiCandidateProvider {\n search(root: ExternalWikiRoot, query: string, limit: number): Promise<readonly ExternalWikiCandidate[]>;\n}\n\nexport interface ExternalWikiSearchOptions {\n readonly candidateProvider?: ExternalWikiCandidateProvider;\n readonly maxCandidateFiles?: number;\n}\n\nexport class ExternalWikiSearchError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ExternalWikiSearchError\";\n }\n}\n\ninterface RankedCatalogEntry {\n readonly entry: ExternalWikiCatalogEntry;\n readonly catalogScore: number;\n readonly providerScore: number;\n readonly providerRank?: number;\n}\n\ninterface UnrankedHit extends Omit<ExternalWikiSearchHit, \"rank\"> {}\n\nexport async function searchExternalWikis(\n roots: readonly ExternalWikiRoot[],\n input: ExternalWikiSearchInput,\n options: ExternalWikiSearchOptions = {}\n): Promise<ExternalWikiSearchResult> {\n const query = requireQuery(input.query);\n const limit = boundedInteger(input.limit, DEFAULT_LIMIT, 1, MAX_LIMIT, \"limit\");\n const maxCharsPerHit = boundedInteger(\n input.maxCharsPerHit,\n DEFAULT_MAX_CHARS_PER_HIT,\n 1,\n MAX_CHARS_PER_HIT,\n \"maxCharsPerHit\"\n );\n const maxCandidateFiles = boundedInteger(\n options.maxCandidateFiles,\n DEFAULT_MAX_CANDIDATE_FILES,\n 1,\n MAX_CANDIDATE_FILES,\n \"maxCandidateFiles\"\n );\n const selectedRoots = selectRoots(roots, input.wikiId);\n const queryTokens = tokenize(query);\n const degradedWikiIds = new Set<string>();\n const perRootHits = await Promise.all(\n selectedRoots.map(async (root) => {\n try {\n const catalog = await loadExternalWikiCatalog(root, { maxEntries: maxCandidateFiles });\n if (!catalog.indexPresent) degradedWikiIds.add(root.id);\n const candidates = await rankCandidates(\n root,\n catalog.entries,\n query,\n queryTokens,\n maxCandidateFiles,\n options.candidateProvider\n );\n return await readCandidateHits(root, candidates, query, queryTokens, maxCharsPerHit);\n } catch {\n degradedWikiIds.add(root.id);\n return [];\n }\n })\n );\n\n const hits = perRootHits\n .flat()\n .sort(compareHits)\n .slice(0, limit)\n .map((hit, index): ExternalWikiSearchHit => ({ ...hit, rank: index + 1 }));\n\n return {\n query,\n hits,\n count: hits.length,\n degradedWikiIds: [...degradedWikiIds].sort(),\n };\n}\n\nfunction requireQuery(value: string): string {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new ExternalWikiSearchError(\"external wiki search query is required\");\n }\n return value.trim();\n}\n\nfunction boundedInteger(\n value: number | undefined,\n fallback: number,\n minimum: number,\n maximum: number,\n field: string\n): number {\n const resolved = value ?? fallback;\n if (!Number.isInteger(resolved) || resolved < minimum || resolved > maximum) {\n throw new ExternalWikiSearchError(`${field} must be an integer from ${minimum} to ${maximum}`);\n }\n return resolved;\n}\n\nfunction selectRoots(roots: readonly ExternalWikiRoot[], wikiId: string | undefined): ExternalWikiRoot[] {\n const enabled = roots.filter((root) => root.enabled);\n if (enabled.length === 0) {\n throw new ExternalWikiSearchError(\"no enabled external wiki roots are configured\");\n }\n if (wikiId === undefined) return enabled;\n const normalizedWikiId = wikiId.trim();\n const selected = enabled.find((root) => root.id === normalizedWikiId);\n if (!selected) {\n throw new ExternalWikiSearchError(`unknown external wiki: ${normalizedWikiId || \"(empty)\"}`);\n }\n return [selected];\n}\n\nasync function rankCandidates(\n root: ExternalWikiRoot,\n entries: readonly ExternalWikiCatalogEntry[],\n query: string,\n queryTokens: readonly string[],\n maxCandidateFiles: number,\n provider: ExternalWikiCandidateProvider | undefined\n): Promise<RankedCatalogEntry[]> {\n let provided: readonly ExternalWikiCandidate[] = [];\n if (provider) {\n try {\n provided = await provider.search(root, query, maxCandidateFiles);\n } catch {\n provided = [];\n }\n }\n\n const providerByPath = new Map<string, { score: number; rank: number }>();\n for (const [index, candidate] of provided.slice(0, maxCandidateFiles).entries()) {\n if (!providerByPath.has(candidate.path)) {\n providerByPath.set(candidate.path, { score: finiteScore(candidate.score), rank: index });\n }\n }\n\n return entries\n .map((entry): RankedCatalogEntry => {\n const providerCandidate = providerByPath.get(entry.path);\n return {\n entry,\n catalogScore: scoreCatalogEntry(entry, query, queryTokens),\n providerScore: providerCandidate?.score ?? 0,\n ...(providerCandidate ? { providerRank: providerCandidate.rank } : {}),\n };\n })\n .sort((left, right) => {\n const leftProvided = left.providerRank !== undefined;\n const rightProvided = right.providerRank !== undefined;\n if (leftProvided !== rightProvided) return leftProvided ? -1 : 1;\n if (left.providerRank !== right.providerRank) {\n return (left.providerRank ?? Number.MAX_SAFE_INTEGER) - (right.providerRank ?? Number.MAX_SAFE_INTEGER);\n }\n if (right.catalogScore !== left.catalogScore) return right.catalogScore - left.catalogScore;\n return left.entry.path.localeCompare(right.entry.path);\n })\n .slice(0, maxCandidateFiles);\n}\n\nasync function readCandidateHits(\n root: ExternalWikiRoot,\n candidates: readonly RankedCatalogEntry[],\n query: string,\n queryTokens: readonly string[],\n maxCharsPerHit: number\n): Promise<UnrankedHit[]> {\n const results = await Promise.all(\n candidates.map(async (candidate): Promise<UnrankedHit | undefined> => {\n try {\n const page = await readExternalWikiPage(root, candidate.entry.path);\n const pageScore = scorePage(page.title, page.content, query, queryTokens);\n const score = candidate.catalogScore + candidate.providerScore + pageScore;\n if (score <= 0) return undefined;\n const snippet = extractSnippet(page.content, queryTokens, maxCharsPerHit);\n const rootRelativePath = path.posix.join(root.pagesDir.replaceAll(\"\\\\\", \"/\"), page.path);\n const citation: CitationEntry = {\n path: rootRelativePath,\n lineStart: snippet.lineStart,\n lineEnd: snippet.lineEnd,\n note: page.title,\n };\n return {\n wikiId: root.id,\n title: page.title,\n path: rootRelativePath,\n snippet: snippet.text,\n score: roundScore(score),\n citations: [citation],\n ...(candidate.entry.indexBlurb === undefined ? {} : { indexBlurb: candidate.entry.indexBlurb }),\n };\n } catch {\n return undefined;\n }\n })\n );\n return results.filter((result): result is UnrankedHit => result !== undefined);\n}\n\nfunction scoreCatalogEntry(entry: ExternalWikiCatalogEntry, query: string, queryTokens: readonly string[]): number {\n return (\n scoreText(entry.title, query, queryTokens, 16, 20) +\n scoreText(entry.path, query, queryTokens, 8, 8) +\n scoreText(entry.indexBlurb ?? \"\", query, queryTokens, 4, 6)\n );\n}\n\nfunction scorePage(title: string, content: string, query: string, queryTokens: readonly string[]): number {\n const titleScore = scoreText(title, query, queryTokens, 12, 16);\n const lines = content.split(/\\r?\\n/u);\n let bestLineScore = 0;\n const matchedTokens = new Set<string>();\n for (const line of lines) {\n const normalizedLine = line.toLocaleLowerCase();\n let lineScore = 0;\n for (const token of queryTokens) {\n if (!normalizedLine.includes(token)) continue;\n matchedTokens.add(token);\n lineScore += line.startsWith(\"#\") ? 6 : 3;\n }\n if (normalizedLine.includes(query.toLocaleLowerCase())) lineScore += 10;\n bestLineScore = Math.max(bestLineScore, lineScore);\n }\n return titleScore + bestLineScore + matchedTokens.size * 2;\n}\n\nfunction scoreText(\n value: string,\n query: string,\n queryTokens: readonly string[],\n tokenWeight: number,\n phraseWeight: number\n): number {\n const normalized = value.toLocaleLowerCase();\n let score = normalized.includes(query.toLocaleLowerCase()) ? phraseWeight : 0;\n for (const token of queryTokens) {\n if (normalized.includes(token)) score += tokenWeight;\n }\n return score;\n}\n\nfunction tokenize(value: string): string[] {\n const tokens = value.toLocaleLowerCase().match(/[\\p{L}\\p{N}]+/gu) ?? [];\n return [...new Set(tokens)];\n}\n\nfunction extractSnippet(content: string, queryTokens: readonly string[], maxChars: number): ExternalWikiSnippet {\n const lines = content.split(/\\r?\\n/u);\n if (lines.length === 0) return { text: \"\", lineStart: 1, lineEnd: 1 };\n let bestIndex = 0;\n let bestScore = -1;\n for (const [index, line] of lines.entries()) {\n const normalized = line.toLocaleLowerCase();\n const matchCount = queryTokens.reduce((sum, token) => sum + (normalized.includes(token) ? 1 : 0), 0);\n const score = matchCount * 2 + (matchCount > 0 && !/^#{1,6}\\s/u.test(line) ? 1 : 0);\n if (score > bestScore) {\n bestScore = score;\n bestIndex = index;\n }\n }\n\n let headingIndex = bestIndex;\n while (headingIndex > 0 && !/^#{1,6}\\s/u.test(lines[headingIndex] ?? \"\")) headingIndex -= 1;\n const bodyStart = Math.max(0, bestIndex - 1);\n const endExclusive = Math.min(lines.length, bestIndex + 3);\n const start = headingIndex < bodyStart ? headingIndex : bodyStart;\n const selected =\n headingIndex < bodyStart\n ? [lines[headingIndex] ?? \"\", ...lines.slice(bodyStart, endExclusive)]\n : lines.slice(start, endExclusive);\n const snippet = selected.join(\"\\n\").trim();\n if (snippet.length <= maxChars) {\n return { text: snippet, lineStart: start + 1, lineEnd: endExclusive };\n }\n\n const normalizedSnippet = snippet.toLocaleLowerCase();\n const firstMatch =\n queryTokens\n .map((token) => normalizedSnippet.indexOf(token))\n .filter((index) => index >= 0)\n .sort((left, right) => left - right)[0] ?? 0;\n const windowStart = Math.max(0, Math.min(firstMatch - Math.floor(maxChars / 3), snippet.length - maxChars));\n return {\n text: snippet.slice(windowStart, windowStart + maxChars).trim(),\n lineStart: start + 1,\n lineEnd: endExclusive,\n };\n}\n\nfunction finiteScore(score: number | undefined): number {\n return typeof score === \"number\" && Number.isFinite(score) ? Math.max(0, score) : 0;\n}\n\nfunction roundScore(score: number): number {\n return Math.round(score * 1_000) / 1_000;\n}\n\nfunction compareHits(left: UnrankedHit, right: UnrankedHit): number {\n if (right.score !== left.score) return right.score - left.score;\n const wikiComparison = left.wikiId.localeCompare(right.wikiId);\n return wikiComparison !== 0 ? wikiComparison : left.path.localeCompare(right.path);\n}\n"],"mappings":"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","names":[]}
@@ -1,3 +1,7 @@
1
+ import {
2
+ searchConversationIndex,
3
+ searchConversationIndexFaissFailOpen
4
+ } from "./chunk-A7Q43EUZ.js";
1
5
  import {
2
6
  failOpenFaissHealth
3
7
  } from "./chunk-ET356KSB.js";
@@ -5,10 +9,6 @@ import {
5
9
  rebuildConversationChunksFailOpen,
6
10
  upsertConversationChunksFailOpen
7
11
  } from "./chunk-72A4L5JJ.js";
8
- import {
9
- searchConversationIndex,
10
- searchConversationIndexFaissFailOpen
11
- } from "./chunk-A7Q43EUZ.js";
12
12
 
13
13
  // src/conversation-index/backend.ts
14
14
  function createConversationIndexBackend(options) {
@@ -235,4 +235,4 @@ function createFaissBackend(getFaiss) {
235
235
  export {
236
236
  createConversationIndexBackend
237
237
  };
238
- //# sourceMappingURL=chunk-227UFSEQ.js.map
238
+ //# sourceMappingURL=chunk-7RZJWZ46.js.map
@@ -1,10 +1,10 @@
1
- import {
2
- getConfiguredNamespaces
3
- } from "./chunk-ULARSG5Z.js";
4
1
  import {
5
2
  resolveDefaultNamespaceRoot,
6
3
  resolveNamespaceStorageRoot
7
- } from "./chunk-LZ4LDKHZ.js";
4
+ } from "./chunk-CLB32OHM.js";
5
+ import {
6
+ getConfiguredNamespaces
7
+ } from "./chunk-YN6ASZUG.js";
8
8
  import {
9
9
  namespaceIdentityFromToken,
10
10
  namespaceIdentityToken,
@@ -2204,4 +2204,4 @@ export {
2204
2204
  runNamespaceMaintenancePlan,
2205
2205
  runNamespaceMaintenanceBatchPlan
2206
2206
  };
2207
- //# sourceMappingURL=chunk-E5UK4VPE.js.map
2207
+ //# sourceMappingURL=chunk-7SHJHPTY.js.map
@@ -3,7 +3,7 @@ import {
3
3
  readNamespaceMaintenanceLastRanStatuses,
4
4
  readNamespaceMaintenanceStatuses,
5
5
  runNamespaceMaintenancePlan
6
- } from "./chunk-E5UK4VPE.js";
6
+ } from "./chunk-7SHJHPTY.js";
7
7
  import {
8
8
  analyzeSessionIntegrity,
9
9
  applySessionRepair,
@@ -14,7 +14,7 @@ import {
14
14
  } from "./chunk-CMTINOFS.js";
15
15
  import {
16
16
  summarizeCorpusAndReplica
17
- } from "./chunk-VUPTKTDV.js";
17
+ } from "./chunk-2MRHJNWL.js";
18
18
  import {
19
19
  readJudgeVerdictStats
20
20
  } from "./chunk-OZKOPQCM.js";
@@ -25,49 +25,45 @@ import {
25
25
  runEvalBenchmarkCiGate,
26
26
  validateEvalBenchmarkPack
27
27
  } from "./chunk-3PY7VHV7.js";
28
+ import {
29
+ runConsolidationProvenanceCheck
30
+ } from "./chunk-HAYSYUAB.js";
28
31
  import {
29
32
  resolveCuratedIncludeFilesStatePath,
30
33
  resolveNativeKnowledgeStatePath,
31
34
  resolveOpenClawWorkspaceStatePath
32
35
  } from "./chunk-2DQ2XREU.js";
33
- import {
34
- runConsolidationProvenanceCheck
35
- } from "./chunk-TSH56VPU.js";
36
36
  import {
37
37
  reportBufferSurpriseDistribution
38
38
  } from "./chunk-YBPYIAA5.js";
39
39
  import {
40
40
  parseConfig
41
- } from "./chunk-CUM2BBPN.js";
41
+ } from "./chunk-AUMWZSE7.js";
42
42
  import {
43
43
  readAggregateExtractionWatermark
44
- } from "./chunk-D3J5SLQK.js";
44
+ } from "./chunk-EJHEWCGQ.js";
45
45
  import {
46
46
  listMemoryGovernanceRuns,
47
47
  readMemoryGovernanceRunArtifact
48
- } from "./chunk-PDLBLTOK.js";
48
+ } from "./chunk-EITZHSX6.js";
49
49
  import {
50
50
  listNamespaces
51
- } from "./chunk-E53DSZEN.js";
51
+ } from "./chunk-C26TE27X.js";
52
52
  import {
53
53
  analyzeGraphHealth
54
54
  } from "./chunk-L2DPF4DF.js";
55
55
  import {
56
56
  StorageManager
57
- } from "./chunk-E6PNLPGJ.js";
57
+ } from "./chunk-FZP32336.js";
58
58
  import {
59
59
  lintWorkspaceFiles
60
60
  } from "./chunk-DM2T26WE.js";
61
- import {
62
- probeProjectionHealth
63
- } from "./chunk-3CSX3ETE.js";
64
61
  import {
65
62
  summarizeExtractionLiveness
66
63
  } from "./chunk-3SG4FGDV.js";
67
64
  import {
68
- readEnvVar,
69
- resolveHomeDir
70
- } from "./chunk-JUC24CTX.js";
65
+ probeProjectionHealth
66
+ } from "./chunk-3CSX3ETE.js";
71
67
  import {
72
68
  resolveAccessSetupCapabilities,
73
69
  resolveCapabilities,
@@ -79,6 +75,10 @@ import {
79
75
  resolvePresentationCapabilities,
80
76
  resolveQmdCapabilities
81
77
  } from "./chunk-2XRE6FLM.js";
78
+ import {
79
+ readEnvVar,
80
+ resolveHomeDir
81
+ } from "./chunk-JUC24CTX.js";
82
82
 
83
83
  // src/operator-toolkit.ts
84
84
  import path from "path";
@@ -1683,4 +1683,4 @@ export {
1683
1683
  runBenchmarkRecall,
1684
1684
  runOperatorRepair
1685
1685
  };
1686
- //# sourceMappingURL=chunk-UVIKWC7M.js.map
1686
+ //# sourceMappingURL=chunk-7YERSTN7.js.map
@@ -3,8 +3,9 @@ import {
3
3
  } from "./chunk-IJ7HK452.js";
4
4
  import {
5
5
  pathMayCarryEntityRefs,
6
- requestEntityCanonicalIdReconcile
7
- } from "./chunk-4J7G5SY4.js";
6
+ requestEntityCanonicalIdReconcile,
7
+ withRawEntityPageMutation
8
+ } from "./chunk-NZBZ7IS2.js";
8
9
  import {
9
10
  ALL_CATEGORY_DIRS,
10
11
  RECALL_FALLBACK_DIRS
@@ -170,10 +171,11 @@ async function revertToVersion(pagePath, versionId, config, log = NOOP_LOGGER, m
170
171
  `reverted to version ${versionId}`,
171
172
  resolvedMemoryDir
172
173
  );
173
- await writeFile(pagePath, targetContent, "utf-8");
174
+ await withRawEntityPageMutation(resolvedMemoryDir, pagePath, async () => {
175
+ await writeFile(pagePath, targetContent, "utf-8");
176
+ });
174
177
  const revertedTop = relPath(pagePath, resolvedMemoryDir).split(path.sep)[0];
175
- const inRecallTier = RECALL_FALLBACK_DIRS.includes(revertedTop);
176
- if (inRecallTier) {
178
+ if (RECALL_FALLBACK_DIRS.includes(revertedTop)) {
177
179
  bumpMemoryCorpusVersionForDir(resolvedMemoryDir);
178
180
  }
179
181
  if (pathMayCarryEntityRefs(resolvedMemoryDir, pagePath)) {
@@ -279,4 +281,4 @@ export {
279
281
  revertToVersion,
280
282
  diffVersions
281
283
  };
282
- //# sourceMappingURL=chunk-DLVPUX7U.js.map
284
+ //# sourceMappingURL=chunk-7YKVM5H3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/page-versioning.ts"],"sourcesContent":["/**\n * Page-level versioning with history and revert (issue #371).\n *\n * Provides snapshot-based versioning for memory files using a sidecar\n * directory layout. Each memory page gets a `.versions/<pageName>/`\n * subdirectory containing numbered snapshots and a `manifest.json` that\n * records the version history.\n *\n * Storage layout:\n * memoryDir/\n * facts/preferences.md <- current file\n * .versions/\n * facts__preferences/\n * manifest.json <- VersionHistory\n * 1.md <- version 1 snapshot\n * 2.md <- version 2 snapshot\n */\n\nimport { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport {\n access,\n mkdir,\n readFile,\n writeFile,\n unlink,\n} from \"node:fs/promises\";\nimport { ALL_CATEGORY_DIRS, RECALL_FALLBACK_DIRS } from \"./utils/category-dir.js\";\nimport { bumpMemoryCorpusVersionForDir } from \"./memory-corpus-version.js\";\nimport {\n pathMayCarryEntityRefs,\n requestEntityCanonicalIdReconcile,\n} from \"./storage/entity-canonical-id-references.js\";\nimport { withRawEntityPageMutation } from \"./storage/entity-canonical-id-lock.js\";\n\n// ---------------------------------------------------------------------------\n// Public interfaces\n// ---------------------------------------------------------------------------\n\nexport interface PageVersion {\n versionId: string;\n timestamp: string;\n contentHash: string;\n sizeBytes: number;\n trigger: VersionTrigger;\n note?: string;\n}\n\nexport type VersionTrigger = \"write\" | \"consolidation\" | \"revert\" | \"manual\";\n\nexport interface VersionHistory {\n pagePath: string;\n versions: PageVersion[];\n currentVersion: string;\n}\n\nexport interface VersioningConfig {\n enabled: boolean;\n maxVersionsPerPage: number;\n sidecarDir: string;\n}\n\n// ---------------------------------------------------------------------------\n// Logger interface (minimal, avoids coupling to the host logger)\n// ---------------------------------------------------------------------------\n\nexport interface VersioningLogger {\n debug(msg: string): void;\n warn(msg: string): void;\n}\n\nconst NOOP_LOGGER: VersioningLogger = {\n debug: () => {},\n warn: () => {},\n};\n\n// ---------------------------------------------------------------------------\n// Per-page write lock (promise-chain pattern, see gotcha #40)\n// ---------------------------------------------------------------------------\n\nconst writeLocks = new Map<string, Promise<void>>();\n\nfunction withPageLock<T>(pageKey: string, fn: () => Promise<T>): Promise<T> {\n const prev = writeLocks.get(pageKey) ?? Promise.resolve();\n const next = prev.then(fn, fn); // run fn after previous completes, even if previous failed\n writeLocks.set(pageKey, next.then(() => {}, () => {})); // recover chain per gotcha #40\n return next;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction contentHash(content: string): string {\n return createHash(\"sha256\").update(content, \"utf-8\").digest(\"hex\");\n}\n\n/**\n * Derive a filesystem-safe sidecar key from a page path relative to memoryDir.\n *\n * `facts/2026-01-15/pref-001.md` -> `facts__2026-01-15__pref-001`\n *\n * Exported so the `remnic doctor` consolidation-provenance check (issue\n * #561 PR 4) resolves snapshot locations using the canonical algorithm\n * without re-implementing it — preventing silent drift if the key\n * format ever changes.\n */\nexport function sidecarKey(pagePath: string): string {\n const withoutExt = pagePath.replace(/\\.md$/i, \"\");\n return withoutExt.replace(/[\\\\/]/g, \"__\");\n}\n\nfunction sidecarDir(memoryDir: string, sidecar: string, pagePath: string): string {\n return path.join(memoryDir, sidecar, sidecarKey(pagePath));\n}\n\nfunction manifestPath(memoryDir: string, sidecar: string, pagePath: string): string {\n return path.join(sidecarDir(memoryDir, sidecar, pagePath), \"manifest.json\");\n}\n\nasync function fileExists(p: string): Promise<boolean> {\n try {\n await access(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readManifest(\n memoryDir: string,\n sidecar: string,\n pagePath: string,\n): Promise<VersionHistory> {\n const mp = manifestPath(memoryDir, sidecar, pagePath);\n if (!(await fileExists(mp))) {\n return { pagePath, versions: [], currentVersion: \"0\" };\n }\n try {\n const raw = await readFile(mp, \"utf-8\");\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null) {\n throw new Error(\"manifest root must be an object\");\n }\n const obj = parsed as Record<string, unknown>;\n if (!Array.isArray(obj.versions)) {\n throw new Error(\"manifest versions must be an array\");\n }\n const versions = obj.versions.map((entry, index) => {\n if (!entry || typeof entry !== \"object\" || Array.isArray(entry)) {\n throw new Error(`manifest version ${index} must be an object`);\n }\n const version = entry as Record<string, unknown>;\n if (\n typeof version.versionId !== \"string\" ||\n !/^\\d+$/.test(version.versionId) ||\n typeof version.timestamp !== \"string\" ||\n typeof version.contentHash !== \"string\" ||\n typeof version.sizeBytes !== \"number\" ||\n !Number.isFinite(version.sizeBytes) ||\n ![\"write\", \"consolidation\", \"revert\", \"manual\"].includes(String(version.trigger))\n ) {\n throw new Error(`manifest version ${index} has invalid shape`);\n }\n return version as unknown as PageVersion;\n });\n if (typeof obj.currentVersion !== \"string\" || !/^\\d+$/.test(obj.currentVersion)) {\n throw new Error(\"manifest currentVersion must be a numeric string\");\n }\n const currentVersion = obj.currentVersion;\n return { pagePath: typeof obj.pagePath === \"string\" ? obj.pagePath : pagePath, versions, currentVersion };\n } catch (error) {\n throw new Error(`page-versioning: invalid manifest ${mp}: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\nasync function writeManifest(\n memoryDir: string,\n sidecar: string,\n pagePath: string,\n history: VersionHistory,\n): Promise<void> {\n const dir = sidecarDir(memoryDir, sidecar, pagePath);\n await mkdir(dir, { recursive: true });\n const mp = manifestPath(memoryDir, sidecar, pagePath);\n await writeFile(mp, JSON.stringify(history, null, 2) + \"\\n\", \"utf-8\");\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a new version snapshot for a page.\n *\n * Call this BEFORE overwriting the current file so the previous content is\n * preserved. If the file does not exist yet (first write), the provided\n * `content` is snapshotted as version 1.\n *\n * Pruning: when the number of versions exceeds `config.maxVersionsPerPage`,\n * the oldest snapshots (and their files) are removed.\n */\nexport async function createVersion(\n pagePath: string,\n content: string,\n trigger: VersionTrigger,\n config: VersioningConfig,\n log: VersioningLogger = NOOP_LOGGER,\n note?: string,\n memoryDir?: string,\n): Promise<PageVersion> {\n const { sidecarDir: sidecar, maxVersionsPerPage } = config;\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n const mPath = manifestPath(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir));\n\n return withPageLock(mPath, async () => {\n const history = await readManifest(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir));\n const nextId = String(history.versions.length > 0\n ? Math.max(...history.versions.map((v) => Number(v.versionId))) + 1\n : 1);\n\n const hash = contentHash(content);\n const version: PageVersion = {\n versionId: nextId,\n timestamp: new Date().toISOString(),\n contentHash: hash,\n sizeBytes: Buffer.byteLength(content, \"utf-8\"),\n trigger,\n ...(note !== undefined ? { note } : {}),\n };\n\n // Write snapshot file\n const dir = sidecarDir(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir));\n await mkdir(dir, { recursive: true });\n const ext = path.extname(pagePath) || \".md\";\n const snapshotPath = path.join(dir, `${nextId}${ext}`);\n await writeFile(snapshotPath, content, \"utf-8\");\n\n history.versions.push(version);\n history.currentVersion = nextId;\n\n // Prune old versions if exceeding max\n if (maxVersionsPerPage > 0 && history.versions.length > maxVersionsPerPage) {\n const toRemove = history.versions.splice(0, history.versions.length - maxVersionsPerPage);\n for (const old of toRemove) {\n const oldPath = path.join(dir, `${old.versionId}${ext}`);\n try {\n await unlink(oldPath);\n } catch {\n log.debug(`page-versioning: could not remove old snapshot ${oldPath}`);\n }\n }\n }\n\n await writeManifest(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir), history);\n log.debug(`page-versioning: created version ${nextId} for ${pagePath} (trigger=${trigger})`);\n\n return version;\n });\n}\n\n/**\n * List all versions for a page.\n */\nexport async function listVersions(\n pagePath: string,\n config: VersioningConfig,\n memoryDir?: string,\n): Promise<VersionHistory> {\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n const rel = relPath(pagePath, resolvedMemoryDir);\n const history = await readManifest(resolvedMemoryDir, config.sidecarDir, rel);\n // Sort ascending by versionId (numeric)\n history.versions.sort((a, b) => Number(a.versionId) - Number(b.versionId));\n return history;\n}\n\n/**\n * Read the content of a specific version.\n */\nexport async function getVersion(\n pagePath: string,\n versionId: string,\n config: VersioningConfig,\n memoryDir?: string,\n): Promise<string> {\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n const rel = relPath(pagePath, resolvedMemoryDir);\n const ext = path.extname(pagePath) || \".md\";\n const dir = sidecarDir(resolvedMemoryDir, config.sidecarDir, rel);\n const snapshotPath = path.join(dir, `${versionId}${ext}`);\n\n if (!(await fileExists(snapshotPath))) {\n throw new Error(`Version ${versionId} not found for ${pagePath}`);\n }\n\n return readFile(snapshotPath, \"utf-8\");\n}\n\n/**\n * Revert a page to a previous version.\n *\n * 1. Reads the target version's content.\n * 2. Snapshots the CURRENT content as a new version (trigger: \"revert\").\n * 3. Writes the reverted content to the page file.\n *\n * Returns the newly created version entry for the revert snapshot.\n */\nexport async function revertToVersion(\n pagePath: string,\n versionId: string,\n config: VersioningConfig,\n log: VersioningLogger = NOOP_LOGGER,\n memoryDir?: string,\n): Promise<PageVersion> {\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n\n // Read target version content\n const targetContent = await getVersion(pagePath, versionId, config, resolvedMemoryDir);\n\n // Snapshot current content before overwriting\n let currentContent = \"\";\n try {\n currentContent = await readFile(pagePath, \"utf-8\");\n } catch {\n // File may not exist; that's okay\n }\n\n const version = await createVersion(\n pagePath,\n currentContent,\n \"revert\",\n config,\n log,\n `reverted to version ${versionId}`,\n resolvedMemoryDir,\n );\n\n await withRawEntityPageMutation(resolvedMemoryDir, pagePath, async () => {\n await writeFile(pagePath, targetContent, \"utf-8\");\n });\n const revertedTop = relPath(pagePath, resolvedMemoryDir).split(path.sep)[0];\n if ((RECALL_FALLBACK_DIRS as readonly string[]).includes(revertedTop)) {\n bumpMemoryCorpusVersionForDir(resolvedMemoryDir);\n }\n if (pathMayCarryEntityRefs(resolvedMemoryDir, pagePath)) {\n await requestEntityCanonicalIdReconcile(path.join(resolvedMemoryDir, \"state\"));\n }\n log.debug(`page-versioning: reverted ${pagePath} to version ${versionId}`);\n\n return version;\n}\n\n/**\n * Simple line-based diff between two versions.\n *\n * Returns a unified-style diff string showing added (+) and removed (-) lines.\n */\nexport async function diffVersions(\n pagePath: string,\n v1: string,\n v2: string,\n config: VersioningConfig,\n memoryDir?: string,\n): Promise<string> {\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n const content1 = await getVersion(pagePath, v1, config, resolvedMemoryDir);\n const content2 = await getVersion(pagePath, v2, config, resolvedMemoryDir);\n\n const lines1 = content1.split(\"\\n\");\n const lines2 = content2.split(\"\\n\");\n\n const result: string[] = [];\n result.push(`--- version ${v1}`);\n result.push(`+++ version ${v2}`);\n\n // Simple LCS-based diff\n const lcs = computeLCS(lines1, lines2);\n let i = 0;\n let j = 0;\n let k = 0;\n\n while (k < lcs.length) {\n // Emit removed lines before the next common line\n while (i < lines1.length && lines1[i] !== lcs[k]) {\n result.push(`-${lines1[i]}`);\n i++;\n }\n // Emit added lines before the next common line\n while (j < lines2.length && lines2[j] !== lcs[k]) {\n result.push(`+${lines2[j]}`);\n j++;\n }\n // Common line\n result.push(` ${lcs[k]}`);\n i++;\n j++;\n k++;\n }\n // Remaining removed lines\n while (i < lines1.length) {\n result.push(`-${lines1[i]}`);\n i++;\n }\n // Remaining added lines\n while (j < lines2.length) {\n result.push(`+${lines2[j]}`);\n j++;\n }\n\n return result.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// LCS helper for diffVersions\n// ---------------------------------------------------------------------------\n\nfunction computeLCS(a: string[], b: string[]): string[] {\n const m = a.length;\n const n = b.length;\n // Build DP table\n const dp: number[][] = Array.from({ length: m + 1 }, () => new Array<number>(n + 1).fill(0));\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n if (a[i - 1] === b[j - 1]) {\n dp[i][j] = dp[i - 1][j - 1] + 1;\n } else {\n dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);\n }\n }\n }\n // Backtrack to build LCS\n const result: string[] = [];\n let i = m;\n let j = n;\n while (i > 0 && j > 0) {\n if (a[i - 1] === b[j - 1]) {\n result.unshift(a[i - 1]);\n i--;\n j--;\n } else if (dp[i - 1][j] > dp[i][j - 1]) {\n i--;\n } else {\n j--;\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Path helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Legacy fallback: given an absolute page path, heuristically resolve the\n * memory directory by walking up past known subdirectory names.\n *\n * Callers should always pass an explicit `memoryDir` instead of relying on\n * this heuristic. It is retained only for backward compatibility when the\n * optional `memoryDir` parameter is omitted.\n */\nfunction resolveMemoryDir(pagePath: string): string {\n // Derive the recall category dirs from ALL_CATEGORY_DIRS (single source of\n // truth) so newly-routed categories (decisions/, preferences/, ...) are\n // recognized when walking up to the memory root (#1546); the non-category\n // subdirs are listed explicitly.\n const knownSubdirs = new Set<string>([\n ...ALL_CATEGORY_DIRS,\n \"entities\",\n \"state\",\n \"artifacts\",\n \"profiles\",\n ]);\n\n let dir = path.dirname(pagePath);\n // Walk up past date directories (YYYY-MM-DD) and known subdirs\n for (let depth = 0; depth < 5; depth++) {\n const base = path.basename(dir);\n if (knownSubdirs.has(base) || /^\\d{4}-\\d{2}-\\d{2}$/.test(base)) {\n dir = path.dirname(dir);\n } else {\n break;\n }\n }\n return dir;\n}\n\n/**\n * Compute relative path of a page within its memory directory.\n */\nfunction relPath(pagePath: string, memoryDir: string): string {\n return path.relative(memoryDir, pagePath);\n}\n"],"mappings":"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","names":["i","j"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createVersion
3
- } from "./chunk-DLVPUX7U.js";
3
+ } from "./chunk-7YKVM5H3.js";
4
4
  import {
5
5
  bumpMemoryCorpusVersionForDir
6
6
  } from "./chunk-IJ7HK452.js";
@@ -10,8 +10,9 @@ import {
10
10
  classifyEntityRefWritePath,
11
11
  readEntityRefFromFrontmatter,
12
12
  repairContentAfterJournalMove,
13
- requestEntityCanonicalIdReconcile
14
- } from "./chunk-4J7G5SY4.js";
13
+ requestEntityCanonicalIdReconcile,
14
+ withRawEntityPageMutation
15
+ } from "./chunk-NZBZ7IS2.js";
15
16
  import {
16
17
  parseExportBundle
17
18
  } from "./chunk-WEHSQBFR.js";
@@ -160,82 +161,94 @@ async function importCapsule(opts) {
160
161
  (a, b) => a.path.localeCompare(b.path)
161
162
  );
162
163
  let reconcileNeeded = false;
163
- for (const rec of sortedRecords) {
164
- const targetRel = computeTargetPath(rec.path, mode, capsule.id);
165
- const targetAbs = path.join(rootReal, fromPosixRelPath(targetRel));
166
- const exists = await fileExistsAt(targetAbs);
167
- if ((mode === "skip" || mode === "fork") && exists) {
168
- skipped.push({ path: rec.path, reason: "exists" });
169
- continue;
170
- }
171
- let snapshotted = false;
172
- if (mode === "overwrite" && exists) {
173
- if (opts.versioning && opts.versioning.enabled) {
174
- const prior = await readFile(targetAbs, "utf-8").catch(() => "");
175
- await createVersion(
176
- targetAbs,
177
- prior,
178
- "manual",
179
- opts.versioning,
180
- opts.log,
181
- `capsule-import: ${capsule.id}`,
182
- rootReal
183
- );
184
- snapshotted = true;
164
+ const applyRecords = async () => {
165
+ for (const rec of sortedRecords) {
166
+ const targetRel = computeTargetPath(rec.path, mode, capsule.id);
167
+ const targetAbs = path.join(rootReal, fromPosixRelPath(targetRel));
168
+ const exists = await fileExistsAt(targetAbs);
169
+ if ((mode === "skip" || mode === "fork") && exists) {
170
+ skipped.push({ path: rec.path, reason: "exists" });
171
+ continue;
185
172
  }
186
- }
187
- let contentToWrite = rec.content;
188
- let rewroteId = false;
189
- if (mode === "fork") {
190
- const forked = rewriteFrontmatterIdForFork(contentToWrite, capsule.id, opts.now);
191
- contentToWrite = forked.content;
192
- rewroteId = forked.rewrote;
193
- }
194
- await mkdir(path.dirname(targetAbs), { recursive: true });
195
- const targetKind = classifyEntityRefWritePath(rootReal, targetAbs);
196
- const rawRef = targetKind === "memory" ? readEntityRefFromFrontmatter(contentToWrite) : null;
197
- if (targetKind === "memory" && rawRef !== null && capsuleEntityIds.has(rawRef)) {
198
- await writeFile(targetAbs, contentToWrite, "utf-8");
199
- reconcileNeeded = true;
200
- } else if (targetKind === "memory") {
201
- const idsAtWrite = historicalIdCache.get(journalStateDir);
202
- const rawRecord = contentToWrite;
203
- contentToWrite = canonicalizeEntityRefFrontmatter(rawRecord, idsAtWrite);
204
- const originalBytes = await readFile(targetAbs, "utf-8").catch(() => null);
205
- await writeFile(targetAbs, contentToWrite, "utf-8");
206
- try {
207
- await repairContentAfterJournalMove({
208
- stateDir: journalStateDir,
209
- cache: historicalIdCache,
210
- idsAtWrite,
211
- rawContent: rawRecord,
212
- lastWritten: contentToWrite,
213
- rewrite: (content) => writeFile(targetAbs, content, "utf-8")
214
- });
215
- } catch (err) {
216
- if (originalBytes === null) {
217
- await unlink(targetAbs).catch(() => void 0);
218
- } else {
219
- await writeFile(targetAbs, originalBytes, "utf-8").catch(() => void 0);
173
+ let snapshotted = false;
174
+ if (mode === "overwrite" && exists) {
175
+ if (opts.versioning && opts.versioning.enabled) {
176
+ const prior = await readFile(targetAbs, "utf-8").catch(() => "");
177
+ await createVersion(
178
+ targetAbs,
179
+ prior,
180
+ "manual",
181
+ opts.versioning,
182
+ opts.log,
183
+ `capsule-import: ${capsule.id}`,
184
+ rootReal
185
+ );
186
+ snapshotted = true;
220
187
  }
221
- throw err;
222
188
  }
223
- } else {
224
- await writeFile(targetAbs, contentToWrite, "utf-8");
225
- if (targetKind === "entity") {
189
+ let contentToWrite = rec.content;
190
+ let rewroteId = false;
191
+ if (mode === "fork") {
192
+ const forked = rewriteFrontmatterIdForFork(contentToWrite, capsule.id, opts.now);
193
+ contentToWrite = forked.content;
194
+ rewroteId = forked.rewrote;
195
+ }
196
+ await mkdir(path.dirname(targetAbs), { recursive: true });
197
+ const targetKind = classifyEntityRefWritePath(rootReal, targetAbs);
198
+ const rawRef = targetKind === "memory" ? readEntityRefFromFrontmatter(contentToWrite) : null;
199
+ if (targetKind === "memory" && rawRef !== null && capsuleEntityIds.has(rawRef)) {
200
+ await writeFile(targetAbs, contentToWrite, "utf-8");
226
201
  reconcileNeeded = true;
202
+ } else if (targetKind === "memory") {
203
+ const idsAtWrite = historicalIdCache.get(journalStateDir);
204
+ const rawRecord = contentToWrite;
205
+ contentToWrite = canonicalizeEntityRefFrontmatter(rawRecord, idsAtWrite);
206
+ const originalBytes = await readFile(targetAbs, "utf-8").catch(() => null);
207
+ await writeFile(targetAbs, contentToWrite, "utf-8");
208
+ try {
209
+ await repairContentAfterJournalMove({
210
+ stateDir: journalStateDir,
211
+ cache: historicalIdCache,
212
+ idsAtWrite,
213
+ rawContent: rawRecord,
214
+ lastWritten: contentToWrite,
215
+ rewrite: (content) => writeFile(targetAbs, content, "utf-8")
216
+ });
217
+ } catch (err) {
218
+ if (originalBytes === null) {
219
+ await unlink(targetAbs).catch(() => void 0);
220
+ } else {
221
+ await writeFile(targetAbs, originalBytes, "utf-8").catch(() => void 0);
222
+ }
223
+ throw err;
224
+ }
225
+ } else {
226
+ await writeFile(targetAbs, contentToWrite, "utf-8");
227
+ if (targetKind === "entity") {
228
+ reconcileNeeded = true;
229
+ }
227
230
  }
231
+ bumpMemoryCorpusVersionForDir(rootReal);
232
+ imported.push({
233
+ sourcePath: rec.path,
234
+ targetPath: targetRel,
235
+ snapshotted,
236
+ rewroteId
237
+ });
228
238
  }
229
- bumpMemoryCorpusVersionForDir(rootReal);
230
- imported.push({
231
- sourcePath: rec.path,
232
- targetPath: targetRel,
233
- snapshotted,
234
- rewroteId
235
- });
236
- }
237
- if (reconcileNeeded) {
238
- await requestEntityCanonicalIdReconcile(journalStateDir);
239
+ if (reconcileNeeded) {
240
+ await requestEntityCanonicalIdReconcile(journalStateDir);
241
+ }
242
+ };
243
+ const firstEntityId = capsuleEntityIds.values().next().value;
244
+ if (firstEntityId === void 0) {
245
+ await applyRecords();
246
+ } else {
247
+ await withRawEntityPageMutation(
248
+ rootReal,
249
+ path.join(rootReal, "entities", `${firstEntityId}.md`),
250
+ applyRecords
251
+ );
239
252
  }
240
253
  skipped.sort((a, b) => a.path.localeCompare(b.path));
241
254
  return { imported, skipped, manifest };
@@ -281,4 +294,4 @@ function mintForkId(capsuleId, originalId, now) {
281
294
  export {
282
295
  importCapsule
283
296
  };
284
- //# sourceMappingURL=chunk-3CE77VAP.js.map
297
+ //# sourceMappingURL=chunk-A4JMGKCD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/transfer/capsule-import.ts"],"sourcesContent":["import { lstat, mkdir, readFile, realpath, stat, unlink, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { gunzipSync } from \"node:zlib\";\nimport { bumpMemoryCorpusVersionForDir } from \"../memory-corpus-version.js\";\nimport {\n HistoricalEntityCanonicalIdCache,\n readEntityRefFromFrontmatter,\n canonicalizeEntityRefFrontmatter,\n classifyEntityRefWritePath,\n repairContentAfterJournalMove,\n requestEntityCanonicalIdReconcile,\n} from \"../storage/entity-canonical-id-references.js\";\nimport { withRawEntityPageMutation } from \"../storage/entity-canonical-id-lock.js\";\nimport {\n createVersion,\n type VersioningConfig,\n type VersioningLogger,\n} from \"../page-versioning.js\";\nimport {\n assertIsDirectoryNotSymlink,\n assertRealpathInsideRoot,\n fromPosixRelPath,\n isPathInsideRoot,\n sha256String,\n} from \"./fs-utils.js\";\nimport {\n parseExportBundle,\n type CapsuleBlock,\n type ExportManifestV2,\n type ExportMemoryRecordV1,\n} from \"./types.js\";\nimport { isEncryptedCapsuleFile, decryptCapsuleFileInMemory } from \"./capsule-crypto.js\";\n\n/**\n * Conflict-resolution mode for {@link importCapsule}. Inverse of the\n * `mode` selector in PR 4/6's CLI surface.\n *\n * - `\"skip\"` (default) — when a target file already exists at the same\n * relative path, leave it untouched. The corresponding record is reported\n * via {@link ImportCapsuleResult.skipped}.\n * - `\"overwrite\"` — when a target file exists, snapshot the prior content\n * via {@link createVersion} (gotcha #54: write-before-delete; gotcha #25:\n * don't destroy old state until new state is confirmed), then write the\n * incoming content. The snapshot's `note` includes the source capsule id.\n * - `\"fork\"` — never overwrite. Every record is rebased under\n * `forks/<capsule-id>/<original-path>` and any YAML-frontmatter `id:`\n * field is rewritten to a new fork-scoped value. The original tree is\n * not touched.\n *\n * The mode is selected once per call and applied uniformly to every record\n * in the bundle. Mixed-mode imports are not supported by design — that\n * would let a single corrupted manifest silently land partial state.\n */\nexport type ImportCapsuleMode = \"skip\" | \"overwrite\" | \"fork\";\n\n/**\n * Options accepted by {@link importCapsule}.\n *\n * `archivePath` — absolute or cwd-relative path to a `.capsule.json.gz`\n * archive produced by `exportCapsule`. The archive must contain a V2\n * bundle (`schemaVersion: 2`); V1 archives are rejected.\n *\n * `root` — absolute or cwd-relative path to the memory directory that\n * will receive the records. Must be an existing directory.\n *\n * `mode` — see {@link ImportCapsuleMode}. Defaults to `\"skip\"`.\n *\n * `versioning` — optional page-versioning config used by `mode: \"overwrite\"`\n * to snapshot prior content before replacing it. Snapshots are skipped when\n * not provided or when `enabled === false`. Tests pass an enabled config\n * to assert snapshot creation; production callers thread the\n * orchestrator's resolved versioning config.\n *\n * `log` — optional logger forwarded to {@link createVersion}.\n *\n * `now` — optional clock override (ms epoch) used to derive deterministic\n * fork ids in tests. Production callers omit this.\n */\nexport interface ImportCapsuleOptions {\n archivePath: string;\n root: string;\n mode?: ImportCapsuleMode;\n versioning?: VersioningConfig;\n log?: VersioningLogger;\n now?: number;\n /**\n * Memory directory whose secure-store keyring is used when the archive is\n * encrypted. Required when `archivePath` ends with `.enc` or when the file\n * starts with the REMNIC-ENC magic header. If `memoryDir` is omitted and the\n * archive turns out to be encrypted, `importCapsule` throws a clear error\n * rather than silently failing.\n *\n * When provided and the archive is NOT encrypted, the value is ignored.\n */\n memoryDir?: string;\n /**\n * Original secure-store passphrase for encrypted format-v2 archives. When\n * supplied, the importer derives the archive key from the embedded KDF\n * header, enabling restore without the source machine's unlocked keyring.\n */\n passphrase?: string;\n}\n\nexport interface ImportCapsuleSkippedRecord {\n /** Original record path (capsule-relative, posix). */\n path: string;\n /**\n * Why this record was not written.\n *\n * `\"exists\"` — the target path already existed and the mode was `\"skip\"`,\n * OR the computed fork path already existed in fork mode.\n *\n * `\"checksum_mismatch\"` is intentionally absent: a checksum failure aborts\n * the import entirely (fail-closed) rather than skipping the offending\n * record, so no `ImportCapsuleSkippedRecord` is ever produced for it.\n */\n reason: \"exists\";\n}\n\nexport interface ImportCapsuleImportedRecord {\n /** Capsule-relative posix path the record carried. */\n sourcePath: string;\n /** Memory-dir-relative posix path the file was written to. */\n targetPath: string;\n /** Whether a prior version snapshot was taken (overwrite-mode only). */\n snapshotted: boolean;\n /** Whether the frontmatter `id:` field was rewritten (fork-mode only). */\n rewroteId: boolean;\n}\n\nexport interface ImportCapsuleResult {\n /** Records that landed on disk. */\n imported: ImportCapsuleImportedRecord[];\n /** Records that were not written. */\n skipped: ImportCapsuleSkippedRecord[];\n /** The manifest decoded from the archive. */\n manifest: ExportManifestV2;\n}\n\n/**\n * Pure async function that imports a capsule archive into a memory\n * directory. Inverse of {@link import(\"./capsule-export.js\").exportCapsule}.\n *\n * Sequence:\n * 1. Read + gunzip + JSON.parse the archive.\n * 2. Validate the bundle through `parseExportBundle` (V1 rejected).\n * 3. Verify each record's content sha256 against the manifest entry.\n * Any mismatch aborts the import BEFORE any file is written —\n * partial-write recovery would require a full rollback we cannot\n * offer cheaply, so we fail closed (gotcha #25).\n * 4. Apply the selected {@link ImportCapsuleMode} to every record.\n *\n * Determinism guarantees:\n * - Imported records are returned sorted by `sourcePath`.\n * - Skipped records are returned sorted by `path`.\n * - Fork-mode rebases under a stable `forks/<capsule-id>/` prefix so\n * repeated fork imports of the same capsule shape land in predictable\n * locations (subsequent fork imports still skip-on-exist because the\n * target tree is computed from the source path).\n */\nexport async function importCapsule(\n opts: ImportCapsuleOptions,\n): Promise<ImportCapsuleResult> {\n const archiveAbs = path.resolve(opts.archivePath);\n const rootAbs = path.resolve(opts.root);\n await assertIsDirectoryNotSymlink(rootAbs, \"importCapsule\", \"root\");\n\n const mode: ImportCapsuleMode = opts.mode ?? \"skip\";\n // Reject unknown mode values up-front (rule 51). TypeScript callers get a\n // compile-time check via the union type; JS/CLI callers get a runtime error\n // here before any write begins — not a silent destructive fallback.\n if (mode !== \"skip\" && mode !== \"overwrite\" && mode !== \"fork\") {\n throw new Error(\n `importCapsule: unknown mode ${JSON.stringify(mode)}; expected \"skip\", \"overwrite\", or \"fork\"`,\n );\n }\n\n // Auto-detect encrypted archives. If the file ends with `.enc` or starts\n // with the REMNIC-ENC magic header, decrypt it first before gunzip+parse.\n // Rule 48: default is \"not encrypted\"; we only attempt decryption when the\n // header is definitively present, never on ambiguous content.\n const encrypted = await isEncryptedCapsuleFile(archiveAbs);\n let raw: Buffer;\n if (encrypted) {\n if (!opts.memoryDir && !opts.passphrase) {\n throw new Error(\n `importCapsule: archive is encrypted but 'memoryDir' was not provided. ` +\n `Pass the memory directory so the secure-store key can be retrieved, ` +\n `provide the original passphrase for a format-v2 archive restore, ` +\n `or run \\`remnic secure-store unlock\\` before importing.`,\n );\n }\n raw = await decryptCapsuleFileInMemory(archiveAbs, opts.memoryDir, {\n passphrase: opts.passphrase,\n });\n } else {\n raw = await readFile(archiveAbs);\n }\n const json = gunzipSync(raw).toString(\"utf-8\");\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(json);\n } catch (cause) {\n throw new Error(\n `importCapsule: archive is not valid JSON after gunzip: ${archiveAbs}`,\n { cause: cause as Error },\n );\n }\n\n const parsed = parseExportBundle(parsedJson);\n if (parsed.capsuleVersion !== 2) {\n // PR 1/6 ships a V1 reader; capsule import is V2-only by design. A V1\n // bundle does not carry a capsule block, so fork-mode (which depends on\n // `capsule.id` for the rebase prefix) cannot work. Reject up-front per\n // gotcha #51 instead of silently routing to a different code path.\n throw new Error(\n \"importCapsule: archive is V1; only V2 capsule archives are supported\",\n );\n }\n const bundle = parsed.bundle as { manifest: ExportManifestV2; records: ExportMemoryRecordV1[] };\n const manifest = bundle.manifest;\n const capsule = manifest.capsule;\n\n // Build a path → manifest-entry index for O(1) checksum lookup. The\n // manifest is the source of truth; records-without-manifest-entries and\n // manifest-entries-without-records are both treated as corruption.\n const manifestIndex = new Map<string, ExportManifestV2[\"files\"][number]>();\n for (const f of manifest.files) {\n manifestIndex.set(f.path, f);\n }\n if (manifestIndex.size !== manifest.files.length) {\n throw new Error(\n \"importCapsule: manifest contains duplicate file paths\",\n );\n }\n const recordPaths = new Set<string>();\n for (const rec of bundle.records) {\n if (recordPaths.has(rec.path)) {\n throw new Error(\n `importCapsule: bundle contains duplicate record path: ${rec.path}`,\n );\n }\n recordPaths.add(rec.path);\n }\n\n // Phase 1: verify every record matches its manifest entry AND validate all\n // target paths before any filesystem mutation. We do both in a single pass\n // so a corrupted or malicious archive cannot leave the memory dir partially\n // written (fail-closed per gotcha #25).\n //\n // The real root is resolved once via realpath so the subsequent per-record\n // inside-root checks are symlink-aware: a record path like `facts/a.md`\n // cannot write outside the intended sandbox via a symlinked subdirectory\n // (Codex P1 feedback). If realpath fails (root does not exist) the earlier\n // assertIsDirectoryNotSymlink call already threw, so this should always succeed.\n const rootReal = await realpath(rootAbs).catch(() => rootAbs);\n\n // Tracks normalized, case-folded target paths seen so far in phase 1. Maps\n // targetAbs.toLowerCase() → first source path so the collision error can name\n // both offending entries. Two manifest entries whose computed target paths\n // normalize to the same absolute path (e.g. `subdir/file.md` and\n // `subdir/./file.md`, or differing case on case-insensitive filesystems such\n // as macOS and Windows) would both try to write the same inode — the second\n // would silently overwrite the first. We reject the import up-front before\n // any write (Codex P2 thread on PR #741, line 283).\n const seenTargetPaths = new Map<string, string>();\n\n for (const rec of bundle.records) {\n // Checksum validation.\n const entry = manifestIndex.get(rec.path);\n if (!entry) {\n throw new Error(\n `importCapsule: archive checksum mismatch (record without manifest entry: ${rec.path})`,\n );\n }\n const { sha256, bytes } = sha256String(rec.content);\n if (sha256 !== entry.sha256 || bytes !== entry.bytes) {\n throw new Error(\n `importCapsule: archive checksum mismatch for ${rec.path}: ` +\n `expected sha256=${entry.sha256} bytes=${entry.bytes}, ` +\n `got sha256=${sha256} bytes=${bytes}`,\n );\n }\n\n // Source path validation: reject any record whose posix source path\n // contains a `..` segment, an absolute prefix, or any component that would\n // let fork-mode bypass its isolation invariant. This check runs before\n // `computeTargetPath` so that fork mode's `forks/<id>/` rebase cannot be\n // bypassed by a path like `../../profile.md` (which `path.join` would\n // silently collapse, landing the file inside root but outside the fork\n // prefix — Cursor medium thread #741). Rejecting `..` up-front is simpler\n // and more robust than normalising after the fact.\n //\n // Extended guard (Codex P1 #741 round 5): also reject paths containing\n // backslash separators (`\\`), which are Windows path separators. On Windows\n // a path like `..\\\\escape.md` or `subdir\\\\..\\\\..\\\\escape.md` would resolve\n // to a parent traversal but would bypass a purely posix-split check.\n // Additionally, after posix-normalizing the path we re-check for a leading\n // `..` or `/` — this catches edge-cases such as `subdir/../..` where the\n // individual split segments are not `..` but the normalized result is.\n if (rec.path.includes(\"\\\\\")) {\n throw new Error(\n `importCapsule: record path contains backslash separators (Windows-style paths are not allowed): ${rec.path}`,\n );\n }\n const posixNormalized = path.posix.normalize(rec.path);\n if (\n rec.path.startsWith(\"/\") ||\n rec.path.split(\"/\").some((seg) => seg === \"..\") ||\n posixNormalized.startsWith(\"..\") ||\n posixNormalized.startsWith(\"/\")\n ) {\n throw new Error(\n `importCapsule: record path escapes target root: ${rec.path}`,\n );\n }\n\n // Path-traversal validation (moved here from phase 2 per Cursor feedback:\n // the traversal check must run before ANY write so a malicious archive\n // with an escaping path that sorts last cannot land partial writes).\n //\n // We build targetAbs relative to the real-resolved root (rootReal) so\n // that the inside-root check is symlink-aware: if `rootReal !== rootAbs`\n // (the import root is itself behind a symlink), we still compare against\n // the canonical path (Codex P1).\n const targetRel = computeTargetPath(rec.path, mode, capsule.id);\n const targetAbs = path.join(rootReal, fromPosixRelPath(targetRel));\n if (!isPathInsideRoot(rootReal, targetAbs)) {\n throw new Error(\n `importCapsule: record path escapes target root: ${rec.path}`,\n );\n }\n\n // Symlink-aware containment check (Cursor thread #741 line 247/264).\n // The lexical check above handles `..`-traversal but cannot detect\n // symlinked subdirectories that point outside the root. We resolve the\n // nearest existing ancestor of the target via realpath to catch symlinks\n // anywhere in the path components. If any resolved prefix escapes rootReal,\n // the import is rejected before any write. This applies to ALL modes,\n // including fork mode whose rebase prefix may itself traverse a symlink.\n await assertRealpathInsideRoot(rootReal, targetAbs, rec.path, \"importCapsule\");\n\n // Target-file symlink check (Codex P1 #741 round 4, line 260).\n // `assertRealpathInsideRoot` resolves the nearest existing *ancestor* to\n // catch symlinked parent directories, but if the TARGET FILE itself already\n // exists and is a symlink, that check passes (the parent is real) while the\n // write would silently follow the symlink to a path outside root. We\n // therefore lstat the target directly: if it exists and is a symlink we\n // reject the record up-front. For new files the parent-canonicalization\n // performed above is sufficient; no realpath of a non-existent file is\n // needed.\n const targetLstat = await lstat(targetAbs).catch(() => null);\n if (targetLstat !== null && targetLstat.isSymbolicLink()) {\n throw new Error(\n `importCapsule: record target is a symlink and cannot be written to safely: ${rec.path}`,\n );\n }\n\n // Duplicate normalized target path detection (Codex P2 #741, line 283).\n // `path.join` already normalises `.` segments (e.g. `subdir/./file.md` →\n // `subdir/file.md`). On case-insensitive filesystems (macOS default,\n // Windows), two paths that differ only in case would resolve to the same\n // inode. We fold the dedup key to lowercase so that `subdir/File.md` and\n // `subdir/file.md` are detected as duplicates before any write occurs.\n // This is intentionally unconditional: the cost of an extra `.toLowerCase()`\n // on case-sensitive filesystems is negligible, and a defensive lowercase\n // is far simpler than probing filesystem case-sensitivity at runtime.\n const dedupKey = targetAbs.toLowerCase();\n const firstSourcePath = seenTargetPaths.get(dedupKey);\n if (firstSourcePath !== undefined) {\n throw new Error(\n `importCapsule: manifest contains two entries that resolve to the same target path: ` +\n `\"${firstSourcePath}\" and \"${rec.path}\" both map to \"${targetRel}\"`,\n );\n }\n seenTargetPaths.set(dedupKey, rec.path);\n }\n // Detect manifest-only entries (missing record). Treat as corruption.\n for (const f of manifest.files) {\n if (!recordPaths.has(f.path)) {\n throw new Error(\n `importCapsule: archive checksum mismatch (manifest entry without record: ${f.path})`,\n );\n }\n }\n\n // Phase 2: apply the mode. All records were validated in phase 1; we now\n // write to disk. Per-record errors propagate; each individual write is\n // atomic (mkdir + writeFile pair).\n const imported: ImportCapsuleImportedRecord[] = [];\n const skipped: ImportCapsuleSkippedRecord[] = [];\n // The target's completed migration journal is a write boundary here too\n // (issue #2213): a capsule can carry pre-migration memories whose entityRef\n // the target already renamed, and no recurring reconciliation pass exists\n // to absorb a stale ref after the fact. Read through the identity-keyed\n // cache PER RECORD so a peer migration completing mid-import is picked up\n // for every record written after it (one lstat per record).\n const journalStateDir = path.join(rootReal, \"state\");\n const historicalIdCache = new HistoricalEntityCanonicalIdCache();\n // Entity pages in THIS capsule can re-establish collisions the target's\n // journal already resolved (Codex P1): once the next migration parks the\n // mapping, a memory canonicalized onto the canonical claimant is\n // permanently misattributed. Memories whose ref targets a capsule-supplied\n // entity id import byte-faithful behind the reconcile marker instead; the\n // migration settles the collision and rewrites references per its verdict.\n const capsuleEntityIds = new Set(\n bundle.records\n .map((record) => computeTargetPath(record.path, mode, capsule.id))\n .filter((rel) => classifyEntityRefWritePath(rootReal, path.join(rootReal, fromPosixRelPath(rel))) === \"entity\")\n .map((rel) => path.basename(rel, \".md\")),\n );\n\n // Sort by source path so the imported/skipped lists are deterministic\n // regardless of bundle order. (`exportCapsule` already sorts; we re-sort\n // defensively in case a hand-edited archive ships records in another order.)\n const sortedRecords = [...bundle.records].sort((a, b) =>\n a.path.localeCompare(b.path),\n );\n\n // The reconcile marker is published ONCE, after every record landed\n // (Codex P1, round 21): a per-record marker could be consumed by a peer\n // between a legacy-preserving memory write and its colliding entity page,\n // canonicalizing the memory onto the wrong claimant irreversibly.\n let reconcileNeeded = false;\n const applyRecords = async (): Promise<void> => {\n for (const rec of sortedRecords) {\n const targetRel = computeTargetPath(rec.path, mode, capsule.id);\n // Use rootReal (realpath-resolved) to stay consistent with phase 1's\n // traversal validation and avoid writing through stale symlinks.\n const targetAbs = path.join(rootReal, fromPosixRelPath(targetRel));\n\n const exists = await fileExistsAt(targetAbs);\n\n // Skip logic applies to both `skip` mode (explicit) and `fork` mode\n // (Cursor medium: fork mode must also be skip-on-exist for the computed\n // fork path, because production imports generate non-deterministic IDs —\n // so re-importing the same capsule should not overwrite user edits in the\n // fork tree or silently change file identities by generating new IDs).\n if ((mode === \"skip\" || mode === \"fork\") && exists) {\n skipped.push({ path: rec.path, reason: \"exists\" });\n continue;\n }\n\n let snapshotted = false;\n if (mode === \"overwrite\" && exists) {\n // Gotcha #54: snapshot BEFORE overwriting. If snapshot creation fails\n // we abort this record's import rather than silently destroying\n // history. The page-versioning module is responsible for atomic\n // sidecar writes; we just call it.\n if (opts.versioning && opts.versioning.enabled) {\n const prior = await readFile(targetAbs, \"utf-8\").catch(() => \"\");\n await createVersion(\n targetAbs,\n prior,\n \"manual\",\n opts.versioning,\n opts.log,\n `capsule-import: ${capsule.id}`,\n rootReal,\n );\n snapshotted = true;\n }\n }\n\n let contentToWrite = rec.content;\n let rewroteId = false;\n if (mode === \"fork\") {\n const forked = rewriteFrontmatterIdForFork(contentToWrite, capsule.id, opts.now);\n contentToWrite = forked.content;\n rewroteId = forked.rewrote;\n }\n\n await mkdir(path.dirname(targetAbs), { recursive: true });\n // Resolve at the write itself (mirrors capsule-merge): a peer migration\n // can complete during the snapshot/mkdir awaits, and capsule writes bump\n // only the corpus version, which the migration fingerprint ignores. The\n // post-write REPAIR re-canonicalizes and rewrites when the journal moved\n // across the write itself (a parked mapping cannot be fixed after the\n // fact by the reconcile pass). Only memory-tier records canonicalize;\n // entities/ pages carry relationship TARGETS only\n // rewriteRelationshipTargets understands, so they import byte-faithful\n // with a reconcile marker; everything else imports losslessly.\n const targetKind = classifyEntityRefWritePath(rootReal, targetAbs);\n const rawRef = targetKind === \"memory\" ? readEntityRefFromFrontmatter(contentToWrite) : null;\n if (targetKind === \"memory\" && rawRef !== null && capsuleEntityIds.has(rawRef)) {\n // Ref targets a capsule-supplied entity page (potential collision\n // claimant): keep the legacy bytes; the DEFERRED marker below lets the\n // migration settle the collision and rewrite per its verdict (Codex P1).\n await writeFile(targetAbs, contentToWrite, \"utf-8\");\n reconcileNeeded = true;\n } else if (targetKind === \"memory\") {\n const idsAtWrite = historicalIdCache.get(journalStateDir);\n const rawRecord = contentToWrite;\n contentToWrite = canonicalizeEntityRefFrontmatter(rawRecord, idsAtWrite);\n // Snapshot the pre-write bytes: a repair failure after the write must\n // restore them (or remove a newly created target), or the import\n // reports failure while an overwrite already destroyed the prior state\n // and the skipped corpus bump leaves warm caches stale (AGENTS.md §14).\n const originalBytes = await readFile(targetAbs, \"utf-8\").catch(() => null);\n await writeFile(targetAbs, contentToWrite, \"utf-8\");\n try {\n await repairContentAfterJournalMove({\n stateDir: journalStateDir,\n cache: historicalIdCache,\n idsAtWrite,\n rawContent: rawRecord,\n lastWritten: contentToWrite,\n rewrite: (content) => writeFile(targetAbs, content, \"utf-8\"),\n });\n } catch (err) {\n if (originalBytes === null) {\n await unlink(targetAbs).catch(() => undefined);\n } else {\n await writeFile(targetAbs, originalBytes, \"utf-8\").catch(() => undefined);\n }\n throw err;\n }\n } else {\n await writeFile(targetAbs, contentToWrite, \"utf-8\");\n if (targetKind === \"entity\") {\n reconcileNeeded = true;\n }\n }\n // Bump the corpus sentinel per write (Cursor Medium, #1902): a concurrent\n // readAllMemories during the import must rescan and see records already on\n // disk, never the pre-import corpus, mid-batch.\n bumpMemoryCorpusVersionForDir(rootReal);\n imported.push({\n sourcePath: rec.path,\n targetPath: targetRel,\n snapshotted,\n rewroteId,\n });\n }\n\n // Every record — including every collision claimant entity page — is on\n // disk; NOW the reconcile pass can settle collisions safely.\n if (reconcileNeeded) {\n await requestEntityCanonicalIdReconcile(journalStateDir);\n }\n };\n const firstEntityId = capsuleEntityIds.values().next().value;\n if (firstEntityId === undefined) {\n await applyRecords();\n } else {\n await withRawEntityPageMutation(\n rootReal,\n path.join(rootReal, \"entities\", `${firstEntityId}.md`),\n applyRecords,\n );\n }\n\n // Sort skipped for stable output (see comment above).\n skipped.sort((a, b) => a.path.localeCompare(b.path));\n\n // Per-record corpus bumps happen inside the loop above (Cursor Medium,\n // #1902); no after-batch bump needed here.\n\n return { imported, skipped, manifest };\n}\n\n// ---------------------------------------------------------------------------\n// Path helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the destination relative path for a record under the chosen\n * mode.\n *\n * - `skip` / `overwrite` — identity: the record's posix path is used as-is.\n * - `fork` — rebased under `forks/<capsule-id>/<original-path>` so the\n * original tree is never modified.\n */\nfunction computeTargetPath(\n sourcePosix: string,\n mode: ImportCapsuleMode,\n capsuleId: string,\n): string {\n if (mode === \"fork\") return `forks/${capsuleId}/${sourcePosix}`;\n return sourcePosix;\n}\n\nasync function fileExistsAt(absPath: string): Promise<boolean> {\n const st = await stat(absPath).catch(() => null);\n return st !== null && st.isFile();\n}\n\n// ---------------------------------------------------------------------------\n// Fork-mode id rewriting\n// ---------------------------------------------------------------------------\n\n/**\n * Rewrite a YAML-frontmatter `id:` field to a fork-scoped value.\n *\n * Strategy: we deliberately do NOT parse the entire YAML — memory files\n * use a deterministic top-of-file frontmatter delimited by `---` lines,\n * and the orchestrator's `parseFrontmatter` reads `id` as a top-level\n * key with a single-line scalar value. We mirror that contract:\n *\n * - Detect a leading `---\\n` … `\\n---` block at the top of the file.\n * - Within that block, locate the first `id:` line that is not nested\n * under another key (cheap heuristic: line starts at column 0).\n * - Replace its value with a new fork-id derived from `capsuleId` and\n * a short random suffix (or {@link opts.now} when provided for tests).\n *\n * Files without a frontmatter block, or without an `id:` key inside one,\n * are returned unchanged with `rewrote: false`. This keeps non-memory\n * artifacts (READMEs, transcripts) byte-identical to the source.\n */\nfunction rewriteFrontmatterIdForFork(\n content: string,\n capsuleId: string,\n now: number | undefined,\n): { content: string; rewrote: boolean } {\n // Detect the dominant line ending in the file so we can preserve it when\n // rebuilding the frontmatter delimiters. Splitting/joining on `\\n` silently\n // drops `\\r` from CRLF files, changing the byte content (Cursor thread #741\n // line 467). We detect the ending of the very first line (the opening `---`)\n // and use that as the canonical separator for the reconstructed delimiters.\n // All three cases are covered: CRLF (\\r\\n), LF (\\n), and bare CR (\\r).\n const crlfMatch = /^---(\\r\\n|\\r|\\n)/.exec(content);\n // Fall back to LF if the file starts with `---` but has no newline (EOF).\n const eol = crlfMatch ? crlfMatch[1] : \"\\n\";\n\n // Frontmatter block detection: `---` on its own line at the very start,\n // followed by content, followed by `---` on its own line. The closing\n // delimiter must be at column 0. We capture the trailing terminator\n // (`\\r?\\n` or end-of-string) as a separate group so we can re-emit it\n // verbatim, preserving CRLF/LF/EOF shape from the original file.\n const fmMatch = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---(\\r?\\n|$)/.exec(content);\n if (!fmMatch) return { content, rewrote: false };\n const fmBody = fmMatch[1];\n const fmTrailer = fmMatch[2];\n const fmStart = fmMatch.index;\n const fmEnd = fmStart + fmMatch[0].length;\n\n // Find a top-level `id:` line. Top-level means the line begins at\n // column 0 inside the frontmatter body (no leading whitespace) and the\n // key is exactly `id`. We deliberately accept `id:` and `id : ` shapes\n // but reject `nested_id:` to avoid touching unrelated keys.\n const idLineRe = /^id:[ \\t]*([^\\r\\n]*)$/m;\n const idMatch = idLineRe.exec(fmBody);\n if (!idMatch) return { content, rewrote: false };\n\n const newId = mintForkId(capsuleId, idMatch[1]?.trim() ?? \"\", now);\n const replacedBody = fmBody.replace(idLineRe, `id: ${newId}`);\n // Reconstruct the file: original prefix (always empty here, fmStart === 0\n // by the `^` anchor) + frontmatter delimiters around the rewritten body.\n // Use the detected `eol` for the opening/closing `---` lines so that CRLF\n // files remain CRLF and LF files remain LF, preserving byte-content fidelity\n // (Cursor thread #741 line 467). The captured `fmTrailer` (the newline\n // immediately after the closing `---`, or end-of-string) is re-emitted\n // verbatim so the byte immediately after the closing fence is unchanged.\n const prefix = content.slice(0, fmStart);\n const tail = content.slice(fmEnd);\n const rebuilt = `${prefix}---${eol}${replacedBody}${eol}---${fmTrailer}${tail}`;\n return { content: rebuilt, rewrote: true };\n}\n\n/**\n * Derive a deterministic-when-`now`-is-set fork id from the capsule id and\n * the original record id. Production callers omit `now` and get a UUID\n * suffix; tests pass `now` for byte-stable assertions.\n */\nfunction mintForkId(capsuleId: string, originalId: string, now: number | undefined): string {\n const base = originalId.length > 0 ? originalId : \"fork\";\n if (now === undefined) {\n const suffix = randomUUID().slice(0, 8);\n return `${base}-fork-${capsuleId}-${suffix}`;\n }\n // Deterministic suffix: short hash of (capsuleId, originalId, now). Using\n // sha256 over a sorted-key serialization (gotcha #38) so the suffix does\n // not depend on Object.entries order.\n const payload = JSON.stringify({ c: capsuleId, i: originalId, n: now });\n const suffix = createHash(\"sha256\").update(payload, \"utf-8\").digest(\"hex\").slice(0, 8);\n return `${base}-fork-${capsuleId}-${suffix}`;\n}\n\n// Note: `CapsuleBlock` is re-exported here purely so callers that want to\n// inspect the manifest block don't have to deep-import from `./types.js`.\nexport type { CapsuleBlock };\n"],"mappings":"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","names":["suffix"]}
@@ -0,0 +1,26 @@
1
+ // src/external-wiki-mcp-tools.ts
2
+ var EXTERNAL_WIKI_MCP_TOOLS = [
3
+ {
4
+ name: "engram.external_wiki_search",
5
+ description: "Search configured external compiled-wiki roots on demand. Returns ranked snippets with root-relative citations and never changes default recall.",
6
+ inputSchema: {
7
+ type: "object",
8
+ properties: {
9
+ query: { type: "string", description: "Required topical query." },
10
+ limit: { type: "number", description: "Maximum hits (default 6, maximum 20)." },
11
+ wikiId: { type: "string", description: "Optional configured wiki id to search exclusively." },
12
+ maxCharsPerHit: {
13
+ type: "number",
14
+ description: "Maximum characters in each snippet (default 1000, maximum 8000)."
15
+ }
16
+ },
17
+ required: ["query"],
18
+ additionalProperties: false
19
+ }
20
+ }
21
+ ];
22
+
23
+ export {
24
+ EXTERNAL_WIKI_MCP_TOOLS
25
+ };
26
+ //# sourceMappingURL=chunk-A5KNZSNA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/external-wiki-mcp-tools.ts"],"sourcesContent":["import type { McpTool } from \"./access-mcp.js\";\n\nexport const EXTERNAL_WIKI_MCP_TOOLS: McpTool[] = [\n {\n name: \"engram.external_wiki_search\",\n description:\n \"Search configured external compiled-wiki roots on demand. Returns ranked snippets with root-relative citations and never changes default recall.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"Required topical query.\" },\n limit: { type: \"number\", description: \"Maximum hits (default 6, maximum 20).\" },\n wikiId: { type: \"string\", description: \"Optional configured wiki id to search exclusively.\" },\n maxCharsPerHit: {\n type: \"number\",\n description: \"Maximum characters in each snippet (default 1000, maximum 8000).\",\n },\n },\n required: [\"query\"],\n additionalProperties: false,\n },\n },\n];\n"],"mappings":";AAEO,IAAM,0BAAqC;AAAA,EAChD;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,OAAO,EAAE,MAAM,UAAU,aAAa,0BAA0B;AAAA,QAChE,OAAO,EAAE,MAAM,UAAU,aAAa,wCAAwC;AAAA,QAC9E,QAAQ,EAAE,MAAM,UAAU,aAAa,qDAAqD;AAAA,QAC5F,gBAAgB;AAAA,UACd,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,OAAO;AAAA,MAClB,sBAAsB;AAAA,IACxB;AAAA,EACF;AACF;","names":[]}