@remnic/core 9.7.8 → 9.7.9

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 (386) hide show
  1. package/dist/access-admin-ops-surface.d.ts +6 -6
  2. package/dist/access-admin-ops-surface.js +31 -29
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-boundary.d.ts +6 -6
  5. package/dist/access-boundary.js +32 -30
  6. package/dist/access-cli.js +88 -86
  7. package/dist/access-cli.js.map +1 -1
  8. package/dist/access-http.d.ts +6 -6
  9. package/dist/access-http.js +39 -37
  10. package/dist/access-identity-continuity-surface.d.ts +5 -5
  11. package/dist/access-identity-continuity-surface.js +31 -29
  12. package/dist/access-lcm-surface.d.ts +6 -6
  13. package/dist/access-lcm-surface.js +31 -29
  14. package/dist/access-mcp.d.ts +6 -6
  15. package/dist/access-mcp.js +36 -34
  16. package/dist/access-observe-write-surface.d.ts +6 -6
  17. package/dist/access-observe-write-surface.js +31 -29
  18. package/dist/access-operations-batch.js +34 -32
  19. package/dist/access-operations.d.ts +9 -9
  20. package/dist/access-operations.js +35 -33
  21. package/dist/access-recall-surface.d.ts +6 -6
  22. package/dist/access-recall-surface.js +31 -29
  23. package/dist/access-schema.d.ts +64 -64
  24. package/dist/{access-service-CxDZXTKt.d.ts → access-service-DSuzikHQ.d.ts} +4 -4
  25. package/dist/access-service.d.ts +6 -6
  26. package/dist/access-service.js +31 -29
  27. package/dist/access-surface-catalog.d.ts +6 -6
  28. package/dist/action-confidence.d.ts +1 -1
  29. package/dist/active-memory-bridge.d.ts +1 -1
  30. package/dist/active-recall.d.ts +1 -1
  31. package/dist/active-recall.js +1 -1
  32. package/dist/adapters/index.js +4 -4
  33. package/dist/adapters/registry.js +2 -2
  34. package/dist/{auto-sync-676N6N6Y.js → auto-sync-AAMTVZMK.js} +5 -5
  35. package/dist/behavior-learner.d.ts +1 -1
  36. package/dist/behavior-signals.d.ts +1 -1
  37. package/dist/bootstrap.d.ts +5 -5
  38. package/dist/briefing.d.ts +2 -2
  39. package/dist/briefing.js +14 -12
  40. package/dist/buffer-surprise-report.d.ts +1 -1
  41. package/dist/buffer.d.ts +2 -2
  42. package/dist/bulk-import/index.d.ts +3 -3
  43. package/dist/calibration.d.ts +1 -1
  44. package/dist/calibration.js +2 -2
  45. package/dist/capabilities.d.ts +1 -1
  46. package/dist/{capsule-merge-GK5E647P.js → capsule-merge-Z2HUO6IK.js} +10 -2
  47. package/dist/capsule-merge-Z2HUO6IK.js.map +1 -0
  48. package/dist/{catalog-DzU9HowE.d.ts → catalog-BNwjACa5.d.ts} +1 -1
  49. package/dist/causal-behavior.d.ts +1 -1
  50. package/dist/causal-consolidation.d.ts +1 -1
  51. package/dist/causal-consolidation.js +15 -13
  52. package/dist/causal-consolidation.js.map +1 -1
  53. package/dist/causal-trajectory-graph.d.ts +1 -1
  54. package/dist/{chunk-TZJVTH3F.js → chunk-27VEKQQA.js} +14 -14
  55. package/dist/{chunk-JO5AT6QT.js → chunk-3ZVFLMFQ.js} +1 -1
  56. package/dist/chunk-3ZVFLMFQ.js.map +1 -0
  57. package/dist/{chunk-AD2KK5MT.js → chunk-5CFHYQU3.js} +9 -3
  58. package/dist/chunk-5CFHYQU3.js.map +1 -0
  59. package/dist/{chunk-7XH7VJN4.js → chunk-5S7Z5SHA.js} +2 -2
  60. package/dist/{chunk-TVVEYCNW.js → chunk-7K5Q6COX.js} +4 -4
  61. package/dist/{chunk-EJCVMPIM.js → chunk-7LMEY5KZ.js} +15 -1
  62. package/dist/chunk-7LMEY5KZ.js.map +1 -0
  63. package/dist/{chunk-3F4N4WDH.js → chunk-AHLPZ2SF.js} +2 -2
  64. package/dist/{chunk-AH3M6F4X.js → chunk-CDGGQGUU.js} +2 -2
  65. package/dist/{chunk-ZHKD4EZM.js → chunk-CK6RI52P.js} +3 -3
  66. package/dist/{chunk-6C35R7P4.js → chunk-DJCKXI4M.js} +2 -2
  67. package/dist/{chunk-GL3SMLMZ.js → chunk-DLPXS7BE.js} +109 -85
  68. package/dist/chunk-DLPXS7BE.js.map +1 -0
  69. package/dist/{chunk-NMMKRVUF.js → chunk-EIKBKQ6L.js} +6 -6
  70. package/dist/{chunk-O3BZ6PFY.js → chunk-F3FC7SMO.js} +2 -2
  71. package/dist/{chunk-ZW6OKHVX.js → chunk-FKCJH7KP.js} +2 -2
  72. package/dist/{chunk-DQPPRXFO.js → chunk-HQ7QZJM5.js} +2 -2
  73. package/dist/{chunk-UYZUJ4EB.js → chunk-I2THZUAF.js} +2 -2
  74. package/dist/{chunk-RKNJBZ55.js → chunk-JBPKEARU.js} +4 -4
  75. package/dist/{chunk-KIPLG7S7.js → chunk-JKLJ6A7W.js} +2 -2
  76. package/dist/{chunk-HXDKC3BI.js → chunk-JU3GHO6J.js} +2 -2
  77. package/dist/{chunk-74MJH7I3.js → chunk-KGNFFCZJ.js} +12 -3
  78. package/dist/chunk-KGNFFCZJ.js.map +1 -0
  79. package/dist/{chunk-Q6JPMCPO.js → chunk-KKASNHGF.js} +62 -57
  80. package/dist/chunk-KKASNHGF.js.map +1 -0
  81. package/dist/{chunk-R2SJDIPO.js → chunk-KPXAJ77O.js} +9 -7
  82. package/dist/chunk-KPXAJ77O.js.map +1 -0
  83. package/dist/{chunk-SYNYI4ZM.js → chunk-L5HJQC36.js} +2 -2
  84. package/dist/{chunk-VXMWDXIJ.js → chunk-LC7OODWZ.js} +2 -2
  85. package/dist/{chunk-CNWC274T.js → chunk-MLT5EG6K.js} +28 -28
  86. package/dist/{chunk-M5QKGHCR.js → chunk-OC35KQIN.js} +6 -2
  87. package/dist/chunk-OC35KQIN.js.map +1 -0
  88. package/dist/chunk-OKUEZOGW.js +27 -0
  89. package/dist/chunk-OKUEZOGW.js.map +1 -0
  90. package/dist/{chunk-PKGWJFNR.js → chunk-OVMS3DCB.js} +2 -2
  91. package/dist/chunk-PDJTHRAW.js +36 -0
  92. package/dist/chunk-PDJTHRAW.js.map +1 -0
  93. package/dist/{chunk-ZUFJ7ZTR.js → chunk-PHXCPVSX.js} +6 -2
  94. package/dist/chunk-PHXCPVSX.js.map +1 -0
  95. package/dist/{chunk-57INMZ6F.js → chunk-POUD5BLV.js} +2 -2
  96. package/dist/{chunk-KTOH7EJE.js → chunk-PV7E2FGY.js} +307 -43
  97. package/dist/chunk-PV7E2FGY.js.map +1 -0
  98. package/dist/{chunk-LRGSLV7M.js → chunk-PYHOAXTI.js} +4 -4
  99. package/dist/{chunk-WKE4VXSZ.js → chunk-QKVX4Y6D.js} +2 -2
  100. package/dist/{chunk-FXGC5UUH.js → chunk-RT7IP3D3.js} +2 -2
  101. package/dist/{chunk-CHVU4RE5.js → chunk-SKXBOZDF.js} +3 -3
  102. package/dist/{chunk-TVRPRFUB.js → chunk-TY43GBX2.js} +9 -7
  103. package/dist/chunk-TY43GBX2.js.map +1 -0
  104. package/dist/{chunk-UVIQHSS7.js → chunk-UP25ZZCN.js} +9 -3
  105. package/dist/chunk-UP25ZZCN.js.map +1 -0
  106. package/dist/{chunk-GKCCHHZK.js → chunk-UXKMMNJD.js} +4 -4
  107. package/dist/{chunk-XFTPUXCE.js → chunk-UXWGPODH.js} +4 -4
  108. package/dist/{chunk-2FSHROYK.js → chunk-V53GJUSL.js} +8 -8
  109. package/dist/{chunk-LKT755LP.js → chunk-VA4WSW54.js} +2 -2
  110. package/dist/{chunk-FYKIEOG6.js → chunk-VCFADTFS.js} +3 -3
  111. package/dist/{chunk-VF4XKTX3.js → chunk-VZ5OJE4X.js} +10 -2
  112. package/dist/chunk-VZ5OJE4X.js.map +1 -0
  113. package/dist/{chunk-AWJ2FHCF.js → chunk-X47LWMKA.js} +49 -21
  114. package/dist/chunk-X47LWMKA.js.map +1 -0
  115. package/dist/{chunk-VMGMY2AI.js → chunk-XG5CGR3K.js} +8 -8
  116. package/dist/{chunk-VMGMY2AI.js.map → chunk-XG5CGR3K.js.map} +1 -1
  117. package/dist/{chunk-T7VNN3ZM.js → chunk-XVLEGMJI.js} +2 -2
  118. package/dist/{chunk-CRFTLUWT.js → chunk-Y5U35ZVS.js} +2 -2
  119. package/dist/{chunk-UHGHTOR5.js → chunk-YGAOLHKN.js} +7 -7
  120. package/dist/{chunk-QDCJNRKK.js → chunk-YXOAQAH2.js} +3 -3
  121. package/dist/{cli-BqyGVyOe.d.ts → cli-DACyuK8-.d.ts} +5 -5
  122. package/dist/cli.d.ts +8 -8
  123. package/dist/cli.js +65 -63
  124. package/dist/compounding/engine.d.ts +2 -2
  125. package/dist/compounding/engine.js +14 -12
  126. package/dist/compounding/preference-consolidator.d.ts +1 -1
  127. package/dist/compression-optimizer.d.ts +1 -1
  128. package/dist/config.d.ts +1 -1
  129. package/dist/config.js +1 -1
  130. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  131. package/dist/connectors/codex-materialize-runner.js +14 -12
  132. package/dist/connectors/codex-materialize.d.ts +1 -1
  133. package/dist/connectors/index.d.ts +1 -1
  134. package/dist/connectors/index.js +14 -12
  135. package/dist/consolidation-provenance-check.d.ts +2 -2
  136. package/dist/consolidation-provenance-check.js +6 -2
  137. package/dist/consolidation-undo.d.ts +2 -2
  138. package/dist/consolidation-undo.js +8 -1
  139. package/dist/consolidation-undo.js.map +1 -1
  140. package/dist/contradiction/index.d.ts +2 -2
  141. package/dist/conversation-index/backend.d.ts +1 -1
  142. package/dist/conversation-index/chunker.d.ts +1 -1
  143. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  144. package/dist/conversation-index/indexer.d.ts +1 -1
  145. package/dist/conversation-index/search.d.ts +1 -1
  146. package/dist/day-summary.d.ts +1 -1
  147. package/dist/delinearize.d.ts +1 -1
  148. package/dist/direct-answer-wiring.d.ts +1 -1
  149. package/dist/direct-answer.d.ts +1 -1
  150. package/dist/embedding-fallback.d.ts +1 -1
  151. package/dist/enrichment/index.d.ts +1 -1
  152. package/dist/entity-retrieval.d.ts +2 -2
  153. package/dist/entity-retrieval.js +14 -12
  154. package/dist/entity-schema.d.ts +1 -1
  155. package/dist/explicit-capture.d.ts +5 -5
  156. package/dist/extraction-faithfulness.d.ts +1 -1
  157. package/dist/extraction-faithfulness.js +3 -3
  158. package/dist/extraction-judge-telemetry.d.ts +1 -1
  159. package/dist/extraction-judge-training.d.ts +1 -1
  160. package/dist/extraction-judge.d.ts +1 -1
  161. package/dist/extraction-judge.js +3 -3
  162. package/dist/extraction.d.ts +1 -1
  163. package/dist/extraction.js +3 -3
  164. package/dist/fallback-llm.d.ts +1 -1
  165. package/dist/fallback-llm.js +2 -2
  166. package/dist/{forget-KHF7A44H.js → forget-CQCLB5LB.js} +2 -2
  167. package/dist/graph-dashboard-diff.d.ts +1 -1
  168. package/dist/graph-dashboard-key.d.ts +1 -1
  169. package/dist/graph-dashboard-parser.d.ts +1 -1
  170. package/dist/graph-edge-reinforcement.d.ts +1 -1
  171. package/dist/graph-snapshot.d.ts +1 -1
  172. package/dist/graph.d.ts +1 -1
  173. package/dist/identity-continuity.d.ts +1 -1
  174. package/dist/importance.d.ts +1 -1
  175. package/dist/importers/index.d.ts +1 -1
  176. package/dist/in-flight-reads.d.ts +19 -0
  177. package/dist/in-flight-reads.js +16 -0
  178. package/dist/in-flight-reads.js.map +1 -0
  179. package/dist/index.d.ts +13 -13
  180. package/dist/index.js +105 -103
  181. package/dist/intent.d.ts +1 -1
  182. package/dist/lcm/engine.d.ts +1 -1
  183. package/dist/lcm/engine.js +2 -2
  184. package/dist/lcm/index.d.ts +1 -1
  185. package/dist/lcm/index.js +7 -7
  186. package/dist/lcm/tools.d.ts +1 -1
  187. package/dist/lifecycle.d.ts +1 -1
  188. package/dist/live-connectors-runner.d.ts +1 -1
  189. package/dist/local-llm.d.ts +1 -1
  190. package/dist/local-model-endpoint.d.ts +1 -1
  191. package/dist/maintenance/memory-governance.d.ts +1 -1
  192. package/dist/maintenance/memory-governance.js +14 -12
  193. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +14 -12
  194. package/dist/maintenance/rebuild-memory-projection.js +15 -13
  195. package/dist/mcp-memory-inspector-app.d.ts +6 -6
  196. package/dist/memory-action-policy.d.ts +1 -1
  197. package/dist/memory-cache.d.ts +24 -13
  198. package/dist/memory-cache.js +3 -1
  199. package/dist/memory-corpus-version.d.ts +19 -0
  200. package/dist/memory-corpus-version.js +13 -0
  201. package/dist/memory-corpus-version.js.map +1 -0
  202. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  203. package/dist/memory-projection-store.d.ts +1 -1
  204. package/dist/memory-provenance.d.ts +1 -1
  205. package/dist/memory-worth-outcomes.d.ts +2 -2
  206. package/dist/models-json.d.ts +1 -1
  207. package/dist/namespaces/migrate.d.ts +3 -3
  208. package/dist/namespaces/migrate.js +21 -19
  209. package/dist/namespaces/principal.d.ts +1 -1
  210. package/dist/namespaces/search.d.ts +1 -1
  211. package/dist/namespaces/search.js +7 -7
  212. package/dist/namespaces/storage.d.ts +3 -3
  213. package/dist/namespaces/storage.js +14 -12
  214. package/dist/native-knowledge.d.ts +1 -1
  215. package/dist/operator-toolkit.d.ts +2 -2
  216. package/dist/operator-toolkit.js +26 -24
  217. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  218. package/dist/orchestration/maintenance.d.ts +2 -2
  219. package/dist/orchestration/maintenance.js +16 -14
  220. package/dist/{orchestrator-37Cx7yyw.d.ts → orchestrator-D83AvrPf.d.ts} +4 -4
  221. package/dist/orchestrator.d.ts +5 -5
  222. package/dist/orchestrator.js +88 -86
  223. package/dist/page-versioning.js +5 -1
  224. package/dist/patterns-cli.d.ts +1 -1
  225. package/dist/{pipeline-C6onljHc.d.ts → pipeline-BSqGpYl1.d.ts} +1 -1
  226. package/dist/policy-runtime.d.ts +1 -1
  227. package/dist/provenance.d.ts +1 -1
  228. package/dist/{qmd-J08G7MEm.d.ts → qmd-CutnpRVe.d.ts} +1 -1
  229. package/dist/qmd-preflight.d.ts +2 -2
  230. package/dist/qmd-recall-cache.d.ts +1 -1
  231. package/dist/qmd.d.ts +2 -2
  232. package/dist/qmd.js +2 -2
  233. package/dist/recall-disclosure-escalation.d.ts +1 -1
  234. package/dist/recall-explain-renderer.d.ts +1 -1
  235. package/dist/recall-explain-renderer.js +3 -3
  236. package/dist/recall-planner-llm.d.ts +1 -1
  237. package/dist/recall-planner-llm.js +2 -2
  238. package/dist/recall-state.d.ts +1 -1
  239. package/dist/recall-tag-filter.d.ts +1 -1
  240. package/dist/recall-timings.d.ts +1 -1
  241. package/dist/recall-xray-cli.d.ts +1 -1
  242. package/dist/recall-xray-cli.js +4 -4
  243. package/dist/recall-xray-renderer.d.ts +1 -1
  244. package/dist/recall-xray-renderer.js +3 -3
  245. package/dist/recall-xray.d.ts +1 -1
  246. package/dist/recall-xray.js +2 -2
  247. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  248. package/dist/replay/normalizers/claude.d.ts +1 -1
  249. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  250. package/dist/replay/normalizers/shared.d.ts +1 -1
  251. package/dist/replay/runner.d.ts +1 -1
  252. package/dist/replay/types.d.ts +1 -1
  253. package/dist/resolve-auth-token.d.ts +1 -1
  254. package/dist/resume-bundles.js +2 -2
  255. package/dist/retrieval-agents.d.ts +2 -2
  256. package/dist/retrieval-tiers.d.ts +1 -1
  257. package/dist/routing/engine.d.ts +1 -1
  258. package/dist/routing/store.d.ts +1 -1
  259. package/dist/schemas.d.ts +74 -74
  260. package/dist/search/embed-helper.d.ts +1 -1
  261. package/dist/search/factory.d.ts +1 -1
  262. package/dist/search/factory.js +6 -6
  263. package/dist/search/index.d.ts +1 -1
  264. package/dist/search/index.js +12 -12
  265. package/dist/search/lancedb-backend.d.ts +1 -1
  266. package/dist/search/meilisearch-backend.d.ts +1 -1
  267. package/dist/search/noop-backend.d.ts +1 -1
  268. package/dist/search/orama-backend.d.ts +1 -1
  269. package/dist/search/port.d.ts +1 -1
  270. package/dist/search/remote-backend.d.ts +1 -1
  271. package/dist/{semantic-consolidation-BFtoVosl.d.ts → semantic-consolidation-btIVRC4l.d.ts} +1 -1
  272. package/dist/semantic-consolidation.d.ts +2 -2
  273. package/dist/semantic-consolidation.js +15 -13
  274. package/dist/semantic-rule-promotion.js +14 -12
  275. package/dist/semantic-rule-verifier.d.ts +5 -1
  276. package/dist/semantic-rule-verifier.js +14 -12
  277. package/dist/session-observer-bands.d.ts +1 -1
  278. package/dist/session-observer-state.d.ts +1 -1
  279. package/dist/shared-context/manager.d.ts +9 -9
  280. package/dist/signal.d.ts +1 -1
  281. package/dist/{storage-CXjwBr69.d.ts → storage-BVv_Mqa0.d.ts} +133 -3
  282. package/dist/storage.d.ts +2 -2
  283. package/dist/storage.js +13 -11
  284. package/dist/summarizer.d.ts +1 -1
  285. package/dist/summarizer.js +3 -3
  286. package/dist/summary-snapshot.d.ts +1 -1
  287. package/dist/temporal-supersession.d.ts +2 -2
  288. package/dist/temporal-timeline-recall.d.ts +1 -1
  289. package/dist/temporal-validity.d.ts +1 -1
  290. package/dist/threading.d.ts +1 -1
  291. package/dist/tier-migration.d.ts +2 -2
  292. package/dist/tier-routing.d.ts +1 -1
  293. package/dist/topics.d.ts +1 -1
  294. package/dist/transcript.d.ts +1 -1
  295. package/dist/transfer/capsule-import.js +6 -2
  296. package/dist/transfer/import-sqlite.js +2 -2
  297. package/dist/transfer/types.d.ts +66 -66
  298. package/dist/trust-score-stage.d.ts +1 -1
  299. package/dist/trust-score.d.ts +1 -1
  300. package/dist/{types-DpxqC8dI.d.ts → types-Cmkz7csa.d.ts} +27 -0
  301. package/dist/types.d.ts +1 -1
  302. package/dist/types.js +1 -1
  303. package/dist/utility-runtime.d.ts +1 -1
  304. package/dist/verified-recall.d.ts +4 -0
  305. package/dist/verified-recall.js +14 -12
  306. package/package.json +12 -2
  307. package/src/binary-lifecycle/pipeline.ts +22 -0
  308. package/src/cli.ts +8 -0
  309. package/src/compounding/engine.ts +9 -1
  310. package/src/config.ts +14 -0
  311. package/src/consolidation-undo.ts +8 -0
  312. package/src/curation/index.ts +9 -0
  313. package/src/in-flight-reads.ts +63 -0
  314. package/src/maintenance/memory-governance.ts +6 -0
  315. package/src/memory-cache-hot.test.ts +131 -0
  316. package/src/memory-cache.ts +146 -22
  317. package/src/memory-corpus-version.ts +45 -0
  318. package/src/namespaces/storage.ts +20 -1
  319. package/src/operator-toolkit.ts +7 -1
  320. package/src/orchestration/recall-internal.ts +6 -3
  321. package/src/orchestrator.ts +25 -1
  322. package/src/page-versioning.ts +14 -1
  323. package/src/provenance-frontmatter.test.ts +6 -0
  324. package/src/review/index.ts +16 -8
  325. package/src/semantic-rule-promotion.ts +9 -1
  326. package/src/semantic-rule-verifier.ts +19 -6
  327. package/src/spaces/index.ts +10 -0
  328. package/src/storage/memory-read-store.ts +9 -2
  329. package/src/storage-contract/cache-coherence.test.ts +242 -0
  330. package/src/storage-contract/namespace-routing.test.ts +26 -1
  331. package/src/storage.ts +513 -31
  332. package/src/transfer/capsule-cache-coherence.test.ts +107 -0
  333. package/src/transfer/capsule-import.ts +8 -0
  334. package/src/transfer/capsule-merge.ts +7 -0
  335. package/src/types.ts +27 -0
  336. package/src/verified-recall.ts +20 -6
  337. package/dist/capsule-merge-GK5E647P.js.map +0 -1
  338. package/dist/chunk-74MJH7I3.js.map +0 -1
  339. package/dist/chunk-AD2KK5MT.js.map +0 -1
  340. package/dist/chunk-AWJ2FHCF.js.map +0 -1
  341. package/dist/chunk-EJCVMPIM.js.map +0 -1
  342. package/dist/chunk-GL3SMLMZ.js.map +0 -1
  343. package/dist/chunk-JO5AT6QT.js.map +0 -1
  344. package/dist/chunk-KTOH7EJE.js.map +0 -1
  345. package/dist/chunk-M5QKGHCR.js.map +0 -1
  346. package/dist/chunk-Q6JPMCPO.js.map +0 -1
  347. package/dist/chunk-R2SJDIPO.js.map +0 -1
  348. package/dist/chunk-TVRPRFUB.js.map +0 -1
  349. package/dist/chunk-UVIQHSS7.js.map +0 -1
  350. package/dist/chunk-VF4XKTX3.js.map +0 -1
  351. package/dist/chunk-ZUFJ7ZTR.js.map +0 -1
  352. /package/dist/{auto-sync-676N6N6Y.js.map → auto-sync-AAMTVZMK.js.map} +0 -0
  353. /package/dist/{chunk-TZJVTH3F.js.map → chunk-27VEKQQA.js.map} +0 -0
  354. /package/dist/{chunk-7XH7VJN4.js.map → chunk-5S7Z5SHA.js.map} +0 -0
  355. /package/dist/{chunk-TVVEYCNW.js.map → chunk-7K5Q6COX.js.map} +0 -0
  356. /package/dist/{chunk-3F4N4WDH.js.map → chunk-AHLPZ2SF.js.map} +0 -0
  357. /package/dist/{chunk-AH3M6F4X.js.map → chunk-CDGGQGUU.js.map} +0 -0
  358. /package/dist/{chunk-ZHKD4EZM.js.map → chunk-CK6RI52P.js.map} +0 -0
  359. /package/dist/{chunk-6C35R7P4.js.map → chunk-DJCKXI4M.js.map} +0 -0
  360. /package/dist/{chunk-NMMKRVUF.js.map → chunk-EIKBKQ6L.js.map} +0 -0
  361. /package/dist/{chunk-O3BZ6PFY.js.map → chunk-F3FC7SMO.js.map} +0 -0
  362. /package/dist/{chunk-ZW6OKHVX.js.map → chunk-FKCJH7KP.js.map} +0 -0
  363. /package/dist/{chunk-DQPPRXFO.js.map → chunk-HQ7QZJM5.js.map} +0 -0
  364. /package/dist/{chunk-UYZUJ4EB.js.map → chunk-I2THZUAF.js.map} +0 -0
  365. /package/dist/{chunk-RKNJBZ55.js.map → chunk-JBPKEARU.js.map} +0 -0
  366. /package/dist/{chunk-KIPLG7S7.js.map → chunk-JKLJ6A7W.js.map} +0 -0
  367. /package/dist/{chunk-HXDKC3BI.js.map → chunk-JU3GHO6J.js.map} +0 -0
  368. /package/dist/{chunk-SYNYI4ZM.js.map → chunk-L5HJQC36.js.map} +0 -0
  369. /package/dist/{chunk-VXMWDXIJ.js.map → chunk-LC7OODWZ.js.map} +0 -0
  370. /package/dist/{chunk-CNWC274T.js.map → chunk-MLT5EG6K.js.map} +0 -0
  371. /package/dist/{chunk-PKGWJFNR.js.map → chunk-OVMS3DCB.js.map} +0 -0
  372. /package/dist/{chunk-57INMZ6F.js.map → chunk-POUD5BLV.js.map} +0 -0
  373. /package/dist/{chunk-LRGSLV7M.js.map → chunk-PYHOAXTI.js.map} +0 -0
  374. /package/dist/{chunk-WKE4VXSZ.js.map → chunk-QKVX4Y6D.js.map} +0 -0
  375. /package/dist/{chunk-FXGC5UUH.js.map → chunk-RT7IP3D3.js.map} +0 -0
  376. /package/dist/{chunk-CHVU4RE5.js.map → chunk-SKXBOZDF.js.map} +0 -0
  377. /package/dist/{chunk-GKCCHHZK.js.map → chunk-UXKMMNJD.js.map} +0 -0
  378. /package/dist/{chunk-XFTPUXCE.js.map → chunk-UXWGPODH.js.map} +0 -0
  379. /package/dist/{chunk-2FSHROYK.js.map → chunk-V53GJUSL.js.map} +0 -0
  380. /package/dist/{chunk-LKT755LP.js.map → chunk-VA4WSW54.js.map} +0 -0
  381. /package/dist/{chunk-FYKIEOG6.js.map → chunk-VCFADTFS.js.map} +0 -0
  382. /package/dist/{chunk-T7VNN3ZM.js.map → chunk-XVLEGMJI.js.map} +0 -0
  383. /package/dist/{chunk-CRFTLUWT.js.map → chunk-Y5U35ZVS.js.map} +0 -0
  384. /package/dist/{chunk-UHGHTOR5.js.map → chunk-YGAOLHKN.js.map} +0 -0
  385. /package/dist/{chunk-QDCJNRKK.js.map → chunk-YXOAQAH2.js.map} +0 -0
  386. /package/dist/{forget-KHF7A44H.js.map → forget-CQCLB5LB.js.map} +0 -0
