@remnic/core 10.0.3 → 10.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (410) hide show
  1. package/dist/access-admin-ops-surface.js +62 -62
  2. package/dist/access-authorization-probe.js +63 -63
  3. package/dist/access-boundary.js +62 -62
  4. package/dist/access-cli.d.ts.map +1 -1
  5. package/dist/access-cli.js +146 -139
  6. package/dist/access-cli.js.map +1 -1
  7. package/dist/access-extraction-force-flush.js +62 -62
  8. package/dist/access-http-briefing.js +63 -63
  9. package/dist/access-http-query.js +64 -64
  10. package/dist/access-http.d.ts.map +1 -1
  11. package/dist/access-http.js +86 -85
  12. package/dist/access-identity-continuity-surface.js +62 -62
  13. package/dist/access-lcm-surface.js +62 -62
  14. package/dist/access-mcp-correction-tools.d.ts +10 -0
  15. package/dist/access-mcp-correction-tools.d.ts.map +1 -0
  16. package/dist/access-mcp-correction-tools.js +8 -0
  17. package/dist/access-mcp.d.ts.map +1 -1
  18. package/dist/access-mcp.js +76 -75
  19. package/dist/access-namespace-preflight.js +62 -62
  20. package/dist/access-observe-write-category.js +5 -5
  21. package/dist/access-observe-write-surface.js +62 -62
  22. package/dist/access-offline-manifest.js +8 -8
  23. package/dist/access-operations-batch.js +65 -65
  24. package/dist/access-operations.d.ts +1 -0
  25. package/dist/access-operations.d.ts.map +1 -1
  26. package/dist/access-operations.js +72 -72
  27. package/dist/access-recall-concurrency.js +62 -62
  28. package/dist/access-recall-diagnostics.js +2 -2
  29. package/dist/access-recall-response.js +62 -62
  30. package/dist/access-recall-surface.js +62 -62
  31. package/dist/access-service.d.ts.map +1 -1
  32. package/dist/access-service.js +62 -62
  33. package/dist/access-surface-catalog.js +64 -64
  34. package/dist/active-recall.js +31 -30
  35. package/dist/active-recall.js.map +1 -1
  36. package/dist/adapters/index.js +7 -7
  37. package/dist/adapters/registry.js +3 -3
  38. package/dist/{auto-sync-PAWBFQWL.js → auto-sync-FN7E3OTO.js} +6 -6
  39. package/dist/briefing.js +26 -26
  40. package/dist/buffer.js +8 -8
  41. package/dist/causal-consolidation.js +26 -26
  42. package/dist/{chunk-YQSWNFZE.js → chunk-2CP577K6.js} +2 -2
  43. package/dist/{chunk-6JIHC5AS.js → chunk-37HCPM56.js} +78 -67
  44. package/dist/chunk-37HCPM56.js.map +1 -0
  45. package/dist/{chunk-345MEMRU.js → chunk-3OUGSOJP.js} +2 -2
  46. package/dist/{chunk-CHI37EHP.js → chunk-4CWUZBPF.js} +8 -6
  47. package/dist/chunk-4CWUZBPF.js.map +1 -0
  48. package/dist/{chunk-G2STTRYB.js → chunk-4D2YH47Z.js} +2 -2
  49. package/dist/{chunk-IXYIW3MZ.js → chunk-4K2H4KTR.js} +5 -5
  50. package/dist/{chunk-UVVSOSHL.js → chunk-52CQKST6.js} +53 -53
  51. package/dist/{chunk-H7BZBSP6.js → chunk-52II7PB6.js} +4 -4
  52. package/dist/{chunk-BLHPADUX.js → chunk-5BPXMAUP.js} +22 -78
  53. package/dist/chunk-5BPXMAUP.js.map +1 -0
  54. package/dist/{chunk-ZS7RK6H6.js → chunk-5BY3IA2U.js} +16 -53
  55. package/dist/chunk-5BY3IA2U.js.map +1 -0
  56. package/dist/{chunk-2QZFZNXO.js → chunk-5CQO6LVM.js} +2 -2
  57. package/dist/{chunk-NLDMTXWV.js → chunk-5LNPW7NE.js} +2 -2
  58. package/dist/{chunk-WHTMVTU4.js → chunk-5X4ZJESN.js} +2 -2
  59. package/dist/{chunk-WI37MWRZ.js → chunk-63UNVGZW.js} +5 -5
  60. package/dist/{chunk-G3T6YMBO.js → chunk-64S6X4IU.js} +7 -7
  61. package/dist/{chunk-CFCEJNOE.js → chunk-6KHF6PAB.js} +2 -2
  62. package/dist/{chunk-5GINB5LC.js → chunk-6MKLMEBE.js} +1 -1
  63. package/dist/{chunk-5GINB5LC.js.map → chunk-6MKLMEBE.js.map} +1 -1
  64. package/dist/{chunk-35A7GCHG.js → chunk-6T42L5FI.js} +2 -2
  65. package/dist/{chunk-JDOBIFBK.js → chunk-7CXL25AA.js} +2 -2
  66. package/dist/{chunk-YLBE6PLR.js → chunk-7IGMKQWK.js} +2 -2
  67. package/dist/{chunk-CSLK7BN6.js → chunk-7LYRFI5A.js} +2 -2
  68. package/dist/{chunk-IB63OVUB.js → chunk-AJ6ORARY.js} +6 -6
  69. package/dist/{chunk-CGOKNQDK.js → chunk-ANZXWOYD.js} +2 -2
  70. package/dist/{chunk-5QXMESS7.js → chunk-AXC7UTLM.js} +2 -2
  71. package/dist/{chunk-RFIJRZ4K.js → chunk-B657ZGDH.js} +2 -2
  72. package/dist/{chunk-AW4QUFQF.js → chunk-BTNNL7ZW.js} +3 -2
  73. package/dist/{chunk-AW4QUFQF.js.map → chunk-BTNNL7ZW.js.map} +1 -1
  74. package/dist/{chunk-MY7B3HYC.js → chunk-CLCMDKTB.js} +2 -2
  75. package/dist/{chunk-QPWUG2S3.js → chunk-CYEK6Z3P.js} +4 -4
  76. package/dist/{chunk-IHCYCE6D.js → chunk-DJMVSUPK.js} +4 -4
  77. package/dist/{chunk-HP4CU2ZA.js → chunk-DST7HRSG.js} +2 -2
  78. package/dist/{chunk-IIFFC3RL.js → chunk-EDR6CVWZ.js} +2 -2
  79. package/dist/{chunk-AUWMKDKL.js → chunk-EMVJU7WC.js} +2 -2
  80. package/dist/{chunk-O6AYMAPJ.js → chunk-ENNC3RZ6.js} +2 -2
  81. package/dist/{chunk-2JRB3Z5N.js → chunk-EP5WXE2G.js} +3 -3
  82. package/dist/{chunk-QLK3SL7Q.js → chunk-ETSJD5IV.js} +131 -12
  83. package/dist/chunk-ETSJD5IV.js.map +1 -0
  84. package/dist/chunk-EWMRFW3F.js +38 -0
  85. package/dist/chunk-EWMRFW3F.js.map +1 -0
  86. package/dist/{chunk-I2KEH2LS.js → chunk-FC6RCOIU.js} +2 -2
  87. package/dist/{chunk-OZVHLBH6.js → chunk-FLV7M7CT.js} +2 -2
  88. package/dist/{chunk-Q6GI7HEC.js → chunk-FRH2UC7Q.js} +2 -2
  89. package/dist/{chunk-3SL52JKD.js → chunk-FZVROZKC.js} +5 -5
  90. package/dist/{chunk-2EZB2DL5.js → chunk-GE6HETIF.js} +3 -3
  91. package/dist/{chunk-2DHJTJIY.js → chunk-GEGUBU3D.js} +2 -2
  92. package/dist/{chunk-6AA7XFMO.js → chunk-GF4H3B3R.js} +8 -8
  93. package/dist/{chunk-NGOZH7R5.js → chunk-GVUW5XK5.js} +311 -142
  94. package/dist/chunk-GVUW5XK5.js.map +1 -0
  95. package/dist/{chunk-ME2LMFHF.js → chunk-HPAOMYKM.js} +92 -92
  96. package/dist/{chunk-4NRZ7BRS.js → chunk-I25RINZK.js} +2 -2
  97. package/dist/{chunk-XG4XXI66.js → chunk-I25RQA65.js} +2 -2
  98. package/dist/chunk-I56MTWE7.js +80 -0
  99. package/dist/chunk-I56MTWE7.js.map +1 -0
  100. package/dist/{chunk-EJJMDLVB.js → chunk-IJ4FEGZR.js} +2 -2
  101. package/dist/{chunk-EUL3S3LE.js → chunk-J5WI4QRP.js} +4 -4
  102. package/dist/{chunk-LMMC55WM.js → chunk-JA54KIYD.js} +4 -4
  103. package/dist/{chunk-5FLFPTDK.js → chunk-JA72X46J.js} +2 -2
  104. package/dist/{chunk-6GU3TNJJ.js → chunk-JMF5Q4JY.js} +246 -49
  105. package/dist/chunk-JMF5Q4JY.js.map +1 -0
  106. package/dist/{chunk-IDSSDL4W.js → chunk-JXSYWTFK.js} +21 -4
  107. package/dist/{chunk-IDSSDL4W.js.map → chunk-JXSYWTFK.js.map} +1 -1
  108. package/dist/{chunk-NLYOOGZ7.js → chunk-KE5PWLI6.js} +3 -3
  109. package/dist/chunk-KIUVEMBI.js +49 -0
  110. package/dist/chunk-KIUVEMBI.js.map +1 -0
  111. package/dist/{chunk-4DDIWRT7.js → chunk-KQI2PKYP.js} +2 -2
  112. package/dist/{chunk-Y2ADLCB3.js → chunk-KSUOM3YU.js} +9 -9
  113. package/dist/{chunk-BTOHGPHC.js → chunk-KZEMFD6E.js} +3 -3
  114. package/dist/{chunk-NXVD46HT.js → chunk-L2VS27PZ.js} +4 -4
  115. package/dist/{chunk-MYYHACOW.js → chunk-L34W4W4I.js} +2 -2
  116. package/dist/{chunk-KRTIHXWC.js → chunk-L3PWXD73.js} +2 -2
  117. package/dist/{chunk-NQHSXHJP.js → chunk-L6GNS5GB.js} +2 -2
  118. package/dist/{chunk-44PBRUXB.js → chunk-M47Q6566.js} +2 -2
  119. package/dist/{chunk-E7FN5N5E.js → chunk-MQNOIH2C.js} +7 -7
  120. package/dist/{chunk-IDSZNHIP.js → chunk-MULNBSPP.js} +4 -4
  121. package/dist/{chunk-RKSGUMVL.js → chunk-NBQIFCJE.js} +2 -2
  122. package/dist/{chunk-I6WFBNA4.js → chunk-NHSVW7UT.js} +15 -15
  123. package/dist/{chunk-32HO62I4.js → chunk-OFEHITAZ.js} +2 -2
  124. package/dist/{chunk-PCO3P7WJ.js → chunk-OGVJXIHX.js} +2 -2
  125. package/dist/{chunk-RYN4AIRM.js → chunk-OZABSIOV.js} +4 -4
  126. package/dist/{chunk-HO7IQP7G.js → chunk-QMFKW4OU.js} +3 -3
  127. package/dist/{chunk-34G4U6HS.js → chunk-QRZMJ2WN.js} +2 -2
  128. package/dist/{chunk-RKDSELA3.js → chunk-QWWMS4AE.js} +1 -1
  129. package/dist/chunk-QWWMS4AE.js.map +1 -0
  130. package/dist/{chunk-GUD6FYQG.js → chunk-RSMIRLKM.js} +2 -2
  131. package/dist/{chunk-TNVZCLJU.js → chunk-S5TGRZWY.js} +2 -2
  132. package/dist/{chunk-O24EWFPQ.js → chunk-SNXBXYUE.js} +3 -3
  133. package/dist/{chunk-KW77LGDX.js → chunk-SUAX5JWY.js} +2 -2
  134. package/dist/{chunk-PNFWIB4X.js → chunk-SWRN6U7Q.js} +2 -2
  135. package/dist/{chunk-X6X4UASX.js → chunk-SZXPKUMN.js} +232 -83
  136. package/dist/chunk-SZXPKUMN.js.map +1 -0
  137. package/dist/{chunk-R4NGLTUS.js → chunk-TDMNADPI.js} +2 -2
  138. package/dist/{chunk-QCP75JGO.js → chunk-TFA6HPOA.js} +5 -5
  139. package/dist/{chunk-LI76ESJL.js → chunk-TZQOCQXB.js} +2 -2
  140. package/dist/{chunk-OV7EYM6M.js → chunk-U6OXJQEH.js} +12 -12
  141. package/dist/{chunk-OWHPA4JS.js → chunk-V32NHP2R.js} +2 -2
  142. package/dist/{chunk-JSUA4YFE.js → chunk-WG4TMZJ2.js} +2 -2
  143. package/dist/{chunk-DQTCGVFK.js → chunk-WHCD4Z3D.js} +2 -2
  144. package/dist/{chunk-GBA4N2SG.js → chunk-WRICYGYG.js} +27 -26
  145. package/dist/chunk-WRICYGYG.js.map +1 -0
  146. package/dist/{chunk-KATEWTQJ.js → chunk-X7J56GPG.js} +2 -2
  147. package/dist/{chunk-7KICGR5W.js → chunk-XPRAOTJY.js} +2 -2
  148. package/dist/{chunk-2NV7MMMM.js → chunk-XQSJXNWC.js} +2 -2
  149. package/dist/{chunk-22DYJLFN.js → chunk-XVC7JU2N.js} +39 -18
  150. package/dist/chunk-XVC7JU2N.js.map +1 -0
  151. package/dist/{chunk-RXT6UB25.js → chunk-YJAOYEWI.js} +2 -2
  152. package/dist/{chunk-L6DJJEFW.js → chunk-YJEUHGZZ.js} +2 -2
  153. package/dist/{chunk-AXFWMRKI.js → chunk-YQJCWR4R.js} +2 -2
  154. package/dist/cli.js +110 -108
  155. package/dist/coding/export-okf-codegraph.js +25 -25
  156. package/dist/compounding/engine.js +25 -25
  157. package/dist/config.d.ts.map +1 -1
  158. package/dist/config.js +31 -30
  159. package/dist/connectors/codex-materialize-runner.js +25 -25
  160. package/dist/connectors/index.js +25 -25
  161. package/dist/consolidation-provenance-check.js +2 -2
  162. package/dist/contradiction/index.js +7 -7
  163. package/dist/convergence-refresh.js +27 -27
  164. package/dist/conversation-index/backend.js +2 -2
  165. package/dist/corpus-read-cancellation.d.ts +7 -0
  166. package/dist/corpus-read-cancellation.d.ts.map +1 -1
  167. package/dist/corpus-read-cancellation.js +1 -1
  168. package/dist/corpus-watermark.js +27 -27
  169. package/dist/correction/correction-access-wiring.d.ts +6 -6
  170. package/dist/correction/correction-access-wiring.d.ts.map +1 -1
  171. package/dist/correction/correction-classify.d.ts +25 -0
  172. package/dist/correction/correction-classify.d.ts.map +1 -0
  173. package/dist/correction/correction-config.d.ts +11 -0
  174. package/dist/correction/correction-config.d.ts.map +1 -0
  175. package/dist/correction/correction-contract.d.ts +13 -1
  176. package/dist/correction/correction-contract.d.ts.map +1 -1
  177. package/dist/correction/correction-executor.d.ts +2 -0
  178. package/dist/correction/correction-executor.d.ts.map +1 -1
  179. package/dist/correction/correction-planner.d.ts +24 -3
  180. package/dist/correction/correction-planner.d.ts.map +1 -1
  181. package/dist/directory-sidecars.js +2 -2
  182. package/dist/entity-retrieval.js +25 -25
  183. package/dist/event-order-recall.js +2 -2
  184. package/dist/explicit-capture.js +2 -2
  185. package/dist/external-wiki-access.js +63 -63
  186. package/dist/extraction-span-materialize.js +2 -2
  187. package/dist/extraction.js +34 -34
  188. package/dist/harmonic-retrieval.js +25 -25
  189. package/dist/index.js +221 -218
  190. package/dist/lcm/index.js +3 -3
  191. package/dist/local-llm.d.ts.map +1 -1
  192. package/dist/local-llm.js +1 -1
  193. package/dist/location/index.js +28 -28
  194. package/dist/maintenance/archive-observations.js +2 -2
  195. package/dist/maintenance/atomic-file.d.ts +1 -1
  196. package/dist/maintenance/atomic-file.d.ts.map +1 -1
  197. package/dist/maintenance/atomic-file.js +1 -1
  198. package/dist/maintenance/memory-governance.js +25 -25
  199. package/dist/maintenance/migrate-observations.js +3 -3
  200. package/dist/maintenance/observation-ledger-utils.js +2 -2
  201. package/dist/maintenance/projection-rebuild-abort.d.ts +17 -0
  202. package/dist/maintenance/projection-rebuild-abort.d.ts.map +1 -0
  203. package/dist/maintenance/projection-timeline.d.ts +19 -0
  204. package/dist/maintenance/projection-timeline.d.ts.map +1 -0
  205. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +25 -25
  206. package/dist/maintenance/rebuild-memory-projection-runner.d.ts +8 -0
  207. package/dist/maintenance/rebuild-memory-projection-runner.d.ts.map +1 -0
  208. package/dist/maintenance/rebuild-memory-projection-runner.js +113 -0
  209. package/dist/maintenance/rebuild-memory-projection-runner.js.map +1 -0
  210. package/dist/maintenance/rebuild-memory-projection.d.ts +8 -0
  211. package/dist/maintenance/rebuild-memory-projection.d.ts.map +1 -1
  212. package/dist/maintenance/rebuild-memory-projection.js +26 -26
  213. package/dist/maintenance/rebuild-observations.js +3 -3
  214. package/dist/memory-browse-operations.js +63 -63
  215. package/dist/memory-browse.js +7 -7
  216. package/dist/memory-subject.js +1 -1
  217. package/dist/namespaces/migrate.js +26 -26
  218. package/dist/namespaces/search.js +10 -10
  219. package/dist/namespaces/storage.js +25 -25
  220. package/dist/offline-sync-impression-drain.js +3 -3
  221. package/dist/operator-doctor-corpus.js +28 -28
  222. package/dist/operator-toolkit.js +41 -40
  223. package/dist/orchestration/full-corpus-heap-guard.d.ts +25 -0
  224. package/dist/orchestration/full-corpus-heap-guard.d.ts.map +1 -0
  225. package/dist/orchestration/maintenance.d.ts.map +1 -1
  226. package/dist/orchestration/maintenance.js +38 -36
  227. package/dist/orchestration/projection-rebuild-schedule.d.ts +40 -0
  228. package/dist/orchestration/projection-rebuild-schedule.d.ts.map +1 -1
  229. package/dist/orchestration/session-context.d.ts.map +1 -1
  230. package/dist/orchestrator.js +142 -139
  231. package/dist/projection-rebuild-config.d.ts +52 -0
  232. package/dist/projection-rebuild-config.d.ts.map +1 -0
  233. package/dist/projection-rebuild-config.js +14 -0
  234. package/dist/projection-rebuild-config.js.map +1 -0
  235. package/dist/qmd.js +4 -4
  236. package/dist/recall-explain-renderer.js +3 -3
  237. package/dist/recall-navigate-access.js +2 -2
  238. package/dist/recall-navigate-disclosure.js +2 -2
  239. package/dist/recall-navigate.js +2 -2
  240. package/dist/recall-navigation-operations.js +63 -63
  241. package/dist/recall-navigation.js +62 -62
  242. package/dist/recall-state-view-admission.js +7 -7
  243. package/dist/recall-state.js +2 -2
  244. package/dist/recall-why-service.js +8 -8
  245. package/dist/recall-xray-cli.js +4 -4
  246. package/dist/recall-xray-renderer.js +3 -3
  247. package/dist/recall-xray.js +2 -2
  248. package/dist/reconcile/manifest.js +3 -3
  249. package/dist/relevance.js +2 -2
  250. package/dist/{resolution-RSG4HZTL.js → resolution-TV3F7ZTH.js} +7 -7
  251. package/dist/resolution-TV3F7ZTH.js.map +1 -0
  252. package/dist/resume-bundles.js +32 -31
  253. package/dist/salvage-envelope.js +1 -1
  254. package/dist/search/factory.js +9 -9
  255. package/dist/search/index.js +17 -17
  256. package/dist/semantic-consolidation.js +31 -31
  257. package/dist/semantic-rule-promotion.js +25 -25
  258. package/dist/semantic-rule-verifier.js +25 -25
  259. package/dist/source-agent-qualifier.js +29 -29
  260. package/dist/standup/build.js +25 -25
  261. package/dist/storage/memory-lifecycle-ledger-access.d.ts +5 -3
  262. package/dist/storage/memory-lifecycle-ledger-access.d.ts.map +1 -1
  263. package/dist/storage/memory-read-store.d.ts +2 -2
  264. package/dist/storage/memory-read-store.d.ts.map +1 -1
  265. package/dist/storage.d.ts +4 -2
  266. package/dist/storage.d.ts.map +1 -1
  267. package/dist/storage.js +24 -24
  268. package/dist/subject-config.js +1 -1
  269. package/dist/summarizer.js +3 -3
  270. package/dist/support-passport/index.js +78 -78
  271. package/dist/transfer/export-okf.js +26 -26
  272. package/dist/types.d.ts +8 -40
  273. package/dist/types.d.ts.map +1 -1
  274. package/dist/types.js +1 -1
  275. package/dist/verified-recall.js +25 -25
  276. package/dist/who-knows-cli.js +26 -26
  277. package/dist/who-knows.js +25 -25
  278. package/dist/write-envelope.js +1 -1
  279. package/package.json +2 -2
  280. package/src/access-cli.ts +4 -0
  281. package/src/access-http.ts +1 -0
  282. package/src/access-mcp-correction-tools.ts +56 -0
  283. package/src/access-mcp.ts +4 -49
  284. package/src/access-operations.ts +3 -0
  285. package/src/access-service.ts +12 -21
  286. package/src/config.test.ts +35 -0
  287. package/src/config.ts +6 -65
  288. package/src/corpus-read-cancellation.ts +7 -0
  289. package/src/correction/correction-access-wiring.ts +56 -16
  290. package/src/correction/correction-classify.test.ts +185 -0
  291. package/src/correction/correction-classify.ts +157 -0
  292. package/src/correction/correction-config.ts +93 -0
  293. package/src/correction/correction-contract.ts +61 -14
  294. package/src/correction/correction-executor.test.ts +102 -2
  295. package/src/correction/correction-executor.ts +19 -1
  296. package/src/correction/correction-planner.test.ts +141 -0
  297. package/src/correction/correction-planner.ts +117 -11
  298. package/src/correction/correction-surfaces.test.ts +22 -1
  299. package/src/local-llm-qos.test.ts +36 -0
  300. package/src/local-llm.ts +20 -3
  301. package/src/maintenance/atomic-file.ts +2 -0
  302. package/src/maintenance/projection-rebuild-abort.ts +40 -0
  303. package/src/maintenance/projection-timeline.ts +209 -0
  304. package/src/maintenance/rebuild-memory-projection-runner.ts +94 -0
  305. package/src/maintenance/rebuild-memory-projection.memory.test.ts +159 -0
  306. package/src/maintenance/rebuild-memory-projection.retain-raw.test.ts +202 -0
  307. package/src/maintenance/rebuild-memory-projection.ts +63 -91
  308. package/src/orchestration/full-corpus-heap-guard.ts +38 -0
  309. package/src/orchestration/maintenance.test.ts +2 -2
  310. package/src/orchestration/maintenance.ts +2 -0
  311. package/src/orchestration/projection-rebuild-schedule.test.ts +498 -0
  312. package/src/orchestration/projection-rebuild-schedule.ts +280 -9
  313. package/src/orchestration/session-context.ts +0 -15
  314. package/src/projection-rebuild-config.ts +82 -0
  315. package/src/recall-handles-wiring.test.ts +24 -0
  316. package/src/storage/memory-lifecycle-ledger-access.ts +61 -33
  317. package/src/storage/memory-read-store.ts +10 -4
  318. package/src/storage.ts +45 -33
  319. package/src/types.ts +8 -41
  320. package/dist/chunk-22DYJLFN.js.map +0 -1
  321. package/dist/chunk-6GU3TNJJ.js.map +0 -1
  322. package/dist/chunk-6JIHC5AS.js.map +0 -1
  323. package/dist/chunk-BLHPADUX.js.map +0 -1
  324. package/dist/chunk-CHI37EHP.js.map +0 -1
  325. package/dist/chunk-GBA4N2SG.js.map +0 -1
  326. package/dist/chunk-NGOZH7R5.js.map +0 -1
  327. package/dist/chunk-QLK3SL7Q.js.map +0 -1
  328. package/dist/chunk-RKDSELA3.js.map +0 -1
  329. package/dist/chunk-X6X4UASX.js.map +0 -1
  330. package/dist/chunk-ZS7RK6H6.js.map +0 -1
  331. /package/dist/{resolution-RSG4HZTL.js.map → access-mcp-correction-tools.js.map} +0 -0
  332. /package/dist/{auto-sync-PAWBFQWL.js.map → auto-sync-FN7E3OTO.js.map} +0 -0
  333. /package/dist/{chunk-YQSWNFZE.js.map → chunk-2CP577K6.js.map} +0 -0
  334. /package/dist/{chunk-345MEMRU.js.map → chunk-3OUGSOJP.js.map} +0 -0
  335. /package/dist/{chunk-G2STTRYB.js.map → chunk-4D2YH47Z.js.map} +0 -0
  336. /package/dist/{chunk-IXYIW3MZ.js.map → chunk-4K2H4KTR.js.map} +0 -0
  337. /package/dist/{chunk-UVVSOSHL.js.map → chunk-52CQKST6.js.map} +0 -0
  338. /package/dist/{chunk-H7BZBSP6.js.map → chunk-52II7PB6.js.map} +0 -0
  339. /package/dist/{chunk-2QZFZNXO.js.map → chunk-5CQO6LVM.js.map} +0 -0
  340. /package/dist/{chunk-NLDMTXWV.js.map → chunk-5LNPW7NE.js.map} +0 -0
  341. /package/dist/{chunk-WHTMVTU4.js.map → chunk-5X4ZJESN.js.map} +0 -0
  342. /package/dist/{chunk-WI37MWRZ.js.map → chunk-63UNVGZW.js.map} +0 -0
  343. /package/dist/{chunk-G3T6YMBO.js.map → chunk-64S6X4IU.js.map} +0 -0
  344. /package/dist/{chunk-CFCEJNOE.js.map → chunk-6KHF6PAB.js.map} +0 -0
  345. /package/dist/{chunk-35A7GCHG.js.map → chunk-6T42L5FI.js.map} +0 -0
  346. /package/dist/{chunk-JDOBIFBK.js.map → chunk-7CXL25AA.js.map} +0 -0
  347. /package/dist/{chunk-YLBE6PLR.js.map → chunk-7IGMKQWK.js.map} +0 -0
  348. /package/dist/{chunk-CSLK7BN6.js.map → chunk-7LYRFI5A.js.map} +0 -0
  349. /package/dist/{chunk-IB63OVUB.js.map → chunk-AJ6ORARY.js.map} +0 -0
  350. /package/dist/{chunk-CGOKNQDK.js.map → chunk-ANZXWOYD.js.map} +0 -0
  351. /package/dist/{chunk-5QXMESS7.js.map → chunk-AXC7UTLM.js.map} +0 -0
  352. /package/dist/{chunk-RFIJRZ4K.js.map → chunk-B657ZGDH.js.map} +0 -0
  353. /package/dist/{chunk-MY7B3HYC.js.map → chunk-CLCMDKTB.js.map} +0 -0
  354. /package/dist/{chunk-QPWUG2S3.js.map → chunk-CYEK6Z3P.js.map} +0 -0
  355. /package/dist/{chunk-IHCYCE6D.js.map → chunk-DJMVSUPK.js.map} +0 -0
  356. /package/dist/{chunk-HP4CU2ZA.js.map → chunk-DST7HRSG.js.map} +0 -0
  357. /package/dist/{chunk-IIFFC3RL.js.map → chunk-EDR6CVWZ.js.map} +0 -0
  358. /package/dist/{chunk-AUWMKDKL.js.map → chunk-EMVJU7WC.js.map} +0 -0
  359. /package/dist/{chunk-O6AYMAPJ.js.map → chunk-ENNC3RZ6.js.map} +0 -0
  360. /package/dist/{chunk-2JRB3Z5N.js.map → chunk-EP5WXE2G.js.map} +0 -0
  361. /package/dist/{chunk-I2KEH2LS.js.map → chunk-FC6RCOIU.js.map} +0 -0
  362. /package/dist/{chunk-OZVHLBH6.js.map → chunk-FLV7M7CT.js.map} +0 -0
  363. /package/dist/{chunk-Q6GI7HEC.js.map → chunk-FRH2UC7Q.js.map} +0 -0
  364. /package/dist/{chunk-3SL52JKD.js.map → chunk-FZVROZKC.js.map} +0 -0
  365. /package/dist/{chunk-2EZB2DL5.js.map → chunk-GE6HETIF.js.map} +0 -0
  366. /package/dist/{chunk-2DHJTJIY.js.map → chunk-GEGUBU3D.js.map} +0 -0
  367. /package/dist/{chunk-6AA7XFMO.js.map → chunk-GF4H3B3R.js.map} +0 -0
  368. /package/dist/{chunk-ME2LMFHF.js.map → chunk-HPAOMYKM.js.map} +0 -0
  369. /package/dist/{chunk-4NRZ7BRS.js.map → chunk-I25RINZK.js.map} +0 -0
  370. /package/dist/{chunk-XG4XXI66.js.map → chunk-I25RQA65.js.map} +0 -0
  371. /package/dist/{chunk-EJJMDLVB.js.map → chunk-IJ4FEGZR.js.map} +0 -0
  372. /package/dist/{chunk-EUL3S3LE.js.map → chunk-J5WI4QRP.js.map} +0 -0
  373. /package/dist/{chunk-LMMC55WM.js.map → chunk-JA54KIYD.js.map} +0 -0
  374. /package/dist/{chunk-5FLFPTDK.js.map → chunk-JA72X46J.js.map} +0 -0
  375. /package/dist/{chunk-NLYOOGZ7.js.map → chunk-KE5PWLI6.js.map} +0 -0
  376. /package/dist/{chunk-4DDIWRT7.js.map → chunk-KQI2PKYP.js.map} +0 -0
  377. /package/dist/{chunk-Y2ADLCB3.js.map → chunk-KSUOM3YU.js.map} +0 -0
  378. /package/dist/{chunk-BTOHGPHC.js.map → chunk-KZEMFD6E.js.map} +0 -0
  379. /package/dist/{chunk-NXVD46HT.js.map → chunk-L2VS27PZ.js.map} +0 -0
  380. /package/dist/{chunk-MYYHACOW.js.map → chunk-L34W4W4I.js.map} +0 -0
  381. /package/dist/{chunk-KRTIHXWC.js.map → chunk-L3PWXD73.js.map} +0 -0
  382. /package/dist/{chunk-NQHSXHJP.js.map → chunk-L6GNS5GB.js.map} +0 -0
  383. /package/dist/{chunk-44PBRUXB.js.map → chunk-M47Q6566.js.map} +0 -0
  384. /package/dist/{chunk-E7FN5N5E.js.map → chunk-MQNOIH2C.js.map} +0 -0
  385. /package/dist/{chunk-IDSZNHIP.js.map → chunk-MULNBSPP.js.map} +0 -0
  386. /package/dist/{chunk-RKSGUMVL.js.map → chunk-NBQIFCJE.js.map} +0 -0
  387. /package/dist/{chunk-I6WFBNA4.js.map → chunk-NHSVW7UT.js.map} +0 -0
  388. /package/dist/{chunk-32HO62I4.js.map → chunk-OFEHITAZ.js.map} +0 -0
  389. /package/dist/{chunk-PCO3P7WJ.js.map → chunk-OGVJXIHX.js.map} +0 -0
  390. /package/dist/{chunk-RYN4AIRM.js.map → chunk-OZABSIOV.js.map} +0 -0
  391. /package/dist/{chunk-HO7IQP7G.js.map → chunk-QMFKW4OU.js.map} +0 -0
  392. /package/dist/{chunk-34G4U6HS.js.map → chunk-QRZMJ2WN.js.map} +0 -0
  393. /package/dist/{chunk-GUD6FYQG.js.map → chunk-RSMIRLKM.js.map} +0 -0
  394. /package/dist/{chunk-TNVZCLJU.js.map → chunk-S5TGRZWY.js.map} +0 -0
  395. /package/dist/{chunk-O24EWFPQ.js.map → chunk-SNXBXYUE.js.map} +0 -0
  396. /package/dist/{chunk-KW77LGDX.js.map → chunk-SUAX5JWY.js.map} +0 -0
  397. /package/dist/{chunk-PNFWIB4X.js.map → chunk-SWRN6U7Q.js.map} +0 -0
  398. /package/dist/{chunk-R4NGLTUS.js.map → chunk-TDMNADPI.js.map} +0 -0
  399. /package/dist/{chunk-QCP75JGO.js.map → chunk-TFA6HPOA.js.map} +0 -0
  400. /package/dist/{chunk-LI76ESJL.js.map → chunk-TZQOCQXB.js.map} +0 -0
  401. /package/dist/{chunk-OV7EYM6M.js.map → chunk-U6OXJQEH.js.map} +0 -0
  402. /package/dist/{chunk-OWHPA4JS.js.map → chunk-V32NHP2R.js.map} +0 -0
  403. /package/dist/{chunk-JSUA4YFE.js.map → chunk-WG4TMZJ2.js.map} +0 -0
  404. /package/dist/{chunk-DQTCGVFK.js.map → chunk-WHCD4Z3D.js.map} +0 -0
  405. /package/dist/{chunk-KATEWTQJ.js.map → chunk-X7J56GPG.js.map} +0 -0
  406. /package/dist/{chunk-7KICGR5W.js.map → chunk-XPRAOTJY.js.map} +0 -0
  407. /package/dist/{chunk-2NV7MMMM.js.map → chunk-XQSJXNWC.js.map} +0 -0
  408. /package/dist/{chunk-RXT6UB25.js.map → chunk-YJAOYEWI.js.map} +0 -0
  409. /package/dist/{chunk-L6DJJEFW.js.map → chunk-YJEUHGZZ.js.map} +0 -0
  410. /package/dist/{chunk-AXFWMRKI.js.map → chunk-YQJCWR4R.js.map} +0 -0
