@remnic/core 9.69.33 → 9.69.35

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/access-admin-ops-surface.d.ts +14 -11
  2. package/dist/access-admin-ops-surface.js +65 -60
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-authorization-probe.d.ts +14 -11
  5. package/dist/access-authorization-probe.js +66 -61
  6. package/dist/access-boundary.d.ts +14 -11
  7. package/dist/access-boundary.js +65 -60
  8. package/dist/access-cli.js +137 -133
  9. package/dist/access-cli.js.map +1 -1
  10. package/dist/access-coding-context-resolution.d.ts +3 -1
  11. package/dist/access-coding-context-resolution.js +3 -3
  12. package/dist/access-extraction-force-flush.d.ts +14 -11
  13. package/dist/access-extraction-force-flush.js +65 -60
  14. package/dist/access-health-types.d.ts +3 -1
  15. package/dist/access-http-briefing.d.ts +14 -11
  16. package/dist/access-http-briefing.js +66 -61
  17. package/dist/access-http-lcm-compaction.d.ts +14 -11
  18. package/dist/access-http-lifecycle-flush.d.ts +14 -11
  19. package/dist/access-http-offline-stream.d.ts +14 -11
  20. package/dist/access-http-query.d.ts +4 -2
  21. package/dist/access-http-query.js +67 -62
  22. package/dist/access-http.d.ts +15 -12
  23. package/dist/access-http.js +86 -82
  24. package/dist/access-identity-continuity-surface.d.ts +12 -9
  25. package/dist/access-identity-continuity-surface.js +65 -60
  26. package/dist/access-lcm-surface.d.ts +14 -11
  27. package/dist/access-lcm-surface.js +65 -60
  28. package/dist/access-mcp.d.ts +14 -11
  29. package/dist/access-mcp.js +74 -70
  30. package/dist/access-memory-search-fanout.d.ts +4 -2
  31. package/dist/{access-namespace-preflight-DMR-jOMS.d.ts → access-namespace-preflight-D8qri11P.d.ts} +1 -1
  32. package/dist/access-namespace-preflight.d.ts +5 -3
  33. package/dist/access-namespace-preflight.js +65 -60
  34. package/dist/access-observe-transcript.d.ts +12 -9
  35. package/dist/access-observe-transcript.js +3 -3
  36. package/dist/access-observe-write-surface.d.ts +16 -13
  37. package/dist/access-observe-write-surface.js +65 -60
  38. package/dist/access-offline-manifest.d.ts +48 -11
  39. package/dist/access-offline-manifest.js +18 -16
  40. package/dist/access-operations-batch.js +68 -64
  41. package/dist/access-operations.d.ts +15 -12
  42. package/dist/access-operations.js +73 -69
  43. package/dist/access-recall-concurrency.d.ts +14 -11
  44. package/dist/access-recall-concurrency.js +65 -60
  45. package/dist/access-recall-response.d.ts +14 -11
  46. package/dist/access-recall-response.js +65 -60
  47. package/dist/access-recall-surface.d.ts +14 -11
  48. package/dist/access-recall-surface.js +65 -60
  49. package/dist/access-schema.d.ts +56 -13
  50. package/dist/access-schema.js +15 -1
  51. package/dist/{access-service-CJQoQvRa.d.ts → access-service-CKu5ixg9.d.ts} +52 -50
  52. package/dist/access-service-helpers.d.ts +14 -11
  53. package/dist/access-service.d.ts +14 -11
  54. package/dist/access-service.js +65 -60
  55. package/dist/access-surface-catalog.d.ts +14 -11
  56. package/dist/access-surface-catalog.js +67 -62
  57. package/dist/access-surface-catalog.js.map +1 -1
  58. package/dist/access-wearables-meetings-surface.d.ts +5 -3
  59. package/dist/action-confidence.d.ts +3 -1
  60. package/dist/active-memory-bridge.d.ts +3 -1
  61. package/dist/active-memory-bridge.js +2 -2
  62. package/dist/active-recall.d.ts +3 -1
  63. package/dist/active-recall.js +12 -10
  64. package/dist/active-recall.js.map +1 -1
  65. package/dist/activity/digest.d.ts +3 -1
  66. package/dist/adapters/index.d.ts +46 -1
  67. package/dist/adapters/index.js +10 -6
  68. package/dist/adapters/registry.js +2 -2
  69. package/dist/ambient-provenance.d.ts +3 -1
  70. package/dist/artifact-search.d.ts +3 -1
  71. package/dist/{auto-sync-NSHLUAQI.js → auto-sync-4YFATLFQ.js} +10 -9
  72. package/dist/{auto-sync-NSHLUAQI.js.map → auto-sync-4YFATLFQ.js.map} +1 -1
  73. package/dist/behavior-learner.d.ts +3 -1
  74. package/dist/behavior-signals.d.ts +3 -1
  75. package/dist/bootstrap.d.ts +12 -9
  76. package/dist/briefing-window.d.ts +4 -2
  77. package/dist/briefing.d.ts +4 -2
  78. package/dist/briefing.js +26 -25
  79. package/dist/buffer-surprise-report.d.ts +3 -1
  80. package/dist/buffer-turn-helpers.d.ts +3 -1
  81. package/dist/buffer.d.ts +4 -2
  82. package/dist/buffer.js +11 -10
  83. package/dist/bulk-import/index.d.ts +5 -3
  84. package/dist/calibration.d.ts +3 -1
  85. package/dist/calibration.js +3 -2
  86. package/dist/calibration.js.map +1 -1
  87. package/dist/capabilities.d.ts +3 -1
  88. package/dist/{capsule-merge-IPG4IOFP.js → capsule-merge-ZCXUPLNJ.js} +2 -2
  89. package/dist/{catalog-8O9KY9eA.d.ts → catalog-Bq1AxZwF.d.ts} +1 -1
  90. package/dist/causal-behavior.d.ts +3 -1
  91. package/dist/causal-consolidation.d.ts +3 -1
  92. package/dist/causal-consolidation.js +27 -26
  93. package/dist/causal-consolidation.js.map +1 -1
  94. package/dist/causal-trajectory-graph.d.ts +3 -1
  95. package/dist/{chunk-CDKHKZL5.js → chunk-2524MOWK.js} +2 -2
  96. package/dist/{chunk-HVAEXYPL.js → chunk-255PC37A.js} +47 -25
  97. package/dist/chunk-255PC37A.js.map +1 -0
  98. package/dist/{chunk-2C3S7J2S.js → chunk-2BQ4ZIWC.js} +741 -28
  99. package/dist/chunk-2BQ4ZIWC.js.map +1 -0
  100. package/dist/{chunk-RKBLRTNT.js → chunk-2YLMUME2.js} +2 -2
  101. package/dist/{chunk-QOIOACIE.js → chunk-326KUXIR.js} +15 -648
  102. package/dist/chunk-326KUXIR.js.map +1 -0
  103. package/dist/{chunk-DBQWVT2H.js → chunk-3CBI2ZSA.js} +2 -2
  104. package/dist/{chunk-MWFGUESQ.js → chunk-3FJKJ5UZ.js} +2 -2
  105. package/dist/{chunk-NZXEK3UF.js → chunk-3Q3N35W7.js} +2 -2
  106. package/dist/{chunk-YYGZJPOK.js → chunk-42DJ235G.js} +2 -2
  107. package/dist/{chunk-SO7SV523.js → chunk-4MDKNUV4.js} +1 -1
  108. package/dist/chunk-4MDKNUV4.js.map +1 -0
  109. package/dist/chunk-5HYUUFMQ.js +1280 -0
  110. package/dist/chunk-5HYUUFMQ.js.map +1 -0
  111. package/dist/{chunk-2JVJ7UHC.js → chunk-5JG5EBVL.js} +4 -2
  112. package/dist/chunk-5JG5EBVL.js.map +1 -0
  113. package/dist/{chunk-HV7OY4DM.js → chunk-5VAF4ID4.js} +643 -202
  114. package/dist/chunk-5VAF4ID4.js.map +1 -0
  115. package/dist/{chunk-N7RWREIQ.js → chunk-65RENJGB.js} +6 -1
  116. package/dist/chunk-65RENJGB.js.map +1 -0
  117. package/dist/{chunk-JTH2SE6B.js → chunk-6J6K3STG.js} +8 -8
  118. package/dist/{chunk-H4VH5VIB.js → chunk-776GVKL7.js} +2 -2
  119. package/dist/{chunk-BUTCAMJM.js → chunk-A2YQL2FF.js} +5 -5
  120. package/dist/chunk-A5UQ52YQ.js +211 -0
  121. package/dist/chunk-A5UQ52YQ.js.map +1 -0
  122. package/dist/{chunk-X2NFFBTO.js → chunk-A7GQBJP5.js} +4 -4
  123. package/dist/{chunk-CGC5UQCF.js → chunk-AKE4GGQ3.js} +2 -2
  124. package/dist/{chunk-B325AGLK.js → chunk-AZSKROVQ.js} +2 -2
  125. package/dist/{chunk-I5DZ3WGR.js → chunk-BJETIR53.js} +3 -3
  126. package/dist/{chunk-JT3EB7ZL.js → chunk-BNGHPYZU.js} +5 -5
  127. package/dist/chunk-BRZWWUCJ.js +13 -0
  128. package/dist/{chunk-FYDW33ZB.js.map → chunk-BRZWWUCJ.js.map} +1 -1
  129. package/dist/{chunk-3JVLGJCY.js → chunk-C6KRO3SU.js} +2 -2
  130. package/dist/{chunk-5NANRSCD.js → chunk-CNV2A557.js} +5 -5
  131. package/dist/{chunk-PBGVVDLY.js → chunk-DK4X5B6I.js} +2 -2
  132. package/dist/{chunk-MFDTVQJX.js → chunk-DVOBLPSQ.js} +22 -7
  133. package/dist/chunk-DVOBLPSQ.js.map +1 -0
  134. package/dist/{chunk-N2ZNPHA3.js → chunk-ECKG5WSI.js} +2 -2
  135. package/dist/{chunk-PYLL63BF.js → chunk-EEBQFG5E.js} +9 -9
  136. package/dist/{chunk-ET356KSB.js → chunk-F4TWWUMP.js} +2 -2
  137. package/dist/{chunk-RHQMKJFG.js → chunk-F6IVBYFS.js} +55 -51
  138. package/dist/{chunk-RHQMKJFG.js.map → chunk-F6IVBYFS.js.map} +1 -1
  139. package/dist/{chunk-CLLPJ6QT.js → chunk-FQXJAC3T.js} +2 -2
  140. package/dist/{chunk-JGHXXQ2G.js → chunk-FVJ4D6L7.js} +2 -2
  141. package/dist/{chunk-DD5JFCWM.js → chunk-GCBIXUPT.js} +2 -2
  142. package/dist/{chunk-MN3LK3KN.js → chunk-GLZH5VEN.js} +2 -2
  143. package/dist/{chunk-S7T2TY65.js → chunk-HC4GFLMQ.js} +3 -3
  144. package/dist/{chunk-EQHDH4C2.js → chunk-HUT2JR6I.js} +3 -3
  145. package/dist/{chunk-UUQG7HAD.js → chunk-HXSAWV3A.js} +4 -4
  146. package/dist/{chunk-XXIHX75O.js → chunk-J7PB5UQ4.js} +3 -3
  147. package/dist/{chunk-UGPUYIET.js → chunk-JHZCXUQI.js} +221 -400
  148. package/dist/chunk-JHZCXUQI.js.map +1 -0
  149. package/dist/{chunk-LTIZHLV7.js → chunk-JR6H5CYS.js} +2 -2
  150. package/dist/{chunk-FCSZ4K2X.js → chunk-JR6PP7UM.js} +3 -3
  151. package/dist/{chunk-TCUKRAMK.js → chunk-JRWW7GM6.js} +10 -10
  152. package/dist/{chunk-Q726HSJO.js → chunk-JSRVXI6E.js} +16 -15
  153. package/dist/chunk-JSRVXI6E.js.map +1 -0
  154. package/dist/{chunk-DB5TGMLZ.js → chunk-JZ2CHRLB.js} +6 -4
  155. package/dist/{chunk-DB5TGMLZ.js.map → chunk-JZ2CHRLB.js.map} +1 -1
  156. package/dist/{chunk-JEIXTYVG.js → chunk-L2QLDZJC.js} +46 -17
  157. package/dist/chunk-L2QLDZJC.js.map +1 -0
  158. package/dist/{chunk-PL7FYKHT.js → chunk-L2WQVSKP.js} +2 -2
  159. package/dist/{chunk-JSN44KIB.js → chunk-LEMD7WZJ.js} +9 -9
  160. package/dist/{chunk-VZWXFXLX.js → chunk-LMCD5W5B.js} +2 -2
  161. package/dist/{chunk-7BMXZCOT.js → chunk-LNDLXMH6.js} +3 -3
  162. package/dist/{chunk-3QQTXYZ6.js → chunk-LSLCFCCQ.js} +2 -1
  163. package/dist/chunk-LSLCFCCQ.js.map +1 -0
  164. package/dist/{chunk-EONF76DT.js → chunk-LYDJRF45.js} +2 -2
  165. package/dist/{chunk-MKD3OMPS.js → chunk-M3MYMWXG.js} +2 -2
  166. package/dist/{chunk-VGXM5B4H.js → chunk-MNIPH6LD.js} +2 -2
  167. package/dist/{chunk-A7XEPMQ6.js → chunk-MVAQ2WM3.js} +6 -6
  168. package/dist/chunk-MVAQ2WM3.js.map +1 -0
  169. package/dist/{chunk-6N3TQFZU.js → chunk-NN4JEFON.js} +3 -3
  170. package/dist/chunk-NPNSKE76.js +220 -0
  171. package/dist/chunk-NPNSKE76.js.map +1 -0
  172. package/dist/{chunk-MOZXTRC2.js → chunk-OQ7SSRXP.js} +19 -19
  173. package/dist/{chunk-XU6OEECT.js → chunk-OQQXGYMX.js} +3 -3
  174. package/dist/{chunk-4MHYKEOM.js → chunk-OS2AT2JU.js} +10 -10
  175. package/dist/{chunk-N57A4KPV.js → chunk-P3ONDDIJ.js} +2 -2
  176. package/dist/chunk-PCEYGOSL.js +66 -0
  177. package/dist/chunk-PCEYGOSL.js.map +1 -0
  178. package/dist/{chunk-R3HKWWUB.js → chunk-PHP3MUGF.js} +2 -2
  179. package/dist/{chunk-EEOUMG3J.js → chunk-PWPIERBM.js} +38 -6
  180. package/dist/chunk-PWPIERBM.js.map +1 -0
  181. package/dist/chunk-Q4AUIFUA.js +111 -0
  182. package/dist/chunk-Q4AUIFUA.js.map +1 -0
  183. package/dist/{chunk-P3SB5BNT.js → chunk-QATYVTP7.js} +2 -2
  184. package/dist/{chunk-LSYDG6MJ.js → chunk-QBLDCI6E.js} +2 -2
  185. package/dist/{chunk-KCB7F4J7.js → chunk-QURNMKME.js} +2 -2
  186. package/dist/{chunk-XOVKXJEP.js → chunk-R3TLVTWW.js} +3 -3
  187. package/dist/{chunk-XXE5P6HJ.js → chunk-RRZKTSFG.js} +2 -2
  188. package/dist/{chunk-44T3Y7SZ.js → chunk-RUXPVSML.js} +5 -5
  189. package/dist/{chunk-DCJ3YFIC.js → chunk-S2ULTQZR.js} +2 -2
  190. package/dist/{chunk-H272ZPQ3.js → chunk-SHEHQBCG.js} +124 -23
  191. package/dist/chunk-SHEHQBCG.js.map +1 -0
  192. package/dist/{chunk-EEC4PCG5.js → chunk-SZDLX763.js} +2 -2
  193. package/dist/{chunk-E2ZHGBAK.js → chunk-T2JSUEH6.js} +2 -2
  194. package/dist/{chunk-227UFSEQ.js → chunk-TFA6HPOA.js} +2 -2
  195. package/dist/{chunk-BA6WOZOT.js → chunk-TK4FHQRN.js} +4 -4
  196. package/dist/{chunk-W27OW7AB.js → chunk-TKFSXDOB.js} +2 -2
  197. package/dist/chunk-TLHNF6GA.js +647 -0
  198. package/dist/chunk-TLHNF6GA.js.map +1 -0
  199. package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
  200. package/dist/{chunk-FDLDOEO6.js → chunk-UBG4GAEP.js} +51 -6
  201. package/dist/chunk-UBG4GAEP.js.map +1 -0
  202. package/dist/{chunk-CETXNLEX.js → chunk-UDZYNIDJ.js} +2 -2
  203. package/dist/{chunk-H5AFCNGA.js → chunk-UJX4I26O.js} +2 -2
  204. package/dist/{chunk-E6TDQRF6.js → chunk-UYUCCQ46.js} +2 -2
  205. package/dist/{chunk-BLUYQFRH.js → chunk-VELCIWJZ.js} +15 -11
  206. package/dist/chunk-VELCIWJZ.js.map +1 -0
  207. package/dist/{chunk-OQDPBRQ6.js → chunk-VYXDUPYE.js} +2 -2
  208. package/dist/{chunk-ZG74PWRW.js → chunk-VZAKYDMJ.js} +2 -2
  209. package/dist/chunk-W6IJMWTZ.js +72 -0
  210. package/dist/chunk-W6IJMWTZ.js.map +1 -0
  211. package/dist/{chunk-NB5BCFUY.js → chunk-WHHEPAO3.js} +4 -4
  212. package/dist/{chunk-H3TKENU4.js → chunk-WIKO4SCR.js} +5 -5
  213. package/dist/{chunk-TX2UTLXC.js → chunk-WPDKBUWX.js} +2 -2
  214. package/dist/{chunk-YFLLGRXO.js → chunk-X2QPKLPL.js} +2 -2
  215. package/dist/{chunk-PFFZWDPE.js → chunk-XCOV45MO.js} +3 -3
  216. package/dist/{chunk-5BCNEBEN.js → chunk-XPJNT6PI.js} +4 -4
  217. package/dist/chunk-XW2T4QAW.js +1 -0
  218. package/dist/{chunk-J7HFPA6O.js → chunk-Y63ZFP4X.js} +2 -2
  219. package/dist/{chunk-D223ZDQV.js → chunk-YEDVOYL2.js} +2 -2
  220. package/dist/{chunk-TLPZ6MKZ.js → chunk-YEN4TREG.js} +541 -5
  221. package/dist/chunk-YEN4TREG.js.map +1 -0
  222. package/dist/{chunk-22FVR2KE.js → chunk-YJ6VCDMZ.js} +6 -2
  223. package/dist/chunk-YJ6VCDMZ.js.map +1 -0
  224. package/dist/{chunk-RC5DXXWC.js → chunk-YM7YN37H.js} +2 -2
  225. package/dist/{chunk-BPJNF7J2.js → chunk-YNN26CIZ.js} +2 -2
  226. package/dist/{chunk-VLXBE57O.js → chunk-YVGXH72Y.js} +2 -2
  227. package/dist/{chunk-YQAXP5AC.js → chunk-YXLUTALO.js} +5 -5
  228. package/dist/{chunk-DGGB65KC.js → chunk-Z7ACR6MJ.js} +3 -3
  229. package/dist/{chunk-X35W4S3L.js → chunk-ZBEGS7OB.js} +4 -4
  230. package/dist/{chunk-O75CRYGF.js → chunk-ZEFVK7XC.js} +1 -1
  231. package/dist/chunk-ZEFVK7XC.js.map +1 -0
  232. package/dist/{chunk-XUE46UYW.js → chunk-ZLN7AROH.js} +6 -6
  233. package/dist/{chunk-E6JA6XWY.js → chunk-ZTG4P7NZ.js} +1013 -1317
  234. package/dist/chunk-ZTG4P7NZ.js.map +1 -0
  235. package/dist/{chunk-HK32G473.js → chunk-ZWEZXVYH.js} +2 -2
  236. package/dist/{cli-D57e2Mqt.d.ts → cli-Bk7Ctql4.d.ts} +5 -5
  237. package/dist/cli-fallback.d.ts +11 -4
  238. package/dist/cli-fallback.js +5 -1
  239. package/dist/cli.d.ts +16 -13
  240. package/dist/cli.js +107 -103
  241. package/dist/coding/export-okf-codegraph.d.ts +3 -1
  242. package/dist/coding/export-okf-codegraph.js +32 -30
  243. package/dist/coding/export-okf-codegraph.js.map +1 -1
  244. package/dist/coding/pre-action-gate.d.ts +3 -1
  245. package/dist/compat/checks.js +2 -2
  246. package/dist/compat/codex-cli-fallback.d.ts +1 -1
  247. package/dist/compat/codex-cli-fallback.js +5 -1
  248. package/dist/compat/codex-cli-fallback.js.map +1 -1
  249. package/dist/compounding/engine.d.ts +4 -2
  250. package/dist/compounding/engine.js +27 -26
  251. package/dist/compounding/preference-consolidator.d.ts +3 -1
  252. package/dist/compression-optimizer.d.ts +3 -1
  253. package/dist/config.d.ts +3 -1
  254. package/dist/config.js +12 -10
  255. package/dist/connectors/codex-materialize-runner.d.ts +3 -1
  256. package/dist/connectors/codex-materialize-runner.js +26 -25
  257. package/dist/connectors/codex-materialize.d.ts +3 -1
  258. package/dist/connectors/index.d.ts +3 -1
  259. package/dist/connectors/index.js +28 -27
  260. package/dist/consolidation-provenance-check.d.ts +4 -2
  261. package/dist/consolidation-undo.d.ts +4 -2
  262. package/dist/contradiction/index.d.ts +5 -3
  263. package/dist/contradiction/index.js +5 -5
  264. package/dist/{contradiction-scan-NOYMFG66.js → contradiction-scan-GVD4JJ7B.js} +3 -3
  265. package/dist/converge-config.d.ts +3 -1
  266. package/dist/convergence-refresh.d.ts +4 -2
  267. package/dist/convergence-refresh.js +28 -27
  268. package/dist/conversation-index/backend.d.ts +3 -1
  269. package/dist/conversation-index/backend.js +3 -3
  270. package/dist/conversation-index/chunker.d.ts +3 -1
  271. package/dist/conversation-index/faiss-adapter.d.ts +3 -1
  272. package/dist/conversation-index/faiss-adapter.js +2 -2
  273. package/dist/conversation-index/indexer.d.ts +3 -1
  274. package/dist/conversation-index/search.d.ts +3 -1
  275. package/dist/corpus-watermark.d.ts +3 -1
  276. package/dist/corpus-watermark.js +29 -28
  277. package/dist/cross-lingual-recall.d.ts +3 -1
  278. package/dist/day-summary.d.ts +3 -1
  279. package/dist/deep-recall-http-glue.d.ts +14 -11
  280. package/dist/deep-recall-http-glue.js +12 -2
  281. package/dist/deep-recall-mcp-tools.d.ts +14 -11
  282. package/dist/deep-recall-policy-llm.d.ts +3 -1
  283. package/dist/deep-recall-policy-llm.js +4 -3
  284. package/dist/deep-recall-seeds.d.ts +3 -1
  285. package/dist/delinearize.d.ts +3 -1
  286. package/dist/dependency-propagation-config.d.ts +3 -1
  287. package/dist/{dependency-propagation-delivery-CmniEsUK.d.ts → dependency-propagation-delivery-DLiAtj25.d.ts} +1 -1
  288. package/dist/direct-answer-wiring.d.ts +3 -1
  289. package/dist/direct-answer.d.ts +3 -1
  290. package/dist/embedding-fallback.d.ts +3 -1
  291. package/dist/enrichment/index.d.ts +3 -1
  292. package/dist/entity-origin-fields.d.ts +3 -1
  293. package/dist/entity-retrieval.d.ts +4 -2
  294. package/dist/entity-retrieval.js +26 -25
  295. package/dist/entity-schema.d.ts +3 -1
  296. package/dist/episodic-context.d.ts +3 -1
  297. package/dist/eval-trajectory-contracts.d.ts +3 -1
  298. package/dist/eval-trajectory-store.d.ts +3 -1
  299. package/dist/eval-trajectory.d.ts +3 -1
  300. package/dist/explicit-capture.d.ts +12 -9
  301. package/dist/explicit-capture.js +6 -6
  302. package/dist/external-wiki-access.d.ts +14 -11
  303. package/dist/external-wiki-access.js +66 -61
  304. package/dist/external-wiki-collection-registration.d.ts +3 -1
  305. package/dist/external-wiki-collection.d.ts +3 -1
  306. package/dist/external-wiki-mcp-tools.d.ts +14 -11
  307. package/dist/extraction-error-classification.d.ts +3 -1
  308. package/dist/extraction-faithfulness.d.ts +3 -1
  309. package/dist/extraction-faithfulness.js +4 -3
  310. package/dist/extraction-judge-telemetry.d.ts +3 -1
  311. package/dist/extraction-judge-training.d.ts +3 -1
  312. package/dist/extraction-judge.d.ts +3 -1
  313. package/dist/extraction-judge.js +5 -4
  314. package/dist/extraction-liveness.d.ts +3 -1
  315. package/dist/extraction-normalization.d.ts +3 -1
  316. package/dist/extraction-prompt.d.ts +3 -1
  317. package/dist/extraction-source-grounding-rules.d.ts +3 -1
  318. package/dist/extraction-source-grounding.d.ts +3 -1
  319. package/dist/extraction.d.ts +3 -1
  320. package/dist/extraction.js +38 -36
  321. package/dist/fallback-llm.d.ts +3 -1
  322. package/dist/fallback-llm.js +3 -2
  323. package/dist/{first-start-migration-RC345GPL.js → first-start-migration-L3UFX5CU.js} +3 -3
  324. package/dist/generic-recall-paths-DbitKJI5.d.ts +23 -0
  325. package/dist/graph-append-error.d.ts +3 -1
  326. package/dist/graph-dashboard-diff.d.ts +3 -1
  327. package/dist/graph-dashboard-key.d.ts +3 -1
  328. package/dist/graph-dashboard-parser.d.ts +3 -1
  329. package/dist/graph-edge-reinforcement.d.ts +3 -1
  330. package/dist/graph-jsonl.d.ts +3 -1
  331. package/dist/graph-path-reconstruction.d.ts +3 -1
  332. package/dist/graph-path-scoring.d.ts +3 -1
  333. package/dist/graph-snapshot.d.ts +3 -1
  334. package/dist/graph.d.ts +3 -1
  335. package/dist/harmonic-retrieval.js +2 -2
  336. package/dist/importance.d.ts +3 -1
  337. package/dist/importers/index.d.ts +3 -1
  338. package/dist/importers/test-utils.d.ts +3 -1
  339. package/dist/in-flight-reads.d.ts +3 -1
  340. package/dist/{index-BTAsSkPG.d.ts → index-BINUgPFo.d.ts} +2 -2
  341. package/dist/index.d.ts +303 -245
  342. package/dist/index.js +316 -214
  343. package/dist/intent.d.ts +3 -1
  344. package/dist/lcm/engine.d.ts +3 -1
  345. package/dist/lcm/engine.js +2 -2
  346. package/dist/lcm/index.d.ts +3 -1
  347. package/dist/lcm/index.js +7 -7
  348. package/dist/lcm/tools.d.ts +3 -1
  349. package/dist/lifecycle.d.ts +3 -1
  350. package/dist/live-connectors-runner.d.ts +3 -1
  351. package/dist/local-llm-config.d.ts +26 -0
  352. package/dist/local-llm-config.js +1 -0
  353. package/dist/local-llm.d.ts +5 -1
  354. package/dist/local-llm.js +3 -3
  355. package/dist/local-model-endpoint.d.ts +3 -1
  356. package/dist/location/index.d.ts +5 -3
  357. package/dist/location/index.js +29 -28
  358. package/dist/maintenance/memory-governance.d.ts +3 -1
  359. package/dist/maintenance/memory-governance.js +26 -25
  360. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +4 -2
  361. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +26 -25
  362. package/dist/maintenance/rebuild-memory-projection.d.ts +4 -2
  363. package/dist/maintenance/rebuild-memory-projection.js +27 -26
  364. package/dist/{maintenance-DCvQGTzL.d.ts → maintenance-ag1gYztC.d.ts} +378 -4
  365. package/dist/mcp-memory-inspector-app.d.ts +14 -11
  366. package/dist/memory-action-policy.d.ts +3 -1
  367. package/dist/memory-cache.d.ts +3 -1
  368. package/dist/memory-controller.d.ts +3 -1
  369. package/dist/memory-lifecycle-ledger-utils.d.ts +3 -1
  370. package/dist/memory-projection-store.d.ts +3 -1
  371. package/dist/memory-provenance.d.ts +3 -1
  372. package/dist/memory-snapshot.d.ts +3 -1
  373. package/dist/memory-subject-cli.d.ts +14 -11
  374. package/dist/memory-subject.d.ts +14 -11
  375. package/dist/memory-worth-outcomes.d.ts +4 -2
  376. package/dist/migrate/from-engram.js +2 -2
  377. package/dist/models-json.d.ts +3 -1
  378. package/dist/namespaces/migrate.d.ts +5 -3
  379. package/dist/namespaces/migrate.js +27 -26
  380. package/dist/namespaces/principal.d.ts +3 -1
  381. package/dist/namespaces/search.d.ts +3 -1
  382. package/dist/namespaces/search.js +8 -8
  383. package/dist/namespaces/storage.d.ts +5 -3
  384. package/dist/namespaces/storage.js +26 -25
  385. package/dist/native-knowledge.d.ts +3 -1
  386. package/dist/network/tailscale.js +2 -2
  387. package/dist/offline-sync-impression-drain.d.ts +3 -1
  388. package/dist/offline-sync-impression-drain.js +6 -6
  389. package/dist/operator-doctor-corpus.d.ts +3 -1
  390. package/dist/operator-doctor-corpus.js +30 -29
  391. package/dist/operator-doctor-replica.d.ts +3 -1
  392. package/dist/operator-toolkit.d.ts +5 -3
  393. package/dist/operator-toolkit.js +44 -42
  394. package/dist/orchestration/compression-guideline-coordinator.d.ts +4 -2
  395. package/dist/orchestration/maintenance.d.ts +6 -4
  396. package/dist/orchestration/maintenance.js +44 -39
  397. package/dist/{orchestrator-CvCsp1tz.d.ts → orchestrator-Cf3G-3Ed.d.ts} +17 -29
  398. package/dist/orchestrator.d.ts +12 -9
  399. package/dist/orchestrator.js +141 -135
  400. package/dist/patterns-cli.d.ts +3 -1
  401. package/dist/{pipeline-JAdwKBS7.d.ts → pipeline-AwB03fw_.d.ts} +1 -1
  402. package/dist/policy-runtime.d.ts +3 -1
  403. package/dist/proactive-contention.d.ts +3 -1
  404. package/dist/provenance.d.ts +3 -1
  405. package/dist/{public-http-h-yWu9rj.d.ts → public-http-BetSQn7q.d.ts} +1 -1
  406. package/dist/{qmd-Cvw9RWKr.d.ts → qmd-Bfaydrfm.d.ts} +1 -1
  407. package/dist/qmd-preflight.d.ts +4 -2
  408. package/dist/qmd-recall-cache.d.ts +3 -1
  409. package/dist/qmd.d.ts +4 -2
  410. package/dist/qmd.js +2 -2
  411. package/dist/recall-concurrency-config.d.ts +3 -1
  412. package/dist/recall-disclosure-escalation.d.ts +3 -1
  413. package/dist/recall-explain-renderer.d.ts +3 -1
  414. package/dist/recall-explain-renderer.js +3 -3
  415. package/dist/recall-memory-map.d.ts +3 -1
  416. package/dist/recall-navigate-access.d.ts +3 -1
  417. package/dist/recall-navigate-access.js +2 -2
  418. package/dist/recall-navigate-disclosure.d.ts +3 -1
  419. package/dist/recall-navigate-disclosure.js +1 -1
  420. package/dist/recall-navigate.d.ts +3 -1
  421. package/dist/recall-navigate.js +2 -2
  422. package/dist/recall-planner-llm.d.ts +3 -1
  423. package/dist/recall-planner-llm.js +3 -2
  424. package/dist/recall-planner-llm.js.map +1 -1
  425. package/dist/recall-state-view-admission.d.ts +57 -0
  426. package/dist/recall-state-view-admission.js +39 -0
  427. package/dist/recall-state-view-admission.js.map +1 -0
  428. package/dist/recall-state-view-inject.js +2 -2
  429. package/dist/recall-state-view-render.js +2 -2
  430. package/dist/recall-state-view-widen.d.ts +18 -1
  431. package/dist/recall-state-view-widen.js +2 -2
  432. package/dist/recall-state-view-wire.d.ts +1 -1
  433. package/dist/recall-state-view-wire.js +3 -3
  434. package/dist/recall-state-view.d.ts +1 -0
  435. package/dist/recall-state-view.js +1 -1
  436. package/dist/recall-state.d.ts +3 -1
  437. package/dist/recall-tag-filter.d.ts +3 -1
  438. package/dist/recall-timings.d.ts +3 -1
  439. package/dist/recall-xray-cli.d.ts +3 -1
  440. package/dist/recall-xray-cli.js +4 -4
  441. package/dist/recall-xray-renderer.d.ts +3 -1
  442. package/dist/recall-xray-renderer.js +3 -3
  443. package/dist/recall-xray.d.ts +10 -1
  444. package/dist/recall-xray.js +2 -2
  445. package/dist/reconcile/cursor.d.ts +12 -2
  446. package/dist/reconcile/cursor.js +6 -4
  447. package/dist/reconcile/cursor.js.map +1 -1
  448. package/dist/reconcile/manifest.d.ts +38 -2
  449. package/dist/reconcile/manifest.js +15 -5
  450. package/dist/reconcile/plan.d.ts +3 -1
  451. package/dist/replay/normalizers/chatgpt.d.ts +3 -1
  452. package/dist/replay/normalizers/claude.d.ts +3 -1
  453. package/dist/replay/normalizers/openclaw.d.ts +3 -1
  454. package/dist/replay/normalizers/shared.d.ts +3 -1
  455. package/dist/replay/runner.d.ts +3 -1
  456. package/dist/replay/types.d.ts +3 -1
  457. package/dist/replica-divergence.d.ts +3 -1
  458. package/dist/replica-peers-config.d.ts +3 -1
  459. package/dist/{resolution-VKATP2HT.js → resolution-OHJZG45O.js} +6 -6
  460. package/dist/resolution-OHJZG45O.js.map +1 -0
  461. package/dist/resolve-auth-token.d.ts +3 -1
  462. package/dist/resume-bundles.js +13 -11
  463. package/dist/retrieval-agents.d.ts +4 -2
  464. package/dist/retrieval-tiers.d.ts +3 -1
  465. package/dist/routing/engine.d.ts +3 -1
  466. package/dist/routing/store.d.ts +3 -1
  467. package/dist/runtime/child-process.d.ts +1 -1
  468. package/dist/runtime/child-process.js +1 -1
  469. package/dist/salvage-envelope.d.ts +3 -1
  470. package/dist/salvage-envelope.js +2 -2
  471. package/dist/{scope-profiles-BShpTPeV.d.ts → scope-profiles-nxTKvjE-.d.ts} +1 -1
  472. package/dist/search/embed-helper.d.ts +3 -1
  473. package/dist/search/factory.d.ts +3 -1
  474. package/dist/search/factory.js +7 -7
  475. package/dist/search/index.d.ts +3 -1
  476. package/dist/search/index.js +11 -11
  477. package/dist/search/lancedb-backend.d.ts +3 -1
  478. package/dist/search/meilisearch-backend.d.ts +3 -1
  479. package/dist/search/noop-backend.d.ts +3 -1
  480. package/dist/search/orama-backend.d.ts +3 -1
  481. package/dist/search/port.d.ts +3 -1
  482. package/dist/search/remote-backend.d.ts +3 -1
  483. package/dist/{semantic-consolidation-CusOpe9F.d.ts → semantic-consolidation-C83DVakV.d.ts} +1 -1
  484. package/dist/semantic-consolidation.d.ts +4 -2
  485. package/dist/semantic-consolidation.js +27 -26
  486. package/dist/semantic-rule-promotion.js +26 -25
  487. package/dist/semantic-rule-verifier.d.ts +3 -1
  488. package/dist/semantic-rule-verifier.js +26 -25
  489. package/dist/{service-BbuVh1eS.d.ts → service-q-xtOoAr.d.ts} +2 -2
  490. package/dist/session-observer-bands.d.ts +3 -1
  491. package/dist/session-observer-state.d.ts +3 -1
  492. package/dist/shared-context/manager.d.ts +3 -1
  493. package/dist/signal.d.ts +3 -1
  494. package/dist/source-agent-qualifier.d.ts +3 -1
  495. package/dist/source-agent-qualifier.js +35 -33
  496. package/dist/standup/build.js +26 -25
  497. package/dist/{storage-BBLLuVTF.d.ts → storage-Ca0MbTfm.d.ts} +67 -6
  498. package/dist/storage.d.ts +5 -3
  499. package/dist/storage.js +25 -24
  500. package/dist/subject-config.d.ts +3 -1
  501. package/dist/subject-config.js +2 -2
  502. package/dist/summarizer.d.ts +3 -1
  503. package/dist/summarizer.js +6 -6
  504. package/dist/summary-snapshot.d.ts +3 -1
  505. package/dist/support-passport/index.d.ts +50 -15
  506. package/dist/support-passport/index.js +73 -64
  507. package/dist/temporal-supersession.d.ts +4 -2
  508. package/dist/temporal-timeline-recall.d.ts +3 -1
  509. package/dist/temporal-validity.d.ts +3 -1
  510. package/dist/threading.d.ts +3 -1
  511. package/dist/tier-migration.d.ts +4 -2
  512. package/dist/tier-routing.d.ts +3 -1
  513. package/dist/tier-routing.js +2 -2
  514. package/dist/{tier-stats-KA6OZX2C.js → tier-stats-VK5PCO2L.js} +3 -3
  515. package/dist/topics.d.ts +3 -1
  516. package/dist/transcript.d.ts +3 -1
  517. package/dist/transfer/capsule-import.js +1 -1
  518. package/dist/transfer/export-okf.d.ts +3 -1
  519. package/dist/transfer/export-okf.js +27 -26
  520. package/dist/transfer/types.d.ts +24 -24
  521. package/dist/trust-score-stage.d.ts +3 -1
  522. package/dist/trust-score.d.ts +3 -1
  523. package/dist/{types-igV4-sbB.d.ts → types-yDgWDkrJ.d.ts} +60 -34
  524. package/dist/types.d.ts +3 -1
  525. package/dist/types.js +1 -1
  526. package/dist/utility-runtime.d.ts +3 -1
  527. package/dist/verified-recall.js +26 -25
  528. package/dist/who-knows-cli.d.ts +14 -11
  529. package/dist/who-knows-cli.js +27 -26
  530. package/dist/who-knows.d.ts +14 -11
  531. package/dist/who-knows.js +26 -25
  532. package/dist/write-envelope.d.ts +5 -2
  533. package/dist/write-envelope.js +3 -1
  534. package/package.json +2 -2
  535. package/src/access-category-alias.test.ts +216 -0
  536. package/src/access-mcp.test.ts +73 -0
  537. package/src/access-mcp.ts +6 -6
  538. package/src/access-observe-write-surface.ts +19 -4
  539. package/src/access-offline-manifest.ts +297 -16
  540. package/src/access-recall-surface.ts +5 -5
  541. package/src/access-schema.ts +76 -7
  542. package/src/access-service.ts +11 -2
  543. package/src/activity/config.test.ts +124 -1
  544. package/src/activity/config.ts +150 -18
  545. package/src/activity/index.ts +3 -0
  546. package/src/activity/journal-extract-storage.test.ts +129 -0
  547. package/src/activity/journal-extract.test.ts +314 -0
  548. package/src/activity/journal-extract.ts +247 -0
  549. package/src/activity/journal-heading.test.ts +24 -1
  550. package/src/activity/journal-heading.ts +36 -0
  551. package/src/activity/journal-read.test.ts +242 -0
  552. package/src/activity/journal-read.ts +183 -0
  553. package/src/activity/journal-source.test.ts +15 -15
  554. package/src/activity/journal-source.ts +21 -14
  555. package/src/activity/journal-state.lock-worker.ts +30 -0
  556. package/src/activity/journal-state.test.ts +144 -0
  557. package/src/activity/journal-state.ts +107 -0
  558. package/src/activity/journal-strip.test.ts +106 -52
  559. package/src/activity/journal-strip.ts +35 -10
  560. package/src/activity/journal-vault-integration.test.ts +230 -0
  561. package/src/activity/journal-vault-provenance.test.ts +9 -7
  562. package/src/activity/journal-vault-provenance.ts +4 -10
  563. package/src/activity/journal-vault-read.test.ts +3 -2
  564. package/src/activity/journal-vault-read.ts +9 -139
  565. package/src/activity/journal.test.ts +74 -23
  566. package/src/activity/runner.test.ts +116 -1
  567. package/src/activity/runner.ts +25 -0
  568. package/src/activity/scheduler.ts +4 -0
  569. package/src/activity/store.test.ts +18 -0
  570. package/src/activity/store.ts +14 -0
  571. package/src/activity/sync-registration.ts +4 -0
  572. package/src/activity/timeline/analysis-metadata.ts +2 -0
  573. package/src/activity/timeline/analysis-provider.ts +140 -0
  574. package/src/activity/timeline/analysis-run.test.ts +419 -0
  575. package/src/activity/timeline/analysis-run.ts +106 -0
  576. package/src/activity/timeline/analysis.ts +66 -37
  577. package/src/activity/timeline/corrections.ts +9 -0
  578. package/src/activity/timeline/index.ts +3 -0
  579. package/src/activity/timeline/query.test.ts +71 -0
  580. package/src/activity/timeline/query.ts +57 -8
  581. package/src/activity/timeline/regenerate.test.ts +505 -0
  582. package/src/activity/timeline/regenerate.ts +373 -0
  583. package/src/activity/types.ts +40 -5
  584. package/src/adapters/grok-opencode.test.ts +146 -0
  585. package/src/adapters/grok.ts +53 -0
  586. package/src/adapters/index.ts +2 -0
  587. package/src/adapters/opencode.ts +52 -0
  588. package/src/adapters/registry.ts +4 -0
  589. package/src/cli-fallback.ts +13 -4
  590. package/src/config.test.ts +27 -1
  591. package/src/config.ts +17 -1
  592. package/src/dedup/merge.test.ts +732 -25
  593. package/src/fallback-llm.test.ts +53 -0
  594. package/src/fallback-llm.ts +12 -0
  595. package/src/index.ts +2 -0
  596. package/src/local-llm-config.ts +25 -0
  597. package/src/local-llm.ts +3 -1
  598. package/src/orchestration/dependency-propagation-recovery-replay.ts +1 -1
  599. package/src/orchestration/extraction-persist-deps.ts +9 -0
  600. package/src/orchestration/extraction-persist-promotion.test.ts +265 -6
  601. package/src/orchestration/extraction-persist-promotion.ts +42 -3
  602. package/src/orchestration/extraction-persist.ts +3 -3
  603. package/src/orchestration/harmonic-construction-persist.test.ts +115 -4
  604. package/src/orchestration/harmonic-construction-persist.ts +34 -6
  605. package/src/orchestration/maintenance.ts +1 -0
  606. package/src/orchestration/orchestrator-helpers.ts +6 -0
  607. package/src/orchestration/recall-entry.ts +16 -0
  608. package/src/orchestration/recall-internal-deps.ts +14 -0
  609. package/src/orchestration/recall-internal.ts +41 -58
  610. package/src/orchestration/recall-result-formatter.ts +11 -1
  611. package/src/orchestration/recall-search-pipeline.ts +121 -11
  612. package/src/orchestration/recall-state-view-pipeline.test.ts +211 -0
  613. package/src/orchestration/semantic-merge-commit-effects.ts +76 -17
  614. package/src/orchestration/semantic-merge-persist.ts +121 -16
  615. package/src/orchestration/semantic-merge-promotion-payload.ts +133 -54
  616. package/src/orchestrator.ts +7 -35
  617. package/src/providers/codex-subscription.test.ts +666 -0
  618. package/src/providers/codex-subscription.ts +743 -0
  619. package/src/recall-disclosure.test.ts +20 -0
  620. package/src/recall-state-view-admission.ts +114 -0
  621. package/src/recall-state-view-asof.test.ts +176 -0
  622. package/src/recall-state-view-call.test.ts +175 -0
  623. package/src/recall-state-view-config.test.ts +16 -0
  624. package/src/recall-state-view-widen.test.ts +70 -0
  625. package/src/recall-state-view-widen.ts +28 -7
  626. package/src/recall-state-view-wire.ts +3 -1
  627. package/src/recall-state-view-zero-diff.test.ts +20 -11
  628. package/src/recall-state-view.test.ts +142 -0
  629. package/src/recall-state-view.ts +72 -24
  630. package/src/recall-xray-renderer.test.ts +27 -0
  631. package/src/recall-xray-renderer.ts +4 -0
  632. package/src/recall-xray.ts +13 -0
  633. package/src/reconcile/cursor.ts +23 -33
  634. package/src/reconcile/manifest.ts +96 -11
  635. package/src/reconcile-identity-cache.test.ts +378 -0
  636. package/src/runtime/child-process.ts +1 -1
  637. package/src/storage/cas-revision-host.ts +75 -0
  638. package/src/storage/cas-revision-store.test.ts +459 -0
  639. package/src/storage/cas-revision-store.ts +661 -0
  640. package/src/storage/deletion-revision-store.ts +80 -6
  641. package/src/storage/tombstone-blocked-capture-index.ts +15 -0
  642. package/src/storage/tombstone-blocked-capture-mutation.ts +67 -7
  643. package/src/storage/tombstone-blocked-capture-sync.ts +55 -20
  644. package/src/storage-contract/failure-semantics.test.ts +1 -1
  645. package/src/storage-frontmatter-cas.test.ts +698 -1
  646. package/src/storage-replay.test.ts +166 -3
  647. package/src/storage.ts +41 -41
  648. package/src/support-passport/card-projection.ts +82 -33
  649. package/src/temporal-supersession.test.ts +10 -10
  650. package/src/types.ts +10 -29
  651. package/src/write-envelope.ts +1 -1
  652. package/dist/chunk-22FVR2KE.js.map +0 -1
  653. package/dist/chunk-2C3S7J2S.js.map +0 -1
  654. package/dist/chunk-2JVJ7UHC.js.map +0 -1
  655. package/dist/chunk-2QSZNTDO.js +0 -56
  656. package/dist/chunk-2QSZNTDO.js.map +0 -1
  657. package/dist/chunk-3QQTXYZ6.js.map +0 -1
  658. package/dist/chunk-5VCDKQWQ.js +0 -560
  659. package/dist/chunk-5VCDKQWQ.js.map +0 -1
  660. package/dist/chunk-A7XEPMQ6.js.map +0 -1
  661. package/dist/chunk-BLUYQFRH.js.map +0 -1
  662. package/dist/chunk-E6JA6XWY.js.map +0 -1
  663. package/dist/chunk-EEOUMG3J.js.map +0 -1
  664. package/dist/chunk-FDLDOEO6.js.map +0 -1
  665. package/dist/chunk-FYDW33ZB.js +0 -13
  666. package/dist/chunk-H272ZPQ3.js.map +0 -1
  667. package/dist/chunk-HV7OY4DM.js.map +0 -1
  668. package/dist/chunk-HVAEXYPL.js.map +0 -1
  669. package/dist/chunk-JEIXTYVG.js.map +0 -1
  670. package/dist/chunk-LRICZIGN.js +0 -52
  671. package/dist/chunk-LRICZIGN.js.map +0 -1
  672. package/dist/chunk-MFDTVQJX.js.map +0 -1
  673. package/dist/chunk-N7RWREIQ.js.map +0 -1
  674. package/dist/chunk-O75CRYGF.js.map +0 -1
  675. package/dist/chunk-Q726HSJO.js.map +0 -1
  676. package/dist/chunk-QOIOACIE.js.map +0 -1
  677. package/dist/chunk-SEDEKFYQ.js +0 -1
  678. package/dist/chunk-SO7SV523.js.map +0 -1
  679. package/dist/chunk-TLPZ6MKZ.js.map +0 -1
  680. package/dist/chunk-UGPUYIET.js.map +0 -1
  681. package/src/activity/journal-mode.test.ts +0 -32
  682. package/src/activity/journal-mode.ts +0 -20
  683. /package/dist/{capsule-merge-IPG4IOFP.js.map → capsule-merge-ZCXUPLNJ.js.map} +0 -0
  684. /package/dist/{chunk-CDKHKZL5.js.map → chunk-2524MOWK.js.map} +0 -0
  685. /package/dist/{chunk-RKBLRTNT.js.map → chunk-2YLMUME2.js.map} +0 -0
  686. /package/dist/{chunk-DBQWVT2H.js.map → chunk-3CBI2ZSA.js.map} +0 -0
  687. /package/dist/{chunk-MWFGUESQ.js.map → chunk-3FJKJ5UZ.js.map} +0 -0
  688. /package/dist/{chunk-NZXEK3UF.js.map → chunk-3Q3N35W7.js.map} +0 -0
  689. /package/dist/{chunk-YYGZJPOK.js.map → chunk-42DJ235G.js.map} +0 -0
  690. /package/dist/{chunk-JTH2SE6B.js.map → chunk-6J6K3STG.js.map} +0 -0
  691. /package/dist/{chunk-H4VH5VIB.js.map → chunk-776GVKL7.js.map} +0 -0
  692. /package/dist/{chunk-BUTCAMJM.js.map → chunk-A2YQL2FF.js.map} +0 -0
  693. /package/dist/{chunk-X2NFFBTO.js.map → chunk-A7GQBJP5.js.map} +0 -0
  694. /package/dist/{chunk-CGC5UQCF.js.map → chunk-AKE4GGQ3.js.map} +0 -0
  695. /package/dist/{chunk-B325AGLK.js.map → chunk-AZSKROVQ.js.map} +0 -0
  696. /package/dist/{chunk-I5DZ3WGR.js.map → chunk-BJETIR53.js.map} +0 -0
  697. /package/dist/{chunk-JT3EB7ZL.js.map → chunk-BNGHPYZU.js.map} +0 -0
  698. /package/dist/{chunk-3JVLGJCY.js.map → chunk-C6KRO3SU.js.map} +0 -0
  699. /package/dist/{chunk-5NANRSCD.js.map → chunk-CNV2A557.js.map} +0 -0
  700. /package/dist/{chunk-PBGVVDLY.js.map → chunk-DK4X5B6I.js.map} +0 -0
  701. /package/dist/{chunk-N2ZNPHA3.js.map → chunk-ECKG5WSI.js.map} +0 -0
  702. /package/dist/{chunk-PYLL63BF.js.map → chunk-EEBQFG5E.js.map} +0 -0
  703. /package/dist/{chunk-ET356KSB.js.map → chunk-F4TWWUMP.js.map} +0 -0
  704. /package/dist/{chunk-CLLPJ6QT.js.map → chunk-FQXJAC3T.js.map} +0 -0
  705. /package/dist/{chunk-JGHXXQ2G.js.map → chunk-FVJ4D6L7.js.map} +0 -0
  706. /package/dist/{chunk-DD5JFCWM.js.map → chunk-GCBIXUPT.js.map} +0 -0
  707. /package/dist/{chunk-MN3LK3KN.js.map → chunk-GLZH5VEN.js.map} +0 -0
  708. /package/dist/{chunk-S7T2TY65.js.map → chunk-HC4GFLMQ.js.map} +0 -0
  709. /package/dist/{chunk-EQHDH4C2.js.map → chunk-HUT2JR6I.js.map} +0 -0
  710. /package/dist/{chunk-UUQG7HAD.js.map → chunk-HXSAWV3A.js.map} +0 -0
  711. /package/dist/{chunk-XXIHX75O.js.map → chunk-J7PB5UQ4.js.map} +0 -0
  712. /package/dist/{chunk-LTIZHLV7.js.map → chunk-JR6H5CYS.js.map} +0 -0
  713. /package/dist/{chunk-FCSZ4K2X.js.map → chunk-JR6PP7UM.js.map} +0 -0
  714. /package/dist/{chunk-TCUKRAMK.js.map → chunk-JRWW7GM6.js.map} +0 -0
  715. /package/dist/{chunk-PL7FYKHT.js.map → chunk-L2WQVSKP.js.map} +0 -0
  716. /package/dist/{chunk-JSN44KIB.js.map → chunk-LEMD7WZJ.js.map} +0 -0
  717. /package/dist/{chunk-VZWXFXLX.js.map → chunk-LMCD5W5B.js.map} +0 -0
  718. /package/dist/{chunk-7BMXZCOT.js.map → chunk-LNDLXMH6.js.map} +0 -0
  719. /package/dist/{chunk-EONF76DT.js.map → chunk-LYDJRF45.js.map} +0 -0
  720. /package/dist/{chunk-MKD3OMPS.js.map → chunk-M3MYMWXG.js.map} +0 -0
  721. /package/dist/{chunk-VGXM5B4H.js.map → chunk-MNIPH6LD.js.map} +0 -0
  722. /package/dist/{chunk-6N3TQFZU.js.map → chunk-NN4JEFON.js.map} +0 -0
  723. /package/dist/{chunk-MOZXTRC2.js.map → chunk-OQ7SSRXP.js.map} +0 -0
  724. /package/dist/{chunk-XU6OEECT.js.map → chunk-OQQXGYMX.js.map} +0 -0
  725. /package/dist/{chunk-4MHYKEOM.js.map → chunk-OS2AT2JU.js.map} +0 -0
  726. /package/dist/{chunk-N57A4KPV.js.map → chunk-P3ONDDIJ.js.map} +0 -0
  727. /package/dist/{chunk-R3HKWWUB.js.map → chunk-PHP3MUGF.js.map} +0 -0
  728. /package/dist/{chunk-P3SB5BNT.js.map → chunk-QATYVTP7.js.map} +0 -0
  729. /package/dist/{chunk-LSYDG6MJ.js.map → chunk-QBLDCI6E.js.map} +0 -0
  730. /package/dist/{chunk-KCB7F4J7.js.map → chunk-QURNMKME.js.map} +0 -0
  731. /package/dist/{chunk-XOVKXJEP.js.map → chunk-R3TLVTWW.js.map} +0 -0
  732. /package/dist/{chunk-XXE5P6HJ.js.map → chunk-RRZKTSFG.js.map} +0 -0
  733. /package/dist/{chunk-44T3Y7SZ.js.map → chunk-RUXPVSML.js.map} +0 -0
  734. /package/dist/{chunk-DCJ3YFIC.js.map → chunk-S2ULTQZR.js.map} +0 -0
  735. /package/dist/{chunk-EEC4PCG5.js.map → chunk-SZDLX763.js.map} +0 -0
  736. /package/dist/{chunk-E2ZHGBAK.js.map → chunk-T2JSUEH6.js.map} +0 -0
  737. /package/dist/{chunk-227UFSEQ.js.map → chunk-TFA6HPOA.js.map} +0 -0
  738. /package/dist/{chunk-BA6WOZOT.js.map → chunk-TK4FHQRN.js.map} +0 -0
  739. /package/dist/{chunk-W27OW7AB.js.map → chunk-TKFSXDOB.js.map} +0 -0
  740. /package/dist/{chunk-7K5Q6COX.js.map → chunk-TVVEYCNW.js.map} +0 -0
  741. /package/dist/{chunk-CETXNLEX.js.map → chunk-UDZYNIDJ.js.map} +0 -0
  742. /package/dist/{chunk-H5AFCNGA.js.map → chunk-UJX4I26O.js.map} +0 -0
  743. /package/dist/{chunk-E6TDQRF6.js.map → chunk-UYUCCQ46.js.map} +0 -0
  744. /package/dist/{chunk-OQDPBRQ6.js.map → chunk-VYXDUPYE.js.map} +0 -0
  745. /package/dist/{chunk-ZG74PWRW.js.map → chunk-VZAKYDMJ.js.map} +0 -0
  746. /package/dist/{chunk-NB5BCFUY.js.map → chunk-WHHEPAO3.js.map} +0 -0
  747. /package/dist/{chunk-H3TKENU4.js.map → chunk-WIKO4SCR.js.map} +0 -0
  748. /package/dist/{chunk-TX2UTLXC.js.map → chunk-WPDKBUWX.js.map} +0 -0
  749. /package/dist/{chunk-YFLLGRXO.js.map → chunk-X2QPKLPL.js.map} +0 -0
  750. /package/dist/{chunk-PFFZWDPE.js.map → chunk-XCOV45MO.js.map} +0 -0
  751. /package/dist/{chunk-5BCNEBEN.js.map → chunk-XPJNT6PI.js.map} +0 -0
  752. /package/dist/{chunk-SEDEKFYQ.js.map → chunk-XW2T4QAW.js.map} +0 -0
  753. /package/dist/{chunk-J7HFPA6O.js.map → chunk-Y63ZFP4X.js.map} +0 -0
  754. /package/dist/{chunk-D223ZDQV.js.map → chunk-YEDVOYL2.js.map} +0 -0
  755. /package/dist/{chunk-RC5DXXWC.js.map → chunk-YM7YN37H.js.map} +0 -0
  756. /package/dist/{chunk-BPJNF7J2.js.map → chunk-YNN26CIZ.js.map} +0 -0
  757. /package/dist/{chunk-VLXBE57O.js.map → chunk-YVGXH72Y.js.map} +0 -0
  758. /package/dist/{chunk-YQAXP5AC.js.map → chunk-YXLUTALO.js.map} +0 -0
  759. /package/dist/{chunk-DGGB65KC.js.map → chunk-Z7ACR6MJ.js.map} +0 -0
  760. /package/dist/{chunk-X35W4S3L.js.map → chunk-ZBEGS7OB.js.map} +0 -0
  761. /package/dist/{chunk-XUE46UYW.js.map → chunk-ZLN7AROH.js.map} +0 -0
  762. /package/dist/{chunk-HK32G473.js.map → chunk-ZWEZXVYH.js.map} +0 -0
  763. /package/dist/{contradiction-scan-NOYMFG66.js.map → contradiction-scan-GVD4JJ7B.js.map} +0 -0
  764. /package/dist/{first-start-migration-RC345GPL.js.map → first-start-migration-L3UFX5CU.js.map} +0 -0
  765. /package/dist/{resolution-VKATP2HT.js.map → local-llm-config.js.map} +0 -0
  766. /package/dist/{tier-stats-KA6OZX2C.js.map → tier-stats-VK5PCO2L.js.map} +0 -0