@@ -1,38 +1,40 @@
1
1
  import {
2
2
  compareVerifiedEpisodeResults,
3
3
  searchVerifiedEpisodes
4
- } from "./chunk-R2SJDIPO.js";
4
+ } from "./chunk-KPXAJ77O.js";
5
5
  import "./chunk-2A3OXAP2.js";
6
6
  import "./chunk-ZBJMUXZH.js";
7
- import "./chunk-KTOH7EJE.js";
7
+ import "./chunk-PV7E2FGY.js";
8
8
  import "./chunk-B3ABVQ36.js";
9
9
  import "./chunk-L2B3EE7B.js";
10
10
  import "./chunk-5UZXUTVO.js";
11
11
  import "./chunk-VSMRDBFT.js";
12
+ import "./chunk-LTJAMRGI.js";
12
13
  import "./chunk-EHK6KZHK.js";
13
14
  import "./chunk-6CIAGZ6X.js";
14
15
  import "./chunk-J6A3CX5N.js";
15
16
  import "./chunk-4KJLYTLS.js";
16
17
  import "./chunk-SVOZFLIQ.js";
17
- import "./chunk-LTJAMRGI.js";
18
- import "./chunk-JO5AT6QT.js";
19
- import "./chunk-RHOZ5LLO.js";
20
- import "./chunk-RL6NEVXT.js";
21
- import "./chunk-AWJ2FHCF.js";
22
- import "./chunk-42JKGUFJ.js";
18
+ import "./chunk-3ZVFLMFQ.js";
23
19
  import "./chunk-RULE4VG5.js";