@@ -0,0 +1,202 @@
1
+ import assert from "node:assert/strict";
2
+ import { createHash } from "node:crypto";
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
+ import {
8
+ compareMemoryLifecycleEvents,
9
+ memoryLifecycleEventProjectionIdentity,
10
+ } from "../memory-lifecycle-ledger-utils.js";
11
+ import { getMemoryProjectionPath, openProjectionReadonly } from "../memory-projection-store.js";
12
+ import { readRawMemoryDocument } from "../storage/memory-frontmatter-metadata.js";
13
+ import { StorageManager } from "../storage.js";
14
+ import type { MemoryLifecycleEvent } from "../types.js";
15
+ import { rebuildMemoryProjection } from "./rebuild-memory-projection.js";
16
+
17
+ const FIXED_NOW = new Date("2026-06-01T00:00:00.000Z");
18
+
19
+ function fact(id: string, body: string): string {
20
+ return [
21
+ "---",
22
+ `id: ${id}`,
23
+ "category: fact",
24
+ "confidence: 0.8",
25
+ "created: 2026-01-01T00:00:00.000Z",
26
+ "updated: 2026-01-02T00:00:00.000Z",
27
+ "status: active",
28
+ "source: test",
29
+ "entityRef: project-alpha",
30
+ "tags:",
31
+ " - topic:alpha",
32
+ "---",
33
+ "",
34
+ body,
35
+ "",
36
+ ].join("\n");
37
+ }
38
+
39
+ function ledgerEvent(partial: Pick<MemoryLifecycleEvent, "eventId" | "memoryId" | "eventType" | "timestamp">): MemoryLifecycleEvent {
40
+ return {
41
+ actor: "test",
42
+ ruleVersion: "1",
43
+ ...partial,
44
+ };
45
+ }
46
+
47
+ async function seedCorpus(memoryDir: string, events: MemoryLifecycleEvent[]): Promise<void> {
48
+ await mkdir(path.join(memoryDir, "facts", "2026-01-01"), { recursive: true });
49
+ await mkdir(path.join(memoryDir, "cold", "facts", "2026-01-01"), { recursive: true });
50
+ await mkdir(path.join(memoryDir, "archive", "facts", "2026-01-01"), { recursive: true });
51
+ await mkdir(path.join(memoryDir, "state"), { recursive: true });
52
+ await writeFile(path.join(memoryDir, "facts", "2026-01-01", "hot-1.md"), fact("hot-1", "HOTBODY unique hot text"));
53
+ await writeFile(path.join(memoryDir, "facts", "2026-01-01", "blank.md"), fact(" ", "blank id body"));
54
+ await writeFile(path.join(memoryDir, "cold", "facts", "2026-01-01", "hot-1.md"), fact("hot-1", "COLDBODY should lose to hot"));
55
+ await writeFile(path.join(memoryDir, "cold", "facts", "2026-01-01", "cold-only.md"), fact("cold-only", "COLDONLY body"));
56
+ await writeFile(path.join(memoryDir, "archive", "facts", "2026-01-01", "arch-1.md"), fact("arch-1", "ARCHBODY archived text"));
57
+ const lines = [
58
+ ...events.map((event) => JSON.stringify(event)),
59
+ "{not-json",
60
+ ];
61
+ await writeFile(
62
+ path.join(memoryDir, "state", "memory-lifecycle-ledger.jsonl"),
63
+ `${lines.join("\n")}\n`,
64
+ "utf8",
65
+ );
66
+ }
67
+
68
+ function expectedKeptEventIds(events: MemoryLifecycleEvent[]): string[] {
69
+ const kept: string[] = [];
70
+ const seen = new Set<string>();
71
+ const sorted = [...events].sort(compareMemoryLifecycleEvents);
72
+ for (const event of sorted) {
73
+ if (!event.memoryId.trim()) continue;
74
+ if (seen.has(event.eventId)) continue;
75
+ seen.add(event.eventId);
76
+ kept.push(event.eventId);
77
+ }
78
+ return kept.sort();
79
+ }
80
+
81
+ function projectionDigest(memoryDir: string): { hash: string; counts: Record<string, number>; eventIds: string[]; previews: Record<string, string>; ledgerCount: string | undefined } {
82
+ const db = openProjectionReadonly(memoryDir);
83
+ assert.ok(db, "projection opens");
84
+ try {
85
+ const hash = createHash("sha256");
86
+ const counts: Record<string, number> = {};
87
+ const queries: Array<[string, string]> = [
88
+ ["memory_current", "SELECT * FROM memory_current ORDER BY memory_id"],
89
+ ["memory_timeline", "SELECT * FROM memory_timeline ORDER BY event_id"],
90
+ ["memory_entity_mentions", "SELECT * FROM memory_entity_mentions ORDER BY memory_id, entity_ref, mention_source"],
91
+ ];
92
+ for (const [name, sql] of queries) {
93
+ hash.update(name);
94
+ hash.update("\n");
95
+ let count = 0;
96
+ for (const row of db.prepare(sql).iterate()) {
97
+ count += 1;
98
+ hash.update(JSON.stringify(row));
99
+ hash.update("\n");
100
+ }
101
+ counts[name] = count;
102
+ }
103
+ const eventIds = (db.prepare("SELECT event_id FROM memory_timeline ORDER BY event_id").all() as Array<{ event_id: string }>)
104
+ .map((row) => row.event_id);
105
+ const previews: Record<string, string> = {};
106
+ for (const row of db.prepare("SELECT memory_id, preview_text FROM memory_current").all() as Array<{ memory_id: string; preview_text: string }>) {
107
+ previews[row.memory_id] = row.preview_text;
108
+ }
109
+ const ledgerCount = (db.prepare("SELECT value FROM meta WHERE key = 'sourceLifecycleLedgerEventCount'").get() as { value?: string } | undefined)?.value;
110
+ return { hash: hash.digest("hex"), counts, eventIds, previews, ledgerCount };
111
+ } finally {
112
+ db.close();
113
+ }
114
+ }
115
+
116
+ test("retainRaw false skips the raw copy and does not poison the corpus cache", async () => {
117
+ const memoryDir = await mkdtemp(path.join(os.tmpdir(), "remnic-retain-raw-cache-"));
118
+ try {
119
+ await mkdir(path.join(memoryDir, "facts", "2026-01-01"), { recursive: true });
120
+ await mkdir(path.join(memoryDir, "cold", "facts", "2026-01-01"), { recursive: true });
121
+ await mkdir(path.join(memoryDir, "archive", "facts", "2026-01-01"), { recursive: true });
122
+ await writeFile(path.join(memoryDir, "facts", "2026-01-01", "hot.md"), fact("hot", "hot body"));
123
+ await writeFile(path.join(memoryDir, "cold", "facts", "2026-01-01", "cold.md"), fact("cold", "cold body"));
124
+ await writeFile(path.join(memoryDir, "archive", "facts", "2026-01-01", "arch.md"), fact("arch", "arch body"));
125
+
126
+ const storage = new StorageManager(memoryDir);
127
+ const hot = await storage.readAllMemories();
128
+ assert.equal(typeof readRawMemoryDocument(hot[0]!), "string");
129
+ const stripped = await storage.readAllMemories({ retainRaw: false });
130
+ assert.equal(readRawMemoryDocument(stripped[0]!), undefined);
131
+ const again = await storage.readAllMemories();
132
+ assert.equal(typeof readRawMemoryDocument(again[0]!), "string");
133
+
134
+ const coldFirst = await storage.readAllColdMemories({ retainRaw: false });
135
+ assert.equal(readRawMemoryDocument(coldFirst[0]!), undefined);
136
+ const coldRetained = await storage.readAllColdMemories();
137
+ assert.equal(typeof readRawMemoryDocument(coldRetained[0]!), "string");
138
+ const coldAfter = await storage.readAllColdMemories({ retainRaw: false });
139
+ assert.equal(readRawMemoryDocument(coldAfter[0]!), undefined);
140
+ const coldStill = await storage.readAllColdMemories();
141
+ assert.equal(typeof readRawMemoryDocument(coldStill[0]!), "string");
142
+
143
+ const archived = await storage.readArchivedMemories({ retainRaw: false });
144
+ assert.equal(readRawMemoryDocument(archived[0]!), undefined);
145
+ const archivedKept = await storage.readArchivedMemories();
146
+ assert.equal(typeof readRawMemoryDocument(archivedKept[0]!), "string");
147
+ } finally {
148
+ await rm(memoryDir, { recursive: true, force: true });
149
+ }
150
+ });
151
+
152
+ test("projection rows are byte-identical with retainRaw false", async () => {
153
+ const memoryDir = await mkdtemp(path.join(os.tmpdir(), "remnic-retain-raw-bytes-"));
154
+ const events = [
155
+ ledgerEvent({
156
+ eventId: "dup-1",
157
+ memoryId: "hot-1",
158
+ eventType: "updated",
159
+ timestamp: "2026-03-01T00:00:00.000Z",
160
+ }),
161
+ ledgerEvent({
162
+ eventId: "dup-1",
163
+ memoryId: "hot-1",
164
+ eventType: "created",
165
+ timestamp: "2026-01-01T00:00:00.000Z",
166
+ }),
167
+ ledgerEvent({
168
+ eventId: "blank-1",
169
+ memoryId: " ",
170
+ eventType: "created",
171
+ timestamp: "2026-01-01T00:00:00.000Z",
172
+ }),
173
+ ledgerEvent({
174
+ eventId: "cold-evt",
175
+ memoryId: "cold-only",
176
+ eventType: "created",
177
+ timestamp: "2026-01-15T00:00:00.000Z",
178
+ }),
179
+ ];
180
+ try {
181
+ await seedCorpus(memoryDir, events);
182
+ await rebuildMemoryProjection({ memoryDir, dryRun: false, now: FIXED_NOW, retainRaw: true });
183
+ const withRaw = projectionDigest(memoryDir);
184
+ await rm(getMemoryProjectionPath(memoryDir), { force: true });
185
+ await rebuildMemoryProjection({ memoryDir, dryRun: false, now: FIXED_NOW });
186
+ const withoutRaw = projectionDigest(memoryDir);
187
+
188
+ assert.equal(withoutRaw.hash, withRaw.hash);
189
+ assert.deepEqual(withoutRaw.counts, withRaw.counts);
190
+ assert.deepEqual(withoutRaw.eventIds, expectedKeptEventIds(events));
191
+ assert.match(withoutRaw.previews["hot-1"] ?? "", /HOTBODY/);
192
+ assert.equal((withoutRaw.previews["hot-1"] ?? "").includes("COLDBODY"), false);
193
+ assert.match(withoutRaw.previews["cold-only"] ?? "", /COLDONLY/);
194
+ assert.match(withoutRaw.previews["arch-1"] ?? "", /ARCHBODY/);
195
+ assert.equal(withoutRaw.previews[" "], undefined);
196
+ const identities = new Set(events.map(memoryLifecycleEventProjectionIdentity));
197
+ assert.equal(withoutRaw.ledgerCount, String(identities.size));
198
+ assert.equal(withoutRaw.counts.memory_timeline, expectedKeptEventIds(events).length);
199
+ } finally {
200
+ await rm(memoryDir, { recursive: true, force: true });
201
+ }
202
+ });
@@ -15,13 +15,12 @@ import type {
15
15
  MemoryStatus,
16
16
  } from "../types.js";