@@ -47,7 +47,8 @@ import {
47
47
  type MergeJudgeRawVerdict,
48
48
  } from "./merge.js";
49
49
  import type { SemanticDedupHit } from "./semantic.js";
50
- import { invalidationCommitFingerprint } from "../storage/deletion-revision-store.js";
50
+ import { invalidationCommitFingerprint, isSemanticFrontmatterChange, markCasCommittedRevision, nextCasRevisionIso } from "../storage/deletion-revision-store.js";
51
+ import type { CasRevisionReadStatus } from "../storage/cas-revision-store.js";
51
52
 
52
53
  // The merge snapshot trigger must stay a literal union: a widened
53
54
  // `VersionTrigger` (e.g. annotated `readonly string[]`) would let an unknown
@@ -455,7 +456,7 @@ interface MergeHarness {
455
456
  storage: StorageManager;
456
457
  target: MemoryFile;
457
458
  /** Simulate another writer committing a new body to the target. */
458
- setTargetContent: (content: string) => Promise<void>;
459
+ setTargetContent: (content: string, revision?: string) => Promise<string>;
459
460
  calls: {
460
461
  contentUpdates: Array<{ id: string; content: string; actor?: string }>;
461
462
  frontmatterPatches: Array<{ id: string; patch: Partial<MemoryFrontmatter>; actor?: string }>;
@@ -464,6 +465,8 @@ interface MergeHarness {
464
465
  hashRegistrations: Array<{ id: string; hash: string }>;
465
466
  reindexed: string[];
466
467
  lookupStorages: string[];
468
+ /** Every revision `commit()` stamped, in order — [0] is the content CAS's receipt. */
469
+ commitRevisions: string[];
467
470
  };
468
471
  }
469
472
 
@@ -506,6 +509,15 @@ async function harness(
506
509
  targetMemoryKind?: MemoryFrontmatter["memoryKind"];
507
510
  /** Stamp stale intent routing fields on the target's frontmatter (round N+3 A). */
508
511
  targetIntent?: { goal: string; actionType: string; entityTypes: string[] };
512
+ /** Seed `updated` on the target's frontmatter (receipt-clock tests). */
513
+ targetUpdated?: string;
514
+ /**
515
+ * Model what StorageManager.writeMemoryFrontmatter does on success: the
516
+ * accepted patch becomes the standing record's frontmatter — INCLUDING
517
+ * `updated` — so a patch that regresses the revision below an issued CAS
518
+ * receipt is observable (#2813 P1, round 3).
519
+ */
520
+ applyFrontmatterPatches?: boolean;
509
521
  /** Top-level parseConfig overrides (citation enablement, round N+2 C). */
510
522
  topLevelConfig?: Record<string, unknown>;
511
523
  lookupHits?: SemanticDedupHit[];
@@ -516,10 +528,34 @@ async function harness(
516
528
  * open.
517
529
  */
518
530
  mutateAtPatch?: string;
531
+ /**
532
+ * #2807 (P1 exception round): a concurrent correction retirement inside
533
+ * the patch window — a SEMANTIC frontmatter mutation whose patch omits
534
+ * `updated` (retireMemoryFn). Routed through the production
535
+ * `frontmatterWriteRevision` so the test exercises the real revision
536
+ * decision, not the stub's opinion.
537
+ */
538
+ retireAtPatch?: boolean;
519
539
  /** Force the frontmatter patch to fail after the content update commits. */
520
540
  frontmatterFails?: boolean;
521
541
  /** Force the automatic rollback of that committed content to fail. */
522
542
  rollbackFails?: boolean;
543
+ /**
544
+ * #2807: force `updateMemoryIfUnchanged` itself to THROW on the
545
+ * semantic-merge actor — "before" fails at lock acquisition (target
546
+ * untouched), "after" commits the merged body and then throws (lock
547
+ * release failure past the write; storage stamps the commit receipt),
548
+ * "concurrent" (#2813 P1) has another writer commit the IDENTICAL
549
+ * deterministic merged body before this writer's lock acquisition
550
+ * fails, so the throw carries no receipt.
551
+ */
552
+ contentCasThrows?: "before" | "after" | "concurrent" | "after-concurrent";
553
+ /**
554
+ * #2813 (P1 B): force the three-way receipt read inside the rollback's
555
+ * ownership check — "unavailable" simulates a transiently unreadable
556
+ * sidecar, "absent" a sidecar that corroborates neither writer.
557
+ */
558
+ receiptStatus?: "unavailable" | "absent";
523
559
  } = {},
524
560
  ): Promise<MergeHarness> {
525
561
  const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-merge-"));
@@ -546,6 +582,7 @@ async function harness(
546
582
  ...(overrides.targetValidAt ? { valid_at: overrides.targetValidAt } : {}),
547
583
  ...(overrides.targetInvalidAt ? { invalid_at: overrides.targetInvalidAt } : {}),
548
584
  ...(overrides.targetMemoryKind ? { memoryKind: overrides.targetMemoryKind } : {}),
585
+ ...(overrides.targetUpdated ? { updated: overrides.targetUpdated } : {}),
549
586
  ...(overrides.targetIntent
550
587
  ? {
551
588
  intentGoal: overrides.targetIntent.goal,
@@ -560,6 +597,10 @@ async function harness(
560
597
  // Live state: the CAS compares against what is on disk NOW, so a stub that
561
598
  // returned the original snapshot forever could never fail a compare.
562
599
  let state: MemoryFile = { ...target };
600
+ // #2807: the dedicated CAS receipt identity — a sidecar simulation,
601
+ // exactly like StorageManager's CasRevisionStore. Public
602
+ // `frontmatter.updated` is business time and never carries it.
603
+ let casRevision: string | undefined;
563
604
 
564
605
  const calls: MergeHarness["calls"] = {
565
606
  contentUpdates: [],
@@ -569,10 +610,27 @@ async function harness(
569
610
  hashRegistrations: [],
570
611
  reindexed: [],
571
612
  lookupStorages: [],
613
+ commitRevisions: [],
572
614
  };
573
- const commit = async (content: string): Promise<void> => {
574
- state = { ...state, content };
615
+ const commit = async (content: string, revision?: string): Promise<string> => {
616
+ // Signature-faithful to updateMemoryFromCurrent (#2807): the durable
617
+ // write stamps public `updated` with the wall clock (business time,
618
+ // monotonic within the fake so two same-millisecond commits stay
619
+ // fingerprint-distinct, as real milliseconds are) and mints the receipt
620
+ // from the per-target sidecar token (nextCasRevisionIso) — unique per
621
+ // commit even inside one millisecond.
622
+ casRevision = revision ?? nextCasRevisionIso(casRevision);
623
+ calls.commitRevisions.push(casRevision);
624
+ state = {
625
+ ...state,
626
+ content,
627
+ frontmatter: {
628
+ ...state.frontmatter,
629
+ updated: nextCasRevisionIso(state.frontmatter.updated),
630
+ },
631
+ };
575
632
  await writeFile(targetPath, `---\nid: fact-target\ncategory: fact\n---\n\n${content}\n`, "utf8");
633
+ return casRevision;
576
634
  };
577
635
  // Live state: reads come off the file, so a stub can neither invent a
578
636
  // restore that never touched storage nor compare a snapshot against itself.
@@ -615,13 +673,49 @@ async function harness(
615
673
  options?: { actor?: string },
616
674
  ) => {
617
675
  if (overrides.rollbackFails && options?.actor === "semantic-merge-rollback") return false;
676
+ if (overrides.contentCasThrows === "before" && options?.actor === "semantic-merge") {
677
+ throw new Error("storage lock acquisition timed out");
678
+ }
679
+ if (overrides.contentCasThrows === "concurrent" && options?.actor === "semantic-merge") {
680
+ // #2813 (P1): a concurrent writer wins the lock and commits the
681
+ // IDENTICAL deterministic merged body; this writer's CAS then throws
682
+ // before its own mutation — no commit receipt is stamped.
683
+ calls.contentUpdates.push({ id: expected.frontmatter.id, content, actor: "other-writer" });
684
+ await commit(content);
685
+ throw new Error("storage lock acquisition timed out");
686
+ }
618
687
  if (overrides.mutateOnWrite !== undefined && options?.actor === "semantic-merge") {
619
688
  await commit(overrides.mutateOnWrite);
620
689
  }
690
+ if (overrides.contentCasThrows === "after" && options?.actor === "semantic-merge") {
691
+ calls.contentUpdates.push({ id: expected.frontmatter.id, content, actor: options?.actor });
692
+ const revision = await commit(content);
693
+ // Signature-faithful to the real CAS: the durable write landed, so
694
+ // storage stamps the post-commit throw with the commit receipt.
695
+ const err = new Error("lock release failed after the content write committed");
696
+ markCasCommittedRevision(err, revision);
697
+ throw err;
698
+ }
699
+ if (overrides.contentCasThrows === "after-concurrent" && options?.actor === "semantic-merge") {
700
+ // #2813 (P1, round 2): THIS writer's CAS commits the merged body and
701
+ // its post-commit work throws with the commit receipt stamped — then
702
+ // a concurrent writer commits the IDENTICAL deterministic merged body
703
+ // after the lock is released, before this writer's catch path
704
+ // performs its rollback. Fix B: both commits land inside the SAME
705
+ // millisecond; only the monotonic revision stamp tells them apart.
706
+ calls.contentUpdates.push({ id: expected.frontmatter.id, content, actor: options?.actor });
707
+ const revision = await commit(content);
708
+ calls.contentUpdates.push({ id: expected.frontmatter.id, content, actor: "other-writer" });
709
+ const foreign = await commit(content);
710
+ assert.notEqual(foreign, revision, "same-millisecond identical commits must carry distinct receipts");
711
+ const err = new Error("lock release failed after the content write committed");
712
+ markCasCommittedRevision(err, revision);
713
+ throw err;
714
+ }
621
715
  if (!(await unchanged(expected))) return false;
622
716
  calls.contentUpdates.push({ id: expected.frontmatter.id, content, actor: options?.actor });
623
- await commit(content);
624
- return true;
717
+ // Signature-faithful: a successful CAS returns its commit receipt.
718
+ return await commit(content);
625
719
  },
626
720
  // Signature-faithful to StorageManager.writeMemoryFrontmatterIfUnchanged.
627
721
  writeMemoryFrontmatterIfUnchanged: async (
@@ -632,8 +726,37 @@ async function harness(
632
726
  // A concurrent writer inside the patch window: after the caller's
633
727
  // verifying read, before storage takes its own lock.
634
728
  if (overrides.mutateAtPatch !== undefined) await commit(overrides.mutateAtPatch);
729
+ // #2807 (P1 exception round): a concurrent correction retirement in
730
+ // the same window — status flip with NO proposed revision, stamped
731
+ // through the production boundary exactly as
732
+ // StorageManager.writeMemoryFrontmatter stamps it.
733
+ if (overrides.retireAtPatch) {
734
+ // #2807: the patch applies VERBATIM (business time untouched — no
735
+ // `updated` rewrite) and, being semantic, mints the next sidecar
736
+ // token exactly as StorageManager.writeMemoryFrontmatter's
737
+ // chokepoint does.
738
+ const retired: MemoryFrontmatter = {
739
+ ...state.frontmatter,
740
+ status: "superseded",
741
+ supersededBy: "fact-replacement",
742
+ };
743
+ if (isSemanticFrontmatterChange(state.frontmatter, retired)) {
744
+ casRevision = nextCasRevisionIso(casRevision);
745
+ }
746
+ state = { ...state, frontmatter: retired };
747
+ }
635
748
  if (!(await unchanged(expected))) return false;
636
749
  calls.frontmatterPatches.push({ id: expected.frontmatter.id, patch, actor: options?.actor });
750
+ // #2807: the accepted patch becomes the standing record's frontmatter
751
+ // VERBATIM (including caller `updated`), and a semantic change mints
752
+ // the next sidecar token — mirroring StorageManager.writeMemoryFrontmatter.
753
+ if (overrides.applyFrontmatterPatches) {
754
+ const merged = { ...state.frontmatter, ...patch };
755
+ if (isSemanticFrontmatterChange(state.frontmatter, merged)) {
756
+ casRevision = nextCasRevisionIso(casRevision);
757
+ }
758
+ state = { ...state, frontmatter: merged };
759
+ }
637
760
  return overrides.frontmatterFails !== true;
638
761
  },
639
762
  removeFactContentHashesForMemories: async (memories: MemoryFile[]) => {
@@ -645,6 +768,15 @@ async function harness(
645
768
  registerFactContentHash: async (id: string, hash: string, _expectedContent: string) => {
646
769
  calls.hashRegistrations.push({ id, hash });
647
770
  },
771
+ readCasRevision: async (p: string) => (p === targetPath ? casRevision : undefined),
772
+ readCasRevisionStatus: async (p: string): Promise<CasRevisionReadStatus> => {
773
+ if (p !== targetPath) return { status: "absent" };
774
+ if (overrides.receiptStatus === "unavailable") {
775
+ return { status: "unavailable", reason: "simulated transient sidecar read failure" };
776
+ }
777
+ if (overrides.receiptStatus === "absent") return { status: "absent" };
778
+ return casRevision === undefined ? { status: "absent" } : { status: "present", revision: casRevision };
779
+ },
648
780
  } as unknown as StorageManager;
649
781
 
650
782
  const config = parseConfig({
@@ -1171,10 +1303,7 @@ test("registerFactContentHash: exact dedup finds the degraded record's merged bo
1171
1303
  // compare-and-swapped to the merged text while the frontmatter keeps the
1172
1304
  // old identity (updateMemoryIfUnchanged preserves contentHash).
1173
1305
  const before = (await storage.readAllMemories()).find((m) => m.frontmatter.id === id)!;
1174
- assert.equal(
1175
- await storage.updateMemoryIfUnchanged(before, MERGED, { actor: "semantic-merge" }),
1176
- true,
1177
- );
1306
+ assert.ok(await storage.updateMemoryIfUnchanged(before, MERGED, { actor: "semantic-merge" }));
1178
1307
  const degraded = (await storage.readAllMemories()).find((m) => m.frontmatter.id === id)!;
1179
1308
  const staleHash = degraded.frontmatter.contentHash;
1180
1309
  const mergedHash = ContentHashIndex.computeHash(sanitizeMemoryContent(MERGED).text);
@@ -1252,7 +1381,7 @@ test("persistRepairedContentHash: the repaired hash survives a restart's corpus
1252
1381
  // compare-and-swapped to the merged text while the frontmatter keeps the
1253
1382
  // old identity (updateMemoryIfUnchanged preserves contentHash).
1254
1383
  const before = (await storage.readAllMemories()).find((m) => m.frontmatter.id === id)!;
1255
- assert.equal(await storage.updateMemoryIfUnchanged(before, MERGED, { actor: "semantic-merge" }), true);
1384
+ assert.ok(await storage.updateMemoryIfUnchanged(before, MERGED, { actor: "semantic-merge" }));
1256
1385
  const mergedHash = ContentHashIndex.computeHash(sanitizeMemoryContent(MERGED).text);
1257
1386
  // The N+16 C repair alone (process-local registration).
1258
1387
  await storage.registerFactContentHash(id, mergedHash, MERGED);
@@ -2358,7 +2487,7 @@ test("applySemanticMergeAtPersist: the committed merged record carries the lower
2358
2487
  assert.equal(committed?.frontmatter.confidenceTier, "inferred");
2359
2488
  // The committed record is the promotion payload's sole source, so the
2360
2489
  // shared/profile copy stamps the downgraded value too.
2361
- const payload = await buildMergedTargetPromotionPayload(storage, {
2490
+ const { payload } = await buildMergedTargetPromotionPayload(storage, {
2362
2491
  targetId: created.id,
2363
2492
  mergedContent: MERGED,
2364
2493
  provenancePatched: true,
@@ -2414,7 +2543,7 @@ test("buildMergedTargetPromotionPayload: never promotes from an inactive committ
2414
2543
  // reread: the multi-writer interleaving, simulated directly.
2415
2544
  const snapshot = await storage.getMemoryByIdIncludingArchived(created.id);
2416
2545
  assert.ok(snapshot);
2417
- assert.equal(await storage.updateMemoryIfUnchanged(snapshot, MERGED), true);
2546
+ assert.ok(await storage.updateMemoryIfUnchanged(snapshot, MERGED));
2418
2547
  for (const status of ["superseded", "archived"] as const) {
2419
2548
  assert.equal(
2420
2549
  await storage.updateMemoryFrontmatter(created.id, { status }),
@@ -2424,11 +2553,11 @@ test("buildMergedTargetPromotionPayload: never promotes from an inactive committ
2424
2553
  // Null, never a payload: the caller skips promoteMemoryToShared, so no
2425
2554
  // new active copy resurrects what the lifecycle operation retired.
2426
2555
  assert.equal(
2427
- await buildMergedTargetPromotionPayload(storage, {
2556
+ (await buildMergedTargetPromotionPayload(storage, {
2428
2557
  targetId: created.id,
2429
2558
  mergedContent: MERGED,
2430
2559
  provenancePatched: true,
2431
- }),
2560
+ })).payload,
2432
2561
  null,
2433
2562
  status,
2434
2563
  );
@@ -2438,7 +2567,7 @@ test("buildMergedTargetPromotionPayload: never promotes from an inactive committ
2438
2567
  await storage.updateMemoryFrontmatter(created.id, { status: "active" }),
2439
2568
  true,
2440
2569
  );
2441
- const payload = await buildMergedTargetPromotionPayload(storage, {
2570
+ const { payload } = await buildMergedTargetPromotionPayload(storage, {
2442
2571
  targetId: created.id,
2443
2572
  mergedContent: MERGED,
2444
2573
  provenancePatched: true,
@@ -2489,7 +2618,7 @@ test("buildMergedTargetPromotionPayload: carries the committed tool-scope marker
2489
2618
  },
2490
2619
  );
2491
2620
  assert.equal(outcome.action, "merged");
2492
- const payload = await buildMergedTargetPromotionPayload(storage, {
2621
+ const { payload } = await buildMergedTargetPromotionPayload(storage, {
2493
2622
  targetId: created.id,
2494
2623
  mergedContent: MERGED,
2495
2624
  provenancePatched: true,
@@ -2523,7 +2652,7 @@ test("buildMergedTargetPromotionPayload: an unscoped target promotes a payload w
2523
2652
  judgeCall: (options) => acceptingJudge(options),
2524
2653
  });
2525
2654
  assert.equal(outcome.action, "merged");
2526
- const payload = await buildMergedTargetPromotionPayload(storage, {
2655
+ const { payload } = await buildMergedTargetPromotionPayload(storage, {
2527
2656
  targetId: created.id,
2528
2657
  mergedContent: MERGED,
2529
2658
  provenancePatched: true,
@@ -2883,7 +3012,7 @@ test("buildMergedTargetPromotionPayload: a degraded merge never yields a promoti
2883
3012
  if (degraded.action !== "merged") return;
2884
3013
  assert.equal(degraded.provenancePatched, false);
2885
3014
  assert.equal(
2886
- await buildMergedTargetPromotionPayload(h.storage, degraded),
3015
+ (await buildMergedTargetPromotionPayload(h.storage, degraded)).payload,
2887
3016
  null,
2888
3017
  "no shared/profile copy may be built from an unpatched provenance record",
2889
3018
  );
@@ -2899,7 +3028,7 @@ test("buildMergedTargetPromotionPayload: a degraded merge never yields a promoti
2899
3028
  assert.equal(patched.action, "merged");
2900
3029
  if (patched.action !== "merged") return;
2901
3030
  assert.equal(patched.provenancePatched, true);
2902
- const payload = await buildMergedTargetPromotionPayload(ok.storage, patched);
3031
+ const { payload } = await buildMergedTargetPromotionPayload(ok.storage, patched);
2903
3032
  assert.ok(payload);
2904
3033
  assert.equal(payload?.sourceMemoryId, "fact-target");
2905
3034
  });
@@ -2925,12 +3054,13 @@ test("buildMergedTargetPromotionPayload: a failed post-commit reread fails open
2925
3054
  throw new Error("secure store locked");
2926
3055
  },
2927
3056
  } as unknown as StorageManager;
2928
- const payload = await buildMergedTargetPromotionPayload(lockedStore, {
3057
+ const { payload, readFailed } = await buildMergedTargetPromotionPayload(lockedStore, {
2929
3058
  targetId: "fact-target",
2930
3059
  mergedContent: "merged body",
2931
3060
  provenancePatched: true,
2932
3061
  });
2933
3062
  assert.equal(payload, null, "a reread failure must resolve to null, not a rejection");
3063
+ assert.equal(readFailed, true, "#2807: the null must be identifiable as a read failure, not a refusal");
2934
3064
  const line = entries.find(
2935
3065
  (e) => e.level === "warn" && e.message.includes("semantic-merge") && e.message.includes("fact-target"),
2936
3066
  )?.message;
@@ -3045,6 +3175,9 @@ async function postEffectsHarness(options: {
3045
3175
  content: MERGED,
3046
3176
  }
3047
3177
  : null,
3178
+ // #2807: static token — these fixtures drive the rollback paths, not
3179
+ // ownership attribution.
3180
+ readCasRevision: async () => "2026-08-20T00:00:00.000Z",
3048
3181
  } as unknown as StorageManager;
3049
3182
  const deps = {
3050
3183
  config: parseConfig({ memoryDir: dir }),
@@ -3375,14 +3508,17 @@ test("runMergedTargetPostEffects: a stale writer's rollback preserves the newer
3375
3508
  id,
3376
3509
  category: "fact",
3377
3510
  entityRef: "entity-billing-service",
3378
- // B's commit flips both the body and the revision once A's
3379
- // rebuild has begun: the initial committed-body check sees A's
3380
- // state, everything from the build onward sees B's.
3381
- ...(buildStarted ? { updated: "2026-08-22T01:00:00.000Z" } : {}),
3511
+ // B's commit flips the body once A's rebuild has begun: the
3512
+ // initial committed-body check sees A's state, everything from
3513
+ // the build onward sees B's.
3382
3514
  },
3383
3515
  content: buildStarted ? NEWER_BODY : MERGED,
3384
3516
  }
3385
3517
  : null,
3518
+ // #2807: B's mid-rebuild commit mints a NEW token — the identity the
3519
+ // revision guard compares (public `updated` no longer carries it).
3520
+ readCasRevision: async () =>
3521
+ buildStarted ? "2026-08-22T01:00:00.001Z" : "2026-08-20T00:00:00.000Z",
3386
3522
  } as unknown as StorageManager;
3387
3523
  const graphConfig = parseConfig({ memoryDir: h.dir });
3388
3524
  const graphIndex = new GraphIndex(h.dir, graphConfig);
@@ -3514,6 +3650,503 @@ test("runMergedTargetPostEffects: a THROWING build's rollback preserves the newe
3514
3650
  }
3515
3651
  });
3516
3652
 
3653
+
3654
+ // ── #2807: deferred P2 follow-ups from the #2771 round cap ──────────────────
3655
+
3656
+ test("applySemanticMergeAtPersist: a content CAS that throws before changing the target discards the staged snapshot (#2807)", async () => {
3657
+ // Scenario A — the CAS throws at lock acquisition: the target was never
3658
+ // touched, yet the old catch left the staged snapshot `pending` forever
3659
+ // (pruneExcessVersions excludes pending entries), so repeated contention
3660
+ // grew version history past maxVersionsPerPage with duplicates of an
3661
+ // unchanged body. The reread confirms the pre-merge body → discard.
3662
+ const before = await harness({ contentCasThrows: "before" });
3663
+ const outcomeA = await applySemanticMergeAtPersist(before.deps, {
3664
+ storage: before.storage,
3665
+ content: INCOMING,
3666
+ category: "fact",
3667
+ judgeCall: (options) => acceptingJudge(options),
3668
+ });
3669
+ assert.deepEqual(outcomeA, { action: "created", reason: "update_failed" });
3670
+ const bodyA = await before.storage.getMemoryByIdIncludingArchived("fact-target");
3671
+ assert.equal(bodyA?.content, EXISTING, "the throw preceded the write — the target is untouched");
3672
+ assert.equal(
3673
+ (
3674
+ await listVersions(
3675
+ before.target.path,
3676
+ { enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
3677
+ before.storage.dir,
3678
+ )
3679
+ ).versions.length,
3680
+ 0,
3681
+ "a snapshot of a body that never changed must not survive the aborted attempt",
3682
+ );
3683
+
3684
+ // Scenario B — the CAS commits the merged body and THEN throws (lock
3685
+ // release past the write): `contentCommitted` never flipped, so the old
3686
+ // code both stranded the snapshot AND reported `created` while storage
3687
+ // held the unprovenanced merged body (the duplicate-fact hazard the
3688
+ // catch's own contract forbids). The reread must see the landed body,
3689
+ // revert it, and drop the now-duplicate snapshot.
3690
+ const after = await harness({ contentCasThrows: "after" });
3691
+ const outcomeB = await applySemanticMergeAtPersist(after.deps, {
3692
+ storage: after.storage,
3693
+ content: INCOMING,
3694
+ category: "fact",
3695
+ judgeCall: (options) => acceptingJudge(options),
3696
+ });
3697
+ assert.deepEqual(outcomeB, { action: "created", reason: "update_failed" });
3698
+ const bodyB = await after.storage.getMemoryByIdIncludingArchived("fact-target");
3699
+ assert.equal(bodyB?.content, EXISTING, "the landed merged body is rolled back before `created` is honest");
3700
+ assert.deepEqual(
3701
+ after.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
3702
+ [
3703
+ { content: MERGED, actor: "semantic-merge" },
3704
+ { content: EXISTING, actor: "semantic-merge-rollback" },
3705
+ ],
3706
+ );
3707
+ assert.equal(
3708
+ (
3709
+ await listVersions(
3710
+ after.target.path,
3711
+ { enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
3712
+ after.storage.dir,
3713
+ )
3714
+ ).versions.length,
3715
+ 0,
3716
+ "the reverted attempt leaves no snapshot: the recovery point would hold the body storage already returned to",
3717
+ );
3718
+ });
3719
+
3720
+ test("applySemanticMergeAtPersist: a concurrent identical commit is never claimed as this writer's (#2813 P1)", async () => {
3721
+ // The P1 hole — body-equality ownership. This writer's CAS throws before
3722
+ // mutating anything, but a concurrent writer commits the IDENTICAL
3723
+ // deterministic merged body. The old reread saw "the merged body
3724
+ // standing" and claimed the commit as ours, so revertMergedContent
3725
+ // CAS-replaced the other writer's valid merge with the pre-merge body
3726
+ // while their patched provenance stood. Ownership now comes from the CAS
3727
+ // commit receipt: absent → the standing body is theirs. This writer
3728
+ // discards only its own staged duplicate snapshot and reports the
3729
+ // degraded merged outcome (never `created` — storage already holds
3730
+ // these claims, so writing the fact again would duplicate them).
3731
+ const h = await harness({ contentCasThrows: "concurrent" });
3732
+ const outcome = await applySemanticMergeAtPersist(h.deps, {
3733
+ storage: h.storage,
3734
+ content: INCOMING,
3735
+ category: "fact",
3736
+ judgeCall: (options) => acceptingJudge(options),
3737
+ });
3738
+ assert.deepEqual(outcome, {
3739
+ action: "merged",
3740
+ targetId: "fact-target",
3741
+ mergedContent: MERGED,
3742
+ provenancePatched: false,
3743
+ });
3744
+ const body = await h.storage.getMemoryByIdIncludingArchived("fact-target");
3745
+ assert.equal(body?.content, MERGED, "the concurrent writer's commit stands — never reverted");
3746
+ assert.deepEqual(
3747
+ h.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
3748
+ [{ content: MERGED, actor: "other-writer" }],
3749
+ "neither a semantic-merge write nor a semantic-merge-rollback ran — the concurrent commit's state is untouched",
3750
+ );
3751
+ assert.equal(
3752
+ (
3753
+ await listVersions(
3754
+ h.target.path,
3755
+ { enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
3756
+ h.storage.dir,
3757
+ )
3758
+ ).versions.length,
3759
+ 0,
3760
+ "this writer's staged duplicate snapshot is cleaned up, not finalized into history",
3761
+ );
3762
+ });
3763
+
3764
+ test("applySemanticMergeAtPersist: a rollback never reverts a concurrent identical commit that landed after this writer's receipt (#2813 P1)", async () => {
3765
+ // The round-2 P1 hole — the receipt used only as a boolean. This writer's
3766
+ // CAS COMMITS the merged body and its post-commit work throws with the
3767
+ // commit receipt stamped; before the catch path runs its rollback, a
3768
+ // concurrent writer commits the IDENTICAL deterministic merged body under a
3769
+ // later revision. Body equality cannot tell the two commits apart, so the
3770
+ // old rollback reread "the merged body standing", CAS-restored the
3771
+ // pre-merge body over the concurrent writer's valid merge, and discarded
3772
+ // the snapshot while their provenance update may already have landed. The
3773
+ // rollback now compares the standing record's revision with the receipt:
3774
+ // equal → ours, safe to revert; advanced → theirs — the other-writer
3775
+ // handling from the previous fix (discard our staged duplicate, repair
3776
+ // indexes for the standing body, report the degraded merge; never revert
3777
+ // theirs).
3778
+ const h = await harness({ contentCasThrows: "after-concurrent" });
3779
+ const outcome = await applySemanticMergeAtPersist(h.deps, {
3780
+ storage: h.storage,
3781
+ content: INCOMING,
3782
+ category: "fact",
3783
+ judgeCall: (options) => acceptingJudge(options),
3784
+ });
3785
+ assert.deepEqual(outcome, {
3786
+ action: "merged",
3787
+ targetId: "fact-target",
3788
+ mergedContent: MERGED,
3789
+ provenancePatched: false,
3790
+ });
3791
+ const body = await h.storage.getMemoryByIdIncludingArchived("fact-target");
3792
+ assert.equal(
3793
+ body?.content,
3794
+ MERGED,
3795
+ "the concurrent writer's identical commit stands — never reverted to the pre-merge body",
3796
+ );
3797
+ assert.deepEqual(
3798
+ h.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
3799
+ [
3800
+ { content: MERGED, actor: "semantic-merge" },
3801
+ { content: MERGED, actor: "other-writer" },
3802
+ ],
3803
+ "no semantic-merge-rollback write runs — the pre-merge restore must never fire against another writer's commit",
3804
+ );
3805
+ assert.equal(
3806
+ h.calls.hashRegistrations.length,
3807
+ 1,
3808
+ "the degraded path repairs the hash indexes for the standing merged body",
3809
+ );
3810
+ assert.equal(
3811
+ (
3812
+ await listVersions(
3813
+ h.target.path,
3814
+ { enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
3815
+ h.storage.dir,
3816
+ )
3817
+ ).versions.length,
3818
+ 0,
3819
+ "this writer's staged duplicate snapshot is discarded, not finalized into history",
3820
+ );
3821
+ });
3822
+
3823
+ test("applySemanticMergeAtPersist: a successful content CAS retains its receipt, so a same-millisecond identical commit survives a failed provenance patch (#2813 P1)", async () => {
3824
+ // Fix A — the receipt was captured only from the THROWING CAS
3825
+ // (casCommittedRevisionOf). When the content CAS SUCCEEDED and a later
3826
+ // step threw (provenance patch rejected), the catch rolled back with NO
3827
+ // revision: revertMergedContent skipped its ownership comparison, body
3828
+ // equality attributed the standing record to this writer, and the
3829
+ // pre-merge restore deleted the concurrent writer's valid identical merge
3830
+ // (here committed inside the patch window, the SAME millisecond — fix B's
3831
+ // wall-clock collision). The success path now retains the landed revision,
3832
+ // the monotonic stamp keeps the two same-ms commits distinct, and the
3833
+ // rollback classifies the standing body as superseded — never reverted.
3834
+ const h = await harness({ mutateAtPatch: MERGED });
3835
+ const outcome = await applySemanticMergeAtPersist(h.deps, {
3836
+ storage: h.storage,
3837
+ content: INCOMING,
3838
+ category: "fact",
3839
+ judgeCall: (options) => acceptingJudge(options),
3840
+ });
3841
+ assert.deepEqual(outcome, {
3842
+ action: "merged",
3843
+ targetId: "fact-target",
3844
+ mergedContent: MERGED,
3845
+ provenancePatched: false,
3846
+ });
3847
+ const body = await h.storage.getMemoryByIdIncludingArchived("fact-target");
3848
+ assert.equal(
3849
+ body?.content,
3850
+ MERGED,
3851
+ "the concurrent writer's identical commit stands — never reverted to the pre-merge body",
3852
+ );
3853
+ assert.deepEqual(
3854
+ h.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
3855
+ [{ content: MERGED, actor: "semantic-merge" }],
3856
+ "no semantic-merge-rollback write runs — the pre-merge restore must never fire against another writer's commit",
3857
+ );
3858
+ assert.equal(
3859
+ h.calls.hashRegistrations.length,
3860
+ 1,
3861
+ "the degraded path repairs the hash indexes for the standing merged body",
3862
+ );
3863
+ assert.equal(
3864
+ (
3865
+ await listVersions(
3866
+ h.target.path,
3867
+ { enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
3868
+ h.storage.dir,
3869
+ )
3870
+ ).versions.length,
3871
+ 0,
3872
+ "this writer's staged duplicate snapshot is discarded, not finalized into history",
3873
+ );
3874
+ });
3875
+
3876
+ test("applySemanticMergeAtPersist: a timestamp-less retirement between the content CAS and the provenance patch is never rolled back over (#2807 P1)", async () => {
3877
+ // The exception-round P1 hole — the PRESERVED revision. This writer's
3878
+ // content CAS commits the merged body (receipt T+1) and, before the
3879
+ // provenance patch takes its lock, a concurrent correction retirement
3880
+ // lands: a semantic frontmatter mutation whose patch omits `updated`
3881
+ // (retireMemoryFn). The status flip makes the provenance patch's
3882
+ // fingerprint compare reject it, so the catch path rolls back holding the
3883
+ // content CAS's receipt. Pre-fix, the timestamp-less write PRESERVED the
3884
+ // standing revision, so the retired record still carried this writer's
3885
+ // receipt — the rollback claimed the foreign record as its own and
3886
+ // CAS-restored the pre-merge body, leaving the retirement metadata
3887
+ // (superseded/supersededBy) attached to content it never described. The
3888
+ // boundary fix advances the revision on EVERY semantic frontmatter
3889
+ // mutation, so the failure handler detects the foreign revision and the
3890
+ // retired record is never touched.
3891
+ const h = await harness({ retireAtPatch: true });
3892
+ const outcome = await applySemanticMergeAtPersist(h.deps, {
3893
+ storage: h.storage,
3894
+ content: INCOMING,
3895
+ category: "fact",
3896
+ judgeCall: (options) => acceptingJudge(options),
3897
+ });
3898
+ assert.deepEqual(outcome, {
3899
+ action: "merged",
3900
+ targetId: "fact-target",
3901
+ mergedContent: MERGED,
3902
+ provenancePatched: false,
3903
+ });
3904
+ const body = await h.storage.getMemoryByIdIncludingArchived("fact-target");
3905
+ assert.ok(body);
3906
+ assert.equal(body.content, MERGED, "the merged body is never rolled back over the concurrent retirement");
3907
+ assert.equal(body.frontmatter.status, "superseded", "the retirement metadata survives untouched");
3908
+ assert.equal(body.frontmatter.supersededBy, "fact-replacement");
3909
+ // The failure handler detected the FOREIGN revision: the standing
3910
+ // revision advanced strictly past the content CAS's receipt — the
3911
+ // identity the rollback compares.
3912
+ const receipt = h.calls.commitRevisions[0];
3913
+ assert.ok(receipt, "the content CAS stamped a receipt");
3914
+ const standingToken = await h.storage.readCasRevision(h.target.path);
3915
+ assert.ok(standingToken, "the retirement minted a new token");
3916
+ assert.notEqual(standingToken, receipt, "the timestamp-less retirement retired the CAS's receipt token");
3917
+ assert.ok(
3918
+ new Date(standingToken).getTime() > new Date(receipt).getTime(),
3919
+ "the timestamp-less retirement advanced the token strictly past the CAS receipt",
3920
+ );
3921
+ assert.deepEqual(
3922
+ h.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
3923
+ [{ content: MERGED, actor: "semantic-merge" }],
3924
+ "no semantic-merge-rollback write runs — the retired record is another writer's",
3925
+ );
3926
+ assert.equal(
3927
+ h.calls.hashRegistrations.length,
3928
+ 1,
3929
+ "the degraded path repairs the hash indexes for the standing merged body",
3930
+ );
3931
+ assert.equal(
3932
+ (
3933
+ await listVersions(
3934
+ h.target.path,
3935
+ { enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
3936
+ h.storage.dir,
3937
+ )
3938
+ ).versions.length,
3939
+ 0,
3940
+ "this writer's staged duplicate snapshot is discarded, not finalized into history",
3941
+ );
3942
+ });
3943
+
3944
+ test("applySemanticMergeAtPersist: the monotonic receipt survives the metadata patch — three same-millisecond merges, A's rollback never restores over C's commit (#2813 P1)", async () => {
3945
+ // Round-3 P1 hole — the receipt was monotonic only until the metadata
3946
+ // patch. The patch stamped the PRE-CAS wall clock (mergePatch.updated), so
3947
+ // a successful writer REGRESSED frontmatter.updated below the receipt its
3948
+ // own CAS had just issued. Three writers merging into the same target
3949
+ // inside one millisecond (target seeded at T, every writer's clock T):
3950
+ // The seed sits AHEAD of the real wall clock on purpose: the fake's commit
3951
+ // stamps via nextCasRevisionIso against the real clock, so a future seed
3952
+ // forces every stamp into the +1ms monotonic branch — the sequence is
3953
+ // pinned to T+n exactly as inside the finding's single millisecond.
3954
+ // #2807: the patch now stamps business time (mergePatch.updated) verbatim;
3955
+ // monotonicity lives in the sidecar token, minted by storage's write
3956
+ // chokepoint — never in `frontmatter.updated`. C's token lands past every
3957
+ // prior receipt, A classifies the standing record as superseded, and C's
3958
+ // commit survives A's failure.
3959
+ const T = new Date(Date.now() + 60_000);
3960
+ const h = await harness({
3961
+ targetUpdated: T.toISOString(),
3962
+ applyFrontmatterPatches: true,
3963
+ });
3964
+ const realPatch = h.storage.writeMemoryFrontmatterIfUnchanged.bind(h.storage);
3965
+ let patchCalls = 0;
3966
+ let releaseC!: () => void;
3967
+ const cGate = new Promise<void>((resolve) => {
3968
+ releaseC = resolve;
3969
+ });
3970
+ let cArrived!: () => void;
3971
+ const cArrivedGate = new Promise<void>((resolve) => {
3972
+ cArrived = resolve;
3973
+ });
3974
+ let cMerge: Promise<{ action: string }> | undefined;
3975
+ h.storage.writeMemoryFrontmatterIfUnchanged = (async (
3976
+ expected: MemoryFile,
3977
+ patch: Partial<MemoryFrontmatter>,
3978
+ options?: { actor?: string },
3979
+ ) => {
3980
+ if (options?.actor !== "semantic-merge") {
3981
+ return await realPatch(expected, patch, options);
3982
+ }
3983
+ patchCalls += 1;
3984
+ if (patchCalls === 1) {
3985
+ // A's patch: B commits fully (CAS + patch) while A's post-commit work
3986
+ // is failing; C commits its CAS and suspends INSIDE its own patch —
3987
+ // exactly the finding's window, where C's commit stands at the reused
3988
+ // receipt and its patch has not landed.
3989
+ const bOutcome = await applySemanticMergeAtPersist(h.deps, {
3990
+ storage: h.storage,
3991
+ content: INCOMING,
3992
+ category: "fact",
3993
+ judgeCall: (options) => acceptingJudge(options),
3994
+ now: () => T,
3995
+ });
3996
+ assert.equal(bOutcome.action, "merged", "B's merge commits fully");
3997
+ cMerge = applySemanticMergeAtPersist(h.deps, {
3998
+ storage: h.storage,
3999
+ content: INCOMING,
4000
+ category: "fact",
4001
+ judgeCall: (options) => acceptingJudge(options),
4002
+ now: () => T,
4003
+ });
4004
+ await cArrivedGate;
4005
+ return false; // A's patch is rejected — A enters its post-commit failure path
4006
+ }
4007
+ if (patchCalls === 3) {
4008
+ // C's patch: suspended until A's rollback has compared the standing
4009
+ // record, so A's classification runs against C's bare CAS commit.
4010
+ cArrived();
4011
+ await cGate;
4012
+ }
4013
+ return await realPatch(expected, patch, options);
4014
+ }) as StorageManager["writeMemoryFrontmatterIfUnchanged"];
4015
+
4016
+ const aOutcome = await applySemanticMergeAtPersist(h.deps, {
4017
+ storage: h.storage,
4018
+ content: INCOMING,
4019
+ category: "fact",
4020
+ judgeCall: (options) => acceptingJudge(options),
4021
+ now: () => T,
4022
+ });
4023
+ releaseC();
4024
+ const cOutcome = await cMerge!;
4025
+
4026
+ assert.deepEqual(aOutcome, {
4027
+ action: "merged",
4028
+ targetId: "fact-target",
4029
+ mergedContent: MERGED,
4030
+ provenancePatched: false,
4031
+ });
4032
+ assert.deepEqual(cOutcome, { action: "merged", targetId: "fact-target", mergedContent: MERGED, provenancePatched: true });
4033
+ const body = await h.storage.getMemoryByIdIncludingArchived("fact-target");
4034
+ assert.equal(
4035
+ body?.content,
4036
+ MERGED,
4037
+ "C's commit stands — A's rollback must not restore the pre-merge body over it",
4038
+ );
4039
+ assert.equal(
4040
+ body?.frontmatter.updated,
4041
+ T.toISOString(),
4042
+ "#2807: the metadata patch stamps business time (mergePatch.updated) verbatim — never a revision",
4043
+ );
4044
+ const standingToken = await h.storage.readCasRevision(h.target.path);
4045
+ const [aReceipt, bReceipt, cReceipt2] = h.calls.commitRevisions;
4046
+ assert.ok(aReceipt && bReceipt && cReceipt2);
4047
+ assert.ok(aReceipt < bReceipt && bReceipt < cReceipt2, "A, B, C receipts are unique and strictly increasing");
4048
+ assert.ok(
4049
+ standingToken !== undefined && standingToken > cReceipt2,
4050
+ "the standing token advanced past every issued CAS receipt through the metadata patches",
4051
+ );
4052
+ assert.notEqual(standingToken, aReceipt, "A's retired receipt no longer matches the standing token");
4053
+ assert.deepEqual(
4054
+ h.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
4055
+ [
4056
+ { content: MERGED, actor: "semantic-merge" },
4057
+ { content: MERGED, actor: "semantic-merge" },
4058
+ { content: MERGED, actor: "semantic-merge" },
4059
+ ],
4060
+ "exactly the three CAS commits — no semantic-merge-rollback write ever fires",
4061
+ );
4062
+ });
4063
+
4064
+ test("runMergedTargetPostEffects: a rolled-back edge rewrite invalidates the graph edge cache (#2807)", async () => {
4065
+ // The warm-cache hole: the target had no prior generated rows (the
4066
+ // removal is a disk no-op, so the cache baseline survives), the build's
4067
+ // onMemoryWritten incrementally pushes the appended rows into
4068
+ // GraphIndex.edgeCache, and a writer that advanced the target past the
4069
+ // revision check triggers the rollback — which repairs only the JSONL
4070
+ // files. Without invalidating the owning index, spreadingActivation kept
4071
+ // serving the rolled-back edges for the full five-minute TTL.
4072
+ const h = await postEffectsHarness();
4073
+ const OTHER = "facts/2026-08-19/other.md";
4074
+ const UNRELATED_FROM = "facts/2026-08-18/unrelated-a.md";
4075
+ const UNRELATED_TO = "facts/2026-08-18/unrelated-b.md";
4076
+ const unrelated: GraphEdge = {
4077
+ from: UNRELATED_FROM, to: UNRELATED_TO, type: "entity", weight: 1,
4078
+ label: "entity-unrelated", ts: "2026-08-18T00:00:00.000Z",
4079
+ };
4080
+ await seedGraphFile(h.dir, "entity", [unrelated]);
4081
+ const NEWER_BODY = "Billing service deploys run on Tuesdays at 09:00 UTC, paging the on-call engineer.";
4082
+ const targetPath = path.join(h.dir, h.targetRelPath);
4083
+ let buildStarted = false;
4084
+ const storage = {
4085
+ dir: h.dir,
4086
+ getMemoryByIdIncludingArchived: async (id: string) =>
4087
+ id === "fact-target"
4088
+ ? {
4089
+ path: targetPath,
4090
+ frontmatter: {
4091
+ id,
4092
+ category: "fact",
4093
+ entityRef: "entity-billing-service",
4094
+ ...(buildStarted ? { updated: "2026-08-22T01:00:00.000Z" } : {}),
4095
+ },
4096
+ content: buildStarted ? NEWER_BODY : MERGED,
4097
+ }
4098
+ : null,
4099
+ } as unknown as StorageManager;
4100
+ const graphConfig = parseConfig({ memoryDir: h.dir, multiGraphMemoryEnabled: true });
4101
+ const graphIndex = new GraphIndex(h.dir, graphConfig);
4102
+ const coordinator = new PersistenceIndexCoordinator({
4103
+ config: graphConfig,
4104
+ graphIndexFor: () => graphIndex,
4105
+ } as unknown as ConstructorParameters<typeof PersistenceIndexCoordinator>[0]);
4106
+ // Warm the cache from the seeded file BEFORE the rewrite runs.
4107
+ await graphIndex.spreadingActivation([UNRELATED_FROM]);
4108
+ const realBuild = coordinator.buildGraphEdge.bind(coordinator);
4109
+ const sibling = {
4110
+ path: path.join(h.dir, OTHER),
4111
+ frontmatter: { id: "mem-sibling", category: "fact", entityRef: "entity-billing-service" },
4112
+ content: "Sibling fact sharing the billing entity.",
4113
+ } as unknown as MemoryFile;
4114
+ const deps = {
4115
+ ...h.deps,
4116
+ buildGraphEdge: async (...args: Parameters<typeof realBuild>) => {
4117
+ buildStarted = true;
4118
+ return realBuild(...args);
4119
+ },
4120
+ invalidateGraphEdgeCache: () => graphIndex.invalidateEdgeCache(),
4121
+ } as unknown as ExtractionPersistDeps;
4122
+ await runMergedTargetPostEffects(
4123
+ deps,
4124
+ storage,
4125
+ { targetId: "fact-target", mergedContent: MERGED },
4126
+ {
4127
+ category: "fact",
4128
+ incomingContent: INCOMING,
4129
+ incomingConfidence: 0.9,
4130
+ namespace: "default",
4131
+ graphCaps: { entityGraph: true, timeGraph: false, causalGraph: false, multiGraphMemory: true, graphWriteSessionAdjacency: false },
4132
+ graphContext: { allMemsForGraph: [sibling], memoryPathById: new Map() },
4133
+ threadIdForEdge: undefined,
4134
+ threadEpisodeIdsForGraph: undefined,
4135
+ },
4136
+ );
4137
+ assert.deepEqual(
4138
+ await readGraphFile(h.dir, "entity"),
4139
+ [unrelated],
4140
+ "the superseded rewrite's rows are rolled back out of the entity file",
4141
+ );
4142
+ const served = await graphIndex.spreadingActivation([h.targetRelPath]);
4143
+ assert.equal(
4144
+ served.filter((result) => result.path === OTHER).length,
4145
+ 0,
4146
+ `the cache must not serve the rolled-back target→sibling edge after the rollback (served: ${JSON.stringify(served)})`,
4147
+ );
4148
+ });
4149
+
3517
4150
  test("persistMergedTargetThreadEpisode: a re-merge moves an existing earlier target to the durable thread tail (round N+12 D)", async () => {
3518
4151
  const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-merge-thread-"));
3519
4152
  try {
@@ -3540,3 +4173,77 @@ test("persistMergedTargetThreadEpisode: a re-merge moves an existing earlier tar
3540
4173
  await rm(dir, { recursive: true, force: true });
3541
4174
  }
3542
4175
  });
4176
+
4177
+ test("applySemanticMergeAtPersist: a transiently unreadable receipt preserves the recovery snapshot instead of discarding it (#2813 P1 B)", async () => {
4178
+ // The P1 B hole: the content CAS COMMITTED, the provenance patch failed,
4179
+ // and the rollback's ownership check hit a sidecar it could not read. The
4180
+ // fail-open read returned undefined, which classified the standing merged
4181
+ // body as superseded and DISCARDED the staged recovery snapshot on
4182
+ // unproven grounds — the degraded state lost its recovery point. The
4183
+ // three-way status keeps every unproven branch keep-side: the rollback
4184
+ // refuses, the snapshot is preserved as the recovery point, and the
4185
+ // outcome stays the degraded merged report.
4186
+ const h = await harness({ frontmatterFails: true, receiptStatus: "unavailable" });
4187
+ const outcome = await applySemanticMergeAtPersist(h.deps, {
4188
+ storage: h.storage,
4189
+ content: INCOMING,
4190
+ category: "fact",
4191
+ judgeCall: (options) => acceptingJudge(options),
4192
+ });
4193
+ assert.deepEqual(outcome, {
4194
+ action: "merged",
4195
+ targetId: "fact-target",
4196
+ mergedContent: MERGED,
4197
+ provenancePatched: false,
4198
+ });
4199
+ assert.deepEqual(
4200
+ h.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
4201
+ [{ content: MERGED, actor: "semantic-merge" }],
4202
+ "no semantic-merge-rollback runs while receipt identity is unavailable",
4203
+ );
4204
+ assert.equal(
4205
+ (
4206
+ await listVersions(
4207
+ h.target.path,
4208
+ { enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
4209
+ h.storage.dir,
4210
+ )
4211
+ ).versions.length,
4212
+ 1,
4213
+ "the recovery snapshot is preserved — an unreadable receipt never proves supersession",
4214
+ );
4215
+ });
4216
+
4217
+ test("applySemanticMergeAtPersist: an absent receipt while this writer holds a commit receipt is keep-side (#2813 P1 B)", async () => {
4218
+ // Absent-with-receipt-in-hand corroborates NEITHER writer, so it takes
4219
+ // the same keep-side handling as unavailable: never the superseded
4220
+ // branch, never the discard it licenses.
4221
+ const h = await harness({ frontmatterFails: true, receiptStatus: "absent" });
4222
+ const outcome = await applySemanticMergeAtPersist(h.deps, {
4223
+ storage: h.storage,
4224
+ content: INCOMING,
4225
+ category: "fact",
4226
+ judgeCall: (options) => acceptingJudge(options),
4227
+ });
4228
+ assert.deepEqual(outcome, {
4229
+ action: "merged",
4230
+ targetId: "fact-target",
4231
+ mergedContent: MERGED,
4232
+ provenancePatched: false,
4233
+ });
4234
+ assert.deepEqual(
4235
+ h.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
4236
+ [{ content: MERGED, actor: "semantic-merge" }],
4237
+ );
4238
+ assert.equal(
4239
+ (
4240
+ await listVersions(
4241
+ h.target.path,
4242
+ { enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
4243
+ h.storage.dir,
4244
+ )
4245
+ ).versions.length,
4246
+ 1,
4247
+ "the recovery snapshot is preserved when the sidecar corroborates neither writer",
4248
+ );
4249
+ });