24
20
  import "./chunk-SCU65EZI.js";
21
+ import "./chunk-RHOZ5LLO.js";
22
+ import "./chunk-RL6NEVXT.js";
25
23
  import "./chunk-DM2T26WE.js";
26
24
  import "./chunk-LDXUBPMO.js";
27
- import "./chunk-LKT755LP.js";
25
+ import "./chunk-VA4WSW54.js";
28
26
  import "./chunk-AAD2ZS6P.js";
29
27
  import "./chunk-G7D6GZ5J.js";
30
- import "./chunk-VF4XKTX3.js";
28
+ import "./chunk-VZ5OJE4X.js";
29
+ import "./chunk-OKUEZOGW.js";
30
+ import "./chunk-X47LWMKA.js";
31
+ import "./chunk-42JKGUFJ.js";
32
+ import "./chunk-PDJTHRAW.js";
31
33
  import "./chunk-W5H6ZRPT.js";
32
- import "./chunk-GKCCHHZK.js";
34
+ import "./chunk-UXKMMNJD.js";
33
35
  import "./chunk-K2ZLHESQ.js";
34
- import "./chunk-L2EXJQJP.js";
35
36
  import "./chunk-VFSP73LP.js";
37
+ import "./chunk-L2EXJQJP.js";
36
38
  import "./chunk-RGMVMVMF.js";
