@remnic/core 9.45.3 → 9.45.5

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 (766) hide show
  1. package/dist/abort-error.d.ts +2 -1
  2. package/dist/abort-error.js +3 -1
  3. package/dist/access-admin-ops-surface.d.ts +14 -10
  4. package/dist/access-admin-ops-surface.js +84 -75
  5. package/dist/access-audit.js +2 -2
  6. package/dist/access-authorization-probe.d.ts +14 -10
  7. package/dist/access-authorization-probe.js +85 -76
  8. package/dist/access-boundary.d.ts +15 -11
  9. package/dist/access-boundary.js +84 -75
  10. package/dist/access-citation-namespace.js +2 -2
  11. package/dist/access-cli.js +191 -177
  12. package/dist/access-cli.js.map +1 -1
  13. package/dist/access-coding-context-resolution.d.ts +16 -0
  14. package/dist/access-coding-context-resolution.js +13 -0
  15. package/dist/access-coding-context-resolution.js.map +1 -0
  16. package/dist/access-extraction-force-flush.d.ts +14 -10
  17. package/dist/access-extraction-force-flush.js +84 -75
  18. package/dist/access-health-types.d.ts +2 -1
  19. package/dist/access-http-lcm-compaction.d.ts +16 -12
  20. package/dist/access-http-lcm-compaction.js +3 -3
  21. package/dist/access-http-lifecycle-flush.d.ts +14 -10
  22. package/dist/access-http-lifecycle-flush.js +2 -2
  23. package/dist/access-http-offline-stream.d.ts +123 -0
  24. package/dist/access-http-offline-stream.js +10 -0
  25. package/dist/access-http-offline-stream.js.map +1 -0
  26. package/dist/access-http-query.js +84 -75
  27. package/dist/access-http.d.ts +15 -11
  28. package/dist/access-http.js +104 -90
  29. package/dist/access-identity-continuity-surface.d.ts +9 -8
  30. package/dist/access-identity-continuity-surface.js +84 -75
  31. package/dist/access-lcm-surface.d.ts +14 -10
  32. package/dist/access-lcm-surface.js +84 -75
  33. package/dist/access-mcp-output-schemas.js +1 -1
  34. package/dist/access-mcp.d.ts +14 -10
  35. package/dist/access-mcp.js +95 -82
  36. package/dist/access-memory-search-fanout.d.ts +3 -2
  37. package/dist/{access-namespace-preflight-5yZ4g6F8.d.ts → access-namespace-preflight-CWUDwB4M.d.ts} +1 -1
  38. package/dist/access-namespace-preflight.d.ts +4 -3
  39. package/dist/access-namespace-preflight.js +84 -75
  40. package/dist/access-observe-helpers.d.ts +1 -0
  41. package/dist/access-observe-helpers.js +1 -1
  42. package/dist/access-observe-write-surface.d.ts +16 -10
  43. package/dist/access-observe-write-surface.js +84 -75
  44. package/dist/access-offline-manifest.d.ts +104 -0
  45. package/dist/access-offline-manifest.js +45 -0
  46. package/dist/access-offline-manifest.js.map +1 -0
  47. package/dist/access-operations-batch.js +86 -77
  48. package/dist/access-operations.d.ts +18 -14
  49. package/dist/access-operations.js +91 -79
  50. package/dist/access-recall-concurrency.d.ts +16 -26
  51. package/dist/access-recall-concurrency.js +86 -76
  52. package/dist/access-recall-response.d.ts +18 -14
  53. package/dist/access-recall-response.js +84 -75
  54. package/dist/access-recall-surface.d.ts +29 -24
  55. package/dist/access-recall-surface.js +84 -75
  56. package/dist/access-schema.d.ts +84 -84
  57. package/dist/access-schema.js +3 -3
  58. package/dist/{access-service-CiJRsgAB.d.ts → access-service-CNN89xyn.d.ts} +25 -16
  59. package/dist/access-service-helpers.d.ts +14 -10
  60. package/dist/access-service.d.ts +14 -10
  61. package/dist/access-service.js +84 -75
  62. package/dist/access-surface-catalog.d.ts +14 -10
  63. package/dist/access-surface-catalog.js +4 -0
  64. package/dist/access-surface-catalog.js.map +1 -1
  65. package/dist/access-wearables-meetings-surface.d.ts +4 -3
  66. package/dist/action-confidence.d.ts +2 -1
  67. package/dist/active-memory-bridge.d.ts +2 -1
  68. package/dist/active-recall.d.ts +2 -1
  69. package/dist/active-recall.js +10 -8
  70. package/dist/active-recall.js.map +1 -1
  71. package/dist/adapters/index.js +4 -4
  72. package/dist/adapters/registry.js +2 -2
  73. package/dist/{auto-sync-5OE5QOZB.js → auto-sync-UPTUVE4X.js} +6 -6
  74. package/dist/behavior-learner.d.ts +2 -1
  75. package/dist/behavior-learner.js +1 -1
  76. package/dist/behavior-signals.d.ts +2 -1
  77. package/dist/bootstrap.d.ts +9 -8
  78. package/dist/briefing.d.ts +3 -2
  79. package/dist/briefing.js +24 -22
  80. package/dist/buffer-surprise-report.d.ts +2 -1
  81. package/dist/buffer-turn-helpers.d.ts +2 -1
  82. package/dist/buffer.d.ts +3 -2
  83. package/dist/buffer.js +12 -11
  84. package/dist/bulk-import/index.d.ts +4 -3
  85. package/dist/calibration.d.ts +2 -1
  86. package/dist/capabilities.d.ts +2 -1
  87. package/dist/{capsule-merge-IDWJPCWK.js → capsule-merge-Q6AR3XL7.js} +67 -54
  88. package/dist/capsule-merge-Q6AR3XL7.js.map +1 -0
  89. package/dist/{catalog-scBmy0sO.d.ts → catalog-bctMURhN.d.ts} +1 -1
  90. package/dist/causal-behavior.d.ts +2 -1
  91. package/dist/causal-behavior.js +2 -2
  92. package/dist/causal-chain.js +2 -2
  93. package/dist/causal-consolidation.d.ts +2 -1
  94. package/dist/causal-consolidation.js +28 -26
  95. package/dist/causal-consolidation.js.map +1 -1
  96. package/dist/causal-retrieval.js +2 -2
  97. package/dist/causal-trajectory-graph.d.ts +2 -1
  98. package/dist/causal-trajectory.js +1 -1
  99. package/dist/{chunk-E5UK4VPE.js → chunk-2FSTB6BJ.js} +5 -5
  100. package/dist/{chunk-5ZE7QHTK.js → chunk-2X2T2UVE.js} +5 -5
  101. package/dist/{chunk-P4DRWEYC.js → chunk-3COYXTGM.js} +2 -2
  102. package/dist/{chunk-5IVLTFOV.js → chunk-44N6ESJ4.js} +2 -2
  103. package/dist/{chunk-DL7ZD3JH.js → chunk-4FBVAGV3.js} +14 -9
  104. package/dist/chunk-4FBVAGV3.js.map +1 -0
  105. package/dist/{chunk-WOCNN776.js → chunk-4POAMKV6.js} +100 -41
  106. package/dist/chunk-4POAMKV6.js.map +1 -0
  107. package/dist/{chunk-HO3QBJEY.js → chunk-5546W5SI.js} +2 -2
  108. package/dist/{chunk-AAIUERNB.js → chunk-5QJQHBLE.js} +6 -6
  109. package/dist/{chunk-6CZPDBJS.js → chunk-5U7ID3EZ.js} +3 -3
  110. package/dist/{chunk-RN7DY3FC.js → chunk-6ISC4AVB.js} +31 -12
  111. package/dist/chunk-6ISC4AVB.js.map +1 -0
  112. package/dist/chunk-773TRRGT.js +36 -0
  113. package/dist/chunk-773TRRGT.js.map +1 -0
  114. package/dist/chunk-7T4TOGMS.js +242 -0
  115. package/dist/chunk-7T4TOGMS.js.map +1 -0
  116. package/dist/{chunk-DLVPUX7U.js → chunk-7YKVM5H3.js} +8 -6
  117. package/dist/chunk-7YKVM5H3.js.map +1 -0
  118. package/dist/chunk-7YQ6ESEA.js +322 -0
  119. package/dist/chunk-7YQ6ESEA.js.map +1 -0
  120. package/dist/{chunk-DNWXFTLD.js → chunk-A4IJCD2Z.js} +2 -2
  121. package/dist/{chunk-3CE77VAP.js → chunk-A4JMGKCD.js} +87 -74
  122. package/dist/chunk-A4JMGKCD.js.map +1 -0
  123. package/dist/chunk-A5KNZSNA.js +26 -0
  124. package/dist/chunk-A5KNZSNA.js.map +1 -0
  125. package/dist/{chunk-PKNLM44P.js → chunk-AC5OWJLV.js} +9 -9
  126. package/dist/{chunk-LZ4LDKHZ.js → chunk-AMAUBUKY.js} +6 -6
  127. package/dist/{chunk-CUM2BBPN.js → chunk-AUMWZSE7.js} +19 -10
  128. package/dist/chunk-AUMWZSE7.js.map +1 -0
  129. package/dist/{chunk-BUE5E2HL.js → chunk-BGLY7EEM.js} +5 -314
  130. package/dist/chunk-BGLY7EEM.js.map +1 -0
  131. package/dist/chunk-BIPBQQFI.js +44 -0
  132. package/dist/chunk-BIPBQQFI.js.map +1 -0
  133. package/dist/{chunk-S5SLVSVY.js → chunk-BQIFZ2MP.js} +5 -5
  134. package/dist/chunk-BTTPKDIL.js +34 -0
  135. package/dist/{chunk-PVGDJXVK.js.map → chunk-BTTPKDIL.js.map} +1 -1
  136. package/dist/chunk-CK5KOVHW.js +69 -0
  137. package/dist/chunk-CK5KOVHW.js.map +1 -0
  138. package/dist/{chunk-Q6IP2ARR.js → chunk-CSOYVTRX.js} +2 -2
  139. package/dist/{chunk-XOQSEF7X.js → chunk-CVILPI77.js} +6 -6
  140. package/dist/{chunk-VWAXN2BN.js → chunk-CX4ZUMC6.js} +91 -83
  141. package/dist/chunk-CX4ZUMC6.js.map +1 -0
  142. package/dist/{chunk-NVRYW264.js → chunk-DAJPRXBR.js} +16 -13
  143. package/dist/chunk-DAJPRXBR.js.map +1 -0
  144. package/dist/{chunk-J7VGGECD.js → chunk-DZPFMQZ7.js} +1 -1
  145. package/dist/chunk-DZPFMQZ7.js.map +1 -0
  146. package/dist/{chunk-4LMA77JH.js → chunk-E5XQIWAL.js} +3 -3
  147. package/dist/{chunk-WUNIWKY4.js → chunk-ELIL2A37.js} +6 -6
  148. package/dist/{chunk-OQ5PRDDS.js → chunk-ERZ2R42X.js} +6 -6
  149. package/dist/{chunk-U7GW7NE7.js → chunk-FIK3CQNA.js} +10 -10
  150. package/dist/{chunk-D3J5SLQK.js → chunk-FR27HBBA.js} +81 -20
  151. package/dist/chunk-FR27HBBA.js.map +1 -0
  152. package/dist/{chunk-E6PNLPGJ.js → chunk-FUCYDRE5.js} +838 -480
  153. package/dist/chunk-FUCYDRE5.js.map +1 -0
  154. package/dist/{chunk-HZFHQ4AQ.js → chunk-G7A5HLUS.js} +23 -17
  155. package/dist/chunk-G7A5HLUS.js.map +1 -0
  156. package/dist/{chunk-33PLLLL7.js → chunk-GFCVUY6G.js} +6 -6
  157. package/dist/{chunk-HREE4JHI.js → chunk-GODSPTOT.js} +477 -278
  158. package/dist/chunk-GODSPTOT.js.map +1 -0
  159. package/dist/{chunk-S2NCTZGJ.js → chunk-GRUYA45P.js} +15 -15
  160. package/dist/chunk-GRUYA45P.js.map +1 -0
  161. package/dist/{chunk-VUPTKTDV.js → chunk-GUAL4PQH.js} +3 -3
  162. package/dist/{chunk-CINZGPSJ.js → chunk-GUMZC2BO.js} +2 -2
  163. package/dist/{chunk-H24WNPA2.js → chunk-GWFSVJ4P.js} +3 -3
  164. package/dist/{chunk-7XC2HX75.js → chunk-GYPQL6XN.js} +157 -16
  165. package/dist/chunk-GYPQL6XN.js.map +1 -0
  166. package/dist/{chunk-TSH56VPU.js → chunk-HAYSYUAB.js} +2 -2
  167. package/dist/{chunk-PDLBLTOK.js → chunk-HC3PBX23.js} +9 -9
  168. package/dist/{chunk-TDHTVMPG.js → chunk-HFPASSFV.js} +7 -2
  169. package/dist/chunk-HFPASSFV.js.map +1 -0
  170. package/dist/chunk-J2WC5LF4.js +395 -0
  171. package/dist/chunk-J2WC5LF4.js.map +1 -0
  172. package/dist/{chunk-KXB4VXHY.js → chunk-JIYDRBVZ.js} +2 -2
  173. package/dist/chunk-JV3C2MNQ.js +74 -0
  174. package/dist/chunk-JV3C2MNQ.js.map +1 -0
  175. package/dist/{chunk-HLPD7B7P.js → chunk-JZH4LWHB.js} +2 -2
  176. package/dist/{chunk-AV5ZEH4M.js → chunk-KVJRXN2E.js} +2 -2
  177. package/dist/{chunk-WFTIGIIS.js → chunk-L6CQ7WIW.js} +5 -5
  178. package/dist/{chunk-227UFSEQ.js → chunk-LEPOP46W.js} +4 -4
  179. package/dist/{chunk-EJUEXZHX.js → chunk-LLJMAULE.js} +2 -2
  180. package/dist/{chunk-N5Z4EVOR.js → chunk-LNEWDF2A.js} +36 -11
  181. package/dist/chunk-LNEWDF2A.js.map +1 -0
  182. package/dist/{chunk-QN25OCUF.js → chunk-LPYDOLSM.js} +5 -5
  183. package/dist/{chunk-AS7YMSL6.js → chunk-M23RF3LJ.js} +4 -4
  184. package/dist/{chunk-OAEQLRCY.js → chunk-MO4HSXHZ.js} +5 -5
  185. package/dist/{chunk-ECK75GDJ.js → chunk-N3LL5NEU.js} +43 -24
  186. package/dist/chunk-N3LL5NEU.js.map +1 -0
  187. package/dist/chunk-NEF7LR5J.js +29 -0
  188. package/dist/chunk-NEF7LR5J.js.map +1 -0
  189. package/dist/{chunk-3F2LKUMU.js → chunk-NIS256NW.js} +2 -2
  190. package/dist/{chunk-YIAA2X3D.js → chunk-NK5RGJ65.js} +3 -3
  191. package/dist/chunk-NLDVVWCL.js +84 -0
  192. package/dist/chunk-NLDVVWCL.js.map +1 -0
  193. package/dist/{chunk-4J7G5SY4.js → chunk-NZBZ7IS2.js} +72 -24
  194. package/dist/chunk-NZBZ7IS2.js.map +1 -0
  195. package/dist/{chunk-3TBLDMJA.js → chunk-O4KMGRXE.js} +5 -2
  196. package/dist/chunk-O4KMGRXE.js.map +1 -0
  197. package/dist/{chunk-7TWUCYER.js → chunk-PNRA7FAD.js} +7 -7
  198. package/dist/{chunk-5I4M26Q7.js → chunk-QBSFOKY6.js} +4 -4
  199. package/dist/{chunk-E53DSZEN.js → chunk-QR6G5KF4.js} +3 -3
  200. package/dist/{chunk-CJ2ZR7UA.js → chunk-QUENPGWZ.js} +261 -211
  201. package/dist/chunk-QUENPGWZ.js.map +1 -0
  202. package/dist/{chunk-4UH4BTGK.js → chunk-QVJPH7SH.js} +84 -84
  203. package/dist/{chunk-UYLMNVY6.js → chunk-R3KHKU7M.js} +16 -9
  204. package/dist/chunk-R3KHKU7M.js.map +1 -0
  205. package/dist/{chunk-JBPKEARU.js → chunk-RKNJBZ55.js} +4 -4
  206. package/dist/{chunk-WDISJRMG.js → chunk-RMMVQQA6.js} +2 -2
  207. package/dist/{chunk-JVLCVFQ4.js → chunk-RNHVVMFN.js} +3 -3
  208. package/dist/{chunk-QJAQNXWI.js → chunk-RVO6TCTU.js} +81 -84
  209. package/dist/chunk-RVO6TCTU.js.map +1 -0
  210. package/dist/chunk-S2HLHAZ4.js +16 -0
  211. package/dist/chunk-S2HLHAZ4.js.map +1 -0
  212. package/dist/{chunk-KWMXR7XS.js → chunk-S2V7RUCL.js} +8 -1
  213. package/dist/{chunk-KWMXR7XS.js.map → chunk-S2V7RUCL.js.map} +1 -1
  214. package/dist/{chunk-5SM35XZR.js → chunk-S5NZBKKQ.js} +2 -2
  215. package/dist/{chunk-VNA7W7QF.js → chunk-SVH57F5Z.js} +12 -4
  216. package/dist/chunk-SVH57F5Z.js.map +1 -0
  217. package/dist/{chunk-WIPEXG6R.js → chunk-SXIMQLGV.js} +2 -2
  218. package/dist/{chunk-RVLJEII5.js → chunk-SYUBB3WM.js} +256 -187
  219. package/dist/chunk-SYUBB3WM.js.map +1 -0
  220. package/dist/{chunk-VCD4PSK2.js → chunk-TQZ4DVBC.js} +7 -4
  221. package/dist/chunk-TQZ4DVBC.js.map +1 -0
  222. package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
  223. package/dist/{chunk-YV32N67O.js → chunk-URS5GSM7.js} +1 -1
  224. package/dist/chunk-URS5GSM7.js.map +1 -0
  225. package/dist/{chunk-4B77XSG5.js → chunk-UV72DEZD.js} +5 -5
  226. package/dist/{chunk-BJKPPZ6Z.js → chunk-UW66OZTD.js} +2 -2
  227. package/dist/{chunk-XYTOI63Z.js → chunk-V2TNYF6Q.js} +19 -11
  228. package/dist/chunk-V2TNYF6Q.js.map +1 -0
  229. package/dist/{chunk-S2BBISHU.js → chunk-VANZKHTN.js} +3 -3
  230. package/dist/chunk-VHFXP27N.js +250 -0
  231. package/dist/chunk-VHFXP27N.js.map +1 -0
  232. package/dist/chunk-VL35ZFSZ.js +102 -0
  233. package/dist/chunk-VL35ZFSZ.js.map +1 -0
  234. package/dist/{chunk-3Y224NYC.js → chunk-VYISFWVX.js} +2 -2
  235. package/dist/{chunk-JE7EK33X.js → chunk-W2V7UESE.js} +2 -2
  236. package/dist/{chunk-TIHMZFIV.js → chunk-W3IC7QOY.js} +3 -3
  237. package/dist/{chunk-NRV4Y3PM.js → chunk-W4FBGYGK.js} +1 -1
  238. package/dist/{chunk-P2BM76KT.js → chunk-WAS4HV46.js} +174 -43
  239. package/dist/chunk-WAS4HV46.js.map +1 -0
  240. package/dist/{chunk-57QKLRBV.js → chunk-WB7JSQCP.js} +2 -1
  241. package/dist/chunk-WB7JSQCP.js.map +1 -0
  242. package/dist/{chunk-A5OJCXZL.js → chunk-WZ3TOIDW.js} +15 -4
  243. package/dist/chunk-WZ3TOIDW.js.map +1 -0
  244. package/dist/{chunk-MU7ZHSZE.js → chunk-WZFAPHIK.js} +2 -2
  245. package/dist/{chunk-T2TTP3KU.js → chunk-X4IDNPOS.js} +2 -2
  246. package/dist/{chunk-UVIKWC7M.js → chunk-XAGYS7X6.js} +17 -17
  247. package/dist/{chunk-BLAKS3CP.js → chunk-XL3TATMJ.js} +3 -3
  248. package/dist/{chunk-W4XJFLAL.js → chunk-XPRJSHNI.js} +2 -2
  249. package/dist/{chunk-5TFP4CUL.js → chunk-XQ3HXAQH.js} +14 -11
  250. package/dist/chunk-XQ3HXAQH.js.map +1 -0
  251. package/dist/{chunk-E6EE5B67.js → chunk-YK6BDDHP.js} +4 -4
  252. package/dist/{chunk-ES36HTSC.js → chunk-YLHM5BQQ.js} +3 -3
  253. package/dist/{chunk-ULARSG5Z.js → chunk-YN6ASZUG.js} +10 -8
  254. package/dist/{chunk-ULARSG5Z.js.map → chunk-YN6ASZUG.js.map} +1 -1
  255. package/dist/{chunk-VOUOLGIP.js → chunk-YRFAYOFQ.js} +11 -13
  256. package/dist/chunk-YRFAYOFQ.js.map +1 -0
  257. package/dist/{chunk-IKKWIPYN.js → chunk-YYQAKIDJ.js} +37 -1
  258. package/dist/chunk-YYQAKIDJ.js.map +1 -0
  259. package/dist/{chunk-GF22HWS2.js → chunk-Z54EM5YZ.js} +4 -4
  260. package/dist/{chunk-64UDOIMI.js → chunk-ZLQ37WJX.js} +2 -2
  261. package/dist/{cli-BUGN3d6_.d.ts → cli-BHBswmUa.d.ts} +5 -5
  262. package/dist/cli.d.ts +16 -12
  263. package/dist/cli.js +138 -123
  264. package/dist/compounding/engine.d.ts +3 -2
  265. package/dist/compounding/engine.js +25 -23
  266. package/dist/compounding/preference-consolidator.d.ts +2 -1
  267. package/dist/compression-optimizer.d.ts +2 -1
  268. package/dist/config.d.ts +2 -1
  269. package/dist/config.js +10 -8
  270. package/dist/connectors/codex-materialize-runner.d.ts +2 -1
  271. package/dist/connectors/codex-materialize-runner.js +24 -22
  272. package/dist/connectors/codex-materialize.d.ts +2 -1
  273. package/dist/connectors/index.d.ts +2 -1
  274. package/dist/connectors/index.js +27 -25
  275. package/dist/consolidation-provenance-check.d.ts +3 -2
  276. package/dist/consolidation-provenance-check.js +4 -4
  277. package/dist/consolidation-undo.d.ts +3 -2
  278. package/dist/consolidation-undo.js +10 -7
  279. package/dist/consolidation-undo.js.map +1 -1
  280. package/dist/contradiction/index.d.ts +3 -2
  281. package/dist/converge-config.d.ts +2 -1
  282. package/dist/convergence-refresh.d.ts +4 -3
  283. package/dist/convergence-refresh.js +28 -26
  284. package/dist/conversation-index/backend.d.ts +2 -1
  285. package/dist/conversation-index/backend.js +2 -2
  286. package/dist/conversation-index/chunker.d.ts +2 -1
  287. package/dist/conversation-index/faiss-adapter.d.ts +2 -1
  288. package/dist/conversation-index/indexer.d.ts +2 -1
  289. package/dist/conversation-index/search.d.ts +2 -1
  290. package/dist/corpus-watermark.d.ts +2 -1
  291. package/dist/corpus-watermark.js +43 -41
  292. package/dist/day-summary.d.ts +2 -1
  293. package/dist/delinearize.d.ts +2 -1
  294. package/dist/direct-answer-wiring.d.ts +2 -1
  295. package/dist/direct-answer-wiring.js +2 -2
  296. package/dist/direct-answer.d.ts +2 -1
  297. package/dist/embedding-fallback.d.ts +2 -1
  298. package/dist/embedding-fallback.js +2 -2
  299. package/dist/enrichment/index.d.ts +2 -1
  300. package/dist/entity-retrieval-boundaries.js +1 -1
  301. package/dist/entity-retrieval.d.ts +3 -2
  302. package/dist/entity-retrieval.js +25 -23
  303. package/dist/entity-schema.d.ts +2 -1
  304. package/dist/explicit-capture.d.ts +9 -8
  305. package/dist/explicit-capture.js +11 -9
  306. package/dist/external-wiki-access.d.ts +127 -0
  307. package/dist/external-wiki-access.js +187 -0
  308. package/dist/external-wiki-access.js.map +1 -0
  309. package/dist/external-wiki-cli.d.ts +13 -0
  310. package/dist/external-wiki-cli.js +10 -0
  311. package/dist/external-wiki-cli.js.map +1 -0
  312. package/dist/external-wiki-collection-registration.d.ts +39 -0
  313. package/dist/external-wiki-collection-registration.js +79 -0
  314. package/dist/external-wiki-collection-registration.js.map +1 -0
  315. package/dist/external-wiki-collection.d.ts +50 -0
  316. package/dist/external-wiki-collection.js +387 -0
  317. package/dist/external-wiki-collection.js.map +1 -0
  318. package/dist/external-wiki-config.d.ts +13 -0
  319. package/dist/external-wiki-config.js +13 -0
  320. package/dist/external-wiki-config.js.map +1 -0
  321. package/dist/external-wiki-guard.d.ts +11 -0
  322. package/dist/external-wiki-guard.js +18 -0
  323. package/dist/external-wiki-guard.js.map +1 -0
  324. package/dist/external-wiki-mcp-tools.d.ts +123 -0
  325. package/dist/external-wiki-mcp-tools.js +8 -0
  326. package/dist/external-wiki-mcp-tools.js.map +1 -0
  327. package/dist/external-wiki-search.d.ts +42 -0
  328. package/dist/external-wiki-search.js +11 -0
  329. package/dist/external-wiki-search.js.map +1 -0
  330. package/dist/external-wiki.d.ts +39 -0
  331. package/dist/external-wiki.js +14 -0
  332. package/dist/external-wiki.js.map +1 -0
  333. package/dist/extraction-error-classification.d.ts +2 -1
  334. package/dist/extraction-faithfulness.d.ts +2 -1
  335. package/dist/extraction-judge-telemetry.d.ts +2 -1
  336. package/dist/extraction-judge-training.d.ts +2 -1
  337. package/dist/extraction-judge.d.ts +2 -1
  338. package/dist/extraction-liveness.d.ts +2 -1
  339. package/dist/extraction-source-grounding-helpers.d.ts +5 -3
  340. package/dist/extraction-source-grounding-helpers.js +1 -1
  341. package/dist/extraction-source-grounding-rules.d.ts +2 -1
  342. package/dist/extraction-source-grounding-rules.js +2 -2
  343. package/dist/extraction-source-grounding.d.ts +2 -1
  344. package/dist/extraction-source-grounding.js +5 -5
  345. package/dist/extraction.d.ts +2 -1
  346. package/dist/extraction.js +46 -43
  347. package/dist/fallback-llm.d.ts +2 -1
  348. package/dist/{first-start-migration-F2QJD66E.js → first-start-migration-ZSHEFEI3.js} +10 -12
  349. package/dist/{first-start-migration-F2QJD66E.js.map → first-start-migration-ZSHEFEI3.js.map} +1 -1
  350. package/dist/graph-dashboard-diff.d.ts +2 -1
  351. package/dist/graph-dashboard-key.d.ts +2 -1
  352. package/dist/graph-dashboard-parser.d.ts +2 -1
  353. package/dist/graph-edge-reinforcement.d.ts +2 -1
  354. package/dist/graph-snapshot.d.ts +2 -1
  355. package/dist/graph.d.ts +2 -1
  356. package/dist/harmonic-retrieval.js +2 -2
  357. package/dist/importance.d.ts +2 -1
  358. package/dist/importers/index.d.ts +2 -1
  359. package/dist/in-flight-reads.d.ts +2 -1
  360. package/dist/index.d.ts +443 -430
  361. package/dist/index.js +304 -269
  362. package/dist/intent.d.ts +2 -1
  363. package/dist/lcm/engine.d.ts +2 -1
  364. package/dist/lcm/engine.js +2 -2
  365. package/dist/lcm/index.d.ts +2 -1
  366. package/dist/lcm/index.js +7 -7
  367. package/dist/lcm/tools.d.ts +2 -1
  368. package/dist/lifecycle.d.ts +2 -1
  369. package/dist/live-connectors-runner.d.ts +2 -1
  370. package/dist/local-llm.d.ts +2 -1
  371. package/dist/local-llm.js +2 -2
  372. package/dist/local-model-endpoint.d.ts +2 -1
  373. package/dist/maintenance/memory-governance.d.ts +2 -1
  374. package/dist/maintenance/memory-governance.js +25 -23
  375. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +3 -2
  376. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +25 -23
  377. package/dist/maintenance/rebuild-memory-projection.d.ts +3 -2
  378. package/dist/maintenance/rebuild-memory-projection.js +27 -25
  379. package/dist/{maintenance-LbuS2rUA.d.ts → maintenance-CoRikzIt.d.ts} +3 -3
  380. package/dist/mcp-memory-inspector-app.d.ts +14 -10
  381. package/dist/mcp-read-only-tools.js +1 -1
  382. package/dist/memory-action-policy.d.ts +2 -1
  383. package/dist/memory-cache.d.ts +2 -1
  384. package/dist/memory-lifecycle-ledger-utils.d.ts +2 -1
  385. package/dist/memory-projection-store.d.ts +2 -1
  386. package/dist/memory-provenance.d.ts +2 -1
  387. package/dist/memory-snapshot.d.ts +10 -0
  388. package/dist/memory-snapshot.js +8 -0
  389. package/dist/memory-snapshot.js.map +1 -0
  390. package/dist/memory-worth-outcomes.d.ts +3 -2
  391. package/dist/models-json.d.ts +2 -1
  392. package/dist/namespaces/migrate.d.ts +4 -3
  393. package/dist/namespaces/migrate.js +41 -39
  394. package/dist/namespaces/principal.d.ts +2 -1
  395. package/dist/namespaces/search.d.ts +2 -1
  396. package/dist/namespaces/search.js +18 -18
  397. package/dist/namespaces/storage.d.ts +4 -3
  398. package/dist/namespaces/storage.js +24 -22
  399. package/dist/native-knowledge.d.ts +2 -1
  400. package/dist/offline-sync-impression-drain.d.ts +2 -1
  401. package/dist/offline-sync-impression-drain.js +11 -9
  402. package/dist/offline-sync.d.ts +29 -3
  403. package/dist/offline-sync.js +6 -2
  404. package/dist/operator-doctor-corpus.d.ts +2 -1
  405. package/dist/operator-doctor-corpus.js +46 -44
  406. package/dist/operator-doctor-replica.d.ts +2 -1
  407. package/dist/operator-doctor-replica.js +3 -3
  408. package/dist/operator-toolkit.d.ts +4 -3
  409. package/dist/operator-toolkit.js +60 -55
  410. package/dist/orchestration/compression-guideline-coordinator.d.ts +3 -2
  411. package/dist/orchestration/maintenance.d.ts +5 -4
  412. package/dist/orchestration/maintenance.js +37 -33
  413. package/dist/{orchestrator-rHiWt32X.d.ts → orchestrator-BJeq7Pw1.d.ts} +14 -7
  414. package/dist/orchestrator.d.ts +9 -8
  415. package/dist/orchestrator.js +200 -186
  416. package/dist/page-versioning.js +3 -3
  417. package/dist/patterns-cli.d.ts +2 -1
  418. package/dist/{pipeline-W_97O8BV.d.ts → pipeline-CNjY4wk3.d.ts} +1 -1
  419. package/dist/policy-runtime.d.ts +2 -1
  420. package/dist/policy-runtime.js +1 -1
  421. package/dist/proactive-contention.d.ts +2 -1
  422. package/dist/provenance.d.ts +2 -1
  423. package/dist/provenance.js +2 -2
  424. package/dist/{qmd-LWtMofAf.d.ts → qmd-C0UDZidt.d.ts} +9 -7
  425. package/dist/qmd-preflight.d.ts +5 -4
  426. package/dist/qmd-preflight.js +2 -2
  427. package/dist/qmd-recall-cache.d.ts +2 -1
  428. package/dist/qmd.d.ts +4 -3
  429. package/dist/qmd.js +8 -8
  430. package/dist/recall-concurrency-config.d.ts +2 -1
  431. package/dist/recall-disclosure-escalation.d.ts +2 -1
  432. package/dist/recall-explain-renderer.d.ts +2 -1
  433. package/dist/recall-explain-renderer.js +3 -3
  434. package/dist/recall-memory-map.d.ts +2 -1
  435. package/dist/recall-planner-llm.d.ts +2 -1
  436. package/dist/recall-state.d.ts +2 -1
  437. package/dist/recall-tag-filter.d.ts +2 -1
  438. package/dist/recall-timings.d.ts +2 -1
  439. package/dist/recall-xray-cli.d.ts +2 -1
  440. package/dist/recall-xray-cli.js +4 -4
  441. package/dist/recall-xray-renderer.d.ts +2 -1
  442. package/dist/recall-xray-renderer.js +3 -3
  443. package/dist/recall-xray.d.ts +8 -1
  444. package/dist/recall-xray.js +2 -2
  445. package/dist/reconcile/cursor.d.ts +12 -2
  446. package/dist/reconcile/cursor.js +46 -7
  447. package/dist/reconcile/cursor.js.map +1 -1
  448. package/dist/reconcile/manifest.d.ts +9 -2
  449. package/dist/reconcile/manifest.js +15 -268
  450. package/dist/reconcile/manifest.js.map +1 -1
  451. package/dist/reconcile/plan.d.ts +4 -1
  452. package/dist/reconcile/plan.js +4 -4
  453. package/dist/replay/normalizers/chatgpt.d.ts +2 -1
  454. package/dist/replay/normalizers/claude.d.ts +2 -1
  455. package/dist/replay/normalizers/openclaw.d.ts +2 -1
  456. package/dist/replay/normalizers/shared.d.ts +2 -1
  457. package/dist/replay/runner.d.ts +2 -1
  458. package/dist/replay/types.d.ts +2 -1
  459. package/dist/replica-divergence.d.ts +2 -1
  460. package/dist/replica-divergence.js +2 -2
  461. package/dist/replica-peers-config.d.ts +2 -1
  462. package/dist/resolve-auth-token.d.ts +2 -1
  463. package/dist/resume-bundles.js +12 -10
  464. package/dist/retrieval-agents.d.ts +4 -3
  465. package/dist/retrieval-agents.js +2 -2
  466. package/dist/retrieval-tiers.d.ts +2 -1
  467. package/dist/routing/engine.d.ts +2 -1
  468. package/dist/routing/store.d.ts +2 -1
  469. package/dist/salvage-envelope.d.ts +2 -1
  470. package/dist/schemas.d.ts +54 -54
  471. package/dist/{scope-profiles-BiQKOE-p.d.ts → scope-profiles-BJzp2F5A.d.ts} +1 -1
  472. package/dist/search/embed-helper.d.ts +2 -1
  473. package/dist/search/embed-helper.js +3 -3
  474. package/dist/search/factory.d.ts +4 -2
  475. package/dist/search/factory.js +20 -18
  476. package/dist/search/index.d.ts +2 -1
  477. package/dist/search/index.js +20 -20
  478. package/dist/search/lancedb-backend.d.ts +2 -1
  479. package/dist/search/lancedb-backend.js +4 -4
  480. package/dist/search/meilisearch-backend.d.ts +2 -1
  481. package/dist/search/meilisearch-backend.js +4 -4
  482. package/dist/search/noop-backend.d.ts +2 -1
  483. package/dist/search/orama-backend.d.ts +2 -1
  484. package/dist/search/orama-backend.js +4 -4
  485. package/dist/search/port.d.ts +18 -1
  486. package/dist/search/port.js +1 -1
  487. package/dist/search/remote-backend.d.ts +2 -1
  488. package/dist/search/remote-backend.js +2 -2
  489. package/dist/secure-store/index.js +2 -2
  490. package/dist/{semantic-consolidation-dHYCyqgh.d.ts → semantic-consolidation-D4KAZO2G.d.ts} +1 -1
  491. package/dist/semantic-consolidation.d.ts +3 -2
  492. package/dist/semantic-consolidation.js +26 -24
  493. package/dist/semantic-rule-promotion.js +24 -22
  494. package/dist/semantic-rule-verifier.d.ts +2 -1
  495. package/dist/semantic-rule-verifier.js +25 -23
  496. package/dist/{service-DJG3KCQ4.d.ts → service-DWC4tq7p.d.ts} +2 -2
  497. package/dist/session-observer-bands.d.ts +2 -1
  498. package/dist/session-observer-state.d.ts +2 -1
  499. package/dist/shared-context/manager.d.ts +10 -9
  500. package/dist/shared-context/manager.js +2 -2
  501. package/dist/signal.d.ts +2 -1
  502. package/dist/source-agent-qualifier.d.ts +2 -1
  503. package/dist/source-agent-qualifier.js +43 -40
  504. package/dist/{storage-F9FVh-w9.d.ts → storage-DPGjB-8e.d.ts} +28 -13
  505. package/dist/storage.d.ts +3 -2
  506. package/dist/storage.js +26 -24
  507. package/dist/summarizer.d.ts +2 -1
  508. package/dist/summarizer.js +5 -5
  509. package/dist/summary-snapshot.d.ts +2 -1
  510. package/dist/temporal-supersession.d.ts +3 -2
  511. package/dist/temporal-timeline-recall.d.ts +2 -1
  512. package/dist/temporal-validity.d.ts +2 -1
  513. package/dist/threading.d.ts +2 -1
  514. package/dist/tier-migration.d.ts +3 -2
  515. package/dist/tier-migration.js +1 -1
  516. package/dist/tier-routing.d.ts +2 -1
  517. package/dist/tool-scoped-memory.d.ts +5 -1
  518. package/dist/tool-scoped-memory.js +3 -1
  519. package/dist/topics.d.ts +2 -1
  520. package/dist/transcript.d.ts +2 -1
  521. package/dist/transfer/capsule-import.js +4 -4
  522. package/dist/transfer/types.d.ts +66 -66
  523. package/dist/trust-score-stage.d.ts +2 -1
  524. package/dist/trust-score.d.ts +2 -1
  525. package/dist/{types-rEwubvim.d.ts → types-yX_FwERf.d.ts} +8 -1
  526. package/dist/types.d.ts +2 -1
  527. package/dist/types.js +1 -1
  528. package/dist/utility-runtime.d.ts +2 -1
  529. package/dist/verified-recall.js +25 -23
  530. package/dist/write-envelope.d.ts +2 -1
  531. package/package.json +2 -2
  532. package/src/abort-error.ts +17 -0
  533. package/src/access-admin-ops-surface.ts +1 -0
  534. package/src/access-boundary.ts +1 -0
  535. package/src/access-coding-context-resolution.ts +42 -0
  536. package/src/access-extraction-force-flush.ts +38 -2
  537. package/src/access-http-lcm-compaction.ts +5 -2
  538. package/src/access-http-offline-stream.ts +80 -0
  539. package/src/access-http.test.ts +310 -3
  540. package/src/access-http.ts +84 -77
  541. package/src/access-mcp-output-schemas.ts +36 -0
  542. package/src/access-mcp.test.ts +95 -1
  543. package/src/access-mcp.ts +7 -9
  544. package/src/access-observe-helpers.ts +64 -22
  545. package/src/access-observe-write-surface.ts +8 -0
  546. package/src/access-offline-manifest.ts +54 -0
  547. package/src/access-operations-batch.ts +3 -3
  548. package/src/access-operations.ts +13 -7
  549. package/src/access-recall-concurrency.ts +3 -27
  550. package/src/access-recall-surface.ts +3 -0
  551. package/src/access-service-health.test.ts +32 -7
  552. package/src/access-service-namespace.test.ts +55 -0
  553. package/src/access-service-observe-idempotency.test.ts +34 -2
  554. package/src/access-service-observe-lcm-parity.test.ts +183 -23
  555. package/src/access-service-observe-scope.test.ts +160 -1
  556. package/src/access-service-offline-file-content.test.ts +345 -1
  557. package/src/access-service.ts +88 -62
  558. package/src/access-surface-catalog.ts +4 -0
  559. package/src/admin/admin-surfaces.ts +2 -0
  560. package/src/binary-lifecycle/pipeline.test.ts +106 -1
  561. package/src/binary-lifecycle/pipeline.ts +3 -0
  562. package/src/coding/git-context.test.ts +47 -0
  563. package/src/coding/git-context.ts +129 -27
  564. package/src/config.test.ts +24 -0
  565. package/src/config.ts +9 -12
  566. package/src/connector-provenance.test.ts +101 -0
  567. package/src/consolidation-undo.ts +3 -0
  568. package/src/convergence-refresh.ts +14 -2
  569. package/src/correction/correction-access-wiring.ts +9 -7
  570. package/src/correction/correction-executor.test.ts +206 -2
  571. package/src/correction/correction-executor.ts +29 -20
  572. package/src/correction/correction-planner.test.ts +36 -0
  573. package/src/correction/correction-planner.ts +9 -15
  574. package/src/correction/correction-service.ts +3 -1
  575. package/src/correction/correction-storage-integration.test.ts +77 -0
  576. package/src/correction/correction-surfaces.test.ts +41 -28
  577. package/src/correction/passive-capture.test.ts +59 -0
  578. package/src/correction/passive-capture.ts +4 -1
  579. package/src/entity-retrieval-boundaries.ts +17 -4
  580. package/src/entity-retrieval.ts +27 -6
  581. package/src/external-wiki-access.test.ts +65 -0
  582. package/src/external-wiki-access.ts +31 -0
  583. package/src/external-wiki-cli.ts +100 -0
  584. package/src/external-wiki-collection-registration.test.ts +163 -0
  585. package/src/external-wiki-collection-registration.ts +101 -0
  586. package/src/external-wiki-collection.test.ts +502 -0
  587. package/src/external-wiki-collection.ts +503 -0
  588. package/src/external-wiki-config.test.ts +135 -0
  589. package/src/external-wiki-config.ts +100 -0
  590. package/src/external-wiki-guard.ts +83 -0
  591. package/src/external-wiki-mcp-tools.ts +23 -0
  592. package/src/external-wiki-search.test.ts +367 -0
  593. package/src/external-wiki-search.ts +362 -0
  594. package/src/external-wiki.test.ts +240 -0
  595. package/src/external-wiki.ts +427 -0
  596. package/src/extraction-scope-source-agent.test.ts +21 -0
  597. package/src/extraction-source-grounding-helpers.ts +243 -53
  598. package/src/extraction-source-grounding-rules.ts +133 -39
  599. package/src/extraction-source-grounding.test.ts +363 -33
  600. package/src/extraction-timeout.test.ts +1 -0
  601. package/src/extraction-watermark.test.ts +150 -7
  602. package/src/extraction.ts +8 -1
  603. package/src/index.ts +9 -5
  604. package/src/maintenance/first-start-migration.ts +11 -11
  605. package/src/mcp-read-only-tools.ts +1 -0
  606. package/src/memory-snapshot.ts +15 -0
  607. package/src/offline-sync.test.ts +194 -0
  608. package/src/offline-sync.ts +217 -13
  609. package/src/orchestration/external-wiki-recall-guard.test.ts +94 -0
  610. package/src/orchestration/extraction-persist.ts +19 -2
  611. package/src/orchestration/extraction-run-helpers.ts +37 -19
  612. package/src/orchestration/extraction-run.test.ts +171 -2
  613. package/src/orchestration/extraction-run.ts +11 -13
  614. package/src/orchestration/extraction-watermark.ts +106 -17
  615. package/src/orchestration/generic-recall-paths.ts +14 -0
  616. package/src/orchestration/orchestrator-helpers.ts +2 -0
  617. package/src/orchestration/orchestrator-init.ts +9 -0
  618. package/src/orchestration/recall-internal-deps.ts +6 -0
  619. package/src/orchestration/recall-internal.ts +154 -33
  620. package/src/orchestration/recall-rerank-coordinator.ts +60 -25
  621. package/src/orchestration/recall-search-pipeline.test.ts +75 -1
  622. package/src/orchestration/recall-search-pipeline.ts +50 -10
  623. package/src/orchestrator-convergence-refresh.test.ts +36 -2
  624. package/src/orchestrator.ts +13 -3
  625. package/src/page-versioning.ts +5 -19
  626. package/src/procedural/procedure-recall.ts +5 -1
  627. package/src/provenance-surfaces.test.ts +3 -0
  628. package/src/qmd-client.test.ts +78 -17
  629. package/src/qmd.test.ts +24 -0
  630. package/src/qmd.ts +224 -315
  631. package/src/recall-explain-renderer.ts +3 -0
  632. package/src/recall-rerank-coordinator.test.ts +61 -0
  633. package/src/recall-xray-renderer.test.ts +6 -0
  634. package/src/recall-xray.test.ts +88 -1
  635. package/src/recall-xray.ts +15 -0
  636. package/src/reconcile/cursor.test.ts +48 -0
  637. package/src/reconcile/cursor.ts +58 -11
  638. package/src/reconcile/manifest.test.ts +4 -0
  639. package/src/reconcile/manifest.ts +41 -51
  640. package/src/reconcile/plan.test.ts +4 -0
  641. package/src/reconcile/plan.ts +28 -16
  642. package/src/search/factory.ts +6 -6
  643. package/src/search/port.ts +25 -9
  644. package/src/secure-store/secure-fs.ts +20 -12
  645. package/src/secure-store/secure-store.test.ts +41 -2
  646. package/src/spaces/index.test.ts +61 -2
  647. package/src/spaces/index.ts +44 -18
  648. package/src/storage/entity-alias-config.ts +97 -0
  649. package/src/storage/entity-canonical-id-lock.ts +53 -23
  650. package/src/storage/entity-canonical-id-migration.ts +53 -22
  651. package/src/storage/entity-canonical-id-references.ts +3 -0
  652. package/src/storage/entity-id-safety.ts +7 -0
  653. package/src/storage/entity-store.ts +6 -2
  654. package/src/storage/memory-frontmatter-metadata.ts +4 -9
  655. package/src/storage/memory-migration-serialization.ts +10 -15
  656. package/src/storage/tombstone-blocked-capture-mutation.ts +52 -64
  657. package/src/storage/tombstone-blocked-capture-sync.ts +244 -199
  658. package/src/storage-contract/cache-coherence.test.ts +99 -0
  659. package/src/storage-deletion-revisions.test.ts +91 -0
  660. package/src/storage-fact-hash-index-defer.test.ts +460 -170
  661. package/src/storage.ts +572 -284
  662. package/src/testing/subjects/first-start-tier-migration.test.ts +75 -0
  663. package/src/tier-migration.ts +10 -12
  664. package/src/tool-scoped-memory.ts +10 -0
  665. package/src/transfer/capsule-import.ts +13 -0
  666. package/src/transfer/capsule-merge.ts +13 -0
  667. package/src/trust-score-recall-paths.test.ts +75 -1
  668. package/src/types.ts +7 -3
  669. package/dist/capsule-merge-IDWJPCWK.js.map +0 -1
  670. package/dist/chunk-3CE77VAP.js.map +0 -1
  671. package/dist/chunk-3TBLDMJA.js.map +0 -1
  672. package/dist/chunk-4J7G5SY4.js.map +0 -1
  673. package/dist/chunk-57QKLRBV.js.map +0 -1
  674. package/dist/chunk-5TFP4CUL.js.map +0 -1
  675. package/dist/chunk-7XC2HX75.js.map +0 -1
  676. package/dist/chunk-A5OJCXZL.js.map +0 -1
  677. package/dist/chunk-BUE5E2HL.js.map +0 -1
  678. package/dist/chunk-CJ2ZR7UA.js.map +0 -1
  679. package/dist/chunk-CUM2BBPN.js.map +0 -1
  680. package/dist/chunk-D3J5SLQK.js.map +0 -1
  681. package/dist/chunk-DL7ZD3JH.js.map +0 -1
  682. package/dist/chunk-DLVPUX7U.js.map +0 -1
  683. package/dist/chunk-E6PNLPGJ.js.map +0 -1
  684. package/dist/chunk-ECK75GDJ.js.map +0 -1
  685. package/dist/chunk-HREE4JHI.js.map +0 -1
  686. package/dist/chunk-HZFHQ4AQ.js.map +0 -1
  687. package/dist/chunk-IKKWIPYN.js.map +0 -1
  688. package/dist/chunk-J7VGGECD.js.map +0 -1
  689. package/dist/chunk-N5Z4EVOR.js.map +0 -1
  690. package/dist/chunk-NVRYW264.js.map +0 -1
  691. package/dist/chunk-P2BM76KT.js.map +0 -1
  692. package/dist/chunk-PVGDJXVK.js +0 -21
  693. package/dist/chunk-QJAQNXWI.js.map +0 -1
  694. package/dist/chunk-RN7DY3FC.js.map +0 -1
  695. package/dist/chunk-RVLJEII5.js.map +0 -1
  696. package/dist/chunk-S2NCTZGJ.js.map +0 -1
  697. package/dist/chunk-TDHTVMPG.js.map +0 -1
  698. package/dist/chunk-UYLMNVY6.js.map +0 -1
  699. package/dist/chunk-VCD4PSK2.js.map +0 -1
  700. package/dist/chunk-VNA7W7QF.js.map +0 -1
  701. package/dist/chunk-VOUOLGIP.js.map +0 -1
  702. package/dist/chunk-VWAXN2BN.js.map +0 -1
  703. package/dist/chunk-WOCNN776.js.map +0 -1
  704. package/dist/chunk-XYTOI63Z.js.map +0 -1
  705. package/dist/chunk-YV32N67O.js.map +0 -1
  706. /package/dist/{auto-sync-5OE5QOZB.js.map → auto-sync-UPTUVE4X.js.map} +0 -0
  707. /package/dist/{chunk-E5UK4VPE.js.map → chunk-2FSTB6BJ.js.map} +0 -0
  708. /package/dist/{chunk-5ZE7QHTK.js.map → chunk-2X2T2UVE.js.map} +0 -0
  709. /package/dist/{chunk-P4DRWEYC.js.map → chunk-3COYXTGM.js.map} +0 -0
  710. /package/dist/{chunk-5IVLTFOV.js.map → chunk-44N6ESJ4.js.map} +0 -0
  711. /package/dist/{chunk-HO3QBJEY.js.map → chunk-5546W5SI.js.map} +0 -0
  712. /package/dist/{chunk-AAIUERNB.js.map → chunk-5QJQHBLE.js.map} +0 -0
  713. /package/dist/{chunk-6CZPDBJS.js.map → chunk-5U7ID3EZ.js.map} +0 -0
  714. /package/dist/{chunk-DNWXFTLD.js.map → chunk-A4IJCD2Z.js.map} +0 -0
  715. /package/dist/{chunk-PKNLM44P.js.map → chunk-AC5OWJLV.js.map} +0 -0
  716. /package/dist/{chunk-LZ4LDKHZ.js.map → chunk-AMAUBUKY.js.map} +0 -0
  717. /package/dist/{chunk-S5SLVSVY.js.map → chunk-BQIFZ2MP.js.map} +0 -0
  718. /package/dist/{chunk-Q6IP2ARR.js.map → chunk-CSOYVTRX.js.map} +0 -0
  719. /package/dist/{chunk-XOQSEF7X.js.map → chunk-CVILPI77.js.map} +0 -0
  720. /package/dist/{chunk-4LMA77JH.js.map → chunk-E5XQIWAL.js.map} +0 -0
  721. /package/dist/{chunk-WUNIWKY4.js.map → chunk-ELIL2A37.js.map} +0 -0
  722. /package/dist/{chunk-OQ5PRDDS.js.map → chunk-ERZ2R42X.js.map} +0 -0
  723. /package/dist/{chunk-U7GW7NE7.js.map → chunk-FIK3CQNA.js.map} +0 -0
  724. /package/dist/{chunk-33PLLLL7.js.map → chunk-GFCVUY6G.js.map} +0 -0
  725. /package/dist/{chunk-VUPTKTDV.js.map → chunk-GUAL4PQH.js.map} +0 -0
  726. /package/dist/{chunk-CINZGPSJ.js.map → chunk-GUMZC2BO.js.map} +0 -0
  727. /package/dist/{chunk-H24WNPA2.js.map → chunk-GWFSVJ4P.js.map} +0 -0
  728. /package/dist/{chunk-TSH56VPU.js.map → chunk-HAYSYUAB.js.map} +0 -0
  729. /package/dist/{chunk-PDLBLTOK.js.map → chunk-HC3PBX23.js.map} +0 -0
  730. /package/dist/{chunk-KXB4VXHY.js.map → chunk-JIYDRBVZ.js.map} +0 -0
  731. /package/dist/{chunk-HLPD7B7P.js.map → chunk-JZH4LWHB.js.map} +0 -0
  732. /package/dist/{chunk-AV5ZEH4M.js.map → chunk-KVJRXN2E.js.map} +0 -0
  733. /package/dist/{chunk-WFTIGIIS.js.map → chunk-L6CQ7WIW.js.map} +0 -0
  734. /package/dist/{chunk-227UFSEQ.js.map → chunk-LEPOP46W.js.map} +0 -0
  735. /package/dist/{chunk-EJUEXZHX.js.map → chunk-LLJMAULE.js.map} +0 -0
  736. /package/dist/{chunk-QN25OCUF.js.map → chunk-LPYDOLSM.js.map} +0 -0
  737. /package/dist/{chunk-AS7YMSL6.js.map → chunk-M23RF3LJ.js.map} +0 -0
  738. /package/dist/{chunk-OAEQLRCY.js.map → chunk-MO4HSXHZ.js.map} +0 -0
  739. /package/dist/{chunk-3F2LKUMU.js.map → chunk-NIS256NW.js.map} +0 -0
  740. /package/dist/{chunk-YIAA2X3D.js.map → chunk-NK5RGJ65.js.map} +0 -0
  741. /package/dist/{chunk-7TWUCYER.js.map → chunk-PNRA7FAD.js.map} +0 -0
  742. /package/dist/{chunk-5I4M26Q7.js.map → chunk-QBSFOKY6.js.map} +0 -0
  743. /package/dist/{chunk-E53DSZEN.js.map → chunk-QR6G5KF4.js.map} +0 -0
  744. /package/dist/{chunk-4UH4BTGK.js.map → chunk-QVJPH7SH.js.map} +0 -0
  745. /package/dist/{chunk-JBPKEARU.js.map → chunk-RKNJBZ55.js.map} +0 -0
  746. /package/dist/{chunk-WDISJRMG.js.map → chunk-RMMVQQA6.js.map} +0 -0
  747. /package/dist/{chunk-JVLCVFQ4.js.map → chunk-RNHVVMFN.js.map} +0 -0
  748. /package/dist/{chunk-5SM35XZR.js.map → chunk-S5NZBKKQ.js.map} +0 -0
  749. /package/dist/{chunk-WIPEXG6R.js.map → chunk-SXIMQLGV.js.map} +0 -0
  750. /package/dist/{chunk-7K5Q6COX.js.map → chunk-TVVEYCNW.js.map} +0 -0
  751. /package/dist/{chunk-4B77XSG5.js.map → chunk-UV72DEZD.js.map} +0 -0
  752. /package/dist/{chunk-BJKPPZ6Z.js.map → chunk-UW66OZTD.js.map} +0 -0
  753. /package/dist/{chunk-S2BBISHU.js.map → chunk-VANZKHTN.js.map} +0 -0
  754. /package/dist/{chunk-3Y224NYC.js.map → chunk-VYISFWVX.js.map} +0 -0
  755. /package/dist/{chunk-JE7EK33X.js.map → chunk-W2V7UESE.js.map} +0 -0
  756. /package/dist/{chunk-TIHMZFIV.js.map → chunk-W3IC7QOY.js.map} +0 -0
  757. /package/dist/{chunk-NRV4Y3PM.js.map → chunk-W4FBGYGK.js.map} +0 -0
  758. /package/dist/{chunk-MU7ZHSZE.js.map → chunk-WZFAPHIK.js.map} +0 -0
  759. /package/dist/{chunk-T2TTP3KU.js.map → chunk-X4IDNPOS.js.map} +0 -0
  760. /package/dist/{chunk-UVIKWC7M.js.map → chunk-XAGYS7X6.js.map} +0 -0
  761. /package/dist/{chunk-BLAKS3CP.js.map → chunk-XL3TATMJ.js.map} +0 -0
  762. /package/dist/{chunk-W4XJFLAL.js.map → chunk-XPRJSHNI.js.map} +0 -0
  763. /package/dist/{chunk-E6EE5B67.js.map → chunk-YK6BDDHP.js.map} +0 -0
  764. /package/dist/{chunk-ES36HTSC.js.map → chunk-YLHM5BQQ.js.map} +0 -0
  765. /package/dist/{chunk-GF22HWS2.js.map → chunk-Z54EM5YZ.js.map} +0 -0
  766. /package/dist/{chunk-64UDOIMI.js.map → chunk-ZLQ37WJX.js.map} +0 -0
