@remnic/core 9.7.14 → 9.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (950) hide show
  1. package/dist/access-admin-ops-surface.d.ts +13 -6
  2. package/dist/access-admin-ops-surface.js +88 -74
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-boundary.d.ts +35 -17
  5. package/dist/access-boundary.js +89 -77
  6. package/dist/access-citation.d.ts +28 -0
  7. package/dist/access-citation.js +9 -0
  8. package/dist/access-cli.js +197 -181
  9. package/dist/access-cli.js.map +1 -1
  10. package/dist/access-errors.d.ts +16 -1
  11. package/dist/access-errors.js +7 -3
  12. package/dist/access-http.d.ts +25 -19
  13. package/dist/access-http.js +103 -90
  14. package/dist/access-identity-continuity-surface.d.ts +13 -8
  15. package/dist/access-identity-continuity-surface.js +88 -74
  16. package/dist/access-lcm-surface.d.ts +16 -9
  17. package/dist/access-lcm-surface.js +88 -74
  18. package/dist/access-mcp.d.ts +23 -16
  19. package/dist/access-mcp.js +99 -87
  20. package/dist/access-memory-search-fanout.d.ts +93 -0
  21. package/dist/access-memory-search-fanout.js +18 -0
  22. package/dist/access-observe-write-surface.d.ts +26 -8
  23. package/dist/access-observe-write-surface.js +88 -74
  24. package/dist/access-operations-batch.js +95 -83
  25. package/dist/access-operations.d.ts +26 -19
  26. package/dist/access-operations.js +97 -85
  27. package/dist/access-recall-concurrency.d.ts +250 -0
  28. package/dist/access-recall-concurrency.js +157 -0
  29. package/dist/access-recall-response.d.ts +130 -0
  30. package/dist/access-recall-response.js +147 -0
  31. package/dist/access-recall-surface.d.ts +15 -7
  32. package/dist/access-recall-surface.js +88 -74
  33. package/dist/access-schema.d.ts +34 -34
  34. package/dist/access-schema.js +8 -6
  35. package/dist/{access-service-CPhSnLOH.d.ts → access-service-DEL4qCrc.d.ts} +25 -32
  36. package/dist/access-service.d.ts +13 -6
  37. package/dist/access-service.js +92 -75
  38. package/dist/access-surface-catalog.d.ts +23 -16
  39. package/dist/access-surface-catalog.js +1 -0
  40. package/dist/access-surface-catalog.js.map +1 -1
  41. package/dist/access-token-capabilities.d.ts +2 -1
  42. package/dist/access-token-capabilities.js +4 -2
  43. package/dist/action-confidence.d.ts +3 -1
  44. package/dist/active-memory-bridge.d.ts +3 -1
  45. package/dist/active-memory-bridge.js +4 -4
  46. package/dist/active-recall.d.ts +4 -1
  47. package/dist/active-recall.js +23 -13
  48. package/dist/active-recall.js.map +1 -1
  49. package/dist/adapters/index.js +4 -4
  50. package/dist/adapters/registry.js +2 -2
  51. package/dist/{auto-sync-AAMTVZMK.js → auto-sync-UZG3XQZ5.js} +14 -8
  52. package/dist/{auto-sync-AAMTVZMK.js.map → auto-sync-UZG3XQZ5.js.map} +1 -1
  53. package/dist/behavior-learner.d.ts +3 -1
  54. package/dist/behavior-signals.d.ts +3 -1
  55. package/dist/bootstrap.d.ts +12 -7
  56. package/dist/bootstrap.js +2 -2
  57. package/dist/bounded-jsonl-state.d.ts +54 -0
  58. package/dist/bounded-jsonl-state.js +10 -0
  59. package/dist/boxes.js +2 -2
  60. package/dist/briefing.d.ts +5 -2
  61. package/dist/briefing.js +37 -27
  62. package/dist/buffer-surprise-report.d.ts +3 -1
  63. package/dist/buffer.d.ts +60 -2
  64. package/dist/buffer.js +3 -3
  65. package/dist/bulk-import/index.d.ts +5 -3
  66. package/dist/calibration.d.ts +3 -1
  67. package/dist/calibration.js +6 -6
  68. package/dist/capabilities.d.ts +7 -7
  69. package/dist/capabilities.js +1 -1
  70. package/dist/{capsule-crypto-CZJSLEFG.js → capsule-crypto-YO5QJ6L3.js} +3 -3
  71. package/dist/capsule-crypto-YO5QJ6L3.js.map +1 -0
  72. package/dist/{capsule-merge-Z2HUO6IK.js → capsule-merge-5KKJQBWQ.js} +4 -4
  73. package/dist/{catalog-uX9sT9ws.d.ts → catalog-BWqHb5HT.d.ts} +1 -1
  74. package/dist/causal-behavior.d.ts +3 -1
  75. package/dist/causal-behavior.js +6 -6
  76. package/dist/causal-chain.js +4 -4
  77. package/dist/causal-consolidation.d.ts +3 -1
  78. package/dist/causal-consolidation.js +46 -37
  79. package/dist/causal-consolidation.js.map +1 -1
  80. package/dist/causal-retrieval.js +6 -6
  81. package/dist/causal-trajectory-graph.d.ts +3 -1
  82. package/dist/causal-trajectory-graph.js +1 -1
  83. package/dist/causal-trajectory.js +1 -1
  84. package/dist/{chunk-A3GOMRJG.js → chunk-23L3IXFD.js} +2 -2
  85. package/dist/chunk-2CGLBUW3.js +15 -0
  86. package/dist/chunk-2CGLBUW3.js.map +1 -0
  87. package/dist/{chunk-MRHFJV44.js → chunk-2DQ2XREU.js} +2 -2
  88. package/dist/{chunk-ASKEM4AR.js → chunk-2EJOEICD.js} +1823 -1483
  89. package/dist/chunk-2EJOEICD.js.map +1 -0
  90. package/dist/{chunk-L2B3EE7B.js → chunk-2QMKMVHH.js} +2 -2
  91. package/dist/{chunk-6CALL5VN.js → chunk-2UFO7X4Q.js} +7 -7
  92. package/dist/{chunk-2MR3MFQB.js → chunk-2VEOKUPP.js} +3 -3
  93. package/dist/chunk-2Z24E5W2.js +22 -0
  94. package/dist/chunk-2Z24E5W2.js.map +1 -0
  95. package/dist/{chunk-RHOZ5LLO.js → chunk-347WD2LE.js} +2 -2
  96. package/dist/{chunk-5S7Z5SHA.js → chunk-34RC5RT7.js} +2 -2
  97. package/dist/{chunk-KGWXHWAH.js → chunk-3QAH2S33.js} +3 -3
  98. package/dist/{chunk-37CTGERM.js → chunk-3WCASNQZ.js} +12 -1
  99. package/dist/chunk-3WCASNQZ.js.map +1 -0
  100. package/dist/{chunk-ZIDSD6VC.js → chunk-3Y224NYC.js} +3 -3
  101. package/dist/{chunk-RBQLJSJ7.js → chunk-44XZ75OQ.js} +46 -10
  102. package/dist/chunk-44XZ75OQ.js.map +1 -0
  103. package/dist/{chunk-VFSP73LP.js → chunk-45GF7Y3V.js} +2 -2
  104. package/dist/{chunk-7ICYQUOL.js → chunk-4BJQODZF.js} +2514 -1526
  105. package/dist/chunk-4BJQODZF.js.map +1 -0
  106. package/dist/{chunk-JMBVCAR4.js → chunk-57OWKFUQ.js} +17 -6
  107. package/dist/chunk-57OWKFUQ.js.map +1 -0
  108. package/dist/{chunk-OEHCMALU.js → chunk-5I4M26Q7.js} +5 -5
  109. package/dist/{chunk-2E6G7FCE.js → chunk-5Q7EVV4X.js} +7 -7
  110. package/dist/{chunk-LC7OODWZ.js → chunk-5SB7SC2G.js} +80 -49
  111. package/dist/chunk-5SB7SC2G.js.map +1 -0
  112. package/dist/{chunk-VZ5OJE4X.js → chunk-5VQJBH2G.js} +2 -2
  113. package/dist/{chunk-PUBTHW5O.js → chunk-6DRPPQEJ.js} +2 -2
  114. package/dist/{chunk-NWTGD4AN.js → chunk-6KIQT7RG.js} +10 -9
  115. package/dist/chunk-6KIQT7RG.js.map +1 -0
  116. package/dist/{chunk-4LEF6XWJ.js → chunk-6O22TZSB.js} +3 -3
  117. package/dist/{chunk-ZQ7UBUZ6.js → chunk-6QYST5XN.js} +6 -6
  118. package/dist/{chunk-W4PGTAS2.js → chunk-6WAFYNVT.js} +3 -3
  119. package/dist/chunk-6ZMAMSHS.js +20 -0
  120. package/dist/chunk-6ZMAMSHS.js.map +1 -0
  121. package/dist/{chunk-R5VAVVHP.js → chunk-72A4L5JJ.js} +2 -2
  122. package/dist/{chunk-X64YLC24.js → chunk-72VAXGEI.js} +5 -13
  123. package/dist/chunk-72VAXGEI.js.map +1 -0
  124. package/dist/{chunk-IKQTFQMI.js → chunk-755Q3DGF.js} +22 -3
  125. package/dist/chunk-755Q3DGF.js.map +1 -0
  126. package/dist/{chunk-F7AU34FC.js → chunk-76GLCM57.js} +160 -127
  127. package/dist/chunk-76GLCM57.js.map +1 -0
  128. package/dist/{chunk-D7FOKIY5.js → chunk-7AMFUATK.js} +12 -9
  129. package/dist/{chunk-D7FOKIY5.js.map → chunk-7AMFUATK.js.map} +1 -1
  130. package/dist/{chunk-BFVEEB7W.js → chunk-7ON2JW73.js} +57 -22
  131. package/dist/chunk-7ON2JW73.js.map +1 -0
  132. package/dist/chunk-7RNBVZZO.js +270 -0
  133. package/dist/chunk-7RNBVZZO.js.map +1 -0
  134. package/dist/{chunk-3FAMU5TX.js → chunk-A6USBZTO.js} +2 -2
  135. package/dist/{chunk-TXVD7PLT.js → chunk-A72SWTWW.js} +7 -7
  136. package/dist/{chunk-FC77VUX5.js → chunk-A7Q43EUZ.js} +2 -2
  137. package/dist/{chunk-UJBESW6X.js → chunk-AE7WMV4V.js} +7 -7
  138. package/dist/{chunk-J2HSAU72.js → chunk-AIK5W3IW.js} +29 -1
  139. package/dist/chunk-AIK5W3IW.js.map +1 -0
  140. package/dist/{chunk-OKUEZOGW.js → chunk-AITCS2RC.js} +2 -2
  141. package/dist/{chunk-OC35KQIN.js → chunk-AJ7QCSIS.js} +4 -4
  142. package/dist/{chunk-FNMFJWBY.js → chunk-ANEUPF6O.js} +5 -5
  143. package/dist/chunk-AREGMX2J.js +50 -0
  144. package/dist/chunk-AREGMX2J.js.map +1 -0
  145. package/dist/chunk-AVPXXV6J.js +448 -0
  146. package/dist/chunk-AVPXXV6J.js.map +1 -0
  147. package/dist/{chunk-2A3OXAP2.js → chunk-B7RWBZXW.js} +2 -2
  148. package/dist/{chunk-GWTFLF2P.js → chunk-BJMBJZ2Y.js} +59 -59
  149. package/dist/chunk-BJMBJZ2Y.js.map +1 -0
  150. package/dist/{chunk-N3JDIRBW.js → chunk-BLAKS3CP.js} +4 -4
  151. package/dist/{chunk-M7VGG3ID.js → chunk-BV5WMSIJ.js} +9 -9
  152. package/dist/{chunk-2BFLDH5F.js → chunk-BXLOS5AJ.js} +2 -2
  153. package/dist/{chunk-UXKMMNJD.js → chunk-C23BYTJV.js} +6 -6
  154. package/dist/{chunk-JZHHREBL.js → chunk-C3AKM55W.js} +2 -2
  155. package/dist/{chunk-RP7YXA67.js → chunk-C5JF6EZ7.js} +2 -2
  156. package/dist/{chunk-FBNWOMCE.js → chunk-C6XBRYVD.js} +16 -15
  157. package/dist/chunk-C6XBRYVD.js.map +1 -0
  158. package/dist/{chunk-FTYDWKO6.js → chunk-CEN6DW6X.js} +12 -2
  159. package/dist/chunk-CEN6DW6X.js.map +1 -0
  160. package/dist/chunk-CGASUJVP.js +421 -0
  161. package/dist/chunk-CGASUJVP.js.map +1 -0
  162. package/dist/{chunk-DDGV7NAX.js → chunk-CQMEM5CC.js} +2 -2
  163. package/dist/{chunk-A7B4RMQG.js → chunk-CXZQOVIE.js} +12 -12
  164. package/dist/chunk-D3V3UMET.js +44 -0
  165. package/dist/chunk-D3V3UMET.js.map +1 -0
  166. package/dist/{chunk-7N2RUBAP.js → chunk-DDA47TES.js} +2 -2
  167. package/dist/{chunk-64SE4X5G.js → chunk-DEBHXHJR.js} +3 -3
  168. package/dist/{chunk-EHK6KZHK.js → chunk-DNHVPZOD.js} +2 -2
  169. package/dist/{chunk-437S3G37.js → chunk-DQEMWVMT.js} +2 -2
  170. package/dist/{chunk-LZZNTPLR.js → chunk-DX3XRGLH.js} +2 -2
  171. package/dist/chunk-EA2H5LML.js +72 -0
  172. package/dist/chunk-EA2H5LML.js.map +1 -0
  173. package/dist/{chunk-IFJ23BHU.js → chunk-EEC7UJPX.js} +112 -106
  174. package/dist/chunk-EEC7UJPX.js.map +1 -0
  175. package/dist/{chunk-KSNVDPDF.js → chunk-EKBNDKDY.js} +21 -20
  176. package/dist/chunk-EKBNDKDY.js.map +1 -0
  177. package/dist/{chunk-YF6FMLBT.js → chunk-EQWEIIKQ.js} +64 -34
  178. package/dist/chunk-EQWEIIKQ.js.map +1 -0
  179. package/dist/{chunk-7MW3CVLD.js → chunk-ES36HTSC.js} +4 -4
  180. package/dist/{chunk-TN7THW5U.js → chunk-ET356KSB.js} +2 -2
  181. package/dist/{chunk-YNDLCWXS.js → chunk-EZ25VE3G.js} +4 -4
  182. package/dist/{chunk-7LFXDGLH.js → chunk-F7GAIWFA.js} +20 -20
  183. package/dist/{chunk-IKSELOIV.js → chunk-FFPJINJE.js} +7 -7
  184. package/dist/chunk-FMLKOL2Z.js +636 -0
  185. package/dist/chunk-FMLKOL2Z.js.map +1 -0
  186. package/dist/chunk-FQC3DHH2.js +20 -0
  187. package/dist/chunk-FQC3DHH2.js.map +1 -0
  188. package/dist/{chunk-V53GJUSL.js → chunk-FUTF72MJ.js} +15 -15
  189. package/dist/chunk-GCASGYIO.js +71 -0
  190. package/dist/chunk-GCASGYIO.js.map +1 -0
  191. package/dist/{chunk-5UNWK7KU.js → chunk-GFPZS3F5.js} +8 -8
  192. package/dist/{chunk-BCDKBDSY.js → chunk-GNVZQ5JN.js} +99 -41
  193. package/dist/chunk-GNVZQ5JN.js.map +1 -0
  194. package/dist/{chunk-G6NKALRN.js → chunk-H4WG3UQZ.js} +2 -2
  195. package/dist/{chunk-HLTAPHZZ.js → chunk-HNZKVLAN.js} +2 -2
  196. package/dist/{chunk-5EZXHU36.js → chunk-HYQJQGD3.js} +2 -2
  197. package/dist/{chunk-ANADNYWK.js → chunk-IDZFBSHN.js} +8 -6
  198. package/dist/{chunk-ANADNYWK.js.map → chunk-IDZFBSHN.js.map} +1 -1
  199. package/dist/{chunk-XVLEGMJI.js → chunk-IFH6LWTO.js} +50 -8
  200. package/dist/chunk-IFH6LWTO.js.map +1 -0
  201. package/dist/{chunk-RULE4VG5.js → chunk-ILGC6JH6.js} +21 -6
  202. package/dist/chunk-ILGC6JH6.js.map +1 -0
  203. package/dist/chunk-IUM3VSHI.js +113 -0
  204. package/dist/chunk-IUM3VSHI.js.map +1 -0
  205. package/dist/{chunk-ND5M64JJ.js → chunk-IYNGIMVG.js} +101 -91
  206. package/dist/chunk-IYNGIMVG.js.map +1 -0
  207. package/dist/{chunk-TRWPCR6P.js → chunk-JECBQBEX.js} +3 -3
  208. package/dist/{chunk-HG32URJJ.js → chunk-JYIFGGEM.js} +2 -2
  209. package/dist/{chunk-VA4WSW54.js → chunk-JYIJNNN3.js} +3 -3
  210. package/dist/{chunk-L5HJQC36.js → chunk-K2TDK7GG.js} +3 -3
  211. package/dist/{chunk-MKDRQAA3.js → chunk-KAVBJSBQ.js} +4 -4
  212. package/dist/{chunk-EEARRVZ2.js → chunk-KF5EUVKQ.js} +16 -6
  213. package/dist/chunk-KF5EUVKQ.js.map +1 -0
  214. package/dist/chunk-KFZY2OFH.js +42 -0
  215. package/dist/chunk-KFZY2OFH.js.map +1 -0
  216. package/dist/{chunk-4OKLXWDZ.js → chunk-KNB7IBBU.js} +2 -2
  217. package/dist/{chunk-QLULYKWZ.js → chunk-KSXJOC4F.js} +2 -2
  218. package/dist/{chunk-OBMR4VIX.js → chunk-L2DPF4DF.js} +186 -15
  219. package/dist/chunk-L2DPF4DF.js.map +1 -0
  220. package/dist/{chunk-JI5AVXYO.js → chunk-LEPOP46W.js} +6 -6
  221. package/dist/{chunk-O7BBFJLP.js → chunk-LTAVSOZW.js} +2 -2
  222. package/dist/{chunk-E3VODCC3.js → chunk-LUDXM7MD.js} +14 -2
  223. package/dist/{chunk-E3VODCC3.js.map → chunk-LUDXM7MD.js.map} +1 -1
  224. package/dist/{chunk-2IZAGAJR.js → chunk-LULR4IUW.js} +3 -3
  225. package/dist/{chunk-NUWYOKS6.js → chunk-MC5Q3J7S.js} +398 -7
  226. package/dist/chunk-MC5Q3J7S.js.map +1 -0
  227. package/dist/{chunk-WMWVO45V.js → chunk-MC6XO7T4.js} +2 -2
  228. package/dist/chunk-MKQBXQKU.js +107 -0
  229. package/dist/chunk-MKQBXQKU.js.map +1 -0
  230. package/dist/{chunk-7PND4PUC.js → chunk-MMGGVZ4Q.js} +29 -9
  231. package/dist/{chunk-7PND4PUC.js.map → chunk-MMGGVZ4Q.js.map} +1 -1
  232. package/dist/{chunk-D6RIFG4O.js → chunk-MNB5RMAY.js} +2 -2
  233. package/dist/{chunk-67ZCJLJY.js → chunk-MYFQ3ED4.js} +8 -8
  234. package/dist/{chunk-V3UE5I5F.js → chunk-MYVPLJOO.js} +2 -2
  235. package/dist/chunk-NINSR6LX.js +83 -0
  236. package/dist/chunk-NINSR6LX.js.map +1 -0
  237. package/dist/{chunk-MTWKDOVO.js → chunk-NLE6TSLG.js} +2 -2
  238. package/dist/{chunk-DBRYEIGY.js → chunk-OJP3N7UK.js} +2 -2
  239. package/dist/{chunk-AD6AMF2N.js → chunk-OQJIB32H.js} +28 -23
  240. package/dist/chunk-OQJIB32H.js.map +1 -0
  241. package/dist/{chunk-SMX5267P.js → chunk-OZKOPQCM.js} +2 -2
  242. package/dist/{chunk-JCK7V6SN.js → chunk-P65YJEEL.js} +2 -2
  243. package/dist/{chunk-MTR7BZQN.js → chunk-PBGWYM3H.js} +3 -3
  244. package/dist/chunk-PIG4WJFQ.js +87 -0
  245. package/dist/chunk-PIG4WJFQ.js.map +1 -0
  246. package/dist/chunk-PQVCH2AE.js +76 -0
  247. package/dist/chunk-PQVCH2AE.js.map +1 -0
  248. package/dist/{chunk-AXTXN4T6.js → chunk-PWFCHOB3.js} +2 -2
  249. package/dist/{chunk-FDPZVY6D.js → chunk-QFN4U7AG.js} +2 -2
  250. package/dist/{chunk-K2ZLHESQ.js → chunk-QIEUU4UK.js} +2 -2
  251. package/dist/{chunk-AHLPZ2SF.js → chunk-QJAQNXWI.js} +44 -6
  252. package/dist/chunk-QJAQNXWI.js.map +1 -0
  253. package/dist/{chunk-3D6AFGQR.js → chunk-QVT3E4CE.js} +7 -7
  254. package/dist/{chunk-VYOFVVNK.js → chunk-R26ZMXR2.js} +24 -24
  255. package/dist/{chunk-VYOFVVNK.js.map → chunk-R26ZMXR2.js.map} +1 -1
  256. package/dist/chunk-R3DJVOSM.js +34 -0
  257. package/dist/chunk-R3DJVOSM.js.map +1 -0
  258. package/dist/{chunk-SFQ6QNL7.js → chunk-R6YJI3HE.js} +2 -1
  259. package/dist/{chunk-5CJVLG3H.js → chunk-RFDD3B7W.js} +5 -5
  260. package/dist/{chunk-JBPKEARU.js → chunk-RKNJBZ55.js} +4 -4
  261. package/dist/chunk-ROI7BK7H.js +88 -0
  262. package/dist/chunk-ROI7BK7H.js.map +1 -0
  263. package/dist/{chunk-UTRJFDP2.js → chunk-S2BBISHU.js} +4 -4
  264. package/dist/{chunk-IALLX7EE.js → chunk-S2FSBU4H.js} +3 -3
  265. package/dist/{chunk-BFPETA3S.js → chunk-SCCO46KZ.js} +3 -2
  266. package/dist/chunk-SCCO46KZ.js.map +1 -0
  267. package/dist/chunk-SICXL4MK.js +165 -0
  268. package/dist/chunk-SICXL4MK.js.map +1 -0
  269. package/dist/chunk-SK7AMF2J.js +168 -0
  270. package/dist/chunk-SK7AMF2J.js.map +1 -0
  271. package/dist/{chunk-GMSDQUCR.js → chunk-TDTXKOAJ.js} +6475 -5748
  272. package/dist/chunk-TDTXKOAJ.js.map +1 -0
  273. package/dist/{chunk-KSBEEMQF.js → chunk-TG6IHVE2.js} +151 -6
  274. package/dist/chunk-TG6IHVE2.js.map +1 -0
  275. package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
  276. package/dist/{chunk-PK5XBDA6.js → chunk-U3ZAVRP3.js} +2 -2
  277. package/dist/{chunk-ODPLEWB6.js → chunk-UFGFMWAD.js} +47 -17
  278. package/dist/chunk-UFGFMWAD.js.map +1 -0
  279. package/dist/{chunk-4KJLYTLS.js → chunk-V57NLO5P.js} +2 -2
  280. package/dist/{chunk-FLVL4L3L.js → chunk-VDX2J7OX.js} +2 -2
  281. package/dist/{chunk-7XGSIUP5.js → chunk-W4FBGYGK.js} +1 -1
  282. package/dist/{chunk-TXLGHDHS.js → chunk-W4XJFLAL.js} +53 -32
  283. package/dist/chunk-W4XJFLAL.js.map +1 -0
  284. package/dist/{chunk-6SXVCD7W.js → chunk-W7IGLX4G.js} +2 -2
  285. package/dist/{chunk-KQDNAXOM.js → chunk-WG5HSQ4P.js} +19 -6
  286. package/dist/chunk-WG5HSQ4P.js.map +1 -0
  287. package/dist/{chunk-LTJAMRGI.js → chunk-WL5EBRDH.js} +17 -3
  288. package/dist/chunk-WL5EBRDH.js.map +1 -0
  289. package/dist/{chunk-KAWTOYAW.js → chunk-WLZYGLJ4.js} +2 -2
  290. package/dist/{chunk-W5NKDU24.js → chunk-WON4APQY.js} +4 -4
  291. package/dist/{chunk-NKCPUHCI.js → chunk-WZFAPHIK.js} +6 -6
  292. package/dist/{chunk-KQPJLK3X.js → chunk-XL24QQ63.js} +2 -2
  293. package/dist/{chunk-X47LWMKA.js → chunk-XMMESCPD.js} +26 -1
  294. package/dist/chunk-XMMESCPD.js.map +1 -0
  295. package/dist/{chunk-4B4MUS5D.js → chunk-YROFNEG5.js} +7 -7
  296. package/dist/{chunk-WU46YPY6.js → chunk-YV32N67O.js} +1 -1
  297. package/dist/chunk-YV32N67O.js.map +1 -0
  298. package/dist/{chunk-B3F4CWQR.js → chunk-YVKF3HEW.js} +1 -1
  299. package/dist/chunk-YVKF3HEW.js.map +1 -0
  300. package/dist/{chunk-VRAD2FGO.js → chunk-Z54EM5YZ.js} +12 -12
  301. package/dist/{chunk-2VN4JAX7.js → chunk-ZOKZIR5K.js} +95 -33
  302. package/dist/chunk-ZOKZIR5K.js.map +1 -0
  303. package/dist/{cli-_Y2Bmt6A.d.ts → cli-C_pqqTCw.d.ts} +28 -12
  304. package/dist/cli.d.ts +16 -9
  305. package/dist/cli.js +145 -130
  306. package/dist/compounding/engine.d.ts +5 -2
  307. package/dist/compounding/engine.js +39 -29
  308. package/dist/compounding/preference-consolidator.d.ts +3 -1
  309. package/dist/compounding/preference-consolidator.js +1 -1
  310. package/dist/compression-optimizer.d.ts +3 -1
  311. package/dist/config-qmd.d.ts +8 -0
  312. package/dist/config-qmd.js +20 -0
  313. package/dist/config-qmd.js.map +1 -0
  314. package/dist/config.d.ts +3 -1
  315. package/dist/config.js +15 -10
  316. package/dist/connectors/codex-materialize-runner.d.ts +3 -1
  317. package/dist/connectors/codex-materialize-runner.js +39 -29
  318. package/dist/connectors/codex-materialize.d.ts +3 -1
  319. package/dist/connectors/codex-materialize.js +2 -2
  320. package/dist/connectors/index.d.ts +3 -1
  321. package/dist/connectors/index.js +44 -35
  322. package/dist/consolidation-provenance-check.d.ts +5 -2
  323. package/dist/consolidation-provenance-check.js +4 -4
  324. package/dist/consolidation-undo.d.ts +5 -2
  325. package/dist/consolidation-undo.js +3 -3
  326. package/dist/contradiction/index.d.ts +5 -2
  327. package/dist/contradiction/index.js +10 -4
  328. package/dist/{contradiction-scan-J57T5QV7.js → contradiction-scan-RJBABNRH.js} +4 -4
  329. package/dist/contradiction-scan-RJBABNRH.js.map +1 -0
  330. package/dist/conversation-index/backend.d.ts +3 -1
  331. package/dist/conversation-index/backend.js +5 -5
  332. package/dist/conversation-index/chunker.d.ts +3 -1
  333. package/dist/conversation-index/cleanup.js +2 -2
  334. package/dist/conversation-index/faiss-adapter.d.ts +3 -1
  335. package/dist/conversation-index/faiss-adapter.js +2 -2
  336. package/dist/conversation-index/indexer.d.ts +3 -1
  337. package/dist/conversation-index/indexer.js +2 -2
  338. package/dist/conversation-index/search.d.ts +3 -1
  339. package/dist/conversation-index/search.js +2 -2
  340. package/dist/cross-namespace-budget.d.ts +45 -1
  341. package/dist/cross-namespace-budget.js +5 -3
  342. package/dist/dashboard-runtime.js +2 -2
  343. package/dist/day-summary.d.ts +3 -1
  344. package/dist/day-summary.js +3 -3
  345. package/dist/delinearize.d.ts +3 -1
  346. package/dist/direct-answer-wiring.d.ts +3 -1
  347. package/dist/direct-answer.d.ts +3 -1
  348. package/dist/{dreams-ledger-6UODQOX6.js → dreams-ledger-567VKVOU.js} +4 -2
  349. package/dist/dreams-ledger-567VKVOU.js.map +1 -0
  350. package/dist/embedding-fallback.d.ts +3 -1
  351. package/dist/embedding-fallback.js +3 -3
  352. package/dist/enrichment/index.d.ts +3 -1
  353. package/dist/entity-retrieval.d.ts +5 -2
  354. package/dist/entity-retrieval.js +38 -29
  355. package/dist/entity-schema.d.ts +3 -1
  356. package/dist/explicit-capture.d.ts +13 -8
  357. package/dist/explicit-capture.js +7 -3
  358. package/dist/extraction-faithfulness.d.ts +3 -1
  359. package/dist/extraction-faithfulness.js +5 -5
  360. package/dist/extraction-judge-telemetry.d.ts +3 -1
  361. package/dist/extraction-judge-telemetry.js +2 -2
  362. package/dist/extraction-judge-training.d.ts +3 -1
  363. package/dist/extraction-judge-training.js +2 -2
  364. package/dist/extraction-judge.d.ts +3 -1
  365. package/dist/extraction-judge.js +5 -5
  366. package/dist/extraction.d.ts +3 -1
  367. package/dist/extraction.js +13 -12
  368. package/dist/faithfulness-config.js +3 -2
  369. package/dist/fallback-llm.d.ts +3 -1
  370. package/dist/fallback-llm.js +4 -4
  371. package/dist/{first-start-migration-TI67YMLG.js → first-start-migration-CSRHCJIQ.js} +2 -2
  372. package/dist/{forget-CQCLB5LB.js → forget-HRPLVB3W.js} +5 -5
  373. package/dist/graph-dashboard-diff.d.ts +3 -1
  374. package/dist/graph-dashboard-key.d.ts +3 -1
  375. package/dist/graph-dashboard-parser.d.ts +3 -1
  376. package/dist/{graph-edge-decay-FO7AM4UR.js → graph-edge-decay-Z6ENALU2.js} +3 -3
  377. package/dist/graph-edge-decay-Z6ENALU2.js.map +1 -0
  378. package/dist/graph-edge-reinforcement.d.ts +3 -1
  379. package/dist/graph-snapshot.d.ts +3 -1
  380. package/dist/graph-snapshot.js +2 -2
  381. package/dist/graph.d.ts +57 -10
  382. package/dist/graph.js +1 -1
  383. package/dist/identity-continuity.d.ts +1 -2
  384. package/dist/importance.d.ts +3 -1
  385. package/dist/importers/index.d.ts +3 -1
  386. package/dist/in-flight-reads.d.ts +3 -1
  387. package/dist/index.d.ts +101 -92
  388. package/dist/index.js +290 -242
  389. package/dist/intent.d.ts +3 -1
  390. package/dist/lcm/archive.js +2 -2
  391. package/dist/lcm/engine.d.ts +3 -1
  392. package/dist/lcm/engine.js +6 -6
  393. package/dist/lcm/index.d.ts +3 -1
  394. package/dist/lcm/index.js +13 -13
  395. package/dist/lcm/schema.js +2 -2
  396. package/dist/lcm/summarizer.js +3 -3
  397. package/dist/lcm/tools.d.ts +3 -1
  398. package/dist/lifecycle.d.ts +3 -1
  399. package/dist/live-connectors-runner.d.ts +3 -1
  400. package/dist/local-llm.d.ts +5 -2
  401. package/dist/local-llm.js +3 -3
  402. package/dist/local-model-endpoint.d.ts +3 -1
  403. package/dist/logger.d.ts +3 -1
  404. package/dist/logger.js +7 -3
  405. package/dist/maintenance/archive-observations.js +2 -2
  406. package/dist/maintenance/memory-governance.d.ts +3 -1
  407. package/dist/maintenance/memory-governance.js +38 -28
  408. package/dist/maintenance/migrate-observations.js +3 -3
  409. package/dist/maintenance/observation-ledger-utils.js +2 -2
  410. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +102 -1
  411. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +40 -28
  412. package/dist/maintenance/rebuild-memory-projection.js +41 -31
  413. package/dist/maintenance/rebuild-observations.js +3 -3
  414. package/dist/mcp-memory-inspector-app.d.ts +22 -15
  415. package/dist/memory-action-policy.d.ts +3 -1
  416. package/dist/memory-cache.d.ts +46 -2
  417. package/dist/memory-cache.js +7 -1
  418. package/dist/memory-corpus-version.js +2 -2
  419. package/dist/memory-lifecycle-ledger-utils.d.ts +25 -2
  420. package/dist/memory-lifecycle-ledger-utils.js +11 -1
  421. package/dist/memory-projection-store.d.ts +3 -1
  422. package/dist/memory-projection-store.js +2 -2
  423. package/dist/memory-provenance.d.ts +3 -1
  424. package/dist/memory-worth-outcomes.d.ts +5 -2
  425. package/dist/model-registry.js +2 -2
  426. package/dist/models-json.d.ts +3 -1
  427. package/dist/models-json.js +2 -2
  428. package/dist/namespaces/migrate.d.ts +6 -3
  429. package/dist/namespaces/migrate.js +54 -45
  430. package/dist/namespaces/principal.d.ts +27 -2
  431. package/dist/namespaces/principal.js +6 -2
  432. package/dist/namespaces/search.d.ts +16 -2
  433. package/dist/namespaces/search.js +25 -21
  434. package/dist/namespaces/storage.d.ts +24 -3
  435. package/dist/namespaces/storage.js +38 -30
  436. package/dist/native-knowledge.d.ts +3 -1
  437. package/dist/native-knowledge.js +2 -2
  438. package/dist/negative.js +2 -2
  439. package/dist/offline-sync-exclude-globs.d.ts +13 -0
  440. package/dist/offline-sync-exclude-globs.js +10 -0
  441. package/dist/offline-sync-exclude-globs.js.map +1 -0
  442. package/dist/offline-sync-impression-drain.d.ts +78 -0
  443. package/dist/offline-sync-impression-drain.js +37 -0
  444. package/dist/offline-sync-impression-drain.js.map +1 -0
  445. package/dist/offline-sync.js +4 -2
  446. package/dist/operator-toolkit.d.ts +5 -2
  447. package/dist/operator-toolkit.js +73 -58
  448. package/dist/orchestration/compression-guideline-coordinator.d.ts +5 -2
  449. package/dist/orchestration/compression-guideline-coordinator.js +3 -3
  450. package/dist/orchestration/maintenance.d.ts +121 -2
  451. package/dist/orchestration/maintenance.js +47 -34
  452. package/dist/{orchestrator-BbZ_dQSU.d.ts → orchestrator-CQJ8U7En.d.ts} +85 -79
  453. package/dist/orchestrator.d.ts +13 -8
  454. package/dist/orchestrator.js +197 -180
  455. package/dist/page-versioning.js +3 -3
  456. package/dist/patterns-cli.d.ts +3 -1
  457. package/dist/{pipeline-FRMDb1fn.d.ts → pipeline-Cn-kvYeV.d.ts} +1 -1
  458. package/dist/policy-runtime.d.ts +3 -1
  459. package/dist/prioritized-embed.d.ts +19 -0
  460. package/dist/prioritized-embed.js +8 -0
  461. package/dist/prioritized-embed.js.map +1 -0
  462. package/dist/proactive-contention.d.ts +28 -0
  463. package/dist/proactive-contention.js +8 -0
  464. package/dist/proactive-contention.js.map +1 -0
  465. package/dist/profiling.js +2 -2
  466. package/dist/provenance.d.ts +3 -1
  467. package/dist/provenance.js +3 -2
  468. package/dist/{purge-NDWV6WYD.js → purge-IRF47ZTX.js} +3 -3
  469. package/dist/{qmd-xJRrHFbA.d.ts → qmd-oh9VXz1d.d.ts} +11 -1
  470. package/dist/qmd-preflight.d.ts +5 -2
  471. package/dist/qmd-recall-cache.d.ts +3 -1
  472. package/dist/qmd-status.d.ts +57 -0
  473. package/dist/qmd-status.js +18 -0
  474. package/dist/qmd-status.js.map +1 -0
  475. package/dist/qmd.d.ts +5 -2
  476. package/dist/qmd.js +8 -4
  477. package/dist/recall-concurrency-config.d.ts +16 -0
  478. package/dist/recall-concurrency-config.js +10 -0
  479. package/dist/recall-concurrency-config.js.map +1 -0
  480. package/dist/recall-disclosure-escalation.d.ts +3 -1
  481. package/dist/recall-explain-renderer.d.ts +4 -1
  482. package/dist/recall-explain-renderer.js +3 -3
  483. package/dist/recall-memory-map.d.ts +26 -0
  484. package/dist/recall-memory-map.js +18 -0
  485. package/dist/recall-memory-map.js.map +1 -0
  486. package/dist/recall-planner-llm.d.ts +3 -1
  487. package/dist/recall-planner-llm.js +4 -4
  488. package/dist/recall-qos.js +2 -2
  489. package/dist/recall-state.d.ts +163 -2
  490. package/dist/recall-state.js +6 -3
  491. package/dist/recall-tag-filter.d.ts +3 -1
  492. package/dist/recall-timings.d.ts +11 -2
  493. package/dist/recall-timings.js +3 -1
  494. package/dist/recall-xray-cli.d.ts +3 -1
  495. package/dist/recall-xray-cli.js +4 -4
  496. package/dist/recall-xray-renderer.d.ts +3 -1
  497. package/dist/recall-xray-renderer.js +3 -3
  498. package/dist/recall-xray.d.ts +3 -1
  499. package/dist/recall-xray.js +2 -2
  500. package/dist/relevance.js +3 -3
  501. package/dist/replay/normalizers/chatgpt.d.ts +3 -1
  502. package/dist/replay/normalizers/claude.d.ts +3 -1
  503. package/dist/replay/normalizers/openclaw.d.ts +3 -1
  504. package/dist/replay/normalizers/shared.d.ts +3 -1
  505. package/dist/replay/runner.d.ts +3 -1
  506. package/dist/replay/types.d.ts +3 -1
  507. package/dist/rerank.d.ts +8 -1
  508. package/dist/rerank.js +3 -1
  509. package/dist/resolution-3K27T4VO.js +18 -0
  510. package/dist/resolution-3K27T4VO.js.map +1 -0
  511. package/dist/resolve-auth-token.d.ts +3 -1
  512. package/dist/resolve-provider-secret.js +2 -2
  513. package/dist/resume-bundles.js +19 -14
  514. package/dist/retrieval-agents.d.ts +19 -16
  515. package/dist/retrieval-agents.js +3 -3
  516. package/dist/retrieval-tiers.d.ts +3 -1
  517. package/dist/routing/engine.d.ts +3 -1
  518. package/dist/routing/store.d.ts +3 -1
  519. package/dist/routing/store.js +2 -2
  520. package/dist/salvage-envelope.d.ts +18 -0
  521. package/dist/salvage-envelope.js +15 -0
  522. package/dist/salvage-envelope.js.map +1 -0
  523. package/dist/schemas.d.ts +24 -24
  524. package/dist/scope-profiles-EpJG7yKP.d.ts +30 -0
  525. package/dist/search/document-scanner.js +3 -2
  526. package/dist/search/embed-helper.d.ts +3 -1
  527. package/dist/search/embed-helper.js +3 -3
  528. package/dist/search/factory.d.ts +3 -1
  529. package/dist/search/factory.js +19 -17
  530. package/dist/search/index.d.ts +3 -1
  531. package/dist/search/index.js +23 -21
  532. package/dist/search/lancedb-backend.d.ts +3 -1
  533. package/dist/search/lancedb-backend.js +6 -5
  534. package/dist/search/meilisearch-backend.d.ts +3 -1
  535. package/dist/search/meilisearch-backend.js +6 -5
  536. package/dist/search/noop-backend.d.ts +3 -1
  537. package/dist/search/orama-backend.d.ts +3 -1
  538. package/dist/search/orama-backend.js +6 -5
  539. package/dist/search/port.d.ts +27 -2
  540. package/dist/search/port.js +1 -1
  541. package/dist/search/remote-backend.d.ts +3 -1
  542. package/dist/search/remote-backend.js +3 -3
  543. package/dist/secure-store/index.d.ts +12 -1
  544. package/dist/secure-store/index.js +6 -3
  545. package/dist/{semantic-consolidation-fvdZRa5Z.d.ts → semantic-consolidation-DILZEQq3.d.ts} +1 -1
  546. package/dist/semantic-consolidation.d.ts +4 -2
  547. package/dist/semantic-consolidation.js +41 -32
  548. package/dist/semantic-rule-promotion.js +37 -27
  549. package/dist/semantic-rule-verifier.d.ts +3 -1
  550. package/dist/semantic-rule-verifier.js +38 -28
  551. package/dist/session-observer-bands.d.ts +3 -1
  552. package/dist/session-observer-state.d.ts +3 -1
  553. package/dist/session-observer-state.js +2 -2
  554. package/dist/session-transcript-migration.js +2 -2
  555. package/dist/shared-context/manager.d.ts +3 -1
  556. package/dist/shared-context/manager.js +3 -3
  557. package/dist/signal.d.ts +3 -1
  558. package/dist/{storage-CrvzaM9C.d.ts → storage-NIyKYD8g.d.ts} +505 -110
  559. package/dist/storage-guards.js +2 -2
  560. package/dist/storage.d.ts +6 -3
  561. package/dist/storage.js +41 -29
  562. package/dist/structured-attributes.d.ts +23 -1
  563. package/dist/structured-attributes.js +7 -1
  564. package/dist/summarizer.d.ts +3 -1
  565. package/dist/summarizer.js +11 -11
  566. package/dist/summary-snapshot.d.ts +3 -1
  567. package/dist/summary-snapshot.js +2 -2
  568. package/dist/temporal-index-batch.d.ts +1 -0
  569. package/dist/temporal-index-batch.js +10 -0
  570. package/dist/temporal-index-batch.js.map +1 -0
  571. package/dist/temporal-index-compat.d.ts +279 -1
  572. package/dist/temporal-index-compat.js +1 -1
  573. package/dist/temporal-index.d.ts +1 -225
  574. package/dist/temporal-index.js +35 -3
  575. package/dist/temporal-supersession.d.ts +5 -2
  576. package/dist/temporal-supersession.js +2 -2
  577. package/dist/temporal-timeline-recall.d.ts +3 -1
  578. package/dist/temporal-validity.d.ts +3 -1
  579. package/dist/threading.d.ts +3 -1
  580. package/dist/threading.js +2 -2
  581. package/dist/tier-migration.d.ts +5 -2
  582. package/dist/tier-routing.d.ts +3 -1
  583. package/dist/{tier-stats-KV7IWCJR.js → tier-stats-QEJSPFV2.js} +2 -2
  584. package/dist/tokens.js +3 -3
  585. package/dist/topics.d.ts +3 -1
  586. package/dist/transcript.d.ts +3 -1
  587. package/dist/transcript.js +2 -2
  588. package/dist/transfer/backup.js +3 -3
  589. package/dist/transfer/capsule-export.js +3 -3
  590. package/dist/transfer/capsule-import.js +6 -6
  591. package/dist/transfer/types.d.ts +24 -24
  592. package/dist/trust-score-stage.d.ts +75 -38
  593. package/dist/trust-score-stage.js +11 -3
  594. package/dist/trust-score.d.ts +3 -1
  595. package/dist/{types-Bl4BWDM8.d.ts → types-D_fG2ix8.d.ts} +49 -63
  596. package/dist/types-continuity.d.ts +52 -0
  597. package/dist/types-continuity.js +1 -0
  598. package/dist/types-continuity.js.map +1 -0
  599. package/dist/types.d.ts +3 -1
  600. package/dist/types.js +1 -1
  601. package/dist/utility-runtime.d.ts +3 -1
  602. package/dist/utils/serialize-mutations.d.ts +31 -2
  603. package/dist/utils/serialize-mutations.js +1 -1
  604. package/dist/verified-recall.js +39 -29
  605. package/dist/write-envelope.d.ts +282 -0
  606. package/dist/write-envelope.js +35 -0
  607. package/dist/write-envelope.js.map +1 -0
  608. package/dist/write-quarantine.d.ts +79 -0
  609. package/dist/write-quarantine.js +11 -0
  610. package/dist/write-quarantine.js.map +1 -0
  611. package/dist/write-rate-limiter.d.ts +45 -0
  612. package/dist/write-rate-limiter.js +9 -0
  613. package/dist/write-rate-limiter.js.map +1 -0
  614. package/package.json +37 -2
  615. package/src/access-admin-ops-surface.ts +17 -7
  616. package/src/access-boundary.test.ts +28 -0
  617. package/src/access-boundary.ts +31 -2
  618. package/src/access-citation.test.ts +72 -0
  619. package/src/access-citation.ts +139 -0
  620. package/src/access-errors.ts +21 -0
  621. package/src/access-fingerprint-parity.test.ts +211 -0
  622. package/src/access-http-cancellation.test.ts +59 -21
  623. package/src/access-http.test.ts +90 -0
  624. package/src/access-http.ts +79 -79
  625. package/src/access-mcp-cancellation.test.ts +16 -7
  626. package/src/access-memory-search-fanout.test.ts +220 -0
  627. package/src/access-memory-search-fanout.ts +168 -0
  628. package/src/access-observe-quarantine.test.ts +120 -0
  629. package/src/access-observe-write-surface.ts +130 -11
  630. package/src/access-operations-batch.ts +2 -0
  631. package/src/access-recall-concurrency.ts +773 -0
  632. package/src/access-recall-response.ts +307 -0
  633. package/src/access-recall-surface.ts +100 -252
  634. package/src/access-service-coding-write.test.ts +22 -4
  635. package/src/access-service-health.test.ts +49 -0
  636. package/src/access-service-namespace.test.ts +486 -8
  637. package/src/access-service-observe-scope.test.ts +4 -0
  638. package/src/access-service-recall-concurrency.test.ts +1990 -0
  639. package/src/access-service.ts +182 -175
  640. package/src/access-surface-catalog.ts +1 -0
  641. package/src/access-token-capabilities.ts +16 -9
  642. package/src/active-recall.test.ts +35 -0
  643. package/src/active-recall.ts +7 -0
  644. package/src/bounded-jsonl-state.ts +93 -0
  645. package/src/buffer-session.test.ts +422 -5
  646. package/src/buffer-surprise-trigger.test.ts +41 -0
  647. package/src/buffer.ts +218 -3
  648. package/src/capabilities-cluster-b.test.ts +1 -0
  649. package/src/capabilities.ts +5 -6
  650. package/src/cli.ts +21 -22
  651. package/src/coding/architecture-surfaces.test.ts +6 -3
  652. package/src/coding/architecture-surfaces.ts +36 -25
  653. package/src/coding/decision-surfaces.ts +42 -34
  654. package/src/compounding/engine.test.ts +5 -1
  655. package/src/compounding/engine.ts +7 -7
  656. package/src/config-qmd.ts +89 -0
  657. package/src/config.test.ts +136 -0
  658. package/src/config.ts +122 -118
  659. package/src/connector-provenance-lifecycle.test.ts +4 -4
  660. package/src/connectors/coerce.test.ts +131 -0
  661. package/src/connectors/coerce.ts +80 -7
  662. package/src/contradiction/contradiction.test.ts +10 -6
  663. package/src/contradiction/resolution.ts +17 -4
  664. package/src/correction/correction-access-wiring.ts +62 -18
  665. package/src/cross-namespace-budget.test.ts +35 -0
  666. package/src/cross-namespace-budget.ts +86 -19
  667. package/src/explicit-capture.ts +54 -17
  668. package/src/extraction.ts +2 -3
  669. package/src/faithfulness-graph-guard.test.ts +16 -69
  670. package/src/graph-recall.test.ts +31 -0
  671. package/src/graph.test.ts +137 -1
  672. package/src/graph.ts +274 -17
  673. package/src/index.ts +22 -2
  674. package/src/local-llm.ts +4 -6
  675. package/src/logger.ts +16 -0
  676. package/src/maintenance/dreams-ledger.ts +100 -49
  677. package/src/maintenance/rebuild-memory-lifecycle-ledger-cli.ts +77 -0
  678. package/src/maintenance/rebuild-memory-lifecycle-ledger.ts +373 -9
  679. package/src/memory-cache.ts +70 -0
  680. package/src/memory-lifecycle-ledger-utils.ts +51 -5
  681. package/src/namespaces/principal.test.ts +37 -1
  682. package/src/namespaces/principal.ts +48 -0
  683. package/src/namespaces/search.test.ts +79 -5
  684. package/src/namespaces/search.ts +59 -6
  685. package/src/namespaces/storage.ts +45 -1
  686. package/src/offline-sync-exclude-globs.ts +58 -0
  687. package/src/offline-sync-impression-drain.test.ts +316 -0
  688. package/src/offline-sync-impression-drain.ts +260 -0
  689. package/src/offline-sync.test.ts +32 -5
  690. package/src/offline-sync.ts +1 -14
  691. package/src/operator-toolkit.ts +1 -1
  692. package/src/orchestration/batch-deindex-flush.test.ts +146 -0
  693. package/src/orchestration/consolidation-run.ts +96 -85
  694. package/src/orchestration/extraction-envelope.ts +94 -0
  695. package/src/orchestration/extraction-persist-promotion.ts +134 -0
  696. package/src/orchestration/extraction-persist.ts +325 -260
  697. package/src/orchestration/extraction-run.test.ts +1 -1
  698. package/src/orchestration/extraction-run.ts +2 -2
  699. package/src/orchestration/graph-recall-coordinator.ts +18 -7
  700. package/src/orchestration/lifecycle-policy-coordinator.ts +63 -48
  701. package/src/orchestration/maintenance.test.ts +2103 -3
  702. package/src/orchestration/maintenance.ts +581 -2
  703. package/src/orchestration/namespace-read-fanout.ts +14 -8
  704. package/src/orchestration/orchestrator-helpers.ts +8 -1
  705. package/src/orchestration/orchestrator-init.ts +22 -6
  706. package/src/orchestration/orchestrator-namespace-scope.ts +71 -0
  707. package/src/orchestration/persistence-index.ts +64 -9
  708. package/src/orchestration/qmd-result-resolver.ts +27 -0
  709. package/src/orchestration/recall-entry.ts +34 -19
  710. package/src/orchestration/recall-internal.ts +207 -79
  711. package/src/orchestration/recall-rerank-coordinator.ts +229 -82
  712. package/src/orchestration/recall-result-formatter.ts +76 -20
  713. package/src/orchestration/recall-search-pipeline.test.ts +70 -0
  714. package/src/orchestration/recall-search-pipeline.ts +102 -129
  715. package/src/orchestration/recall-section-coordinator.ts +315 -85
  716. package/src/orchestration/semantic-consolidation-coordinator.ts +69 -37
  717. package/src/orchestration/session-context.ts +21 -0
  718. package/src/orchestration/workspace-ops.test.ts +348 -0
  719. package/src/orchestration/workspace-ops.ts +172 -34
  720. package/src/orchestrator-chunked-hash-durability.test.ts +126 -0
  721. package/src/orchestrator-connector-dedup.test.ts +1061 -40
  722. package/src/orchestrator-flush.test.ts +155 -39
  723. package/src/orchestrator-nonchunked-hash-durability.test.ts +121 -0
  724. package/src/orchestrator-source-attribution.test.ts +9 -9
  725. package/src/orchestrator.ts +166 -150
  726. package/src/prioritized-embed.ts +123 -0
  727. package/src/proactive-contention.test.ts +80 -0
  728. package/src/proactive-contention.ts +39 -0
  729. package/src/procedural/procedure-miner.test.ts +19 -14
  730. package/src/procedural/procedure-miner.ts +44 -13
  731. package/src/qmd-client.test.ts +111 -1
  732. package/src/qmd-status.ts +186 -0
  733. package/src/qmd.test.ts +22 -0
  734. package/src/qmd.ts +60 -48
  735. package/src/recall-budget-config.test.ts +30 -0
  736. package/src/recall-cold-deadline.test.ts +149 -0
  737. package/src/recall-concurrency-config.ts +28 -0
  738. package/src/recall-memory-map.ts +74 -0
  739. package/src/recall-rerank-coordinator.test.ts +508 -0
  740. package/src/recall-state.test.ts +825 -1
  741. package/src/recall-state.ts +406 -7
  742. package/src/recall-timings-access.test.ts +41 -0
  743. package/src/recall-timings.ts +16 -0
  744. package/src/relay/mission-access.test.ts +5 -5
  745. package/src/rerank.ts +22 -0
  746. package/src/retrieval-agents.test.ts +79 -0
  747. package/src/retrieval-agents.ts +71 -19
  748. package/src/salvage-envelope.ts +28 -0
  749. package/src/scopes/scope-plan.test.ts +42 -0
  750. package/src/scopes/scope-plan.ts +45 -0
  751. package/src/search/port.ts +24 -0
  752. package/src/secure-store/index.ts +1 -0
  753. package/src/secure-store/secure-fs.ts +48 -0
  754. package/src/secure-store/secure-store.test.ts +40 -0
  755. package/src/semantic-rule-promotion.ts +13 -4
  756. package/src/storage/content-hash-index.ts +655 -0
  757. package/src/storage/entity-timeline.ts +473 -0
  758. package/src/storage/memory-lifecycle-ledger-access.ts +603 -0
  759. package/src/storage/secure-line-reader.test.ts +197 -0
  760. package/src/storage/secure-line-reader.ts +181 -3
  761. package/src/storage-append-header-sniff.test.ts +195 -0
  762. package/src/storage-behavior-signals-cache.test.ts +237 -0
  763. package/src/storage-contract/cache-coherence.test.ts +96 -1
  764. package/src/storage-contract/content-hash.test.ts +47 -2
  765. package/src/storage-fact-hash-index-defer.test.ts +1200 -0
  766. package/src/storage-memory-lifecycle-ledger.test.ts +1146 -3
  767. package/src/storage.ts +942 -903
  768. package/src/structured-attributes.ts +52 -0
  769. package/src/temporal-index-batch.ts +112 -0
  770. package/src/temporal-index.test.ts +193 -0
  771. package/src/temporal-index.ts +49 -53
  772. package/src/testing/lifecycle-matrix.test.ts +212 -0
  773. package/src/testing/lifecycle-matrix.ts +271 -0
  774. package/src/testing/orchestrator-lite.ts +236 -0
  775. package/src/testing/subjects/dreams-ledger.test.ts +67 -0
  776. package/src/testing/subjects/extraction-lifecycle.test.ts +442 -0
  777. package/src/testing/subjects/lifecycle-ledger.test.ts +93 -0
  778. package/src/testing/subjects/recall-budget.test.ts +461 -0
  779. package/src/testing/subjects/serialized-write-chain.test.ts +224 -0
  780. package/src/trust-score-stage.test.ts +154 -0
  781. package/src/trust-score-stage.ts +216 -53
  782. package/src/types-continuity.ts +57 -0
  783. package/src/types.ts +66 -77
  784. package/src/utils/path-containment.test.ts +75 -0
  785. package/src/utils/path-containment.ts +76 -0
  786. package/src/utils/serialize-mutations.test.ts +122 -0
  787. package/src/utils/serialize-mutations.ts +68 -3
  788. package/src/wearables/memory-gen.test.ts +31 -9
  789. package/src/wearables/memory-gen.ts +95 -55
  790. package/src/wearables/pipeline.test.ts +10 -7
  791. package/src/wearables/service.test.ts +6 -8
  792. package/src/wearables/service.ts +2 -2
  793. package/src/write-envelope.extension.test.ts +111 -0
  794. package/src/write-envelope.test.ts +683 -0
  795. package/src/write-envelope.ts +902 -0
  796. package/src/write-quarantine.test.ts +193 -0
  797. package/src/write-quarantine.ts +241 -0
  798. package/src/write-rate-limiter.test.ts +105 -0
  799. package/src/write-rate-limiter.ts +135 -0
  800. package/src/write-sealed-parity.test.ts +204 -0
  801. package/dist/chunk-2VN4JAX7.js.map +0 -1
  802. package/dist/chunk-37CTGERM.js.map +0 -1
  803. package/dist/chunk-7ICYQUOL.js.map +0 -1
  804. package/dist/chunk-AD6AMF2N.js.map +0 -1
  805. package/dist/chunk-AHLPZ2SF.js.map +0 -1
  806. package/dist/chunk-ASKEM4AR.js.map +0 -1
  807. package/dist/chunk-B3F4CWQR.js.map +0 -1
  808. package/dist/chunk-BCDKBDSY.js.map +0 -1
  809. package/dist/chunk-BFPETA3S.js.map +0 -1
  810. package/dist/chunk-BFVEEB7W.js.map +0 -1
  811. package/dist/chunk-E5BK6CGV.js +0 -335
  812. package/dist/chunk-E5BK6CGV.js.map +0 -1
  813. package/dist/chunk-EEARRVZ2.js.map +0 -1
  814. package/dist/chunk-F7AU34FC.js.map +0 -1
  815. package/dist/chunk-FBNWOMCE.js.map +0 -1
  816. package/dist/chunk-FTYDWKO6.js.map +0 -1
  817. package/dist/chunk-GMSDQUCR.js.map +0 -1
  818. package/dist/chunk-GWTFLF2P.js.map +0 -1
  819. package/dist/chunk-IFJ23BHU.js.map +0 -1
  820. package/dist/chunk-IKQTFQMI.js.map +0 -1
  821. package/dist/chunk-J2HSAU72.js.map +0 -1
  822. package/dist/chunk-JMBVCAR4.js.map +0 -1
  823. package/dist/chunk-KQDNAXOM.js.map +0 -1
  824. package/dist/chunk-KSBEEMQF.js.map +0 -1
  825. package/dist/chunk-KSNVDPDF.js.map +0 -1
  826. package/dist/chunk-LC7OODWZ.js.map +0 -1
  827. package/dist/chunk-LTJAMRGI.js.map +0 -1
  828. package/dist/chunk-ND5M64JJ.js.map +0 -1
  829. package/dist/chunk-NUWYOKS6.js.map +0 -1
  830. package/dist/chunk-NWTGD4AN.js.map +0 -1
  831. package/dist/chunk-OBMR4VIX.js.map +0 -1
  832. package/dist/chunk-ODPLEWB6.js.map +0 -1
  833. package/dist/chunk-PHK3HARR.js +0 -32
  834. package/dist/chunk-PHK3HARR.js.map +0 -1
  835. package/dist/chunk-RANHFI3P.js +0 -8
  836. package/dist/chunk-RANHFI3P.js.map +0 -1
  837. package/dist/chunk-RBQLJSJ7.js.map +0 -1
  838. package/dist/chunk-RULE4VG5.js.map +0 -1
  839. package/dist/chunk-SVOZFLIQ.js +0 -16
  840. package/dist/chunk-SVOZFLIQ.js.map +0 -1
  841. package/dist/chunk-TXLGHDHS.js.map +0 -1
  842. package/dist/chunk-UN3CH3CO.js +0 -118
  843. package/dist/chunk-UN3CH3CO.js.map +0 -1
  844. package/dist/chunk-VSMRDBFT.js +0 -17
  845. package/dist/chunk-VSMRDBFT.js.map +0 -1
  846. package/dist/chunk-WU46YPY6.js.map +0 -1
  847. package/dist/chunk-X47LWMKA.js.map +0 -1
  848. package/dist/chunk-X64YLC24.js.map +0 -1
  849. package/dist/chunk-XVLEGMJI.js.map +0 -1
  850. package/dist/chunk-YF6FMLBT.js.map +0 -1
  851. package/dist/resolution-VH4NGENZ.js +0 -12
  852. /package/dist/{capsule-crypto-CZJSLEFG.js.map → access-citation.js.map} +0 -0
  853. /package/dist/{contradiction-scan-J57T5QV7.js.map → access-memory-search-fanout.js.map} +0 -0
  854. /package/dist/{dreams-ledger-6UODQOX6.js.map → access-recall-concurrency.js.map} +0 -0
  855. /package/dist/{graph-edge-decay-FO7AM4UR.js.map → access-recall-response.js.map} +0 -0
  856. /package/dist/{resolution-VH4NGENZ.js.map → bounded-jsonl-state.js.map} +0 -0
  857. /package/dist/{capsule-merge-Z2HUO6IK.js.map → capsule-merge-5KKJQBWQ.js.map} +0 -0
  858. /package/dist/{chunk-A3GOMRJG.js.map → chunk-23L3IXFD.js.map} +0 -0
  859. /package/dist/{chunk-MRHFJV44.js.map → chunk-2DQ2XREU.js.map} +0 -0
  860. /package/dist/{chunk-L2B3EE7B.js.map → chunk-2QMKMVHH.js.map} +0 -0
  861. /package/dist/{chunk-6CALL5VN.js.map → chunk-2UFO7X4Q.js.map} +0 -0
  862. /package/dist/{chunk-2MR3MFQB.js.map → chunk-2VEOKUPP.js.map} +0 -0
  863. /package/dist/{chunk-RHOZ5LLO.js.map → chunk-347WD2LE.js.map} +0 -0
  864. /package/dist/{chunk-5S7Z5SHA.js.map → chunk-34RC5RT7.js.map} +0 -0
  865. /package/dist/{chunk-KGWXHWAH.js.map → chunk-3QAH2S33.js.map} +0 -0
  866. /package/dist/{chunk-ZIDSD6VC.js.map → chunk-3Y224NYC.js.map} +0 -0
  867. /package/dist/{chunk-VFSP73LP.js.map → chunk-45GF7Y3V.js.map} +0 -0
  868. /package/dist/{chunk-OEHCMALU.js.map → chunk-5I4M26Q7.js.map} +0 -0
  869. /package/dist/{chunk-2E6G7FCE.js.map → chunk-5Q7EVV4X.js.map} +0 -0
  870. /package/dist/{chunk-VZ5OJE4X.js.map → chunk-5VQJBH2G.js.map} +0 -0
  871. /package/dist/{chunk-PUBTHW5O.js.map → chunk-6DRPPQEJ.js.map} +0 -0
  872. /package/dist/{chunk-4LEF6XWJ.js.map → chunk-6O22TZSB.js.map} +0 -0
  873. /package/dist/{chunk-ZQ7UBUZ6.js.map → chunk-6QYST5XN.js.map} +0 -0
  874. /package/dist/{chunk-W4PGTAS2.js.map → chunk-6WAFYNVT.js.map} +0 -0
  875. /package/dist/{chunk-R5VAVVHP.js.map → chunk-72A4L5JJ.js.map} +0 -0
  876. /package/dist/{chunk-3FAMU5TX.js.map → chunk-A6USBZTO.js.map} +0 -0
  877. /package/dist/{chunk-TXVD7PLT.js.map → chunk-A72SWTWW.js.map} +0 -0
  878. /package/dist/{chunk-FC77VUX5.js.map → chunk-A7Q43EUZ.js.map} +0 -0
  879. /package/dist/{chunk-UJBESW6X.js.map → chunk-AE7WMV4V.js.map} +0 -0
  880. /package/dist/{chunk-OKUEZOGW.js.map → chunk-AITCS2RC.js.map} +0 -0
  881. /package/dist/{chunk-OC35KQIN.js.map → chunk-AJ7QCSIS.js.map} +0 -0
  882. /package/dist/{chunk-FNMFJWBY.js.map → chunk-ANEUPF6O.js.map} +0 -0
  883. /package/dist/{chunk-2A3OXAP2.js.map → chunk-B7RWBZXW.js.map} +0 -0
  884. /package/dist/{chunk-N3JDIRBW.js.map → chunk-BLAKS3CP.js.map} +0 -0
  885. /package/dist/{chunk-M7VGG3ID.js.map → chunk-BV5WMSIJ.js.map} +0 -0
  886. /package/dist/{chunk-2BFLDH5F.js.map → chunk-BXLOS5AJ.js.map} +0 -0
  887. /package/dist/{chunk-UXKMMNJD.js.map → chunk-C23BYTJV.js.map} +0 -0
  888. /package/dist/{chunk-JZHHREBL.js.map → chunk-C3AKM55W.js.map} +0 -0
  889. /package/dist/{chunk-RP7YXA67.js.map → chunk-C5JF6EZ7.js.map} +0 -0
  890. /package/dist/{chunk-DDGV7NAX.js.map → chunk-CQMEM5CC.js.map} +0 -0
  891. /package/dist/{chunk-A7B4RMQG.js.map → chunk-CXZQOVIE.js.map} +0 -0
  892. /package/dist/{chunk-7N2RUBAP.js.map → chunk-DDA47TES.js.map} +0 -0
  893. /package/dist/{chunk-64SE4X5G.js.map → chunk-DEBHXHJR.js.map} +0 -0
  894. /package/dist/{chunk-EHK6KZHK.js.map → chunk-DNHVPZOD.js.map} +0 -0
  895. /package/dist/{chunk-437S3G37.js.map → chunk-DQEMWVMT.js.map} +0 -0
  896. /package/dist/{chunk-LZZNTPLR.js.map → chunk-DX3XRGLH.js.map} +0 -0
  897. /package/dist/{chunk-7MW3CVLD.js.map → chunk-ES36HTSC.js.map} +0 -0
  898. /package/dist/{chunk-TN7THW5U.js.map → chunk-ET356KSB.js.map} +0 -0
  899. /package/dist/{chunk-YNDLCWXS.js.map → chunk-EZ25VE3G.js.map} +0 -0
  900. /package/dist/{chunk-7LFXDGLH.js.map → chunk-F7GAIWFA.js.map} +0 -0
  901. /package/dist/{chunk-IKSELOIV.js.map → chunk-FFPJINJE.js.map} +0 -0
  902. /package/dist/{chunk-V53GJUSL.js.map → chunk-FUTF72MJ.js.map} +0 -0
  903. /package/dist/{chunk-5UNWK7KU.js.map → chunk-GFPZS3F5.js.map} +0 -0
  904. /package/dist/{chunk-G6NKALRN.js.map → chunk-H4WG3UQZ.js.map} +0 -0
  905. /package/dist/{chunk-HLTAPHZZ.js.map → chunk-HNZKVLAN.js.map} +0 -0
  906. /package/dist/{chunk-5EZXHU36.js.map → chunk-HYQJQGD3.js.map} +0 -0
  907. /package/dist/{chunk-TRWPCR6P.js.map → chunk-JECBQBEX.js.map} +0 -0
  908. /package/dist/{chunk-HG32URJJ.js.map → chunk-JYIFGGEM.js.map} +0 -0
  909. /package/dist/{chunk-VA4WSW54.js.map → chunk-JYIJNNN3.js.map} +0 -0
  910. /package/dist/{chunk-L5HJQC36.js.map → chunk-K2TDK7GG.js.map} +0 -0
  911. /package/dist/{chunk-MKDRQAA3.js.map → chunk-KAVBJSBQ.js.map} +0 -0
  912. /package/dist/{chunk-4OKLXWDZ.js.map → chunk-KNB7IBBU.js.map} +0 -0
  913. /package/dist/{chunk-QLULYKWZ.js.map → chunk-KSXJOC4F.js.map} +0 -0
  914. /package/dist/{chunk-JI5AVXYO.js.map → chunk-LEPOP46W.js.map} +0 -0
  915. /package/dist/{chunk-O7BBFJLP.js.map → chunk-LTAVSOZW.js.map} +0 -0
  916. /package/dist/{chunk-2IZAGAJR.js.map → chunk-LULR4IUW.js.map} +0 -0
  917. /package/dist/{chunk-WMWVO45V.js.map → chunk-MC6XO7T4.js.map} +0 -0
  918. /package/dist/{chunk-D6RIFG4O.js.map → chunk-MNB5RMAY.js.map} +0 -0
  919. /package/dist/{chunk-67ZCJLJY.js.map → chunk-MYFQ3ED4.js.map} +0 -0
  920. /package/dist/{chunk-V3UE5I5F.js.map → chunk-MYVPLJOO.js.map} +0 -0
  921. /package/dist/{chunk-MTWKDOVO.js.map → chunk-NLE6TSLG.js.map} +0 -0
  922. /package/dist/{chunk-DBRYEIGY.js.map → chunk-OJP3N7UK.js.map} +0 -0
  923. /package/dist/{chunk-SMX5267P.js.map → chunk-OZKOPQCM.js.map} +0 -0
  924. /package/dist/{chunk-JCK7V6SN.js.map → chunk-P65YJEEL.js.map} +0 -0
  925. /package/dist/{chunk-MTR7BZQN.js.map → chunk-PBGWYM3H.js.map} +0 -0
  926. /package/dist/{chunk-AXTXN4T6.js.map → chunk-PWFCHOB3.js.map} +0 -0
  927. /package/dist/{chunk-FDPZVY6D.js.map → chunk-QFN4U7AG.js.map} +0 -0
  928. /package/dist/{chunk-K2ZLHESQ.js.map → chunk-QIEUU4UK.js.map} +0 -0
  929. /package/dist/{chunk-3D6AFGQR.js.map → chunk-QVT3E4CE.js.map} +0 -0
  930. /package/dist/{chunk-SFQ6QNL7.js.map → chunk-R6YJI3HE.js.map} +0 -0
  931. /package/dist/{chunk-5CJVLG3H.js.map → chunk-RFDD3B7W.js.map} +0 -0
  932. /package/dist/{chunk-JBPKEARU.js.map → chunk-RKNJBZ55.js.map} +0 -0
  933. /package/dist/{chunk-UTRJFDP2.js.map → chunk-S2BBISHU.js.map} +0 -0
  934. /package/dist/{chunk-IALLX7EE.js.map → chunk-S2FSBU4H.js.map} +0 -0
  935. /package/dist/{chunk-7K5Q6COX.js.map → chunk-TVVEYCNW.js.map} +0 -0
  936. /package/dist/{chunk-PK5XBDA6.js.map → chunk-U3ZAVRP3.js.map} +0 -0
  937. /package/dist/{chunk-4KJLYTLS.js.map → chunk-V57NLO5P.js.map} +0 -0
  938. /package/dist/{chunk-FLVL4L3L.js.map → chunk-VDX2J7OX.js.map} +0 -0
  939. /package/dist/{chunk-7XGSIUP5.js.map → chunk-W4FBGYGK.js.map} +0 -0
  940. /package/dist/{chunk-6SXVCD7W.js.map → chunk-W7IGLX4G.js.map} +0 -0
  941. /package/dist/{chunk-KAWTOYAW.js.map → chunk-WLZYGLJ4.js.map} +0 -0
  942. /package/dist/{chunk-W5NKDU24.js.map → chunk-WON4APQY.js.map} +0 -0
  943. /package/dist/{chunk-NKCPUHCI.js.map → chunk-WZFAPHIK.js.map} +0 -0
  944. /package/dist/{chunk-KQPJLK3X.js.map → chunk-XL24QQ63.js.map} +0 -0
  945. /package/dist/{chunk-4B4MUS5D.js.map → chunk-YROFNEG5.js.map} +0 -0
  946. /package/dist/{chunk-VRAD2FGO.js.map → chunk-Z54EM5YZ.js.map} +0 -0
  947. /package/dist/{first-start-migration-TI67YMLG.js.map → first-start-migration-CSRHCJIQ.js.map} +0 -0
  948. /package/dist/{forget-CQCLB5LB.js.map → forget-HRPLVB3W.js.map} +0 -0
  949. /package/dist/{purge-NDWV6WYD.js.map → purge-IRF47ZTX.js.map} +0 -0
  950. /package/dist/{tier-stats-KV7IWCJR.js.map → tier-stats-QEJSPFV2.js.map} +0 -0