37
39
  import "./chunk-N7RWREIQ.js";
38
40
  import "./chunk-OEHCMALU.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/core",
3
- "version": "9.7.8",
3
+ "version": "9.7.9",
4
4
  "description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1090,6 +1090,16 @@
1090
1090
  "remnic-source": "./src/importance.ts",
1091
1091
  "import": "./dist/importance.js"
1092
1092
  },
1093
+ "./in-flight-reads": {
1094
+ "types": "./dist/in-flight-reads.d.ts",
1095
+ "remnic-source": "./src/in-flight-reads.ts",
1096
+ "import": "./dist/in-flight-reads.js"
1097
+ },
1098
+ "./in-flight-reads.js": {
1099
+ "types": "./dist/in-flight-reads.d.ts",
1100
+ "remnic-source": "./src/in-flight-reads.ts",
1101
+ "import": "./dist/in-flight-reads.js"
1102
+ },
1093
1103
  "./index": {
1094
1104
  "types": "./dist/index.d.ts",
1095
1105
  "remnic-source": "./src/index.ts",
@@ -3000,7 +3010,7 @@
3000
3010
  "core"
3001
3011
  ],
3002
3012
  "peerDependencies": {
3003
- "@remnic/coding-graph": "^9.7.8"
3013
+ "@remnic/coding-graph": "^9.7.9"
3004
3014
  },
