@remnic/core 1.1.11 → 1.1.13

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 (1462) hide show
  1. package/README.md +3 -3
  2. package/dist/access-cli.d.ts +2 -1
  3. package/dist/access-cli.js +293 -104
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +31 -62
  6. package/dist/access-http.js +53 -35
  7. package/dist/access-mcp.d.ts +31 -8
  8. package/dist/access-mcp.js +45 -34
  9. package/dist/access-schema.d.ts +197 -14
  10. package/dist/access-schema.js +16 -5
  11. package/dist/access-service-DcCDmNYC.d.ts +1542 -0
  12. package/dist/access-service.d.ts +30 -9
  13. package/dist/access-service.js +42 -32
  14. package/dist/action-confidence.d.ts +83 -0
  15. package/dist/action-confidence.js +22 -0
  16. package/dist/active-memory-bridge.d.ts +1 -1
  17. package/dist/active-memory-bridge.js +2 -2
  18. package/dist/active-recall.d.ts +1 -1
  19. package/dist/active-recall.js +11 -3
  20. package/dist/active-recall.js.map +1 -1
  21. package/dist/adapters/claude-code.d.ts +24 -0
  22. package/dist/adapters/claude-code.js +9 -0
  23. package/dist/adapters/codex.d.ts +25 -0
  24. package/dist/adapters/codex.js +9 -0
  25. package/dist/adapters/hermes.d.ts +35 -0
  26. package/dist/adapters/hermes.js +9 -0
  27. package/dist/adapters/index.d.ts +6 -0
  28. package/dist/adapters/index.js +26 -0
  29. package/dist/adapters/registry.d.ts +20 -0
  30. package/dist/adapters/registry.js +13 -0
  31. package/dist/adapters/replit.d.ts +28 -0
  32. package/dist/adapters/replit.js +9 -0
  33. package/dist/adapters/types.d.ts +43 -0
  34. package/dist/adapters/types.js +8 -0
  35. package/dist/behavior-learner.d.ts +1 -1
  36. package/dist/behavior-signals.d.ts +1 -1
  37. package/dist/bootstrap.d.ts +23 -6
  38. package/dist/boxes.d.ts +7 -0
  39. package/dist/boxes.js +1 -1
  40. package/dist/briefing.d.ts +5 -3
  41. package/dist/briefing.js +10 -7
  42. package/dist/buffer-surprise-report.d.ts +1 -1
  43. package/dist/buffer-surprise-report.js +1 -1
  44. package/dist/buffer.d.ts +18 -4
  45. package/dist/buffer.js +1 -1
  46. package/dist/calibration.d.ts +1 -1
  47. package/dist/calibration.js +6 -6
  48. package/dist/capsule-cli.d.ts +4 -4
  49. package/dist/capsule-cli.js +1 -1
  50. package/dist/capsule-crypto-5CYAGVC5.js +18 -0
  51. package/dist/capsule-merge-4MGKE7C5.js +189 -0
  52. package/dist/causal-behavior.d.ts +9 -29
  53. package/dist/causal-behavior.js +6 -3
  54. package/dist/causal-behavior.js.map +1 -1
  55. package/dist/causal-chain.js +3 -2
  56. package/dist/causal-consolidation.d.ts +2 -2
  57. package/dist/causal-consolidation.js +28 -17
  58. package/dist/causal-consolidation.js.map +1 -1
  59. package/dist/causal-retrieval.js +3 -3
  60. package/dist/causal-trajectory.js +1 -1
  61. package/dist/chunk-25MQ7IHJ.js +427 -0
  62. package/dist/chunk-25MQ7IHJ.js.map +1 -0
  63. package/dist/chunk-2F2W355T.js +256 -0
  64. package/dist/chunk-2F2W355T.js.map +1 -0
  65. package/dist/chunk-2KI4QFHU.js +228 -0
  66. package/dist/chunk-2KI4QFHU.js.map +1 -0
  67. package/dist/chunk-2PRQG7PV.js +86 -0
  68. package/dist/chunk-2PRQG7PV.js.map +1 -0
  69. package/dist/chunk-2QR3XXIC.js +2272 -0
  70. package/dist/chunk-2QR3XXIC.js.map +1 -0
  71. package/dist/chunk-2WWLHTZY.js +121 -0
  72. package/dist/chunk-326G7DJK.js +2185 -0
  73. package/dist/chunk-326G7DJK.js.map +1 -0
  74. package/dist/chunk-34DQE4KF.js +174 -0
  75. package/dist/chunk-34DQE4KF.js.map +1 -0
  76. package/dist/chunk-3APJ5EVB.js +601 -0
  77. package/dist/chunk-3APJ5EVB.js.map +1 -0
  78. package/dist/chunk-3HPAPHUK.js +51 -0
  79. package/dist/chunk-3HPAPHUK.js.map +1 -0
  80. package/dist/chunk-3JXBXXM2.js +69 -0
  81. package/dist/chunk-3JXBXXM2.js.map +1 -0
  82. package/dist/chunk-3KW65B36.js +681 -0
  83. package/dist/chunk-3KW65B36.js.map +1 -0
  84. package/dist/chunk-3UXOZBHV.js +20 -0
  85. package/dist/chunk-3UXOZBHV.js.map +1 -0
  86. package/dist/chunk-3VAL7ZL2.js +266 -0
  87. package/dist/chunk-3VAL7ZL2.js.map +1 -0
  88. package/dist/chunk-3Y4P7RXM.js +31 -0
  89. package/dist/chunk-3Y4P7RXM.js.map +1 -0
  90. package/dist/chunk-47VWKCAF.js +273 -0
  91. package/dist/chunk-47VWKCAF.js.map +1 -0
  92. package/dist/chunk-4CRG46BG.js +271 -0
  93. package/dist/chunk-4RA3C3EV.js +60 -0
  94. package/dist/chunk-4RA3C3EV.js.map +1 -0
  95. package/dist/chunk-5375UYTQ.js +914 -0
  96. package/dist/chunk-5375UYTQ.js.map +1 -0
  97. package/dist/chunk-56K5QLHX.js +506 -0
  98. package/dist/chunk-56K5QLHX.js.map +1 -0
  99. package/dist/chunk-5NXIJZFX.js +180 -0
  100. package/dist/chunk-5NXIJZFX.js.map +1 -0
  101. package/dist/chunk-5RGLBDQF.js +596 -0
  102. package/dist/chunk-5RGLBDQF.js.map +1 -0
  103. package/dist/chunk-5UZXUTVO.js +9 -0
  104. package/dist/chunk-5UZXUTVO.js.map +1 -0
  105. package/dist/chunk-65PG43EQ.js +105 -0
  106. package/dist/chunk-65PG43EQ.js.map +1 -0
  107. package/dist/chunk-66DHUKLO.js +57 -0
  108. package/dist/chunk-66DHUKLO.js.map +1 -0
  109. package/dist/chunk-6FC5EGNV.js +46 -0
  110. package/dist/chunk-6FC5EGNV.js.map +1 -0
  111. package/dist/chunk-6H2TESSP.js +62 -0
  112. package/dist/chunk-6H2TESSP.js.map +1 -0
  113. package/dist/chunk-6LVVDPJ4.js +32 -0
  114. package/dist/chunk-6LVVDPJ4.js.map +1 -0
  115. package/dist/chunk-6NKAQ74D.js +2237 -0
  116. package/dist/chunk-6NKAQ74D.js.map +1 -0
  117. package/dist/chunk-6RVI47ZR.js +159 -0
  118. package/dist/chunk-6RVI47ZR.js.map +1 -0
  119. package/dist/chunk-7AAT6G4Q.js +5117 -0
  120. package/dist/chunk-7AAT6G4Q.js.map +1 -0
  121. package/dist/chunk-7DTASS5T.js +29 -0
  122. package/dist/chunk-7DTASS5T.js.map +1 -0
  123. package/dist/chunk-7IASACLB.js +596 -0
  124. package/dist/chunk-7MNMYOFP.js +32 -0
  125. package/dist/chunk-7MNMYOFP.js.map +1 -0
  126. package/dist/chunk-7N4KAIGN.js +133 -0
  127. package/dist/chunk-7N4KAIGN.js.map +1 -0
  128. package/dist/chunk-7OZ53EXP.js +101 -0
  129. package/dist/chunk-7OZ53EXP.js.map +1 -0
  130. package/dist/chunk-7XYTQGCC.js +134 -0
  131. package/dist/chunk-7XYTQGCC.js.map +1 -0
  132. package/dist/chunk-A2XUIMJ3.js +341 -0
  133. package/dist/chunk-A2XUIMJ3.js.map +1 -0
  134. package/dist/chunk-AC5LO7IU.js +308 -0
  135. package/dist/chunk-AC5LO7IU.js.map +1 -0
  136. package/dist/chunk-AGZQD76C.js +201 -0
  137. package/dist/chunk-AGZQD76C.js.map +1 -0
  138. package/dist/chunk-AH2JUU6X.js +336 -0
  139. package/dist/chunk-AH2JUU6X.js.map +1 -0
  140. package/dist/chunk-APO3DCMU.js +361 -0
  141. package/dist/chunk-APO3DCMU.js.map +1 -0
  142. package/dist/chunk-BFBF3XEF.js +283 -0
  143. package/dist/chunk-BFBF3XEF.js.map +1 -0
  144. package/dist/chunk-BJ3KMYTB.js +1974 -0
  145. package/dist/chunk-BJ3KMYTB.js.map +1 -0
  146. package/dist/chunk-C5BCH4ZS.js +317 -0
  147. package/dist/chunk-C5BCH4ZS.js.map +1 -0
  148. package/dist/chunk-CHEL3SKB.js +6758 -0
  149. package/dist/chunk-CHEL3SKB.js.map +1 -0
  150. package/dist/chunk-CQZRLNMV.js +1491 -0
  151. package/dist/chunk-CQZRLNMV.js.map +1 -0
  152. package/dist/chunk-D46YSIYX.js +892 -0
  153. package/dist/chunk-D46YSIYX.js.map +1 -0
  154. package/dist/chunk-DB5A3NHS.js +906 -0
  155. package/dist/chunk-DB5A3NHS.js.map +1 -0
  156. package/dist/chunk-DINWEURR.js +648 -0
  157. package/dist/chunk-DINWEURR.js.map +1 -0
  158. package/dist/chunk-DK5LDEQM.js +530 -0
  159. package/dist/chunk-DK5LDEQM.js.map +1 -0
  160. package/dist/chunk-DOM4GKSW.js +34 -0
  161. package/dist/chunk-DOM4GKSW.js.map +1 -0
  162. package/dist/chunk-EDTHC6UD.js +1075 -0
  163. package/dist/chunk-EDTHC6UD.js.map +1 -0
  164. package/dist/chunk-EFJ3MQ4V.js +721 -0
  165. package/dist/chunk-EHRTFRWW.js +89 -0
  166. package/dist/chunk-EHRTFRWW.js.map +1 -0
  167. package/dist/chunk-FAJ7FZYM.js +11 -0
  168. package/dist/chunk-FAJ7FZYM.js.map +1 -0
  169. package/dist/chunk-FBYESMQ2.js +570 -0
  170. package/dist/chunk-FBYESMQ2.js.map +1 -0
  171. package/dist/chunk-FDU6HUUL.js +147 -0
  172. package/dist/chunk-FF4KLI5W.js +99 -0
  173. package/dist/chunk-FF4KLI5W.js.map +1 -0
  174. package/dist/chunk-FIT6DMX6.js +310 -0
  175. package/dist/chunk-FIT6DMX6.js.map +1 -0
  176. package/dist/chunk-FJ43PRLT.js +272 -0
  177. package/dist/chunk-FJ43PRLT.js.map +1 -0
  178. package/dist/chunk-FKFMOY3N.js +32 -0
  179. package/dist/chunk-FKFMOY3N.js.map +1 -0
  180. package/dist/chunk-FLTNHQK6.js +262 -0
  181. package/dist/chunk-FLTNHQK6.js.map +1 -0
  182. package/dist/chunk-GA454ALV.js +12436 -0
  183. package/dist/chunk-GA454ALV.js.map +1 -0
  184. package/dist/chunk-GGKRUQOO.js +228 -0
  185. package/dist/chunk-GIF42EW3.js +63 -0
  186. package/dist/chunk-GIF42EW3.js.map +1 -0
  187. package/dist/chunk-GL6I6MEQ.js +647 -0
  188. package/dist/chunk-H3ME6L6D.js +709 -0
  189. package/dist/chunk-H3ME6L6D.js.map +1 -0
  190. package/dist/chunk-HHLLAQGZ.js +1 -0
  191. package/dist/chunk-HXXBL2KD.js +2040 -0
  192. package/dist/chunk-I5V2VDIW.js +219 -0
  193. package/dist/chunk-I5V2VDIW.js.map +1 -0
  194. package/dist/chunk-I6K5FBRQ.js +35 -0
  195. package/dist/chunk-I6K5FBRQ.js.map +1 -0
  196. package/dist/chunk-ICRIXAP2.js +121 -0
  197. package/dist/chunk-ICRIXAP2.js.map +1 -0
  198. package/dist/chunk-J4EB7DNW.js +11 -0
  199. package/dist/chunk-J4EB7DNW.js.map +1 -0
  200. package/dist/chunk-JLFA7DQG.js +62 -0
  201. package/dist/chunk-JLFA7DQG.js.map +1 -0
  202. package/dist/chunk-KJTKLXTH.js +9 -0
  203. package/dist/chunk-KJTKLXTH.js.map +1 -0
  204. package/dist/chunk-KLAO5DGL.js +917 -0
  205. package/dist/chunk-KLAO5DGL.js.map +1 -0
  206. package/dist/chunk-KNKUID7G.js +183 -0
  207. package/dist/chunk-KOSORCJG.js +624 -0
  208. package/dist/chunk-KOSORCJG.js.map +1 -0
  209. package/dist/chunk-KUJVMMZQ.js +1262 -0
  210. package/dist/chunk-KUJVMMZQ.js.map +1 -0
  211. package/dist/chunk-LCR46JY5.js +123 -0
  212. package/dist/chunk-LCR46JY5.js.map +1 -0
  213. package/dist/chunk-LLQ2LLWF.js +148 -0
  214. package/dist/chunk-LLQ2LLWF.js.map +1 -0
  215. package/dist/chunk-LPMVBPA3.js +236 -0
  216. package/dist/chunk-LT3NLYSI.js +50 -0
  217. package/dist/chunk-LT3NLYSI.js.map +1 -0
  218. package/dist/chunk-LUDTDZLK.js +287 -0
  219. package/dist/chunk-LUDTDZLK.js.map +1 -0
  220. package/dist/chunk-M23FSH32.js +3963 -0
  221. package/dist/chunk-M23FSH32.js.map +1 -0
  222. package/dist/chunk-MC26UJIM.js +118 -0
  223. package/dist/chunk-ME6ESPZU.js +119 -0
  224. package/dist/chunk-ME6ESPZU.js.map +1 -0
  225. package/dist/chunk-MGKYQQYF.js +272 -0
  226. package/dist/chunk-MGKYQQYF.js.map +1 -0
  227. package/dist/chunk-MJFNCJXV.js +66 -0
  228. package/dist/chunk-MJFNCJXV.js.map +1 -0
  229. package/dist/chunk-MSWG7JI6.js +237 -0
  230. package/dist/chunk-MSWG7JI6.js.map +1 -0
  231. package/dist/chunk-MT25YHYH.js +141 -0
  232. package/dist/chunk-MT25YHYH.js.map +1 -0
  233. package/dist/chunk-MT4HVDUZ.js +53 -0
  234. package/dist/chunk-MY6TPVXW.js +219 -0
  235. package/dist/chunk-N2D6GXBM.js +267 -0
  236. package/dist/chunk-N2D6GXBM.js.map +1 -0
  237. package/dist/chunk-NJ3MJQZX.js +46 -0
  238. package/dist/chunk-NJ3MJQZX.js.map +1 -0
  239. package/dist/chunk-NMZY542O.js +335 -0
  240. package/dist/chunk-NMZY542O.js.map +1 -0
  241. package/dist/chunk-NNVTUXEB.js +23 -0
  242. package/dist/chunk-NZL6GGQE.js +375 -0
  243. package/dist/chunk-NZL6GGQE.js.map +1 -0
  244. package/dist/chunk-OAZ5MFUB.js +4124 -0
  245. package/dist/chunk-OAZ5MFUB.js.map +1 -0
  246. package/dist/chunk-OIGNEXKZ.js +237 -0
  247. package/dist/chunk-OIGNEXKZ.js.map +1 -0
  248. package/dist/chunk-OZKZ2TRP.js +3729 -0
  249. package/dist/chunk-OZKZ2TRP.js.map +1 -0
  250. package/dist/chunk-P4NEIHUT.js +108 -0
  251. package/dist/chunk-P7FMDTKL.js +103 -0
  252. package/dist/chunk-P7FMDTKL.js.map +1 -0
  253. package/dist/chunk-PD6O7AXF.js +110 -0
  254. package/dist/chunk-PD6O7AXF.js.map +1 -0
  255. package/dist/chunk-PHK3HARR.js +32 -0
  256. package/dist/chunk-PHK3HARR.js.map +1 -0
  257. package/dist/chunk-PIRJPV5T.js +98 -0
  258. package/dist/chunk-PIRJPV5T.js.map +1 -0
  259. package/dist/chunk-PK7H5L6Y.js +159 -0
  260. package/dist/chunk-PK7H5L6Y.js.map +1 -0
  261. package/dist/chunk-PR5FBTFU.js +233 -0
  262. package/dist/chunk-PR5FBTFU.js.map +1 -0
  263. package/dist/chunk-PU63GXWS.js +174 -0
  264. package/dist/chunk-PU63GXWS.js.map +1 -0
  265. package/dist/chunk-PYPOFEMK.js +294 -0
  266. package/dist/chunk-PYPOFEMK.js.map +1 -0
  267. package/dist/chunk-PZIAX57I.js +124 -0
  268. package/dist/chunk-PZIAX57I.js.map +1 -0
  269. package/dist/chunk-Q7P4WJDP.js +26 -0
  270. package/dist/chunk-Q7P4WJDP.js.map +1 -0
  271. package/dist/chunk-QDZ2RLEC.js +908 -0
  272. package/dist/chunk-QDZ2RLEC.js.map +1 -0
  273. package/dist/chunk-QQUAB63I.js +63 -0
  274. package/dist/chunk-QQUAB63I.js.map +1 -0
  275. package/dist/chunk-QRNI5JBH.js +18 -0
  276. package/dist/chunk-RHY3HH7P.js +601 -0
  277. package/dist/chunk-RHY3HH7P.js.map +1 -0
  278. package/dist/chunk-RK6F44Y6.js +84 -0
  279. package/dist/chunk-RK6F44Y6.js.map +1 -0
  280. package/dist/chunk-RRF5UOBJ.js +91 -0
  281. package/dist/chunk-RXDLTSWT.js +124 -0
  282. package/dist/chunk-RXDLTSWT.js.map +1 -0
  283. package/dist/chunk-RYED3SPJ.js +42 -0
  284. package/dist/chunk-RYED3SPJ.js.map +1 -0
  285. package/dist/chunk-S7KDBTWT.js +106 -0
  286. package/dist/chunk-S7KDBTWT.js.map +1 -0
  287. package/dist/chunk-SEDEKFYQ.js +1 -0
  288. package/dist/chunk-SOAU2OE2.js +125 -0
  289. package/dist/chunk-SOAU2OE2.js.map +1 -0
  290. package/dist/chunk-TECVW3JP.js +36 -0
  291. package/dist/chunk-TECVW3JP.js.map +1 -0
  292. package/dist/chunk-TFO23QT4.js +88 -0
  293. package/dist/chunk-TFO23QT4.js.map +1 -0
  294. package/dist/chunk-TK4UEOSK.js +76 -0
  295. package/dist/chunk-TK4UEOSK.js.map +1 -0
  296. package/dist/chunk-TKWGAOLV.js +122 -0
  297. package/dist/chunk-TKWGAOLV.js.map +1 -0
  298. package/dist/chunk-TMM4S4IJ.js +597 -0
  299. package/dist/chunk-TMM4S4IJ.js.map +1 -0
  300. package/dist/chunk-TMQLARTH.js +188 -0
  301. package/dist/chunk-TMQLARTH.js.map +1 -0
  302. package/dist/chunk-TPDBFYEG.js +130 -0
  303. package/dist/chunk-TPDBFYEG.js.map +1 -0
  304. package/dist/chunk-TPMQ3G6Z.js +145 -0
  305. package/dist/chunk-TPMQ3G6Z.js.map +1 -0
  306. package/dist/chunk-TZOLIGIG.js +61 -0
  307. package/dist/chunk-TZOLIGIG.js.map +1 -0
  308. package/dist/chunk-U3PN77QT.js +113 -0
  309. package/dist/chunk-U3WSW6PZ.js +277 -0
  310. package/dist/chunk-U4SCL7B7.js +640 -0
  311. package/dist/chunk-U4SCL7B7.js.map +1 -0
  312. package/dist/chunk-UWK5OXUJ.js +156 -0
  313. package/dist/chunk-UWK5OXUJ.js.map +1 -0
  314. package/dist/chunk-UWVJF25J.js +74 -0
  315. package/dist/chunk-UXHQAFNA.js +1317 -0
  316. package/dist/chunk-UXHQAFNA.js.map +1 -0
  317. package/dist/chunk-V5OCT34X.js +1 -0
  318. package/dist/chunk-V5OCT34X.js.map +1 -0
  319. package/dist/chunk-VLXA6PI2.js +304 -0
  320. package/dist/chunk-VLXA6PI2.js.map +1 -0
  321. package/dist/chunk-VNO6ZJ35.js +500 -0
  322. package/dist/chunk-VNO6ZJ35.js.map +1 -0
  323. package/dist/chunk-VW676BEI.js +827 -0
  324. package/dist/chunk-VW676BEI.js.map +1 -0
  325. package/dist/chunk-VWT3F4IV.js +2161 -0
  326. package/dist/chunk-VWT3F4IV.js.map +1 -0
  327. package/dist/chunk-W3LR522O.js +2296 -0
  328. package/dist/chunk-W3LR522O.js.map +1 -0
  329. package/dist/chunk-W4L6CZKA.js +96 -0
  330. package/dist/chunk-W4L6CZKA.js.map +1 -0
  331. package/dist/chunk-W4RVMTHR.js +372 -0
  332. package/dist/chunk-W4RVMTHR.js.map +1 -0
  333. package/dist/chunk-WEHSQBFR.js +188 -0
  334. package/dist/chunk-WEHSQBFR.js.map +1 -0
  335. package/dist/chunk-WELDCG6C.js +380 -0
  336. package/dist/chunk-WELDCG6C.js.map +1 -0
  337. package/dist/chunk-WZYKANL3.js +2800 -0
  338. package/dist/chunk-WZYKANL3.js.map +1 -0
  339. package/dist/chunk-XIG5PDM7.js +48 -0
  340. package/dist/chunk-XJNBEDFE.js +193 -0
  341. package/dist/chunk-XJNBEDFE.js.map +1 -0
  342. package/dist/chunk-XVVIG67A.js +291 -0
  343. package/dist/chunk-XVVIG67A.js.map +1 -0
  344. package/dist/chunk-XVZ7B3HG.js +135 -0
  345. package/dist/chunk-YBPYIAA5.js +73 -0
  346. package/dist/chunk-YBPYIAA5.js.map +1 -0
  347. package/dist/chunk-Z734BLO3.js +21 -0
  348. package/dist/chunk-Z734BLO3.js.map +1 -0
  349. package/dist/chunk-ZKSK55RC.js +269 -0
  350. package/dist/chunk-ZKSK55RC.js.map +1 -0
  351. package/dist/chunk-ZTFCYYEZ.js +69 -0
  352. package/dist/chunk-ZTFCYYEZ.js.map +1 -0
  353. package/dist/chunk-ZY2MNJR6.js +329 -0
  354. package/dist/chunk-ZY2MNJR6.js.map +1 -0
  355. package/dist/cli-D3VpkVwB.d.ts +1136 -0
  356. package/dist/cli.d.ts +42 -10
  357. package/dist/cli.js +121 -58
  358. package/dist/codex-cli-fallback.d.ts +1 -0
  359. package/dist/codex-cli-fallback.js +1 -1
  360. package/dist/commitment-ledger.js +1 -1
  361. package/dist/compat/checks.d.ts +5 -0
  362. package/dist/compat/checks.js +11 -0
  363. package/dist/compat/checks.js.map +1 -0
  364. package/dist/compat/types.d.ts +30 -0
  365. package/dist/compat/types.js +1 -0
  366. package/dist/compat/types.js.map +1 -0
  367. package/dist/compounding/engine.d.ts +221 -0
  368. package/dist/compounding/engine.js +32 -0
  369. package/dist/compounding/engine.js.map +1 -0
  370. package/dist/compounding/preference-consolidator.d.ts +92 -0
  371. package/dist/compounding/preference-consolidator.js +553 -0
  372. package/dist/compounding/preference-consolidator.js.map +1 -0
  373. package/dist/compression-optimizer.d.ts +1 -1
  374. package/dist/config.d.ts +5 -3
  375. package/dist/config.js +9 -4
  376. package/dist/conflict-policy-DyJ2wd-h.d.ts +4 -0
  377. package/dist/connectors/codex-materialize-runner.d.ts +64 -0
  378. package/dist/connectors/codex-materialize-runner.js +33 -0
  379. package/dist/connectors/codex-materialize-runner.js.map +1 -0
  380. package/dist/connectors/codex-materialize.d.ts +195 -0
  381. package/dist/connectors/codex-materialize.js +38 -0
  382. package/dist/connectors/codex-materialize.js.map +1 -0
  383. package/dist/connectors/index.d.ts +444 -0
  384. package/dist/connectors/index.js +115 -0
  385. package/dist/connectors/index.js.map +1 -0
  386. package/dist/connectors-cli-CwbyjGR7.d.ts +257 -0
  387. package/dist/connectors-cli.d.ts +1 -1
  388. package/dist/consolidation-provenance-check.d.ts +4 -2
  389. package/dist/consolidation-undo.d.ts +4 -2
  390. package/dist/contradiction/index.d.ts +258 -0
  391. package/dist/contradiction/index.js +43 -0
  392. package/dist/contradiction/index.js.map +1 -0
  393. package/dist/contradiction-review-ATP4S6IC.js +30 -0
  394. package/dist/contradiction-review-ATP4S6IC.js.map +1 -0
  395. package/dist/contradiction-scan-5A4IDZV5.js +13 -0
  396. package/dist/contradiction-scan-5A4IDZV5.js.map +1 -0
  397. package/dist/conversation-index/backend.d.ts +97 -0
  398. package/dist/conversation-index/backend.js +13 -0
  399. package/dist/conversation-index/backend.js.map +1 -0
  400. package/dist/conversation-index/chunker.d.ts +16 -0
  401. package/dist/conversation-index/chunker.js +8 -0
  402. package/dist/conversation-index/chunker.js.map +1 -0
  403. package/dist/conversation-index/cleanup.d.ts +11 -0
  404. package/dist/conversation-index/cleanup.js +9 -0
  405. package/dist/conversation-index/cleanup.js.map +1 -0
  406. package/dist/conversation-index/faiss-adapter.d.ts +6 -0
  407. package/dist/conversation-index/faiss-adapter.js +16 -0
  408. package/dist/conversation-index/faiss-adapter.js.map +1 -0
  409. package/dist/conversation-index/indexer.d.ts +23 -0
  410. package/dist/conversation-index/indexer.js +15 -0
  411. package/dist/conversation-index/indexer.js.map +1 -0
  412. package/dist/conversation-index/search.d.ts +6 -0
  413. package/dist/conversation-index/search.js +11 -0
  414. package/dist/conversation-index/search.js.map +1 -0
  415. package/dist/day-summary.d.ts +1 -1
  416. package/dist/delinearize.d.ts +1 -1
  417. package/dist/direct-answer-wiring.d.ts +1 -1
  418. package/dist/direct-answer-wiring.js +1 -1
  419. package/dist/direct-answer.d.ts +1 -1
  420. package/dist/embedding-fallback.d.ts +1 -1
  421. package/dist/embedding-fallback.js +2 -2
  422. package/dist/enrichment/index.d.ts +163 -0
  423. package/dist/enrichment/index.js +18 -0
  424. package/dist/enrichment/index.js.map +1 -0
  425. package/dist/entity-retrieval.d.ts +4 -2
  426. package/dist/entity-retrieval.js +9 -6
  427. package/dist/entity-schema.d.ts +1 -1
  428. package/dist/evals.js +1 -1
  429. package/dist/event-order-recall.d.ts +17 -0
  430. package/dist/event-order-recall.js +11 -0
  431. package/dist/event-order-recall.js.map +1 -0
  432. package/dist/evidence-pack.d.ts +3 -1
  433. package/dist/evidence-pack.js +5 -3
  434. package/dist/explicit-capture.d.ts +23 -6
  435. package/dist/explicit-capture.js +2 -2
  436. package/dist/explicit-cue-recall.d.ts +4 -1
  437. package/dist/explicit-cue-recall.js +4 -2
  438. package/dist/extraction-judge-telemetry.d.ts +1 -1
  439. package/dist/extraction-judge-training.d.ts +1 -1
  440. package/dist/extraction-judge-training.js +1 -1
  441. package/dist/extraction-judge.d.ts +1 -1
  442. package/dist/extraction.d.ts +1 -1
  443. package/dist/extraction.js +11 -10
  444. package/dist/faiss-adapter-CzPghc4C.d.ts +70 -0
  445. package/dist/fallback-llm.d.ts +4 -1
  446. package/dist/fallback-llm.js +6 -6
  447. package/dist/focused-list-recall.d.ts +17 -0
  448. package/dist/focused-list-recall.js +11 -0
  449. package/dist/focused-list-recall.js.map +1 -0
  450. package/dist/graph-edge-decay-5DI5GUNL.js +207 -0
  451. package/dist/identity-continuity.d.ts +1 -1
  452. package/dist/importance.d.ts +1 -1
  453. package/dist/index-DJ9QWMw-.d.ts +35 -0
  454. package/dist/index.d.ts +107 -715
  455. package/dist/index.js +657 -2611
  456. package/dist/index.js.map +1 -1
  457. package/dist/intent.d.ts +1 -1
  458. package/dist/intent.js +1 -1
  459. package/dist/lcm/archive.d.ts +89 -0
  460. package/dist/lcm/archive.js +12 -0
  461. package/dist/lcm/archive.js.map +1 -0
  462. package/dist/lcm/dag.d.ts +48 -0
  463. package/dist/lcm/dag.js +8 -0
  464. package/dist/lcm/dag.js.map +1 -0
  465. package/dist/lcm/engine.d.ts +116 -0
  466. package/dist/lcm/engine.js +20 -0
  467. package/dist/lcm/engine.js.map +1 -0
  468. package/dist/lcm/index.d.ts +12 -0
  469. package/dist/lcm/index.js +44 -0
  470. package/dist/lcm/index.js.map +1 -0
  471. package/dist/lcm/queue.d.ts +62 -0
  472. package/dist/lcm/queue.js +8 -0
  473. package/dist/lcm/queue.js.map +1 -0
  474. package/dist/lcm/recall.d.ts +20 -0
  475. package/dist/lcm/recall.js +8 -0
  476. package/dist/lcm/recall.js.map +1 -0
  477. package/dist/lcm/schema.d.ts +16 -0
  478. package/dist/lcm/schema.js +14 -0
  479. package/dist/lcm/schema.js.map +1 -0
  480. package/dist/lcm/summarizer.d.ts +38 -0
  481. package/dist/lcm/summarizer.js +12 -0
  482. package/dist/lcm/summarizer.js.map +1 -0
  483. package/dist/lcm/tools.d.ts +29 -0
  484. package/dist/lcm/tools.js +8 -0
  485. package/dist/lcm/tools.js.map +1 -0
  486. package/dist/lifecycle.d.ts +1 -1
  487. package/dist/live-connectors-runner.d.ts +1 -1
  488. package/dist/live-connectors-runner.js +5 -5
  489. package/dist/local-llm.d.ts +8 -4
  490. package/dist/local-llm.js +3 -3
  491. package/dist/maintenance/archive-observations.d.ts +18 -0
  492. package/dist/maintenance/archive-observations.js +8 -0
  493. package/dist/maintenance/archive-observations.js.map +1 -0
  494. package/dist/maintenance/backup-stamp.d.ts +3 -0
  495. package/dist/maintenance/backup-stamp.js +8 -0
  496. package/dist/maintenance/backup-stamp.js.map +1 -0
  497. package/dist/maintenance/memory-governance-cron.d.ts +85 -0
  498. package/dist/maintenance/memory-governance-cron.js +22 -0
  499. package/dist/maintenance/memory-governance-cron.js.map +1 -0
  500. package/dist/maintenance/memory-governance.d.ts +137 -0
  501. package/dist/maintenance/memory-governance.js +40 -0
  502. package/dist/maintenance/memory-governance.js.map +1 -0
  503. package/dist/maintenance/migrate-observations.d.ts +18 -0
  504. package/dist/maintenance/migrate-observations.js +9 -0
  505. package/dist/maintenance/migrate-observations.js.map +1 -0
  506. package/dist/maintenance/observation-ledger-utils.d.ts +10 -0
  507. package/dist/maintenance/observation-ledger-utils.js +10 -0
  508. package/dist/maintenance/observation-ledger-utils.js.map +1 -0
  509. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +15 -0
  510. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +28 -0
  511. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js.map +1 -0
  512. package/dist/maintenance/rebuild-memory-projection.d.ts +77 -0
  513. package/dist/maintenance/rebuild-memory-projection.js +35 -0
  514. package/dist/maintenance/rebuild-memory-projection.js.map +1 -0
  515. package/dist/maintenance/rebuild-observations.d.ts +17 -0
  516. package/dist/maintenance/rebuild-observations.js +9 -0
  517. package/dist/maintenance/rebuild-observations.js.map +1 -0
  518. package/dist/mcp-memory-inspector-app.d.ts +124 -0
  519. package/dist/mcp-memory-inspector-app.js +20 -0
  520. package/dist/mcp-memory-inspector-app.js.map +1 -0
  521. package/dist/memory-action-policy.d.ts +1 -1
  522. package/dist/memory-cache.d.ts +1 -1
  523. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  524. package/dist/memory-projection-store.d.ts +108 -3
  525. package/dist/memory-projection-store.js +2 -1
  526. package/dist/memory-provenance.d.ts +57 -0
  527. package/dist/memory-provenance.js +13 -0
  528. package/dist/memory-provenance.js.map +1 -0
  529. package/dist/memory-worth-outcomes.d.ts +4 -2
  530. package/dist/migrate/from-engram.d.ts +24 -0
  531. package/dist/migrate/from-engram.js +12 -0
  532. package/dist/migrate/from-engram.js.map +1 -0
  533. package/dist/models-json.d.ts +1 -1
  534. package/dist/namespaces/migrate.d.ts +50 -0
  535. package/dist/namespaces/migrate.js +50 -0
  536. package/dist/namespaces/migrate.js.map +1 -0
  537. package/dist/namespaces/principal.d.ts +17 -0
  538. package/dist/namespaces/principal.js +16 -0
  539. package/dist/namespaces/principal.js.map +1 -0
  540. package/dist/namespaces/search.d.ts +46 -0
  541. package/dist/namespaces/search.js +28 -0
  542. package/dist/namespaces/search.js.map +1 -0
  543. package/dist/namespaces/storage.d.ts +32 -0
  544. package/dist/namespaces/storage.js +28 -0
  545. package/dist/namespaces/storage.js.map +1 -0
  546. package/dist/native-knowledge.d.ts +1 -1
  547. package/dist/network/tailscale.d.ts +41 -0
  548. package/dist/network/tailscale.js +9 -0
  549. package/dist/network/tailscale.js.map +1 -0
  550. package/dist/network/webdav.d.ts +39 -0
  551. package/dist/network/webdav.js +10 -0
  552. package/dist/network/webdav.js.map +1 -0
  553. package/dist/objective-state-writers.d.ts +1 -1
  554. package/dist/objective-state-writers.js +2 -2
  555. package/dist/operator-toolkit.d.ts +4 -2
  556. package/dist/operator-toolkit.js +35 -17
  557. package/dist/opik-exporter.js +2 -2
  558. package/dist/opik-exporter.js.map +1 -1
  559. package/dist/orchestrator-DuWl9Hwx.d.ts +1244 -0
  560. package/dist/orchestrator.d.ts +24 -7
  561. package/dist/orchestrator.js +107 -65
  562. package/dist/path-MR5JPYOP.js +9 -0
  563. package/dist/path-MR5JPYOP.js.map +1 -0
  564. package/dist/patterns-cli.d.ts +1 -1
  565. package/dist/policy-runtime.d.ts +1 -1
  566. package/dist/qmd-recall-cache.d.ts +2 -2
  567. package/dist/qmd.d.ts +103 -4
  568. package/dist/qmd.js +23 -5
  569. package/dist/recall-disclosure-escalation.d.ts +1 -1
  570. package/dist/recall-explain-renderer.d.ts +3 -1
  571. package/dist/recall-explain-renderer.js +5 -3
  572. package/dist/recall-state.d.ts +1 -1
  573. package/dist/recall-tag-filter.d.ts +3 -1
  574. package/dist/recall-xray-cli.d.ts +3 -1
  575. package/dist/recall-xray-cli.js +6 -4
  576. package/dist/recall-xray-renderer.d.ts +3 -1
  577. package/dist/recall-xray-renderer.js +5 -3
  578. package/dist/recall-xray.d.ts +8 -1
  579. package/dist/recall-xray.js +4 -2
  580. package/dist/replay/normalizers/chatgpt.d.ts +6 -0
  581. package/dist/replay/normalizers/chatgpt.js +11 -0
  582. package/dist/replay/normalizers/chatgpt.js.map +1 -0
  583. package/dist/replay/normalizers/claude.d.ts +6 -0
  584. package/dist/replay/normalizers/claude.js +11 -0
  585. package/dist/replay/normalizers/claude.js.map +1 -0
  586. package/dist/replay/normalizers/openclaw.d.ts +6 -0
  587. package/dist/replay/normalizers/openclaw.js +11 -0
  588. package/dist/replay/normalizers/openclaw.js.map +1 -0
  589. package/dist/replay/normalizers/shared.d.ts +16 -0
  590. package/dist/replay/normalizers/shared.js +14 -0
  591. package/dist/replay/normalizers/shared.js.map +1 -0
  592. package/dist/replay/runner.d.ts +35 -0
  593. package/dist/replay/runner.js +16 -0
  594. package/dist/replay/runner.js.map +1 -0
  595. package/dist/replay/types.d.ts +57 -0
  596. package/dist/replay/types.js +19 -0
  597. package/dist/replay/types.js.map +1 -0
  598. package/dist/resolution-B7FNQSSP.js +12 -0
  599. package/dist/resolution-B7FNQSSP.js.map +1 -0
  600. package/dist/resolve-auth-token.d.ts +1 -1
  601. package/dist/resolve-provider-secret.js +2 -2
  602. package/dist/response-guidance-recall.d.ts +18 -0
  603. package/dist/response-guidance-recall.js +11 -0
  604. package/dist/response-guidance-recall.js.map +1 -0
  605. package/dist/resume-bundles.js +7 -5
  606. package/dist/retrieval-agents.d.ts +2 -2
  607. package/dist/retrieval-tiers.d.ts +1 -1
  608. package/dist/routing/engine.d.ts +35 -0
  609. package/dist/routing/engine.js +16 -0
  610. package/dist/routing/engine.js.map +1 -0
  611. package/dist/routing/store.d.ts +27 -0
  612. package/dist/routing/store.js +10 -0
  613. package/dist/routing/store.js.map +1 -0
  614. package/dist/runtime/better-sqlite.d.ts +8 -0
  615. package/dist/runtime/better-sqlite.js +10 -0
  616. package/dist/runtime/better-sqlite.js.map +1 -0
  617. package/dist/runtime/child-process.d.ts +32 -0
  618. package/dist/runtime/child-process.js +10 -0
  619. package/dist/runtime/child-process.js.map +1 -0
  620. package/dist/runtime/env.d.ts +5 -0
  621. package/dist/runtime/env.js +12 -0
  622. package/dist/runtime/env.js.map +1 -0
  623. package/dist/sdk-compat.js +1 -1
  624. package/dist/search/document-scanner.d.ts +22 -0
  625. package/dist/search/document-scanner.js +8 -0
  626. package/dist/search/document-scanner.js.map +1 -0
  627. package/dist/search/embed-helper.d.ts +35 -0
  628. package/dist/search/embed-helper.js +9 -0
  629. package/dist/search/embed-helper.js.map +1 -0
  630. package/dist/search/factory.d.ts +32 -0
  631. package/dist/search/factory.js +29 -0
  632. package/dist/search/factory.js.map +1 -0
  633. package/dist/search/index.d.ts +15 -0
  634. package/dist/search/index.js +50 -0
  635. package/dist/search/index.js.map +1 -0
  636. package/dist/search/lancedb-backend.d.ts +51 -0
  637. package/dist/search/lancedb-backend.js +10 -0
  638. package/dist/search/lancedb-backend.js.map +1 -0
  639. package/dist/search/meilisearch-backend.d.ts +48 -0
  640. package/dist/search/meilisearch-backend.js +10 -0
  641. package/dist/search/meilisearch-backend.js.map +1 -0
  642. package/dist/search/noop-backend.d.ts +26 -0
  643. package/dist/search/noop-backend.js +8 -0
  644. package/dist/search/noop-backend.js.map +1 -0
  645. package/dist/search/orama-backend.d.ts +53 -0
  646. package/dist/search/orama-backend.js +10 -0
  647. package/dist/search/orama-backend.js.map +1 -0
  648. package/dist/search/port.d.ts +61 -0
  649. package/dist/search/port.js +1 -0
  650. package/dist/search/port.js.map +1 -0
  651. package/dist/search/remote-backend.d.ts +39 -0
  652. package/dist/search/remote-backend.js +9 -0
  653. package/dist/search/remote-backend.js.map +1 -0
  654. package/dist/secure-store/index.d.ts +890 -0
  655. package/dist/secure-store/index.js +156 -0
  656. package/dist/secure-store/index.js.map +1 -0
  657. package/dist/semantic-VwGI14Ok.d.ts +69 -0
  658. package/dist/semantic-consolidation-4HkHWgeI.d.ts +180 -0
  659. package/dist/semantic-consolidation.d.ts +3 -3
  660. package/dist/semantic-consolidation.js +15 -8
  661. package/dist/semantic-rule-promotion.js +9 -6
  662. package/dist/semantic-rule-verifier.d.ts +1 -1
  663. package/dist/semantic-rule-verifier.js +10 -7
  664. package/dist/session-observer-bands.d.ts +1 -1
  665. package/dist/session-observer-state.d.ts +1 -1
  666. package/dist/shared-context/manager.d.ts +131 -0
  667. package/dist/shared-context/manager.js +15 -0
  668. package/dist/shared-context/manager.js.map +1 -0
  669. package/dist/signal.d.ts +1 -1
  670. package/dist/skills-registry.js +13 -1
  671. package/dist/skills-registry.js.map +1 -1
  672. package/dist/state-store-VZU2IA53.js +16 -0
  673. package/dist/state-store-VZU2IA53.js.map +1 -0
  674. package/dist/storage-paths.d.ts +9 -0
  675. package/dist/storage-paths.js +20 -0
  676. package/dist/storage-paths.js.map +1 -0
  677. package/dist/storage.d.ts +6 -2
  678. package/dist/storage.js +8 -5
  679. package/dist/summarizer.d.ts +6 -1
  680. package/dist/summarizer.js +11 -10
  681. package/dist/summary-snapshot.d.ts +1 -1
  682. package/dist/summary-snapshot.js +2 -1
  683. package/dist/surfaces/dreams.d.ts +16 -0
  684. package/dist/surfaces/dreams.js +282 -0
  685. package/dist/surfaces/dreams.js.map +1 -0
  686. package/dist/surfaces/heartbeat.d.ts +17 -0
  687. package/dist/surfaces/heartbeat.js +265 -0
  688. package/dist/surfaces/heartbeat.js.map +1 -0
  689. package/dist/targeted-fact-recall.d.ts +17 -0
  690. package/dist/targeted-fact-recall.js +11 -0
  691. package/dist/targeted-fact-recall.js.map +1 -0
  692. package/dist/telemetry-transcript.d.ts +7 -0
  693. package/dist/telemetry-transcript.js +16 -0
  694. package/dist/telemetry-transcript.js.map +1 -0
  695. package/dist/temporal-supersession.d.ts +4 -2
  696. package/dist/temporal-supersession.js +2 -1
  697. package/dist/temporal-validity.d.ts +1 -1
  698. package/dist/threading.d.ts +6 -1
  699. package/dist/threading.js +2 -1
  700. package/dist/tier-migration.d.ts +5 -3
  701. package/dist/tier-routing.d.ts +1 -1
  702. package/dist/tokens.js +2 -2
  703. package/dist/topics.d.ts +1 -1
  704. package/dist/transcript.d.ts +16 -2
  705. package/dist/transcript.js +2 -1
  706. package/dist/transfer/autodetect.d.ts +4 -0
  707. package/dist/transfer/autodetect.js +15 -0
  708. package/dist/transfer/autodetect.js.map +1 -0
  709. package/dist/transfer/backup.d.ts +21 -0
  710. package/dist/transfer/backup.js +17 -0
  711. package/dist/transfer/backup.js.map +1 -0
  712. package/dist/transfer/capsule-export.d.ts +113 -0
  713. package/dist/transfer/capsule-export.js +19 -0
  714. package/dist/transfer/capsule-export.js.map +1 -0
  715. package/dist/transfer/capsule-import.d.ts +124 -0
  716. package/dist/transfer/capsule-import.js +16 -0
  717. package/dist/transfer/capsule-import.js.map +1 -0
  718. package/dist/transfer/constants.d.ts +13 -0
  719. package/dist/transfer/constants.js +12 -0
  720. package/dist/transfer/constants.js.map +1 -0
  721. package/dist/transfer/export-json.d.ts +11 -0
  722. package/dist/transfer/export-json.js +11 -0
  723. package/dist/transfer/export-json.js.map +1 -0
  724. package/dist/transfer/export-md.d.ts +10 -0
  725. package/dist/transfer/export-md.js +13 -0
  726. package/dist/transfer/export-md.js.map +1 -0
  727. package/dist/transfer/export-sqlite.d.ts +9 -0
  728. package/dist/transfer/export-sqlite.js +12 -0
  729. package/dist/transfer/export-sqlite.js.map +1 -0
  730. package/dist/transfer/fs-utils.d.ts +61 -0
  731. package/dist/transfer/fs-utils.js +40 -0
  732. package/dist/transfer/fs-utils.js.map +1 -0
  733. package/dist/transfer/import-json.d.ts +16 -0
  734. package/dist/transfer/import-json.js +13 -0
  735. package/dist/transfer/import-json.js.map +1 -0
  736. package/dist/transfer/import-md.d.ts +14 -0
  737. package/dist/transfer/import-md.js +11 -0
  738. package/dist/transfer/import-md.js.map +1 -0
  739. package/dist/transfer/import-sqlite.d.ts +14 -0
  740. package/dist/transfer/import-sqlite.js +12 -0
  741. package/dist/transfer/import-sqlite.js.map +1 -0
  742. package/dist/transfer/sqlite-schema.d.ts +4 -0
  743. package/dist/transfer/sqlite-schema.js +10 -0
  744. package/dist/transfer/sqlite-schema.js.map +1 -0
  745. package/dist/transfer/types.d.ts +916 -0
  746. package/dist/transfer/types.js +30 -0
  747. package/dist/transfer/types.js.map +1 -0
  748. package/dist/trust-zones.d.ts +3 -2
  749. package/dist/trust-zones.js +1 -1
  750. package/dist/types.d.ts +88 -3
  751. package/dist/types.js +1 -1
  752. package/dist/user-model.d.ts +37 -0
  753. package/dist/user-model.js +28 -0
  754. package/dist/user-model.js.map +1 -0
  755. package/dist/utility-runtime.d.ts +1 -1
  756. package/dist/verified-recall.js +11 -8
  757. package/dist/work/board.d.ts +43 -0
  758. package/dist/work/board.js +14 -0
  759. package/dist/work/board.js.map +1 -0
  760. package/dist/work/boundary.d.ts +8 -0
  761. package/dist/work/boundary.js +14 -0
  762. package/dist/work/boundary.js.map +1 -0
  763. package/dist/work/storage.d.ts +39 -0
  764. package/dist/work/storage.js +11 -0
  765. package/dist/work/storage.js.map +1 -0
  766. package/dist/work/types.d.ts +75 -0
  767. package/dist/work/types.js +1 -0
  768. package/dist/work/types.js.map +1 -0
  769. package/package.json +2767 -6
  770. package/scripts/faiss_index.py +816 -0
  771. package/scripts/faiss_requirements.txt +3 -0
  772. package/skills/remnic-entities/SKILL.md +51 -0
  773. package/skills/remnic-memory-workflow/SKILL.md +61 -0
  774. package/skills/remnic-recall/SKILL.md +51 -0
  775. package/skills/remnic-remember/SKILL.md +56 -0
  776. package/skills/remnic-search/SKILL.md +51 -0
  777. package/skills/remnic-status/SKILL.md +51 -0
  778. package/src/abort-error.test.ts +49 -0
  779. package/src/abort-error.ts +46 -0
  780. package/src/abstraction-nodes.ts +162 -0
  781. package/src/access-audit.test.ts +178 -0
  782. package/src/access-audit.ts +125 -0
  783. package/src/access-cli.test.ts +439 -0
  784. package/src/access-cli.ts +438 -0
  785. package/src/access-http.test.ts +225 -0
  786. package/src/access-http.ts +1899 -0
  787. package/src/access-idempotency.ts +232 -0
  788. package/src/access-mcp.test.ts +568 -0
  789. package/src/access-mcp.ts +3056 -0
  790. package/src/access-schema-pi.test.ts +60 -0
  791. package/src/access-schema.ts +522 -0
  792. package/src/access-service-namespace.test.ts +123 -0
  793. package/src/access-service.ts +5629 -0
  794. package/src/action-confidence.test.ts +206 -0
  795. package/src/action-confidence.ts +466 -0
  796. package/src/active-memory-bridge.test.ts +285 -0
  797. package/src/active-memory-bridge.ts +217 -0
  798. package/src/active-recall.test.ts +484 -0
  799. package/src/active-recall.ts +459 -0
  800. package/src/adapters/claude-code.ts +56 -0
  801. package/src/adapters/codex.ts +57 -0
  802. package/src/adapters/hermes.ts +64 -0
  803. package/src/adapters/index.ts +6 -0
  804. package/src/adapters/registry.ts +41 -0
  805. package/src/adapters/replit.ts +55 -0
  806. package/src/adapters/types.ts +51 -0
  807. package/src/behavior-learner.ts +144 -0
  808. package/src/behavior-signals.ts +73 -0
  809. package/src/binary-lifecycle/backend.ts +117 -0
  810. package/src/binary-lifecycle/index.ts +35 -0
  811. package/src/binary-lifecycle/manifest.ts +79 -0
  812. package/src/binary-lifecycle/pipeline.ts +352 -0
  813. package/src/binary-lifecycle/scanner.ts +89 -0
  814. package/src/binary-lifecycle/types.ts +89 -0
  815. package/src/bootstrap.ts +178 -0
  816. package/src/boxes.ts +521 -0
  817. package/src/briefing.test.ts +1535 -0
  818. package/src/briefing.ts +1382 -0
  819. package/src/buffer-session.test.ts +443 -0
  820. package/src/buffer-surprise-report.ts +176 -0
  821. package/src/buffer-surprise-telemetry.test.ts +606 -0
  822. package/src/buffer-surprise-trigger.test.ts +766 -0
  823. package/src/buffer-surprise.test.ts +339 -0
  824. package/src/buffer-surprise.ts +203 -0
  825. package/src/buffer.ts +900 -0
  826. package/src/bulk-import/cli-command.test.ts +204 -0
  827. package/src/bulk-import/index.ts +34 -0
  828. package/src/bulk-import/pipeline.test.ts +445 -0
  829. package/src/bulk-import/pipeline.ts +178 -0
  830. package/src/bulk-import/registry.test.ts +151 -0
  831. package/src/bulk-import/registry.ts +72 -0
  832. package/src/bulk-import/types.test.ts +272 -0
  833. package/src/bulk-import/types.ts +145 -0
  834. package/src/calibration.ts +394 -0
  835. package/src/capsule-cli.test.ts +398 -0
  836. package/src/capsule-cli.ts +565 -0
  837. package/src/causal-behavior.ts +308 -0
  838. package/src/causal-chain.ts +419 -0
  839. package/src/causal-consolidation.ts +370 -0
  840. package/src/causal-retrieval.ts +286 -0
  841. package/src/causal-trajectory-graph.ts +60 -0
  842. package/src/causal-trajectory.ts +303 -0
  843. package/src/chunking.ts +220 -0
  844. package/src/citations.ts +232 -0
  845. package/src/cli.ts +9403 -0
  846. package/src/codex-cli-fallback.ts +162 -0
  847. package/src/codex-thread-key.ts +1 -0
  848. package/src/coding/access-coding-context.test.ts +197 -0
  849. package/src/coding/coding-branch-scope.test.ts +281 -0
  850. package/src/coding/coding-namespace.test.ts +360 -0
  851. package/src/coding/coding-namespace.ts +412 -0
  852. package/src/coding/coding-orchestrator.test.ts +249 -0
  853. package/src/coding/git-context.test.ts +507 -0
  854. package/src/coding/git-context.ts +336 -0
  855. package/src/coding/mcp-set-coding-context.test.ts +174 -0
  856. package/src/coding/review-context.test.ts +316 -0
  857. package/src/coding/review-context.ts +349 -0
  858. package/src/coding/wire-coding-context.test.ts +468 -0
  859. package/src/commitment-ledger.test.ts +78 -0
  860. package/src/commitment-ledger.ts +337 -0
  861. package/src/compat/checks.test.ts +206 -0
  862. package/src/compat/checks.ts +716 -0
  863. package/src/compat/types.ts +33 -0
  864. package/src/compounding/engine.ts +1686 -0
  865. package/src/compounding/preference-consolidator.ts +778 -0
  866. package/src/compression-optimizer.ts +312 -0
  867. package/src/config.test.ts +930 -0
  868. package/src/config.ts +3807 -0
  869. package/src/connectors/codex/instructions.md +160 -0
  870. package/src/connectors/codex/resources/namespace-cheatsheet.md +48 -0
  871. package/src/connectors/codex-marketplace.ts +500 -0
  872. package/src/connectors/codex-materialize-runner.ts +212 -0
  873. package/src/connectors/codex-materialize.ts +983 -0
  874. package/src/connectors/coerce.ts +62 -0
  875. package/src/connectors/index.test.ts +1570 -0
  876. package/src/connectors/index.ts +3222 -0
  877. package/src/connectors/live/framework.ts +164 -0
  878. package/src/connectors/live/github.test.ts +1218 -0
  879. package/src/connectors/live/github.ts +1068 -0
  880. package/src/connectors/live/gmail.test.ts +1706 -0
  881. package/src/connectors/live/gmail.ts +1293 -0
  882. package/src/connectors/live/google-drive.test.ts +696 -0
  883. package/src/connectors/live/google-drive.ts +724 -0
  884. package/src/connectors/live/index.ts +101 -0
  885. package/src/connectors/live/live-connectors.test.ts +689 -0
  886. package/src/connectors/live/notion.test.ts +1109 -0
  887. package/src/connectors/live/notion.ts +978 -0
  888. package/src/connectors/live/registry.ts +103 -0
  889. package/src/connectors/live/state-store.ts +399 -0
  890. package/src/connectors/live/transient-errors.ts +150 -0
  891. package/src/connectors/weclone-installer.test.ts +850 -0
  892. package/src/connectors-cli.ts +513 -0
  893. package/src/console/state.test.ts +224 -0
  894. package/src/console/state.ts +514 -0
  895. package/src/console/trace.test.ts +813 -0
  896. package/src/console/trace.ts +603 -0
  897. package/src/console/tui.test.ts +582 -0
  898. package/src/console/tui.ts +508 -0
  899. package/src/consolidation-operator.ts +182 -0
  900. package/src/consolidation-provenance-check.ts +551 -0
  901. package/src/consolidation-undo.ts +718 -0
  902. package/src/contradiction/contradiction-judge.test.ts +189 -0
  903. package/src/contradiction/contradiction-judge.ts +333 -0
  904. package/src/contradiction/contradiction-review.ts +574 -0
  905. package/src/contradiction/contradiction-scan.ts +504 -0
  906. package/src/contradiction/contradiction.test.ts +2230 -0
  907. package/src/contradiction/index.ts +37 -0
  908. package/src/contradiction/resolution.ts +383 -0
  909. package/src/conversation-index/backend.ts +323 -0
  910. package/src/conversation-index/chunker.ts +47 -0
  911. package/src/conversation-index/cleanup.ts +53 -0
  912. package/src/conversation-index/faiss-adapter.ts +384 -0
  913. package/src/conversation-index/indexer.test.ts +164 -0
  914. package/src/conversation-index/indexer.ts +192 -0
  915. package/src/conversation-index/search.ts +37 -0
  916. package/src/cross-namespace-budget.test.ts +275 -0
  917. package/src/cross-namespace-budget.ts +365 -0
  918. package/src/cue-anchors.ts +163 -0
  919. package/src/curation/index.ts +544 -0
  920. package/src/dashboard-runtime.ts +337 -0
  921. package/src/day-summary.ts +122 -0
  922. package/src/dedup/index.ts +330 -0
  923. package/src/dedup/semantic.test.ts +1577 -0
  924. package/src/dedup/semantic.ts +148 -0
  925. package/src/delinearize.ts +193 -0
  926. package/src/direct-answer-wiring.test.ts +473 -0
  927. package/src/direct-answer-wiring.ts +180 -0
  928. package/src/direct-answer.test.ts +484 -0
  929. package/src/direct-answer.ts +273 -0
  930. package/src/embedding-fallback.ts +565 -0
  931. package/src/enrichment/audit.ts +89 -0
  932. package/src/enrichment/index.ts +27 -0
  933. package/src/enrichment/pipeline.ts +197 -0
  934. package/src/enrichment/provider-registry.ts +85 -0
  935. package/src/enrichment/types.ts +100 -0
  936. package/src/enrichment/web-search-provider.ts +63 -0
  937. package/src/entity-retrieval.ts +774 -0
  938. package/src/entity-schema.ts +239 -0
  939. package/src/evals.ts +1312 -0
  940. package/src/event-order-recall.test.ts +4164 -0
  941. package/src/event-order-recall.ts +2802 -0
  942. package/src/evidence-pack.test.ts +89 -0
  943. package/src/evidence-pack.ts +388 -0
  944. package/src/explicit-capture.ts +530 -0
  945. package/src/explicit-cue-recall.test.ts +3019 -0
  946. package/src/explicit-cue-recall.ts +5545 -0
  947. package/src/extraction-judge-telemetry.ts +234 -0
  948. package/src/extraction-judge-training.ts +221 -0
  949. package/src/extraction-judge.ts +846 -0
  950. package/src/extraction-timeout.test.ts +265 -0
  951. package/src/extraction.ts +2719 -0
  952. package/src/fallback-llm.test.ts +1060 -0
  953. package/src/fallback-llm.ts +918 -0
  954. package/src/focused-list-recall.test.ts +734 -0
  955. package/src/focused-list-recall.ts +1160 -0
  956. package/src/graph-dashboard-diff.ts +35 -0
  957. package/src/graph-dashboard-key.ts +5 -0
  958. package/src/graph-dashboard-parser.ts +104 -0
  959. package/src/graph-edge-reinforcement.ts +192 -0
  960. package/src/graph-events.ts +151 -0
  961. package/src/graph-recall.test.ts +164 -0
  962. package/src/graph-recall.ts +189 -0
  963. package/src/graph-retrieval.test.ts +809 -0
  964. package/src/graph-retrieval.ts +823 -0
  965. package/src/graph-snapshot.ts +329 -0
  966. package/src/graph.ts +813 -0
  967. package/src/harmonic-retrieval.ts +223 -0
  968. package/src/himem.ts +154 -0
  969. package/src/hygiene.ts +87 -0
  970. package/src/identity-continuity.ts +333 -0
  971. package/src/importance.ts +328 -0
  972. package/src/importers/base.test.ts +294 -0
  973. package/src/importers/base.ts +436 -0
  974. package/src/importers/index.ts +21 -0
  975. package/src/index.ts +1204 -0
  976. package/src/intent.ts +154 -0
  977. package/src/json-extract.ts +85 -0
  978. package/src/json-store.ts +42 -0
  979. package/src/lcm/archive.ts +617 -0
  980. package/src/lcm/dag.ts +199 -0
  981. package/src/lcm/engine.ts +645 -0
  982. package/src/lcm/index.ts +7 -0
  983. package/src/lcm/queue.test.ts +178 -0
  984. package/src/lcm/queue.ts +200 -0
  985. package/src/lcm/recall.ts +117 -0
  986. package/src/lcm/schema.ts +154 -0
  987. package/src/lcm/summarizer.ts +235 -0
  988. package/src/lcm/tools.ts +191 -0
  989. package/src/lcm-engine.test.ts +660 -0
  990. package/src/legacy-hook-compat.test.ts +20 -0
  991. package/src/legacy-hook-compat.ts +45 -0
  992. package/src/lifecycle.ts +289 -0
  993. package/src/live-connectors-runner.ts +385 -0
  994. package/src/local-llm-qos.test.ts +303 -0
  995. package/src/local-llm-thinking.test.ts +292 -0
  996. package/src/local-llm.ts +1464 -0
  997. package/src/logger.ts +49 -0
  998. package/src/maintenance/archive-observations.ts +147 -0
  999. package/src/maintenance/backup-stamp.ts +3 -0
  1000. package/src/maintenance/dreams-ledger.ts +516 -0
  1001. package/src/maintenance/first-start-migration.ts +362 -0
  1002. package/src/maintenance/forget.test.ts +206 -0
  1003. package/src/maintenance/forget.ts +126 -0
  1004. package/src/maintenance/graph-edge-decay.test.ts +409 -0
  1005. package/src/maintenance/graph-edge-decay.ts +394 -0
  1006. package/src/maintenance/memory-governance-cron.ts +447 -0
  1007. package/src/maintenance/memory-governance.ts +1039 -0
  1008. package/src/maintenance/migrate-observations.ts +216 -0
  1009. package/src/maintenance/observation-ledger-utils.ts +54 -0
  1010. package/src/maintenance/pattern-reinforcement.test.ts +875 -0
  1011. package/src/maintenance/pattern-reinforcement.ts +369 -0
  1012. package/src/maintenance/purge.ts +334 -0
  1013. package/src/maintenance/rebuild-memory-lifecycle-ledger.ts +78 -0
  1014. package/src/maintenance/rebuild-memory-projection.ts +1234 -0
  1015. package/src/maintenance/rebuild-observations.ts +178 -0
  1016. package/src/maintenance/tier-stats.test.ts +378 -0
  1017. package/src/maintenance/tier-stats.ts +222 -0
  1018. package/src/mcp-memory-inspector-app.ts +421 -0
  1019. package/src/memory-action-policy.ts +80 -0
  1020. package/src/memory-cache.ts +208 -0
  1021. package/src/memory-extension/claude-code-publisher.ts +51 -0
  1022. package/src/memory-extension/codex-publisher.ts +149 -0
  1023. package/src/memory-extension/hermes-publisher.ts +51 -0
  1024. package/src/memory-extension/index.ts +100 -0
  1025. package/src/memory-extension/shared-instructions.ts +133 -0
  1026. package/src/memory-extension/types.ts +86 -0
  1027. package/src/memory-extension-host/host-discovery.ts +276 -0
  1028. package/src/memory-extension-host/index.ts +14 -0
  1029. package/src/memory-extension-host/render-extensions-block.ts +73 -0
  1030. package/src/memory-extension-host/types.ts +21 -0
  1031. package/src/memory-lifecycle-ledger-utils.ts +116 -0
  1032. package/src/memory-projection-format.ts +11 -0
  1033. package/src/memory-projection-store.ts +951 -0
  1034. package/src/memory-provenance.test.ts +196 -0
  1035. package/src/memory-provenance.ts +484 -0
  1036. package/src/memory-worth-bench.test.ts +71 -0
  1037. package/src/memory-worth-bench.ts +265 -0
  1038. package/src/memory-worth-filter.test.ts +209 -0
  1039. package/src/memory-worth-filter.ts +204 -0
  1040. package/src/memory-worth-frontmatter.test.ts +311 -0
  1041. package/src/memory-worth-outcomes.test.ts +316 -0
  1042. package/src/memory-worth-outcomes.ts +286 -0
  1043. package/src/memory-worth.test.ts +317 -0
  1044. package/src/memory-worth.ts +215 -0
  1045. package/src/message-parts/index.ts +806 -0
  1046. package/src/message-parts/message-parts.test.ts +421 -0
  1047. package/src/migrate/from-engram.ts +789 -0
  1048. package/src/model-registry.ts +313 -0
  1049. package/src/models-json.ts +76 -0
  1050. package/src/namespaces/migrate.ts +187 -0
  1051. package/src/namespaces/path.ts +25 -0
  1052. package/src/namespaces/principal.test.ts +195 -0
  1053. package/src/namespaces/principal.ts +86 -0
  1054. package/src/namespaces/search.test.ts +105 -0
  1055. package/src/namespaces/search.ts +233 -0
  1056. package/src/namespaces/storage.ts +74 -0
  1057. package/src/native-knowledge.ts +1823 -0
  1058. package/src/negative.ts +72 -0
  1059. package/src/network/tailscale.ts +179 -0
  1060. package/src/network/webdav.ts +385 -0
  1061. package/src/objective-state-writers.ts +951 -0
  1062. package/src/objective-state.ts +320 -0
  1063. package/src/onboarding/index.ts +529 -0
  1064. package/src/openai-chat-compat.ts +56 -0
  1065. package/src/operator-toolkit.ts +2132 -0
  1066. package/src/opik-exporter.test.ts +72 -0
  1067. package/src/opik-exporter.ts +587 -0
  1068. package/src/orchestrator-extraction-queue.test.ts +197 -0
  1069. package/src/orchestrator-flush.test.ts +1171 -0
  1070. package/src/orchestrator-pattern-reinforcement.test.ts +128 -0
  1071. package/src/orchestrator-source-attribution.test.ts +701 -0
  1072. package/src/orchestrator.ts +16368 -0
  1073. package/src/page-versioning.ts +450 -0
  1074. package/src/patterns-cli.ts +574 -0
  1075. package/src/peers/index.ts +54 -0
  1076. package/src/peers/migrate-from-identity-anchor.test.ts +291 -0
  1077. package/src/peers/migrate-from-identity-anchor.ts +350 -0
  1078. package/src/peers/peers.test.ts +419 -0
  1079. package/src/peers/profile-reasoner.ts +694 -0
  1080. package/src/peers/storage.ts +1350 -0
  1081. package/src/peers/types.ts +138 -0
  1082. package/src/plugin-id.ts +84 -0
  1083. package/src/policy-runtime.ts +209 -0
  1084. package/src/procedural/procedure-miner.ts +150 -0
  1085. package/src/procedural/procedure-recall.ts +93 -0
  1086. package/src/procedural/procedure-stats.ts +213 -0
  1087. package/src/procedural/procedure-types.ts +132 -0
  1088. package/src/procedural/reinforcement-core.test.ts +132 -0
  1089. package/src/procedural/reinforcement-core.ts +73 -0
  1090. package/src/profiling.test.ts +263 -0
  1091. package/src/profiling.ts +435 -0
  1092. package/src/projection/index.ts +398 -0
  1093. package/src/qmd-recall-cache.test.ts +138 -0
  1094. package/src/qmd-recall-cache.ts +111 -0
  1095. package/src/qmd.test.ts +257 -0
  1096. package/src/qmd.ts +2614 -0
  1097. package/src/reasoning-trace-recall.ts +201 -0
  1098. package/src/reasoning-trace-types.ts +235 -0
  1099. package/src/recall-audit-anomaly.test.ts +246 -0
  1100. package/src/recall-audit-anomaly.ts +297 -0
  1101. package/src/recall-audit.test.ts +51 -0
  1102. package/src/recall-audit.ts +72 -0
  1103. package/src/recall-budget-config.test.ts +87 -0
  1104. package/src/recall-disclosure-escalation.test.ts +196 -0
  1105. package/src/recall-disclosure-escalation.ts +158 -0
  1106. package/src/recall-disclosure-shaping.test.ts +146 -0
  1107. package/src/recall-disclosure.test.ts +214 -0
  1108. package/src/recall-explain-renderer.test.ts +140 -0
  1109. package/src/recall-explain-renderer.ts +356 -0
  1110. package/src/recall-mmr.test.ts +808 -0
  1111. package/src/recall-mmr.ts +607 -0
  1112. package/src/recall-qos.test.ts +85 -0
  1113. package/src/recall-qos.ts +82 -0
  1114. package/src/recall-query-policy.ts +221 -0
  1115. package/src/recall-state.test.ts +233 -0
  1116. package/src/recall-state.ts +456 -0
  1117. package/src/recall-tag-filter.ts +143 -0
  1118. package/src/recall-tokenization.ts +35 -0
  1119. package/src/recall-xray-cli.test.ts +118 -0
  1120. package/src/recall-xray-cli.ts +100 -0
  1121. package/src/recall-xray-disclosure-telemetry.test.ts +183 -0
  1122. package/src/recall-xray-renderer.test.ts +539 -0
  1123. package/src/recall-xray-renderer.ts +487 -0
  1124. package/src/recall-xray.test.ts +503 -0
  1125. package/src/recall-xray.ts +621 -0
  1126. package/src/reconstruct.ts +41 -0
  1127. package/src/release-changelog.ts +35 -0
  1128. package/src/relevance.ts +67 -0
  1129. package/src/replay/normalizers/chatgpt.ts +133 -0
  1130. package/src/replay/normalizers/claude.ts +102 -0
  1131. package/src/replay/normalizers/openclaw.ts +119 -0
  1132. package/src/replay/normalizers/shared.ts +69 -0
  1133. package/src/replay/runner.ts +197 -0
  1134. package/src/replay/types.ts +143 -0
  1135. package/src/rerank.test.ts +48 -0
  1136. package/src/rerank.ts +176 -0
  1137. package/src/resolve-auth-token.test.ts +226 -0
  1138. package/src/resolve-auth-token.ts +151 -0
  1139. package/src/resolve-provider-secret.test.ts +187 -0
  1140. package/src/resolve-provider-secret.ts +410 -0
  1141. package/src/response-guidance-recall.test.ts +3952 -0
  1142. package/src/response-guidance-recall.ts +4431 -0
  1143. package/src/resume-bundles.ts +415 -0
  1144. package/src/retrieval-agents.ts +623 -0
  1145. package/src/retrieval-tiers.ts +25 -0
  1146. package/src/retrieval.ts +104 -0
  1147. package/src/review/index.test.ts +201 -0
  1148. package/src/review/index.ts +536 -0
  1149. package/src/routing/engine.ts +162 -0
  1150. package/src/routing/store.ts +321 -0
  1151. package/src/runtime/better-sqlite.test.ts +32 -0
  1152. package/src/runtime/better-sqlite.ts +76 -0
  1153. package/src/runtime/child-process.ts +67 -0
  1154. package/src/runtime/env.ts +48 -0
  1155. package/src/sanitize.ts +58 -0
  1156. package/src/schemas.ts +449 -0
  1157. package/src/sdk-compat.ts +87 -0
  1158. package/src/search/document-scanner.ts +96 -0
  1159. package/src/search/embed-helper.ts +142 -0
  1160. package/src/search/factory.ts +189 -0
  1161. package/src/search/index.ts +10 -0
  1162. package/src/search/lancedb-backend.ts +342 -0
  1163. package/src/search/meilisearch-backend.ts +232 -0
  1164. package/src/search/noop-backend.ts +57 -0
  1165. package/src/search/orama-backend.ts +358 -0
  1166. package/src/search/port.ts +86 -0
  1167. package/src/search/remote-backend.ts +124 -0
  1168. package/src/secure-store/cipher.ts +271 -0
  1169. package/src/secure-store/cli-handlers.ts +355 -0
  1170. package/src/secure-store/cli-renderer.ts +131 -0
  1171. package/src/secure-store/header.ts +373 -0
  1172. package/src/secure-store/index.ts +137 -0
  1173. package/src/secure-store/kdf.ts +263 -0
  1174. package/src/secure-store/keyring.ts +106 -0
  1175. package/src/secure-store/metadata.ts +394 -0
  1176. package/src/secure-store/passphrase-reader.ts +252 -0
  1177. package/src/secure-store/secure-fs.ts +571 -0
  1178. package/src/secure-store/secure-store.test.ts +755 -0
  1179. package/src/semantic-chunking.ts +545 -0
  1180. package/src/semantic-consolidation.test.ts +182 -0
  1181. package/src/semantic-consolidation.ts +432 -0
  1182. package/src/semantic-rule-promotion.ts +183 -0
  1183. package/src/semantic-rule-verifier.ts +160 -0
  1184. package/src/session-integrity.ts +569 -0
  1185. package/src/session-observer-bands.ts +11 -0
  1186. package/src/session-observer-state.ts +346 -0
  1187. package/src/session-toggles.test.ts +96 -0
  1188. package/src/session-toggles.ts +159 -0
  1189. package/src/shared-context/manager.ts +810 -0
  1190. package/src/signal.ts +84 -0
  1191. package/src/skills-registry.test.ts +277 -0
  1192. package/src/skills-registry.ts +120 -0
  1193. package/src/source-attribution-roundtrip.test.ts +215 -0
  1194. package/src/source-attribution.test.ts +1425 -0
  1195. package/src/source-attribution.ts +639 -0
  1196. package/src/spaces/index.ts +627 -0
  1197. package/src/storage-paths.ts +117 -0
  1198. package/src/storage.ts +6657 -0
  1199. package/src/store-contract.ts +55 -0
  1200. package/src/summarizer.ts +844 -0
  1201. package/src/summary-snapshot.test.ts +681 -0
  1202. package/src/summary-snapshot.ts +238 -0
  1203. package/src/surfaces/dreams.test.ts +394 -0
  1204. package/src/surfaces/dreams.ts +346 -0
  1205. package/src/surfaces/heartbeat.test.ts +415 -0
  1206. package/src/surfaces/heartbeat.ts +325 -0
  1207. package/src/sync/index.ts +308 -0
  1208. package/src/targeted-fact-recall.test.ts +1694 -0
  1209. package/src/targeted-fact-recall.ts +2905 -0
  1210. package/src/taxonomy/default-taxonomy.ts +87 -0
  1211. package/src/taxonomy/index.ts +26 -0
  1212. package/src/taxonomy/resolver-doc-generator.ts +57 -0
  1213. package/src/taxonomy/resolver.ts +184 -0
  1214. package/src/taxonomy/taxonomy-loader.ts +186 -0
  1215. package/src/taxonomy/types.ts +48 -0
  1216. package/src/telemetry-transcript.ts +70 -0
  1217. package/src/temporal-index.ts +890 -0
  1218. package/src/temporal-supersession.test.ts +2703 -0
  1219. package/src/temporal-supersession.ts +493 -0
  1220. package/src/temporal-validity.test.ts +448 -0
  1221. package/src/temporal-validity.ts +123 -0
  1222. package/src/threading.ts +395 -0
  1223. package/src/tier-migration.ts +124 -0
  1224. package/src/tier-routing.ts +102 -0
  1225. package/src/tmt.ts +462 -0
  1226. package/src/tokens.test.ts +178 -0
  1227. package/src/tokens.ts +279 -0
  1228. package/src/topics.ts +147 -0
  1229. package/src/training-export/cli-date-validation.test.ts +258 -0
  1230. package/src/training-export/converter.test.ts +452 -0
  1231. package/src/training-export/converter.ts +319 -0
  1232. package/src/training-export/date-parse.ts +117 -0
  1233. package/src/training-export/index.ts +26 -0
  1234. package/src/training-export/registry.test.ts +85 -0
  1235. package/src/training-export/registry.ts +57 -0
  1236. package/src/training-export/types.ts +31 -0
  1237. package/src/transcript.ts +1179 -0
  1238. package/src/transfer/autodetect.ts +30 -0
  1239. package/src/transfer/backup.ts +138 -0
  1240. package/src/transfer/capsule-crypto.ts +485 -0
  1241. package/src/transfer/capsule-encrypt.test.ts +690 -0
  1242. package/src/transfer/capsule-export.ts +543 -0
  1243. package/src/transfer/capsule-fork.ts +375 -0
  1244. package/src/transfer/capsule-import.ts +564 -0
  1245. package/src/transfer/capsule-merge.ts +433 -0
  1246. package/src/transfer/conflict-policy.ts +16 -0
  1247. package/src/transfer/constants.ts +13 -0
  1248. package/src/transfer/exclusions.ts +37 -0
  1249. package/src/transfer/export-json.ts +65 -0
  1250. package/src/transfer/export-md.ts +59 -0
  1251. package/src/transfer/export-sqlite.ts +52 -0
  1252. package/src/transfer/fs-utils.ts +269 -0
  1253. package/src/transfer/import-json.ts +108 -0
  1254. package/src/transfer/import-md.ts +84 -0
  1255. package/src/transfer/import-sqlite.ts +100 -0
  1256. package/src/transfer/integrity.ts +71 -0
  1257. package/src/transfer/sqlite-schema.ts +16 -0
  1258. package/src/transfer/types.ts +297 -0
  1259. package/src/trust-zones.ts +1186 -0
  1260. package/src/types.ts +3074 -0
  1261. package/src/user-model.test.ts +124 -0
  1262. package/src/user-model.ts +162 -0
  1263. package/src/utility-learner.ts +353 -0
  1264. package/src/utility-runtime.ts +88 -0
  1265. package/src/utility-telemetry.ts +215 -0
  1266. package/src/utils/category-dir.ts +44 -0
  1267. package/src/utils/errno.ts +6 -0
  1268. package/src/utils/iso-timestamp.test.ts +37 -0
  1269. package/src/utils/iso-timestamp.ts +164 -0
  1270. package/src/utils/path.ts +26 -0
  1271. package/src/verified-recall.ts +138 -0
  1272. package/src/version-utils.test.ts +10 -0
  1273. package/src/version-utils.ts +9 -0
  1274. package/src/whitespace.ts +10 -0
  1275. package/src/work/board.ts +359 -0
  1276. package/src/work/boundary.ts +107 -0
  1277. package/src/work/storage.ts +436 -0
  1278. package/src/work/types.ts +82 -0
  1279. package/src/work-product-ledger.ts +265 -0
  1280. package/dist/access-service-BkXt3di1.d.ts +0 -2039
  1281. package/dist/capsule-crypto-SJS5VVAP.js +0 -18
  1282. package/dist/capsule-export-LLEVB2RG.js +0 -17
  1283. package/dist/capsule-import-UW45R2MZ.js +0 -16
  1284. package/dist/capsule-merge-DI7PNQ2H.js +0 -189
  1285. package/dist/chunk-2LGMW3DJ.js +0 -111
  1286. package/dist/chunk-2YMTO4ZJ.js +0 -265
  1287. package/dist/chunk-2YMTO4ZJ.js.map +0 -1
  1288. package/dist/chunk-363MWCD3.js +0 -9683
  1289. package/dist/chunk-363MWCD3.js.map +0 -1
  1290. package/dist/chunk-36CTNQY7.js +0 -1554
  1291. package/dist/chunk-36CTNQY7.js.map +0 -1
  1292. package/dist/chunk-457A4P3L.js +0 -119
  1293. package/dist/chunk-457A4P3L.js.map +0 -1
  1294. package/dist/chunk-4DXC6HQQ.js +0 -1837
  1295. package/dist/chunk-4DXC6HQQ.js.map +0 -1
  1296. package/dist/chunk-4IS4SXIQ.js +0 -2040
  1297. package/dist/chunk-57QNCUEZ.js +0 -1914
  1298. package/dist/chunk-57QNCUEZ.js.map +0 -1
  1299. package/dist/chunk-6AUUAZEX.js +0 -150
  1300. package/dist/chunk-6AUUAZEX.js.map +0 -1
  1301. package/dist/chunk-6TBWYBJ3.js +0 -236
  1302. package/dist/chunk-6XA7UN4Z.js +0 -135
  1303. package/dist/chunk-6Z6UH6TK.js +0 -2129
  1304. package/dist/chunk-6Z6UH6TK.js.map +0 -1
  1305. package/dist/chunk-74EMIVE4.js +0 -329
  1306. package/dist/chunk-74EMIVE4.js.map +0 -1
  1307. package/dist/chunk-74WWN7ZW.js +0 -82
  1308. package/dist/chunk-74WWN7ZW.js.map +0 -1
  1309. package/dist/chunk-767ODGE6.js +0 -183
  1310. package/dist/chunk-A4ACKWIW.js +0 -289
  1311. package/dist/chunk-A4ACKWIW.js.map +0 -1
  1312. package/dist/chunk-ASAITVLA.js +0 -64
  1313. package/dist/chunk-ASAITVLA.js.map +0 -1
  1314. package/dist/chunk-C5HUWVH2.js +0 -891
  1315. package/dist/chunk-C5HUWVH2.js.map +0 -1
  1316. package/dist/chunk-D54LZC5L.js +0 -147
  1317. package/dist/chunk-DF3RVK3X.js +0 -119
  1318. package/dist/chunk-DF3RVK3X.js.map +0 -1
  1319. package/dist/chunk-E6K4NIEU.js +0 -747
  1320. package/dist/chunk-E6K4NIEU.js.map +0 -1
  1321. package/dist/chunk-EEQLFRUM.js +0 -89
  1322. package/dist/chunk-EQINRHYR.js +0 -672
  1323. package/dist/chunk-EQINRHYR.js.map +0 -1
  1324. package/dist/chunk-ETOW6ACV.js +0 -158
  1325. package/dist/chunk-ETOW6ACV.js.map +0 -1
  1326. package/dist/chunk-EYNQTST2.js +0 -721
  1327. package/dist/chunk-FYIYMQ5N.js +0 -221
  1328. package/dist/chunk-FYIYMQ5N.js.map +0 -1
  1329. package/dist/chunk-G2WADRQ3.js +0 -219
  1330. package/dist/chunk-G4SK7DSQ.js +0 -121
  1331. package/dist/chunk-GGD5W7TB.js +0 -105
  1332. package/dist/chunk-GGD5W7TB.js.map +0 -1
  1333. package/dist/chunk-GVPWB7EY.js +0 -390
  1334. package/dist/chunk-GVPWB7EY.js.map +0 -1
  1335. package/dist/chunk-HJYHRE4S.js +0 -647
  1336. package/dist/chunk-I6BQZSML.js +0 -1451
  1337. package/dist/chunk-I6BQZSML.js.map +0 -1
  1338. package/dist/chunk-IBX3VFOM.js +0 -446
  1339. package/dist/chunk-IBX3VFOM.js.map +0 -1
  1340. package/dist/chunk-IXEJRKCZ.js +0 -18
  1341. package/dist/chunk-JBMSGZEQ.js +0 -441
  1342. package/dist/chunk-JBMSGZEQ.js.map +0 -1
  1343. package/dist/chunk-JRNQ3RNA.js +0 -284
  1344. package/dist/chunk-JRNQ3RNA.js.map +0 -1
  1345. package/dist/chunk-K6WK37A6.js +0 -865
  1346. package/dist/chunk-K6WK37A6.js.map +0 -1
  1347. package/dist/chunk-KBYWQWSB.js +0 -271
  1348. package/dist/chunk-KUHRUM6B.js +0 -14397
  1349. package/dist/chunk-KUHRUM6B.js.map +0 -1
  1350. package/dist/chunk-KWBPHZUU.js +0 -83
  1351. package/dist/chunk-KWBPHZUU.js.map +0 -1
  1352. package/dist/chunk-LIO5X3CM.js +0 -596
  1353. package/dist/chunk-MARWOCVP.js +0 -48
  1354. package/dist/chunk-MCC6KDQF.js +0 -5095
  1355. package/dist/chunk-MCC6KDQF.js.map +0 -1
  1356. package/dist/chunk-N5AKDXAI.js +0 -74
  1357. package/dist/chunk-NN3LPQ5D.js +0 -936
  1358. package/dist/chunk-NN3LPQ5D.js.map +0 -1
  1359. package/dist/chunk-O4XJUPSF.js +0 -533
  1360. package/dist/chunk-O4XJUPSF.js.map +0 -1
  1361. package/dist/chunk-OA3L7BFR.js +0 -183
  1362. package/dist/chunk-OA3L7BFR.js.map +0 -1
  1363. package/dist/chunk-OR64ZGRZ.js +0 -23
  1364. package/dist/chunk-P73JTV34.js +0 -275
  1365. package/dist/chunk-P73JTV34.js.map +0 -1
  1366. package/dist/chunk-P77UEOU2.js +0 -1521
  1367. package/dist/chunk-P77UEOU2.js.map +0 -1
  1368. package/dist/chunk-PB5KW5PL.js +0 -118
  1369. package/dist/chunk-PHNGXFQ6.js +0 -623
  1370. package/dist/chunk-PHNGXFQ6.js.map +0 -1
  1371. package/dist/chunk-QIGOEM65.js +0 -228
  1372. package/dist/chunk-RXTFCYQF.js +0 -108
  1373. package/dist/chunk-S2JJBLJG.js +0 -2101
  1374. package/dist/chunk-S2JJBLJG.js.map +0 -1
  1375. package/dist/chunk-S3IP6R6K.js +0 -219
  1376. package/dist/chunk-S3IP6R6K.js.map +0 -1
  1377. package/dist/chunk-SRBJUAMP.js +0 -403
  1378. package/dist/chunk-SRBJUAMP.js.map +0 -1
  1379. package/dist/chunk-URB2WSKZ.js +0 -350
  1380. package/dist/chunk-URB2WSKZ.js.map +0 -1
  1381. package/dist/chunk-VQXK37XA.js +0 -26
  1382. package/dist/chunk-VQXK37XA.js.map +0 -1
  1383. package/dist/chunk-VTU2B4VF.js +0 -146
  1384. package/dist/chunk-VTU2B4VF.js.map +0 -1
  1385. package/dist/chunk-VX2IUQFE.js +0 -613
  1386. package/dist/chunk-VX2IUQFE.js.map +0 -1
  1387. package/dist/chunk-WGK4VHGP.js +0 -4292
  1388. package/dist/chunk-WGK4VHGP.js.map +0 -1
  1389. package/dist/chunk-WTFWLUSX.js +0 -827
  1390. package/dist/chunk-WTFWLUSX.js.map +0 -1
  1391. package/dist/chunk-XJKFSSDW.js +0 -726
  1392. package/dist/chunk-XJKFSSDW.js.map +0 -1
  1393. package/dist/chunk-XMHBH5H6.js +0 -283
  1394. package/dist/chunk-XMHBH5H6.js.map +0 -1
  1395. package/dist/chunk-XMVFHBHT.js +0 -277
  1396. package/dist/chunk-Y5KDIOKF.js +0 -2403
  1397. package/dist/chunk-Y5KDIOKF.js.map +0 -1
  1398. package/dist/chunk-YNB73F22.js +0 -137
  1399. package/dist/chunk-YNB73F22.js.map +0 -1
  1400. package/dist/chunk-Z2E7VW55.js +0 -335
  1401. package/dist/chunk-Z2E7VW55.js.map +0 -1
  1402. package/dist/chunk-Z5S5HNGY.js +0 -2280
  1403. package/dist/chunk-Z5S5HNGY.js.map +0 -1
  1404. package/dist/chunk-ZL4S7ARC.js +0 -53
  1405. package/dist/chunk-ZTSE2ZJ6.js +0 -190
  1406. package/dist/chunk-ZTSE2ZJ6.js.map +0 -1
  1407. package/dist/cli-Cvy2SNhF.d.ts +0 -1259
  1408. package/dist/codex-materialize-CQlLTzke.d.ts +0 -139
  1409. package/dist/connectors-cli-DFGtY2DB.d.ts +0 -257
  1410. package/dist/contradiction-review-5LTTVDQV.js +0 -22
  1411. package/dist/contradiction-scan-3Z6YW7YA.js +0 -413
  1412. package/dist/contradiction-scan-3Z6YW7YA.js.map +0 -1
  1413. package/dist/engine-FOC3IJLA.js +0 -28
  1414. package/dist/fs-utils-IRVUFB6G.js +0 -30
  1415. package/dist/graph-edge-decay-PWB63GRE.js +0 -207
  1416. package/dist/index-1qIcnbG1.d.ts +0 -34
  1417. package/dist/memory-governance-F3QOJGEY.js +0 -37
  1418. package/dist/memory-projection-store-CY8TU40w.d.ts +0 -222
  1419. package/dist/orchestrator-AOQMo7QI.d.ts +0 -1784
  1420. package/dist/path-RMTY5Y5A.js +0 -9
  1421. package/dist/port-B6VEDIkC.d.ts +0 -53
  1422. package/dist/resolution-YGIBORXI.js +0 -101
  1423. package/dist/resolution-YGIBORXI.js.map +0 -1
  1424. package/dist/secure-store-4R2GSO7S.js +0 -156
  1425. package/dist/semantic-consolidation-ByBXb-sf.d.ts +0 -180
  1426. package/dist/state-store-3EH7HYIN.js +0 -16
  1427. package/dist/types-V3FJ26TF.js +0 -30
  1428. /package/dist/{capsule-crypto-SJS5VVAP.js.map → action-confidence.js.map} +0 -0
  1429. /package/dist/{capsule-export-LLEVB2RG.js.map → adapters/claude-code.js.map} +0 -0
  1430. /package/dist/{capsule-import-UW45R2MZ.js.map → adapters/codex.js.map} +0 -0
  1431. /package/dist/{contradiction-review-5LTTVDQV.js.map → adapters/hermes.js.map} +0 -0
  1432. /package/dist/{engine-FOC3IJLA.js.map → adapters/index.js.map} +0 -0
  1433. /package/dist/{fs-utils-IRVUFB6G.js.map → adapters/registry.js.map} +0 -0
  1434. /package/dist/{memory-governance-F3QOJGEY.js.map → adapters/replit.js.map} +0 -0
  1435. /package/dist/{path-RMTY5Y5A.js.map → adapters/types.js.map} +0 -0
  1436. /package/dist/{secure-store-4R2GSO7S.js.map → capsule-crypto-5CYAGVC5.js.map} +0 -0
  1437. /package/dist/{capsule-merge-DI7PNQ2H.js.map → capsule-merge-4MGKE7C5.js.map} +0 -0
  1438. /package/dist/{chunk-G4SK7DSQ.js.map → chunk-2WWLHTZY.js.map} +0 -0
  1439. /package/dist/{chunk-KBYWQWSB.js.map → chunk-4CRG46BG.js.map} +0 -0
  1440. /package/dist/{chunk-LIO5X3CM.js.map → chunk-7IASACLB.js.map} +0 -0
  1441. /package/dist/{chunk-EYNQTST2.js.map → chunk-EFJ3MQ4V.js.map} +0 -0
  1442. /package/dist/{chunk-D54LZC5L.js.map → chunk-FDU6HUUL.js.map} +0 -0
  1443. /package/dist/{chunk-QIGOEM65.js.map → chunk-GGKRUQOO.js.map} +0 -0
  1444. /package/dist/{chunk-HJYHRE4S.js.map → chunk-GL6I6MEQ.js.map} +0 -0
  1445. /package/dist/{state-store-3EH7HYIN.js.map → chunk-HHLLAQGZ.js.map} +0 -0
  1446. /package/dist/{chunk-4IS4SXIQ.js.map → chunk-HXXBL2KD.js.map} +0 -0
  1447. /package/dist/{chunk-767ODGE6.js.map → chunk-KNKUID7G.js.map} +0 -0
  1448. /package/dist/{chunk-6TBWYBJ3.js.map → chunk-LPMVBPA3.js.map} +0 -0
  1449. /package/dist/{chunk-PB5KW5PL.js.map → chunk-MC26UJIM.js.map} +0 -0
  1450. /package/dist/{chunk-ZL4S7ARC.js.map → chunk-MT4HVDUZ.js.map} +0 -0
  1451. /package/dist/{chunk-G2WADRQ3.js.map → chunk-MY6TPVXW.js.map} +0 -0
  1452. /package/dist/{chunk-OR64ZGRZ.js.map → chunk-NNVTUXEB.js.map} +0 -0
  1453. /package/dist/{chunk-RXTFCYQF.js.map → chunk-P4NEIHUT.js.map} +0 -0
  1454. /package/dist/{chunk-IXEJRKCZ.js.map → chunk-QRNI5JBH.js.map} +0 -0
  1455. /package/dist/{chunk-EEQLFRUM.js.map → chunk-RRF5UOBJ.js.map} +0 -0
  1456. /package/dist/{types-V3FJ26TF.js.map → chunk-SEDEKFYQ.js.map} +0 -0
  1457. /package/dist/{chunk-2LGMW3DJ.js.map → chunk-U3PN77QT.js.map} +0 -0
  1458. /package/dist/{chunk-XMVFHBHT.js.map → chunk-U3WSW6PZ.js.map} +0 -0
  1459. /package/dist/{chunk-N5AKDXAI.js.map → chunk-UWVJF25J.js.map} +0 -0
  1460. /package/dist/{chunk-MARWOCVP.js.map → chunk-XIG5PDM7.js.map} +0 -0
  1461. /package/dist/{chunk-6XA7UN4Z.js.map → chunk-XVZ7B3HG.js.map} +0 -0
  1462. /package/dist/{graph-edge-decay-PWB63GRE.js.map → graph-edge-decay-5DI5GUNL.js.map} +0 -0