@@ -1,3 +1,4 @@
1
+ import { createHash } from "node:crypto";
1
2
  import assert from "node:assert/strict";
2
3
  import { mkdtemp, mkdir, readFile, readdir, rename, rm, stat, utimes, writeFile } from "node:fs/promises";
3
4
  import { existsSync } from "node:fs";
@@ -10,8 +11,12 @@ import {
10
11
  buildExplicitCaptureDedupKey,
11
12
  TombstoneBlockedCaptureIndex,
12
13
  } from "./storage/tombstone-blocked-capture-index.js";
13
- import { TombstoneBlockedCaptureWriteLock } from "./storage/tombstone-blocked-capture-mutation.js";
14
- import { isEncryptedFile } from "./secure-store/secure-fs.js";
14
+ import {
15
+ buildCapturePathLockIdentity,
16
+ runTombstoneBlockedMutation,
17
+ TombstoneBlockedCaptureWriteLock,
18
+ } from "./storage/tombstone-blocked-capture-mutation.js";
19
+ import { isEncryptedFile, SECURE_STORE_ENVELOPE_OVERHEAD_BYTES } from "./secure-store/secure-fs.js";
15
20
  import type { MemoryFile } from "./types.js";
16
21
 
17
22
  // Issue #1909 (Part B): writeMemory("fact") used to rewrite the whole
