@remnic/core 9.69.22 → 9.69.24

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 (772) hide show
  1. package/dist/abstraction-nodes.js +3 -2
  2. package/dist/access-admin-ops-surface.d.ts +14 -12
  3. package/dist/access-admin-ops-surface.js +94 -91
  4. package/dist/access-authorization-probe.d.ts +14 -12
  5. package/dist/access-authorization-probe.js +95 -92
  6. package/dist/access-boundary.d.ts +14 -12
  7. package/dist/access-boundary.js +94 -91
  8. package/dist/access-citation-namespace.js +3 -3
  9. package/dist/access-cli.js +200 -195
  10. package/dist/access-cli.js.map +1 -1
  11. package/dist/access-coding-context-resolution.d.ts +2 -1
  12. package/dist/access-extraction-force-flush.d.ts +14 -12
  13. package/dist/access-extraction-force-flush.js +94 -91
  14. package/dist/access-health-types.d.ts +2 -1
  15. package/dist/access-http-briefing.d.ts +156 -0
  16. package/dist/access-http-briefing.js +233 -0
  17. package/dist/access-http-lcm-compaction.d.ts +14 -12
  18. package/dist/access-http-lifecycle-flush.d.ts +14 -12
  19. package/dist/access-http-offline-stream.d.ts +14 -12
  20. package/dist/access-http-query.d.ts +3 -2
  21. package/dist/access-http-query.js +96 -93
  22. package/dist/access-http.d.ts +15 -13
  23. package/dist/access-http.js +119 -114
  24. package/dist/access-identity-continuity-surface.d.ts +12 -10
  25. package/dist/access-identity-continuity-surface.js +94 -91
  26. package/dist/access-lcm-surface.d.ts +14 -12
  27. package/dist/access-lcm-surface.js +94 -91
  28. package/dist/access-mcp.d.ts +14 -12
  29. package/dist/access-mcp.js +105 -101
  30. package/dist/access-memory-search-fanout.d.ts +3 -2
  31. package/dist/{access-namespace-preflight-BMHhxoL9.d.ts → access-namespace-preflight-BsvmyENS.d.ts} +1 -1
  32. package/dist/access-namespace-preflight.d.ts +4 -3
  33. package/dist/access-namespace-preflight.js +94 -91
  34. package/dist/access-observe-transcript.d.ts +12 -10
  35. package/dist/access-observe-write-surface.d.ts +14 -12
  36. package/dist/access-observe-write-surface.js +94 -91
  37. package/dist/access-offline-manifest.d.ts +12 -10
  38. package/dist/access-offline-manifest.js +15 -15
  39. package/dist/access-operations-batch.js +99 -95
  40. package/dist/access-operations.d.ts +14 -12
  41. package/dist/access-operations.js +104 -100
  42. package/dist/access-recall-concurrency.d.ts +14 -12
  43. package/dist/access-recall-concurrency.js +94 -91
  44. package/dist/access-recall-response.d.ts +14 -12
  45. package/dist/access-recall-response.js +94 -91
  46. package/dist/access-recall-surface.d.ts +14 -12
  47. package/dist/access-recall-surface.js +94 -91
  48. package/dist/access-schema.js +8 -7
  49. package/dist/{access-service-BlsNXFwx.d.ts → access-service-DWdY9Mlk.d.ts} +7 -7
  50. package/dist/access-service-helpers.d.ts +14 -12
  51. package/dist/access-service.d.ts +14 -12
  52. package/dist/access-service.js +94 -91
  53. package/dist/access-surface-catalog.d.ts +14 -12
  54. package/dist/access-surface-catalog.js +97 -93
  55. package/dist/access-surface-catalog.js.map +1 -1
  56. package/dist/access-wearables-meetings-surface.d.ts +4 -3
  57. package/dist/action-confidence.d.ts +2 -1
  58. package/dist/active-memory-bridge.d.ts +2 -1
  59. package/dist/active-recall.d.ts +2 -1
  60. package/dist/active-recall.js +16 -13
  61. package/dist/active-recall.js.map +1 -1
  62. package/dist/adapters/index.js +7 -7
  63. package/dist/adapters/registry.js +3 -3
  64. package/dist/ambient-provenance.d.ts +2 -1
  65. package/dist/artifact-search.d.ts +2 -1
  66. package/dist/{auto-sync-GRUJFD2F.js → auto-sync-WNGG2GC2.js} +9 -9
  67. package/dist/behavior-learner.d.ts +2 -1
  68. package/dist/behavior-signals.d.ts +2 -1
  69. package/dist/bootstrap.d.ts +12 -10
  70. package/dist/briefing-window.d.ts +3 -2
  71. package/dist/briefing.d.ts +3 -2
  72. package/dist/briefing.js +36 -36
  73. package/dist/buffer-surprise-report.d.ts +2 -1
  74. package/dist/buffer-turn-helpers.d.ts +2 -1
  75. package/dist/buffer.d.ts +3 -2
  76. package/dist/buffer.js +13 -13
  77. package/dist/bulk-import/index.d.ts +4 -3
  78. package/dist/calibration.d.ts +2 -1
  79. package/dist/calibration.js +2 -1
  80. package/dist/calibration.js.map +1 -1
  81. package/dist/capabilities.d.ts +2 -1
  82. package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-YO5QJ6L3.js} +2 -2
  83. package/dist/{capsule-merge-SEHERWWP.js → capsule-merge-IPG4IOFP.js} +5 -5
  84. package/dist/{catalog-C1qHsGew.d.ts → catalog-CDZLyiXL.d.ts} +1 -1
  85. package/dist/causal-behavior.d.ts +2 -1
  86. package/dist/causal-behavior.js +4 -3
  87. package/dist/causal-behavior.js.map +1 -1
  88. package/dist/causal-chain.js +4 -3
  89. package/dist/causal-consolidation.d.ts +2 -1
  90. package/dist/causal-consolidation.js +42 -42
  91. package/dist/causal-retrieval.js +4 -3
  92. package/dist/causal-retrieval.js.map +1 -1
  93. package/dist/causal-trajectory-graph.d.ts +5 -2
  94. package/dist/causal-trajectory-graph.js +6 -2
  95. package/dist/causal-trajectory-graph.js.map +1 -1
  96. package/dist/causal-trajectory.js +3 -2
  97. package/dist/{chunk-KTVSPFCQ.js → chunk-22FVR2KE.js} +2 -2
  98. package/dist/{chunk-7Y5V3LAP.js → chunk-27QVNSQ3.js} +2 -2
  99. package/dist/{chunk-R7LY4YKF.js → chunk-2EKJDQZB.js} +2 -2
  100. package/dist/{chunk-FCATYKQA.js → chunk-2IOHTUP3.js} +263 -13
  101. package/dist/chunk-2IOHTUP3.js.map +1 -0
  102. package/dist/{chunk-HOUST5UX.js → chunk-2ITE4C2Z.js} +2 -2
  103. package/dist/{chunk-JOYC4RYC.js → chunk-2JVJ7UHC.js} +2 -2
  104. package/dist/{chunk-X2NFFBTO.js → chunk-2L5FSNPC.js} +7 -7
  105. package/dist/{chunk-DUAJKRR2.js → chunk-2SGLMP2E.js} +2 -2
  106. package/dist/{chunk-6FUMA6AA.js → chunk-2Z4GS5E6.js} +2 -2
  107. package/dist/{chunk-G6MXN2G5.js → chunk-37KUQPX4.js} +6 -6
  108. package/dist/{chunk-DDQQY2E3.js → chunk-3BTFBQLO.js} +7 -7
  109. package/dist/chunk-3BTFBQLO.js.map +1 -0
  110. package/dist/{chunk-UR6PBX2J.js → chunk-3K7V3HE6.js} +35 -60
  111. package/dist/chunk-3K7V3HE6.js.map +1 -0
  112. package/dist/{chunk-WKAXBXVA.js → chunk-3QQTXYZ6.js} +2 -2
  113. package/dist/{chunk-DJUKBGAD.js → chunk-46EST7JO.js} +5 -5
  114. package/dist/chunk-46EST7JO.js.map +1 -0
  115. package/dist/{chunk-4ZWCQJNM.js → chunk-46WM6JX2.js} +5 -5
  116. package/dist/{chunk-CASWJ2HM.js → chunk-46ZPIGWI.js} +3 -3
  117. package/dist/{chunk-HTIIXNJQ.js → chunk-4FIH6MPS.js} +6 -3
  118. package/dist/chunk-4FIH6MPS.js.map +1 -0
  119. package/dist/{chunk-MCA2X4WH.js → chunk-4IHBN6WU.js} +2 -2
  120. package/dist/{chunk-W7IGLX4G.js → chunk-4O6WRBGE.js} +7 -7
  121. package/dist/chunk-4O6WRBGE.js.map +1 -0
  122. package/dist/{chunk-FB7LAJQM.js → chunk-4TKJGOCJ.js} +2 -2
  123. package/dist/{chunk-H7BZBSP6.js → chunk-52II7PB6.js} +4 -4
  124. package/dist/{chunk-N4Y5T6VD.js → chunk-54WHLA65.js} +4 -4
  125. package/dist/chunk-56Y6EKZN.js +24 -0
  126. package/dist/chunk-56Y6EKZN.js.map +1 -0
  127. package/dist/{chunk-YVLENSNS.js → chunk-5ATKSPEQ.js} +2 -2
  128. package/dist/{chunk-OLT3YTDH.js → chunk-5FAGCOZD.js} +37 -24
  129. package/dist/chunk-5FAGCOZD.js.map +1 -0
  130. package/dist/{chunk-ZVZHG7AI.js → chunk-5UBH37SL.js} +3 -3
  131. package/dist/{chunk-N3WZU76A.js → chunk-66OJSCI6.js} +2 -2
  132. package/dist/{chunk-D35XLYQ7.js → chunk-6CVNSDCZ.js} +11 -11
  133. package/dist/{chunk-KA2HZCMG.js → chunk-6NXSYYGP.js} +2 -2
  134. package/dist/{chunk-2HIJHXB3.js → chunk-6WHJ2EAB.js} +2 -2
  135. package/dist/{chunk-ZZM476NV.js → chunk-6XL73HQ4.js} +4 -4
  136. package/dist/{chunk-EJ5RKUXW.js → chunk-AQ7SYDVO.js} +2 -2
  137. package/dist/{chunk-2Z3DG5CQ.js → chunk-B3O3IRZN.js} +2 -2
  138. package/dist/{chunk-P77QX3ID.js → chunk-B6O2YLUR.js} +21 -20
  139. package/dist/chunk-B6O2YLUR.js.map +1 -0
  140. package/dist/{chunk-RACZB5HT.js → chunk-BD7JTBYP.js} +4 -4
  141. package/dist/{chunk-I762GW7V.js → chunk-BLJWYCNO.js} +5 -5
  142. package/dist/{chunk-ACPCA4NO.js → chunk-BMWN7B3Y.js} +6 -6
  143. package/dist/chunk-BMWN7B3Y.js.map +1 -0
  144. package/dist/{chunk-2NLLXCJG.js → chunk-BXLOS5AJ.js} +2 -2
  145. package/dist/{chunk-KK66P5GQ.js → chunk-C553ZTLF.js} +46 -48
  146. package/dist/chunk-C553ZTLF.js.map +1 -0
  147. package/dist/{chunk-GCASGYIO.js → chunk-C7HJ3NEI.js} +2 -2
  148. package/dist/{chunk-C24UZSFW.js → chunk-CEH2AFXG.js} +6 -6
  149. package/dist/{chunk-WVGXCBOC.js → chunk-D5F7TKMH.js} +2 -2
  150. package/dist/chunk-DGS34QSY.js +141 -0
  151. package/dist/chunk-DGS34QSY.js.map +1 -0
  152. package/dist/{chunk-X7Y7WX73.js → chunk-DQEMWVMT.js} +1 -1
  153. package/dist/{chunk-2OXIPF3A.js → chunk-DZD3WGCD.js} +4 -4
  154. package/dist/{chunk-UMEOXLIZ.js → chunk-E2P7TZTF.js} +5 -5
  155. package/dist/{chunk-6FC3IZ26.js → chunk-EBA5DA77.js} +2 -2
  156. package/dist/{chunk-N7JK2RKG.js → chunk-EOQ6FSQP.js} +2 -2
  157. package/dist/chunk-EUT2WCWS.js +54 -0
  158. package/dist/chunk-EUT2WCWS.js.map +1 -0
  159. package/dist/{chunk-YNDLCWXS.js → chunk-EZ25VE3G.js} +4 -4
  160. package/dist/{chunk-XDMI5VKE.js → chunk-FVOP3NT7.js} +2 -2
  161. package/dist/{chunk-NRLELHAY.js → chunk-G7NYVKD6.js} +2 -2
  162. package/dist/{chunk-B3W7GWQB.js → chunk-GHTSNGBZ.js} +2 -2
  163. package/dist/chunk-GKCXTSFF.js +17 -0
  164. package/dist/chunk-GKCXTSFF.js.map +1 -0
  165. package/dist/{chunk-LUDBXTBJ.js → chunk-H272ZPQ3.js} +5 -5
  166. package/dist/{chunk-SN4JXNLL.js → chunk-H3TKENU4.js} +2 -2
  167. package/dist/{chunk-4HYNMLT6.js → chunk-H4SEGIZY.js} +2 -2
  168. package/dist/{chunk-ACZN5ZXD.js → chunk-H54VWRPS.js} +13 -13
  169. package/dist/{chunk-HTP6XRUI.js → chunk-HM7RHKS4.js} +2 -2
  170. package/dist/{chunk-Z3SQEEB6.js → chunk-HWLIMQE2.js} +2 -2
  171. package/dist/{chunk-NQFCLAYT.js → chunk-ICKJ52PE.js} +99 -322
  172. package/dist/chunk-ICKJ52PE.js.map +1 -0
  173. package/dist/{chunk-2QSZNTDO.js → chunk-JBPKEARU.js} +7 -7
  174. package/dist/{chunk-DK6GMO6D.js → chunk-JEC4DVM3.js} +16 -16
  175. package/dist/chunk-JEC4DVM3.js.map +1 -0
  176. package/dist/{chunk-ET2CNMLD.js → chunk-JN72EPOE.js} +2 -2
  177. package/dist/{chunk-U62OK7BB.js → chunk-JPKK466T.js} +188 -21
  178. package/dist/chunk-JPKK466T.js.map +1 -0
  179. package/dist/{chunk-JCCWJHOP.js → chunk-JYZSRNR7.js} +2 -2
  180. package/dist/{chunk-7D6HXODY.js → chunk-K7724CH2.js} +2 -2
  181. package/dist/{chunk-X33MJFD2.js → chunk-KAXCYM66.js} +3 -3
  182. package/dist/{chunk-7RRUHJPG.js → chunk-KB2G2I6Q.js} +3 -3
  183. package/dist/{chunk-ZXBTTMGZ.js → chunk-KEF46KL2.js} +5 -5
  184. package/dist/{chunk-5UZXUTVO.js → chunk-KNA3BXXL.js} +6 -2
  185. package/dist/chunk-KNA3BXXL.js.map +1 -0
  186. package/dist/{chunk-UWTDARPF.js → chunk-KTWG7CNY.js} +6 -6
  187. package/dist/{chunk-XQYTSZW3.js → chunk-L7Z57SID.js} +6 -6
  188. package/dist/{chunk-JMAG7WZ7.js → chunk-LO4UKPKX.js} +3 -3
  189. package/dist/{chunk-LDWIPYJ6.js → chunk-LS2FHUML.js} +3 -3
  190. package/dist/{chunk-GDB4J2H3.js → chunk-MPC7TYTZ.js} +2 -2
  191. package/dist/{chunk-2GF27PGH.js → chunk-MRPOZBJC.js} +3 -3
  192. package/dist/{chunk-BR3OOQZQ.js → chunk-MWN6QEI2.js} +2 -2
  193. package/dist/{chunk-NZGO2GKL.js → chunk-MY5EDR46.js} +4 -4
  194. package/dist/{chunk-LCMUZDBZ.js → chunk-N3ZOP7KC.js} +3 -3
  195. package/dist/{chunk-TVW4C7PV.js → chunk-NB3LRY4T.js} +6 -6
  196. package/dist/{chunk-QJCWK2A7.js → chunk-ND6IQGSZ.js} +2 -2
  197. package/dist/{chunk-NOB2T2FC.js → chunk-NHLLKEKK.js} +2 -2
  198. package/dist/{chunk-7GSSHAXC.js → chunk-NLYVH66G.js} +6 -6
  199. package/dist/chunk-NLYVH66G.js.map +1 -0
  200. package/dist/{chunk-EJIWBTVM.js → chunk-O6ZNNVSP.js} +2 -2
  201. package/dist/{chunk-AG46P24C.js → chunk-OB3XMWX5.js} +4 -4
  202. package/dist/{chunk-NYRB7BKY.js → chunk-OEYZXDQI.js} +6 -6
  203. package/dist/chunk-OEYZXDQI.js.map +1 -0
  204. package/dist/{chunk-46QMN7I7.js → chunk-PAZY2ZKP.js} +6 -6
  205. package/dist/{chunk-EF4JUM55.js → chunk-PX4UMA5Z.js} +2 -2
  206. package/dist/chunk-QLK3SL7Q.js +242 -0
  207. package/dist/chunk-QLK3SL7Q.js.map +1 -0
  208. package/dist/{chunk-GGYDJJBO.js → chunk-QOOBICJF.js} +5 -5
  209. package/dist/chunk-QOOBICJF.js.map +1 -0
  210. package/dist/{chunk-NNZFPYYX.js → chunk-R7QY5ZVB.js} +2 -2
  211. package/dist/{chunk-RO2X2EYM.js → chunk-R7RTXEYG.js} +2 -2
  212. package/dist/{chunk-3LJPSRAN.js → chunk-RBCQVOVJ.js} +3 -3
  213. package/dist/{chunk-N4F7ZSSG.js → chunk-RC5DXXWC.js} +2 -2
  214. package/dist/{chunk-VLAQV4HT.js → chunk-RJYJ7KR7.js} +1636 -611
  215. package/dist/chunk-RJYJ7KR7.js.map +1 -0
  216. package/dist/{chunk-5CF2R4NS.js → chunk-RKBLRTNT.js} +2 -2
  217. package/dist/{chunk-5QZR2RA3.js → chunk-ROBHL3GL.js} +2 -2
  218. package/dist/{chunk-D5ZNOKR7.js → chunk-S7T2TY65.js} +3 -3
  219. package/dist/{chunk-C2JCVZWX.js → chunk-SCXURCVT.js} +25 -13
  220. package/dist/chunk-SCXURCVT.js.map +1 -0
  221. package/dist/{chunk-3LADWWMA.js → chunk-SJDQ5RSN.js} +3 -3
  222. package/dist/{chunk-45XVII3J.js → chunk-SMWTZLHE.js} +99 -89
  223. package/dist/{chunk-45XVII3J.js.map → chunk-SMWTZLHE.js.map} +1 -1
  224. package/dist/{chunk-XOQGUGJL.js → chunk-SO7SV523.js} +1 -1
  225. package/dist/{chunk-XOQGUGJL.js.map → chunk-SO7SV523.js.map} +1 -1
  226. package/dist/{chunk-CHWUICVY.js → chunk-SV4Z2S67.js} +4 -4
  227. package/dist/{chunk-JHP45LO5.js → chunk-SVXJLDDC.js} +9 -7
  228. package/dist/{chunk-JHP45LO5.js.map → chunk-SVXJLDDC.js.map} +1 -1
  229. package/dist/{chunk-SEF4IOFE.js → chunk-SWIKABKI.js} +2 -2
  230. package/dist/{chunk-JRRQ747T.js → chunk-TBXAY2SS.js} +13 -13
  231. package/dist/{chunk-J6A3CX5N.js → chunk-TG3FAM2S.js} +33 -8
  232. package/dist/{chunk-J6A3CX5N.js.map → chunk-TG3FAM2S.js.map} +1 -1
  233. package/dist/{chunk-XZBXINXZ.js → chunk-TNSCIPBQ.js} +4 -4
  234. package/dist/{chunk-S37NN23M.js → chunk-TVEONGBU.js} +2 -2
  235. package/dist/{chunk-5RPMTFB6.js → chunk-TWF35IC6.js} +3 -3
  236. package/dist/{chunk-BZTJEILZ.js → chunk-U6N5IBVY.js} +2 -2
  237. package/dist/{chunk-7TUB6JWA.js → chunk-UCKYTA2T.js} +3 -3
  238. package/dist/{chunk-PPOT6SPR.js → chunk-UNNPNBR2.js} +11 -11
  239. package/dist/{chunk-KQAFEZQX.js → chunk-VDX2J7OX.js} +2 -2
  240. package/dist/{chunk-J2R275FN.js → chunk-VVX5PZFS.js} +4 -4
  241. package/dist/{chunk-ME35HVDJ.js → chunk-VYCOJKSX.js} +2 -2
  242. package/dist/{chunk-F5UWQ4LX.js → chunk-W24T5YMW.js} +2 -2
  243. package/dist/{chunk-HDQUQBPW.js → chunk-W3K3HITK.js} +2 -2
  244. package/dist/{chunk-GDASG7NC.js → chunk-W4F3C7N7.js} +2 -2
  245. package/dist/{chunk-LFK623SF.js → chunk-WJHGDE7X.js} +5 -5
  246. package/dist/{chunk-DP4EBV7C.js → chunk-WMLEPWMO.js} +16 -16
  247. package/dist/chunk-WMLEPWMO.js.map +1 -0
  248. package/dist/{chunk-3Q6RD76J.js → chunk-WQZZDN5M.js} +5 -5
  249. package/dist/{chunk-ZJWDWPX6.js → chunk-X5K5TAQZ.js} +4 -4
  250. package/dist/{chunk-ZL3XX5LW.js → chunk-XM24CDZX.js} +3 -3
  251. package/dist/{chunk-JTWZKNUH.js → chunk-XOVKXJEP.js} +3 -3
  252. package/dist/{chunk-OGTKQ5MJ.js → chunk-XSGUMQQQ.js} +62 -50
  253. package/dist/chunk-XSGUMQQQ.js.map +1 -0
  254. package/dist/{chunk-X5YYSAZX.js → chunk-XUE46UYW.js} +3 -3
  255. package/dist/{chunk-DJORULH3.js → chunk-YRLHEEQT.js} +2 -2
  256. package/dist/{chunk-TA7UZZMW.js → chunk-Z3O53WZR.js} +2 -2
  257. package/dist/{chunk-4LG4CPOC.js → chunk-Z6COGHHN.js} +2 -2
  258. package/dist/{chunk-RE3H6Y2X.js → chunk-ZIW5JVRM.js} +2 -2
  259. package/dist/{cli-BNtvR-nU.d.ts → cli-DD0P-lu8.d.ts} +6 -6
  260. package/dist/cli.d.ts +16 -14
  261. package/dist/cli.js +154 -149
  262. package/dist/coding/export-okf-codegraph.d.ts +2 -1
  263. package/dist/coding/export-okf-codegraph.js +37 -37
  264. package/dist/coding/pre-action-gate.d.ts +2 -1
  265. package/dist/coding/pre-action-gate.js +4 -3
  266. package/dist/commitment-ledger.js +3 -2
  267. package/dist/compounding/engine.d.ts +3 -2
  268. package/dist/compounding/engine.js +37 -37
  269. package/dist/compounding/preference-consolidator.d.ts +2 -1
  270. package/dist/compression-optimizer.d.ts +2 -1
  271. package/dist/config.d.ts +2 -1
  272. package/dist/config.js +16 -13
  273. package/dist/connectors/codex-materialize-runner.d.ts +2 -1
  274. package/dist/connectors/codex-materialize-runner.js +38 -38
  275. package/dist/connectors/codex-materialize.d.ts +2 -1
  276. package/dist/connectors/codex-materialize.js +4 -4
  277. package/dist/connectors/index.d.ts +2 -1
  278. package/dist/connectors/index.js +38 -38
  279. package/dist/consolidation-provenance-check.d.ts +3 -2
  280. package/dist/consolidation-provenance-check.js +4 -4
  281. package/dist/consolidation-undo.d.ts +3 -2
  282. package/dist/consolidation-undo.js +3 -3
  283. package/dist/contradiction/index.d.ts +4 -3
  284. package/dist/contradiction/index.js +9 -9
  285. package/dist/converge-config.d.ts +2 -1
  286. package/dist/convergence-refresh.d.ts +3 -2
  287. package/dist/convergence-refresh.js +38 -38
  288. package/dist/conversation-index/backend.d.ts +2 -1
  289. package/dist/conversation-index/chunker.d.ts +2 -1
  290. package/dist/conversation-index/faiss-adapter.d.ts +2 -1
  291. package/dist/conversation-index/indexer.d.ts +2 -1
  292. package/dist/conversation-index/search.d.ts +2 -1
  293. package/dist/corpus-watermark.d.ts +2 -1
  294. package/dist/corpus-watermark.js +38 -38
  295. package/dist/cross-lingual-recall.d.ts +2 -1
  296. package/dist/cue-anchors.js +4 -3
  297. package/dist/dashboard-runtime.js +2 -2
  298. package/dist/day-summary.d.ts +2 -1
  299. package/dist/deep-recall-http-glue.d.ts +14 -12
  300. package/dist/deep-recall-http-glue.js +9 -8
  301. package/dist/deep-recall-mcp-tools.d.ts +14 -12
  302. package/dist/deep-recall-policy-llm.d.ts +2 -1
  303. package/dist/deep-recall-seeds.d.ts +2 -1
  304. package/dist/deep-recall.js +2 -2
  305. package/dist/delinearize.d.ts +2 -1
  306. package/dist/dependency-propagation-config.d.ts +2 -1
  307. package/dist/{dependency-propagation-delivery-DjpUlhLi.d.ts → dependency-propagation-delivery-CQPCu0o5.d.ts} +1 -1
  308. package/dist/direct-answer-wiring.d.ts +2 -1
  309. package/dist/direct-answer.d.ts +2 -1
  310. package/dist/embedding-fallback.d.ts +2 -1
  311. package/dist/enrichment/index.d.ts +2 -1
  312. package/dist/entity-origin-fields.d.ts +2 -1
  313. package/dist/entity-retrieval.d.ts +3 -2
  314. package/dist/entity-retrieval.js +36 -36
  315. package/dist/entity-schema.d.ts +2 -1
  316. package/dist/episodic-context.d.ts +2 -1
  317. package/dist/eval-trajectory-contracts.d.ts +2 -1
  318. package/dist/eval-trajectory-store.d.ts +2 -1
  319. package/dist/eval-trajectory-store.js +4 -3
  320. package/dist/eval-trajectory.d.ts +2 -1
  321. package/dist/eval-trajectory.js +4 -3
  322. package/dist/evals.js +3 -2
  323. package/dist/event-order-recall.js +2 -2
  324. package/dist/explicit-capture.d.ts +12 -10
  325. package/dist/explicit-capture.js +10 -10
  326. package/dist/external-wiki-access.d.ts +14 -12
  327. package/dist/external-wiki-access.js +95 -92
  328. package/dist/external-wiki-collection-registration.d.ts +2 -1
  329. package/dist/external-wiki-collection.d.ts +2 -1
  330. package/dist/external-wiki-mcp-tools.d.ts +14 -12
  331. package/dist/extraction-error-classification.d.ts +2 -1
  332. package/dist/extraction-faithfulness.d.ts +2 -1
  333. package/dist/extraction-judge-telemetry.d.ts +2 -1
  334. package/dist/extraction-judge-training.d.ts +2 -1
  335. package/dist/extraction-judge.d.ts +2 -1
  336. package/dist/extraction-liveness.d.ts +2 -1
  337. package/dist/extraction-normalization.d.ts +2 -1
  338. package/dist/extraction-prompt.d.ts +2 -1
  339. package/dist/extraction-source-grounding-rules.d.ts +2 -1
  340. package/dist/extraction-source-grounding.d.ts +2 -1
  341. package/dist/extraction.d.ts +2 -1
  342. package/dist/extraction.js +43 -43
  343. package/dist/fallback-llm.d.ts +2 -1
  344. package/dist/{first-start-migration-KHIMCBIC.js → first-start-migration-RC345GPL.js} +6 -5
  345. package/dist/{first-start-migration-KHIMCBIC.js.map → first-start-migration-RC345GPL.js.map} +1 -1
  346. package/dist/{forget-2AE4MDK3.js → forget-SZ2BXDGF.js} +3 -3
  347. package/dist/{graph-444E-DrF.d.ts → graph-DRkl22KE.d.ts} +10 -12
  348. package/dist/graph-append-error.d.ts +40 -0
  349. package/dist/graph-append-error.js +8 -0
  350. package/dist/graph-dashboard-diff.d.ts +5 -2
  351. package/dist/graph-dashboard-key.d.ts +5 -2
  352. package/dist/graph-dashboard-parser.d.ts +5 -2
  353. package/dist/{graph-edge-decay-DGTBFALQ.js → graph-edge-decay-MKIRZ762.js} +10 -4
  354. package/dist/graph-edge-decay-MKIRZ762.js.map +1 -0
  355. package/dist/graph-edge-reinforcement.d.ts +5 -2
  356. package/dist/graph-jsonl.d.ts +82 -0
  357. package/dist/graph-jsonl.js +23 -0
  358. package/dist/graph-jsonl.js.map +1 -0
  359. package/dist/graph-path-reconstruction.d.ts +5 -2
  360. package/dist/graph-path-scoring.d.ts +5 -2
  361. package/dist/graph-snapshot.d.ts +5 -2
  362. package/dist/graph-snapshot.js +7 -3
  363. package/dist/graph-write-lock.d.ts +84 -0
  364. package/dist/graph-write-lock.js +15 -0
  365. package/dist/graph-write-lock.js.map +1 -0
  366. package/dist/graph.d.ts +5 -2
  367. package/dist/graph.js +10 -3
  368. package/dist/harmonic-construction.js +5 -4
  369. package/dist/harmonic-retrieval.js +5 -4
  370. package/dist/importance.d.ts +2 -1
  371. package/dist/importers/index.d.ts +2 -1
  372. package/dist/in-flight-reads.d.ts +2 -1
  373. package/dist/{index-CsUrdMyL.d.ts → index-C9VXenR8.d.ts} +2 -2
  374. package/dist/index.d.ts +39 -25
  375. package/dist/index.js +291 -284
  376. package/dist/intent.d.ts +2 -1
  377. package/dist/json-store.js +2 -1
  378. package/dist/lcm/engine.d.ts +2 -1
  379. package/dist/lcm/engine.js +3 -3
  380. package/dist/lcm/index.d.ts +2 -1
  381. package/dist/lcm/index.js +6 -6
  382. package/dist/lcm/tools.d.ts +2 -1
  383. package/dist/lifecycle.d.ts +2 -1
  384. package/dist/live-connectors-runner.d.ts +2 -1
  385. package/dist/live-connectors-runner.js +3 -2
  386. package/dist/local-llm.d.ts +2 -1
  387. package/dist/local-model-endpoint.d.ts +2 -1
  388. package/dist/location/index.d.ts +4 -3
  389. package/dist/location/index.js +39 -39
  390. package/dist/maintenance/memory-governance.d.ts +2 -1
  391. package/dist/maintenance/memory-governance.js +36 -36
  392. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +3 -2
  393. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +36 -36
  394. package/dist/maintenance/rebuild-memory-projection.d.ts +3 -2
  395. package/dist/maintenance/rebuild-memory-projection.js +37 -37
  396. package/dist/{maintenance-D1GRGLTE.d.ts → maintenance-C14sorKa.d.ts} +3 -3
  397. package/dist/mcp-memory-inspector-app.d.ts +14 -12
  398. package/dist/memory-action-policy.d.ts +2 -1
  399. package/dist/memory-cache.d.ts +2 -1
  400. package/dist/memory-controller.d.ts +2 -1
  401. package/dist/memory-lifecycle-ledger-utils.d.ts +2 -1
  402. package/dist/memory-projection-mutations.js +3 -3
  403. package/dist/memory-projection-store.d.ts +2 -1
  404. package/dist/memory-provenance.d.ts +2 -1
  405. package/dist/memory-snapshot.d.ts +2 -1
  406. package/dist/memory-subject-cli.d.ts +14 -12
  407. package/dist/memory-subject.d.ts +14 -12
  408. package/dist/memory-subject.js +5 -5
  409. package/dist/memory-worth-outcomes.d.ts +3 -2
  410. package/dist/models-json.d.ts +2 -1
  411. package/dist/namespaces/migrate.d.ts +4 -3
  412. package/dist/namespaces/migrate.js +37 -37
  413. package/dist/namespaces/principal.d.ts +2 -1
  414. package/dist/namespaces/search.d.ts +2 -1
  415. package/dist/namespaces/search.js +11 -11
  416. package/dist/namespaces/storage.d.ts +4 -3
  417. package/dist/namespaces/storage.js +36 -36
  418. package/dist/native-knowledge.d.ts +2 -1
  419. package/dist/objective-state-writers.js +4 -3
  420. package/dist/objective-state.js +3 -2
  421. package/dist/offline-sync-file-io.js +4 -3
  422. package/dist/offline-sync-impression-drain.d.ts +2 -1
  423. package/dist/offline-sync-impression-drain.js +7 -7
  424. package/dist/offline-sync.js +5 -4
  425. package/dist/operator-doctor-corpus.d.ts +2 -1
  426. package/dist/operator-doctor-corpus.js +39 -39
  427. package/dist/operator-doctor-replica.d.ts +2 -1
  428. package/dist/operator-toolkit.d.ts +6 -4
  429. package/dist/operator-toolkit.js +61 -58
  430. package/dist/orchestration/compression-guideline-coordinator.d.ts +3 -2
  431. package/dist/orchestration/maintenance.d.ts +5 -4
  432. package/dist/orchestration/maintenance.js +46 -46
  433. package/dist/{orchestrator-DeqaPGT5.d.ts → orchestrator-DgyvFfPR.d.ts} +9 -9
  434. package/dist/orchestrator.d.ts +12 -10
  435. package/dist/orchestrator.js +201 -196
  436. package/dist/page-versioning.d.ts +73 -4
  437. package/dist/page-versioning.js +11 -3
  438. package/dist/patterns-cli.d.ts +2 -1
  439. package/dist/{pipeline-umUzU0D1.d.ts → pipeline-DRUwHb1X.d.ts} +1 -1
  440. package/dist/policy-runtime.d.ts +2 -1
  441. package/dist/proactive-contention.d.ts +2 -1
  442. package/dist/provenance.d.ts +2 -1
  443. package/dist/{public-http-Bevrjll9.d.ts → public-http-C4i8Opxc.d.ts} +1 -1
  444. package/dist/{purge-OP6BEDFY.js → purge-TZKRE6ZQ.js} +5 -5
  445. package/dist/purge-TZKRE6ZQ.js.map +1 -0
  446. package/dist/{qmd-BasT78PP.d.ts → qmd-BVWlg1YS.d.ts} +1 -1
  447. package/dist/qmd-preflight.d.ts +3 -2
  448. package/dist/qmd-recall-cache.d.ts +2 -1
  449. package/dist/qmd.d.ts +3 -2
  450. package/dist/qmd.js +4 -4
  451. package/dist/recall-concurrency-config.d.ts +2 -1
  452. package/dist/recall-disclosure-escalation.d.ts +2 -1
  453. package/dist/recall-explain-renderer.d.ts +2 -1
  454. package/dist/recall-explain-renderer.js +3 -3
  455. package/dist/recall-memory-map.d.ts +2 -1
  456. package/dist/recall-navigate-access.d.ts +2 -1
  457. package/dist/recall-navigate-access.js +2 -2
  458. package/dist/recall-navigate-disclosure.d.ts +2 -1
  459. package/dist/recall-navigate-disclosure.js +1 -1
  460. package/dist/recall-navigate.d.ts +2 -1
  461. package/dist/recall-navigate.js +2 -2
  462. package/dist/recall-planner-llm.d.ts +2 -1
  463. package/dist/recall-state.d.ts +2 -1
  464. package/dist/recall-state.js +3 -3
  465. package/dist/recall-tag-filter.d.ts +2 -1
  466. package/dist/recall-timings.d.ts +2 -1
  467. package/dist/recall-xray-cli.d.ts +2 -1
  468. package/dist/recall-xray-cli.js +4 -4
  469. package/dist/recall-xray-renderer.d.ts +2 -1
  470. package/dist/recall-xray-renderer.js +3 -3
  471. package/dist/recall-xray.d.ts +2 -1
  472. package/dist/recall-xray.js +2 -2
  473. package/dist/reconcile/cursor.d.ts +2 -1
  474. package/dist/reconcile/manifest.d.ts +2 -1
  475. package/dist/reconcile/manifest.js +7 -7
  476. package/dist/reconcile/plan.d.ts +2 -1
  477. package/dist/replay/normalizers/chatgpt.d.ts +2 -1
  478. package/dist/replay/normalizers/claude.d.ts +2 -1
  479. package/dist/replay/normalizers/openclaw.d.ts +2 -1
  480. package/dist/replay/normalizers/shared.d.ts +2 -1
  481. package/dist/replay/runner.d.ts +2 -1
  482. package/dist/replay/types.d.ts +2 -1
  483. package/dist/replica-divergence.d.ts +2 -1
  484. package/dist/replica-peers-config.d.ts +2 -1
  485. package/dist/{resolution-4DLI3IOR.js → resolution-VKATP2HT.js} +10 -10
  486. package/dist/resolution-VKATP2HT.js.map +1 -0
  487. package/dist/resolve-auth-token.d.ts +2 -1
  488. package/dist/resume-bundles.js +21 -18
  489. package/dist/retrieval-agents.d.ts +3 -2
  490. package/dist/retrieval-tiers.d.ts +2 -1
  491. package/dist/routing/engine.d.ts +2 -1
  492. package/dist/routing/store.d.ts +2 -1
  493. package/dist/salvage-envelope.d.ts +2 -1
  494. package/dist/salvage-envelope.js +7 -7
  495. package/dist/{scope-profiles-DXYzyOXW.d.ts → scope-profiles-Vl00B1KU.d.ts} +1 -1
  496. package/dist/search/document-scanner.js +3 -3
  497. package/dist/search/embed-helper.d.ts +2 -1
  498. package/dist/search/factory.d.ts +2 -1
  499. package/dist/search/factory.js +10 -10
  500. package/dist/search/index.d.ts +2 -1
  501. package/dist/search/index.js +16 -16
  502. package/dist/search/lancedb-backend.d.ts +2 -1
  503. package/dist/search/lancedb-backend.js +4 -4
  504. package/dist/search/meilisearch-backend.d.ts +2 -1
  505. package/dist/search/meilisearch-backend.js +4 -4
  506. package/dist/search/noop-backend.d.ts +2 -1
  507. package/dist/search/orama-backend.d.ts +2 -1
  508. package/dist/search/orama-backend.js +4 -4
  509. package/dist/search/port.d.ts +2 -1
  510. package/dist/search/remote-backend.d.ts +2 -1
  511. package/dist/secure-store/index.js +3 -3
  512. package/dist/{semantic-consolidation-CqDeaY0U.d.ts → semantic-consolidation-BC9-GFuT.d.ts} +1 -1
  513. package/dist/semantic-consolidation.d.ts +3 -2
  514. package/dist/semantic-consolidation.js +39 -39
  515. package/dist/semantic-merge-config.d.ts +17 -0
  516. package/dist/semantic-merge-config.js +1 -0
  517. package/dist/semantic-merge-config.js.map +1 -0
  518. package/dist/semantic-rule-promotion.js +36 -36
  519. package/dist/semantic-rule-verifier.d.ts +2 -1
  520. package/dist/semantic-rule-verifier.js +36 -36
  521. package/dist/{service-BKD-DVYZ.d.ts → service-BOy6dHfc.d.ts} +2 -2
  522. package/dist/session-observer-bands.d.ts +2 -1
  523. package/dist/session-observer-state.d.ts +2 -1
  524. package/dist/shared-context/manager.d.ts +2 -1
  525. package/dist/signal.d.ts +2 -1
  526. package/dist/source-agent-qualifier.d.ts +2 -1
  527. package/dist/source-agent-qualifier.js +42 -42
  528. package/dist/source-attribution.d.ts +18 -6
  529. package/dist/source-attribution.js +3 -1
  530. package/dist/standup/build.js +36 -36
  531. package/dist/{storage-BcFd1lN_.d.ts → storage-BLJRnFi6.d.ts} +15 -8
  532. package/dist/storage.d.ts +3 -2
  533. package/dist/storage.js +35 -35
  534. package/dist/subject-config.d.ts +2 -1
  535. package/dist/subject-config.js +6 -6
  536. package/dist/summarizer.d.ts +2 -1
  537. package/dist/summary-snapshot.d.ts +2 -1
  538. package/dist/support-passport/index.d.ts +17 -15
  539. package/dist/support-passport/index.js +97 -94
  540. package/dist/temporal-supersession.d.ts +3 -2
  541. package/dist/temporal-timeline-recall.d.ts +2 -1
  542. package/dist/temporal-validity.d.ts +2 -1
  543. package/dist/threading.d.ts +2 -1
  544. package/dist/tier-migration.d.ts +3 -2
  545. package/dist/tier-routing.d.ts +2 -1
  546. package/dist/{tier-stats-2TOW3QNL.js → tier-stats-KA6OZX2C.js} +6 -5
  547. package/dist/{tier-stats-2TOW3QNL.js.map → tier-stats-KA6OZX2C.js.map} +1 -1
  548. package/dist/topics.d.ts +2 -1
  549. package/dist/transcript.d.ts +2 -1
  550. package/dist/transfer/backup.js +2 -2
  551. package/dist/transfer/capsule-export.js +2 -2
  552. package/dist/transfer/capsule-import.js +6 -6
  553. package/dist/transfer/export-okf.d.ts +2 -1
  554. package/dist/transfer/export-okf.js +37 -37
  555. package/dist/trust-score-stage.d.ts +2 -1
  556. package/dist/trust-score.d.ts +2 -1
  557. package/dist/trust-zones.js +3 -2
  558. package/dist/{types-BRg3tMyp.d.ts → types-YY-eKKU7.d.ts} +3 -0
  559. package/dist/types.d.ts +2 -1
  560. package/dist/types.js +1 -1
  561. package/dist/utility-learner.js +4 -3
  562. package/dist/utility-runtime.d.ts +2 -1
  563. package/dist/utility-runtime.js +5 -4
  564. package/dist/utility-telemetry.js +3 -2
  565. package/dist/verified-recall.js +36 -36
  566. package/dist/who-knows-cli.d.ts +14 -12
  567. package/dist/who-knows-cli.js +37 -37
  568. package/dist/who-knows.d.ts +14 -12
  569. package/dist/who-knows.js +36 -36
  570. package/dist/work/board.js +3 -3
  571. package/dist/work/storage.js +2 -2
  572. package/dist/work-product-ledger.js +3 -2
  573. package/dist/write-envelope.d.ts +2 -1
  574. package/dist/write-envelope.js +6 -6
  575. package/package.json +2 -2
  576. package/src/abstraction-nodes.ts +1 -4
  577. package/src/access-http-briefing.ts +35 -0
  578. package/src/access-http.test.ts +76 -0
  579. package/src/access-http.ts +20 -23
  580. package/src/access-surface-catalog.test.ts +9 -0
  581. package/src/access-surface-catalog.ts +1 -0
  582. package/src/binary-lifecycle/backend.ts +2 -1
  583. package/src/config.ts +2 -0
  584. package/src/connectors/live/github.ts +10 -17
  585. package/src/connectors/live/gmail.ts +8 -19
  586. package/src/connectors/live/google-drive.ts +6 -13
  587. package/src/connectors/live/notion.ts +11 -21
  588. package/src/cue-anchors.ts +1 -6
  589. package/src/dedup/connector-scope.ts +39 -0
  590. package/src/dedup/merge-content.test.ts +21 -0
  591. package/src/dedup/merge-content.ts +21 -7
  592. package/src/dedup/merge-judge.ts +146 -0
  593. package/src/dedup/merge.test.ts +3542 -0
  594. package/src/dedup/merge.ts +384 -0
  595. package/src/dedup/novelty-gate.ts +12 -10
  596. package/src/dedup/semantic.ts +7 -9
  597. package/src/graph-append-error.ts +28 -0
  598. package/src/graph-jsonl.ts +267 -0
  599. package/src/graph-write-lock.test.ts +228 -0
  600. package/src/graph-write-lock.ts +132 -0
  601. package/src/graph.ts +49 -45
  602. package/src/harmonic-construction.test.ts +329 -0
  603. package/src/json-store.ts +17 -20
  604. package/src/live-connectors-runner.ts +2 -1
  605. package/src/location/store.ts +1 -4
  606. package/src/maintenance/graph-edge-decay.ts +24 -13
  607. package/src/maintenance/purge.ts +2 -5
  608. package/src/maintenance/rebuild-memory-lifecycle-ledger.ts +3 -6
  609. package/src/maintenance/rebuild-memory-projection.ts +2 -5
  610. package/src/namespaces/catalog.ts +1 -9
  611. package/src/offline-sync-file-io.test.ts +39 -0
  612. package/src/offline-sync-file-io.ts +3 -7
  613. package/src/orchestration/contradiction-localization.integration.test.ts +35 -0
  614. package/src/orchestration/extraction-anchor-snapshot.ts +6 -1
  615. package/src/orchestration/extraction-persist-deps.ts +2 -1
  616. package/src/orchestration/extraction-persist-profile-promotion.test.ts +456 -0
  617. package/src/orchestration/extraction-persist-promotion.test.ts +534 -0
  618. package/src/orchestration/extraction-persist-promotion.ts +387 -1
  619. package/src/orchestration/extraction-persist.ts +95 -94
  620. package/src/orchestration/harmonic-construction-persist.test.ts +69 -0
  621. package/src/orchestration/harmonic-construction-persist.ts +55 -0
  622. package/src/orchestration/persistence-index.ts +35 -7
  623. package/src/orchestration/semantic-merge-commit-effects.ts +354 -0
  624. package/src/orchestration/semantic-merge-persist.ts +1095 -0
  625. package/src/orchestration/semantic-merge-promotion-payload.ts +161 -0
  626. package/src/orchestrator.ts +2 -2
  627. package/src/page-versioning.ts +396 -22
  628. package/src/procedural/procedure-miner.ts +1 -9
  629. package/src/search/document-scanner.ts +3 -6
  630. package/src/semantic-merge-config.ts +16 -0
  631. package/src/semantic-rule-promotion.ts +1 -4
  632. package/src/source-attribution-roundtrip.test.ts +21 -0
  633. package/src/source-attribution.ts +57 -17
  634. package/src/storage-contract/versioning.test.ts +500 -1
  635. package/src/storage.ts +30 -30
  636. package/src/testing/subjects/graph-edge-decay.test.ts +163 -0
  637. package/src/testing/subjects/semantic-merge-lifecycle.test.ts +1175 -0
  638. package/src/types.ts +2 -0
  639. package/src/utils/errno.test.ts +31 -0
  640. package/src/utils/errno.ts +5 -0
  641. package/src/wearables/index.ts +1 -0
  642. package/src/wearables/registry.ts +23 -0
  643. package/dist/chunk-5UZXUTVO.js.map +0 -1
  644. package/dist/chunk-7GSSHAXC.js.map +0 -1
  645. package/dist/chunk-ACPCA4NO.js.map +0 -1
  646. package/dist/chunk-C2JCVZWX.js.map +0 -1
  647. package/dist/chunk-DDQQY2E3.js.map +0 -1
  648. package/dist/chunk-DJUKBGAD.js.map +0 -1
  649. package/dist/chunk-DK6GMO6D.js.map +0 -1
  650. package/dist/chunk-DP4EBV7C.js.map +0 -1
  651. package/dist/chunk-FCATYKQA.js.map +0 -1
  652. package/dist/chunk-GGYDJJBO.js.map +0 -1
  653. package/dist/chunk-HTIIXNJQ.js.map +0 -1
  654. package/dist/chunk-KK66P5GQ.js.map +0 -1
  655. package/dist/chunk-NQFCLAYT.js.map +0 -1
  656. package/dist/chunk-NYRB7BKY.js.map +0 -1
  657. package/dist/chunk-OGTKQ5MJ.js.map +0 -1
  658. package/dist/chunk-OLT3YTDH.js.map +0 -1
  659. package/dist/chunk-P77QX3ID.js.map +0 -1
  660. package/dist/chunk-U62OK7BB.js.map +0 -1
  661. package/dist/chunk-UR6PBX2J.js.map +0 -1
  662. package/dist/chunk-VLAQV4HT.js.map +0 -1
  663. package/dist/chunk-W7IGLX4G.js.map +0 -1
  664. package/dist/purge-OP6BEDFY.js.map +0 -1
  665. /package/dist/{capsule-crypto-7FJQINUR.js.map → access-http-briefing.js.map} +0 -0
  666. /package/dist/{auto-sync-GRUJFD2F.js.map → auto-sync-WNGG2GC2.js.map} +0 -0
  667. /package/dist/{graph-edge-decay-DGTBFALQ.js.map → capsule-crypto-YO5QJ6L3.js.map} +0 -0
  668. /package/dist/{capsule-merge-SEHERWWP.js.map → capsule-merge-IPG4IOFP.js.map} +0 -0
  669. /package/dist/{chunk-KTVSPFCQ.js.map → chunk-22FVR2KE.js.map} +0 -0
  670. /package/dist/{chunk-7Y5V3LAP.js.map → chunk-27QVNSQ3.js.map} +0 -0
  671. /package/dist/{chunk-R7LY4YKF.js.map → chunk-2EKJDQZB.js.map} +0 -0
  672. /package/dist/{chunk-HOUST5UX.js.map → chunk-2ITE4C2Z.js.map} +0 -0
  673. /package/dist/{chunk-JOYC4RYC.js.map → chunk-2JVJ7UHC.js.map} +0 -0
  674. /package/dist/{chunk-X2NFFBTO.js.map → chunk-2L5FSNPC.js.map} +0 -0
  675. /package/dist/{chunk-DUAJKRR2.js.map → chunk-2SGLMP2E.js.map} +0 -0
  676. /package/dist/{chunk-6FUMA6AA.js.map → chunk-2Z4GS5E6.js.map} +0 -0
  677. /package/dist/{chunk-G6MXN2G5.js.map → chunk-37KUQPX4.js.map} +0 -0
  678. /package/dist/{chunk-WKAXBXVA.js.map → chunk-3QQTXYZ6.js.map} +0 -0
  679. /package/dist/{chunk-4ZWCQJNM.js.map → chunk-46WM6JX2.js.map} +0 -0
  680. /package/dist/{chunk-CASWJ2HM.js.map → chunk-46ZPIGWI.js.map} +0 -0
  681. /package/dist/{chunk-MCA2X4WH.js.map → chunk-4IHBN6WU.js.map} +0 -0
  682. /package/dist/{chunk-FB7LAJQM.js.map → chunk-4TKJGOCJ.js.map} +0 -0
  683. /package/dist/{chunk-H7BZBSP6.js.map → chunk-52II7PB6.js.map} +0 -0
  684. /package/dist/{chunk-N4Y5T6VD.js.map → chunk-54WHLA65.js.map} +0 -0
  685. /package/dist/{chunk-YVLENSNS.js.map → chunk-5ATKSPEQ.js.map} +0 -0
  686. /package/dist/{chunk-ZVZHG7AI.js.map → chunk-5UBH37SL.js.map} +0 -0
  687. /package/dist/{chunk-N3WZU76A.js.map → chunk-66OJSCI6.js.map} +0 -0
  688. /package/dist/{chunk-D35XLYQ7.js.map → chunk-6CVNSDCZ.js.map} +0 -0
  689. /package/dist/{chunk-KA2HZCMG.js.map → chunk-6NXSYYGP.js.map} +0 -0
  690. /package/dist/{chunk-2HIJHXB3.js.map → chunk-6WHJ2EAB.js.map} +0 -0
  691. /package/dist/{chunk-ZZM476NV.js.map → chunk-6XL73HQ4.js.map} +0 -0
  692. /package/dist/{chunk-EJ5RKUXW.js.map → chunk-AQ7SYDVO.js.map} +0 -0
  693. /package/dist/{chunk-2Z3DG5CQ.js.map → chunk-B3O3IRZN.js.map} +0 -0
  694. /package/dist/{chunk-RACZB5HT.js.map → chunk-BD7JTBYP.js.map} +0 -0
  695. /package/dist/{chunk-I762GW7V.js.map → chunk-BLJWYCNO.js.map} +0 -0
  696. /package/dist/{chunk-2NLLXCJG.js.map → chunk-BXLOS5AJ.js.map} +0 -0
  697. /package/dist/{chunk-GCASGYIO.js.map → chunk-C7HJ3NEI.js.map} +0 -0
  698. /package/dist/{chunk-C24UZSFW.js.map → chunk-CEH2AFXG.js.map} +0 -0
  699. /package/dist/{chunk-WVGXCBOC.js.map → chunk-D5F7TKMH.js.map} +0 -0
  700. /package/dist/{chunk-X7Y7WX73.js.map → chunk-DQEMWVMT.js.map} +0 -0
  701. /package/dist/{chunk-2OXIPF3A.js.map → chunk-DZD3WGCD.js.map} +0 -0
  702. /package/dist/{chunk-UMEOXLIZ.js.map → chunk-E2P7TZTF.js.map} +0 -0
  703. /package/dist/{chunk-6FC3IZ26.js.map → chunk-EBA5DA77.js.map} +0 -0
  704. /package/dist/{chunk-N7JK2RKG.js.map → chunk-EOQ6FSQP.js.map} +0 -0
  705. /package/dist/{chunk-YNDLCWXS.js.map → chunk-EZ25VE3G.js.map} +0 -0
  706. /package/dist/{chunk-XDMI5VKE.js.map → chunk-FVOP3NT7.js.map} +0 -0
  707. /package/dist/{chunk-NRLELHAY.js.map → chunk-G7NYVKD6.js.map} +0 -0
  708. /package/dist/{chunk-B3W7GWQB.js.map → chunk-GHTSNGBZ.js.map} +0 -0
  709. /package/dist/{chunk-LUDBXTBJ.js.map → chunk-H272ZPQ3.js.map} +0 -0
  710. /package/dist/{chunk-SN4JXNLL.js.map → chunk-H3TKENU4.js.map} +0 -0
  711. /package/dist/{chunk-4HYNMLT6.js.map → chunk-H4SEGIZY.js.map} +0 -0
  712. /package/dist/{chunk-ACZN5ZXD.js.map → chunk-H54VWRPS.js.map} +0 -0
  713. /package/dist/{chunk-HTP6XRUI.js.map → chunk-HM7RHKS4.js.map} +0 -0
  714. /package/dist/{chunk-Z3SQEEB6.js.map → chunk-HWLIMQE2.js.map} +0 -0
  715. /package/dist/{chunk-2QSZNTDO.js.map → chunk-JBPKEARU.js.map} +0 -0
  716. /package/dist/{chunk-ET2CNMLD.js.map → chunk-JN72EPOE.js.map} +0 -0
  717. /package/dist/{chunk-JCCWJHOP.js.map → chunk-JYZSRNR7.js.map} +0 -0
  718. /package/dist/{chunk-7D6HXODY.js.map → chunk-K7724CH2.js.map} +0 -0
  719. /package/dist/{chunk-X33MJFD2.js.map → chunk-KAXCYM66.js.map} +0 -0
  720. /package/dist/{chunk-7RRUHJPG.js.map → chunk-KB2G2I6Q.js.map} +0 -0
  721. /package/dist/{chunk-ZXBTTMGZ.js.map → chunk-KEF46KL2.js.map} +0 -0
  722. /package/dist/{chunk-UWTDARPF.js.map → chunk-KTWG7CNY.js.map} +0 -0
  723. /package/dist/{chunk-XQYTSZW3.js.map → chunk-L7Z57SID.js.map} +0 -0
  724. /package/dist/{chunk-JMAG7WZ7.js.map → chunk-LO4UKPKX.js.map} +0 -0
  725. /package/dist/{chunk-LDWIPYJ6.js.map → chunk-LS2FHUML.js.map} +0 -0
  726. /package/dist/{chunk-GDB4J2H3.js.map → chunk-MPC7TYTZ.js.map} +0 -0
  727. /package/dist/{chunk-2GF27PGH.js.map → chunk-MRPOZBJC.js.map} +0 -0
  728. /package/dist/{chunk-BR3OOQZQ.js.map → chunk-MWN6QEI2.js.map} +0 -0
  729. /package/dist/{chunk-NZGO2GKL.js.map → chunk-MY5EDR46.js.map} +0 -0
  730. /package/dist/{chunk-LCMUZDBZ.js.map → chunk-N3ZOP7KC.js.map} +0 -0
  731. /package/dist/{chunk-TVW4C7PV.js.map → chunk-NB3LRY4T.js.map} +0 -0
  732. /package/dist/{chunk-QJCWK2A7.js.map → chunk-ND6IQGSZ.js.map} +0 -0
  733. /package/dist/{chunk-NOB2T2FC.js.map → chunk-NHLLKEKK.js.map} +0 -0
  734. /package/dist/{chunk-EJIWBTVM.js.map → chunk-O6ZNNVSP.js.map} +0 -0
  735. /package/dist/{chunk-AG46P24C.js.map → chunk-OB3XMWX5.js.map} +0 -0
  736. /package/dist/{chunk-46QMN7I7.js.map → chunk-PAZY2ZKP.js.map} +0 -0
  737. /package/dist/{chunk-EF4JUM55.js.map → chunk-PX4UMA5Z.js.map} +0 -0
  738. /package/dist/{chunk-NNZFPYYX.js.map → chunk-R7QY5ZVB.js.map} +0 -0
  739. /package/dist/{chunk-RO2X2EYM.js.map → chunk-R7RTXEYG.js.map} +0 -0
  740. /package/dist/{chunk-3LJPSRAN.js.map → chunk-RBCQVOVJ.js.map} +0 -0
  741. /package/dist/{chunk-N4F7ZSSG.js.map → chunk-RC5DXXWC.js.map} +0 -0
  742. /package/dist/{chunk-5CF2R4NS.js.map → chunk-RKBLRTNT.js.map} +0 -0
  743. /package/dist/{chunk-5QZR2RA3.js.map → chunk-ROBHL3GL.js.map} +0 -0
  744. /package/dist/{chunk-D5ZNOKR7.js.map → chunk-S7T2TY65.js.map} +0 -0
  745. /package/dist/{chunk-3LADWWMA.js.map → chunk-SJDQ5RSN.js.map} +0 -0
  746. /package/dist/{chunk-CHWUICVY.js.map → chunk-SV4Z2S67.js.map} +0 -0
  747. /package/dist/{chunk-SEF4IOFE.js.map → chunk-SWIKABKI.js.map} +0 -0
  748. /package/dist/{chunk-JRRQ747T.js.map → chunk-TBXAY2SS.js.map} +0 -0
  749. /package/dist/{chunk-XZBXINXZ.js.map → chunk-TNSCIPBQ.js.map} +0 -0
  750. /package/dist/{chunk-S37NN23M.js.map → chunk-TVEONGBU.js.map} +0 -0
  751. /package/dist/{chunk-5RPMTFB6.js.map → chunk-TWF35IC6.js.map} +0 -0
  752. /package/dist/{chunk-BZTJEILZ.js.map → chunk-U6N5IBVY.js.map} +0 -0
  753. /package/dist/{chunk-7TUB6JWA.js.map → chunk-UCKYTA2T.js.map} +0 -0
  754. /package/dist/{chunk-PPOT6SPR.js.map → chunk-UNNPNBR2.js.map} +0 -0
  755. /package/dist/{chunk-KQAFEZQX.js.map → chunk-VDX2J7OX.js.map} +0 -0
  756. /package/dist/{chunk-J2R275FN.js.map → chunk-VVX5PZFS.js.map} +0 -0
  757. /package/dist/{chunk-ME35HVDJ.js.map → chunk-VYCOJKSX.js.map} +0 -0
  758. /package/dist/{chunk-F5UWQ4LX.js.map → chunk-W24T5YMW.js.map} +0 -0
  759. /package/dist/{chunk-HDQUQBPW.js.map → chunk-W3K3HITK.js.map} +0 -0
  760. /package/dist/{chunk-GDASG7NC.js.map → chunk-W4F3C7N7.js.map} +0 -0
  761. /package/dist/{chunk-LFK623SF.js.map → chunk-WJHGDE7X.js.map} +0 -0
  762. /package/dist/{chunk-3Q6RD76J.js.map → chunk-WQZZDN5M.js.map} +0 -0
  763. /package/dist/{chunk-ZJWDWPX6.js.map → chunk-X5K5TAQZ.js.map} +0 -0
  764. /package/dist/{chunk-ZL3XX5LW.js.map → chunk-XM24CDZX.js.map} +0 -0
  765. /package/dist/{chunk-JTWZKNUH.js.map → chunk-XOVKXJEP.js.map} +0 -0
  766. /package/dist/{chunk-X5YYSAZX.js.map → chunk-XUE46UYW.js.map} +0 -0
  767. /package/dist/{chunk-DJORULH3.js.map → chunk-YRLHEEQT.js.map} +0 -0
  768. /package/dist/{chunk-TA7UZZMW.js.map → chunk-Z3O53WZR.js.map} +0 -0
  769. /package/dist/{chunk-4LG4CPOC.js.map → chunk-Z6COGHHN.js.map} +0 -0
  770. /package/dist/{chunk-RE3H6Y2X.js.map → chunk-ZIW5JVRM.js.map} +0 -0
  771. /package/dist/{forget-2AE4MDK3.js.map → forget-SZ2BXDGF.js.map} +0 -0
  772. /package/dist/{resolution-4DLI3IOR.js.map → graph-append-error.js.map} +0 -0