17
17
  import {
18
- buildLifecycleEventsForMemory,
19
18
  inferMemoryStatus,
20
19
  MEMORY_LIFECYCLE_EVENT_SORT_ORDER,
21
- memoryLifecycleEventProjectionIdentity,
22
20
  sortMemoryLifecycleEvents,
23
21
  toMemoryPathRel,
24
22
  } from "../memory-lifecycle-ledger-utils.js";
23
+ import { loadProjectionTimeline } from "./projection-timeline.js";
25
24
  import {
26
25
  getMemoryProjectionPath,
27
26
  initializeMemoryProjectionDb,
@@ -44,6 +43,7 @@ import {
44
43
  } from "../memory-projection-format.js";
45
44
  import { openBetterSqlite3 } from "../runtime/better-sqlite.js";
46
45
  import { commitPreparedFileAtomically } from "./atomic-file.js";
46
+ import { throwIfProjectionRebuildAborted } from "./projection-rebuild-abort.js";
47
47
  import { isSupportPassportPrivateMemory } from "../support-passport/card-projection.js";
48
48
 
49
49
  export interface RebuildMemoryProjectionOptions {
@@ -55,6 +55,14 @@ export interface RebuildMemoryProjectionOptions {
55
55
  now?: Date;
56
56
  updatedAfter?: string;
57
57
  updatedBefore?: string;
58
+ /**
59
+ * When true, corpus reads keep the raw file text. Default false: the
60
+ * projection is built from parsed fields, and skipping the raw copy keeps
61
+ * the rebuild's peak heap down. Output rows stay the same either way.
62
+ */
63
+ retainRaw?: boolean;
64
+ /** When aborted, the rebuild stops before it publishes the projection file. */
65
+ signal?: AbortSignal;
58
66
  }
59
67
 
60
68
  export type {
@@ -201,7 +209,8 @@ function toCurrentStateRow(memoryDir: string, memory: MemoryFile): MemoryProject
201
209
  accessCount: memory.frontmatter.accessCount,
202
210
  lastAccessed: memory.frontmatter.lastAccessed,
203
211
  tags: normalizeProjectionTags(memory.frontmatter.tags),
204
- preview: normalizeProjectionPreview(memory.content),
212
+ // Copy the preview off the source string so the full document can be collected.
213
+ preview: Buffer.from(normalizeProjectionPreview(memory.content), "utf8").toString("utf8"),
205
214
  privateRecord: isSupportPassportPrivateMemory(memory),
206
215
  };
207
216
  }
@@ -295,23 +304,6 @@ async function loadLatestGovernanceProjection(memoryDir: string): Promise<{
295
304
  }
296
305
  }