@@ -26,7 +31,7 @@ async function withMemoryDir(run: (dir: string) => Promise<void>): Promise<void>
26
31
  try {
27
32
  await run(dir);
28
33
  } finally {
29
- await rm(dir, { recursive: true, force: true });
34
+ await rm(dir, { recursive: true, force: true, maxRetries: 5, retryDelay: 50 });
30
35
  }
31
36
  }
32
37
 
@@ -54,6 +59,171 @@ test("capture write locks combine streamed hashes in canonical order", async ()
54
59
  );
55
60
  });
56
61
  });
62
+ test("active mutations recheck queued-review replacements inside coordinated identity locks", async () => {
63
+ const pathname = "/memory/facts/active.md";
64
+ const active = {
65
+ path: pathname,
66
+ content: "active content",
67
+ frontmatter: { id: "active", category: "fact", status: "active" },
68
+ } as MemoryFile;
69
+ const queued = {
70
+ path: pathname,
71
+ content: "queued content",
72
+ frontmatter: {
73
+ id: "queued",
74
+ category: "fact",
75
+ status: "pending_review",
76
+ tags: ["queued-review"],
77
+ sourceConnector: "provider-a",
78
+ },
79
+ } as MemoryFile;
80
+ const activeIdentity = buildExplicitCaptureDedupKey(
81
+ active.content,
82
+ active.frontmatter.category,
83
+ active.frontmatter.sourceConnector
84
+ );
85
+ const queuedIdentity = buildExplicitCaptureDedupKey(
86
+ queued.content,
87
+ queued.frontmatter.category,
88
+ queued.frontmatter.sourceConnector
89
+ );
90
+ let current = active;
91
+ const lockIdentities: string[][] = [];
92
+ let writes = 0;
93
+
94
+ await runTombstoneBlockedMutation(
95
+ {
96
+ readCurrent: async () => current,
97
+ isBlocked: () => false,
98
+ isQueuedReview: (memory) => memory?.frontmatter.id === queued.frontmatter.id,
99
+ memoryIdentity: (memory) => (memory.frontmatter.id === active.frontmatter.id ? activeIdentity : queuedIdentity),
100
+ prepareWrite: async () => "marker",
101
+ commitWrite: async () => {},
102
+ discardWrite: async () => {},
103
+ markUntrusted: () => {},
104
+ writeStorageSecureFile: async () => {
105
+ assert.equal(lockIdentities.length, 2);
106
+ assert.ok(lockIdentities[1]?.includes(queuedIdentity));
107
+ writes += 1;
108
+ },
109
+ withCaptureWriteLock: async (task, identity) => {
110
+ const identities = Array.isArray(identity) ? [...identity] : [identity];
111
+ lockIdentities.push(identities);
112
+ if (lockIdentities.length === 1) current = queued;
113
+ await task();
114
+ },
115
+ logWarning: () => {},
116
+ },
117
+ {
118
+ blocked: false,
119
+ pathname,
120
+ fileContent: "replacement",
121
+ identity: [
122
+ buildCapturePathLockIdentity(pathname),
123
+ activeIdentity,
124
+ buildExplicitCaptureDedupKey("replacement", "fact", undefined),
125
+ ],
126
+ updateIndex: async () => {},
127
+ }
128
+ );
129
+
130
+ assert.equal(writes, 1);
131
+ assert.equal(lockIdentities.length, 2);
132
+ assert.ok(lockIdentities[0]?.includes(activeIdentity));
133
+ assert.ok(lockIdentities[0]?.includes(buildCapturePathLockIdentity(pathname)));
134
+ });
135
+
136
+ test("shared memory writes include their pathname in the capture lock union", async () => {
137
+ await withMemoryDir(async (dir) => {
138
+ const storage = new StorageManager(dir);
139
+ await storage.ensureDirectories();
140
+ const storageWithOverride = storage as unknown as {
141
+ withTombstoneBlockedCaptureWriteLock: (
142
+ task: () => Promise<unknown>,
143
+ identity?: string | readonly string[]
144
+ ) => Promise<unknown>;
145
+ };
146
+ const originalLock = storageWithOverride.withTombstoneBlockedCaptureWriteLock.bind(storage);
147
+ const captured: Array<string | readonly string[] | undefined> = [];
148
+ storageWithOverride.withTombstoneBlockedCaptureWriteLock = async (task, identity) => {
149
+ captured.push(identity);
150
+ return await originalLock(task, identity);
151
+ };
152
+ try {
153
+ const written = await storage.writeMemory("fact", "Every writer shares the deterministic pathname lock.", {
154
+ source: "test",
155
+ });
156
+ const memory = await storage.getMemoryById(written.id);
157
+ assert.ok(memory);
158
+ const pathIdentity = buildCapturePathLockIdentity(memory.path);
159
+ assert.ok(captured.some((identity) => (Array.isArray(identity) ? identity : [identity]).includes(pathIdentity)));
160
+ } finally {
161
+ storageWithOverride.withTombstoneBlockedCaptureWriteLock = originalLock;
162
+ }
163
+ });
164
+ });
165
+
166
+ test("offline sync reserves a marker when its locked snapshot became blocked with the same identity", async () => {
167
+ await withMemoryDir(async (dir) => {
168
+ const storage = new StorageManager(dir);
169
+ await storage.ensureDirectories();
170
+ const target = path.join(dir, "memory", "facts", "same-identity.md");
171
+ const active = {
172
+ path: target,
173
+ content: "Same identity, different review state.",
174
+ frontmatter: {
175
+ id: "same-identity",
176
+ category: "fact",
177
+ status: "active",
178
+ sourceConnector: "provider-a",
179
+ },
180
+ } as MemoryFile;
181
+ const blocked = {
182
+ ...active,
183
+ frontmatter: {
184
+ ...active.frontmatter,
185
+ status: "pending_review",
186
+ blockedBy: "same-identity-tombstone",
187
+ },
188
+ } as MemoryFile;
189
+ let readCount = 0;
190
+ let prepared = 0;
191
+ const fakeIndex = {
192
+ withCaptureWriteLock: async <T>(task: () => Promise<T>) => await task(),
193
+ prepareWrite: async () => {
194
+ prepared += 1;
195
+ return "same-identity-marker";
196
+ },
197
+ commitWrite: async () => {},
198
+ discardWrite: async () => {},
199
+ markUntrusted: () => {},
200
+ };
201
+ const storageWithOverrides = storage as unknown as {
202
+ readMemoryByPath: (pathname: string) => Promise<MemoryFile | null>;
203
+ getTombstoneBlockedCaptureIndex: () => typeof fakeIndex;
204
+ invalidateAfterOfflineSyncMutation: (pathname: string, marker?: string) => Promise<void>;
205
+ runTombstoneBlockedOfflineSyncMutation: (
206
+ pathname: string,
207
+ after: MemoryFile | null,
208
+ write: () => Promise<void>
209
+ ) => Promise<void>;
210
+ };
211
+ const originalRead = storageWithOverrides.readMemoryByPath.bind(storage);
212
+ const originalIndex = storageWithOverrides.getTombstoneBlockedCaptureIndex.bind(storage);
213
+ const originalInvalidate = storageWithOverrides.invalidateAfterOfflineSyncMutation.bind(storage);
214
+ storageWithOverrides.readMemoryByPath = async () => (readCount++ === 0 ? active : blocked);
215
+ storageWithOverrides.getTombstoneBlockedCaptureIndex = () => fakeIndex;
216
+ storageWithOverrides.invalidateAfterOfflineSyncMutation = async () => {};
217
+ try {
218
+ await storageWithOverrides.runTombstoneBlockedOfflineSyncMutation(target, active, async () => {});
219
+ assert.equal(prepared, 1);
220
+ } finally {
221
+ storageWithOverrides.readMemoryByPath = originalRead;
222
+ storageWithOverrides.getTombstoneBlockedCaptureIndex = originalIndex;
223
+ storageWithOverrides.invalidateAfterOfflineSyncMutation = originalInvalidate;
224
+ }
225
+ });
226
+ });
57
227
 