3005
3015
  "peerDependenciesMeta": {
3006
3016
  "@remnic/coding-graph": {
@@ -18,6 +18,21 @@ import type {
18
18
  import type { BinaryStorageBackend } from "./backend.js";
19
19
  import { readManifest, writeManifest } from "./manifest.js";
20
20
  import { scanForBinaries } from "./scanner.js";
21
+ import { bumpMemoryCorpusVersionForDir } from "../memory-corpus-version.js";
22
+ import { RECALL_FALLBACK_DIRS } from "../utils/category-dir.js";
23
+
24
+ /**
25
+ * True when `mdPath` is an active recall-corpus memory file under `memoryDir`
26
+ * (a top-level RECALL_FALLBACK_DIRS category), so a redirect rewrite of it must
27
+ * bump the corpus sentinel to self-heal a warm hot-memories cache (#1902).
28
+ * entities/, artifacts/, and other non-recall paths need no bump.
29
+ */
30
+ function isRecallCorpusMarkdown(mdPath: string, memoryDir: string): boolean {
31
+ const rel = path.relative(memoryDir, mdPath);
32
+ if (rel.startsWith("..") || path.isAbsolute(rel)) return false;
33
+ const top = rel.split(path.sep)[0];
34
+ return (RECALL_FALLBACK_DIRS as readonly string[]).includes(top);
35
+ }
21
36
 
22
37
  /** Minimal logger interface so we don't depend on the full logger module. */
23
38
  interface PipelineLogger {
@@ -305,6 +320,13 @@ async function stageRedirect(
305
320
  for (const update of updates) {
306
321
  try {
307
322
  await writeMarkdownFile(update.mdPath, update.content);
323
+ // The redirect rewrote an on-disk memory file out-of-band (not through a
324
+ // StorageManager mutation). Bump the corpus sentinel per write so a warm
325
+ // hot-memories cache rescans — mid-batch too, never serving pre-redirect
326
+ // content (#1902). Only recall-corpus files affect that cache.
327
+ if (isRecallCorpusMarkdown(update.mdPath, memoryDir)) {
328
+ bumpMemoryCorpusVersionForDir(memoryDir);
329
+ }
308
330
  } catch (err) {
309
331
  writeFailCount++;
310
332
  const msg = `redirect write failed for ${update.mdPath}: ${err instanceof Error ? err.message : String(err)}`;
package/src/cli.ts CHANGED
@@ -10,6 +10,7 @@ import { resolveNamespaceCapabilities,
10
10
  resolveIdentityContinuityCapabilities,
11
11
  resolveSecurityCapabilities, resolveEvalCapabilities, resolveConsolidationCapabilities, resolveRecallAuxiliaryCapabilities } from "./capabilities.js";
12
12
  import { ThreadingManager } from "./threading.js";
13
+ import { bumpMemoryCorpusVersionForDir } from "./memory-corpus-version.js";
13
14
  import { utcDayRange } from "./transcript.js";
14
15
  import { runWearablesCliCommand } from "./wearables/cli.js";
15
16
  import { registerResearchStatusCommands } from "./cli/research-status-commands.js";
@@ -7495,6 +7496,11 @@ export function registerCli(
7495
7496
  try {
7496
7497
  await unlink(filePath);
7497
7498
  deleted += 1;
7499
+ // Per-delete corpus bump (Cursor Medium, #1902): dedupe removes
7500
+ // active memory files directly (bypassing StorageManager), so bump
7501
+ // each delete to keep a same-process or peer readAllMemories from
7502
+ // recalling a duplicate that was already removed mid-batch.
7503
+ bumpMemoryCorpusVersionForDir(memoryDir);
7498
7504
  } catch (err) {
7499
7505
  console.log(` failed to delete ${filePath}: ${String(err)}`);
7500
7506
  }
@@ -7556,6 +7562,8 @@ export function registerCli(
7556
7562
  try {
7557
7563
  await unlink(filePath);
7558
7564
  deleted += 1;
7565
+ // Per-delete corpus bump (Cursor Medium, #1902) — see dedupe-exact.
7566
+ bumpMemoryCorpusVersionForDir(memoryDir);
7559
7567
  } catch (err) {
7560
7568
  console.log(` failed to delete ${filePath}: ${String(err)}`);
7561
7569
  }
@@ -321,7 +321,15 @@ function normalizePromotionWhitespace(value: string): string {
321
321
  }
322
322
 
323
323
  function stripTrailingPromotionPunctuation(value: string): string {
324
- return value.replace(/[,:;]+$/g, "").trim();
324
+ // Linear trailing-punctuation strip (no `/[,:;]+$/` — CodeQL flags that as a
325
+ // polynomial-backtracking ReDoS on long runs of ',;:'). Walk back once, O(n).
326
+ let end = value.length;
327
+ while (end > 0) {
328
+ const ch = value[end - 1];
329
+ if (ch === "," || ch === ":" || ch === ";") end--;
330
+ else break;
331
+ }
332
+ return value.slice(0, end).trim();
325
333
  }
326
334
 
327
335
  function extractExplicitIfThenRule(value: string): string | null {
package/src/config.ts CHANGED
@@ -2106,6 +2106,20 @@ export function parseConfig(
2106
2106
  // opt out with recallMemoryWorthFilterEnabled=false.
2107
2107
  recallMemoryWorthFilterEnabled:
2108
2108
  coerceBool(cfg.recallMemoryWorthFilterEnabled) ?? true,
2109
+ // Hot-memories result cache (issue #1902). Default on: readAllMemories()
2110
+ // serves from the version-keyed in-process corpus cache. coerceBool
2111
+ // handles "false"/"0" string forms; set false to force disk scans.
2112
+ hotMemoriesCacheEnabled: coerceBool(cfg.hotMemoriesCacheEnabled) ?? true,
2113
+ // External-edit safety net (issue #1902): the version sentinel gives
2114
+ // immediate coherence for cooperating writers, but direct user/git/editor
2115
+ // writes to memory files (which the project supports) don't bump it. Bound
2116
+ // the hot cache's staleness with a TTL so such edits self-heal. Default 60s;
2117
+ // 0 disables the TTL (version invalidation only — max perf for pure-daemon
2118
+ // deployments with no external edits). coerceNumber handles string forms.
2119
+ hotMemoriesCacheTtlMs: (() => {
2120
+ const n = coerceNumber(cfg.hotMemoriesCacheTtlMs);
2121
+ return n !== undefined && n >= 0 ? n : 60_000;
2122
+ })(),
2109
2123
  recallMemoryWorthHalfLifeMs: (() => {
2110
2124
  const n = coerceNumber(cfg.recallMemoryWorthHalfLifeMs);
2111
2125
  return n !== undefined && n >= 0 ? n : 0;
@@ -25,6 +25,7 @@ import { mkdir, writeFile, access, realpath, lstat } from "node:fs/promises";
25
25
  import { constants as fsConstants } from "node:fs";
26
26
  import type { StorageManager } from "./storage.js";
27
27
  import type { VersioningConfig } from "./page-versioning.js";
28
+ import { bumpMemoryCorpusVersionForDir } from "./memory-corpus-version.js";
28
29
  import { getVersion } from "./page-versioning.js";
29
30
 
30
31
  /**
@@ -646,6 +647,13 @@ export async function runConsolidationUndo(options: {
646
647
  // write fails with EEXIST instead of silently overwriting the new
647
648
  // file (PR #637 round-11 review, codex P1).
648
649
  await writeFile(p.sourcePath, p.content, { encoding: "utf-8", flag: "wx" });
650
+ // Restore writes an active memory file back out-of-band (direct wx write,
651
+ // not a StorageManager mutation). Bump the corpus sentinel per successful
652
+ // restore so a warm hot-memories cache rescans — a later restore failure
653
+ // returns before archiveMemory() runs, so without this the already-written
654
+ // restores would stay invisible to recall until an unrelated mutation or
655
+ // restart (esp. with hotMemoriesCacheTtlMs: 0). Issue #1902, Codex Medium.
656
+ bumpMemoryCorpusVersionForDir(memoryDir);
649
657
  result.restores.push({
650
658
  entry: p.entry,
651
659
  sourcePath: p.sourcePath,
@@ -9,6 +9,7 @@ import fs from "node:fs";
9
9
  import path from "node:path";
10
10
  import crypto from "node:crypto";
11
11
  import { getCategoryDir, ALL_CATEGORY_DIRS } from "../utils/category-dir.js";
12
+ import { bumpMemoryCorpusVersionForDir } from "../memory-corpus-version.js";
12
13
 
13
14
  // ── Types ────────────────────────────────────────────────────────────────────
14
15
 
@@ -202,6 +203,10 @@ export async function curate(options: CurateOptions): Promise<CurateResult> {
202
203
  }
203
204
  }
204
205
 
206
+ // Per-statement corpus bumps happen in writeStatement (below) so a
207
+ // same-process readAllMemories mid-batch never serves a stale/partial corpus
208
+ // (Cursor Medium, #1902); no after-loop bump needed here.
209
+
205
210
  return {
206
211
  statements,
207
212
  filesProcessed,
@@ -471,6 +476,10 @@ function writeStatement(stmt: CuratedStatement, memoryDir: string): string {
471
476
  const body = `${frontmatter}\n\n${stmt.content}\n`;
472
477
 
473
478
  fs.writeFileSync(filePath, body);
479
+ // Bump the corpus sentinel per write (out-of-band create) so a concurrent
480
+ // same-process readAllMemories rescans and sees this statement immediately,
481
+ // never a stale/partial corpus mid-batch (Cursor Medium, #1902).
482
+ bumpMemoryCorpusVersionForDir(memoryDir);
474
483
  return filePath;
475
484
  }
476
485
 
@@ -0,0 +1,63 @@
1
+ import type { MemoryFile } from "./types.js";
2
+
3
+ /**
4
+ * In-flight readAllMemories() dedup registry (issue #1902).
5
+ *
6
+ * NOT a cache layer — it holds transient per-(directory, secure-store key) scan
7
+ * promises so temporally-overlapping reads collapse onto ONE disk scan; the slot
8
+ * is deleted when the promise settles. It lives in its own module (not
9
+ * memory-cache.ts) so it is not swept by the ALL_CACHE_LAYERS invalidation
10
+ * contract, yet remains importable by both StorageManager and the out-of-band
11
+ * corpus-bump helper (memory-corpus-version.ts).
12
+ *
13
+ * Keyed by baseDir AND secure-store key identity (Codex P1 / Cursor Medium):
14
+ * an unlocked manager's decrypted scan must NOT be handed to a locked or
15
+ * differently-keyed manager for the same dir — that would bypass the keyId
16
+ * isolation getCachedMemories enforces. Locked/plaintext stores use keyId "".
17
+ */
18
+ const inFlightReadsByKey = new Map<string, Promise<MemoryFile[]>>();
19
+
20
+ const DIR_SEP = "\u0000";
21
+
22
+ function composeKey(baseDir: string, keyId: string): string {
23
+ return `${baseDir}${DIR_SEP}${keyId}`;
24
+ }
25
+
26
+ export function getInFlightRead(baseDir: string, keyId = ""): Promise<MemoryFile[]> | undefined {
27
+ return inFlightReadsByKey.get(composeKey(baseDir, keyId));
28
+ }
29
+
30
+ export function setInFlightRead(baseDir: string, keyId: string, read: Promise<MemoryFile[]>): void {
31
+ inFlightReadsByKey.set(composeKey(baseDir, keyId), read);
32
+ }
33
+
34
+ /**
35
+ * Delete the in-flight slot for one (baseDir, keyId). When `expected` is given,
36
+ * only deletes if the slot still holds that exact promise (owner-only clear).
37
+ */
38
+ export function deleteInFlightRead(
39
+ baseDir: string,
40
+ keyId = "",
41
+ expected?: Promise<MemoryFile[]>,
42
+ ): void {
43
+ const key = composeKey(baseDir, keyId);
44
+ if (expected === undefined || inFlightReadsByKey.get(key) === expected) {
45
+ inFlightReadsByKey.delete(key);
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Drop EVERY in-flight slot for `baseDir` across all secure-store identities.
51
+ * Used by mutations / invalidation / out-of-band corpus bumps: after the corpus
52
+ * changes, no reader of any key identity may attach to a pre-mutation scan.
53
+ */
54
+ export function deleteInFlightReadsForDir(baseDir: string): void {
55
+ const prefix = `${baseDir}${DIR_SEP}`;
56
+ for (const key of inFlightReadsByKey.keys()) {
57
+ if (key.startsWith(prefix)) inFlightReadsByKey.delete(key);
58
+ }
59
+ }
60
+
61
+ export function clearInFlightReads(): void {
62
+ inFlightReadsByKey.clear();
63
+ }
@@ -4,6 +4,7 @@ import { StorageManager } from "../storage.js";
4
4
  import { decideLifecycleTransition } from "../lifecycle.js";
5
5
  import type { MemoryFile, MemoryStatus } from "../types.js";
6
6
  import { RECALL_FALLBACK_DIRS } from "../utils/category-dir.js";
7
+ import { bumpMemoryCorpusVersionForDir } from "../memory-corpus-version.js";
7
8
  import { assertPathInsideRoot } from "../utils/path-containment.js";
8
9
 
9
10
  export type MemoryGovernanceMode = "shadow" | "apply";
@@ -1015,6 +1016,11 @@ export async function restoreMemoryGovernanceRun(
1015
1016
  await mkdir(path.dirname(entry.originalPath), { recursive: true });
1016
1017
  await writeFile(entry.originalPath, entry.beforeRaw, "utf-8");
1017
1018
  restoredActions += 1;
1019
+ // Restore writes/removes memory files directly (out-of-band — not through a
1020
+ // StorageManager mutation). Bump the corpus sentinel PER entry so a
1021
+ // same-process or peer readAllMemories rescans mid-batch and never serves a
1022
+ // partially-restored corpus (Cursor Medium, #1902).
1023
+ bumpMemoryCorpusVersionForDir(options.memoryDir);
1018
1024
  }
1019
1025
 
1020
1026
  return {
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Issue #1902 — unit tests for the hot-memories result cache layer.
3
+ *
4
+ * These pin the low-level cache contract that StorageManager.readAllMemories()
5
+ * relies on: version-keyed round-trip, the version-0 and version-mismatch null
6
+ * guards, in-place patch-on-write / patch-on-delete, and the two invalidation
7
+ * shapes (wholesale drop vs derived/global-only keep).
8
+ */
9
+
10
+ import assert from "node:assert/strict";
11
+ import test from "node:test";
12
+
13
+ import {
14
+ clearMemoryCache,
15
+ getCachedMemories,
16
+ invalidateAllForDir,
17
+ invalidateDerivedAndGlobalForDir,
18
+ setCachedMemories,
19
+ updateCacheOnDelete,
20
+ updateCacheOnWrite,
21
+ } from "./memory-cache.js";
22
+ import type { MemoryFile } from "./types.js";
23
+
24
+ function mem(p: string, content = "x"): MemoryFile {
25
+ return {
26
+ path: p,
27
+ frontmatter: { id: p, category: "fact" },
28
+ content,
29
+ } as unknown as MemoryFile;
30
+ }
31
+
32
+ test("hot cache: round-trips at a matching version", () => {
33
+ const dir = "/tmp/remnic-hot-unit-a";
34
+ clearMemoryCache();
35
+ setCachedMemories(dir, [mem("a.md"), mem("b.md")], 3);
36
+ const got = getCachedMemories(dir, 3);
37
+ assert.ok(got, "expected a cache hit at the matching version");
38
+ assert.deepEqual(got!.map((m) => m.path).sort(), ["a.md", "b.md"]);
39
+ clearMemoryCache();
40
+ });
41
+
42
+ test("hot cache: version 0 always misses (fresh/test dirs)", () => {
43
+ const dir = "/tmp/remnic-hot-unit-b";
44
+ clearMemoryCache();
45
+ setCachedMemories(dir, [mem("a.md")], 0);
46
+ assert.equal(getCachedMemories(dir, 0), null, "version 0 must never serve a cache hit");
47
+ clearMemoryCache();
48
+ });
49
+
50
+ test("hot cache: version mismatch misses (never serves stale)", () => {
51
+ const dir = "/tmp/remnic-hot-unit-c";
52
+ clearMemoryCache();
53
+ setCachedMemories(dir, [mem("a.md")], 5);
54
+ assert.ok(getCachedMemories(dir, 5), "same version hits");
55
+ assert.equal(getCachedMemories(dir, 6), null, "a bumped version must miss");
56
+ clearMemoryCache();
57
+ });
58
+
59
+ test("hot cache: updateCacheOnWrite / updateCacheOnDelete mutate the entry in place", () => {
60
+ const dir = "/tmp/remnic-hot-unit-d";
61
+ clearMemoryCache();
62
+ setCachedMemories(dir, [mem("a.md")], 2);
63
+ updateCacheOnWrite(dir, mem("b.md", "new"));
64
+ const afterWrite = getCachedMemories(dir, 2);
65
+ assert.deepEqual(afterWrite!.map((m) => m.path).sort(), ["a.md", "b.md"], "write adds in place");
66
+ updateCacheOnWrite(dir, mem("a.md", "updated"));
67
+ assert.equal(
68
+ getCachedMemories(dir, 2)!.find((m) => m.path === "a.md")!.content,
69
+ "updated",
70
+ "write to an existing path replaces in place",
71
+ );
72
+ updateCacheOnDelete(dir, "a.md");
73
+ assert.deepEqual(getCachedMemories(dir, 2)!.map((m) => m.path), ["b.md"], "delete removes in place");
74
+ clearMemoryCache();
75
+ });
76
+
77
+ test("hot cache: wholesale invalidateAllForDir drops the hot layer; invalidateDerivedAndGlobalForDir keeps it", () => {
78
+ const dir = "/tmp/remnic-hot-unit-e";
79
+ clearMemoryCache();
80
+ setCachedMemories(dir, [mem("a.md")], 4);
81
+ invalidateDerivedAndGlobalForDir(dir);
82
+ assert.ok(
83
+ getCachedMemories(dir, 4),
84
+ "invalidateDerivedAndGlobalForDir must NOT drop the hot layer (patch-on-write keeps it warm)",
85
+ );
86
+ invalidateAllForDir(dir);
87
+ assert.equal(getCachedMemories(dir, 4), null, "invalidateAllForDir must drop the hot layer");
88
+ clearMemoryCache();
89
+ });
90
+
91
+ test("hot cache: keyId scopes entries — a mismatched secure-store key misses (#1902 Codex P1)", () => {
92
+ const dir = "/tmp/remnic-hot-unit-keyid";
93
+ clearMemoryCache();
94
+ // A keyed (unlocked encrypted) manager warms the cache with decrypted content.
95
+ setCachedMemories(dir, [mem("secret.md", "decrypted")], 5, "secure-store:key:1");
96
+ // A locked/unkeyed manager for the SAME dir must NOT read the decrypted entry.
97
+ assert.equal(
98
+ getCachedMemories(dir, 5, ""),
99
+ null,
100
+ "a manager without the matching key must miss the decrypted cache entry",
101
+ );
102
+ // A different key id also misses.
103
+ assert.equal(getCachedMemories(dir, 5, "secure-store:key:2"), null, "a different key id misses");
104
+ // The matching key id hits.
105
+ const got = getCachedMemories(dir, 5, "secure-store:key:1");
106
+ assert.ok(got, "the matching key id serves the cached corpus");
107
+ assert.deepEqual(got!.map((m) => m.path), ["secret.md"]);
108
+ clearMemoryCache();
109
+ });
110
+
111
+ test("hot cache: TTL expires an entry so external edits self-heal (#1902 Codex P1)", (t) => {
112
+ const dir = "/tmp/remnic-hot-unit-ttl";
113
+ clearMemoryCache();
114
+ // Deterministic time control (no real timers): the entry's loadedAt is stamped
115
+ // from the mocked clock at set time; advancing it past the TTL forces a miss.
116
+ t.mock.timers.enable({ apis: ["Date"] });
117
+ try {
118
+ setCachedMemories(dir, [mem("a.md")], 9, "");
119
+ // ttl=0 disables the TTL: always a hit at the matching version.
120
+ assert.ok(getCachedMemories(dir, 9, "", 0), "ttl=0 disables expiry");
121
+ // Fresh entry within a generous TTL still hits.
122
+ assert.ok(getCachedMemories(dir, 9, "", 60_000), "fresh entry within TTL hits");
123
+ // Advance past the TTL: the entry is now a miss, forcing a rescan that would
124
+ // pick up any external filesystem edit that bypassed the version sentinel.
125
+ t.mock.timers.tick(120_000);
126
+ assert.equal(getCachedMemories(dir, 9, "", 60_000), null, "entry older than ttl is a miss");
127
+ } finally {
128
+ t.mock.timers.reset();
129
+ clearMemoryCache();
130
+ }
131
+ });