@@ -19,6 +19,12 @@
19
19
  * tests continue to work.
20
20
  */
21
21
 
22
+ import { isMemoryCategory } from "../write-envelope.js";
23
+ import {
24
+ composeSalvagedExtractionEnvelope,
25
+ probeSalvageSurvivingFields,
26
+ withReservedMarkerTag,
27
+ } from "./extraction-envelope.js";
22
28
  import path from "node:path";
23
29
  import {
24
30
  StorageManager,
@@ -38,6 +44,7 @@ import {
38
44
  resolveNamespaceCapabilities,
39
45
  resolveRecallEnhancementCapabilities,
40
46
  resolveConversationContextCapabilities,
47
+ resolveRecallAuxiliaryCapabilities,
41
48
  type GraphConstructionCapabilitySet,
42
49
  type MemoryLifecycleCapabilitySet,
43
50
  } from "../capabilities.js";
@@ -101,8 +108,14 @@ import type {
101
108
  MemoryLink,
102
109
  PluginConfig,
103
110
  ProvenanceSource,
111
+ MemoryCategory,
104
112
  } from "../types.js";
105
- import { confidenceTier } from "../types.js";
113
+ import {
114
+ flushDeferredFactHashOnFailure,
115
+ profileAutoPromotionAllows,
116
+ readActiveMemoriesBothTiers,
117
+ shouldPromoteToShared,
118
+ } from "./extraction-persist-promotion.js";
106
119
  import type { ResolvedScopeProfilePlan } from "../namespaces/scope-profiles.js";
107
120
  import {
108
121
  buildMemoryPathById,
@@ -208,7 +221,6 @@ export class ExtractionPersistCoordinator {
208
221
  constructor(
209
222
  private readonly deps: ExtractionPersistDeps,
210
223
  ) {}
211
-
212
224
  private get config(): PluginConfig {
213
225
  return this.deps.config;
214
226
  }
@@ -224,7 +236,7 @@ export class ExtractionPersistCoordinator {
224
236
  sourceText?: string,
225
237
  graphCaps: GraphConstructionCapabilitySet = resolveGraphConstructionCapabilities(this.deps.config),
226
238
  lifecycleCaps: MemoryLifecycleCapabilitySet = resolveMemoryLifecycleCapabilities(this.deps.config),
227
- ): Promise<string[]> {
239
+ ): Promise<{ persistedIds: string[]; memoryPathById: Map<string, string> }> {
228
240
  // Inline source attribution (issue #369). When enabled, every extracted
229
241
  // fact is rewritten to carry a compact provenance tag inside its body so
230
242
  // the citation survives hostile memory text, copy/paste, and LLM quoting.
@@ -232,6 +244,15 @@ export class ExtractionPersistCoordinator {
232
244
  // see zero behavioral change.
233
245
  const citationEnabled = resolvePipelineProcessingCapabilities(this.deps.config).inlineSourceAttribution === true;
234
246
  const citationTemplate = this.deps.config.inlineSourceAttributionFormat;
247
+ // #1909: the main-path fact writes defer their per-fact fact-hash-index flush
248
+ // to the orchestrator's end-of-persist reconciling batch save ONLY when fact
249
+ // deduplication is enabled (with it off, contentHashIndexForStorage() returns
250
+ // null and the batch save is a no-op, so the write must save immediately).
251
+ // Round 11: there is NO fact-hashes.ready marker anymore — the fact-hash
252
+ // index is ALWAYS rebuilt from the corpus on restart (see
253
+ // ensureFactHashIndexAuthoritative), so a deferred write, crash, or
254
+ // multi-process interleave is safe by construction with no marker to guard.
255
+ const factDedupEnabled = resolveRecallAuxiliaryCapabilities(this.deps.config).factDeduplication;
235
256
 
236
257
  // Canonicalize stored content for dedup comparison: strip citations
237
258
  // (using the same template), sanitize, then normalize whitespace.
@@ -268,14 +289,12 @@ export class ExtractionPersistCoordinator {
268
289
  return attachCitation(content, citationContext, citationTemplate);
269
290
  };
270
291
  const persistedIds: string[] = [];
292
+ const memoryPathById = new Map<string, string>();
271
293
  const supersessionOrderingAt = (validAt?: string): string =>
272
294
  validAt && validAt.length > 0 ? validAt : new Date().toISOString();
273
295
  // #1635: pending_review persisted ids, excluded from the thread episode set below.
274
296
  const pendingReviewPersistedIds: string[] = [];
275
- const persistedIdsByStorage = new Map<
276
- string,
277
- { storage: StorageManager; ids: string[] }
278
- >();
297
+ const persistedIdsByStorage = new Map<string, { storage: StorageManager; ids: string[] }>();
279
298
  const trackPersistedId = (
280
299
  targetStorage: StorageManager,
281
300
  id: string,
@@ -283,6 +302,7 @@ export class ExtractionPersistCoordinator {
283
302
  includeReturnedIds?: boolean;
284
303
  /** #1635: keep this id out of the persisted thread episode set. */
285
304
  pendingReview?: boolean;
305
+ category?: MemoryCategory;
286
306
  } = {},
287
307
  ): void => {
288
308
  if (options.includeReturnedIds !== false) {
@@ -295,14 +315,16 @@ export class ExtractionPersistCoordinator {
295
315
  const existing = persistedIdsByStorage.get(key);
296
316
  if (existing) {
297
317
  existing.ids.push(id);
298
- return;
318
+ } else {
319
+ persistedIdsByStorage.set(key, { storage: targetStorage, ids: [id] });
320
+ }
321
+ if (options.category && !memoryPathById.has(id)) {
322
+ const relPath = resolvePersistedMemoryRelativePath({ memoryId: id, pathById: memoryPathById, category: options.category });
323
+ memoryPathById.set(id, relPath);
299
324
  }
300
- persistedIdsByStorage.set(key, { storage: targetStorage, ids: [id] });
301
325
  };
302
326
  let dedupedCount = 0;
303
327
  // Counter for facts skipped by the importance write-gate (issue #372).
304
- // Emitted via the `importance_gated` metric below and rolled into the
305
- // final `persisted:` log line so operators can tune the threshold.
306
328
  let importanceGatedCount = 0;
307
329
  // UUI2: short-circuit semantic dedup after first backend-unavailable signal
308
330
  // within this batch. Once any fact in the batch gets reason="backend_unavailable"
@@ -349,12 +371,6 @@ export class ExtractionPersistCoordinator {
349
371
  events: [...events],
350
372
  });
351
373
  };
352
- const confidenceTierOrder = [
353
- "explicit",
354
- "implied",
355
- "inferred",
356
- "speculative",
357
- ] as const;
358
374
  const sharedProfileLayer = scopeProfileWritePlan?.layers.find(
359
375
  (layer) =>
360
376
  layer.id === "serverShared" &&
@@ -378,59 +394,6 @@ export class ExtractionPersistCoordinator {
378
394
  // (pre-judge + write-loop) so no new scattered config.*Enabled read is
379
395
  // introduced (ratchet scatteredConfigFlagReads; see #1523).
380
396
  const namespacesEnabled = resolveNamespaceCapabilities(this.deps.config).namespaces;
381
- const profileAutoPromotionAllows = (
382
- category: string,
383
- confidence: number,
384
- ): boolean => {
385
- if (!scopeProfileWritePlan) return false;
386
- const actualTier = confidenceTier(confidence);
387
- const actualRank = confidenceTierOrder.indexOf(actualTier);
388
- if (actualRank === -1) return false;
389
- const autoPromote = scopeProfileWritePlan.profile.autoPromote;
390
- if (!autoPromote.enabled) return false;
391
- if (!autoPromote.categories.includes(category as any)) return false;
392
- const minimumRank = confidenceTierOrder.indexOf(autoPromote.minConfidenceTier);
393
- return minimumRank !== -1 && actualRank <= minimumRank;
394
- };
395
- const sharedAutoPromotionAllows = (
396
- category: string,
397
- confidence: number,
398
- ): boolean => {
399
- if (!scopeProfileWritePlan) {
400
- const actualTier = confidenceTier(confidence);
401
- const actualRank = confidenceTierOrder.indexOf(actualTier);
402
- if (actualRank === -1) return false;
403
- if (!resolveRecallEnhancementCapabilities(this.deps.config).autoPromoteToShared) return false;
404
- if (!this.deps.config.autoPromoteToSharedCategories.includes(category as any))
405
- return false;
406
- const minimumRank = confidenceTierOrder.indexOf(
407
- this.deps.config.autoPromoteMinConfidenceTier,
408
- );
409
- return minimumRank !== -1 && actualRank <= minimumRank;
410
- }
411
- return (
412
- scopeProfileWritePlan.profile.autoPromote.targets.includes("serverShared") &&
413
- profileAutoPromotionAllows(category, confidence)
414
- );
415
- };
416
- const shouldPromoteToShared = (
417
- targetStorage: StorageManager,
418
- category: string,
419
- confidence: number,
420
- ): boolean => {
421
- if (
422
- !resolveNamespaceCapabilities(this.deps.config).namespaces ||
423
- !profileAllowsSharedWrites ||
424
- !sharedAutoPromotionAllows(category, confidence)
425
- )
426
- return false;
427
- if (
428
- this.deps.storageDirNamespace(targetStorage.dir) ===
429
- this.deps.config.sharedNamespace
430
- )
431
- return false;
432
- return true;
433
- };
434
397
  const promoteMemoryToProfileTargets = async (options: {
435
398
  sourceStorage: StorageManager;
436
399
  category: string;
@@ -457,7 +420,7 @@ export class ExtractionPersistCoordinator {
457
420
  }): Promise<void> => {
458
421
  if (
459
422
  !scopeProfileWritePlan ||
460
- !profileAutoPromotionAllows(options.category, options.confidence)
423
+ !profileAutoPromotionAllows(scopeProfileWritePlan, options.category, options.confidence)
461
424
  )
462
425
  return;
463
426
  const autoTargets = new Set(scopeProfileWritePlan.profile.autoPromote.targets);
@@ -475,17 +438,35 @@ export class ExtractionPersistCoordinator {
475
438
  : options.content;
476
439
  const citedContent = applyInlineCitation(rawContent);
477
440
  const sanitizedBase = sanitizeMemoryContent(rawContent);
478
- const dedupContent =
479
- options.category === "fact" &&
480
- options.structuredAttributes &&
481
- Object.keys(options.structuredAttributes).length > 0
482
- ? `${sanitizedBase.text}\n[Attributes: ${normalizeAttributePairs(options.structuredAttributes)}]`
483
- : sanitizedBase.text;
484
441
  for (const target of targets) {
485
442
  if (!target.namespace) continue;
486
443
  try {
487
444
  const targetStorage = await this.deps.getStorageRouter().storageFor(target.namespace);
488
445
  if (targetStorage.dir === options.sourceStorage.dir) continue;
446
+ // Compose BEFORE the dedup gate (#2014 round 2): salvage mode may
447
+ // drop or clamp attributes, and the dedup hash, contentHashSource,
448
+ // and supersession keys below must all describe the SURVIVING
449
+ // fields that writeSealedMemory actually persists.
450
+ const targetPromotionEnvelope = composeSalvagedExtractionEnvelope(
451
+ {
452
+ content: citedContent,
453
+ category: options.category as MemoryCategory,
454
+ confidence: options.confidence,
455
+ tags: withReservedMarkerTag(options.tags, `${target.target}-promotion`),
456
+ entityRef: options.entityRef,
457
+ structuredAttributes: options.structuredAttributes,
458
+ validAt: options.validAt,
459
+ ...(sourceContext?.sourceConnector ? { sourceConnector: sourceContext.sourceConnector } : {}),
460
+ },
461
+ { source: `${options.source}-${target.target}-promotion` },
462
+ );
463
+ const targetSurvivingAttrs = targetPromotionEnvelope.rawStructuredAttributes;
464
+ const dedupContent =
465
+ options.category === "fact" &&
466
+ targetSurvivingAttrs &&
467
+ Object.keys(targetSurvivingAttrs).length > 0
468
+ ? `${sanitizedBase.text}\n[Attributes: ${normalizeAttributePairs({ ...targetSurvivingAttrs })}]`
469
+ : sanitizedBase.text;
489
470
  if (
490
471
  options.category === "fact" &&
491
472
  (await targetStorage.hasFactContentHash(dedupContent))
@@ -495,7 +476,7 @@ export class ExtractionPersistCoordinator {
495
476
  // Different connectors with same content should NOT be deduped.
496
477
  let skipPromotion = true;
497
478
  try {
498
- const allMems = await targetStorage.readAllMemories();
479
+ const allMems = await readActiveMemoriesBothTiers(targetStorage);
499
480
  const nc = sourceContext?.sourceConnector?.trim() || undefined;
500
481
  skipPromotion = allMems.some((m) => {
501
482
  if (m.frontmatter.category !== options.category) return false;
@@ -526,40 +507,34 @@ export class ExtractionPersistCoordinator {
526
507
  ...(options.observedAt ? { observedAt: options.observedAt } : {}),
527
508
  ...(options.eventTimeSource ? { eventTimeSource: options.eventTimeSource } : {}),
528
509
  },
529
- options.entityRef,
510
+ // #2014 round 3: the envelope's SURVIVING entityRef — the raw
511
+ // option can differ (untrimmed/dropped) from what sealed
512
+ // writes persisted, mistargeting the backfill row.
513
+ targetPromotionEnvelope.entityRef,
530
514
  sourceContext?.sourceConnector,
531
515
  );
532
516
  }
533
517
  continue;
534
518
  }
535
519
  }
536
- const targetPromotion = await targetStorage.writeMemory(
537
- options.category as any,
538
- citedContent,
539
- {
540
- confidence: options.confidence,
541
- tags: [...options.tags, `${target.target}-promotion`],
542
- entityRef: options.entityRef,
543
- structuredAttributes: options.structuredAttributes,
544
- source: `${options.source}-${target.target}-promotion`,
545
- importance: options.importance,
546
- lineage: [options.sourceMemoryId],
547
- sourceMemoryId: options.sourceMemoryId,
548
- intentGoal: options.intentGoal,
549
- intentActionType: options.intentActionType,
550
- intentEntityTypes: options.intentEntityTypes,
551
- memoryKind: options.memoryKind,
552
- validAt: options.validAt,
553
- // #1578 — forward bi-temporal bounds + ingestion provenance.
554
- ...(options.invalidAt ? { invalidAt: options.invalidAt } : {}),
555
- ...(options.observedAt ? { observedAt: options.observedAt } : {}),
556
- ...(options.eventTimeSource ? { eventTimeSource: options.eventTimeSource } : {}),
557
- contentHashSource: options.category === "fact" ? dedupContent : rawContent,
558
- ...(options.sources && options.sources.length > 0 ? { sources: options.sources } : {}),
559
- ...(options.provenance ? { provenance: options.provenance } : {}),
560
- ...(sourceContext?.sourceConnector ? { sourceConnector: sourceContext.sourceConnector } : {}),
561
- },
562
- );
520
+ // Sealed-envelope write (issue #1989 PR2): cross-cutting fields ride
521
+ // the composed envelope (built above, before the dedup gate).
522
+ const targetPromotion = await targetStorage.writeSealedMemory(targetPromotionEnvelope, {
523
+ importance: options.importance,
524
+ lineage: [options.sourceMemoryId],
525
+ sourceMemoryId: options.sourceMemoryId,
526
+ intentGoal: options.intentGoal,
527
+ intentActionType: options.intentActionType,
528
+ intentEntityTypes: options.intentEntityTypes,
529
+ memoryKind: options.memoryKind,
530
+ // #1578 — forward bi-temporal bounds + ingestion provenance.
531
+ ...(options.invalidAt ? { invalidAt: options.invalidAt } : {}),
532
+ ...(options.observedAt ? { observedAt: options.observedAt } : {}),
533
+ ...(options.eventTimeSource ? { eventTimeSource: options.eventTimeSource } : {}),
534
+ contentHashSource: options.category === "fact" ? dedupContent : rawContent,
535
+ ...(options.sources && options.sources.length > 0 ? { sources: options.sources } : {}),
536
+ ...(options.provenance ? { provenance: options.provenance } : {}),
537
+ });
563
538
  const promotedId = targetPromotion.id;
564
539
  // #1645: if the TARGET namespace's own tombstone blocked this promotion,
565
540
  // the row lands pending_review — do NOT supersede active target memories.
@@ -567,16 +542,16 @@ export class ExtractionPersistCoordinator {
567
542
  !targetPromotion.tombstoneBlocked &&
568
543
  lifecycleCaps.temporalSupersession &&
569
544
  options.category === "fact" &&
570
- options.entityRef &&
571
- options.structuredAttributes &&
572
- Object.keys(options.structuredAttributes).length > 0
545
+ targetPromotionEnvelope.entityRef &&
546
+ targetSurvivingAttrs &&
547
+ Object.keys(targetSurvivingAttrs).length > 0
573
548
  ) {
574
549
  try {
575
550
  await applyTemporalSupersession({
576
551
  storage: targetStorage,
577
552
  newMemoryId: promotedId,
578
- entityRef: options.entityRef,
579
- structuredAttributes: options.structuredAttributes,
553
+ entityRef: targetPromotionEnvelope.entityRef,
554
+ structuredAttributes: { ...targetSurvivingAttrs },
580
555
  createdAt: supersessionOrderingAt(options.validAt),
581
556
  enabled: !(options.eventTimeSource === "extracted" && !options.validAt),
582
557
  });
@@ -589,7 +564,7 @@ export class ExtractionPersistCoordinator {
589
564
  // #1645 TV6: a tombstone-blocked promotion is pending_review (no
590
565
  // active copy) — skip catalog/index/behavior like postWriteGuard.
591
566
  if (!targetPromotion.tombstoneBlocked) {
592
- trackPersistedId(targetStorage, promotedId, { includeReturnedIds: false });
567
+ trackPersistedId(targetStorage, promotedId, { includeReturnedIds: false, category: options.category as MemoryCategory });
593
568
  await this.deps.indexPersistedMemory(targetStorage, promotedId);
594
569
  trackBehaviorSignals(
595
570
  targetStorage,
@@ -639,6 +614,10 @@ export class ExtractionPersistCoordinator {
639
614
  await promoteMemoryToProfileTargets(options);
640
615
  if (
641
616
  !shouldPromoteToShared(
617
+ this.deps.config,
618
+ scopeProfileWritePlan,
619
+ profileAllowsSharedWrites,
620
+ (dir) => this.deps.storageDirNamespace(dir),
642
621
  options.sourceStorage,
643
622
  options.category,
644
623
  options.confidence,
@@ -693,11 +672,29 @@ export class ExtractionPersistCoordinator {
693
672
  : options.content;
694
673
  const citedContent = applyInlineCitation(rawContent);
695
674
  const sanitizedBase = sanitizeMemoryContent(rawContent);
675
+ // Compose BEFORE the dedup gate (#2014 round 2): salvage mode may drop
676
+ // or clamp attributes, and the dedup hash, contentHashSource, and
677
+ // supersession keys below must all describe the SURVIVING fields that
678
+ // writeSealedMemory actually persists — never the raw extractor map.
679
+ const sharedPromotionEnvelope = composeSalvagedExtractionEnvelope(
680
+ {
681
+ content: citedContent,
682
+ category: options.category as MemoryCategory,
683
+ confidence: options.confidence,
684
+ tags: withReservedMarkerTag(options.tags, "shared-promotion"),
685
+ entityRef: options.entityRef,
686
+ structuredAttributes: options.structuredAttributes,
687
+ validAt: options.validAt,
688
+ ...(sourceContext?.sourceConnector ? { sourceConnector: sourceContext.sourceConnector } : {}),
689
+ },
690
+ { source: `${options.source}-shared-promotion` },
691
+ );
692
+ const sharedSurvivingAttrs = sharedPromotionEnvelope.rawStructuredAttributes;
696
693
  const dedupContent =
697
694
  options.category === "fact" &&
698
- options.structuredAttributes &&
699
- Object.keys(options.structuredAttributes).length > 0
700
- ? `${sanitizedBase.text}\n[Attributes: ${normalizeAttributePairs(options.structuredAttributes)}]`
695
+ sharedSurvivingAttrs &&
696
+ Object.keys(sharedSurvivingAttrs).length > 0
697
+ ? `${sanitizedBase.text}\n[Attributes: ${normalizeAttributePairs({ ...sharedSurvivingAttrs })}]`
701
698
  : sanitizedBase.text;
702
699
  if (
703
700
  options.category === "fact" &&
@@ -712,7 +709,7 @@ export class ExtractionPersistCoordinator {
712
709
  let sharedSameConnector = true;
713
710
  if (options.invalidAt || options.validAt) {
714
711
  try {
715
- const sharedMems = await sharedStorage.readAllMemories();
712
+ const sharedMems = await readActiveMemoriesBothTiers(sharedStorage);
716
713
  const snc = sourceContext?.sourceConnector?.trim() || undefined;
717
714
  sharedSameConnector = sharedMems.some((m) => {
718
715
  if (m.frontmatter.category !== "fact") return false;
@@ -750,7 +747,8 @@ export class ExtractionPersistCoordinator {
750
747
  ...(options.observedAt ? { observedAt: options.observedAt } : {}),
751
748
  ...(options.eventTimeSource ? { eventTimeSource: options.eventTimeSource } : {}),
752
749
  },
753
- options.entityRef,
750
+ // #2014 round 3: envelope-surviving entityRef (see profile-target).
751
+ sharedPromotionEnvelope.entityRef,
754
752
  sourceContext?.sourceConnector,
755
753
  );
756
754
  }
@@ -767,9 +765,9 @@ export class ExtractionPersistCoordinator {
767
765
  // step — if the lookup fails we skip silently (same as the normal path).
768
766
  if (
769
767
  lifecycleCaps.temporalSupersession &&
770
- options.entityRef &&
771
- options.structuredAttributes &&
772
- Object.keys(options.structuredAttributes).length > 0
768
+ sharedPromotionEnvelope.entityRef &&
769
+ sharedSurvivingAttrs &&
770
+ Object.keys(sharedSurvivingAttrs).length > 0
773
771
  ) {
774
772
  // PR #402 round-7 (Fix #2 / Codex P1 PRRT_kwDORJXyws56VALC):
775
773
  // Track whether matchingFact lookup completed before the try block
@@ -787,7 +785,7 @@ export class ExtractionPersistCoordinator {
787
785
  // sanitization redacted the content, causing the candidate lookup to
788
786
  // return undefined and leaving stale facts active.
789
787
  const normalizedIncoming = ContentHashIndex.normalizeContent(dedupContent);
790
- const allShared = await sharedStorage.readAllMemories();
788
+ const allShared = await readActiveMemoriesBothTiers(sharedStorage);
791
789
  // PR #402 round-12 (Finding Uybg): restrict hash-dedup matching to
792
790
  // the SAME entity. Content-hash equality alone can collide across
793
791
  // entities when two entities share identical fact text. Using an
@@ -795,7 +793,7 @@ export class ExtractionPersistCoordinator {
795
793
  // supersession to that entity's record and corrupt its
796
794
  // `supersededBy` links. Only consider facts whose normalized
797
795
  // `entityRef` matches the incoming entity.
798
- const incomingEntityNorm = normalizeSupersessionKey(options.entityRef);
796
+ const incomingEntityNorm = normalizeSupersessionKey(sharedPromotionEnvelope.entityRef);
799
797
  hashDedupMatchingFact = allShared.find((m) => {
800
798
  if (m.frontmatter.category !== "fact") return false;
801
799
  if ((m.frontmatter.status ?? "active") !== "active") return false;
@@ -839,8 +837,8 @@ export class ExtractionPersistCoordinator {
839
837
  const hashDedupSupersession = await applyTemporalSupersession({
840
838
  storage: sharedStorage,
841
839
  newMemoryId: hashDedupMatchingFact.frontmatter.id,
842
- entityRef: options.entityRef,
843
- structuredAttributes: options.structuredAttributes,
840
+ entityRef: sharedPromotionEnvelope.entityRef,
841
+ structuredAttributes: { ...sharedSurvivingAttrs },
844
842
  createdAt: supersessionOrderingAt(options.validAt),
845
843
  enabled: !(options.eventTimeSource === "extracted" && !options.validAt),
846
844
  useCallerTimestamp: true,
@@ -903,7 +901,7 @@ export class ExtractionPersistCoordinator {
903
901
  // fact gets its own promoted copy.
904
902
  let skipSharedPromotion = true;
905
903
  try {
906
- const allSharedMems = await sharedStorage.readAllMemories();
904
+ const allSharedMems = await readActiveMemoriesBothTiers(sharedStorage);
907
905
  const snc = sourceContext?.sourceConnector?.trim() || undefined;
908
906
  const sharedNormalized = ContentHashIndex.normalizeContent(dedupContent);
909
907
  skipSharedPromotion = allSharedMems.some((m) => {
@@ -924,34 +922,23 @@ export class ExtractionPersistCoordinator {
924
922
  // No same-connector active shared fact — fall through to write.
925
923
  }
926
924
  }
927
- const sharedPromotion = await sharedStorage.writeMemory(
928
- options.category as any,
929
- citedContent,
930
- {
931
- confidence: options.confidence,
932
- tags: [...options.tags, "shared-promotion"],
933
- entityRef: options.entityRef,
934
- structuredAttributes: options.structuredAttributes,
935
- source: `${options.source}-shared-promotion`,
936
- importance: options.importance,
937
- lineage: [options.sourceMemoryId],
938
- sourceMemoryId: options.sourceMemoryId,
939
- intentGoal: options.intentGoal,
940
- intentActionType: options.intentActionType,
941
- intentEntityTypes: options.intentEntityTypes,
942
- memoryKind: options.memoryKind,
943
- validAt: options.validAt,
944
- // #1578 — forward bi-temporal bounds + ingestion provenance.
945
- ...(options.invalidAt ? { invalidAt: options.invalidAt } : {}),
946
- ...(options.observedAt ? { observedAt: options.observedAt } : {}),
947
- ...(options.eventTimeSource ? { eventTimeSource: options.eventTimeSource } : {}),
948
- contentHashSource: options.category === "fact" ? dedupContent : rawContent,
949
- // Claim-level provenance spans (issue #1575 PR 2).
950
- ...(options.sources && options.sources.length > 0 ? { sources: options.sources } : {}),
951
- ...(options.provenance ? { provenance: options.provenance } : {}),
952
- ...(sourceContext?.sourceConnector ? { sourceConnector: sourceContext.sourceConnector } : {}),
953
- },
954
- );
925
+ const sharedPromotion = await sharedStorage.writeSealedMemory(sharedPromotionEnvelope, {
926
+ importance: options.importance,
927
+ lineage: [options.sourceMemoryId],
928
+ sourceMemoryId: options.sourceMemoryId,
929
+ intentGoal: options.intentGoal,
930
+ intentActionType: options.intentActionType,
931
+ intentEntityTypes: options.intentEntityTypes,
932
+ memoryKind: options.memoryKind,
933
+ // #1578 — forward bi-temporal bounds + ingestion provenance.
934
+ ...(options.invalidAt ? { invalidAt: options.invalidAt } : {}),
935
+ ...(options.observedAt ? { observedAt: options.observedAt } : {}),
936
+ ...(options.eventTimeSource ? { eventTimeSource: options.eventTimeSource } : {}),
937
+ contentHashSource: options.category === "fact" ? dedupContent : rawContent,
938
+ // Claim-level provenance spans (issue #1575 PR 2).
939
+ ...(options.sources && options.sources.length > 0 ? { sources: options.sources } : {}),
940
+ ...(options.provenance ? { provenance: options.provenance } : {}),
941
+ });
955
942
  const promotedId = sharedPromotion.id;
956
943
  // #1645: if the shared namespace's own tombstone blocked this promotion,
957
944
  // leave the row pending_review but do NOT supersede active shared memories.
@@ -964,16 +951,16 @@ export class ExtractionPersistCoordinator {
964
951
  if (
965
952
  !sharedPromotion.tombstoneBlocked &&
966
953
  lifecycleCaps.temporalSupersession &&
967
- options.entityRef &&
968
- options.structuredAttributes &&
969
- Object.keys(options.structuredAttributes).length > 0
954
+ sharedPromotionEnvelope.entityRef &&
955
+ sharedSurvivingAttrs &&
956
+ Object.keys(sharedSurvivingAttrs).length > 0
970
957
  ) {
971
958
  try {
972
959
  await applyTemporalSupersession({
973
960
  storage: sharedStorage,
974
961
  newMemoryId: promotedId,
975
- entityRef: options.entityRef,
976
- structuredAttributes: options.structuredAttributes,
962
+ entityRef: sharedPromotionEnvelope.entityRef,
963
+ structuredAttributes: { ...sharedSurvivingAttrs },
977
964
  createdAt: supersessionOrderingAt(options.validAt),
978
965
  enabled: !(options.eventTimeSource === "extracted" && !options.validAt),
979
966
  });
@@ -996,6 +983,7 @@ export class ExtractionPersistCoordinator {
996
983
  if (!sharedPromotion.tombstoneBlocked) {
997
984
  trackPersistedId(sharedStorage, promotedId, {
998
985
  includeReturnedIds: false,
986
+ category: options.category as MemoryCategory,
999
987
  });
1000
988
  await this.deps.indexPersistedMemory(sharedStorage, promotedId);
1001
989
  trackBehaviorSignals(
@@ -1055,11 +1043,28 @@ export class ExtractionPersistCoordinator {
1055
1043
  ? stripCitationForTemplate(args.content, citationTemplate)
1056
1044
  : args.content;
1057
1045
  const sanitizedBase = sanitizeMemoryContent(rawContent);
1046
+ // #2014 round 3: promoted copies were written from SALVAGE envelopes,
1047
+ // so hash on the same surviving fields those writes persisted — a
1048
+ // raw-attrs hash silently misses after salvage drops/dedupes keys.
1049
+ // Fail open to raw fields when the probe rejects.
1050
+ const probed =
1051
+ args.category === "fact" && isMemoryCategory(args.category)
1052
+ ? probeSalvageSurvivingFields({
1053
+ content: rawContent,
1054
+ category: args.category,
1055
+ structuredAttributes: args.structuredAttributes,
1056
+ entityRef: args.entityRef,
1057
+ })
1058
+ : null;
1059
+ const backfillEntityRef = probed ? probed.entityRef : args.entityRef;
1060
+ const survivingBackfillAttrs = probed
1061
+ ? probed.structuredAttributes
1062
+ : args.structuredAttributes;
1058
1063
  const dedupContent =
1059
1064
  args.category === "fact" &&
1060
- args.structuredAttributes &&
1061
- Object.keys(args.structuredAttributes).length > 0
1062
- ? `${sanitizedBase.text}\n[Attributes: ${normalizeAttributePairs(args.structuredAttributes)}]`
1065
+ survivingBackfillAttrs &&
1066
+ Object.keys(survivingBackfillAttrs).length > 0
1067
+ ? `${sanitizedBase.text}\n[Attributes: ${normalizeAttributePairs(survivingBackfillAttrs)}]`
1063
1068
  : sanitizedBase.text;
1064
1069
  // Profile targets. NOTE: we do NOT gate on profileAutoPromotionAllows —
1065
1070
  // a promoted profile copy may exist from an EARLIER extraction with
@@ -1090,7 +1095,7 @@ export class ExtractionPersistCoordinator {
1090
1095
  targetStorage,
1091
1096
  dedupContent,
1092
1097
  args.bounds,
1093
- args.entityRef,
1098
+ backfillEntityRef,
1094
1099
  args.sourceConnector,
1095
1100
  );
1096
1101
  } catch (err) {
@@ -1118,7 +1123,7 @@ export class ExtractionPersistCoordinator {
1118
1123
  sharedStorage,
1119
1124
  dedupContent,
1120
1125
  args.bounds,
1121
- args.entityRef,
1126
+ backfillEntityRef,
1122
1127
  args.sourceConnector,
1123
1128
  );
1124
1129
  }
@@ -1136,7 +1141,7 @@ export class ExtractionPersistCoordinator {
1136
1141
  "persistExtraction: result or result.facts is invalid, skipping",
1137
1142
  { resultType: typeof result, factsType: typeof result?.facts },
1138
1143
  );
1139
- return persistedIds;
1144
+ return { persistedIds, memoryPathById };
1140
1145
  }
1141
1146
 
1142
1147
  // Chunking config from plugin settings
@@ -1521,6 +1526,18 @@ export class ExtractionPersistCoordinator {
1521
1526
  ) {
1522
1527
  continue;
1523
1528
  }
1529
+ // Trim first (round 5): legacy writeMemory accepted " fact ".
1530
+ (fact as any).category = (fact as any).category.trim();
1531
+ // #2014/#2017 review round: an unrecognized non-empty category from
1532
+ // the extractor is a per-CANDIDATE defect. The composer keeps category
1533
+ // fatal even in salvage mode (identity field), so filter here — one
1534
+ // malformed model field must not abort the whole extraction batch.
1535
+ if (!isMemoryCategory((fact as any).category)) {
1536
+ log.warn(
1537
+ `persistExtraction: skipping fact with unrecognized category ${JSON.stringify((fact as any).category)}`,
1538
+ );
1539
+ continue;
1540
+ }
1524
1541
  (fact as any).tags = Array.isArray((fact as any).tags)
1525
1542
  ? (fact as any).tags.filter((t: any) => typeof t === "string")
1526
1543
  : [];
@@ -1668,26 +1685,47 @@ export class ExtractionPersistCoordinator {
1668
1685
  fact.tags,
1669
1686
  );
1670
1687
  let exactDuplicate = false;
1688
+ let needsCorpusConfirm = false;
1671
1689
  try {
1672
- exactDuplicate = await this.deps.hasContentHashDedup(
1673
- targetStorage,
1674
- contentHashDedupKey,
1675
- );
1690
+ exactDuplicate = await this.deps.hasContentHashDedup(targetStorage, contentHashDedupKey);
1691
+ if (factDedupEnabled && !exactDuplicate) {
1692
+ // Fact dedup disabled → skip the authority check AND (via the guarded
1693
+ // corpus block below) corpus confirmation, so a disabled deployment
1694
+ // never suppresses a write via dedup (PR #2016 thread SD-nH). Enabled:
1695
+ // a MISS is trustworthy only against an AUTHORITATIVE index — re-check.
1696
+ if (await targetStorage.isFactContentHashAuthoritative()) {
1697
+ exactDuplicate = await this.deps.hasContentHashDedup(targetStorage, contentHashDedupKey);
1698
+ } else {
1699
+ needsCorpusConfirm = true;
1700
+ }
1701
+ }
1676
1702
  } catch (err) {
1703
+ // Dedup lookup failed (e.g. the authoritative rebuild could not run). Do
1704
+ // NOT fail-open into a possible duplicate — confirm against the corpus.
1705
+ needsCorpusConfirm = true;
1677
1706
  log.warn(
1678
- `content-hash dedup lookup failed for storage ${targetStorage.dir}; writing fact fail-open: ${err}`,
1707
+ `content-hash dedup lookup unavailable for storage ${targetStorage.dir}; confirming against corpus: ${err}`,
1679
1708
  );
1680
1709
  }
1681
- // Connector-aware dedup (QOjlB): if the hash says duplicate, verify
1682
- // a same-content, same-connector active fact exists. Different
1683
- // connectors with same content should NOT be deduped. Fail open
1684
- // (write) on scan failure so an unverifiable hash hit cannot
1685
- // silently drop content.
1686
- if (exactDuplicate) {
1710
+ // Connector-aware dedup (QOjlB): if the hash says duplicate — or the index
1711
+ // could not authoritatively confirm a miss — verify a same-content,
1712
+ // same-connector active fact exists across the hot+cold tiers. Different
1713
+ // connectors with the same content are NOT duplicates. Fail open (write) on
1714
+ // scan failure so an unverifiable state cannot silently drop content.
1715
+ if (factDedupEnabled && (exactDuplicate || needsCorpusConfirm)) {
1687
1716
  try {
1688
- const allMems = await targetStorage.readAllMemories();
1717
+ // #2016 cold-tier finding: the authoritative content-hash rebuild
1718
+ // unions the HOT and COLD tiers, so a hash hit can name an active copy
1719
+ // that was demoted to cold/. A hot-only confirmation scan misses it,
1720
+ // flips exactDuplicate back to false, and writes a second active hot
1721
+ // copy of the same content. Scan both tiers so a cold-only active copy
1722
+ // still confirms the duplicate and suppresses the redundant hot write.
1723
+ const [hotMems, coldMems] = await Promise.all([
1724
+ targetStorage.readAllMemories(),
1725
+ targetStorage.readAllColdMemories(),
1726
+ ]);
1689
1727
  const nc = sourceContext?.sourceConnector?.trim() || undefined;
1690
- exactDuplicate = allMems.some((m) => {
1728
+ const matchesActiveDuplicate = (m: MemoryFile): boolean => {
1691
1729
  if (m.frontmatter.category !== writeCategory) return false;
1692
1730
  if ((m.frontmatter.status ?? "active") !== "active") return false;
1693
1731
  // Thread 5 (QPDE5): for procedures the hash is keyed on the full
@@ -1700,7 +1738,9 @@ export class ExtractionPersistCoordinator {
1700
1738
  if (normalizeStoredHashSource(stripAttributesSuffix(m.content ?? "")) !==
1701
1739
  ContentHashIndex.normalizeContent(contentHashDedupKey)) return false;
1702
1740
  return (m.frontmatter.sourceConnector?.trim() || undefined) === nc;
1703
- });
1741
+ };
1742
+ exactDuplicate =
1743
+ hotMems.some(matchesActiveDuplicate) || coldMems.some(matchesActiveDuplicate);
1704
1744
  } catch (err) {
1705
1745
  log.warn(
1706
1746
  `connector-aware dedup scan failed for storage ${targetStorage.dir}; writing fail-open: ${err instanceof Error ? err.message : String(err)}`,
@@ -2158,34 +2198,39 @@ export class ExtractionPersistCoordinator {
2158
2198
  ? stripCitationForTemplate(fact.content, citationTemplate)
2159
2199
  : fact.content;
2160
2200
  const citedChunkedContent = applyInlineCitation(rawChunkedContent);
2161
- const parentWrite = await targetStorage.writeMemory(
2162
- writeCategory,
2163
- citedChunkedContent,
2201
+ const parentWriteEnvelope = composeSalvagedExtractionEnvelope(
2164
2202
  {
2203
+ content: citedChunkedContent,
2204
+ category: writeCategory,
2165
2205
  confidence: fact.confidence,
2166
- tags: [...fact.tags, "chunked"],
2206
+ tags: withReservedMarkerTag(fact.tags, "chunked"),
2167
2207
  entityRef: fact.entityRef,
2168
- source: extractionWriteSource,
2169
- ...(extractionSourceConnector ? { sourceConnector: extractionSourceConnector } : {}),
2170
- importance,
2171
- supersedes,
2172
- links: links.length > 0 ? links : undefined,
2173
- intentGoal: inferredIntent?.goal,
2174
- intentActionType: inferredIntent?.actionType,
2175
- intentEntityTypes: inferredIntent?.entityTypes,
2176
- memoryKind,
2177
2208
  structuredAttributes: fact.structuredAttributes,
2178
2209
  validAt: biTemporal ? biTemporal.validFrom : sourceContext?.validAt,
2179
- ...(biTemporal ? { observedAt: biTemporal.observedAt, eventTimeSource: biTemporal.eventTimeSource, ...(biTemporal.validUntil ? { invalidAt: biTemporal.validUntil } : {}) } : {}),
2180
- contentHashSource: rawChunkedContent,
2181
- // Faithfulness gate (issue #1576).
2182
- ...(faithfulnessFm ? { faithfulness: faithfulnessFm } : {}),
2183
- ...(faithfulnessEnforceStatus ? { status: faithfulnessEnforceStatus } : {}),
2184
- // Claim-level provenance spans (issue #1575 PR 2).
2185
- ...(fact.sources && fact.sources.length > 0 ? { sources: fact.sources } : {}),
2186
- ...(fact.provenance ? { provenance: fact.provenance } : {}),
2210
+ ...(extractionSourceConnector ? { sourceConnector: extractionSourceConnector } : {}),
2187
2211
  },
2188
- );
2212
+ { source: extractionWriteSource },
2213
+ );
2214
+ const parentWrite = await targetStorage.writeSealedMemory(parentWriteEnvelope, {
2215
+ importance,
2216
+ supersedes,
2217
+ links: links.length > 0 ? links : undefined,
2218
+ intentGoal: inferredIntent?.goal,
2219
+ intentActionType: inferredIntent?.actionType,
2220
+ intentEntityTypes: inferredIntent?.entityTypes,
2221
+ memoryKind,
2222
+ ...(biTemporal ? { observedAt: biTemporal.observedAt, eventTimeSource: biTemporal.eventTimeSource, ...(biTemporal.validUntil ? { invalidAt: biTemporal.validUntil } : {}) } : {}),
2223
+ contentHashSource: rawChunkedContent,
2224
+ // Faithfulness gate (issue #1576).
2225
+ ...(faithfulnessFm ? { faithfulness: faithfulnessFm } : {}),
2226
+ ...(faithfulnessEnforceStatus ? { status: faithfulnessEnforceStatus } : {}),
2227
+ // Claim-level provenance spans (issue #1575 PR 2).
2228
+ ...(fact.sources && fact.sources.length > 0 ? { sources: fact.sources } : {}),
2229
+ ...(fact.provenance ? { provenance: fact.provenance } : {}),
2230
+ // PR #2016: never defer here — fallible chunk/artifact writes follow this
2231
+ // durable parent .md; flush the hash now so a throw can't strand it (dup).
2232
+ deferHashIndexSave: false,
2233
+ });
2189
2234
  const parentId = parentWrite.id;
2190
2235
  // #1645: surface the tombstone block and gate active post-write paths
2191
2236
  // (chunks, supersession, shared promotion, graph/artifact) like #1576.
@@ -2201,13 +2246,18 @@ export class ExtractionPersistCoordinator {
2201
2246
  postWriteGuard,
2202
2247
  );
2203
2248
  try {
2249
+ // #2014 round 3: chunks inherit the PARENT ENVELOPE's surviving
2250
+ // tags (minus the parent-only "chunked" marker) and entityRef —
2251
+ // passing raw fact.tags let chunk frontmatter disagree with the
2252
+ // sealed parent and retain tags past the per-memory limits.
2253
+ const chunkTags = parentWriteEnvelope.tags.filter((tag) => tag !== "chunked");
2204
2254
  // Write individual chunks with parent reference
2205
2255
  for (const chunk of chunkResult.chunks) {
2206
2256
  // Score each chunk's importance separately
2207
2257
  const chunkImportance = scoreImportance(
2208
2258
  chunk.content,
2209
2259
  writeCategory,
2210
- fact.tags,
2260
+ chunkTags,
2211
2261
  );
2212
2262
  const chunkWriteSource =
2213
2263
  (fact as any).source === "proactive"
@@ -2223,9 +2273,11 @@ export class ExtractionPersistCoordinator {
2223
2273
  // survives when a single chunk is quoted in isolation.
2224
2274
  applyInlineCitation(chunk.content),
2225
2275
  {
2226
- confidence: fact.confidence,
2227
- tags: fact.tags,
2228
- entityRef: fact.entityRef,
2276
+ // #2014 round 4: sealed parent's confidence — raw
2277
+ // fact.confidence would let parent and chunk disagree.
2278
+ confidence: parentWriteEnvelope.confidence,
2279
+ tags: [...chunkTags],
2280
+ entityRef: parentWriteEnvelope.entityRef,
2229
2281
  source: chunkWriteSource,
2230
2282
  importance: chunkImportance,
2231
2283
  intentGoal: inferredIntent?.goal,
@@ -2282,6 +2334,7 @@ export class ExtractionPersistCoordinator {
2282
2334
  );
2283
2335
  trackPersistedId(targetStorage, parentId, {
2284
2336
  pendingReview: postWriteGuard,
2337
+ category: writeCategory,
2285
2338
  });
2286
2339
  // #1576 (cursor Medium): keep pending_review ids out of threadEpisodeIdsForGraph — else later active facts build thread-predecessor edges to an unfaithful memory.
2287
2340
  if (
@@ -2304,15 +2357,15 @@ export class ExtractionPersistCoordinator {
2304
2357
  // must NOT retire older active memories.
2305
2358
  if (!postWriteGuard) {
2306
2359
  try {
2307
- const supersessionEntityRef =
2308
- typeof (fact as any).entityRef === "string"
2309
- ? ((fact as any).entityRef as string)
2310
- : undefined;
2360
+ // #2014 round 2: same envelope-surviving key rule as the
2361
+ // non-chunked path.
2311
2362
  await applyTemporalSupersession({
2312
2363
  storage: targetStorage,
2313
2364
  newMemoryId: parentId,
2314
- entityRef: supersessionEntityRef,
2315
- structuredAttributes: fact.structuredAttributes,
2365
+ entityRef: parentWriteEnvelope.entityRef,
2366
+ structuredAttributes: parentWriteEnvelope.rawStructuredAttributes
2367
+ ? { ...parentWriteEnvelope.rawStructuredAttributes }
2368
+ : undefined,
2316
2369
  createdAt: supersessionOrderingAt(biTemporal?.validFrom ?? sourceContext?.validAt),
2317
2370
  // #1578 r3: an extracted end-only bound (validFrom absent) is
2318
2371
  // historical, not a new authoritative state — never let it
@@ -2412,10 +2465,9 @@ export class ExtractionPersistCoordinator {
2412
2465
  if (graphCaps.multiGraphMemory && !postWriteGuard) {
2413
2466
  try {
2414
2467
  const graphContext = await ensureGraphContext(targetStorage);
2415
- const entityRef =
2416
- typeof (fact as any).entityRef === "string"
2417
- ? (fact as any).entityRef
2418
- : undefined;
2468
+ // #2014 round 4: graph identity must match the PERSISTED
2469
+ // memory the envelope's surviving entityRef.
2470
+ const entityRef = parentWriteEnvelope.entityRef;
2419
2471
  const parentRelPath = resolvePersistedMemoryRelativePath({
2420
2472
  memoryId: parentId,
2421
2473
  pathById: graphContext.memoryPathById,
@@ -2511,39 +2563,44 @@ export class ExtractionPersistCoordinator {
2511
2563
  ? buildProcedurePersistBody(fact.content, fact.procedureSteps)
2512
2564
  : fact.content;
2513
2565
  const citedFactContent = applyInlineCitation(rawPersistBody);
2514
- const factWrite = await targetStorage.writeMemory(
2515
- writeCategory,
2516
- citedFactContent,
2566
+ const factWriteEnvelope = composeSalvagedExtractionEnvelope(
2517
2567
  {
2568
+ content: citedFactContent,
2569
+ category: writeCategory,
2518
2570
  confidence: fact.confidence,
2519
2571
  tags: fact.tags,
2520
2572
  entityRef:
2521
2573
  typeof (fact as any).entityRef === "string"
2522
2574
  ? (fact as any).entityRef
2523
2575
  : undefined,
2524
- source: extractionWriteSource,
2525
- ...(extractionSourceConnector ? { sourceConnector: extractionSourceConnector } : {}),
2526
- importance,
2527
- supersedes,
2528
- links: links.length > 0 ? links : undefined,
2529
- intentGoal: inferredIntent?.goal,
2530
- intentActionType: inferredIntent?.actionType,
2531
- intentEntityTypes: inferredIntent?.entityTypes,
2532
- memoryKind,
2533
2576
  structuredAttributes: fact.structuredAttributes,
2534
2577
  validAt: biTemporal ? biTemporal.validFrom : sourceContext?.validAt,
2535
- ...(biTemporal ? { observedAt: biTemporal.observedAt, eventTimeSource: biTemporal.eventTimeSource, ...(biTemporal.validUntil ? { invalidAt: biTemporal.validUntil } : {}) } : {}),
2536
- contentHashSource: writeCategory === "fact" ? fact.content : undefined,
2537
- // Faithfulness gate (issue #1576).
2538
- ...(faithfulnessFm ? { faithfulness: faithfulnessFm } : {}),
2539
- ...(faithfulnessEnforceStatus ? { status: faithfulnessEnforceStatus } : {}),
2540
- // Claim-level provenance spans (issue #1575 PR 2). Carry verified
2541
- // sources + the coarse strength tag from the extraction validator
2542
- // through to frontmatter so they survive end-to-end.
2543
- ...(fact.sources && fact.sources.length > 0 ? { sources: fact.sources } : {}),
2544
- ...(fact.provenance ? { provenance: fact.provenance } : {}),
2578
+ ...(extractionSourceConnector ? { sourceConnector: extractionSourceConnector } : {}),
2545
2579
  },
2546
- );
2580
+ { source: extractionWriteSource },
2581
+ );
2582
+ const factWrite = await targetStorage.writeSealedMemory(factWriteEnvelope, {
2583
+ importance,
2584
+ supersedes,
2585
+ links: links.length > 0 ? links : undefined,
2586
+ intentGoal: inferredIntent?.goal,
2587
+ intentActionType: inferredIntent?.actionType,
2588
+ intentEntityTypes: inferredIntent?.entityTypes,
2589
+ memoryKind,
2590
+ ...(biTemporal ? { observedAt: biTemporal.observedAt, eventTimeSource: biTemporal.eventTimeSource, ...(biTemporal.validUntil ? { invalidAt: biTemporal.validUntil } : {}) } : {}),
2591
+ contentHashSource: writeCategory === "fact" ? fact.content : undefined,
2592
+ // Faithfulness gate (issue #1576).
2593
+ ...(faithfulnessFm ? { faithfulness: faithfulnessFm } : {}),
2594
+ ...(faithfulnessEnforceStatus ? { status: faithfulnessEnforceStatus } : {}),
2595
+ // Claim-level provenance spans (issue #1575 PR 2). Carry verified
2596
+ // sources + the coarse strength tag from the extraction validator
2597
+ // through to frontmatter so they survive end-to-end.
2598
+ ...(fact.sources && fact.sources.length > 0 ? { sources: fact.sources } : {}),
2599
+ ...(fact.provenance ? { provenance: fact.provenance } : {}),
2600
+ // #1909: defer the per-fact index flush to the batch save only when
2601
+ // fact dedup is on (the batch saver is a no-op otherwise).
2602
+ deferHashIndexSave: factDedupEnabled,
2603
+ });
2547
2604
  const memoryId = factWrite.id;
2548
2605
  // #1645: surface the tombstone block; gate active post-write paths like #1576
2549
2606
  // so a blocked fact creates no active shared copy / supersession / graph entry.
@@ -2552,12 +2609,12 @@ export class ExtractionPersistCoordinator {
2552
2609
  faithfulnessEnforceStatus === "pending_review" || tombstoneBlocked;
2553
2610
  // #1645: defer contradiction auto-resolve until tombstone status is
2554
2611
  // known (see applyDeferredContradictionResolve).
2555
- await this.deps.applyDeferredContradictionResolve(
2556
- contradiction,
2557
- targetStorage,
2558
- memoryId,
2559
- postWriteGuard,
2560
- );
2612
+ try {
2613
+ await this.deps.applyDeferredContradictionResolve(contradiction, targetStorage, memoryId, postWriteGuard);
2614
+ } catch (err) {
2615
+ await flushDeferredFactHashOnFailure(() => this.deps.saveContentHashIndexes(), factDedupEnabled);
2616
+ throw err;
2617
+ }
2561
2618
  if (routedRuleId) {
2562
2619
  log.debug(
2563
2620
  `routing applied for memory ${memoryId}: rule=${routedRuleId} category=${writeCategory} storage=${targetStorage.dir}`,
@@ -2570,15 +2627,16 @@ export class ExtractionPersistCoordinator {
2570
2627
  // the review queue must NOT retire older active memories.
2571
2628
  if (!postWriteGuard) {
2572
2629
  try {
2573
- const supersessionEntityRef =
2574
- typeof (fact as any).entityRef === "string"
2575
- ? ((fact as any).entityRef as string)
2576
- : undefined;
2630
+ // #2014 round 2: key supersession on the envelope's SURVIVING
2631
+ // fields salvage may have dropped attributes that must not
2632
+ // retire older facts the persisted copy does not actually contest.
2577
2633
  await applyTemporalSupersession({
2578
2634
  storage: targetStorage,
2579
2635
  newMemoryId: memoryId,
2580
- entityRef: supersessionEntityRef,
2581
- structuredAttributes: fact.structuredAttributes,
2636
+ entityRef: factWriteEnvelope.entityRef,
2637
+ structuredAttributes: factWriteEnvelope.rawStructuredAttributes
2638
+ ? { ...factWriteEnvelope.rawStructuredAttributes }
2639
+ : undefined,
2582
2640
  createdAt: supersessionOrderingAt(biTemporal?.validFrom ?? sourceContext?.validAt),
2583
2641
  enabled: lifecycleCaps.temporalSupersession &&
2584
2642
  !(biTemporal && !biTemporal.validFrom),
@@ -2601,6 +2659,7 @@ export class ExtractionPersistCoordinator {
2601
2659
  );
2602
2660
  trackPersistedId(targetStorage, memoryId, {
2603
2661
  pendingReview: postWriteGuard,
2662
+ category: writeCategory,
2604
2663
  });
2605
2664
  if (
2606
2665
  !postWriteGuard &&
@@ -2652,10 +2711,8 @@ export class ExtractionPersistCoordinator {
2652
2711
  if (graphCaps.multiGraphMemory && !postWriteGuard) {
2653
2712
  try {
2654
2713
  const graphContext = await ensureGraphContext(targetStorage);
2655
- const entityRef =
2656
- typeof (fact as any).entityRef === "string"
2657
- ? (fact as any).entityRef
2658
- : undefined;
2714
+ // #2014 round 4: envelope-surviving entityRef (see chunked path).
2715
+ const entityRef = factWriteEnvelope.entityRef;
2659
2716
  const memoryRelPath = resolvePersistedMemoryRelativePath({
2660
2717
  memoryId,
2661
2718
  pathById: graphContext.memoryPathById,
@@ -2731,6 +2788,11 @@ export class ExtractionPersistCoordinator {
2731
2788
  `content-hash dedup registration failed for memory ${memoryId}: ${err}`,
2732
2789
  );
2733
2790
  }
2791
+ } catch (err) {
2792
+ // PR #2016: flush the deferred fact-hash before propagating so a durable
2793
+ // .md never outlives a missing shared fact-hash index entry.
2794
+ await flushDeferredFactHashOnFailure(() => this.deps.saveContentHashIndexes(), factDedupEnabled);
2795
+ throw err;
2734
2796
  } finally {
2735
2797
  // Catalog touch (issue #1499): record AFTER every synchronous
2736
2798
  // source-namespace mutation in the non-chunked path: writeMemory,
@@ -2883,10 +2945,15 @@ export class ExtractionPersistCoordinator {
2883
2945
  touchBaseNonFactNamespace();
2884
2946
  }
2885
2947
 
2886
- // Save any content-hash indexes touched during the batch.
2887
- await this.deps.saveContentHashIndexes().catch((err) =>
2888
- log.warn(`content-hash index save failed: ${err}`),
2889
- );
2948
+ // Save any content-hash indexes touched during the batch via the removal-
2949
+ // aware, lock-held reconciling save (issue #1909). Round 11: the fact-hash
2950
+ // index is rebuilt from the corpus on every restart (no ready marker), so
2951
+ // this on-disk write is the in-process persisted view — never a cross-restart
2952
+ // trust anchor. A deferred write whose addContentHashDedup threw is still
2953
+ // safe: the fact .md is durable and the next restart's rebuild includes it.
2954
+ await this.deps.saveContentHashIndexes().catch((err) => {
2955
+ log.warn(`content-hash index save failed: ${err}`);
2956
+ });
2890
2957
 
2891
2958
  for (const {
2892
2959
  storage: targetStorage,
@@ -2911,7 +2978,6 @@ export class ExtractionPersistCoordinator {
2911
2978
  log.info(
2912
2979
  `persisted: ${facts.length - dedupedCount - importanceGatedCount - judgeGatedCount - redactionGatedCount} facts${dedupSuffix}${gatedSuffix}${judgeSuffix}${redactionSuffix}, ${entities.length} entities, ${questions.length} questions, ${profileUpdates.length} profile updates`,
2913
2980
  );
2914
-
2915
2981
  // Update temporal + tag indexes (v8.1) — fire-and-forget, fail-open
2916
2982
  void (async () => {
2917
2983
  if (persistedIdsByStorage.size === 0) {
@@ -2924,10 +2990,9 @@ export class ExtractionPersistCoordinator {
2924
2990
  })().catch((err) =>
2925
2991
  log.debug(`temporal-index update error (non-fatal): ${err}`),
2926
2992
  );
2927
-
2928
2993
  // #1635: surface pending_review ids so the thread episode set excludes them.
2929
2994
  this.deps.setLastPersistExtractionPendingReviewIds(pendingReviewPersistedIds);
2930
2995
  // Return the persisted fact IDs for threading
2931
- return persistedIds;
2996
+ return { persistedIds, memoryPathById };
2932
2997
  }
2933
2998
  }