@@ -0,0 +1,1095 @@
1
+ /**
2
+ * Persist-side executor for judge-mediated merge-on-write (issue #2330, step 3).
3
+ *
4
+ * Lives beside `extraction-persist.ts` so that file stays within its
5
+ * file-size ratchet ceiling. Called once per surviving fact, right before
6
+ * the normal (non-chunked) sealed-envelope write. On every failure mode —
7
+ * disabled gate, empty band, judge refusal, invalid verdict, snapshot or
8
+ * update failure — the outcome is "created" and the caller falls through
9
+ * to the unchanged write path.
10
+ *
11
+ * Exact mutation order (checklist #14/#42): version snapshot FIRST, then
12
+ * the in-place content update, then the frontmatter patch, then hash-index
13
+ * remove/add, then reindex. The new fact's content is never indexed as
14
+ * its own entry — it was never persisted (checklist #32).
15
+ */
16
+
17
+ import path from "node:path";
18
+
19
+ import { buildBehaviorSignalsForMemory } from "../behavior-signals.js";
20
+
21
+ import { isUntrustedOrigin, parseOriginClass } from "../security/origin-authority.js";
22
+ import {
23
+ FallbackLlmClient,
24
+ fallbackLlmRuntimeContextFromConfig,
25
+ } from "../fallback-llm.js";
26
+ import { log } from "../logger.js";
27
+ import { sanitizeMemoryContent } from "../sanitize.js";
28
+ import { ContentHashIndex } from "../storage/content-hash-index.js";
29
+ import type { VersioningConfig } from "../page-versioning.js";
30
+ import {
31
+ committedMergedFactHash,
32
+ discardMergedTargetSnapshot,
33
+ finalizeMergedVersionPrune,
34
+ persistRepairedContentHash,
35
+ rawPreCitationMergedBody,
36
+ readTargetSnapshot,
37
+ revertMergedContent,
38
+ rewriteMergedTargetGraphEdges,
39
+ stageMergedTargetSnapshot,
40
+ } from "./semantic-merge-commit-effects.js";
41
+ import {
42
+ buildMergeFrontmatterUpdate,
43
+ type MergeFrontmatterUpdate,
44
+ type MergeProvenanceSource,
45
+ } from "../dedup/merge-provenance.js";
46
+ import {
47
+ callMergeJudge,
48
+ type MergeJudgeCallOptions,
49
+ } from "../dedup/merge-judge.js";
50
+ import {
51
+ decideSemanticMerge,
52
+ type MergeCreateReason,
53
+ type MergeJudgeRawVerdict,
54
+ } from "../dedup/merge.js";
55
+ import { confidenceTier } from "../types.js";
56
+ import { REFUSED_MERGE_CATEGORIES } from "../dedup/merge-on-write.js";
57
+ import { inferMemoryStatus } from "../memory-lifecycle-ledger-utils.js";
58
+ import { inferIntentFromText } from "../intent.js";
59
+ import {
60
+ hasCitationForTemplate,
61
+ lastCitationMarkerForTemplate,
62
+ stripCitationForTemplate,
63
+ } from "../source-attribution.js";
64
+ import {
65
+ resolveConversationContextCapabilities,
66
+ resolvePipelineProcessingCapabilities,
67
+ resolvePresentationCapabilities,
68
+ resolveRecallAuxiliaryCapabilities,
69
+ type GraphConstructionCapabilitySet,
70
+ } from "../capabilities.js";
71
+ import type { GraphType } from "../graph.js";
72
+ import type {
73
+ BehaviorSignalEvent,
74
+ FaithfulnessFrontmatter,
75
+ MemoryCategory,
76
+ MemoryFile,
77
+ MemoryFrontmatter,
78
+ MemoryLink,
79
+ MemorySubject,
80
+ ProvenanceSource,
81
+ } from "../types.js";
82
+ import { normalizeConnectorScope } from "../dedup/connector-scope.js";
83
+ import type { StorageManager } from "../index.js";
84
+ import type { ExtractionPersistDeps } from "./extraction-persist-deps.js";
85
+
86
+ export type SemanticMergeCreateReason =
87
+ | MergeCreateReason
88
+ | "target_inactive"
89
+ | "target_changed"
90
+ | "metadata_unpreservable"
91
+ | "promoted_copy_present"
92
+ | "snapshot_unavailable"
93
+ | "snapshot_failed"
94
+ | "update_failed"
95
+ | "shadow_would_merge";
96
+
97
+
98
+ export type SemanticMergePersistOutcome =
99
+ | {
100
+ action: "merged";
101
+ targetId: string;
102
+ /**
103
+ * The committed merged body (finding A): the caller's merged-target
104
+ * promotion must copy THIS body — not the incoming fact — so the
105
+ * shared/profile copy serves the same claims its `sourceMemoryId`
106
+ * points at. Present on the degraded branch too, where the merged
107
+ * text is committed even though the provenance patch failed.
108
+ */
109
+ mergedContent: string;
110
+ /**
111
+ * False only in the degraded case where the content update committed,
112
+ * the frontmatter patch failed, AND the automatic rollback could not
113
+ * run. The merged text IS in the target, so the caller must not write
114
+ * the fact again; the pre-merge snapshot is named in the error log.
115
+ */
116
+ provenancePatched: boolean;
117
+ }
118
+ | { action: "created"; reason: SemanticMergeCreateReason };
119
+
120
+ /** Categories that never merge (episodic / immutable by nature). */
121
+ const REFUSED = REFUSED_MERGE_CATEGORIES as readonly string[];
122
+
123
+ export interface ApplySemanticMergeOptions {
124
+ storage: StorageManager;
125
+ /** RAW (pre-citation) fact content — the same form the dedup band scores. */
126
+ content: string;
127
+ category: string;
128
+ /** The incoming fact's claim-level provenance spans, appended to the target. */
129
+ sources?: ProvenanceSource[];
130
+ /**
131
+ * Provenance connector of the incoming fact. Forwarded to the decision so a
132
+ * cross-connector neighbor is never a merge target (same scope contract the
133
+ * novelty and semantic-dedup gates apply).
134
+ */
135
+ sourceConnector?: string;
136
+ /**
137
+ * Extraction metadata the normal write path persists but a merge cannot
138
+ * carry onto the target (item A). A merge forwards only content, category,
139
+ * sources, and connector; when any entry here is NEW information relative
140
+ * to the target, merging is bypassed so nothing is silently discarded.
141
+ */
142
+ incomingMetadata?: {
143
+ tags?: readonly string[];
144
+ entityRef?: string;
145
+ structuredAttributes?: Record<string, string>;
146
+ /** Effective `validAt` the write path would persist (bi-temporal or source). */
147
+ validAt?: string;
148
+ /** True when bi-temporal bounds (validFrom/validUntil/observedAt/eventTimeSource) apply. */
149
+ biTemporal?: boolean;
150
+ /** Importance score the write path would stamp. */
151
+ importanceScore?: number;
152
+ /**
153
+ * Confidence the write path would stamp (final round A). The merged
154
+ * record keeps the LOWER side — min(incoming, target), with the tier
155
+ * that score maps to — matching what the create path would have stored
156
+ * for the incoming fact alone; an incoming value at or above the
157
+ * target's needs no rewrite. An unreadable value (non-finite or outside
158
+ * [0, 1]) bypasses the merge rather than guessing a floor.
159
+ */
160
+ confidence?: number;
161
+ /**
162
+ * Provenance strength the write path would stamp.
163
+ */
164
+ provenanceStrength?: "verified" | "unverified" | "none";
165
+ /**
166
+ * True when the write path would stamp `toolScoped: true` (finding A):
167
+ * connector-scoped claims must never widen into an unscoped target, so
168
+ * such a fact is created through the write that stamps the flag. A
169
+ * target that already carries `toolScoped: true` keeps its stricter
170
+ * scope — the merge patch never touches that field.
171
+ */
172
+ toolScoped?: boolean;
173
+ /**
174
+ * Subject the write path would stamp when subject classification is
175
+ * enabled (finding A): the merge patch has no carrier for `subject`, so
176
+ * a fact whose effective subject differs from the target's must be
177
+ * created rather than merged into a target that keeps a different label.
178
+ */
179
+ subject?: MemorySubject;
180
+ /**
181
+ * Authority origin the write path would stamp (finding A). The merge
182
+ * patch has no carrier for `origin`, so the merged body would render
183
+ * under the TARGET's authority at recall; a cross-origin merge is
184
+ * refused outright (see {@link createPathMergeParity}).
185
+ */
186
+ origin?: string;
187
+ /**
188
+ * Faithfulness verdict the write path would stamp (finding C). In
189
+ * shadow mode a contradicted/unsupported fact receives this frontmatter
190
+ * without pending_review status, so the verdict — not just the enforce
191
+ * status — gates parity: the merge patch cannot compose an honest
192
+ * verdict for a combined body, so an incoming verdict that differs from
193
+ * the target's effective one bypasses the merge.
194
+ */
195
+ faithfulness?: FaithfulnessFrontmatter;
196
+ /**
197
+ * Episode/note classification the write path would stamp when
198
+ * `episodeNoteMode` is on (round N+2, finding B). The merge patch has
199
+ * no `memoryKind` carrier, so the merged record keeps the target's
200
+ * kind — the classification that drives episode-cache membership and
201
+ * the episode-only verification/promotion paths. A computed incoming
202
+ * kind that differs from the target's committed kind (including a
203
+ * kinded fact into an unkinded legacy target) bypasses the merge.
204
+ * Undefined means classification is off and no episode path consults
205
+ * the field, so those merges keep passing.
206
+ */
207
+ memoryKind?: MemoryFrontmatter["memoryKind"];
208
+ };
209
+ /**
210
+ * Navigation links the caller suggested for the incoming fact (finding B).
211
+ * The create path stamps these on the fact it writes; a merge that dropped
212
+ * them would permanently lose the relationships, so a successful merge
213
+ * attaches them to the TARGET record in the same conditional frontmatter
214
+ * patch that stamps provenance — deduped on (targetId, linkType), the key
215
+ * `StorageManager.addLinksToMemory` uses.
216
+ */
217
+ incomingLinks?: readonly MemoryLink[];
218
+ /**
219
+ * Round N+7 (C): the caller's single cited body for this write — the raw
220
+ * fact content with this write's citation marker attached (the same
221
+ * string the verbatim artifact stores). The committed merged body reuses
222
+ * that exact marker so the incoming claims stay attributed alongside the
223
+ * target's older citation, and memory and artifact share one timestamp.
224
+ * Absent (or citation-free) commits the judge's merged body unchanged.
225
+ */
226
+ incomingCitedContent?: string;
227
+ /**
228
+ * Finding C: async probe run after a merge verdict but before any
229
+ * mutation. True when the would-be target already has promoted
230
+ * shared/profile copies the merge cannot reconcile — the fact is created
231
+ * through the normal write (whose promotion step owns those copies)
232
+ * instead of merged.
233
+ */
234
+ targetHasPromotedCopies?: (targetId: string) => Promise<boolean>;
235
+ /** Caller-side bypass: contradiction detected or pending_review routing. */
236
+ skip?: boolean;
237
+ /** Injection seam for tests. */
238
+ now?: () => Date;
239
+ judgeCall?: (options: MergeJudgeCallOptions) => Promise<MergeJudgeRawVerdict | null>;
240
+ }
241
+
242
+ const PROVENANCE_STRENGTH_RANK: Record<string, number> = {
243
+ none: 0,
244
+ unverified: 1,
245
+ verified: 2,
246
+ };
247
+
248
+ /**
249
+ * Create-path parity gate (final round, PR #2771). Nine review rounds all
250
+ * found the same defect class: the merge path did less, or something wider,
251
+ * than the create path. Instead of patching call sites, this ONE gate
252
+ * enumerates every trust/scope/verdict field the create path's write stamps
253
+ * (`writeSealedMemory` + extras in `extraction-persist.ts`) and decides,
254
+ * per field, whether the merge preserves it. A merge proceeds only when
255
+ * EVERY field is carried by the merge patch, preserved monotonically, or
256
+ * provably equal. Anything else — including anything unknown or unreadable —
257
+ * bypasses to a create, because a create is always safe and a merge is not.
258
+ *
259
+ * Field classification, from the create-path write:
260
+ * - carried by the merge patch: content (judge-composed merged body),
261
+ * sources (appended by buildMergeFrontmatterUpdate), contentHash
262
+ * (restamped off the canonical merged form), status (a merge-eligible
263
+ * fact is never pending_review — the caller skips — and the target is
264
+ * re-verified active), provenance (only when downgraded to the
265
+ * least-trusted side, see below).
266
+ * - equality-required (bypass on mismatch): category (also enforced at
267
+ * candidate resolution), entityRef, effective validity bounds — both
268
+ * sides unbounded, or an incoming validAt identical to the target's
269
+ * valid_at; a target carrying invalid_at never merges (round N+2 A) —
270
+ * subject (effective), memoryKind when the incoming fact carries a
271
+ * computed kind (round N+2 B), sourceConnector (against the COLD-AWARE
272
+ * target snapshot, finding D), faithfulness verdict (effective, finding C).
273
+ * - monotone-preservable (bypass when the incoming side exceeds what the
274
+ * target retains): tags (target must be a superset), importance score
275
+ * (incoming may not exceed), confidence score (incoming may not exceed;
276
+ * a lower incoming DOWNGRADES the record to min(incoming, target) with
277
+ * the tier that score maps to — final round A), provenance strength
278
+ * (incoming may not be stronger — and a weaker incoming downgrades the
279
+ * target so the merged body never carries trust its new claims did not
280
+ * earn, finding B).
281
+ * - bypass-on-presence (no carrier exists at all): structuredAttributes,
282
+ * bi-temporal bounds.
283
+ * - escalation-refused: origin (an untrusted incoming origin may never
284
+ * merge into a trusted target; equal or fence-safe mismatches may).
285
+ * - scope-widening-refused: toolScoped (an unscoped target may never gain
286
+ * tool-scoped claims; a scoped target keeps its stricter flag).
287
+ */
288
+ export type CreatePathMergeParity =
289
+ | {
290
+ ok: true;
291
+ provenanceFloor?: "verified" | "unverified" | "none";
292
+ /** Lower incoming confidence the patch must stamp (final round A). */
293
+ confidenceFloor?: number;
294
+ }
295
+ | { ok: false; field: string };
296
+
297
+ /** Effective provenance rank; absent reads as "none" (legacy contract, types.ts). */
298
+ function provenanceRank(value: string | undefined): number {
299
+ return PROVENANCE_STRENGTH_RANK[value ?? "none"] ?? 0;
300
+ }
301
+
302
+ /**
303
+ * Effective faithfulness verdict using the trust stage's own normalization
304
+ * (`skipped_no_span` reads as "unchecked"); undefined = gate never ran.
305
+ */
306
+ function effectiveFaithfulness(
307
+ verdict: FaithfulnessFrontmatter["verdict"] | undefined,
308
+ ): FaithfulnessFrontmatter["verdict"] | undefined {
309
+ if (verdict === undefined) return undefined;
310
+ return verdict === "skipped_no_span" ? "unchecked" : verdict;
311
+ }
312
+
313
+ export function createPathMergeParity(input: {
314
+ /** Cold-aware committed snapshot of the merge target (never a lookup hit). */
315
+ target: MemoryFile;
316
+ incoming: ApplySemanticMergeOptions["incomingMetadata"];
317
+ /** The incoming fact's connector scope (finding D). */
318
+ sourceConnector?: string;
319
+ untrustedOrigins: readonly string[];
320
+ }): CreatePathMergeParity {
321
+ const { target, untrustedOrigins } = input;
322
+ const md = input.incoming;
323
+ if (md?.structuredAttributes && Object.keys(md.structuredAttributes).length > 0) {
324
+ return { ok: false, field: "structuredAttributes" };
325
+ }
326
+ if (md?.biTemporal === true) return { ok: false, field: "biTemporal" };
327
+ if (md?.entityRef !== undefined && md.entityRef !== target.frontmatter.entityRef) {
328
+ return { ok: false, field: "entityRef" };
329
+ }
330
+ if (md?.validAt !== undefined && md.validAt !== target.frontmatter.valid_at) {
331
+ return { ok: false, field: "validAt" };
332
+ }
333
+ // Round N+2 (A) — effective validity bounds. The merged body inherits the
334
+ // TARGET's valid_at/invalid_at (the patch has no carrier for either), and
335
+ // inferMemoryStatus ignores temporal validity, so a lifecycle-active
336
+ // target with a past invalid_at takes the fresh claims out of normal
337
+ // recall the moment they merge in (isValidityExpiredNow reads the bound).
338
+ // Refuse instead: a target carrying invalid_at never merges (a non-
339
+ // bi-temporal incoming fact cannot carry one — bi-temporal facts already
340
+ // bypass above), and a target carrying valid_at merges only with an
341
+ // incoming fact carrying the same bound via the equality check above.
342
+ // Both-unbounded pairs keep merging.
343
+ if (target.frontmatter.invalid_at !== undefined) {
344
+ return { ok: false, field: "validity_bounds" };
345
+ }
346
+ if (target.frontmatter.valid_at !== undefined && md?.validAt === undefined) {
347
+ return { ok: false, field: "validity_bounds" };
348
+ }
349
+ const targetTags = new Set(target.frontmatter.tags ?? []);
350
+ if ((md?.tags ?? []).some((tag) => !targetTags.has(tag))) {
351
+ return { ok: false, field: "tags" };
352
+ }
353
+ if (
354
+ md?.importanceScore !== undefined &&
355
+ md.importanceScore > (target.frontmatter.importance?.score ?? 0)
356
+ ) {
357
+ return { ok: false, field: "importance" };
358
+ }
359
+
360
+ // Finding B — provenance must not be upgraded by merging. A stronger
361
+ // incoming strength has no carrier (create stamps it on its own fact);
362
+ // a weaker one must RETAG the combined body to the least-trusted value,
363
+ // because `trust-score.ts` maps the memory-level tag straight to a
364
+ // provenance contribution and unverified new claims must not inherit
365
+ // `verified`'s maximum.
366
+ const incomingProvenanceRank = provenanceRank(md?.provenanceStrength);
367
+ const targetProvenanceRank = provenanceRank(target.frontmatter.provenance);
368
+ if (incomingProvenanceRank > targetProvenanceRank) {
369
+ return { ok: false, field: "provenance" };
370
+ }
371
+ const provenanceFloor =
372
+ incomingProvenanceRank < targetProvenanceRank
373
+ ? ((md?.provenanceStrength ?? "none") as "verified" | "unverified" | "none")
374
+ : undefined;
375
+
376
+ // Final round (A) — confidence must not be upgraded by merging either.
377
+ // Lifecycle scoring, preference consolidation, and the merged-target
378
+ // promotion all read the record's confidence, so a low-confidence
379
+ // extraction merging into a higher-confidence target must DOWNGRADE the
380
+ // record to min(incoming, target) — the value the create path would have
381
+ // stored for the incoming fact alone. A value at or above the target's
382
+ // needs no rewrite (the min IS the target's); an unreadable one bypasses
383
+ // the merge rather than guessing a floor. A legacy target with no
384
+ // confidence reads as the write path's 0.8 default (parseMemoryFrontmatter).
385
+ if (md?.confidence !== undefined) {
386
+ if (
387
+ typeof md.confidence !== "number" ||
388
+ !Number.isFinite(md.confidence) ||
389
+ md.confidence < 0 ||
390
+ md.confidence > 1
391
+ ) {
392
+ return { ok: false, field: "confidence" };
393
+ }
394
+ }
395
+ const confidenceFloor =
396
+ md?.confidence !== undefined && md.confidence < (target.frontmatter.confidence ?? 0.8)
397
+ ? md.confidence
398
+ : undefined;
399
+
400
+ // Finding D — connector scope from the COLD-AWARE target snapshot. The
401
+ // lookup's hit enrichment reads `sourceConnector` hot-only
402
+ // (persistence-index.ts), so a cold-tier (or read-failed) target looks
403
+ // unscoped and an unscoped incoming fact slips past the lookup-side
404
+ // comparison. The re-read target carries the authoritative frontmatter;
405
+ // fail closed on any mismatch (both sides unscoped, or identical).
406
+ if (
407
+ normalizeConnectorScope(target.frontmatter.sourceConnector) !==
408
+ normalizeConnectorScope(input.sourceConnector)
409
+ ) {
410
+ return { ok: false, field: "sourceConnector" };
411
+ }
412
+
413
+ if (md?.toolScoped === true && target.frontmatter.toolScoped !== true) {
414
+ return { ok: false, field: "toolScoped" };
415
+ }
416
+ // Subject: the write path stamps `subject`, and the merge patch has no
417
+ // carrier for it, so a fact whose EFFECTIVE subject differs from the
418
+ // target's must be created. An absent subject resolves to the
419
+ // least-privileged `user` — the same default the subject guard applies —
420
+ // so classification being disabled never lets an unclassified fact merge
421
+ // into an `agent`-labeled target.
422
+ if ((md?.subject ?? "user") !== (target.frontmatter.subject ?? "user")) {
423
+ return { ok: false, field: "subject" };
424
+ }
425
+ // Round N+2 (B) — memoryKind parity. See the field doc on
426
+ // ApplySemanticMergeOptions.incomingMetadata.memoryKind.
427
+ if (md?.memoryKind !== undefined && md.memoryKind !== target.frontmatter.memoryKind) {
428
+ return { ok: false, field: "memoryKind" };
429
+ }
430
+ // Origin: the merged body renders under the TARGET's origin at recall, so
431
+ // an UNTRUSTED incoming origin (per the deployment's untrustedOrigins)
432
+ // merging into a TRUSTED target would hand injected text unfenced,
433
+ // user-authority rendering — the escalation the recall fence exists to
434
+ // prevent. That merge is refused; the fact is created through the write
435
+ // that stamps its own origin. Mismatches that never reduce fencing still
436
+ // merge, so legacy unstamped targets (`origin` absent → `unknown`, the
437
+ // fence's least-privilege default) keep receiving user-origin facts.
438
+ if (
439
+ isUntrustedOrigin(parseOriginClass(md?.origin), untrustedOrigins) &&
440
+ !isUntrustedOrigin(parseOriginClass(target.frontmatter.origin), untrustedOrigins)
441
+ ) {
442
+ return { ok: false, field: "origin" };
443
+ }
444
+ // Finding C — faithfulness verdicts must be preserved. The create path
445
+ // stamps `faithfulnessFm` whenever the gate ran (shadow mode included: a
446
+ // contradicted fact gets the verdict without pending_review status). The
447
+ // merge patch cannot compose an honest verdict for a combined body, so the
448
+ // effective verdicts must be EQUAL — both present and identical, or both
449
+ // absent. One-sided verdicts (gate ran on one side only) bypass too: the
450
+ // trust stage maps `entailed` to the maximum contribution, so claims the
451
+ // gate never checked must not inherit an entailment rendered over the
452
+ // other side's claims alone. The create path runs instead and persists
453
+ // the verdict it computed (or none).
454
+ const incomingFaithfulness = effectiveFaithfulness(md?.faithfulness?.verdict);
455
+ const targetFaithfulness = effectiveFaithfulness(target.frontmatter.faithfulness?.verdict);
456
+ if (incomingFaithfulness !== targetFaithfulness) {
457
+ return { ok: false, field: "faithfulness" };
458
+ }
459
+ // Round N+9 (A): an EQUAL verdict cannot survive either — the target's
460
+ // `entailed` was rendered over its pre-merge body, never the judge's
461
+ // merged text, so bypass (entailment only; others under-claim / no signal).
462
+ if (targetFaithfulness === "entailed") {
463
+ return { ok: false, field: "faithfulness" };
464
+ }
465
+ return {
466
+ ok: true,
467
+ ...(provenanceFloor !== undefined ? { provenanceFloor } : {}),
468
+ ...(confidenceFloor !== undefined ? { confidenceFloor } : {}),
469
+ };
470
+ }
471
+
472
+ /**
473
+ * Round N+7 (C): the committed merged body carries the incoming extraction's
474
+ * citation marker (lifted from the caller's cited body for this write)
475
+ * appended after the judge's merged text, so incoming claims stay attributed
476
+ * even when the merged text embeds the target's older citation — quoted
477
+ * excerpts travel without frontmatter, so `sources` alone is not enough.
478
+ * Idempotent; a no-op when attribution is off or no marker exists.
479
+ */
480
+ function committedMergedBody(
481
+ deps: ExtractionPersistDeps,
482
+ mergedContent: string,
483
+ incomingCitedContent: string | undefined,
484
+ ): string {
485
+ if (
486
+ resolvePipelineProcessingCapabilities(deps.config).inlineSourceAttribution !== true ||
487
+ incomingCitedContent === undefined
488
+ ) {
489
+ return mergedContent;
490
+ }
491
+ const marker = lastCitationMarkerForTemplate(
492
+ incomingCitedContent,
493
+ deps.config.inlineSourceAttributionFormat,
494
+ );
495
+ if (!marker || mergedContent.endsWith(marker)) return mergedContent;
496
+ return `${mergedContent} ${marker}`;
497
+ }
498
+
499
+ function versioningConfigFrom(deps: ExtractionPersistDeps): VersioningConfig {
500
+ return {
501
+ enabled: resolveRecallAuxiliaryCapabilities(deps.config).versioning,
502
+ maxVersionsPerPage: deps.config.versioningMaxPerPage,
503
+ sidecarDir: deps.config.versioningSidecarDir,
504
+ };
505
+ }
506
+
507
+ /**
508
+ * Finding B — union the incoming fact's suggested navigation links into the
509
+ * target's committed links, deduping on (targetId, linkType): the same key
510
+ * `StorageManager.addLinksToMemory` uses. A suggestion naming the surviving
511
+ * target itself is DISCARDED — memory linking and the merge judge both
512
+ * search on the incoming content, so the suggested neighbor is often the
513
+ * merge target itself, and attaching it would make the record its own
514
+ * neighbor (recall-navigate would return the current memory and burn
515
+ * traversal budget). Returns undefined when there is nothing to attach so
516
+ * the patch carries no `links` key at all (an empty array would ERASE
517
+ * committed links).
518
+ */
519
+ export function mergeMemoryLinks(
520
+ existing: readonly MemoryLink[] | undefined,
521
+ incoming: readonly MemoryLink[] | undefined,
522
+ survivingTargetId: string,
523
+ ): MemoryLink[] | undefined {
524
+ if (!incoming || incoming.length === 0) return undefined;
525
+ const merged = [...(existing ?? [])];
526
+ for (const link of incoming) {
527
+ if (link.targetId === survivingTargetId) continue;
528
+ if (!merged.some((l) => l.targetId === link.targetId && l.linkType === link.linkType)) {
529
+ merged.push({ ...link });
530
+ }
531
+ }
532
+ return merged.length > 0 ? merged : undefined;
533
+ }
534
+ export async function applySemanticMergeAtPersist(
535
+ deps: ExtractionPersistDeps,
536
+ options: ApplySemanticMergeOptions,
537
+ ): Promise<SemanticMergePersistOutcome> {
538
+ const config = deps.config.semanticMerge;
539
+ if (config?.enabled !== true || options.skip === true) {
540
+ return { action: "created", reason: "disabled" };
541
+ }
542
+ if (REFUSED.includes(options.category)) {
543
+ return { action: "created", reason: "disabled" };
544
+ }
545
+
546
+ const decision = await decideSemanticMerge({
547
+ content: options.content,
548
+ category: options.category,
549
+ config,
550
+ sourceConnector: options.sourceConnector,
551
+ dedupThreshold: deps.config.semanticDedupThreshold,
552
+ lookup: (content, limit) => deps.semanticDedupLookup(content, limit, options.storage),
553
+ resolveCandidate: async (memoryId) => {
554
+ const memory = await options.storage.getMemoryByIdIncludingArchived(memoryId);
555
+ if (!memory) return null;
556
+ return {
557
+ content: memory.content,
558
+ category: memory.frontmatter.category,
559
+ status: inferMemoryStatus(memory.frontmatter, memory.path),
560
+ };
561
+ },
562
+ judge: async (input) => {
563
+ const call = options.judgeCall ?? callMergeJudge;
564
+ // A null (no backend answered / schema-failed) maps to a thrown error
565
+ // so decideSemanticMerge classifies it as judge_error → create.
566
+ const verdict = await call({
567
+ ...input,
568
+ candidates: [...input.candidates],
569
+ config: deps.config,
570
+ localLlm: deps.getLocalLlm(),
571
+ fallbackLlm: new FallbackLlmClient(
572
+ deps.config.gatewayConfig,
573
+ fallbackLlmRuntimeContextFromConfig(deps.config),
574
+ ),
575
+ });
576
+ if (!verdict) throw new Error("merge judge unavailable or unparseable");
577
+ return verdict;
578
+ },
579
+ });
580
+
581
+ if (decision.action === "create") {
582
+ if (config.shadowMode) {
583
+ // Telemetry only — category, length, reason. Never fact content: log
584
+ // sinks generally have broader access and retention than the memory
585
+ // store, and extracted facts can hold personal material.
586
+ log.info(
587
+ `semantic-merge[shadow]: would create category=${options.category} length=${options.content.length} reason="${decision.reason}"`,
588
+ );
589
+ }
590
+ return { action: "created", reason: decision.reason };
591
+ }
592
+
593
+ if (config.shadowMode) {
594
+ // Rollout lever: decision-only. Never mutate in shadow mode.
595
+ log.info(
596
+ `semantic-merge[shadow]: would merge into ${decision.targetId} reason="judge_merge"`,
597
+ );
598
+ return { action: "created", reason: "shadow_would_merge" };
599
+ }
600
+
601
+ // Step 1 — re-read the target; gone or no-longer-active → create.
602
+ const target = await options.storage.getMemoryByIdIncludingArchived(decision.targetId);
603
+ if (!target || inferMemoryStatus(target.frontmatter, target.path) !== "active") {
604
+ return { action: "created", reason: "target_inactive" };
605
+ }
606
+ // `mergedContent` was composed from the body the judge was shown. In a
607
+ // multi-writer deployment another extraction can update the target between
608
+ // that resolve and now; writing the merge would silently drop the
609
+ // concurrent writer's details. A changed body creates instead.
610
+ if (target.content !== decision.targetContent) {
611
+ return { action: "created", reason: "target_changed" };
612
+ }
613
+ // Round N+7 (C): every mutation below commits THIS body — the judge's
614
+ // merged text plus the incoming citation marker — and the outcome reports
615
+ // it, so caller comparisons describe what storage actually holds.
616
+ const committedContent = committedMergedBody(deps, decision.mergedContent, options.incomingCitedContent);
617
+
618
+ // Create-path parity gate (final round) — ONE place enumerates every
619
+ // trust/scope/verdict field the normal write stamps and bypasses the
620
+ // merge unless each is carried, preserved, or provably equal. See
621
+ // {@link createPathMergeParity} for the field classification.
622
+ const parity = createPathMergeParity({
623
+ target,
624
+ incoming: options.incomingMetadata,
625
+ sourceConnector: options.sourceConnector,
626
+ untrustedOrigins: deps.config.untrustedOrigins,
627
+ });
628
+ if (!parity.ok) {
629
+ return { action: "created", reason: "metadata_unpreservable" };
630
+ }
631
+
632
+ // Finding C — the create path's promotion step owns shared/profile copies
633
+ // linked by `sourceMemoryId`; a merge mutates only this storage, so those
634
+ // copies would keep serving the pre-merge body. When any promoted copy
635
+ // exists, bypass the merge so the normal write (with its own promotion
636
+ // reconciliation) runs instead. Probed before any mutation, so a bypass
637
+ // leaves the target — and its page-version history — untouched.
638
+ if (
639
+ options.targetHasPromotedCopies &&
640
+ (await options.targetHasPromotedCopies(decision.targetId))
641
+ ) {
642
+ return { action: "created", reason: "promoted_copy_present" };
643
+ }
644
+ // Step 2 — rollback data BEFORE any mutation (checklist #14). A failed
645
+ // snapshot must leave the target untouched. Versioning disabled means no
646
+ // rollback story exists at all, so merge refuses to run.
647
+ const versioning = versioningConfigFrom(deps);
648
+ if (!versioning.enabled) {
649
+ return { action: "created", reason: "snapshot_unavailable" };
650
+ }
651
+ let versionId: string;
652
+ try {
653
+ versionId = await stageMergedTargetSnapshot(target, versioning, options.storage.dir);
654
+ } catch (err) {
655
+ log.warn(
656
+ `semantic-merge: snapshot failed for ${decision.targetId}; creating new fact instead: ${err instanceof Error ? err.message : String(err)}`,
657
+ );
658
+ return { action: "created", reason: "snapshot_failed" };
659
+ }
660
+
661
+ // Round N+16 (C): `committedFactHash` — passed ONLY on the degraded path —
662
+ // registers the hash of what storage actually HOLDS. The default reader
663
+ // (`restoreFactHashAfterApproval` → `corpusRegisteredHashes`) prefers the
664
+ // PERSISTED frontmatter `contentHash`, which the degraded record still
665
+ // carries from BEFORE the merge, so routing the degraded repair through it
666
+ // re-registered the stale pre-merge identity and left the merged body
667
+ // unindexed for exact dedup.
668
+ const repairIndexes = async (committedFactHash?: string): Promise<void> => {
669
+ // Hash index: remove the old form, add the new form, in the same
670
+ // corpus-registered identity the write path uses. Both helpers are
671
+ // fact-category no-ops, mirroring `contentHashSource` on the write path.
672
+ // The index rebuilds from the corpus on restart, so a failure here is
673
+ // logged, not fatal.
674
+ try {
675
+ await options.storage.removeFactContentHashesForMemories([target]);
676
+ if (committedFactHash !== undefined) {
677
+ // Round N+20 (B): body-coupled — a writer that replaced the target
678
+ // after this writer's content commit keeps its own record (and its
679
+ // own hash); registering ours would be a phantom exact-dedup hit.
680
+ await options.storage.registerFactContentHash(decision.targetId, committedFactHash, committedContent);
681
+ // Round N+19 (B): also persist the repaired identity in the
682
+ // frontmatter — the index registration is process-local state over
683
+ // a persisted stale `contentHash`, and a restart's corpus rebuild
684
+ // prefers the persisted value, which would discard this repair.
685
+ // CAS-guarded and non-fatal: a concurrent writer that already
686
+ // replaced the record keeps its own (correct) identity.
687
+ await persistRepairedContentHash(
688
+ options.storage,
689
+ decision.targetId,
690
+ committedContent,
691
+ committedFactHash,
692
+ );
693
+ } else {
694
+ await options.storage.restoreFactHashAfterApproval(decision.targetId);
695
+ }
696
+ } catch (err) {
697
+ log.warn(
698
+ `semantic-merge: hash-index sync failed for ${decision.targetId} (non-fatal; index rebuilds from corpus): ${err instanceof Error ? err.message : String(err)}`,
699
+ );
700
+ }
701
+ // Reindex the merged target or its new content stays undiscoverable until
702
+ // unrelated maintenance runs (checklist #31).
703
+ try {
704
+ await deps.indexPersistedMemory(options.storage, decision.targetId);
705
+ } catch (err) {
706
+ log.warn(
707
+ `semantic-merge: reindex failed for ${decision.targetId} (non-fatal): ${err instanceof Error ? err.message : String(err)}`,
708
+ );
709
+ }
710
+ };
711
+
712
+ // Step 3 — update in place, preserving the id, via compare-and-swap on the
713
+ // snapshot just read: a writer landing between the read and the write must
714
+ // win rather than be overwritten from a stale body. The active-target check
715
+ // above makes a tombstone block structurally impossible here.
716
+ const nowIso = (options.now ? options.now() : new Date()).toISOString();
717
+ let contentCommitted = false;
718
+ // Captured so the success return can describe the COMMITTED frontmatter
719
+ // (the patch's appended sources) without widening the try's scope.
720
+ let mergePatch: MergeFrontmatterUpdate | undefined;
721
+ try {
722
+ mergePatch = buildMergeFrontmatterUpdate({
723
+ targetSources: (target.frontmatter.sources ?? []) as MergeProvenanceSource[],
724
+ incomingSources: (options.sources ?? []) as MergeProvenanceSource[],
725
+ targetReinforcementCount: target.frontmatter.reinforcement_count,
726
+ nowIso,
727
+ });
728
+ const updated = await options.storage.updateMemoryIfUnchanged(target, committedContent, {
729
+ actor: "semantic-merge",
730
+ });
731
+ if (!updated) {
732
+ // Round N+13 (B): the CAS lost the race, so no merge committed — roll
733
+ // the staged snapshot back out or this failed attempt leaves a
734
+ // duplicate history entry a later successful prune would trade real
735
+ // rollback states for.
736
+ await discardMergedTargetSnapshot(
737
+ target.path,
738
+ versioning,
739
+ options.storage.dir,
740
+ decision.targetId,
741
+ versionId,
742
+ );
743
+ return { action: "created", reason: "target_changed" };
744
+ }
745
+ contentCommitted = true;
746
+ // The provenance patch must land on OUR merged body. An id-keyed patch
747
+ // re-reads and stamps whatever the latest row holds, so a writer landing
748
+ // after the content commit would receive this merge's provenance while
749
+ // its own body stood — and the caller would still be told "merged".
750
+ // Verify the snapshot, then patch it through the conditional API so the
751
+ // window between the verify and the patch is closed by storage itself.
752
+ const merged = await readTargetSnapshot(options.storage, target);
753
+ if (!merged || merged.content !== committedContent) {
754
+ throw new Error("target replaced before the provenance patch");
755
+ }
756
+ const mergedRawBody = rawPreCitationMergedBody(deps, committedContent);
757
+ // Finding A (round N+3) — intent parity. With intent routing on, the
758
+ // create path stamps intentGoal/intentActionType/intentEntityTypes from
759
+ // the body it persists, and recall-search-pipeline scores intent
760
+ // compatibility from exactly those fields; a merge that left the
761
+ // target's stale values would misroute the newly merged claims. The
762
+ // patch recomputes them with the SAME call the write path runs
763
+ // (`${category} ${tags} ${content}`) over the committed record — its own
764
+ // category and tags plus the canonical RAW pre-citation merged body — so
765
+ // the committed values equal what an ordinary write of the same body
766
+ // would persist. An empty entityTypes list clears a stale field, exactly
767
+ // as serialization omits it on a fresh write.
768
+ const mergedIntent = resolveConversationContextCapabilities(deps.config).intentRouting
769
+ ? inferIntentFromText(
770
+ `${merged.frontmatter.category} ${(merged.frontmatter.tags ?? []).join(" ")} ${mergedRawBody}`,
771
+ )
772
+ : undefined;
773
+ // Item B — `updateMemoryIfUnchanged` keeps the target's old
774
+ // `frontmatter.contentHash`, so the patch must restamp the identity the
775
+ // write path would register: the hash of the SAME canonical form normal
776
+ // persistence hashes — the sanitized RAW pre-citation body (round N+2 C).
777
+ // Facts only, mirroring `contentHashSource` on the write path.
778
+ const mergedFactHash =
779
+ options.category === "fact"
780
+ ? ContentHashIndex.computeHash(sanitizeMemoryContent(mergedRawBody).text)
781
+ : undefined;
782
+ // Finding B — the incoming fact's suggested navigation links attach to
783
+ // the target here, in the same conditional patch (the fact is never
784
+ // created on this path, so the create path's `links` carrier cannot run).
785
+ const mergedLinks = mergeMemoryLinks(
786
+ merged.frontmatter.links,
787
+ options.incomingLinks,
788
+ decision.targetId,
789
+ );
790
+ const patched = await options.storage.writeMemoryFrontmatterIfUnchanged(
791
+ merged,
792
+ {
793
+ updated: mergePatch.updated,
794
+ derived_via: mergePatch.derived_via,
795
+ reinforcement_count: mergePatch.reinforcement_count,
796
+ sources: mergePatch.sources,
797
+ ...(mergedFactHash !== undefined ? { contentHash: mergedFactHash } : {}),
798
+ // Finding B — a weaker incoming provenance retags the combined body
799
+ // to the least-trusted value instead of letting unverified new
800
+ // claims ride the target's stronger memory-level tag.
801
+ ...(parity.ok && parity.provenanceFloor !== undefined
802
+ ? { provenance: parity.provenanceFloor }
803
+ : {}),
804
+ // Final round (A) — min(incoming, target) confidence: the merged
805
+ // record keeps the lower score, and the tier that score maps to,
806
+ // so lifecycle scoring and the committed-record promotion payload
807
+ // can never treat the combined body as higher-confidence than the
808
+ // create path would have stored for the incoming fact alone.
809
+ ...(parity.ok && parity.confidenceFloor !== undefined
810
+ ? {
811
+ confidence: parity.confidenceFloor,
812
+ confidenceTier: confidenceTier(parity.confidenceFloor),
813
+ }
814
+ : {}),
815
+ ...(mergedLinks !== undefined ? { links: mergedLinks } : {}),
816
+ ...(mergedIntent !== undefined
817
+ ? {
818
+ intentGoal: mergedIntent.goal,
819
+ intentActionType: mergedIntent.actionType,
820
+ intentEntityTypes: mergedIntent.entityTypes,
821
+ }
822
+ : {}),
823
+ },
824
+ { actor: "semantic-merge" },
825
+ );
826
+ if (!patched) throw new Error("frontmatter patch rejected (target changed)");
827
+ } catch (err) {
828
+ const detail = err instanceof Error ? err.message : String(err);
829
+ // A committed content update means the merged text may be IN the target.
830
+ // Reporting `created` while it is would write the fact a second time and
831
+ // leave those claims without the incoming provenance, so `created` is
832
+ // reachable only once storage has been re-read and confirms the target no
833
+ // longer holds this merge's unprovenanced body.
834
+ if (
835
+ contentCommitted &&
836
+ !(await revertMergedContent(options.storage, target, committedContent))
837
+ ) {
838
+ log.error(
839
+ `semantic-merge: ${decision.targetId} holds merged content without provenance metadata and the rollback failed (${detail}); snapshot ${versionId} holds the pre-merge state — recover with revertToVersion. Not creating a duplicate fact.`,
840
+ );
841
+ // Item C — the merged body IS committed; repair the indexes before
842
+ // reporting the degraded success. N+16 (C): the record's persisted
843
+ // frontmatter hash is the stale PRE-merge identity, so register the
844
+ // COMMITTED body's hash instead.
845
+ // Round N+20 (C): degraded SUCCESS commits the recovery snapshot —
846
+ // the body is committed and kept, so the staged version clears its
847
+ // `pending` flag under the same page lock as a finalizing prune.
848
+ // Without it pruneExcessVersions excluded every degraded recovery
849
+ // point forever, so repeated degraded merges grew the manifest and
850
+ // snapshot directory past maxVersionsPerPage and no later successful
851
+ // merge could prune them back.
852
+ await finalizeMergedVersionPrune(target.path, versioning, options.storage.dir, decision.targetId, versionId);
853
+ await repairIndexes(committedMergedFactHash(deps, options.category, committedContent));
854
+ return {
855
+ action: "merged",
856
+ targetId: decision.targetId,
857
+ mergedContent: committedContent,
858
+ provenancePatched: false,
859
+ };
860
+ }
861
+ // Round N+13 (B): with the content committed and the revert above
862
+ // confirmed, storage holds the pre-merge body, so the staged snapshot of
863
+ // that same body is a duplicate and goes. (The degraded-success branch
864
+ // above keeps it as the recovery point. A throw BEFORE the content
865
+ // commit leaves storage state unverifiable — keep-side, the snapshot
866
+ // stays.)
867
+ if (contentCommitted) {
868
+ await discardMergedTargetSnapshot(
869
+ target.path,
870
+ versioning,
871
+ options.storage.dir,
872
+ decision.targetId,
873
+ versionId,
874
+ );
875
+ }
876
+ log.warn(
877
+ `semantic-merge: update failed for ${decision.targetId}${contentCommitted ? ` (content rolled back; snapshot ${versionId} rolled back out of history)` : ` (snapshot ${versionId} staged)`}: ${detail}`,
878
+ );
879
+ return { action: "created", reason: "update_failed" };
880
+ }
881
+ // Round N+12 (A): the prune finalizes only after BOTH compare-and-swaps
882
+ // commit — full rationale on finalizeMergedVersionPrune. A degraded
883
+ await finalizeMergedVersionPrune(target.path, versioning, options.storage.dir, decision.targetId, versionId);
884
+
885
+ // Steps 4+5 — hash-index resync and reindex (see repairIndexes above).
886
+ await repairIndexes();
887
+
888
+ log.info(
889
+ `semantic-merge: merged fact into ${decision.targetId} (version ${versionId})`,
890
+ );
891
+ return {
892
+ action: "merged",
893
+ targetId: decision.targetId,
894
+ mergedContent: committedContent,
895
+ provenancePatched: true,
896
+ };
897
+ }
898
+
899
+ /**
900
+ * Finding B: for a qualifying write the create path stores the incoming
901
+ * extraction's text as a verbatim artifact anchored to the memory it just
902
+ * wrote. A merge that skipped that step would permanently drop the anchor
903
+ * the same extraction would have stored, so a successful merge persists the
904
+ * artifact against the MERGED target — same gates as the write path
905
+ * (verbatim artifacts enabled, category qualifies, confidence at or above
906
+ * the threshold). A merge target is always active and a pending_review fact
907
+ * never reaches the merge, so the write path's post-write guards cannot
908
+ * apply here. Round N+17 (B): this write is the merge path's LAST durable
909
+ * effect (create-path ordering), and a rejection is isolated inside to a
910
+ * logged warning — the committed target stays discoverable; failures never
911
+ * abort the merge batch.
912
+ */
913
+ export async function writeMergedVerbatimArtifact(
914
+ deps: ExtractionPersistDeps,
915
+ storage: StorageManager,
916
+ targetId: string,
917
+ input: {
918
+ category: string;
919
+ /** Incoming fact body, cited exactly once for this write by the caller. */
920
+ citedContent: string;
921
+ confidence: number;
922
+ tags: readonly string[];
923
+ intent?: { goal?: string; actionType?: string; entityTypes?: string[] };
924
+ sourceConnector?: string;
925
+ origin?: string;
926
+ toolScoped?: boolean;
927
+ },
928
+ ): Promise<void> {
929
+ if (!resolvePresentationCapabilities(deps.config).verbatimArtifacts) return;
930
+ if (!deps.config.verbatimArtifactCategories.includes(input.category as MemoryCategory)) {
931
+ return;
932
+ }
933
+ if (!(input.confidence >= deps.config.verbatimArtifactsMinConfidence)) return;
934
+ try {
935
+ await storage.writeArtifact(input.citedContent, {
936
+ confidence: input.confidence,
937
+ tags: [...input.tags, "artifact"],
938
+ artifactType: deps.artifactTypeForCategory(input.category),
939
+ sourceMemoryId: targetId,
940
+ intentGoal: input.intent?.goal,
941
+ intentActionType: input.intent?.actionType,
942
+ intentEntityTypes: input.intent?.entityTypes,
943
+ ...(input.sourceConnector ? { sourceConnector: input.sourceConnector } : {}),
944
+ ...(input.origin ? { origin: input.origin } : {}),
945
+ ...(input.toolScoped ? { toolScoped: true as const } : {}),
946
+ });
947
+ } catch (err) {
948
+ // Round N+17 (B): the caller runs this LAST, after every durable merge
949
+ // effect — log and skip; the committed target stays discoverable.
950
+ log.warn(
951
+ `semantic-merge: verbatim artifact write failed for ${targetId} (non-fatal; the committed target remains discoverable): ${err instanceof Error ? err.message : String(err)}`,
952
+ );
953
+ }
954
+ }
955
+
956
+ /**
957
+ * Round N+5 (A+B) + N+6 (A/B/C): the create path's write is followed by
958
+ * post-write stages that OBSERVE the persisted record — graph-edge
959
+ * construction and the behavior-signal ledger. The merge path's `continue`
960
+ * skipped both, so a judge-accepted merge committed new claims that
961
+ * graph-mode recall and runtime-policy learning could never see. This helper
962
+ * runs them for the SURVIVING target, derived from the re-read committed
963
+ * record exactly like `buildMergedTargetPromotionPayload`: category,
964
+ * entityRef, graph content, AND the relative graph path come from the
965
+ * committed record, never the incoming extraction and never a hot-only
966
+ * path-map fallback — the graph context is built from a hot-only corpus
967
+ * scan, so a cold-tier target is absent from it and only `committed.path`
968
+ * carries the true location (N+6 A). The graph content is the canonical RAW
969
+ * pre-citation form — the same body the create path hands `buildGraphEdge`.
970
+ * The target's prior generated edges are removed first in EVERY enabled
971
+ * graph type — entity from-side, time/causal inbound — so a re-merge
972
+ * REPLACES them instead of re-appending duplicates into append-only JSONLs
973
+ * that spreadingActivation would then double-count (N+6 B, N+7 G); if the
974
+ * replacement build fails, the rows the failed build already appended are
975
+ * removed and the removed edges restored, so failure leaves EXACTLY the old
976
+ * set (N+7 E, N+10 C). The target joins the
977
+ * batch's thread episode list at its END — deduped first when already
978
+ * present — so the merge is the thread's latest event and later facts in
979
+ * the same extraction chain their time/causal adjacency through it (N+6 C,
980
+ * N+7 F). Graph failures are fail-open (the committed merge stands,
981
+ * matching the create path's try/catch); the caller owns the ledger flush,
982
+ * so the behavior events are RETURNED for its storage.
983
+ */
984
+ export async function runMergedTargetPostEffects(
985
+ deps: ExtractionPersistDeps,
986
+ storage: StorageManager,
987
+ merge: { targetId: string; mergedContent: string },
988
+ input: {
989
+ /** Written category (parity-guaranteed equal to the committed record's). */
990
+ category: MemoryCategory;
991
+ incomingContent: string;
992
+ incomingConfidence: number;
993
+ namespace: string;
994
+ graphCaps: GraphConstructionCapabilitySet;
995
+ graphContext: {
996
+ allMemsForGraph: MemoryFile[] | null;
997
+ memoryPathById: Map<string, string>;
998
+ previousPersistedRelPath?: string;
999
+ };
1000
+ threadIdForEdge: string | undefined;
1001
+ threadEpisodeIdsForGraph: string[] | undefined;
1002
+ },
1003
+ ): Promise<BehaviorSignalEvent[]> {
1004
+ const signals = buildBehaviorSignalsForMemory({
1005
+ memoryId: merge.targetId,
1006
+ category: input.category,
1007
+ content: input.incomingContent,
1008
+ namespace: input.namespace,
1009
+ confidence: input.incomingConfidence,
1010
+ source: "extraction",
1011
+ });
1012
+ // N+6 C + round N+7 (F): the normal write path pushes every freshly
1013
+ // persisted memory onto the thread episode list (extraction-persist.ts
1014
+ // post-write block); the merge must record the target as the thread's
1015
+ // LATEST event. A target already in the list (created in this thread
1016
+ // earlier, or pushed by a previous merge in this batch) must MOVE to the
1017
+ // end: leaving it at its old position makes the NEXT fact's
1018
+ // recent-in-thread resolution chain through an older episode instead of
1019
+ // the merge that just happened.
1020
+ if (input.threadEpisodeIdsForGraph) {
1021
+ const episodes = input.threadEpisodeIdsForGraph;
1022
+ const existing = episodes.lastIndexOf(merge.targetId);
1023
+ if (existing !== -1) episodes.splice(existing, 1);
1024
+ episodes.push(merge.targetId);
1025
+ }
1026
+ if (!input.graphCaps.multiGraphMemory) return signals;
1027
+ try {
1028
+ const committed = await storage.getMemoryByIdIncludingArchived(merge.targetId);
1029
+ if (!committed || committed.content !== merge.mergedContent) return signals;
1030
+ if (inferMemoryStatus(committed.frontmatter, committed.path) !== "active") return signals;
1031
+ const entityRef = committed.frontmatter.entityRef;
1032
+ const rawBody = rawPreCitationMergedBody(deps, merge.mergedContent);
1033
+ // N+6 A: derive the relative path from the cold-aware committed record.
1034
+ // The graph context's path map was built from a HOT-only corpus scan, so
1035
+ // a cold-tier target is missing from it and the category-dir fallback
1036
+ // would fabricate a hot node path that graph recall cannot resolve.
1037
+ const memoryRelPath = path.relative(storage.dir, committed.path);
1038
+ input.graphContext.memoryPathById.set(merge.targetId, memoryRelPath);
1039
+ // The target predates this extraction, so a corpus-loaded context already
1040
+ // holds an entry for it — refresh that entry's body in place instead of
1041
+ // appending a duplicate the sibling scan would double-count.
1042
+ const all = input.graphContext.allMemsForGraph;
1043
+ if (Array.isArray(all)) {
1044
+ const entry = all.find((m) => path.relative(storage.dir, m.path) === memoryRelPath);
1045
+ if (entry) entry.content = rawBody;
1046
+ }
1047
+ // N+6 B + round N+7 (E/G) + round N+10 (C) + round N+12 (C): onMemoryWritten is
1048
+ // append-only, so a re-merge must first drop the target's prior
1049
+ // generated edges in EVERY enabled graph type — entity from-side,
1050
+ // time/causal inbound — or each later merge re-appends them and
1051
+ // spreadingActivation double-counts the duplicates while the JSONLs
1052
+ // The removed edges are captured; when the replacement build FAILS or is
1053
+ // superseded, the rows THAT build appended — returned by identity from
1054
+ // onMemoryWritten (round N+14), or carried on its rejection when it
1055
+ // throws mid-append (round N+16 A) — are removed first, never a
1056
+ // node-wide sweep, so rows a newer writer rebuilt after this removal
1057
+ // survive. The
1058
+ // prior edges are then RESTORED per graph type, skipped only where a
1059
+ // newer writer's rebuilt rows are live in the file — so failure leaves
1060
+ // EXACTLY the old set, and supersession leaves exactly the newer
1061
+ // writer's set: never none, never old plus partial-new.
1062
+ const rewriteTypes: GraphType[] = [];
1063
+ if (input.graphCaps.entityGraph) rewriteTypes.push("entity");
1064
+ if (input.graphCaps.timeGraph) rewriteTypes.push("time");
1065
+ if (input.graphCaps.causalGraph) rewriteTypes.push("causal");
1066
+ // Round N+12 (C): the remove-and-rebuild is revision-guarded end to end
1067
+ // (see rewriteMergedTargetGraphEdges) — a writer committing a newer body
1068
+ // mid-rebuild aborts this install instead of clobbering its edges.
1069
+ const installed = await rewriteMergedTargetGraphEdges(storage, {
1070
+ targetId: merge.targetId,
1071
+ memoryRelPath,
1072
+ mergedContent: merge.mergedContent,
1073
+ revisionChecked: committed.frontmatter.updated,
1074
+ rewriteTypes,
1075
+ build: () =>
1076
+ deps.buildGraphEdge(
1077
+ storage,
1078
+ memoryRelPath,
1079
+ entityRef,
1080
+ merge.targetId,
1081
+ rawBody,
1082
+ all,
1083
+ input.graphContext.memoryPathById,
1084
+ input.threadIdForEdge,
1085
+ input.threadEpisodeIdsForGraph,
1086
+ input.graphContext.previousPersistedRelPath,
1087
+ input.graphCaps,
1088
+ ),
1089
+ });
1090
+ if (installed) input.graphContext.previousPersistedRelPath = memoryRelPath;
1091
+ } catch {
1092
+ /* fail-open: the committed merge stands; the create path's graph block fails open too */
1093
+ }
1094
+ return signals;
1095
+ }