58
228
  test("deferred fact writes do NO per-fact index saves; a single flush persists all", async () => {
59
229
  await withMemoryDir(async (dir) => {
@@ -1662,6 +1832,45 @@ test("blocked chunk writes recheck identity after waiting on the capture lock",
1662
1832
  });
1663
1833
  });
1664
1834
 
1835
+ test("chunk rewrites reacquire discovered identities in canonical lock order", async () => {
1836
+ await withMemoryDir(async (dir) => {
1837
+ const storage = new StorageManager(dir);
1838
+ await storage.ensureDirectories();
1839
+ let queuedContent = "";
1840
+ let blockedContent = "";
1841
+ for (let index = 0; index < 100 && queuedContent.length === 0; index += 1) {
1842
+ const queuedCandidate = `queued identity ${index}`;
1843
+ const blockedCandidate = `blocked identity ${index}`;
1844
+ const queuedHash = createHash("sha256")
1845
+ .update(buildExplicitCaptureDedupKey(queuedCandidate, "fact", "provider-a"))
1846
+ .digest("hex");
1847
+ const blockedHash = createHash("sha256")
1848
+ .update(buildExplicitCaptureDedupKey(blockedCandidate, "fact", "provider-a"))
1849
+ .digest("hex");
1850
+ if (queuedHash < blockedHash) {
1851
+ queuedContent = queuedCandidate;
1852
+ blockedContent = blockedCandidate;
1853
+ }
1854
+ }
1855
+ assert.ok(queuedContent.length > 0);
1856
+
1857
+ await storage.writeChunk("nested-lock-order", 0, 1, "fact", queuedContent, {
1858
+ source: "explicit-inline-review",
1859
+ sourceConnector: "provider-a",
1860
+ status: "pending_review",
1861
+ tags: ["queued-review"],
1862
+ });
1863
+ const id = await storage.writeChunk("nested-lock-order", 0, 1, "fact", blockedContent, {
1864
+ source: "offline-sync",
1865
+ sourceConnector: "provider-a",
1866
+ status: "pending_review",
1867
+ blockedBy: "tombstone-lock-order",
1868
+ });
1869
+
1870
+ assert.equal((await storage.getMemoryById(id))?.content, blockedContent);
1871
+ });
1872
+ });
1873
+
1665
1874
  test("offline sync rechecks blocked identity after waiting on the capture lock", async () => {
1666
1875
  await withMemoryDir(async (dir) => {
1667
1876
  const storage = new StorageManager(dir);
@@ -1725,6 +1934,84 @@ test("offline sync rechecks blocked identity after waiting on the capture lock",
1725
1934
  assert.equal(matches[0]?.frontmatter.id, captureResult.id);
1726
1935
  });
1727
1936
  });
1937
+ test("offline sync locks queued-review target identities before replacement", async () => {
1938
+ await withMemoryDir(async (dir) => {
1939
+ const storage = new StorageManager(dir);
1940
+ await storage.ensureDirectories();
1941
+ const queuedContent = "A queued review must not disappear during capture dedupe.";
1942
+ const queuedResult = await storage.writeMemory("fact", queuedContent, {
1943
+ source: "explicit-inline-review",
1944
+ sourceConnector: "provider-a",
1945
+ status: "pending_review",
1946
+ tags: ["explicit-capture", "queued-review"],
1947
+ });
1948
+ const queuedMemory = await storage.getMemoryById(queuedResult.id);
1949
+ assert.ok(queuedMemory);
1950
+ const queuedIdentity = buildExplicitCaptureDedupKey(queuedContent, "fact", "provider-a");
1951
+ const entered = Promise.withResolvers<void>();
1952
+ const release = Promise.withResolvers<void>();
1953
+ const held = storage.withTombstoneBlockedCaptureWriteLock(async () => {
1954
+ entered.resolve();
1955
+ await release.promise;
1956
+ }, queuedIdentity);
1957
+ await entered.promise;
1958
+ const storageWithOverride = storage as unknown as {
1959
+ withTombstoneBlockedCaptureWriteLock: (
1960
+ task: () => Promise<unknown>,
1961
+ identity?: string | readonly string[]
1962
+ ) => Promise<unknown>;
1963
+ };
1964
+ const originalLock = storageWithOverride.withTombstoneBlockedCaptureWriteLock.bind(storage);
1965
+ const coordinationAttempted = Promise.withResolvers<void>();
1966
+ storageWithOverride.withTombstoneBlockedCaptureWriteLock = async (task, identity) => {
1967
+ if ((Array.isArray(identity) ? identity : [identity]).includes(queuedIdentity)) {
1968
+ coordinationAttempted.resolve();
1969
+ }
1970
+ return await originalLock(task, identity);
1971
+ };
1972
+
1973
+ const replacementContent = "The reviewed replacement is now active.";
1974
+ const replacementFile = [
1975
+ "---",
1976
+ "id: queued-review-replacement",
1977
+ "category: fact",
1978
+ "created: 2026-01-01T00:00:00.000Z",
1979
+ "updated: 2026-01-01T00:00:00.000Z",
1980
+ "source: offline-sync",
1981
+ "confidence: 0.8",
1982
+ "confidenceTier: implied",
1983
+ "tags: []",
1984
+ "status: active",
1985
+ "---",
1986
+ "",
1987
+ replacementContent,
1988
+ "",
1989
+ ].join("\n");
1990
+ let completed = false;
1991
+ let replacement: Promise<void> | undefined;
1992
+ try {
1993
+ replacement = storage.writeOfflineSyncFile(queuedMemory.path, Buffer.from(replacementFile, "utf8")).then(() => {
1994
+ completed = true;
1995
+ });
1996
+ const first = await Promise.race([
1997
+ coordinationAttempted.promise.then(() => "coordinated" as const),
1998
+ replacement.then(() => "completed" as const),
1999
+ ]);
2000
+ assert.equal(first, "coordinated");
2001
+ assert.equal(completed, false, "offline sync must wait for the queued-review identity lock");
2002
+ release.resolve();
2003
+ await held;
2004
+ await replacement;
2005
+ assert.equal((await storage.getMemoryById("queued-review-replacement"))?.content, replacementContent);
2006
+ } finally {
2007
+ release.resolve();
2008
+ storageWithOverride.withTombstoneBlockedCaptureWriteLock = originalLock;
2009
+ await held.catch(() => undefined);
2010
+ await replacement?.catch(() => undefined);
2011
+ }
2012
+ });
2013
+ });
2014
+
1728
2015
  test("offline sync reacquires a rewritten blocked target identity", async () => {
1729
2016
  await withMemoryDir(async (dir) => {
1730
2017
  const storage = new StorageManager(dir);
@@ -1776,9 +2063,7 @@ test("offline sync reacquires a rewritten blocked target identity", async () =>
1776
2063
  contentA,
1777
2064
  "",
1778
2065
  ].join("\n");
1779
- const targetMemory = (await storage.readAllMemories()).find(
1780
- (memory) => memory.frontmatter.id === target.id
1781
- );
2066
+ const targetMemory = (await storage.readAllMemories()).find((memory) => memory.frontmatter.id === target.id);
1782
2067
  assert.ok(targetMemory);
1783
2068
  const identityA = buildExplicitCaptureDedupKey(contentA, "fact", "provider-a");
1784
2069
  const identityB = buildExplicitCaptureDedupKey(contentB, "fact", "provider-a");
@@ -1786,7 +2071,7 @@ test("offline sync reacquires a rewritten blocked target identity", async () =>
1786
2071
  const storageWithOverride = storage as unknown as {
1787
2072
  withTombstoneBlockedCaptureWriteLock: (
1788
2073
  task: () => Promise<unknown>,
1789
- identity?: string | readonly string[],
2074
+ identity?: string | readonly string[]
1790
2075
  ) => Promise<unknown>;
1791
2076
  };
1792
2077
  const originalLock = storageWithOverride.withTombstoneBlockedCaptureWriteLock.bind(storage);
@@ -1816,7 +2101,7 @@ test("offline sync reacquires a rewritten blocked target identity", async () =>
1816
2101
  await releaseMarker.promise;
1817
2102
  }
1818
2103
  return marker;
1819
- },
2104
+ }
1820
2105
  );
1821
2106
 
1822
2107
  const sync = storage.writeOfflineSyncFile(targetMemory.path, Buffer.from(incomingFile, "utf8"));
@@ -1826,11 +2111,11 @@ test("offline sync reacquires a rewritten blocked target identity", async () =>
1826
2111
  const secondKeys = capturedIdentities[1];
1827
2112
  assert.ok(
1828
2113
  (Array.isArray(firstKeys) ? firstKeys : [firstKeys]).includes(identityB),
1829
- "sync must first observe the original target identity",
2114
+ "sync must first observe the original target identity"
1830
2115
  );
1831
2116
  assert.ok(
1832
2117
  (Array.isArray(secondKeys) ? secondKeys : [secondKeys]).includes(identityC),
1833
- "sync must reacquire the rewritten target identity",
2118
+ "sync must reacquire the rewritten target identity"
1834
2119
  );
1835
2120
  let recaptureCompleted = false;
1836
2121
  const recapture = peer
@@ -1852,7 +2137,7 @@ test("offline sync reacquires a rewritten blocked target identity", async () =>
1852
2137
  assert.equal(
1853
2138
  after.find((memory) => memory.path === targetMemory.path)?.content,
1854
2139
  contentA,
1855
- "offline sync must replace the target after holding its current identity lock",
2140
+ "offline sync must replace the target after holding its current identity lock"
1856
2141
  );
1857
2142
  assert.equal(after.filter((memory) => memory.content === contentC).length, 1);
1858
2143
  } finally {
@@ -2247,7 +2532,7 @@ test("chunked offline sync scans oversized frontmatter before locking its identi
2247
2532
  semanticThreshold: 0.9,
2248
2533
  namespace: "default",
2249
2534
  });
2250
- const content = `Oversized frontmatter sync ${"x".repeat(900_000)}`;
2535
+ const content = "Oversized frontmatter sync";
2251
2536
  const tombstoneId = await storage.appendTombstone({
2252
2537
  reason: "correction",
2253
2538
  createdBy: "user_correction",
@@ -2263,7 +2548,7 @@ test("chunked offline sync scans oversized frontmatter before locking its identi
2263
2548
  const memory = (await storage.readAllMemories()).find((candidate) => candidate.frontmatter.id === result.id);
2264
2549
  assert.ok(memory);
2265
2550
 
2266
- const largeTags = Array.from({ length: 22_000 }, (_, index) => `"tag-${index}"`).join(", ");
2551
+ const largeTags = Array.from({ length: 100_000 }, (_, index) => `"tag-${index}"`).join(", ");
2267
2552
  const updatedFile = [
2268
2553
  "---",
2269
2554
  `id: ${memory.frontmatter.id}`,
@@ -2282,6 +2567,10 @@ test("chunked offline sync scans oversized frontmatter before locking its identi
2282
2567
  content,
2283
2568
  "",
2284
2569
  ].join("\n");
2570
+ assert.ok(
2571
+ updatedFile.indexOf("\n---\n") > 1_048_576,
2572
+ "the streamed body delimiter must appear after the chunk buffer limit",
2573
+ );
2285
2574
  const chunks = (async function* (): AsyncIterable<Buffer> {
2286
2575
  for (let offset = 0; offset < updatedFile.length; offset += 32 * 1024) {
2287
2576
  yield Buffer.from(updatedFile.slice(offset, offset + 32 * 1024), "utf8");
@@ -2309,6 +2598,52 @@ test("chunked offline sync scans oversized frontmatter before locking its identi
2309
2598
  });
2310
2599
  });
2311
2600
 
2601
+ test("chunked offline sync lowercases contextual Unicode across staged read boundaries", async () => {
2602
+ await withMemoryDir(async (dir) => {
2603
+ const storage = new StorageManager(dir);
2604
+ await storage.ensureDirectories();
2605
+ const header = (id: string) =>
2606
+ [
2607
+ "---",
2608
+ `id: ${id}`,
2609
+ "category: fact",
2610
+ "created: 2026-01-01T00:00:00.000Z",
2611
+ "updated: 2026-01-01T00:00:00.000Z",
2612
+ "source: offline-sync",
2613
+ "confidence: 0.8",
2614
+ "confidenceTier: implied",
2615
+ "tags: []",
2616
+ "sourceConnector: provider-a",
2617
+ "status: pending_review",
2618
+ "blockedBy: tombstone-unicode-boundary",
2619
+ "---",
2620
+ ].join("\n");
2621
+ const incomingHeader = header("unicode-boundary-incoming");
2622
+ const firstReadBoundary = SECURE_STORE_ENVELOPE_OVERHEAD_BYTES + 64 * 1024;
2623
+ const bodyOffset = Buffer.byteLength(`${incomingHeader}\n`);
2624
+ const prefixLength = firstReadBoundary - bodyOffset - Buffer.byteLength("\nΟΣ", "utf8");
2625
+ assert.ok(prefixLength > 0);
2626
+ const content = `${"x".repeat(prefixLength)}ΟΣΑ${"z".repeat(1_050_000)}`;
2627
+ assert.equal(Buffer.byteLength(`${incomingHeader}\n\n${"x".repeat(prefixLength)}ΟΣ`, "utf8"), firstReadBoundary);
2628
+ const memoryFile = (id: string) => `${header(id)}\n\n${content}\n`;
2629
+ const existingPath = path.join(dir, "facts", "2026-01-01", "unicode-boundary-existing.md");
2630
+ await storage.writeOfflineSyncFile(existingPath, Buffer.from(memoryFile("unicode-boundary-existing"), "utf8"));
2631
+
2632
+ const incomingPath = path.join(dir, "facts", "2026-01-01", "unicode-boundary-incoming.md");
2633
+ const incoming = Buffer.from(memoryFile("unicode-boundary-incoming"), "utf8");
2634
+ const chunks = (async function* (): AsyncIterable<Buffer> {
2635
+ for (let offset = 0; offset < incoming.length; offset += 32 * 1024) {
2636
+ yield incoming.subarray(offset, offset + 32 * 1024);
2637
+ }
2638
+ })();
2639
+ await storage.writeOfflineSyncFileChunks(incomingPath, chunks);
2640
+
2641
+ assert.equal(existsSync(incomingPath), false, "the normalized duplicate must not be published");
2642
+ const matches = (await storage.readAllMemories()).filter((memory) => memory.content === content);
2643
+ assert.equal(matches.length, 1);
2644
+ });
2645
+ });
2646
+
2312
2647
  test("chunked offline sync encrypts oversized staging files when secure storage is enabled", async () => {
2313
2648
  await withMemoryDir(async (dir) => {
2314
2649
  const storage = new StorageManager(dir);
@@ -2320,7 +2655,7 @@ test("chunked offline sync encrypts oversized staging files when secure storage
2320
2655
  semanticThreshold: 0.9,
2321
2656
  namespace: "default",
2322
2657
  });
2323
- const content = `Oversized encrypted staging content ${"x".repeat(1_048_576)}`;
2658
+ const content = "Oversized encrypted staging content";
2324
2659
  const tombstoneId = await storage.appendTombstone({
2325
2660
  reason: "correction",
2326
2661
  createdBy: "user_correction",
@@ -2335,6 +2670,7 @@ test("chunked offline sync encrypts oversized staging files when secure storage
2335
2670
  assert.equal(result.tombstoneBlocked, true);
2336
2671
  const memory = (await storage.readAllMemories()).find((candidate) => candidate.frontmatter.id === result.id);
2337
2672
  assert.ok(memory);
2673
+ const largeTags = Array.from({ length: 100_000 }, (_, index) => `"tag-${index}"`).join(", ");
2338
2674
 
2339
2675
  const incomingFile = [
2340
2676
  "---",
@@ -2345,7 +2681,7 @@ test("chunked offline sync encrypts oversized staging files when secure storage
2345
2681
  `source: ${memory.frontmatter.source}`,
2346
2682
  `confidence: ${memory.frontmatter.confidence}`,
2347
2683
  `confidenceTier: ${memory.frontmatter.confidenceTier}`,
2348
- "tags: []",
2684
+ `tags: [${largeTags}]`,
2349
2685
  "sourceConnector: provider-a",
2350
2686
  "status: pending_review",
2351
2687
  `blockedBy: ${memory.frontmatter.blockedBy}`,
@@ -2354,6 +2690,7 @@ test("chunked offline sync encrypts oversized staging files when secure storage
2354
2690
  content,
2355
2691
  "",
2356
2692
  ].join("\n");
2693
+ assert.ok(incomingFile.length > 1_048_576, "the encrypted staging fixture must exceed the chunk buffer limit");
2357
2694
  const chunks = (async function* (): AsyncIterable<Buffer> {
2358
2695
  for (let offset = 0; offset < incomingFile.length; offset += 32 * 1024) {
2359
2696
  yield Buffer.from(incomingFile.slice(offset, offset + 32 * 1024), "utf8");
@@ -2481,9 +2818,7 @@ test("chunked offline sync acquires a target identity discovered in a nested rec
2481
2818
  });
2482
2819
  assert.ok(targetTombstone);
2483
2820
  assert.equal(target.tombstoneBlocked, false);
2484
- const targetMemory = (await storage.readAllMemories()).find(
2485
- (memory) => memory.frontmatter.id === target.id
2486
- );
2821
+ const targetMemory = (await storage.readAllMemories()).find((memory) => memory.frontmatter.id === target.id);
2487
2822
  assert.ok(targetMemory);
2488
2823
  const incomingFile = [
2489
2824
  "---",
@@ -2512,13 +2847,13 @@ test("chunked offline sync acquires a target identity discovered in a nested rec
2512
2847
  const storageWithOverrides = storage as unknown as {
2513
2848
  withTombstoneBlockedCaptureWriteLock: (
2514
2849
  task: () => Promise<unknown>,
2515
- identity?: string | readonly string[],
2850
+ identity?: string | readonly string[]
2516
2851
  ) => Promise<unknown>;
2517
2852
  runTombstoneBlockedOfflineSyncMutation: (
2518
2853
  target: string,
2519
2854
  after: MemoryFile | null,
2520
2855
  write: () => Promise<void>,
2521
- coordinate?: boolean,
2856
+ coordinate?: boolean
2522
2857
  ) => Promise<void>;
2523
2858
  };
2524
2859
  const originalLock = storageWithOverrides.withTombstoneBlockedCaptureWriteLock.bind(storage);
@@ -2532,17 +2867,10 @@ test("chunked offline sync acquires a target identity discovered in a nested rec
2532
2867
  let pauseNextPrepare = false;
2533
2868
  const markerEntered = Promise.withResolvers<void>();
2534
2869
  const releaseMarker = Promise.withResolvers<void>();
2535
- storageWithOverrides.runTombstoneBlockedOfflineSyncMutation = async (
2536
- syncTarget,
2537
- after,
2538
- write,
2539
- coordinate,
2540
- ) => {
2870
+ storageWithOverrides.runTombstoneBlockedOfflineSyncMutation = async (syncTarget, after, write, coordinate) => {
2541
2871
  if (!rewroteTarget) {
2542
2872
  rewroteTarget = true;
2543
- const current = (await peer.readAllMemories()).find(
2544
- (memory) => memory.frontmatter.id === target.id
2545
- );
2873
+ const current = (await peer.readAllMemories()).find((memory) => memory.frontmatter.id === target.id);
2546
2874
  assert.ok(current);
2547
2875
  await peer.writeMemoryFrontmatter(current, {
2548
2876
  status: "pending_review",
@@ -2564,17 +2892,15 @@ test("chunked offline sync acquires a target identity discovered in a nested rec
2564
2892
  await releaseMarker.promise;
2565
2893
  }
2566
2894
  return marker;
2567
- },
2895
+ }
2568
2896
  );
2569
2897
 
2570
2898
  const sync = storage.writeOfflineSyncFileChunks(targetMemory.path, chunks);
2571
2899
  try {
2572
2900
  await markerEntered.promise;
2573
2901
  assert.ok(
2574
- capturedIdentities.some((identity) =>
2575
- (Array.isArray(identity) ? identity : [identity]).includes(identityC)
2576
- ),
2577
- "nested chunk sync must acquire the identity discovered after the outer recheck",
2902
+ capturedIdentities.some((identity) => (Array.isArray(identity) ? identity : [identity]).includes(identityC)),
2903
+ "nested chunk sync must acquire the identity discovered after the outer recheck"
2578
2904
  );
2579
2905
  let recaptureCompleted = false;
2580
2906
  const recapture = peer
@@ -2596,7 +2922,7 @@ test("chunked offline sync acquires a target identity discovered in a nested rec
2596
2922
  assert.equal(
2597
2923
  after.find((memory) => memory.path === targetMemory.path)?.content,
2598
2924
  incomingContent,
2599
- "chunk sync must replace the target only while holding its current identity lock",
2925
+ "chunk sync must replace the target only while holding its current identity lock"
2600
2926
  );
2601
2927
  assert.equal(after.filter((memory) => memory.content === targetContent).length, 1);
2602
2928
  } finally {
@@ -2640,7 +2966,8 @@ test("large blocked offline sync streams through bounded staging and deduplicate
2640
2966
  semanticThreshold: 0.9,
2641
2967
  namespace: "default",
2642
2968
  });
2643
- const largeContent = "large stream duplicate ".repeat(60_000);
2969
+ const largeContent = "large stream duplicate";
2970
+ const largeTags = Array.from({ length: 100_000 }, (_, index) => `"tag-${index}"`).join(", ");
2644
2971
  const tombstoneId = await storage.appendTombstone({
2645
2972
  reason: "correction",
2646
2973
  createdBy: "user_correction",
@@ -2663,7 +2990,7 @@ test("large blocked offline sync streams through bounded staging and deduplicate
2663
2990
  "source: offline-sync",
2664
2991
  "confidence: 0.8",
2665
2992
  "confidenceTier: implied",
2666
- "tags: []",
2993
+ `tags: [${largeTags}]`,
2667
2994
  "sourceConnector: provider-a",
2668
2995
  "status: pending_review",
2669
2996
  `blockedBy: ${tombstoneId}`,
@@ -2672,7 +2999,7 @@ test("large blocked offline sync streams through bounded staging and deduplicate
2672
2999
  largeContent,
2673
3000
  "",
2674
3001
  ].join("\n"),
2675
- "utf8",
3002
+ "utf8"
2676
3003
  );
2677
3004
  assert.ok(incomingFile.byteLength > 1_048_576);
2678
3005
  const target = path.join(dir, "cold", "large-stream-incoming.md");
@@ -2689,10 +3016,9 @@ test("large blocked offline sync streams through bounded staging and deduplicate
2689
3016
 
2690
3017
  assert.equal(consumedBytes, incomingFile.byteLength);
2691
3018
  assert.equal(existsSync(target), false, "a streamed blocked duplicate must not publish a new row");
2692
- const matches = [
2693
- ...(await storage.readAllMemories()),
2694
- ...(await storage.readAllColdMemories()),
2695
- ].filter((memory) => memory.frontmatter.id === existing.id);
3019
+ const matches = [...(await storage.readAllMemories()), ...(await storage.readAllColdMemories())].filter(
3020
+ (memory) => memory.frontmatter.id === existing.id
3021
+ );
2696
3022
  assert.equal(matches.length, 1, "the existing blocked row remains the sole durable duplicate");
2697
3023
  });
2698
3024
  });
@@ -2827,10 +3153,7 @@ test("frontmatter rewrites invalidate cold cache before blocked index sync", asy
2827
3153
  );
2828
3154
  assert.ok(coldMemory, "migrated blocked memory must be readable from cold tier");
2829
3155
 
2830
- assert.equal(
2831
- await storage.writeMemoryFrontmatter(coldMemory, { sourceConnector: "provider-b" }),
2832
- true
2833
- );
3156
+ assert.equal(await storage.writeMemoryFrontmatter(coldMemory, { sourceConnector: "provider-b" }), true);
2834
3157
  assert.equal(
2835
3158
  await storage.hasTombstoneBlockedExplicitCapture(content, "fact", "provider-a"),
2836
3159
  false,
@@ -3207,7 +3530,7 @@ test("blocked invalidation reserves the index marker before deleting under the i
3207
3530
  const storageWithOverride = storage as unknown as {
3208
3531
  withTombstoneBlockedCaptureWriteLock: (
3209
3532
  task: () => Promise<boolean>,
3210
- identity?: string | readonly string[],
3533
+ identity?: string | readonly string[]
3211
3534
  ) => Promise<boolean>;
3212
3535
  };
3213
3536
  let capturedIdentity: string | readonly string[] | undefined;
@@ -3229,7 +3552,7 @@ test("blocked invalidation reserves the index marker before deleting under the i
3229
3552
  await release.promise;
3230
3553
  }
3231
3554
  return marker;
3232
- },
3555
+ }
3233
3556
  );
3234
3557
 
3235
3558
  const invalidation = storage.invalidateMemory(first.id);
@@ -3238,15 +3561,12 @@ test("blocked invalidation reserves the index marker before deleting under the i
3238
3561
  entered.promise.then(() => true),
3239
3562
  new Promise<boolean>((resolve) => setTimeout(() => resolve(false), 100)),
3240
3563
  ]);
3241
- assert.equal(
3242
- enteredBeforeTimeout,
3243
- true,
3244
- "blocked invalidation must reserve its rebuild marker before unlinking",
3245
- );
3246
- assert.equal(capturedIdentity, identity);
3564
+ assert.equal(enteredBeforeTimeout, true, "blocked invalidation must reserve its rebuild marker before unlinking");
3565
+ assert.ok(Array.isArray(capturedIdentity) && capturedIdentity.includes(identity));
3566
+ assert.ok(Array.isArray(capturedIdentity) && capturedIdentity.some((key) => key.startsWith("path ")));
3247
3567
  assert.ok(
3248
3568
  (await readdir(path.join(dir, "state", "tombstone-blocked-capture", "rebuild-required"))).length > 0,
3249
- "blocked invalidation must publish its rebuild marker before unlinking",
3569
+ "blocked invalidation must publish its rebuild marker before unlinking"
3250
3570
  );
3251
3571
 
3252
3572
  let peerCompleted = false;
@@ -3266,10 +3586,7 @@ test("blocked invalidation reserves the index marker before deleting under the i
3266
3586
  const second = await recapture;
3267
3587
  assert.equal(second.tombstoneBlocked, true);
3268
3588
  assert.notEqual(second.id, first.id);
3269
- assert.equal(
3270
- (await peer.readAllMemories()).filter((memory) => memory.content === content).length,
3271
- 1,
3272
- );
3589
+ assert.equal((await peer.readAllMemories()).filter((memory) => memory.content === content).length, 1);
3273
3590
  } finally {
3274
3591
  release.resolve();
3275
3592
  prepareSpy.mock.restore();
@@ -3313,7 +3630,7 @@ test("blocked archive serializes capture scans with the archive transition", asy
3313
3630
  const storageWithOverride = storage as unknown as {
3314
3631
  withTombstoneBlockedCaptureWriteLock: (
3315
3632
  task: () => Promise<unknown>,
3316
- identity?: string | readonly string[],
3633
+ identity?: string | readonly string[]
3317
3634
  ) => Promise<unknown>;
3318
3635
  };
3319
3636
  const originalLock = storageWithOverride.withTombstoneBlockedCaptureWriteLock.bind(storage);
@@ -3338,7 +3655,7 @@ test("blocked archive serializes capture scans with the archive transition", asy
3338
3655
  await releaseMarker.promise;
3339
3656
  }
3340
3657
  return marker;
3341
- },
3658
+ }
3342
3659
  );
3343
3660
 
3344
3661
  const archive = storage.archiveMemory(firstMemory);
@@ -3348,7 +3665,8 @@ test("blocked archive serializes capture scans with the archive transition", asy
3348
3665
  new Promise<boolean>((resolve) => setTimeout(() => resolve(false), 100)),
3349
3666
  ]);
3350
3667
  assert.equal(enteredBeforeTimeout, true, "archive must reserve its marker under the capture lock");
3351
- assert.equal(capturedIdentity, identity);
3668
+ assert.ok(Array.isArray(capturedIdentity) && capturedIdentity.includes(identity));
3669
+ assert.ok(Array.isArray(capturedIdentity) && capturedIdentity.some((key) => key.startsWith("path ")));
3352
3670
 
3353
3671
  let recaptureCompleted = false;
3354
3672
  const recapture = peer
@@ -3372,12 +3690,12 @@ test("blocked archive serializes capture scans with the archive transition", asy
3372
3690
  assert.equal(
3373
3691
  (await peer.readAllMemories()).filter((memory) => memory.content === content).length,
3374
3692
  1,
3375
- "recapture must recreate the review row after archive removes the old row",
3693
+ "recapture must recreate the review row after archive removes the old row"
3376
3694
  );
3377
3695
  assert.equal(
3378
3696
  await peer.hasTombstoneBlockedExplicitCapture(content, "fact", "provider-a"),
3379
3697
  true,
3380
- "the recreated review row must remain indexed",
3698
+ "the recreated review row must remain indexed"
3381
3699
  );
3382
3700
  } finally {
3383
3701
  releaseMarker.resolve();
@@ -3396,7 +3714,7 @@ test("blocked archive failures discard their uncommitted rebuild marker", async
3396
3714
  protected override writeStorageSecureFile(
3397
3715
  filePath: string,
3398
3716
  content: string | Buffer,
3399
- forceEncrypt = false,
3717
+ forceEncrypt = false
3400
3718
  ): Promise<void> {
3401
3719
  if (this.failArchiveWrites && filePath.includes(`${path.sep}archive${path.sep}`)) {
3402
3720
  return Promise.reject(new Error("simulated archive write failure"));
@@ -3476,7 +3794,7 @@ test("blocked invalidation reacquires the reloaded identity lock", async () => {
3476
3794
  const storageWithOverride = storage as unknown as {
3477
3795
  withTombstoneBlockedCaptureWriteLock: (
3478
3796
  task: () => Promise<unknown>,
3479
- identity?: string | readonly string[],
3797
+ identity?: string | readonly string[]
3480
3798
  ) => Promise<unknown>;
3481
3799
  };
3482
3800
  const originalLock = storageWithOverride.withTombstoneBlockedCaptureWriteLock.bind(storage);
@@ -3506,13 +3824,23 @@ test("blocked invalidation reacquires the reloaded identity lock", async () => {
3506
3824
  await releaseMarker.promise;
3507
3825
  }
3508
3826
  return marker;
3509
- },
3827
+ }
3510
3828
  );
3511
3829
 
3512
3830
  const invalidation = storage.invalidateMemory(first.id);
3513
3831
  try {
3514
3832
  await markerEntered.promise;
3515
- assert.deepEqual(capturedIdentities, [identityA, identityB]);
3833
+ assert.deepEqual(
3834
+ capturedIdentities.map((identity) =>
3835
+ (Array.isArray(identity) ? identity : [identity]).filter((key) => key?.startsWith("category "))
3836
+ ),
3837
+ [[identityA], [identityA, identityB]]
3838
+ );
3839
+ assert.ok(
3840
+ capturedIdentities.every((identity) =>
3841
+ (Array.isArray(identity) ? identity : [identity]).some((key) => key?.startsWith("path "))
3842
+ )
3843
+ );
3516
3844
  let recaptureCompleted = false;
3517
3845
  const recapture = peer
3518
3846
  .writeMemory("fact", contentB, {
@@ -3530,10 +3858,7 @@ test("blocked invalidation reacquires the reloaded identity lock", async () => {
3530
3858
  const second = await recapture;
3531
3859
  assert.equal(second.tombstoneBlocked, true);
3532
3860
  assert.notEqual(second.id, first.id);
3533
- assert.equal(
3534
- (await peer.readAllMemories()).filter((memory) => memory.content === contentB).length,
3535
- 1,
3536
- );
3861
+ assert.equal((await peer.readAllMemories()).filter((memory) => memory.content === contentB).length, 1);
3537
3862
  } finally {
3538
3863
  releaseMarker.resolve();
3539
3864
  prepareSpy.mock.restore();
@@ -3570,7 +3895,7 @@ test("blocked rewrites reacquire a target identity changed before update", async
3570
3895
  createdBy: "user_correction",
3571
3896
  sourceMemoryId,
3572
3897
  rawContent,
3573
- }),
3898
+ })
3574
3899
  );
3575
3900
  }
3576
3901
  const target = await storage.writeMemory("fact", contentA, {
@@ -3578,9 +3903,7 @@ test("blocked rewrites reacquire a target identity changed before update", async
3578
3903
  sourceConnector: "provider-a",
3579
3904
  });
3580
3905
  assert.equal(target.tombstoneBlocked, true);
3581
- const targetMemory = (await storage.readAllMemories()).find(
3582
- (memory) => memory.frontmatter.id === target.id
3583
- );
3906
+ const targetMemory = (await storage.readAllMemories()).find((memory) => memory.frontmatter.id === target.id);
3584
3907
  assert.ok(targetMemory);
3585
3908
  const identityA = buildExplicitCaptureDedupKey(contentA, "fact", "provider-a");
3586
3909
  const identityB = buildExplicitCaptureDedupKey(contentB, "fact", "provider-a");
@@ -3588,7 +3911,7 @@ test("blocked rewrites reacquire a target identity changed before update", async
3588
3911
  const storageWithOverride = storage as unknown as {
3589
3912
  withTombstoneBlockedCaptureWriteLock: (
3590
3913
  task: () => Promise<unknown>,
3591
- identity?: string | readonly string[],
3914
+ identity?: string | readonly string[]
3592
3915
  ) => Promise<unknown>;
3593
3916
  };
3594
3917
  const originalLock = storageWithOverride.withTombstoneBlockedCaptureWriteLock.bind(storage);
@@ -3618,7 +3941,7 @@ test("blocked rewrites reacquire a target identity changed before update", async
3618
3941
  await releaseMarker.promise;
3619
3942
  }
3620
3943
  return marker;
3621
- },
3944
+ }
3622
3945
  );
3623
3946
 
3624
3947
  const update = storage.updateMemory(target.id, contentC, { sourceConnector: "provider-a" });
@@ -3629,11 +3952,11 @@ test("blocked rewrites reacquire a target identity changed before update", async
3629
3952
  const secondKeys = capturedIdentities[1];
3630
3953
  assert.ok(
3631
3954
  (Array.isArray(firstKeys) ? firstKeys : [firstKeys]).includes(identityA),
3632
- "update must first lock the identity read before the peer rewrite",
3955
+ "update must first lock the identity read before the peer rewrite"
3633
3956
  );
3634
3957
  assert.ok(
3635
3958
  (Array.isArray(secondKeys) ? secondKeys : [secondKeys]).includes(identityB),
3636
- "update must reacquire the rewritten target identity",
3959
+ "update must reacquire the rewritten target identity"
3637
3960
  );
3638
3961
  let recaptureCompleted = false;
3639
3962
  const recapture = peer
@@ -3655,7 +3978,7 @@ test("blocked rewrites reacquire a target identity changed before update", async
3655
3978
  assert.equal(
3656
3979
  after.find((memory) => memory.path === targetMemory.path)?.content,
3657
3980
  contentC,
3658
- "update must write only after holding the current target identity lock",
3981
+ "update must write only after holding the current target identity lock"
3659
3982
  );
3660
3983
  assert.equal(after.filter((memory) => memory.content === contentB).length, 1);
3661
3984
  } finally {
@@ -3914,130 +4237,97 @@ test("queued-review dispositions coordinate with explicit capture dedupe", async
3914
4237
  });
3915
4238
  });
3916
4239
 
3917
- test("active rewrites recheck a target that becomes blocked before the unlocked write", async () => {
4240
+ test("active rewrites serialize the target path across their read and write", async () => {
3918
4241
  await withMemoryDir(async (dir) => {
3919
4242
  const storage = new StorageManager(dir);
3920
4243
  const peer = new StorageManager(dir);
3921
4244
  await storage.ensureDirectories();
3922
4245
  await peer.ensureDirectories();
3923
- const tombstoneConfig = {
3924
- enabled: true,
3925
- semanticMatch: false,
3926
- semanticThreshold: 0.9,
3927
- namespace: "default",
3928
- };
3929
- storage.setTombstonesConfig(tombstoneConfig);
3930
- peer.setTombstonesConfig(tombstoneConfig);
3931
- const contentA = "An active target becomes blocked before an update writes.";
3932
- const contentB = "The rewritten blocked target identity must be locked.";
3933
- const contentC = "The stale update must publish only after locking identity B.";
3934
- const tombstoneId = await peer.appendTombstone({
3935
- reason: "correction",
3936
- createdBy: "user_correction",
3937
- sourceMemoryId: "active-rewrite-recheck",
3938
- rawContent: contentB,
3939
- });
3940
- assert.ok(tombstoneId);
4246
+ const contentA = "An active target is read before a concurrent update.";
4247
+ const contentB = "The concurrent update must run after the in-flight write.";
4248
+ const contentC = "The in-flight update holds the path through persistence.";
3941
4249
  const target = await storage.writeMemory("fact", contentA, {
3942
4250
  source: "test",
3943
4251
  sourceConnector: "provider-a",
3944
4252
  });
3945
4253
  const targetMemory = await storage.getMemoryById(target.id);
3946
4254
  assert.ok(targetMemory);
3947
- assert.equal(targetMemory.frontmatter.status, "active");
3948
- const identityB = buildExplicitCaptureDedupKey(contentB, "fact", "provider-a");
3949
- await storage.hasTombstoneBlockedExplicitCapture(contentB, "fact", "provider-a");
3950
4255
 
4256
+ const readPaused = Promise.withResolvers<void>();
4257
+ const releaseRead = Promise.withResolvers<void>();
3951
4258
  const storageWithOverrides = storage as unknown as {
3952
4259
  readMemoryByPath: (filePath: string) => Promise<MemoryFile | null>;
3953
4260
  withTombstoneBlockedCaptureWriteLock: (
3954
4261
  task: () => Promise<unknown>,
3955
- identity?: string | readonly string[],
4262
+ identity?: string | readonly string[]
3956
4263
  ) => Promise<unknown>;
3957
4264
  };
3958
4265
  const originalRead = storageWithOverrides.readMemoryByPath.bind(storage);
3959
- let rewriteOnRead = true;
4266
+ let pauseRead = true;
3960
4267
  storageWithOverrides.readMemoryByPath = async (filePath) => {
3961
4268
  const current = await originalRead(filePath);
3962
- if (rewriteOnRead) {
3963
- rewriteOnRead = false;
3964
- assert.ok(current);
3965
- assert.equal(await peer.updateMemory(target.id, contentB, { sourceConnector: "provider-a" }), true);
3966
- const rewritten = await peer.getMemoryById(target.id);
3967
- assert.ok(rewritten);
3968
- assert.equal(
3969
- await peer.writeMemoryFrontmatter(rewritten, {
3970
- status: "pending_review",
3971
- blockedBy: tombstoneId,
3972
- }),
3973
- true,
3974
- );
3975
- pauseNextPrepare = true;
3976
- return await originalRead(filePath);
4269
+ if (pauseRead && filePath === targetMemory.path) {
4270
+ pauseRead = false;
4271
+ readPaused.resolve();
4272
+ await releaseRead.promise;
3977
4273
  }
3978
4274
  return current;
3979
4275
  };
3980
- const originalLock = storageWithOverrides.withTombstoneBlockedCaptureWriteLock.bind(storage);
3981
- const capturedIdentities: Array<string | readonly string[] | undefined> = [];
4276
+ const originalStorageLock = storageWithOverrides.withTombstoneBlockedCaptureWriteLock.bind(storage);
4277
+ const storageIdentities: Array<string | readonly string[] | undefined> = [];
3982
4278
  storageWithOverrides.withTombstoneBlockedCaptureWriteLock = async (task, identity) => {
3983
- capturedIdentities.push(identity);
3984
- return await originalLock(task, identity);
4279
+ storageIdentities.push(identity);
4280
+ return await originalStorageLock(task, identity);
4281
+ };
4282
+
4283
+ const peerWithOverride = peer as unknown as {
4284
+ withTombstoneBlockedCaptureWriteLock: (
4285
+ task: () => Promise<unknown>,
4286
+ identity?: string | readonly string[]
4287
+ ) => Promise<unknown>;
4288
+ };
4289
+ const originalPeerLock = peerWithOverride.withTombstoneBlockedCaptureWriteLock.bind(peer);
4290
+ const peerLockRequested = Promise.withResolvers<void>();
4291
+ const peerIdentities: Array<string | readonly string[] | undefined> = [];
4292
+ peerWithOverride.withTombstoneBlockedCaptureWriteLock = async (task, identity) => {
4293
+ peerIdentities.push(identity);
4294
+ peerLockRequested.resolve();
4295
+ return await originalPeerLock(task, identity);
3985
4296
  };
3986
- const releaseMarker = Promise.withResolvers<void>();
3987
- const markerEntered = Promise.withResolvers<void>();
3988
- let pauseNextPrepare = false;
3989
- const originalPrepare = TombstoneBlockedCaptureIndex.prototype.prepareWrite;
3990
- const prepareSpy = mock.method(
3991
- TombstoneBlockedCaptureIndex.prototype,
3992
- "prepareWrite",
3993
- async function (this: TombstoneBlockedCaptureIndex) {
3994
- const marker = await originalPrepare.call(this);
3995
- if (pauseNextPrepare) {
3996
- pauseNextPrepare = false;
3997
- markerEntered.resolve();
3998
- await releaseMarker.promise;
3999
- }
4000
- return marker;
4001
- }
4002
- );
4003
4297
 
4004
4298
  const update = storage.updateMemory(target.id, contentC, { sourceConnector: "provider-a" });
4299
+ let competingUpdate: Promise<boolean> | undefined;
4300
+ let competingFinished = false;
4005
4301
  try {
4006
- await markerEntered.promise;
4302
+ await readPaused.promise;
4303
+ competingUpdate = peer.updateMemory(target.id, contentB, { sourceConnector: "provider-a" }).then((updated) => {
4304
+ competingFinished = true;
4305
+ return updated;
4306
+ });
4307
+ await peerLockRequested.promise;
4308
+ const contentionWindow = Promise.withResolvers<void>();
4309
+ setTimeout(contentionWindow.resolve, 50);
4310
+ await contentionWindow.promise;
4311
+ const pathIdentity = buildCapturePathLockIdentity(targetMemory.path);
4007
4312
  assert.ok(
4008
- capturedIdentities.some((identity) =>
4009
- (Array.isArray(identity) ? identity : [identity]).includes(identityB)
4010
- ),
4011
- "active rewrite must reacquire the current blocked target identity",
4313
+ storageIdentities.some((identity) => (Array.isArray(identity) ? identity : [identity]).includes(pathIdentity))
4012
4314
  );
4013
- let recaptureCompleted = false;
4014
- const recapture = peer
4015
- .writeMemory("fact", contentB, {
4016
- source: "test",
4017
- sourceConnector: "provider-a",
4018
- })
4019
- .then((result) => {
4020
- recaptureCompleted = true;
4021
- return result;
4022
- });
4023
- await new Promise((resolve) => setTimeout(resolve, 50));
4024
- assert.equal(recaptureCompleted, false, "recapture must wait for the current target identity lock");
4025
- releaseMarker.resolve();
4026
- assert.equal(await update, true);
4027
- assert.equal((await recapture).tombstoneBlocked, true);
4028
- const after = await peer.readAllMemories();
4029
- assert.equal(
4030
- after.find((memory) => memory.path === targetMemory.path)?.content,
4031
- contentC,
4032
- "the stale update must write the requested content",
4315
+ assert.ok(
4316
+ peerIdentities.some((identity) => (Array.isArray(identity) ? identity : [identity]).includes(pathIdentity))
4033
4317
  );
4034
- assert.equal(await peer.hasTombstoneBlockedExplicitCapture(contentB, "fact", "provider-a"), true);
4318
+ assert.equal(competingFinished, false, "the peer must wait while the first writer holds the target path");
4319
+
4320
+ releaseRead.resolve();
4321
+ assert.equal(await update, true);
4322
+ assert.equal(await competingUpdate, true);
4323
+ assert.equal((await peer.getMemoryById(target.id))?.content, contentB);
4035
4324
  } finally {
4036
- releaseMarker.resolve();
4037
- prepareSpy.mock.restore();
4325
+ releaseRead.resolve();
4038
4326
  storageWithOverrides.readMemoryByPath = originalRead;
4039
- storageWithOverrides.withTombstoneBlockedCaptureWriteLock = originalLock;
4327
+ storageWithOverrides.withTombstoneBlockedCaptureWriteLock = originalStorageLock;
4328
+ peerWithOverride.withTombstoneBlockedCaptureWriteLock = originalPeerLock;
4040
4329
  await update.catch(() => false);
4330
+ await competingUpdate?.catch(() => false);
4041
4331
  }
4042
4332
  });
4043
4333
  });