297
306
 
298
- function loadTimelineEvents(
299
- memories: MemoryFile[],
300
- lifecycleEvents: MemoryLifecycleEvent[],
301
- ): { events: MemoryLifecycleEvent[]; usedLifecycleLedger: boolean } {
302
- if (lifecycleEvents.length > 0) {
303
- return {
304
- events: sortMemoryLifecycleEvents(lifecycleEvents),
305
- usedLifecycleLedger: true,
306
- };
307
- }
308
-
309
- return {
310
- events: sortMemoryLifecycleEvents(memories.flatMap((memory) => buildLifecycleEventsForMemory(memory))),
311
- usedLifecycleLedger: false,
312
- };
313
- }
314
-
315
307
  function normalizeScopedIso(value: string | undefined): string | null {
316
308
  if (!value) return null;
317
309
  const trimmed = value.trim();
@@ -509,53 +501,14 @@ function selectProjectionMemories(
509
501
  return { allMemories, memories, skippedDuplicateMemories, skippedBlankIdMemories };
510
502
  }
511
503
 
512
- function deduplicateTimelineEvents(
513
- events: MemoryLifecycleEvent[],
514
- sourcePathFor: (event: MemoryLifecycleEvent) => string,
515
- ): {
516
- events: MemoryLifecycleEvent[];
517
- skipped: SkippedDuplicateTimelineEvent[];
518
- skippedBlankIds: SkippedBlankIdTimelineEvent[];
519
- } {
520
- const keptById = new Map<string, { event: MemoryLifecycleEvent; path: string }>();
521
- const unique: MemoryLifecycleEvent[] = [];
522
- const skipped: SkippedDuplicateTimelineEvent[] = [];
523
- const skippedBlankIds: SkippedBlankIdTimelineEvent[] = [];
524
- for (const event of sortMemoryLifecycleEvents(events)) {
525
- const sourcePath = sourcePathFor(event);
526
- if (!event.memoryId.trim()) {
527
- skippedBlankIds.push({ eventId: event.eventId, path: sourcePath });
528
- log.warn(
529
- `projection rebuild skipped timeline event with blank memory id: `
530
- + `event_id=${event.eventId} path=${sourcePath}`,
531
- );
532
- continue;
533
- }
534
- const kept = keptById.get(event.eventId);
535
- if (kept) {
536
- skipped.push({
537
- eventId: event.eventId,
538
- keptPath: kept.path,
539
- skippedPath: sourcePath,
540
- });
541
- log.warn(
542
- `projection rebuild skipped duplicate timeline event_id=${event.eventId}: `
543
- + `kept=${kept.path} skipped=${sourcePath}`,
544
- );
545
- continue;
546
- }
547
- keptById.set(event.eventId, { event, path: sourcePath });
548
- unique.push(event);
549
- }
550
- return { events: unique, skipped, skippedBlankIds };
551
- }
552
-
553
504
  async function loadAuthoritativeProjectionSnapshot(options: {
554
505
  memoryDir: string;
555
506
  defaultNamespace?: string;
556
507
  storage?: StorageManager;
557
508
  updatedAfter?: string;
558
509
  updatedBefore?: string;
510
+ retainRaw?: boolean;
511
+ signal?: AbortSignal;
559
512
  }): Promise<{
560
513
  allMemories: MemoryFile[];
561
514
  currentRows: MemoryProjectionCurrentState[];
@@ -590,35 +543,40 @@ async function loadAuthoritativeProjectionSnapshot(options: {
590
543
  // Force a fresh disk read — projection verify/rebuild must see the true
591
544
  // on-disk state, not a potentially stale in-process cache.
592
545
  storage.invalidateAllMemoriesCacheForDir({ indexedText: false });
593
- const selected = selectProjectionMemories([
594
- await storage.readAllMemories(),
595
- await storage.readAllColdMemories(),
596
- await storage.readArchivedMemories(),
597
- ]);
546
+ const corpusRead = {
547
+ retainRaw: options.retainRaw === true,
548
+ abortSignal: options.signal,
549
+ };
550
+ const hot = await storage.readAllMemories(corpusRead);
551
+ await throwIfProjectionRebuildAborted(options.signal);
552
+ const cold = await storage.readAllColdMemories(corpusRead);
553
+ await throwIfProjectionRebuildAborted(options.signal);
554
+ const archived = await storage.readArchivedMemories(corpusRead);
555
+ await throwIfProjectionRebuildAborted(options.signal);
556
+ const selected = selectProjectionMemories([hot, cold, archived]);
598
557
  const allMemories = selected.allMemories;
599
558
  const projectionMemories = selected.memories;
600
- const lifecycleEvents = await storage.readAllMemoryLifecycleEvents();
601
- const timeline = loadTimelineEvents(projectionMemories, lifecycleEvents);
602
- const lifecycleLedgerPath = path.join(
603
- options.memoryDir,
604
- "state",
605
- "memory-lifecycle-ledger.jsonl",
606
- );
607
- const memoryPathById = new Map(
608
- projectionMemories.map((memory) => [memory.frontmatter.id, memory.path]),
609
- );
610
- const deduplicatedTimeline = deduplicateTimelineEvents(
611
- timeline.events,
612
- (event) => timeline.usedLifecycleLedger
613
- ? lifecycleLedgerPath
614
- : memoryPathById.get(event.memoryId) ?? lifecycleLedgerPath,
615
- );
616
- const events = deduplicatedTimeline.events;
617
- const usedLifecycleLedger = timeline.usedLifecycleLedger;
618
- const sourceLifecycleLedgerEventCount = new Set(
619
- lifecycleEvents.map(memoryLifecycleEventProjectionIdentity),
620
- ).size;
621
559
  const currentRows = projectionMemories.map((memory) => toCurrentStateRow(options.memoryDir, memory));
560
+ // Preview is already a detached copy. Drop the document bodies before the
561
+ // ledger scan so peak heap is the larger of the corpus and the timeline,
562
+ // not both. These objects bypass the shared caches when retainRaw is off,
563
+ // so clearing them cannot strip a raw copy another caller is holding.
564
+ if (options.retainRaw !== true) {
565
+ for (const memory of allMemories) memory.content = "";
566
+ }
567
+ const {
568
+ events,
569
+ usedLifecycleLedger,
570
+ sourceLifecycleLedgerEventCount,
571
+ skipped: skippedDuplicateTimelineEvents,
572
+ skippedBlankIds: skippedBlankIdTimelineEvents,
573
+ } = await loadProjectionTimeline({
574
+ storage,
575
+ memoryDir: options.memoryDir,
576
+ memories: projectionMemories,
577
+ signal: options.signal,
578
+ });
579
+ await throwIfProjectionRebuildAborted(options.signal);
622
580
  const scope = normalizeProjectionScope(options);
623
581
  const scopedMemories = filterMemoriesForProjectionScope(projectionMemories, scope);
624
582
  const scopedMemoryIds = new Set(scopedMemories.map((memory) => memory.frontmatter.id));
@@ -660,8 +618,8 @@ async function loadAuthoritativeProjectionSnapshot(options: {
660
618
  scope,
661
619
  skippedDuplicateMemories: selected.skippedDuplicateMemories,
662
620
  skippedBlankIdMemories: selected.skippedBlankIdMemories,
663
- skippedDuplicateTimelineEvents: deduplicatedTimeline.skipped,
664
- skippedBlankIdTimelineEvents: deduplicatedTimeline.skippedBlankIds,
621
+ skippedDuplicateTimelineEvents,
622
+ skippedBlankIdTimelineEvents,
665
623
  };
666
624
  }
667
625
 
@@ -1058,6 +1016,7 @@ export async function rebuildMemoryProjection(
1058
1016
  const now = options.now ?? new Date();
1059
1017
  const outputPath = getMemoryProjectionPath(options.memoryDir);
1060
1018
  const snapshot = await loadAuthoritativeProjectionSnapshot(options);
1019
+ await throwIfProjectionRebuildAborted(options.signal);
1061
1020
 
1062
1021
  let backupPath: string | undefined;
1063
1022
  if (!dryRun) {
@@ -1117,6 +1076,7 @@ export async function rebuildMemoryProjection(
1117
1076
 
1118
1077
  const tempPath = `${outputPath}.tmp`;
1119
1078
  await mkdir(path.dirname(outputPath), { recursive: true });
1079
+ await throwIfProjectionRebuildAborted(options.signal);
1120
1080
  await rm(tempPath, { force: true });
1121
1081
  writeProjectionDb(
1122
1082
  tempPath,
@@ -1130,8 +1090,20 @@ export async function rebuildMemoryProjection(
1130
1090
  snapshot.sourceLifecycleLedgerEventCount,
1131
1091
  !hasScopedProjectionFilter(snapshot.scope),
1132
1092
  );
1133
- backupPath = await backupExistingProjection(options.memoryDir, outputPath, now);
1134
- backupPath = await commitPreparedFileAtomically(tempPath, outputPath, backupPath);
1093
+ try {
1094
+ await throwIfProjectionRebuildAborted(options.signal);
1095
+ backupPath = await backupExistingProjection(options.memoryDir, outputPath, now);
1096
+ await throwIfProjectionRebuildAborted(options.signal);
1097
+ backupPath = await commitPreparedFileAtomically(
1098
+ tempPath,
1099
+ outputPath,
1100
+ backupPath,
1101
+ () => throwIfProjectionRebuildAborted(options.signal),
1102
+ );
1103
+ } catch (err) {
1104
+ if (options.signal?.aborted) await rm(tempPath, { force: true });
1105
+ throw err;
1106
+ }
1135
1107
  }
1136
1108
 
1137
1109
  return {
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Heap guard for scheduled full-corpus work.
3
+ *
4
+ * A daemon already near Node's default heap limit must not start another
5
+ * multi-GB allocation (the scheduled projection rebuild loads hot, cold, and
6
+ * archived memories plus the lifecycle ledger). Callers postpone the job and
7
+ * arm their existing failure backoff instead.
8
+ */
9
+
10
+ export interface HeapLimitStatistics {
11
+ used_heap_size: number;
12
+ heap_size_limit: number;
13
+ }
14
+
15
+ export interface FullCorpusHeapPressure {
16
+ /** True when usage is strictly above `limitRatio`. */
17
+ postpone: boolean;
18
+ /** `used_heap_size / heap_size_limit`, or 0 when the statistics are unusable. */
19
+ ratio: number;
20
+ }
21
+
22
+ /**
23
+ * Decide whether a scheduled full-corpus job should wait. Non-finite or
24
+ * non-positive heap limits do not postpone (there is no ratio to trust).
25
+ * Comparison is strict `>` so a limit of `1` never fires.
26
+ */
27
+ export function fullCorpusHeapPressure(
28
+ stats: HeapLimitStatistics,
29
+ limitRatio: number,
30
+ ): FullCorpusHeapPressure {
31
+ const used = stats.used_heap_size;
32
+ const cap = stats.heap_size_limit;
33
+ if (!Number.isFinite(used) || used < 0 || !Number.isFinite(cap) || cap <= 0 || !Number.isFinite(limitRatio)) {
34
+ return { postpone: false, ratio: 0 };
35
+ }
36
+ const ratio = used / cap;
37
+ return { postpone: ratio > limitRatio, ratio };
38
+ }
@@ -2968,8 +2968,8 @@ test("maintenance tool request invokes the scheduled projection rebuild wiring (
2968
2968
  });
2969
2969
  try {
2970
2970
  scheduler.requestQmdMaintenanceForTool("test");
2971
- for (let attempt = 0; attempt < 100 && probeProjectionHealth(memoryDir).state === "absent"; attempt += 1) {
2972
- await delay(10);
2971
+ for (let attempt = 0; attempt < 60 && probeProjectionHealth(memoryDir).state === "absent"; attempt += 1) {
2972
+ await delay(500);
2973
2973
  }
2974
2974
  assert.equal(
2975
2975
  probeProjectionHealth(memoryDir).state,
@@ -55,6 +55,7 @@ import { resolveDaySummaryCronModel } from "../maintenance/day-summary-cron.js";
55
55
  import {
56
56
  createProjectionRebuildScheduleState,
57
57
  maybeRebuildMemoryProjectionScheduled,
58
+ terminateScheduledProjectionRebuilds,
58
59
  } from "./projection-rebuild-schedule.js";
59
60
  import {
60
61
  drainPendingLifecycleLedgerIfAny,
@@ -1168,6 +1169,7 @@ export class MaintenanceScheduler {
1168
1169
  */
1169
1170
  async dispose(): Promise<void> {
1170
1171
  this.disposed = true;
1172
+ terminateScheduledProjectionRebuilds(this.projectionRebuild);
1171
1173
  const consolidationDrain = this.consolidationRunPromise;
1172
1174
  // The registrar latches teardown first (so a draining tick's onRun cannot
1173
1175
  // re-arm QMD maintenance) and aborts+drains the sync. Capture its drain and