@@ -0,0 +1,2230 @@
1
+ import assert from "node:assert/strict";
2
+ import fs from "node:fs";
3
+ import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import test from "node:test";
7
+
8
+ import {
9
+ computePairId,
10
+ writePair,
11
+ writePairs,
12
+ readPair,
13
+ listPairs,
14
+ isCoolingDown,
15
+ memoryHashesChanged,
16
+ computeMemoryContentHash,
17
+ resolvePair,
18
+ deferPair,
19
+ migrateUnscopedPairsToNamespace,
20
+ type ContradictionPair,
21
+ } from "./contradiction-review.js";
22
+ import { _pairKey, _contentHash } from "./contradiction-judge.js";
23
+ import { executeResolution, isValidResolutionVerb } from "./resolution.js";
24
+ import { ACTIVE_STATUSES, runContradictionScan } from "./contradiction-scan.js";
25
+ import { parseConfig } from "../config.js";
26
+ import type { StorageManager } from "../storage.js";
27
+ import type { MemoryCategory, MemoryFile, MemoryFrontmatter } from "../types.js";
28
+
29
+ type FrontmatterLifecycleOptions = Parameters<StorageManager["writeMemoryFrontmatter"]>[2];
30
+
31
+ // ── Helpers ────────────────────────────────────────────────────────────────────
32
+
33
+ async function makeTempDir(prefix = "contradiction-test-"): Promise<{
34
+ dir: string;
35
+ cleanup: () => Promise<void>;
36
+ }> {
37
+ const dir = await mkdtemp(path.join(os.tmpdir(), prefix));
38
+ return { dir, cleanup: () => rm(dir, { recursive: true, force: true }) };
39
+ }
40
+
41
+ function makePair(overrides?: Partial<ContradictionPair>): Omit<ContradictionPair, "pairId"> & { memoryIds: [string, string] } {
42
+ return {
43
+ memoryIds: ["mem-a-001", "mem-b-002"],
44
+ verdict: "contradicts",
45
+ rationale: "Test rationale",
46
+ confidence: 0.9,
47
+ detectedAt: new Date().toISOString(),
48
+ ...overrides,
49
+ };
50
+ }
51
+
52
+ async function writeStoredPair(dir: string, pair: ContradictionPair): Promise<void> {
53
+ const reviewDir = path.join(dir, ".review", "contradictions");
54
+ await mkdir(reviewDir, { recursive: true });
55
+ await writeFile(path.join(reviewDir, `${pair.pairId}.json`), JSON.stringify(pair, null, 2), "utf-8");
56
+ }
57
+
58
+ function makeMemory(id: string, category: MemoryCategory = "fact"): MemoryFile {
59
+ const now = "2026-05-17T00:00:00.000Z";
60
+ return {
61
+ path: `/tmp/${id}.md`,
62
+ content: `content for ${id}`,
63
+ frontmatter: {
64
+ id,
65
+ category,
66
+ created: now,
67
+ updated: now,
68
+ source: "test",
69
+ confidence: 0.9,
70
+ confidenceTier: "explicit",
71
+ tags: [],
72
+ },
73
+ };
74
+ }
75
+
76
+ function cloneMemory(memory: MemoryFile): MemoryFile {
77
+ return {
78
+ path: memory.path,
79
+ content: memory.content,
80
+ frontmatter: {
81
+ ...memory.frontmatter,
82
+ tags: [...(memory.frontmatter.tags ?? [])],
83
+ lineage: memory.frontmatter.lineage ? [...memory.frontmatter.lineage] : undefined,
84
+ derived_from: memory.frontmatter.derived_from ? [...memory.frontmatter.derived_from] : undefined,
85
+ },
86
+ };
87
+ }
88
+
89
+ function makeResolutionStorage(options: {
90
+ failSupersedeFor?: string;
91
+ failRollbackFor?: string;
92
+ partialSupersedeBeforeFailureFor?: string;
93
+ } = {}) {
94
+ const memories = new Map<string, MemoryFile>([
95
+ ["mem-a-001", makeMemory("mem-a-001")],
96
+ ["mem-b-002", makeMemory("mem-b-002")],
97
+ ["mem-merged-003", makeMemory("mem-merged-003")],
98
+ ]);
99
+ const supersedeCalls: Array<{ oldId: string; newId: string; reason: string }> = [];
100
+ const frontmatterWrites: Array<{
101
+ memoryId: string;
102
+ beforeStatus: MemoryFrontmatter["status"];
103
+ patch: Partial<MemoryFrontmatter>;
104
+ lifecycle?: FrontmatterLifecycleOptions;
105
+ }> = [];
106
+ const removedFactHashIds: string[] = [];
107
+
108
+ const storage = {
109
+ memories,
110
+ supersedeCalls,
111
+ frontmatterWrites,
112
+ removedFactHashIds,
113
+ async getMemoryById(id: string) {
114
+ const memory = memories.get(id);
115
+ return memory ? cloneMemory(memory) : null;
116
+ },
117
+ async writeMemory(category: MemoryCategory, content: string, writeOptions: {
118
+ lineage?: string[];
119
+ derivedFrom?: string[];
120
+ derivedVia?: string;
121
+ tags?: string[];
122
+ }) {
123
+ const id = `merged-created-${memories.size}`;
124
+ const memory = makeMemory(id, category);
125
+ memory.content = content;
126
+ memory.frontmatter.tags = writeOptions.tags ?? [];
127
+ memory.frontmatter.lineage = writeOptions.lineage;
128
+ memory.frontmatter.derived_from = writeOptions.derivedFrom;
129
+ memory.frontmatter.derived_via = writeOptions.derivedVia as MemoryFrontmatter["derived_via"];
130
+ memories.set(id, memory);
131
+ return id;
132
+ },
133
+ async supersedeMemory(oldId: string, newId: string, reason: string) {
134
+ supersedeCalls.push({ oldId, newId, reason });
135
+ if (oldId === options.failSupersedeFor) return false;
136
+ const memory = memories.get(oldId);
137
+ if (!memory) return false;
138
+ const supersededMemory: MemoryFile = {
139
+ ...memory,
140
+ frontmatter: {
141
+ ...memory.frontmatter,
142
+ status: "superseded",
143
+ supersededBy: newId,
144
+ supersededAt: "2026-05-17T00:01:00.000Z",
145
+ },
146
+ };
147
+ memories.set(oldId, supersededMemory);
148
+ if (oldId === options.partialSupersedeBeforeFailureFor) return false;
149
+ return true;
150
+ },
151
+ async writeMemoryFrontmatter(
152
+ memory: MemoryFile,
153
+ patch: Partial<MemoryFrontmatter>,
154
+ lifecycle?: FrontmatterLifecycleOptions,
155
+ ) {
156
+ const existing = memories.get(memory.frontmatter.id);
157
+ if (!existing) return false;
158
+ frontmatterWrites.push({
159
+ memoryId: memory.frontmatter.id,
160
+ beforeStatus: memory.frontmatter.status,
161
+ patch,
162
+ lifecycle,
163
+ });
164
+ if (memory.frontmatter.id === options.failRollbackFor) return false;
165
+ memories.set(memory.frontmatter.id, {
166
+ ...memory,
167
+ frontmatter: { ...memory.frontmatter, ...patch },
168
+ });
169
+ return true;
170
+ },
171
+ async invalidateMemory(id: string) {
172
+ return memories.delete(id);
173
+ },
174
+ async removeFactContentHashesForMemories(hashMemories: MemoryFile[]) {
175
+ removedFactHashIds.push(...hashMemories.map((memory) => memory.frontmatter.id));
176
+ },
177
+ };
178
+
179
+ return storage as typeof storage & StorageManager;
180
+ }
181
+
182
+ function makeScanStorage(memories: MemoryFile[]) {
183
+ let readCount = 0;
184
+ const storage = {
185
+ get readCount() {
186
+ return readCount;
187
+ },
188
+ async readAllMemories() {
189
+ readCount += 1;
190
+ return memories.map(cloneMemory);
191
+ },
192
+ };
193
+ return storage as typeof storage & StorageManager;
194
+ }
195
+
196
+ // ── Pair ID determinism ────────────────────────────────────────────────────────
197
+
198
+ test("computePairId is deterministic and order-independent", () => {
199
+ const ab = computePairId("a", "b");
200
+ const ba = computePairId("b", "a");
201
+ assert.equal(ab, ba, "Pair ID should be the same regardless of argument order");
202
+ });
203
+
204
+ test("computePairId produces different IDs for different pairs", () => {
205
+ const ab = computePairId("a", "b");
206
+ const ac = computePairId("a", "c");
207
+ assert.notEqual(ab, ac);
208
+ });
209
+
210
+ test("computePairId includes namespace scope when present", () => {
211
+ const unscoped = computePairId("a", "b");
212
+ const ns1 = computePairId("a", "b", "ns1");
213
+ const ns1Reversed = computePairId("b", "a", "ns1");
214
+ const ns2 = computePairId("a", "b", "ns2");
215
+
216
+ assert.notEqual(ns1, unscoped);
217
+ assert.equal(ns1, ns1Reversed);
218
+ assert.notEqual(ns1, ns2);
219
+ assert.equal(computePairId("a", "b", " "), unscoped);
220
+ });
221
+
222
+ // ── Review queue write/read ────────────────────────────────────────────────────
223
+
224
+ test("writePair and readPair round-trip", async () => {
225
+ const { dir, cleanup } = await makeTempDir();
226
+ try {
227
+ const pair = makePair();
228
+ const written = writePair(dir, pair);
229
+ assert.ok(written.pairId, "Written pair should have a pairId");
230
+ assert.deepEqual(written.memoryIds, pair.memoryIds);
231
+
232
+ const read = readPair(dir, written.pairId);
233
+ assert.ok(read, "Should read back the pair");
234
+ assert.equal(read!.pairId, written.pairId);
235
+ assert.equal(read!.verdict, "contradicts");
236
+ } finally {
237
+ await cleanup();
238
+ }
239
+ });
240
+
241
+ test("writePair is idempotent", async () => {
242
+ const { dir, cleanup } = await makeTempDir();
243
+ try {
244
+ const pair = makePair();
245
+ const first = writePair(dir, pair);
246
+ const second = writePair(dir, pair);
247
+ assert.equal(first.pairId, second.pairId);
248
+ } finally {
249
+ await cleanup();
250
+ }
251
+ });
252
+
253
+ test("writePair stores identical memory id pairs separately per namespace", async () => {
254
+ const { dir, cleanup } = await makeTempDir();
255
+ try {
256
+ const ns1 = writePair(dir, makePair({ namespace: "ns1" }));
257
+ const ns2 = writePair(dir, makePair({ namespace: "ns2" }));
258
+
259
+ assert.notEqual(ns1.pairId, ns2.pairId);
260
+ assert.equal(listPairs(dir, { namespace: "ns1" }).pairs[0]?.pairId, ns1.pairId);
261
+ assert.equal(listPairs(dir, { namespace: "ns2" }).pairs[0]?.pairId, ns2.pairId);
262
+ } finally {
263
+ await cleanup();
264
+ }
265
+ });
266
+
267
+ test("review queue writes use unique temporary paths", async () => {
268
+ const { dir, cleanup } = await makeTempDir();
269
+ const tempPaths: string[] = [];
270
+ const originalWriteFileSync = fs.writeFileSync;
271
+
272
+ (fs as any).writeFileSync = (file: unknown, ...args: unknown[]) => {
273
+ const filePath = String(file);
274
+ if (filePath.includes(`${path.sep}.review${path.sep}contradictions${path.sep}`)) {
275
+ tempPaths.push(filePath);
276
+ }
277
+ return (originalWriteFileSync as any).call(fs, file, ...args);
278
+ };
279
+
280
+ try {
281
+ const first = writePair(dir, makePair({ memoryIds: ["mem-a-001", "mem-b-002"] }));
282
+ const second = writePair(dir, makePair({ memoryIds: ["mem-a-003", "mem-b-004"] }));
283
+ resolvePair(dir, first.pairId, "both-valid");
284
+ deferPair(dir, second.pairId);
285
+
286
+ assert.equal(tempPaths.length, 4);
287
+ assert.equal(new Set(tempPaths).size, tempPaths.length);
288
+ for (const tempPath of tempPaths) {
289
+ assert.match(tempPath, /\.json\.\d+\.\d+\.[0-9a-f-]+\.tmp$/);
290
+ assert.equal(tempPath.endsWith(".json.tmp"), false);
291
+ }
292
+ } finally {
293
+ fs.writeFileSync = originalWriteFileSync;
294
+ await cleanup();
295
+ }
296
+ });
297
+
298
+ test("review queue write failures clean up unique temporary files", async () => {
299
+ const { dir, cleanup } = await makeTempDir();
300
+ const originalRenameSync = fs.renameSync;
301
+ let attemptedTempPath: string | null = null;
302
+
303
+ (fs as any).renameSync = (oldPath: unknown, newPath: unknown) => {
304
+ if (String(newPath).includes(`${path.sep}.review${path.sep}contradictions${path.sep}`)) {
305
+ attemptedTempPath = String(oldPath);
306
+ throw new Error("simulated rename failure");
307
+ }
308
+ return (originalRenameSync as any).call(fs, oldPath, newPath);
309
+ };
310
+
311
+ try {
312
+ assert.throws(
313
+ () => writePair(dir, makePair()),
314
+ /simulated rename failure/,
315
+ );
316
+ assert.ok(attemptedTempPath);
317
+ assert.equal(fs.existsSync(attemptedTempPath), false);
318
+ } finally {
319
+ fs.renameSync = originalRenameSync;
320
+ await cleanup();
321
+ }
322
+ });
323
+
324
+ test("writePair preserves user resolution", async () => {
325
+ const { dir, cleanup } = await makeTempDir();
326
+ try {
327
+ const pair = makePair();
328
+ const written = writePair(dir, pair);
329
+ resolvePair(dir, written.pairId, "keep-a");
330
+
331
+ const updated = writePair(dir, makePair({ memoryIds: ["mem-a-001", "mem-b-002"], confidence: 0.95 }));
332
+ assert.equal(updated.resolution, "keep-a", "Should preserve existing resolution");
333
+ } finally {
334
+ await cleanup();
335
+ }
336
+ });
337
+
338
+ test("writePair preserves both-valid resolutions without scan cooldown context", async () => {
339
+ const { dir, cleanup } = await makeTempDir();
340
+ try {
341
+ const written = writePair(dir, makePair({ confidence: 0.5 }));
342
+ resolvePair(dir, written.pairId, "both-valid");
343
+
344
+ const updated = writePair(dir, makePair({ confidence: 0.95 }));
345
+ assert.equal(updated.resolution, "both-valid");
346
+ assert.equal(updated.confidence, 0.5);
347
+ } finally {
348
+ await cleanup();
349
+ }
350
+ });
351
+
352
+ test("writePair preserves dormant independent verdicts during cooldown", async () => {
353
+ const { dir, cleanup } = await makeTempDir();
354
+ try {
355
+ const now = new Date().toISOString();
356
+ const dormant = writePair(dir, makePair({
357
+ verdict: "independent",
358
+ confidence: 0.95,
359
+ lastReviewedAt: now,
360
+ }));
361
+
362
+ const refreshed = writePair(dir, makePair({
363
+ verdict: "contradicts",
364
+ confidence: 1,
365
+ rationale: "Fresh actionable judge result during cooldown",
366
+ }), { cooldownDays: 14 });
367
+
368
+ assert.equal(refreshed.pairId, dormant.pairId);
369
+ assert.equal(refreshed.verdict, "independent");
370
+ assert.equal(refreshed.confidence, 0.95);
371
+ assert.equal(refreshed.lastReviewedAt, now);
372
+ } finally {
373
+ await cleanup();
374
+ }
375
+ });
376
+
377
+ test("writePair refreshes dormant independent verdicts during cooldown when memory content changed", async () => {
378
+ const { dir, cleanup } = await makeTempDir();
379
+ try {
380
+ const now = new Date().toISOString();
381
+ const staleAHash = computeMemoryContentHash("old content for mem-a-001", "fact");
382
+ const currentAHash = computeMemoryContentHash("new content for mem-a-001", "fact");
383
+ const bHash = computeMemoryContentHash("content for mem-b-002", "fact");
384
+ const dormant = writePair(dir, makePair({
385
+ verdict: "independent",
386
+ confidence: 0.95,
387
+ lastReviewedAt: now,
388
+ memoryContentHashes: {
389
+ "mem-a-001": staleAHash,
390
+ "mem-b-002": bHash,
391
+ },
392
+ }));
393
+
394
+ const refreshed = writePair(dir, makePair({
395
+ verdict: "contradicts",
396
+ confidence: 0.5,
397
+ rationale: "Changed source memories now conflict",
398
+ memoryContentHashes: {
399
+ "mem-a-001": currentAHash,
400
+ "mem-b-002": bHash,
401
+ },
402
+ }), { cooldownDays: 14 });
403
+
404
+ assert.equal(refreshed.pairId, dormant.pairId);
405
+ assert.equal(refreshed.verdict, "contradicts");
406
+ assert.equal(refreshed.confidence, 0.5);
407
+ assert.equal(refreshed.resolution, undefined);
408
+ assert.equal(refreshed.lastReviewedAt, undefined);
409
+ assert.deepEqual(refreshed.memoryContentHashes, {
410
+ "mem-a-001": currentAHash,
411
+ "mem-b-002": bHash,
412
+ });
413
+ } finally {
414
+ await cleanup();
415
+ }
416
+ });
417
+
418
+ test("memoryHashesChanged compares stored pair hashes with current memory hashes", async () => {
419
+ const previousHash = computeMemoryContentHash("old content", "fact");
420
+ const unchangedHash = computeMemoryContentHash("same content", "fact");
421
+ const currentHash = computeMemoryContentHash("new content", "fact");
422
+ const pair = makePair({
423
+ memoryContentHashes: {
424
+ "mem-a-001": previousHash,
425
+ "mem-b-002": unchangedHash,
426
+ },
427
+ });
428
+
429
+ assert.equal(
430
+ memoryHashesChanged("", { ...pair, pairId: computePairId("mem-a-001", "mem-b-002") }, (memoryId) => {
431
+ if (memoryId === "mem-a-001") return currentHash;
432
+ if (memoryId === "mem-b-002") return unchangedHash;
433
+ return null;
434
+ }),
435
+ true,
436
+ );
437
+ assert.equal(
438
+ memoryHashesChanged("", { ...pair, pairId: computePairId("mem-a-001", "mem-b-002") }, (memoryId) => {
439
+ if (memoryId === "mem-a-001") return previousHash;
440
+ if (memoryId === "mem-b-002") return unchangedHash;
441
+ return null;
442
+ }),
443
+ false,
444
+ );
445
+ });
446
+
447
+ test("writePair refreshes expired independent verdicts with actionable lower-confidence results", async () => {
448
+ const { dir, cleanup } = await makeTempDir();
449
+ try {
450
+ const expiredAt = new Date(Date.now() - 15 * 24 * 60 * 60 * 1000).toISOString();
451
+ const dormant = writePair(dir, makePair({
452
+ verdict: "independent",
453
+ confidence: 0.95,
454
+ detectedAt: expiredAt,
455
+ lastReviewedAt: expiredAt,
456
+ }));
457
+
458
+ const refreshed = writePair(dir, makePair({
459
+ verdict: "contradicts",
460
+ confidence: 0.5,
461
+ rationale: "Fresh actionable judge result after cooldown",
462
+ }), { cooldownDays: 14 });
463
+
464
+ assert.equal(refreshed.pairId, dormant.pairId);
465
+ assert.equal(refreshed.verdict, "contradicts");
466
+ assert.equal(refreshed.confidence, 0.5);
467
+ assert.equal(refreshed.resolution, undefined);
468
+ assert.equal(refreshed.lastReviewedAt, undefined);
469
+ assert.equal(readPair(dir, dormant.pairId)?.verdict, "contradicts");
470
+
471
+ const unresolved = listPairs(dir, { filter: "unresolved" });
472
+ assert.equal(unresolved.total, 1);
473
+ assert.equal(unresolved.pairs[0]?.pairId, dormant.pairId);
474
+ assert.equal(unresolved.pairs[0]?.verdict, "contradicts");
475
+ } finally {
476
+ await cleanup();
477
+ }
478
+ });
479
+
480
+ test("writePair refreshes expired both-valid resolutions with actionable results", async () => {
481
+ const { dir, cleanup } = await makeTempDir();
482
+ try {
483
+ const expiredAt = new Date(Date.now() - 15 * 24 * 60 * 60 * 1000).toISOString();
484
+ const written = writePair(dir, makePair({ confidence: 0.95 }));
485
+ const resolved = resolvePair(dir, written.pairId, "both-valid");
486
+ assert.ok(resolved);
487
+ await writeStoredPair(dir, {
488
+ ...resolved,
489
+ lastReviewedAt: expiredAt,
490
+ });
491
+
492
+ const refreshed = writePair(dir, makePair({
493
+ verdict: "contradicts",
494
+ confidence: 0.5,
495
+ rationale: "Fresh actionable judge result after both-valid cooldown",
496
+ }), { cooldownDays: 14 });
497
+
498
+ assert.equal(refreshed.pairId, written.pairId);
499
+ assert.equal(refreshed.verdict, "contradicts");
500
+ assert.equal(refreshed.confidence, 0.5);
501
+ assert.equal(refreshed.resolution, undefined);
502
+ assert.equal(refreshed.lastReviewedAt, undefined);
503
+ assert.equal(readPair(dir, written.pairId)?.resolution, undefined);
504
+ } finally {
505
+ await cleanup();
506
+ }
507
+ });
508
+
509
+ // ── Batch dedup (rule 49) ──────────────────────────────────────────────────────
510
+
511
+ test("writePairs deduplicates batch inputs", async () => {
512
+ const { dir, cleanup } = await makeTempDir();
513
+ try {
514
+ const pair = makePair();
515
+ // Same pair submitted 3 times
516
+ const results = writePairs(dir, [pair, pair, pair]);
517
+ assert.equal(results.length, 1, "Should deduplicate identical pairs in batch");
518
+ } finally {
519
+ await cleanup();
520
+ }
521
+ });
522
+
523
+ // ── List and filter ────────────────────────────────────────────────────────────
524
+
525
+ test("listPairs filters by verdict", async () => {
526
+ const { dir, cleanup } = await makeTempDir();
527
+ try {
528
+ writePair(dir, makePair({ verdict: "contradicts", memoryIds: ["a1", "b1"] }));
529
+ writePair(dir, makePair({ verdict: "independent", memoryIds: ["a2", "b2"] }));
530
+ writePair(dir, makePair({ verdict: "duplicates", memoryIds: ["a3", "b3"] }));
531
+
532
+ const contradicts = listPairs(dir, { filter: "contradicts" });
533
+ assert.equal(contradicts.pairs.length, 1);
534
+ assert.equal(contradicts.pairs[0].verdict, "contradicts");
535
+
536
+ const all = listPairs(dir, { filter: "all" });
537
+ assert.equal(all.pairs.length, 3);
538
+ } finally {
539
+ await cleanup();
540
+ }
541
+ });
542
+
543
+ test("listPairs respects limit", async () => {
544
+ const { dir, cleanup } = await makeTempDir();
545
+ try {
546
+ for (let i = 0; i < 5; i++) {
547
+ writePair(dir, makePair({ memoryIds: [`a-${i}`, `b-${i}`] }));
548
+ }
549
+ const result = listPairs(dir, { filter: "all", limit: 2 });
550
+ assert.equal(result.pairs.length, 2);
551
+ assert.equal(result.total, 5, "total should reflect all matching pairs, not just returned");
552
+ } finally {
553
+ await cleanup();
554
+ }
555
+ });
556
+
557
+ test("listPairs filters by namespace", async () => {
558
+ const { dir, cleanup } = await makeTempDir();
559
+ try {
560
+ writePair(dir, makePair({ namespace: "ns1", memoryIds: ["a1", "b1"] }));
561
+ writePair(dir, makePair({ namespace: "ns2", memoryIds: ["a2", "b2"] }));
562
+
563
+ const ns1 = listPairs(dir, { namespace: "ns1" });
564
+ assert.equal(ns1.pairs.length, 1);
565
+ assert.equal(ns1.pairs[0].namespace, "ns1");
566
+ } finally {
567
+ await cleanup();
568
+ }
569
+ });
570
+
571
+ test("listPairs can include legacy unscoped pairs for a namespace filter", async () => {
572
+ const { dir, cleanup } = await makeTempDir();
573
+ try {
574
+ const legacy = writePair(dir, makePair({ memoryIds: ["legacy-a", "legacy-b"] }));
575
+ writePair(dir, makePair({ namespace: "other", memoryIds: ["other-a", "other-b"] }));
576
+
577
+ const result = listPairs(dir, { namespace: "default", includeUnscopedForNamespace: true });
578
+
579
+ assert.equal(result.total, 1);
580
+ assert.equal(result.pairs[0]?.pairId, legacy.pairId);
581
+ assert.equal(result.pairs[0]?.namespace, undefined);
582
+ } finally {
583
+ await cleanup();
584
+ }
585
+ });
586
+
587
+ test("migrateUnscopedPairsToNamespace adopts legacy unscoped review pairs", async () => {
588
+ const { dir, cleanup } = await makeTempDir();
589
+ try {
590
+ const legacy = writePair(dir, makePair({ memoryIds: ["legacy-a", "legacy-b"] }));
591
+ writePair(dir, makePair({ namespace: "other", memoryIds: ["other-a", "other-b"] }));
592
+
593
+ assert.equal(migrateUnscopedPairsToNamespace(dir, "default"), 1);
594
+
595
+ const migrated = listPairs(dir, { filter: "all", namespace: "default" }).pairs;
596
+ assert.equal(migrated.length, 1);
597
+ assert.equal(migrated[0]!.namespace, "default");
598
+ assert.equal(migrated[0]!.pairId, computePairId("legacy-a", "legacy-b", "default"));
599
+ assert.equal(readPair(dir, legacy.pairId), null);
600
+
601
+ const other = listPairs(dir, { filter: "all", namespace: "other" }).pairs;
602
+ assert.equal(other.length, 1);
603
+ } finally {
604
+ await cleanup();
605
+ }
606
+ });
607
+
608
+ test("migrateUnscopedPairsToNamespace skips review directory scan after completion marker", async () => {
609
+ const { dir, cleanup } = await makeTempDir();
610
+ try {
611
+ writePair(dir, makePair({ memoryIds: ["legacy-a", "legacy-b"] }));
612
+ assert.equal(migrateUnscopedPairsToNamespace(dir, "default"), 1);
613
+
614
+ const reviewPath = path.join(dir, ".review", "contradictions");
615
+ const originalReaddirSync = fs.readdirSync;
616
+ const callOriginalReaddirSync = originalReaddirSync as unknown as (...args: unknown[]) => unknown;
617
+ const fsMutable = fs as unknown as { readdirSync: typeof fs.readdirSync };
618
+ let reviewDirScans = 0;
619
+ try {
620
+ fsMutable.readdirSync = ((...args: unknown[]) => {
621
+ if (String(args[0]) === reviewPath) reviewDirScans += 1;
622
+ return callOriginalReaddirSync(...args);
623
+ }) as typeof fs.readdirSync;
624
+
625
+ assert.equal(migrateUnscopedPairsToNamespace(dir, "default"), 0);
626
+ assert.equal(reviewDirScans, 0);
627
+ } finally {
628
+ fsMutable.readdirSync = originalReaddirSync;
629
+ }
630
+
631
+ const lateLegacy = writePair(dir, makePair({ memoryIds: ["late-a", "late-b"] }));
632
+ assert.equal(migrateUnscopedPairsToNamespace(dir, "default"), 1);
633
+ assert.equal(readPair(dir, lateLegacy.pairId), null);
634
+ assert.equal(readPair(dir, computePairId("late-a", "late-b", "default"))?.namespace, "default");
635
+ } finally {
636
+ await cleanup();
637
+ }
638
+ });
639
+
640
+ test("migrateUnscopedPairsToNamespace retries after partial migration failure", async () => {
641
+ const { dir, cleanup } = await makeTempDir();
642
+ try {
643
+ const failingLegacy = writePair(dir, makePair({ memoryIds: ["fail-a", "fail-b"] }));
644
+ writePair(dir, makePair({ memoryIds: ["ok-a", "ok-b"] }));
645
+
646
+ const reviewPath = path.join(dir, ".review", "contradictions");
647
+ const failingPath = path.join(reviewPath, `${failingLegacy.pairId}.json`);
648
+ const originalRmSync = fs.rmSync;
649
+ const fsMutable = fs as unknown as { rmSync: typeof fs.rmSync };
650
+ let failedOnce = false;
651
+
652
+ try {
653
+ fsMutable.rmSync = ((target: fs.PathLike, options?: fs.RmOptions) => {
654
+ if (!failedOnce && String(target) === failingPath) {
655
+ failedOnce = true;
656
+ throw new Error("simulated legacy cleanup failure");
657
+ }
658
+ return originalRmSync(target, options);
659
+ }) as typeof fs.rmSync;
660
+
661
+ assert.equal(migrateUnscopedPairsToNamespace(dir, "default"), 1);
662
+ } finally {
663
+ fsMutable.rmSync = originalRmSync;
664
+ }
665
+
666
+ const markerEntriesAfterFailure = fs
667
+ .readdirSync(reviewPath)
668
+ .filter((entry) => entry.startsWith(".unscoped-migrated-"));
669
+ assert.deepEqual(
670
+ markerEntriesAfterFailure,
671
+ [],
672
+ "partial migration failure must not write the completion marker",
673
+ );
674
+ assert.ok(readPair(dir, failingLegacy.pairId), "failed legacy pair remains retryable");
675
+
676
+ assert.equal(migrateUnscopedPairsToNamespace(dir, "default"), 1);
677
+ assert.equal(readPair(dir, failingLegacy.pairId), null);
678
+ assert.equal(readPair(dir, computePairId("fail-a", "fail-b", "default"))?.namespace, "default");
679
+
680
+ const markerEntriesAfterRetry = fs
681
+ .readdirSync(reviewPath)
682
+ .filter((entry) => entry.startsWith(".unscoped-migrated-"));
683
+ assert.equal(markerEntriesAfterRetry.length, 1);
684
+ } finally {
685
+ await cleanup();
686
+ }
687
+ });
688
+
689
+ test("migrateUnscopedPairsToNamespace still completes when malformed files are skipped", async () => {
690
+ const { dir, cleanup } = await makeTempDir();
691
+ try {
692
+ const legacy = writePair(dir, makePair({ memoryIds: ["legacy-a", "legacy-b"] }));
693
+ const reviewPath = path.join(dir, ".review", "contradictions");
694
+ await writeFile(path.join(reviewPath, "malformed.json"), "{not-json", "utf-8");
695
+
696
+ assert.equal(migrateUnscopedPairsToNamespace(dir, "default"), 1);
697
+ assert.equal(readPair(dir, legacy.pairId), null);
698
+ assert.equal(readPair(dir, computePairId("legacy-a", "legacy-b", "default"))?.namespace, "default");
699
+
700
+ const markerEntries = fs
701
+ .readdirSync(reviewPath)
702
+ .filter((entry) => entry.startsWith(".unscoped-migrated-"));
703
+ assert.equal(markerEntries.length, 1);
704
+ } finally {
705
+ await cleanup();
706
+ }
707
+ });
708
+
709
+ test("migrateUnscopedPairsToNamespace preserves legacy both-valid state on scoped collisions", async () => {
710
+ const { dir, cleanup } = await makeTempDir();
711
+ try {
712
+ const scoped = writePair(dir, makePair({
713
+ namespace: "default",
714
+ memoryIds: ["shared-a", "shared-b"],
715
+ verdict: "contradicts",
716
+ confidence: 0.95,
717
+ detectedAt: "2026-01-01T00:00:00.000Z",
718
+ }));
719
+ const legacy: ContradictionPair = {
720
+ ...makePair({
721
+ memoryIds: ["shared-a", "shared-b"],
722
+ verdict: "independent",
723
+ resolution: "both-valid",
724
+ lastReviewedAt: "2026-02-01T00:00:00.000Z",
725
+ detectedAt: "2026-01-15T00:00:00.000Z",
726
+ }),
727
+ pairId: computePairId("shared-a", "shared-b"),
728
+ };
729
+ await writeStoredPair(dir, legacy);
730
+
731
+ assert.equal(migrateUnscopedPairsToNamespace(dir, "default"), 1);
732
+
733
+ const migrated = readPair(dir, scoped.pairId);
734
+ assert.ok(migrated);
735
+ assert.equal(migrated.namespace, "default");
736
+ assert.equal(migrated.resolution, "both-valid");
737
+ assert.equal(migrated.verdict, "independent");
738
+ assert.equal(migrated.lastReviewedAt, "2026-02-01T00:00:00.000Z");
739
+ assert.equal(readPair(dir, legacy.pairId), null);
740
+ } finally {
741
+ await cleanup();
742
+ }
743
+ });
744
+
745
+ test("migrateUnscopedPairsToNamespace preserves legacy cooldown state on scoped collisions", async () => {
746
+ const { dir, cleanup } = await makeTempDir();
747
+ try {
748
+ const scoped = writePair(dir, makePair({
749
+ namespace: "default",
750
+ memoryIds: ["shared-a", "shared-b"],
751
+ verdict: "contradicts",
752
+ confidence: 0.95,
753
+ detectedAt: "2026-01-01T00:00:00.000Z",
754
+ }));
755
+ const legacy: ContradictionPair = {
756
+ ...makePair({
757
+ memoryIds: ["shared-a", "shared-b"],
758
+ verdict: "independent",
759
+ lastReviewedAt: "2026-02-01T00:00:00.000Z",
760
+ detectedAt: "2026-01-15T00:00:00.000Z",
761
+ }),
762
+ pairId: computePairId("shared-a", "shared-b"),
763
+ };
764
+ await writeStoredPair(dir, legacy);
765
+
766
+ assert.equal(migrateUnscopedPairsToNamespace(dir, "default"), 1);
767
+
768
+ const migrated = readPair(dir, scoped.pairId);
769
+ assert.ok(migrated);
770
+ assert.equal(migrated.namespace, "default");
771
+ assert.equal(migrated.verdict, "independent");
772
+ assert.equal(migrated.lastReviewedAt, "2026-02-01T00:00:00.000Z");
773
+ assert.equal(readPair(dir, legacy.pairId), null);
774
+ } finally {
775
+ await cleanup();
776
+ }
777
+ });
778
+
779
+ test("migrateUnscopedPairsToNamespace preserves scoped conflicts over expired legacy cooldowns", async () => {
780
+ const { dir, cleanup } = await makeTempDir();
781
+ try {
782
+ const scoped = writePair(dir, makePair({
783
+ namespace: "default",
784
+ memoryIds: ["shared-a", "shared-b"],
785
+ verdict: "contradicts",
786
+ confidence: 0.95,
787
+ detectedAt: "2026-04-01T00:00:00.000Z",
788
+ }));
789
+ const legacy: ContradictionPair = {
790
+ ...makePair({
791
+ memoryIds: ["shared-a", "shared-b"],
792
+ verdict: "independent",
793
+ lastReviewedAt: "2020-01-01T00:00:00.000Z",
794
+ detectedAt: "2020-01-01T00:00:00.000Z",
795
+ }),
796
+ pairId: computePairId("shared-a", "shared-b"),
797
+ };
798
+ await writeStoredPair(dir, legacy);
799
+
800
+ assert.equal(migrateUnscopedPairsToNamespace(dir, "default", { cooldownDays: 14 }), 1);
801
+
802
+ const migrated = readPair(dir, scoped.pairId);
803
+ assert.ok(migrated);
804
+ assert.equal(migrated.namespace, "default");
805
+ assert.equal(migrated.verdict, "contradicts");
806
+ assert.equal(migrated.resolution, undefined);
807
+ assert.equal(readPair(dir, legacy.pairId), null);
808
+ } finally {
809
+ await cleanup();
810
+ }
811
+ });
812
+
813
+ test("migrateUnscopedPairsToNamespace preserves existing terminal scoped state on collisions", async () => {
814
+ const { dir, cleanup } = await makeTempDir();
815
+ try {
816
+ const scoped: ContradictionPair = {
817
+ ...makePair({
818
+ namespace: "default",
819
+ memoryIds: ["shared-a", "shared-b"],
820
+ verdict: "contradicts",
821
+ resolution: "keep-a",
822
+ lastReviewedAt: "2026-01-01T00:00:00.000Z",
823
+ }),
824
+ pairId: computePairId("shared-a", "shared-b", "default"),
825
+ };
826
+ await writeStoredPair(dir, scoped);
827
+ const legacy: ContradictionPair = {
828
+ ...makePair({
829
+ memoryIds: ["shared-a", "shared-b"],
830
+ verdict: "independent",
831
+ resolution: "both-valid",
832
+ lastReviewedAt: "2026-02-01T00:00:00.000Z",
833
+ }),
834
+ pairId: computePairId("shared-a", "shared-b"),
835
+ };
836
+ await writeStoredPair(dir, legacy);
837
+
838
+ assert.equal(migrateUnscopedPairsToNamespace(dir, "default"), 1);
839
+
840
+ const migrated = readPair(dir, scoped.pairId);
841
+ assert.ok(migrated);
842
+ assert.equal(migrated.namespace, "default");
843
+ assert.equal(migrated.resolution, "keep-a");
844
+ assert.equal(migrated.verdict, "contradicts");
845
+ assert.equal(readPair(dir, legacy.pairId), null);
846
+ } finally {
847
+ await cleanup();
848
+ }
849
+ });
850
+
851
+ test("migrateUnscopedPairsToNamespace keeps selected memory order on scoped collisions", async () => {
852
+ const { dir, cleanup } = await makeTempDir();
853
+ try {
854
+ const scoped: ContradictionPair = {
855
+ ...makePair({
856
+ namespace: "default",
857
+ memoryIds: ["shared-b", "shared-a"],
858
+ verdict: "contradicts",
859
+ resolution: "keep-a",
860
+ lastReviewedAt: "2026-01-01T00:00:00.000Z",
861
+ }),
862
+ pairId: computePairId("shared-a", "shared-b", "default"),
863
+ };
864
+ await writeStoredPair(dir, scoped);
865
+ const legacy: ContradictionPair = {
866
+ ...makePair({
867
+ memoryIds: ["shared-a", "shared-b"],
868
+ verdict: "independent",
869
+ resolution: "both-valid",
870
+ lastReviewedAt: "2026-02-01T00:00:00.000Z",
871
+ }),
872
+ pairId: computePairId("shared-a", "shared-b"),
873
+ };
874
+ await writeStoredPair(dir, legacy);
875
+
876
+ assert.equal(migrateUnscopedPairsToNamespace(dir, "default"), 1);
877
+
878
+ const migrated = readPair(dir, scoped.pairId);
879
+ assert.ok(migrated);
880
+ assert.equal(migrated.resolution, "keep-a");
881
+ assert.deepEqual(migrated.memoryIds, ["shared-b", "shared-a"]);
882
+ assert.equal(readPair(dir, legacy.pairId), null);
883
+ } finally {
884
+ await cleanup();
885
+ }
886
+ });
887
+
888
+ test("runContradictionScan loads memories from namespace-scoped storage", async () => {
889
+ const { dir, cleanup } = await makeTempDir();
890
+ try {
891
+ const ns1A = makeMemory("ns1-a");
892
+ ns1A.frontmatter.entityRef = "entity:shared";
893
+ const ns1B = makeMemory("ns1-b");
894
+ ns1B.frontmatter.entityRef = "entity:shared";
895
+ const ns2A = makeMemory("ns2-a");
896
+ ns2A.frontmatter.entityRef = "entity:shared";
897
+
898
+ const rootStorage = makeScanStorage([ns1A, ns1B, ns2A]);
899
+ const ns1Storage = makeScanStorage([ns1A, ns1B]);
900
+ const config = parseConfig({
901
+ memoryDir: dir,
902
+ namespacesEnabled: true,
903
+ defaultNamespace: "default",
904
+ contradictionScan: {
905
+ enabled: true,
906
+ maxPairsPerRun: 10,
907
+ topicOverlapFloor: 0,
908
+ similarityFloor: 0,
909
+ },
910
+ });
911
+
912
+ const result = await runContradictionScan({
913
+ storage: rootStorage,
914
+ storageForNamespace(namespace) {
915
+ assert.equal(namespace, "ns1");
916
+ return ns1Storage;
917
+ },
918
+ config,
919
+ memoryDir: dir,
920
+ localLlm: null,
921
+ fallbackLlm: null,
922
+ namespace: "ns1",
923
+ });
924
+
925
+ assert.equal(rootStorage.readCount, 0);
926
+ assert.equal(ns1Storage.readCount, 1);
927
+ assert.equal(result.scanned, 2);
928
+ assert.equal(result.judged, 1);
929
+ assert.equal(result.queued, 1);
930
+
931
+ const queued = listPairs(dir, { filter: "all", namespace: "ns1" }).pairs;
932
+ assert.equal(queued.length, 1);
933
+ assert.deepEqual([...queued[0]!.memoryIds].sort(), ["ns1-a", "ns1-b"]);
934
+ } finally {
935
+ await cleanup();
936
+ }
937
+ });
938
+
939
+ test("runContradictionScan caps candidates during generation and preserves strategy priority", async () => {
940
+ const { dir, cleanup } = await makeTempDir();
941
+ try {
942
+ const entityA = makeMemory("entity-a");
943
+ entityA.frontmatter.entityRef = "entity:shared";
944
+ const entityB = makeMemory("entity-b");
945
+ entityB.frontmatter.entityRef = "entity:shared";
946
+
947
+ const topicA = makeMemory("topic-a");
948
+ topicA.frontmatter.tags = ["shared-topic"];
949
+ const topicB = makeMemory("topic-b");
950
+ topicB.frontmatter.tags = ["shared-topic"];
951
+
952
+ const embedA = makeMemory("embed-0-a");
953
+ embedA.frontmatter.tags = ["embed-a"];
954
+ const embedB = makeMemory("embed-0-b");
955
+ embedB.frontmatter.tags = ["embed-b"];
956
+
957
+ const storage = makeScanStorage([embedB, topicB, entityB, embedA, topicA, entityA]);
958
+ const config = parseConfig({
959
+ memoryDir: dir,
960
+ contradictionScan: {
961
+ enabled: true,
962
+ maxPairsPerRun: 2,
963
+ topicOverlapFloor: 0.5,
964
+ similarityFloor: 0.8,
965
+ },
966
+ });
967
+ let embeddingCalls = 0;
968
+
969
+ const result = await runContradictionScan({
970
+ storage,
971
+ config,
972
+ memoryDir: dir,
973
+ embeddingLookup: async (content) => {
974
+ embeddingCalls += 1;
975
+ return content === embedA.content ? [{ id: "embed-0-b", score: 0.99 }] : [];
976
+ },
977
+ localLlm: null,
978
+ fallbackLlm: null,
979
+ });
980
+
981
+ assert.equal(result.candidates, 2);
982
+ assert.equal(result.judged, 2);
983
+ assert.equal(result.queued, 2);
984
+ assert.equal(embeddingCalls, 0);
985
+
986
+ const queuedPairs = listPairs(dir, { filter: "all" }).pairs
987
+ .map((pair) => [...pair.memoryIds].sort().join(":"))
988
+ .sort();
989
+ assert.deepEqual(queuedPairs, ["entity-a:entity-b", "topic-a:topic-b"]);
990
+ } finally {
991
+ await cleanup();
992
+ }
993
+ });
994
+
995
+ test("runContradictionScan resolves default namespace scans through namespace storage resolver", async () => {
996
+ const { dir, cleanup } = await makeTempDir();
997
+ try {
998
+ const defaultA = makeMemory("default-a");
999
+ defaultA.frontmatter.entityRef = "entity:shared";
1000
+ const defaultB = makeMemory("default-b");
1001
+ defaultB.frontmatter.entityRef = "entity:shared";
1002
+ const rootOnly = makeMemory("root-only");
1003
+ rootOnly.frontmatter.entityRef = "entity:shared";
1004
+
1005
+ const rootStorage = makeScanStorage([rootOnly]);
1006
+ const defaultStorage = makeScanStorage([defaultA, defaultB]);
1007
+ const config = parseConfig({
1008
+ memoryDir: dir,
1009
+ namespacesEnabled: true,
1010
+ defaultNamespace: "configured-default",
1011
+ contradictionScan: {
1012
+ enabled: true,
1013
+ maxPairsPerRun: 10,
1014
+ topicOverlapFloor: 0,
1015
+ similarityFloor: 0,
1016
+ },
1017
+ });
1018
+
1019
+ const result = await runContradictionScan({
1020
+ storage: rootStorage,
1021
+ storageForNamespace(namespace) {
1022
+ assert.equal(namespace, undefined);
1023
+ return { storage: defaultStorage, namespace: "resolved-default" };
1024
+ },
1025
+ config,
1026
+ memoryDir: dir,
1027
+ localLlm: null,
1028
+ fallbackLlm: null,
1029
+ });
1030
+
1031
+ assert.equal(rootStorage.readCount, 0);
1032
+ assert.equal(defaultStorage.readCount, 1);
1033
+ assert.equal(result.scanned, 2);
1034
+
1035
+ const queued = listPairs(dir, { filter: "all", namespace: "resolved-default" }).pairs;
1036
+ assert.equal(queued.length, 1);
1037
+ assert.equal(queued[0]!.namespace, "resolved-default");
1038
+ assert.deepEqual([...queued[0]!.memoryIds].sort(), ["default-a", "default-b"]);
1039
+ } finally {
1040
+ await cleanup();
1041
+ }
1042
+ });
1043
+
1044
+ test("runContradictionScan treats StorageManager with storage property as raw storage", async () => {
1045
+ const { dir, cleanup } = await makeTempDir();
1046
+ try {
1047
+ const defaultA = makeMemory("default-a");
1048
+ defaultA.frontmatter.entityRef = "entity:shared";
1049
+ const defaultB = makeMemory("default-b");
1050
+ defaultB.frontmatter.entityRef = "entity:shared";
1051
+ const nestedOnly = makeMemory("nested-only");
1052
+ nestedOnly.frontmatter.entityRef = "entity:shared";
1053
+
1054
+ const rawStorage = makeScanStorage([defaultA, defaultB]) as ReturnType<typeof makeScanStorage> & {
1055
+ storage: ReturnType<typeof makeScanStorage>;
1056
+ };
1057
+ rawStorage.storage = makeScanStorage([nestedOnly]);
1058
+ const config = parseConfig({
1059
+ memoryDir: dir,
1060
+ namespacesEnabled: true,
1061
+ defaultNamespace: "configured-default",
1062
+ contradictionScan: {
1063
+ enabled: true,
1064
+ maxPairsPerRun: 10,
1065
+ topicOverlapFloor: 0,
1066
+ similarityFloor: 0,
1067
+ },
1068
+ });
1069
+
1070
+ const result = await runContradictionScan({
1071
+ storage: makeScanStorage([]),
1072
+ storageForNamespace() {
1073
+ return rawStorage;
1074
+ },
1075
+ config,
1076
+ memoryDir: dir,
1077
+ localLlm: null,
1078
+ fallbackLlm: null,
1079
+ });
1080
+
1081
+ assert.equal(rawStorage.readCount, 1);
1082
+ assert.equal(rawStorage.storage.readCount, 0);
1083
+ assert.equal(result.scanned, 2);
1084
+
1085
+ const queued = listPairs(dir, { filter: "all", namespace: "configured-default" }).pairs;
1086
+ assert.equal(queued.length, 1);
1087
+ assert.deepEqual([...queued[0]!.memoryIds].sort(), ["default-a", "default-b"]);
1088
+ } finally {
1089
+ await cleanup();
1090
+ }
1091
+ });
1092
+
1093
+ test("runContradictionScan migrates legacy unscoped cooldown pairs for default namespace scans", async () => {
1094
+ const { dir, cleanup } = await makeTempDir();
1095
+ try {
1096
+ const defaultA = makeMemory("default-a");
1097
+ defaultA.frontmatter.entityRef = "entity:shared";
1098
+ const defaultB = makeMemory("default-b");
1099
+ defaultB.frontmatter.entityRef = "entity:shared";
1100
+ writePair(dir, makePair({
1101
+ memoryIds: ["default-a", "default-b"],
1102
+ verdict: "independent",
1103
+ lastReviewedAt: new Date().toISOString(),
1104
+ }));
1105
+
1106
+ const defaultStorage = makeScanStorage([defaultA, defaultB]);
1107
+ const config = parseConfig({
1108
+ memoryDir: dir,
1109
+ namespacesEnabled: true,
1110
+ defaultNamespace: "configured-default",
1111
+ contradictionScan: {
1112
+ enabled: true,
1113
+ cooldownDays: 14,
1114
+ maxPairsPerRun: 10,
1115
+ topicOverlapFloor: 0,
1116
+ similarityFloor: 0,
1117
+ },
1118
+ });
1119
+
1120
+ const result = await runContradictionScan({
1121
+ storage: makeScanStorage([]),
1122
+ storageForNamespace(namespace) {
1123
+ assert.equal(namespace, undefined);
1124
+ return { storage: defaultStorage, namespace: "resolved-default" };
1125
+ },
1126
+ config,
1127
+ memoryDir: dir,
1128
+ localLlm: null,
1129
+ fallbackLlm: null,
1130
+ });
1131
+
1132
+ assert.equal(result.cooledDown, 1);
1133
+ assert.equal(result.judged, 0);
1134
+ assert.equal(result.queued, 0);
1135
+
1136
+ const queued = listPairs(dir, { filter: "all", namespace: "resolved-default" }).pairs;
1137
+ assert.equal(queued.length, 1);
1138
+ assert.equal(queued[0]!.namespace, "resolved-default");
1139
+ } finally {
1140
+ await cleanup();
1141
+ }
1142
+ });
1143
+
1144
+ test("runContradictionScan migrates legacy unscoped cooldown pairs for explicit default namespace scans", async () => {
1145
+ const { dir, cleanup } = await makeTempDir();
1146
+ try {
1147
+ const defaultA = makeMemory("default-a");
1148
+ defaultA.frontmatter.entityRef = "entity:shared";
1149
+ const defaultB = makeMemory("default-b");
1150
+ defaultB.frontmatter.entityRef = "entity:shared";
1151
+ writePair(dir, makePair({
1152
+ memoryIds: ["default-a", "default-b"],
1153
+ verdict: "independent",
1154
+ lastReviewedAt: new Date().toISOString(),
1155
+ }));
1156
+
1157
+ const defaultStorage = makeScanStorage([defaultA, defaultB]);
1158
+ const config = parseConfig({
1159
+ memoryDir: dir,
1160
+ namespacesEnabled: true,
1161
+ defaultNamespace: "configured-default",
1162
+ contradictionScan: {
1163
+ enabled: true,
1164
+ cooldownDays: 14,
1165
+ maxPairsPerRun: 10,
1166
+ topicOverlapFloor: 0,
1167
+ similarityFloor: 0,
1168
+ },
1169
+ });
1170
+
1171
+ const result = await runContradictionScan({
1172
+ storage: makeScanStorage([]),
1173
+ storageForNamespace(namespace) {
1174
+ assert.equal(namespace, "configured-default");
1175
+ return { storage: defaultStorage, namespace: "configured-default" };
1176
+ },
1177
+ config,
1178
+ memoryDir: dir,
1179
+ localLlm: null,
1180
+ fallbackLlm: null,
1181
+ namespace: "configured-default",
1182
+ });
1183
+
1184
+ assert.equal(result.cooledDown, 1);
1185
+ assert.equal(result.judged, 0);
1186
+ assert.equal(result.queued, 0);
1187
+
1188
+ const queued = listPairs(dir, { filter: "all", namespace: "configured-default" }).pairs;
1189
+ assert.equal(queued.length, 1);
1190
+ assert.equal(queued[0]!.namespace, "configured-default");
1191
+ } finally {
1192
+ await cleanup();
1193
+ }
1194
+ });
1195
+
1196
+ test("runContradictionScan rejudges cooling pairs when referenced memory content changed", async () => {
1197
+ const { dir, cleanup } = await makeTempDir();
1198
+ try {
1199
+ const defaultA = makeMemory("default-a");
1200
+ defaultA.frontmatter.entityRef = "entity:shared";
1201
+ defaultA.content = "Joshua uses pnpm for Remnic";
1202
+ const defaultB = makeMemory("default-b");
1203
+ defaultB.frontmatter.entityRef = "entity:shared";
1204
+ defaultB.content = "Joshua uses npm for Remnic";
1205
+ const currentAHash = computeMemoryContentHash(defaultA.content, "fact");
1206
+ const currentBHash = computeMemoryContentHash(defaultB.content, "fact");
1207
+
1208
+ writePair(dir, makePair({
1209
+ memoryIds: ["default-a", "default-b"],
1210
+ verdict: "independent",
1211
+ lastReviewedAt: new Date().toISOString(),
1212
+ memoryContentHashes: {
1213
+ "default-a": computeMemoryContentHash("Joshua uses yarn for Remnic", "fact"),
1214
+ "default-b": currentBHash,
1215
+ },
1216
+ }));
1217
+
1218
+ const storage = makeScanStorage([defaultA, defaultB]);
1219
+ const config = parseConfig({
1220
+ memoryDir: dir,
1221
+ contradictionScan: {
1222
+ enabled: true,
1223
+ cooldownDays: 14,
1224
+ maxPairsPerRun: 10,
1225
+ topicOverlapFloor: 0,
1226
+ similarityFloor: 0,
1227
+ },
1228
+ });
1229
+
1230
+ const result = await runContradictionScan({
1231
+ storage,
1232
+ config,
1233
+ memoryDir: dir,
1234
+ localLlm: null,
1235
+ fallbackLlm: {
1236
+ async complete() {
1237
+ return {
1238
+ content: JSON.stringify([{
1239
+ pairKey: "default-a:default-b",
1240
+ verdict: "independent",
1241
+ rationale: "Still no contradiction after changed content",
1242
+ confidence: 0.4,
1243
+ }]),
1244
+ };
1245
+ },
1246
+ } as any,
1247
+ });
1248
+
1249
+ assert.equal(result.cooledDown, 0);
1250
+ assert.equal(result.candidates, 1);
1251
+ assert.equal(result.judged, 1);
1252
+ assert.equal(result.queued, 1);
1253
+
1254
+ const queued = listPairs(dir, { filter: "all" }).pairs;
1255
+ assert.equal(queued.length, 1);
1256
+ assert.deepEqual(queued[0]!.memoryContentHashes, {
1257
+ "default-a": currentAHash,
1258
+ "default-b": currentBHash,
1259
+ });
1260
+ } finally {
1261
+ await cleanup();
1262
+ }
1263
+ });
1264
+
1265
+ test("runContradictionScan rejects namespace scans without an access-checked storage resolver", async () => {
1266
+ const { dir, cleanup } = await makeTempDir();
1267
+ try {
1268
+ const rootStorage = makeScanStorage([makeMemory("root-a"), makeMemory("root-b")]);
1269
+ const config = parseConfig({
1270
+ memoryDir: dir,
1271
+ namespacesEnabled: true,
1272
+ defaultNamespace: "default",
1273
+ contradictionScan: {
1274
+ enabled: true,
1275
+ maxPairsPerRun: 10,
1276
+ },
1277
+ });
1278
+
1279
+ await assert.rejects(
1280
+ runContradictionScan({
1281
+ storage: rootStorage,
1282
+ config,
1283
+ memoryDir: dir,
1284
+ localLlm: null,
1285
+ fallbackLlm: null,
1286
+ namespace: "ns1",
1287
+ }),
1288
+ /storageForNamespace/,
1289
+ );
1290
+
1291
+ assert.equal(rootStorage.readCount, 0);
1292
+ } finally {
1293
+ await cleanup();
1294
+ }
1295
+ });
1296
+
1297
+ test("runContradictionScan rejects default scans without an access-checked storage resolver when namespaces are enabled", async () => {
1298
+ const { dir, cleanup } = await makeTempDir();
1299
+ try {
1300
+ const rootStorage = makeScanStorage([makeMemory("root-a"), makeMemory("root-b")]);
1301
+ const config = parseConfig({
1302
+ memoryDir: dir,
1303
+ namespacesEnabled: true,
1304
+ defaultNamespace: "default",
1305
+ contradictionScan: {
1306
+ enabled: true,
1307
+ maxPairsPerRun: 10,
1308
+ },
1309
+ });
1310
+
1311
+ await assert.rejects(
1312
+ runContradictionScan({
1313
+ storage: rootStorage,
1314
+ config,
1315
+ memoryDir: dir,
1316
+ localLlm: null,
1317
+ fallbackLlm: null,
1318
+ }),
1319
+ /storageForNamespace/,
1320
+ );
1321
+
1322
+ assert.equal(rootStorage.readCount, 0);
1323
+ } finally {
1324
+ await cleanup();
1325
+ }
1326
+ });
1327
+
1328
+ test("runContradictionScan rejects unsupported explicit namespaces when namespaces are disabled", async () => {
1329
+ const { dir, cleanup } = await makeTempDir();
1330
+ try {
1331
+ const rootStorage = makeScanStorage([makeMemory("root-a"), makeMemory("root-b")]);
1332
+ let resolverCalls = 0;
1333
+ const config = parseConfig({
1334
+ memoryDir: dir,
1335
+ namespacesEnabled: false,
1336
+ defaultNamespace: "default",
1337
+ contradictionScan: {
1338
+ enabled: true,
1339
+ maxPairsPerRun: 10,
1340
+ },
1341
+ });
1342
+
1343
+ await assert.rejects(
1344
+ runContradictionScan({
1345
+ storage: rootStorage,
1346
+ storageForNamespace() {
1347
+ resolverCalls += 1;
1348
+ return makeScanStorage([]);
1349
+ },
1350
+ config,
1351
+ memoryDir: dir,
1352
+ localLlm: null,
1353
+ fallbackLlm: null,
1354
+ namespace: "typo",
1355
+ }),
1356
+ /unsupported namespace: typo/,
1357
+ );
1358
+
1359
+ assert.equal(resolverCalls, 0);
1360
+ assert.equal(rootStorage.readCount, 0);
1361
+ } finally {
1362
+ await cleanup();
1363
+ }
1364
+ });
1365
+
1366
+ test("runContradictionScan ignores explicit default namespace when namespaces are disabled", async () => {
1367
+ const { dir, cleanup } = await makeTempDir();
1368
+ try {
1369
+ const rootA = makeMemory("root-a");
1370
+ rootA.frontmatter.entityRef = "entity:shared";
1371
+ const rootB = makeMemory("root-b");
1372
+ rootB.frontmatter.entityRef = "entity:shared";
1373
+ const rootStorage = makeScanStorage([rootA, rootB]);
1374
+ let resolverCalls = 0;
1375
+ const config = parseConfig({
1376
+ memoryDir: dir,
1377
+ namespacesEnabled: false,
1378
+ defaultNamespace: "default",
1379
+ contradictionScan: {
1380
+ enabled: true,
1381
+ maxPairsPerRun: 10,
1382
+ topicOverlapFloor: 0,
1383
+ similarityFloor: 0,
1384
+ },
1385
+ });
1386
+
1387
+ const result = await runContradictionScan({
1388
+ storage: rootStorage,
1389
+ storageForNamespace() {
1390
+ resolverCalls += 1;
1391
+ return makeScanStorage([]);
1392
+ },
1393
+ config,
1394
+ memoryDir: dir,
1395
+ localLlm: null,
1396
+ fallbackLlm: null,
1397
+ namespace: "default",
1398
+ });
1399
+
1400
+ assert.equal(resolverCalls, 0);
1401
+ assert.equal(rootStorage.readCount, 1);
1402
+ assert.equal(result.scanned, 2);
1403
+ assert.equal(result.queued, 1);
1404
+ assert.equal(listPairs(dir, { filter: "all", namespace: "default" }).pairs.length, 0);
1405
+ assert.equal(listPairs(dir, { filter: "all" }).pairs.length, 1);
1406
+ } finally {
1407
+ await cleanup();
1408
+ }
1409
+ });
1410
+
1411
+ test("listPairs returns empty when dir does not exist", async () => {
1412
+ const { dir, cleanup } = await makeTempDir();
1413
+ try {
1414
+ const result = listPairs(path.join(dir, "nonexistent"));
1415
+ assert.equal(result.pairs.length, 0);
1416
+ assert.equal(result.total, 0);
1417
+ } finally {
1418
+ await cleanup();
1419
+ }
1420
+ });
1421
+
1422
+ // ── Cooldown ───────────────────────────────────────────────────────────────────
1423
+
1424
+ test("isCoolingDown returns false when no lastReviewedAt", () => {
1425
+ const pair: ContradictionPair = {
1426
+ pairId: "test",
1427
+ memoryIds: ["a", "b"],
1428
+ verdict: "independent",
1429
+ rationale: "",
1430
+ confidence: 0.8,
1431
+ detectedAt: new Date().toISOString(),
1432
+ };
1433
+ assert.equal(isCoolingDown(pair, 14), false);
1434
+ });
1435
+
1436
+ test("isCoolingDown returns true within cooldown window", () => {
1437
+ const pair: ContradictionPair = {
1438
+ pairId: "test",
1439
+ memoryIds: ["a", "b"],
1440
+ verdict: "independent",
1441
+ rationale: "",
1442
+ confidence: 0.8,
1443
+ detectedAt: new Date().toISOString(),
1444
+ lastReviewedAt: new Date().toISOString(),
1445
+ };
1446
+ assert.equal(isCoolingDown(pair, 14), true);
1447
+ });
1448
+
1449
+ test("isCoolingDown returns false after cooldown expires", () => {
1450
+ const past = new Date(Date.now() - 15 * 24 * 60 * 60 * 1000).toISOString();
1451
+ const pair: ContradictionPair = {
1452
+ pairId: "test",
1453
+ memoryIds: ["a", "b"],
1454
+ verdict: "independent",
1455
+ rationale: "",
1456
+ confidence: 0.8,
1457
+ detectedAt: past,
1458
+ lastReviewedAt: past,
1459
+ };
1460
+ assert.equal(isCoolingDown(pair, 14), false);
1461
+ });
1462
+
1463
+ test("isCoolingDown returns false when cooldownDays is 0 (rule 27)", () => {
1464
+ const pair: ContradictionPair = {
1465
+ pairId: "test",
1466
+ memoryIds: ["a", "b"],
1467
+ verdict: "independent",
1468
+ rationale: "",
1469
+ confidence: 0.8,
1470
+ detectedAt: new Date().toISOString(),
1471
+ lastReviewedAt: new Date().toISOString(),
1472
+ };
1473
+ assert.equal(isCoolingDown(pair, 0), false, "0 cooldownDays should disable cooldown");
1474
+ assert.equal(
1475
+ isCoolingDown({ ...pair, pairId: "deferred", deferredUntil: new Date(Date.now() + 60_000).toISOString() }, 0),
1476
+ false,
1477
+ "0 cooldownDays should disable explicit deferral cooldown",
1478
+ );
1479
+ assert.equal(
1480
+ isCoolingDown({ ...pair, pairId: "legacy-deferred", resolution: "needs-more-context" }, 0),
1481
+ false,
1482
+ "0 cooldownDays should disable legacy deferral cooldown",
1483
+ );
1484
+ });
1485
+
1486
+ test("isCoolingDown uses deferredUntil instead of generic cooldown for deferrals", () => {
1487
+ const now = Date.now();
1488
+ const active: ContradictionPair = {
1489
+ pairId: "active-deferral",
1490
+ memoryIds: ["a", "b"],
1491
+ verdict: "contradicts",
1492
+ rationale: "",
1493
+ confidence: 0.8,
1494
+ detectedAt: new Date(now).toISOString(),
1495
+ lastReviewedAt: new Date(now).toISOString(),
1496
+ deferredUntil: new Date(now + 60_000).toISOString(),
1497
+ };
1498
+ const expired: ContradictionPair = {
1499
+ ...active,
1500
+ pairId: "expired-deferral",
1501
+ deferredUntil: new Date(now - 60_000).toISOString(),
1502
+ };
1503
+
1504
+ assert.equal(isCoolingDown(active, 14), true);
1505
+ assert.equal(isCoolingDown(expired, 14), false);
1506
+ });
1507
+
1508
+ // ── Resolution verbs ───────────────────────────────────────────────────────────
1509
+
1510
+ test("isValidResolutionVerb accepts valid verbs", () => {
1511
+ assert.equal(isValidResolutionVerb("keep-a"), true);
1512
+ assert.equal(isValidResolutionVerb("keep-b"), true);
1513
+ assert.equal(isValidResolutionVerb("merge"), true);
1514
+ assert.equal(isValidResolutionVerb("both-valid"), true);
1515
+ assert.equal(isValidResolutionVerb("needs-more-context"), true);
1516
+ });
1517
+
1518
+ test("isValidResolutionVerb rejects invalid verbs", () => {
1519
+ assert.equal(isValidResolutionVerb("delete"), false);
1520
+ assert.equal(isValidResolutionVerb(""), false);
1521
+ assert.equal(isValidResolutionVerb("unknown"), false);
1522
+ });
1523
+
1524
+ test("executeResolution rejects invalid runtime verbs without poisoning the pair", async () => {
1525
+ const { dir, cleanup } = await makeTempDir();
1526
+ try {
1527
+ const written = writePair(dir, makePair());
1528
+ const storage = makeResolutionStorage();
1529
+
1530
+ await assert.rejects(
1531
+ () => executeResolution(dir, storage, written.pairId, "delete" as never),
1532
+ /Invalid contradiction resolution verb: delete/,
1533
+ );
1534
+
1535
+ assert.deepEqual(storage.supersedeCalls, []);
1536
+ assert.equal(readPair(dir, written.pairId)?.resolution, undefined);
1537
+
1538
+ const valid = await executeResolution(dir, storage, written.pairId, "keep-a");
1539
+
1540
+ assert.deepEqual(valid.affectedIds, ["mem-b-002"]);
1541
+ assert.equal(readPair(dir, written.pairId)?.resolution, "keep-a");
1542
+ } finally {
1543
+ await cleanup();
1544
+ }
1545
+ });
1546
+
1547
+ test("resolvePair rejects invalid runtime verbs without mutating the pair", async () => {
1548
+ const { dir, cleanup } = await makeTempDir();
1549
+ try {
1550
+ const written = writePair(dir, makePair());
1551
+
1552
+ assert.throws(
1553
+ () => resolvePair(dir, written.pairId, "delete" as never),
1554
+ /Invalid contradiction resolution verb: delete/,
1555
+ );
1556
+
1557
+ assert.equal(readPair(dir, written.pairId)?.resolution, undefined);
1558
+ assert.equal(resolvePair(dir, written.pairId, "both-valid")?.resolution, "both-valid");
1559
+ } finally {
1560
+ await cleanup();
1561
+ }
1562
+ });
1563
+
1564
+ test("executeResolution merge requires a real merged memory", async () => {
1565
+ const { dir, cleanup } = await makeTempDir();
1566
+ try {
1567
+ const written = writePair(dir, makePair());
1568
+ const storage = makeResolutionStorage();
1569
+
1570
+ const result = await executeResolution(dir, storage, written.pairId, "merge");
1571
+
1572
+ assert.deepEqual(storage.supersedeCalls, []);
1573
+ assert.match(result.message, /requires mergedMemoryId or mergedContent/);
1574
+ assert.equal(readPair(dir, written.pairId)?.resolution, undefined);
1575
+ } finally {
1576
+ await cleanup();
1577
+ }
1578
+ });
1579
+
1580
+ test("executeResolution merge rejects missing replacement before superseding sources", async () => {
1581
+ const { dir, cleanup } = await makeTempDir();
1582
+ try {
1583
+ const written = writePair(dir, makePair());
1584
+ const storage = makeResolutionStorage();
1585
+
1586
+ const result = await executeResolution(dir, storage, written.pairId, "merge", {
1587
+ mergedMemoryId: "missing-merged-memory",
1588
+ });
1589
+
1590
+ assert.deepEqual(storage.supersedeCalls, []);
1591
+ assert.match(result.message, /Merged memory missing-merged-memory not found/);
1592
+ assert.equal(storage.memories.get("mem-a-001")?.frontmatter.status, undefined);
1593
+ assert.equal(storage.memories.get("mem-b-002")?.frontmatter.status, undefined);
1594
+ assert.equal(readPair(dir, written.pairId)?.resolution, undefined);
1595
+ } finally {
1596
+ await cleanup();
1597
+ }
1598
+ });
1599
+
1600
+ test("executeResolution merge supersedes both sources to a verified merged memory", async () => {
1601
+ const { dir, cleanup } = await makeTempDir();
1602
+ try {
1603
+ const written = writePair(dir, makePair());
1604
+ const storage = makeResolutionStorage();
1605
+
1606
+ const result = await executeResolution(dir, storage, written.pairId, "merge", {
1607
+ mergedMemoryId: "mem-merged-003",
1608
+ });
1609
+
1610
+ assert.deepEqual(
1611
+ storage.supersedeCalls.map(({ oldId, newId }) => ({ oldId, newId })),
1612
+ [
1613
+ { oldId: "mem-a-001", newId: "mem-merged-003" },
1614
+ { oldId: "mem-b-002", newId: "mem-merged-003" },
1615
+ ],
1616
+ );
1617
+ assert.deepEqual(result.affectedIds, ["mem-a-001", "mem-b-002"]);
1618
+ assert.equal(storage.memories.get("mem-a-001")?.frontmatter.status, "superseded");
1619
+ assert.equal(storage.memories.get("mem-a-001")?.frontmatter.supersededBy, "mem-merged-003");
1620
+ assert.equal(storage.memories.get("mem-b-002")?.frontmatter.status, "superseded");
1621
+ assert.equal(storage.memories.get("mem-b-002")?.frontmatter.supersededBy, "mem-merged-003");
1622
+ assert.equal(readPair(dir, written.pairId)?.resolution, "merge");
1623
+ } finally {
1624
+ await cleanup();
1625
+ }
1626
+ });
1627
+
1628
+ test("executeResolution merge can create and verify a merged memory from content", async () => {
1629
+ const { dir, cleanup } = await makeTempDir();
1630
+ try {
1631
+ const written = writePair(dir, makePair());
1632
+ const storage = makeResolutionStorage();
1633
+
1634
+ const result = await executeResolution(dir, storage, written.pairId, "merge", {
1635
+ mergedContent: "merged canonical fact",
1636
+ });
1637
+
1638
+ const mergedId = storage.supersedeCalls[0]?.newId;
1639
+ assert.ok(mergedId);
1640
+ assert.deepEqual(result.affectedIds, ["mem-a-001", "mem-b-002"]);
1641
+ assert.equal(storage.memories.get(mergedId)?.content, "merged canonical fact");
1642
+ assert.deepEqual(storage.memories.get(mergedId)?.frontmatter.derived_from, ["mem-a-001", "mem-b-002"]);
1643
+ assert.equal(storage.memories.get(mergedId)?.frontmatter.derived_via, "merge");
1644
+ assert.equal(readPair(dir, written.pairId)?.resolution, "merge");
1645
+ } finally {
1646
+ await cleanup();
1647
+ }
1648
+ });
1649
+
1650
+ test("executeResolution merge rolls back the first supersession when the second fails", async () => {
1651
+ const { dir, cleanup } = await makeTempDir();
1652
+ try {
1653
+ const written = writePair(dir, makePair());
1654
+ const storage = makeResolutionStorage({ failSupersedeFor: "mem-b-002" });
1655
+
1656
+ const result = await executeResolution(dir, storage, written.pairId, "merge", {
1657
+ mergedMemoryId: "mem-merged-003",
1658
+ });
1659
+
1660
+ assert.deepEqual(
1661
+ storage.supersedeCalls.map(({ oldId, newId }) => ({ oldId, newId })),
1662
+ [
1663
+ { oldId: "mem-a-001", newId: "mem-merged-003" },
1664
+ { oldId: "mem-b-002", newId: "mem-merged-003" },
1665
+ ],
1666
+ );
1667
+ assert.match(result.message, /restored mem-a-001 and mem-b-002/);
1668
+ assert.deepEqual(result.affectedIds, []);
1669
+ assert.deepEqual(
1670
+ storage.frontmatterWrites.map(({ memoryId, lifecycle }) => ({
1671
+ memoryId,
1672
+ actor: lifecycle?.actor,
1673
+ reasonCode: lifecycle?.reasonCode,
1674
+ })),
1675
+ [
1676
+ {
1677
+ memoryId: "mem-a-001",
1678
+ actor: "contradiction-resolution",
1679
+ reasonCode: "contradiction-resolution:merge-rollback",
1680
+ },
1681
+ {
1682
+ memoryId: "mem-b-002",
1683
+ actor: "contradiction-resolution",
1684
+ reasonCode: "contradiction-resolution:merge-rollback",
1685
+ },
1686
+ ],
1687
+ );
1688
+ assert.equal(storage.memories.get("mem-a-001")?.frontmatter.status, undefined);
1689
+ assert.equal(storage.memories.get("mem-a-001")?.frontmatter.supersededBy, undefined);
1690
+ assert.equal(storage.memories.get("mem-b-002")?.frontmatter.status, undefined);
1691
+ assert.equal(readPair(dir, written.pairId)?.resolution, undefined);
1692
+ } finally {
1693
+ await cleanup();
1694
+ }
1695
+ });
1696
+
1697
+ test("executeResolution merge restores the second source after partial supersede failure", async () => {
1698
+ const { dir, cleanup } = await makeTempDir();
1699
+ try {
1700
+ const written = writePair(dir, makePair());
1701
+ const storage = makeResolutionStorage({ partialSupersedeBeforeFailureFor: "mem-b-002" });
1702
+
1703
+ const result = await executeResolution(dir, storage, written.pairId, "merge", {
1704
+ mergedContent: "merged canonical fact",
1705
+ });
1706
+
1707
+ const mergedId = storage.supersedeCalls[0]?.newId;
1708
+ assert.ok(mergedId);
1709
+ assert.match(result.message, /restored mem-a-001 and mem-b-002/);
1710
+ assert.deepEqual(result.affectedIds, []);
1711
+ assert.equal(storage.memories.get("mem-a-001")?.frontmatter.status, undefined);
1712
+ assert.equal(storage.memories.get("mem-b-002")?.frontmatter.status, undefined);
1713
+ assert.equal(storage.memories.has(mergedId), false);
1714
+ assert.deepEqual(
1715
+ storage.frontmatterWrites.map(({ memoryId, beforeStatus }) => ({ memoryId, beforeStatus })),
1716
+ [
1717
+ { memoryId: "mem-a-001", beforeStatus: "superseded" },
1718
+ { memoryId: "mem-b-002", beforeStatus: "superseded" },
1719
+ ],
1720
+ );
1721
+ assert.deepEqual(storage.removedFactHashIds, [mergedId]);
1722
+ assert.equal(readPair(dir, written.pairId)?.resolution, undefined);
1723
+ } finally {
1724
+ await cleanup();
1725
+ }
1726
+ });
1727
+
1728
+ test("executeResolution merge restores the first source after partial supersede failure", async () => {
1729
+ const { dir, cleanup } = await makeTempDir();
1730
+ try {
1731
+ const written = writePair(dir, makePair());
1732
+ const storage = makeResolutionStorage({ partialSupersedeBeforeFailureFor: "mem-a-001" });
1733
+
1734
+ const result = await executeResolution(dir, storage, written.pairId, "merge", {
1735
+ mergedContent: "merged canonical fact",
1736
+ });
1737
+
1738
+ const mergedId = storage.supersedeCalls[0]?.newId;
1739
+ assert.ok(mergedId);
1740
+ assert.match(result.message, /restored mem-a-001/);
1741
+ assert.deepEqual(result.affectedIds, []);
1742
+ assert.deepEqual(
1743
+ storage.frontmatterWrites.map(({ memoryId, lifecycle }) => ({
1744
+ memoryId,
1745
+ actor: lifecycle?.actor,
1746
+ reasonCode: lifecycle?.reasonCode,
1747
+ })),
1748
+ [
1749
+ {
1750
+ memoryId: "mem-a-001",
1751
+ actor: "contradiction-resolution",
1752
+ reasonCode: "contradiction-resolution:merge-rollback",
1753
+ },
1754
+ ],
1755
+ );
1756
+ assert.equal(storage.memories.get("mem-a-001")?.frontmatter.status, undefined);
1757
+ assert.equal(storage.memories.get("mem-a-001")?.frontmatter.supersededBy, undefined);
1758
+ assert.equal(storage.memories.get("mem-b-002")?.frontmatter.status, undefined);
1759
+ assert.equal(storage.memories.has(mergedId), false);
1760
+ assert.deepEqual(
1761
+ storage.frontmatterWrites.map(({ memoryId, beforeStatus }) => ({ memoryId, beforeStatus })),
1762
+ [{ memoryId: "mem-a-001", beforeStatus: "superseded" }],
1763
+ );
1764
+ assert.deepEqual(storage.removedFactHashIds, [mergedId]);
1765
+ assert.equal(readPair(dir, written.pairId)?.resolution, undefined);
1766
+ } finally {
1767
+ await cleanup();
1768
+ }
1769
+ });
1770
+
1771
+ test("executeResolution merge keeps created replacement when rollback fails", async () => {
1772
+ const { dir, cleanup } = await makeTempDir();
1773
+ try {
1774
+ const written = writePair(dir, makePair());
1775
+ const storage = makeResolutionStorage({
1776
+ failSupersedeFor: "mem-b-002",
1777
+ failRollbackFor: "mem-a-001",
1778
+ });
1779
+
1780
+ const result = await executeResolution(dir, storage, written.pairId, "merge", {
1781
+ mergedContent: "merged canonical fact",
1782
+ });
1783
+
1784
+ const mergedId = storage.supersedeCalls[0]?.newId;
1785
+ assert.ok(mergedId);
1786
+ assert.match(result.message, /rollback incomplete for mem-a-001/);
1787
+ assert.equal(storage.memories.get("mem-a-001")?.frontmatter.status, "superseded");
1788
+ assert.equal(storage.memories.get("mem-a-001")?.frontmatter.supersededBy, mergedId);
1789
+ assert.equal(storage.memories.get(mergedId)?.content, "merged canonical fact");
1790
+ assert.deepEqual(storage.removedFactHashIds, []);
1791
+ assert.equal(readPair(dir, written.pairId)?.resolution, undefined);
1792
+ } finally {
1793
+ await cleanup();
1794
+ }
1795
+ });
1796
+
1797
+ test("executeResolution keep-a does not supersede when the kept memory is missing", async () => {
1798
+ const { dir, cleanup } = await makeTempDir();
1799
+ try {
1800
+ const written = writePair(dir, makePair());
1801
+ const storage = makeResolutionStorage();
1802
+ storage.memories.delete("mem-a-001");
1803
+
1804
+ const result = await executeResolution(dir, storage, written.pairId, "keep-a");
1805
+
1806
+ assert.match(result.message, /Kept memory mem-a-001 not found/);
1807
+ assert.deepEqual(result.affectedIds, []);
1808
+ assert.deepEqual(storage.supersedeCalls, []);
1809
+ assert.equal(storage.memories.get("mem-b-002")?.frontmatter.status, undefined);
1810
+ assert.equal(readPair(dir, written.pairId)?.resolution, undefined);
1811
+ } finally {
1812
+ await cleanup();
1813
+ }
1814
+ });
1815
+
1816
+ test("executeResolution resolves namespaced pairs against namespace storage", async () => {
1817
+ const { dir, cleanup } = await makeTempDir();
1818
+ try {
1819
+ const rootStorage = makeResolutionStorage();
1820
+ rootStorage.memories.clear();
1821
+ const nsStorage = makeResolutionStorage();
1822
+ const written = writePair(dir, makePair({ namespace: "ns1" }));
1823
+
1824
+ const result = await executeResolution(dir, rootStorage, written.pairId, "keep-a", {
1825
+ storageForNamespace(namespace) {
1826
+ assert.equal(namespace, "ns1");
1827
+ return nsStorage;
1828
+ },
1829
+ });
1830
+
1831
+ assert.deepEqual(result.affectedIds, ["mem-b-002"]);
1832
+ assert.equal(rootStorage.supersedeCalls.length, 0);
1833
+ assert.deepEqual(nsStorage.supersedeCalls, [{
1834
+ oldId: "mem-b-002",
1835
+ newId: "mem-a-001",
1836
+ reason: "contradiction-resolution:keep-a",
1837
+ }]);
1838
+ assert.equal(readPair(dir, written.pairId)?.resolution, "keep-a");
1839
+ } finally {
1840
+ await cleanup();
1841
+ }
1842
+ });
1843
+
1844
+ test("executeResolution rejects namespaced pairs without a storage resolver", async () => {
1845
+ const { dir, cleanup } = await makeTempDir();
1846
+ try {
1847
+ const rootStorage = makeResolutionStorage();
1848
+ const written = writePair(dir, makePair({ namespace: "ns1" }));
1849
+
1850
+ await assert.rejects(
1851
+ () => executeResolution(dir, rootStorage, written.pairId, "keep-a"),
1852
+ /storageForNamespace/,
1853
+ );
1854
+ assert.equal(rootStorage.supersedeCalls.length, 0);
1855
+ assert.equal(readPair(dir, written.pairId)?.resolution, undefined);
1856
+ } finally {
1857
+ await cleanup();
1858
+ }
1859
+ });
1860
+
1861
+ test("executeResolution checks namespace resolver before reporting already resolved pairs", async () => {
1862
+ const { dir, cleanup } = await makeTempDir();
1863
+ try {
1864
+ const pair: ContradictionPair = {
1865
+ ...makePair({
1866
+ namespace: "team",
1867
+ resolution: "both-valid",
1868
+ lastReviewedAt: "2026-01-01T00:00:00.000Z",
1869
+ }),
1870
+ pairId: computePairId("mem-a-001", "mem-b-002", "team"),
1871
+ };
1872
+ await writeStoredPair(dir, pair);
1873
+ const storage = makeResolutionStorage();
1874
+ let resolverCalls = 0;
1875
+
1876
+ await assert.rejects(
1877
+ () => executeResolution(dir, storage, pair.pairId, "keep-a", {
1878
+ storageForNamespace(namespace) {
1879
+ resolverCalls += 1;
1880
+ assert.equal(namespace, "team");
1881
+ throw new Error("namespace denied");
1882
+ },
1883
+ }),
1884
+ /namespace denied/,
1885
+ );
1886
+
1887
+ assert.equal(resolverCalls, 1);
1888
+ assert.equal(storage.supersedeCalls.length, 0);
1889
+ } finally {
1890
+ await cleanup();
1891
+ }
1892
+ });
1893
+
1894
+ test("executeResolution resolves legacy unscoped pairs through default namespace storage", async () => {
1895
+ const { dir, cleanup } = await makeTempDir();
1896
+ try {
1897
+ const rootStorage = makeResolutionStorage();
1898
+ rootStorage.memories.clear();
1899
+ const defaultStorage = makeResolutionStorage();
1900
+ const written = writePair(dir, makePair());
1901
+
1902
+ const result = await executeResolution(dir, rootStorage, written.pairId, "keep-a", {
1903
+ storageForNamespace(namespace) {
1904
+ assert.equal(namespace, undefined);
1905
+ return defaultStorage;
1906
+ },
1907
+ });
1908
+
1909
+ assert.deepEqual(result.affectedIds, ["mem-b-002"]);
1910
+ assert.equal(rootStorage.supersedeCalls.length, 0);
1911
+ assert.deepEqual(defaultStorage.supersedeCalls, [{
1912
+ oldId: "mem-b-002",
1913
+ newId: "mem-a-001",
1914
+ reason: "contradiction-resolution:keep-a",
1915
+ }]);
1916
+ assert.equal(readPair(dir, written.pairId)?.resolution, "keep-a");
1917
+ } finally {
1918
+ await cleanup();
1919
+ }
1920
+ });
1921
+
1922
+ test("executeResolution keep-b does not supersede when the kept memory is inactive", async () => {
1923
+ const { dir, cleanup } = await makeTempDir();
1924
+ try {
1925
+ const written = writePair(dir, makePair());
1926
+ const storage = makeResolutionStorage();
1927
+ const keepB = storage.memories.get("mem-b-002");
1928
+ assert.ok(keepB);
1929
+ storage.memories.set("mem-b-002", {
1930
+ ...keepB,
1931
+ frontmatter: {
1932
+ ...keepB.frontmatter,
1933
+ status: "superseded",
1934
+ supersededBy: "replacement",
1935
+ },
1936
+ });
1937
+
1938
+ const result = await executeResolution(dir, storage, written.pairId, "keep-b");
1939
+
1940
+ assert.match(result.message, /Kept memory mem-b-002 is superseded/);
1941
+ assert.deepEqual(result.affectedIds, []);
1942
+ assert.deepEqual(storage.supersedeCalls, []);
1943
+ assert.equal(storage.memories.get("mem-a-001")?.frontmatter.status, undefined);
1944
+ assert.equal(readPair(dir, written.pairId)?.resolution, undefined);
1945
+ } finally {
1946
+ await cleanup();
1947
+ }
1948
+ });
1949
+
1950
+ test("executeResolution keep-a restores source after partial supersede failure", async () => {
1951
+ const { dir, cleanup } = await makeTempDir();
1952
+ try {
1953
+ const written = writePair(dir, makePair());
1954
+ const storage = makeResolutionStorage({ partialSupersedeBeforeFailureFor: "mem-b-002" });
1955
+
1956
+ const result = await executeResolution(dir, storage, written.pairId, "keep-a");
1957
+
1958
+ assert.match(result.message, /restored mem-b-002/);
1959
+ assert.deepEqual(result.affectedIds, []);
1960
+ assert.equal(storage.memories.get("mem-b-002")?.frontmatter.status, undefined);
1961
+ assert.equal(storage.memories.get("mem-b-002")?.frontmatter.supersededBy, undefined);
1962
+ assert.deepEqual(
1963
+ storage.frontmatterWrites.map(({ memoryId, beforeStatus, lifecycle }) => ({
1964
+ memoryId,
1965
+ beforeStatus,
1966
+ actor: lifecycle?.actor,
1967
+ reasonCode: lifecycle?.reasonCode,
1968
+ })),
1969
+ [
1970
+ {
1971
+ memoryId: "mem-b-002",
1972
+ beforeStatus: "superseded",
1973
+ actor: "contradiction-resolution",
1974
+ reasonCode: "contradiction-resolution:keep-a-rollback",
1975
+ },
1976
+ ],
1977
+ );
1978
+ assert.equal(readPair(dir, written.pairId)?.resolution, undefined);
1979
+ } finally {
1980
+ await cleanup();
1981
+ }
1982
+ });
1983
+
1984
+ test("executeResolution keep-b restores source after partial supersede failure", async () => {
1985
+ const { dir, cleanup } = await makeTempDir();
1986
+ try {
1987
+ const written = writePair(dir, makePair());
1988
+ const storage = makeResolutionStorage({ partialSupersedeBeforeFailureFor: "mem-a-001" });
1989
+
1990
+ const result = await executeResolution(dir, storage, written.pairId, "keep-b");
1991
+
1992
+ assert.match(result.message, /restored mem-a-001/);
1993
+ assert.deepEqual(result.affectedIds, []);
1994
+ assert.equal(storage.memories.get("mem-a-001")?.frontmatter.status, undefined);
1995
+ assert.equal(storage.memories.get("mem-a-001")?.frontmatter.supersededBy, undefined);
1996
+ assert.deepEqual(
1997
+ storage.frontmatterWrites.map(({ memoryId, beforeStatus, lifecycle }) => ({
1998
+ memoryId,
1999
+ beforeStatus,
2000
+ actor: lifecycle?.actor,
2001
+ reasonCode: lifecycle?.reasonCode,
2002
+ })),
2003
+ [
2004
+ {
2005
+ memoryId: "mem-a-001",
2006
+ beforeStatus: "superseded",
2007
+ actor: "contradiction-resolution",
2008
+ reasonCode: "contradiction-resolution:keep-b-rollback",
2009
+ },
2010
+ ],
2011
+ );
2012
+ assert.equal(readPair(dir, written.pairId)?.resolution, undefined);
2013
+ } finally {
2014
+ await cleanup();
2015
+ }
2016
+ });
2017
+
2018
+ test("executeResolution needs-more-context defers without terminal resolution", async () => {
2019
+ const { dir, cleanup } = await makeTempDir();
2020
+ try {
2021
+ const written = writePair(dir, makePair());
2022
+ const storage = makeResolutionStorage();
2023
+
2024
+ const result = await executeResolution(dir, storage, written.pairId, "needs-more-context");
2025
+ const deferred = readPair(dir, written.pairId);
2026
+
2027
+ assert.deepEqual(result.affectedIds, []);
2028
+ assert.match(result.message, /Deferred/);
2029
+ assert.ok(deferred?.lastReviewedAt);
2030
+ assert.ok(deferred?.deferredUntil);
2031
+ assert.equal(deferred?.resolution, undefined);
2032
+ assert.equal(listPairs(dir, { filter: "unresolved" }).total, 0);
2033
+ assert.equal(listPairs(dir, { filter: "all" }).total, 1);
2034
+ } finally {
2035
+ await cleanup();
2036
+ }
2037
+ });
2038
+
2039
+ test("expired needs-more-context deferral returns to unresolved and can be refreshed", async () => {
2040
+ const { dir, cleanup } = await makeTempDir();
2041
+ try {
2042
+ const written = writePair(dir, makePair({ confidence: 0.95 }));
2043
+ const deferred = resolvePair(dir, written.pairId, "needs-more-context");
2044
+ assert.ok(deferred);
2045
+
2046
+ const expiredAt = new Date(Date.now() - 60_000).toISOString();
2047
+ await writeStoredPair(dir, {
2048
+ ...deferred!,
2049
+ lastReviewedAt: expiredAt,
2050
+ deferredUntil: expiredAt,
2051
+ });
2052
+
2053
+ assert.equal(listPairs(dir, { filter: "unresolved" }).total, 1);
2054
+
2055
+ const refreshed = writePair(dir, makePair({
2056
+ confidence: 0.5,
2057
+ verdict: "duplicates",
2058
+ rationale: "Fresh judge result after deferral expiry",
2059
+ }));
2060
+
2061
+ assert.equal(refreshed.confidence, 0.5);
2062
+ assert.equal(refreshed.verdict, "duplicates");
2063
+ assert.equal(refreshed.resolution, undefined);
2064
+ assert.equal(refreshed.deferredUntil, undefined);
2065
+ assert.equal(readPair(dir, written.pairId)?.deferredUntil, undefined);
2066
+ } finally {
2067
+ await cleanup();
2068
+ }
2069
+ });
2070
+
2071
+ test("legacy needs-more-context resolutions honor cooldown before returning to unresolved", async () => {
2072
+ const { dir, cleanup } = await makeTempDir();
2073
+ try {
2074
+ const written = writePair(dir, makePair());
2075
+
2076
+ await writeStoredPair(dir, {
2077
+ ...written,
2078
+ lastReviewedAt: new Date().toISOString(),
2079
+ resolution: "needs-more-context",
2080
+ });
2081
+ assert.equal(listPairs(dir, { filter: "unresolved" }).total, 0);
2082
+
2083
+ await writeStoredPair(dir, {
2084
+ ...written,
2085
+ lastReviewedAt: new Date(Date.now() - 25 * 60 * 60 * 1000).toISOString(),
2086
+ resolution: "needs-more-context",
2087
+ });
2088
+ assert.equal(listPairs(dir, { filter: "unresolved" }).total, 1);
2089
+ } finally {
2090
+ await cleanup();
2091
+ }
2092
+ });
2093
+
2094
+ // ── resolvePair ────────────────────────────────────────────────────────────────
2095
+
2096
+ test("resolvePair sets resolution and lastReviewedAt", async () => {
2097
+ const { dir, cleanup } = await makeTempDir();
2098
+ try {
2099
+ const written = writePair(dir, makePair());
2100
+ const resolved = resolvePair(dir, written.pairId, "both-valid");
2101
+ assert.ok(resolved);
2102
+ assert.equal(resolved!.resolution, "both-valid");
2103
+ assert.ok(resolved!.lastReviewedAt);
2104
+ } finally {
2105
+ await cleanup();
2106
+ }
2107
+ });
2108
+
2109
+ test("needs-more-context deferral does not clear terminal resolutions", async () => {
2110
+ const { dir, cleanup } = await makeTempDir();
2111
+ try {
2112
+ const keepPair = writePair(dir, makePair());
2113
+ const keepResolved = resolvePair(dir, keepPair.pairId, "keep-a");
2114
+ assert.equal(keepResolved?.resolution, "keep-a");
2115
+
2116
+ const deferredKeepViaResolve = resolvePair(dir, keepPair.pairId, "needs-more-context");
2117
+ assert.equal(deferredKeepViaResolve?.resolution, "keep-a");
2118
+ assert.equal(deferredKeepViaResolve?.deferredUntil, undefined);
2119
+
2120
+ const deferredKeepDirectly = deferPair(dir, keepPair.pairId);
2121
+ assert.equal(deferredKeepDirectly?.resolution, "keep-a");
2122
+ assert.equal(deferredKeepDirectly?.deferredUntil, undefined);
2123
+
2124
+ const bothValidPair = writePair(dir, makePair({ memoryIds: ["mem-a-003", "mem-b-004"] }));
2125
+ const bothValidResolved = resolvePair(dir, bothValidPair.pairId, "both-valid");
2126
+ assert.equal(bothValidResolved?.resolution, "both-valid");
2127
+
2128
+ const deferredBothValidViaResolve = resolvePair(dir, bothValidPair.pairId, "needs-more-context");
2129
+ assert.equal(deferredBothValidViaResolve?.resolution, "both-valid");
2130
+ assert.equal(deferredBothValidViaResolve?.deferredUntil, undefined);
2131
+
2132
+ const deferredBothValidDirectly = deferPair(dir, bothValidPair.pairId);
2133
+ assert.equal(deferredBothValidDirectly?.resolution, "both-valid");
2134
+ assert.equal(deferredBothValidDirectly?.deferredUntil, undefined);
2135
+ assert.equal(listPairs(dir, { filter: "unresolved" }).total, 0);
2136
+ } finally {
2137
+ await cleanup();
2138
+ }
2139
+ });
2140
+
2141
+ test("resolvePair does not overwrite terminal resolutions", async () => {
2142
+ const { dir, cleanup } = await makeTempDir();
2143
+ try {
2144
+ const written = writePair(dir, makePair());
2145
+ const first = resolvePair(dir, written.pairId, "keep-a");
2146
+ assert.equal(first?.resolution, "keep-a");
2147
+ assert.ok(first?.lastReviewedAt);
2148
+
2149
+ const second = resolvePair(dir, written.pairId, "keep-b");
2150
+ assert.equal(second?.resolution, "keep-a");
2151
+ assert.equal(second?.lastReviewedAt, first?.lastReviewedAt);
2152
+
2153
+ const third = resolvePair(dir, written.pairId, "merge");
2154
+ assert.equal(third?.resolution, "keep-a");
2155
+ assert.equal(third?.lastReviewedAt, first?.lastReviewedAt);
2156
+
2157
+ const stored = readPair(dir, written.pairId);
2158
+ assert.equal(stored?.resolution, "keep-a");
2159
+ assert.equal(stored?.lastReviewedAt, first?.lastReviewedAt);
2160
+ } finally {
2161
+ await cleanup();
2162
+ }
2163
+ });
2164
+
2165
+ test("resolvePair returns null for nonexistent pair", async () => {
2166
+ const { dir, cleanup } = await makeTempDir();
2167
+ try {
2168
+ const result = resolvePair(dir, "nonexistent", "both-valid");
2169
+ assert.equal(result, null);
2170
+ } finally {
2171
+ await cleanup();
2172
+ }
2173
+ });
2174
+
2175
+ // ── ACTIVE_STATUSES (rule 53) ──────────────────────────────────────────────────
2176
+
2177
+ test("ACTIVE_STATUSES contains only active", () => {
2178
+ assert.ok(ACTIVE_STATUSES.has("active"));
2179
+ assert.equal(ACTIVE_STATUSES.has("superseded"), false);
2180
+ assert.equal(ACTIVE_STATUSES.has("archived"), false);
2181
+ assert.equal(ACTIVE_STATUSES.has("quarantined"), false);
2182
+ assert.equal(ACTIVE_STATUSES.has("rejected"), false);
2183
+ assert.equal(ACTIVE_STATUSES.has("pending_review"), false);
2184
+ });
2185
+
2186
+ // ── Judge helper: pairKey ──────────────────────────────────────────────────────
2187
+
2188
+ test("pairKey is order-independent", () => {
2189
+ assert.equal(_pairKey("a", "b"), _pairKey("b", "a"));
2190
+ });
2191
+
2192
+ // ── Judge helper: contentHash ──────────────────────────────────────────────────
2193
+
2194
+ test("contentHash is deterministic", () => {
2195
+ const a = { memoryIdA: "1", memoryIdB: "2", textA: "hello", textB: "world" };
2196
+ const b = { memoryIdA: "1", memoryIdB: "2", textA: "hello", textB: "world" };
2197
+ assert.equal(_contentHash(a), _contentHash(b));
2198
+ });
2199
+
2200
+ test("contentHash differs for different content", () => {
2201
+ const a = { memoryIdA: "1", memoryIdB: "2", textA: "hello", textB: "world" };
2202
+ const b = { memoryIdA: "1", memoryIdB: "2", textA: "goodbye", textB: "world" };
2203
+ assert.notEqual(_contentHash(a), _contentHash(b));
2204
+ });
2205
+
2206
+ // ── JSON parse safety (rule 18) ────────────────────────────────────────────────
2207
+
2208
+ test("readPair returns null for invalid JSON", async () => {
2209
+ const { dir, cleanup } = await makeTempDir();
2210
+ try {
2211
+ const reviewDir = path.join(dir, ".review", "contradictions");
2212
+ await mkdir(reviewDir, { recursive: true });
2213
+ await writeFile(path.join(reviewDir, "test-id.json"), "null");
2214
+ assert.equal(readPair(dir, "test-id"), null, "JSON.parse('null') should not be a valid pair");
2215
+ } finally {
2216
+ await cleanup();
2217
+ }
2218
+ });
2219
+
2220
+ test("readPair returns null for non-object JSON", async () => {
2221
+ const { dir, cleanup } = await makeTempDir();
2222
+ try {
2223
+ const reviewDir = path.join(dir, ".review", "contradictions");
2224
+ await mkdir(reviewDir, { recursive: true });
2225
+ await writeFile(path.join(reviewDir, "test-id.json"), '"a string"');
2226
+ assert.equal(readPair(dir, "test-id"), null);
2227
+ } finally {
2228
+ await cleanup();
2229
+ }
2230
+ });