@remnic/core 9.29.0 → 9.30.0

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 (359) hide show
  1. package/dist/access-admin-ops-surface.d.ts +11 -11
  2. package/dist/access-admin-ops-surface.js +19 -18
  3. package/dist/access-authorization-probe.d.ts +11 -11
  4. package/dist/access-authorization-probe.js +20 -19
  5. package/dist/access-boundary.d.ts +11 -11
  6. package/dist/access-boundary.js +19 -18
  7. package/dist/access-citation-namespace.js +2 -2
  8. package/dist/access-cli.js +45 -44
  9. package/dist/access-cli.js.map +1 -1
  10. package/dist/access-health-types.d.ts +1 -1
  11. package/dist/access-http-lcm-compaction.d.ts +11 -11
  12. package/dist/access-http.d.ts +11 -11
  13. package/dist/access-http.js +25 -24
  14. package/dist/access-identity-continuity-surface.d.ts +8 -8
  15. package/dist/access-identity-continuity-surface.js +19 -18
  16. package/dist/access-lcm-surface.d.ts +10 -10
  17. package/dist/access-lcm-surface.js +19 -18
  18. package/dist/access-mcp.d.ts +11 -11
  19. package/dist/access-mcp.js +23 -22
  20. package/dist/access-memory-search-fanout.d.ts +2 -2
  21. package/dist/{access-namespace-preflight-DCXBkDp0.d.ts → access-namespace-preflight-VfXssvoI.d.ts} +1 -1
  22. package/dist/access-namespace-preflight.d.ts +3 -3
  23. package/dist/access-namespace-preflight.js +19 -18
  24. package/dist/access-observe-write-surface.d.ts +10 -10
  25. package/dist/access-observe-write-surface.js +19 -18
  26. package/dist/access-operations-batch.js +20 -19
  27. package/dist/access-operations.d.ts +11 -11
  28. package/dist/access-operations.js +22 -21
  29. package/dist/access-recall-concurrency.d.ts +11 -11
  30. package/dist/access-recall-concurrency.js +19 -18
  31. package/dist/access-recall-response.d.ts +10 -10
  32. package/dist/access-recall-response.js +19 -18
  33. package/dist/access-recall-surface.d.ts +10 -10
  34. package/dist/access-recall-surface.js +19 -18
  35. package/dist/access-schema.d.ts +7 -7
  36. package/dist/access-schema.js +3 -3
  37. package/dist/{access-service-DvPW_M5j.d.ts → access-service-B5RwVsTV.d.ts} +7 -7
  38. package/dist/access-service.d.ts +11 -11
  39. package/dist/access-service.js +19 -18
  40. package/dist/access-surface-catalog.d.ts +11 -11
  41. package/dist/access-wearables-meetings-surface.d.ts +4 -3
  42. package/dist/action-confidence.d.ts +1 -1
  43. package/dist/active-memory-bridge.d.ts +1 -1
  44. package/dist/active-recall.d.ts +1 -1
  45. package/dist/active-recall.js +3 -3
  46. package/dist/behavior-learner.d.ts +1 -1
  47. package/dist/behavior-signals.d.ts +1 -1
  48. package/dist/bootstrap.d.ts +8 -8
  49. package/dist/briefing.d.ts +3 -2
  50. package/dist/briefing.js +10 -9
  51. package/dist/buffer-surprise-report.d.ts +1 -1
  52. package/dist/buffer.d.ts +3 -2
  53. package/dist/bulk-import/index.d.ts +3 -3
  54. package/dist/calibration.d.ts +1 -1
  55. package/dist/capabilities.d.ts +1 -1
  56. package/dist/{catalog-BIVgftWu.d.ts → catalog-V7inUQdp.d.ts} +1 -1
  57. package/dist/causal-behavior.d.ts +1 -1
  58. package/dist/causal-consolidation.d.ts +1 -1
  59. package/dist/causal-consolidation.js +11 -10
  60. package/dist/causal-consolidation.js.map +1 -1
  61. package/dist/causal-trajectory-graph.d.ts +1 -1
  62. package/dist/{chunk-KUJQHXPH.js → chunk-2EUVEDF5.js} +2 -2
  63. package/dist/{chunk-2XC73SHY.js → chunk-4WKA6I65.js} +20 -20
  64. package/dist/{chunk-2XC73SHY.js.map → chunk-4WKA6I65.js.map} +1 -1
  65. package/dist/{chunk-AIK5W3IW.js → chunk-5TFP4CUL.js} +68 -2
  66. package/dist/chunk-5TFP4CUL.js.map +1 -0
  67. package/dist/{chunk-EVX44I7C.js → chunk-5W4ZLBEZ.js} +9 -9
  68. package/dist/{chunk-P3MH72CI.js → chunk-62U4J2GN.js} +2 -2
  69. package/dist/{chunk-YGHMSDLK.js → chunk-66772WBP.js} +2 -2
  70. package/dist/{chunk-EP5BVCRI.js → chunk-6BNE62PM.js} +2 -2
  71. package/dist/{chunk-AAP5T6QG.js → chunk-6DNMUYEE.js} +2 -2
  72. package/dist/{chunk-SG265CVF.js → chunk-6FUPCJUL.js} +7 -7
  73. package/dist/{chunk-WZ7UB7XQ.js → chunk-6U7F52DE.js} +19 -19
  74. package/dist/{chunk-E4OCKU67.js → chunk-7XC2HX75.js} +2 -2
  75. package/dist/{chunk-OVRQLAYR.js → chunk-AZ5BTEKX.js} +2 -2
  76. package/dist/{chunk-2HNUMF5V.js → chunk-CZRYLSSW.js} +3 -3
  77. package/dist/chunk-FBUE6PD3.js +1769 -0
  78. package/dist/chunk-FBUE6PD3.js.map +1 -0
  79. package/dist/{chunk-WONS4RZ2.js → chunk-FDAMS4PK.js} +2 -2
  80. package/dist/{chunk-WL5EBRDH.js → chunk-FFAZ2XFU.js} +9 -8
  81. package/dist/chunk-FFAZ2XFU.js.map +1 -0
  82. package/dist/{chunk-Q6VFVAKZ.js → chunk-GIBMDSJ2.js} +2 -2
  83. package/dist/{chunk-ZXAGJFHJ.js → chunk-H5CPS5JP.js} +3 -3
  84. package/dist/{chunk-NBDCZWP4.js → chunk-I5NLEENJ.js} +2 -2
  85. package/dist/{chunk-DRBXHRXE.js → chunk-IB26HVAJ.js} +2 -2
  86. package/dist/{chunk-XEQ7OT7U.js → chunk-IC6CBHCA.js} +3 -3
  87. package/dist/{chunk-CMRQ34J5.js → chunk-JCBWCYEJ.js} +2 -2
  88. package/dist/{chunk-3PDOVUHC.js → chunk-KXB4VXHY.js} +2 -2
  89. package/dist/{chunk-G6LBWZRF.js → chunk-LBOD4U5B.js} +7 -7
  90. package/dist/{chunk-ZGOQTOYA.js → chunk-LGHKJABJ.js} +3 -3
  91. package/dist/{chunk-T3GCXULH.js → chunk-M3C2V3PV.js} +10 -10
  92. package/dist/{chunk-OFHFH655.js → chunk-MJCGLM25.js} +8 -8
  93. package/dist/{chunk-JDZRYH2N.js → chunk-NHWB6HG2.js} +2 -2
  94. package/dist/{chunk-TC3VNKGX.js → chunk-NM2WP3B7.js} +4 -4
  95. package/dist/{chunk-IMA2EWLV.js → chunk-P5PXWTW7.js} +2 -2
  96. package/dist/chunk-PH3ZWL3W.js +786 -0
  97. package/dist/chunk-PH3ZWL3W.js.map +1 -0
  98. package/dist/{chunk-QMBNMPQM.js → chunk-PUS63Q3G.js} +24 -22
  99. package/dist/{chunk-QMBNMPQM.js.map → chunk-PUS63Q3G.js.map} +1 -1
  100. package/dist/{chunk-2QMKMVHH.js → chunk-QNWXCJ76.js} +2 -2
  101. package/dist/{chunk-FCDWWCLX.js → chunk-RGIWINDN.js} +427 -795
  102. package/dist/chunk-RGIWINDN.js.map +1 -0
  103. package/dist/{chunk-CSMCNOPH.js → chunk-SPJXKAVF.js} +3 -3
  104. package/dist/{chunk-4PBVXX7L.js → chunk-TH2LSRMG.js} +2 -2
  105. package/dist/{chunk-ESBQWC3U.js → chunk-VI2JQPNQ.js} +2 -2
  106. package/dist/{chunk-GGUBDXRR.js → chunk-W5EG6LE3.js} +2 -2
  107. package/dist/{chunk-DEBHXHJR.js → chunk-WIPEXG6R.js} +2 -2
  108. package/dist/{chunk-SH6YO3LT.js → chunk-WVO4G37W.js} +2 -2
  109. package/dist/{chunk-VVIW3PTA.js → chunk-YTQNQ4KB.js} +14 -14
  110. package/dist/{chunk-PKRIQL3V.js → chunk-YTSNAUXN.js} +2 -2
  111. package/dist/{chunk-QAOGGNE3.js → chunk-ZPSVBSOF.js} +4 -4
  112. package/dist/{cli-CxoSOiG0.d.ts → cli-C4GbETPC.d.ts} +5 -5
  113. package/dist/cli.d.ts +13 -13
  114. package/dist/cli.js +36 -35
  115. package/dist/compounding/engine.d.ts +3 -2
  116. package/dist/compounding/engine.js +10 -9
  117. package/dist/compounding/preference-consolidator.d.ts +1 -1
  118. package/dist/compression-optimizer.d.ts +1 -1
  119. package/dist/config.d.ts +1 -1
  120. package/dist/config.js +3 -3
  121. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  122. package/dist/connectors/codex-materialize-runner.js +10 -9
  123. package/dist/connectors/codex-materialize.d.ts +1 -1
  124. package/dist/connectors/index.d.ts +1 -1
  125. package/dist/connectors/index.js +10 -9
  126. package/dist/consolidation-provenance-check.d.ts +3 -2
  127. package/dist/consolidation-undo.d.ts +3 -2
  128. package/dist/contradiction/index.d.ts +3 -2
  129. package/dist/conversation-index/backend.d.ts +1 -1
  130. package/dist/conversation-index/chunker.d.ts +1 -1
  131. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  132. package/dist/conversation-index/indexer.d.ts +1 -1
  133. package/dist/conversation-index/search.d.ts +1 -1
  134. package/dist/corpus-watermark.d.ts +1 -1
  135. package/dist/corpus-watermark.js +12 -11
  136. package/dist/day-summary.d.ts +1 -1
  137. package/dist/delinearize.d.ts +1 -1
  138. package/dist/direct-answer-wiring.d.ts +1 -1
  139. package/dist/direct-answer.d.ts +1 -1
  140. package/dist/embedding-fallback.d.ts +1 -1
  141. package/dist/enrichment/index.d.ts +1 -1
  142. package/dist/entity-retrieval.d.ts +3 -2
  143. package/dist/entity-retrieval.js +10 -9
  144. package/dist/entity-schema.d.ts +1 -1
  145. package/dist/explicit-capture.d.ts +52 -10
  146. package/dist/explicit-capture.js +13 -1
  147. package/dist/extraction-error-classification.d.ts +1 -1
  148. package/dist/extraction-faithfulness.d.ts +1 -1
  149. package/dist/extraction-judge-telemetry.d.ts +1 -1
  150. package/dist/extraction-judge-training.d.ts +1 -1
  151. package/dist/extraction-judge.d.ts +1 -1
  152. package/dist/extraction-liveness.d.ts +1 -1
  153. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  154. package/dist/extraction-source-grounding.d.ts +1 -1
  155. package/dist/extraction.d.ts +1 -1
  156. package/dist/fallback-llm.d.ts +1 -1
  157. package/dist/{forget-HRPLVB3W.js → forget-4UY2EOKH.js} +3 -3
  158. package/dist/graph-dashboard-diff.d.ts +1 -1
  159. package/dist/graph-dashboard-key.d.ts +1 -1
  160. package/dist/graph-dashboard-parser.d.ts +1 -1
  161. package/dist/graph-edge-reinforcement.d.ts +1 -1
  162. package/dist/graph-snapshot.d.ts +1 -1
  163. package/dist/graph.d.ts +1 -1
  164. package/dist/importance.d.ts +1 -1
  165. package/dist/importers/index.d.ts +1 -1
  166. package/dist/in-flight-reads.d.ts +1 -1
  167. package/dist/index.d.ts +21 -21
  168. package/dist/index.js +47 -45
  169. package/dist/intent.d.ts +1 -1
  170. package/dist/lcm/engine.d.ts +1 -1
  171. package/dist/lcm/index.d.ts +1 -1
  172. package/dist/lcm/tools.d.ts +1 -1
  173. package/dist/lifecycle.d.ts +1 -1
  174. package/dist/live-connectors-runner.d.ts +1 -1
  175. package/dist/local-llm.d.ts +1 -1
  176. package/dist/local-model-endpoint.d.ts +1 -1
  177. package/dist/maintenance/memory-governance.d.ts +1 -1
  178. package/dist/maintenance/memory-governance.js +10 -9
  179. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  180. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +10 -9
  181. package/dist/maintenance/rebuild-memory-projection.d.ts +3 -2
  182. package/dist/maintenance/rebuild-memory-projection.js +11 -10
  183. package/dist/{maintenance-Cb-PjxQd.d.ts → maintenance-CL30NWtc.d.ts} +3 -3
  184. package/dist/mcp-memory-inspector-app.d.ts +11 -11
  185. package/dist/memory-action-policy.d.ts +1 -1
  186. package/dist/memory-cache.d.ts +1 -1
  187. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  188. package/dist/memory-projection-store.d.ts +1 -1
  189. package/dist/memory-provenance.d.ts +1 -1
  190. package/dist/memory-worth-outcomes.d.ts +3 -2
  191. package/dist/models-json.d.ts +1 -1
  192. package/dist/namespaces/migrate.d.ts +4 -3
  193. package/dist/namespaces/migrate.js +11 -10
  194. package/dist/namespaces/principal.d.ts +1 -1
  195. package/dist/namespaces/search.d.ts +1 -1
  196. package/dist/namespaces/storage.d.ts +4 -3
  197. package/dist/namespaces/storage.js +10 -9
  198. package/dist/native-knowledge.d.ts +1 -1
  199. package/dist/offline-sync-impression-drain.d.ts +1 -1
  200. package/dist/offline-sync-impression-drain.js +5 -5
  201. package/dist/offline-sync.js +2 -2
  202. package/dist/operator-doctor-corpus.d.ts +1 -1
  203. package/dist/operator-doctor-corpus.js +13 -12
  204. package/dist/operator-doctor-replica.d.ts +1 -1
  205. package/dist/operator-toolkit.d.ts +4 -3
  206. package/dist/operator-toolkit.js +18 -17
  207. package/dist/orchestration/compression-guideline-coordinator.d.ts +3 -2
  208. package/dist/orchestration/maintenance.d.ts +5 -4
  209. package/dist/orchestration/maintenance.js +15 -14
  210. package/dist/{orchestrator-5GKqb_HL.d.ts → orchestrator-CKTCRwWV.d.ts} +7 -7
  211. package/dist/orchestrator.d.ts +8 -8
  212. package/dist/orchestrator.js +45 -44
  213. package/dist/patterns-cli.d.ts +1 -1
  214. package/dist/{pipeline-3Qi1TpRo.d.ts → pipeline-B7wj4rRZ.d.ts} +1 -1
  215. package/dist/policy-runtime.d.ts +1 -1
  216. package/dist/proactive-contention.d.ts +1 -1
  217. package/dist/provenance.d.ts +1 -1
  218. package/dist/{purge-YSGX5BOG.js → purge-533FZLS4.js} +16 -9
  219. package/dist/purge-533FZLS4.js.map +1 -0
  220. package/dist/qmd-preflight.d.ts +2 -2
  221. package/dist/{qmd-D9JqzzRX.d.ts → qmd-q9tg4dHp.d.ts} +1 -1
  222. package/dist/qmd-recall-cache.d.ts +1 -1
  223. package/dist/qmd.d.ts +2 -2
  224. package/dist/recall-concurrency-config.d.ts +1 -1
  225. package/dist/recall-disclosure-escalation.d.ts +1 -1
  226. package/dist/recall-explain-renderer.d.ts +1 -1
  227. package/dist/recall-memory-map.d.ts +1 -1
  228. package/dist/recall-planner-llm.d.ts +1 -1
  229. package/dist/recall-state.d.ts +1 -1
  230. package/dist/recall-state.js +2 -2
  231. package/dist/recall-tag-filter.d.ts +1 -1
  232. package/dist/recall-timings.d.ts +1 -1
  233. package/dist/recall-xray-cli.d.ts +1 -1
  234. package/dist/recall-xray-renderer.d.ts +1 -1
  235. package/dist/recall-xray.d.ts +1 -1
  236. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  237. package/dist/replay/normalizers/claude.d.ts +1 -1
  238. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  239. package/dist/replay/normalizers/shared.d.ts +1 -1
  240. package/dist/replay/runner.d.ts +1 -1
  241. package/dist/replay/types.d.ts +1 -1
  242. package/dist/replica-divergence.d.ts +1 -1
  243. package/dist/replica-peers-config.d.ts +1 -1
  244. package/dist/resolve-auth-token.d.ts +1 -1
  245. package/dist/resume-bundles.js +4 -4
  246. package/dist/retrieval-agents.d.ts +2 -2
  247. package/dist/retrieval-tiers.d.ts +1 -1
  248. package/dist/routing/engine.d.ts +1 -1
  249. package/dist/routing/store.d.ts +1 -1
  250. package/dist/salvage-envelope.d.ts +1 -1
  251. package/dist/schemas.d.ts +22 -22
  252. package/dist/{scope-profiles-C4g6_UdP.d.ts → scope-profiles-CWDyglPM.d.ts} +1 -1
  253. package/dist/search/embed-helper.d.ts +1 -1
  254. package/dist/search/factory.d.ts +1 -1
  255. package/dist/search/index.d.ts +1 -1
  256. package/dist/search/lancedb-backend.d.ts +1 -1
  257. package/dist/search/meilisearch-backend.d.ts +1 -1
  258. package/dist/search/noop-backend.d.ts +1 -1
  259. package/dist/search/orama-backend.d.ts +1 -1
  260. package/dist/search/port.d.ts +1 -1
  261. package/dist/search/remote-backend.d.ts +1 -1
  262. package/dist/secure-store/index.js +2 -2
  263. package/dist/{semantic-consolidation-BrxqnzTW.d.ts → semantic-consolidation-BUE3deLn.d.ts} +1 -1
  264. package/dist/semantic-consolidation.d.ts +2 -2
  265. package/dist/semantic-consolidation.js +11 -10
  266. package/dist/semantic-rule-promotion.js +10 -9
  267. package/dist/semantic-rule-verifier.d.ts +1 -1
  268. package/dist/semantic-rule-verifier.js +10 -9
  269. package/dist/{service-Bi1JgxdP.d.ts → service-CXgM0bQG.d.ts} +2 -2
  270. package/dist/session-observer-bands.d.ts +1 -1
  271. package/dist/session-observer-state.d.ts +1 -1
  272. package/dist/shared-context/manager.d.ts +1 -1
  273. package/dist/signal.d.ts +1 -1
  274. package/dist/{storage-CcH6yPk2.d.ts → storage-DysJq-XH.d.ts} +163 -27
  275. package/dist/storage.d.ts +3 -2
  276. package/dist/storage.js +12 -10
  277. package/dist/summarizer.d.ts +1 -1
  278. package/dist/summarizer.js +3 -3
  279. package/dist/summary-snapshot.d.ts +1 -1
  280. package/dist/summary-snapshot.js +2 -2
  281. package/dist/temporal-supersession.d.ts +3 -2
  282. package/dist/temporal-timeline-recall.d.ts +1 -1
  283. package/dist/temporal-validity.d.ts +1 -1
  284. package/dist/threading.d.ts +1 -1
  285. package/dist/tier-migration.d.ts +3 -2
  286. package/dist/tier-routing.d.ts +1 -1
  287. package/dist/topics.d.ts +1 -1
  288. package/dist/transcript.d.ts +1 -1
  289. package/dist/transfer/types.d.ts +12 -12
  290. package/dist/trust-score-stage.d.ts +1 -1
  291. package/dist/trust-score.d.ts +1 -1
  292. package/dist/{types-Dg0w9ADr.d.ts → types-aPPzhnjT.d.ts} +1 -1
  293. package/dist/types.d.ts +1 -1
  294. package/dist/utility-runtime.d.ts +1 -1
  295. package/dist/utils/serialize-mutations.d.ts +11 -7
  296. package/dist/utils/serialize-mutations.js +1 -1
  297. package/dist/verified-recall.js +10 -9
  298. package/dist/write-envelope.d.ts +1 -1
  299. package/package.json +2 -2
  300. package/src/access-observe-write-surface.ts +1 -1
  301. package/src/access-service-coding-write.test.ts +40 -0
  302. package/src/explicit-capture.test.ts +1110 -1
  303. package/src/explicit-capture.ts +534 -135
  304. package/src/maintenance/purge.test.ts +157 -1
  305. package/src/maintenance/purge.ts +15 -9
  306. package/src/secure-store/secure-fs.ts +78 -1
  307. package/src/storage/content-hash-index.ts +43 -17
  308. package/src/storage/entity-canonical-id-migration.ts +151 -23
  309. package/src/storage/tombstone-blocked-capture-index.ts +562 -0
  310. package/src/storage/tombstone-blocked-capture-mutation.ts +284 -0
  311. package/src/storage/tombstone-blocked-capture-sync.ts +872 -0
  312. package/src/storage-fact-hash-index-defer.test.ts +2900 -57
  313. package/src/storage.ts +266 -265
  314. package/src/testing/subjects/tombstone-blocked-capture.test.ts +181 -0
  315. package/src/utils/serialize-mutations.test.ts +4 -1
  316. package/src/utils/serialize-mutations.ts +26 -27
  317. package/dist/chunk-55MDBZLC.js +0 -490
  318. package/dist/chunk-55MDBZLC.js.map +0 -1
  319. package/dist/chunk-AIK5W3IW.js.map +0 -1
  320. package/dist/chunk-FCDWWCLX.js.map +0 -1
  321. package/dist/chunk-WL5EBRDH.js.map +0 -1
  322. package/dist/purge-YSGX5BOG.js.map +0 -1
  323. /package/dist/{chunk-KUJQHXPH.js.map → chunk-2EUVEDF5.js.map} +0 -0
  324. /package/dist/{chunk-EVX44I7C.js.map → chunk-5W4ZLBEZ.js.map} +0 -0
  325. /package/dist/{chunk-P3MH72CI.js.map → chunk-62U4J2GN.js.map} +0 -0
  326. /package/dist/{chunk-YGHMSDLK.js.map → chunk-66772WBP.js.map} +0 -0
  327. /package/dist/{chunk-EP5BVCRI.js.map → chunk-6BNE62PM.js.map} +0 -0
  328. /package/dist/{chunk-AAP5T6QG.js.map → chunk-6DNMUYEE.js.map} +0 -0
  329. /package/dist/{chunk-SG265CVF.js.map → chunk-6FUPCJUL.js.map} +0 -0
  330. /package/dist/{chunk-WZ7UB7XQ.js.map → chunk-6U7F52DE.js.map} +0 -0
  331. /package/dist/{chunk-E4OCKU67.js.map → chunk-7XC2HX75.js.map} +0 -0
  332. /package/dist/{chunk-OVRQLAYR.js.map → chunk-AZ5BTEKX.js.map} +0 -0
  333. /package/dist/{chunk-2HNUMF5V.js.map → chunk-CZRYLSSW.js.map} +0 -0
  334. /package/dist/{chunk-WONS4RZ2.js.map → chunk-FDAMS4PK.js.map} +0 -0
  335. /package/dist/{chunk-Q6VFVAKZ.js.map → chunk-GIBMDSJ2.js.map} +0 -0
  336. /package/dist/{chunk-ZXAGJFHJ.js.map → chunk-H5CPS5JP.js.map} +0 -0
  337. /package/dist/{chunk-NBDCZWP4.js.map → chunk-I5NLEENJ.js.map} +0 -0
  338. /package/dist/{chunk-DRBXHRXE.js.map → chunk-IB26HVAJ.js.map} +0 -0
  339. /package/dist/{chunk-XEQ7OT7U.js.map → chunk-IC6CBHCA.js.map} +0 -0
  340. /package/dist/{chunk-CMRQ34J5.js.map → chunk-JCBWCYEJ.js.map} +0 -0
  341. /package/dist/{chunk-3PDOVUHC.js.map → chunk-KXB4VXHY.js.map} +0 -0
  342. /package/dist/{chunk-G6LBWZRF.js.map → chunk-LBOD4U5B.js.map} +0 -0
  343. /package/dist/{chunk-ZGOQTOYA.js.map → chunk-LGHKJABJ.js.map} +0 -0
  344. /package/dist/{chunk-T3GCXULH.js.map → chunk-M3C2V3PV.js.map} +0 -0
  345. /package/dist/{chunk-OFHFH655.js.map → chunk-MJCGLM25.js.map} +0 -0
  346. /package/dist/{chunk-JDZRYH2N.js.map → chunk-NHWB6HG2.js.map} +0 -0
  347. /package/dist/{chunk-TC3VNKGX.js.map → chunk-NM2WP3B7.js.map} +0 -0
  348. /package/dist/{chunk-IMA2EWLV.js.map → chunk-P5PXWTW7.js.map} +0 -0
  349. /package/dist/{chunk-2QMKMVHH.js.map → chunk-QNWXCJ76.js.map} +0 -0
  350. /package/dist/{chunk-CSMCNOPH.js.map → chunk-SPJXKAVF.js.map} +0 -0
  351. /package/dist/{chunk-4PBVXX7L.js.map → chunk-TH2LSRMG.js.map} +0 -0
  352. /package/dist/{chunk-ESBQWC3U.js.map → chunk-VI2JQPNQ.js.map} +0 -0
  353. /package/dist/{chunk-GGUBDXRR.js.map → chunk-W5EG6LE3.js.map} +0 -0
  354. /package/dist/{chunk-DEBHXHJR.js.map → chunk-WIPEXG6R.js.map} +0 -0
  355. /package/dist/{chunk-SH6YO3LT.js.map → chunk-WVO4G37W.js.map} +0 -0
  356. /package/dist/{chunk-VVIW3PTA.js.map → chunk-YTQNQ4KB.js.map} +0 -0
  357. /package/dist/{chunk-PKRIQL3V.js.map → chunk-YTSNAUXN.js.map} +0 -0
  358. /package/dist/{chunk-QAOGGNE3.js.map → chunk-ZPSVBSOF.js.map} +0 -0
  359. /package/dist/{forget-HRPLVB3W.js.map → forget-4UY2EOKH.js.map} +0 -0
@@ -1,5 +1,5 @@
1
1
  import assert from "node:assert/strict";
2
- import { access, mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
2
+ import { access, mkdir, mkdtemp, readFile, rm, unlink, writeFile } from "node:fs/promises";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
5
5
  import test from "node:test";
@@ -9,6 +9,7 @@ import { rebuildMemoryProjection } from "./rebuild-memory-projection.js";
9
9
  import { readProjectedMemoryBrowse } from "../memory-projection-store.js";
10
10
  import { StorageManager } from "../storage.js";
11
11
  import type { MemoryFile } from "../types.js";
12
+ import { buildExplicitCaptureDedupKey } from "../storage/tombstone-blocked-capture-index.js";
12
13
 
13
14
  test("purgeMemories records audit errors without blocking hard delete", async () => {
14
15
  const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-purge-"));
@@ -38,6 +39,10 @@ test("purgeMemories records audit errors without blocking hard delete", async ()
38
39
  readAllMemories: async () => [],
39
40
  readAllColdMemories: async () => [memory],
40
41
  readArchivedMemories: async () => [],
42
+ deleteMemoryForMaintenance: async (candidate: MemoryFile) => {
43
+ await unlink(candidate.path);
44
+ return candidate;
45
+ },
41
46
  };
42
47
 
43
48
  const result = await purgeMemories({
@@ -108,6 +113,10 @@ test("purgeMemories invalidates projection rows for already-absent files but not
108
113
  dir,
109
114
  readAllMemories: async () => [firstMemory, secondMemory],
110
115
  readAllColdMemories: async () => [],
116
+ deleteMemoryForMaintenance: async (candidate: MemoryFile) => {
117
+ await unlink(candidate.path);
118
+ return candidate;
119
+ },
111
120
  readArchivedMemories: async () => [],
112
121
  };
113
122
  const future = () => new Date(Date.now() + 86_400_000);
@@ -130,6 +139,153 @@ test("purgeMemories invalidates projection rows for already-absent files but not
130
139
  }
131
140
  });
132
141
 
142
+ test("cleanExpiredCommitments coordinates blocked capture deletion", async () => {
143
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-commitment-delete-lock-"));
144
+ try {
145
+ const storage = new StorageManager(dir);
146
+ await storage.ensureDirectories();
147
+ storage.setTombstonesConfig({
148
+ enabled: true,
149
+ semanticMatch: false,
150
+ semanticThreshold: 0.9,
151
+ namespace: "default",
152
+ });
153
+ const content = "A blocked commitment must not disappear under a concurrent capture.";
154
+ const tombstoneId = await storage.appendTombstone({
155
+ reason: "correction",
156
+ createdBy: "user_correction",
157
+ sourceMemoryId: "commitment-delete-lock",
158
+ rawContent: content,
159
+ });
160
+ assert.ok(tombstoneId);
161
+ const result = await storage.writeMemory("fact", content, {
162
+ source: "test",
163
+ sourceConnector: "provider-a",
164
+ });
165
+ assert.equal(result.tombstoneBlocked, true);
166
+ const blocked = await storage.getMemoryById(result.id);
167
+ assert.ok(blocked);
168
+ assert.equal(
169
+ await storage.writeMemoryFrontmatter(blocked, {
170
+ category: "commitment",
171
+ tags: ["fulfilled"],
172
+ }),
173
+ true,
174
+ );
175
+ const identity = buildExplicitCaptureDedupKey(content, "commitment", "provider-a");
176
+ const release = Promise.withResolvers<void>();
177
+ const entered = Promise.withResolvers<void>();
178
+ const held = storage.withTombstoneBlockedCaptureWriteLock(async () => {
179
+ entered.resolve();
180
+ await release.promise;
181
+ }, identity);
182
+ await entered.promise;
183
+
184
+ let completed = false;
185
+ const pending = storage.cleanExpiredCommitments(-1).then((deleted) => {
186
+ completed = true;
187
+ return deleted;
188
+ });
189
+ await new Promise((resolve) => setTimeout(resolve, 50));
190
+ assert.equal(completed, false, "commitment cleanup must wait for the blocked capture identity lock");
191
+ release.resolve();
192
+ await held;
193
+ const deleted = await pending;
194
+ assert.equal(deleted.length, 1);
195
+ assert.equal(deleted[0]?.frontmatter.id, result.id);
196
+ } finally {
197
+ await rm(dir, { recursive: true, force: true });
198
+ }
199
+ });
200
+
201
+ test("purgeMemories coordinates blocked capture deletion", async () => {
202
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-purge-delete-lock-"));
203
+ try {
204
+ const storage = new StorageManager(dir);
205
+ await storage.ensureDirectories();
206
+ storage.setTombstonesConfig({
207
+ enabled: true,
208
+ semanticMatch: false,
209
+ semanticThreshold: 0.9,
210
+ namespace: "default",
211
+ });
212
+ const content = "A blocked memory must not disappear under a concurrent capture.";
213
+ const tombstoneId = await storage.appendTombstone({
214
+ reason: "correction",
215
+ createdBy: "user_correction",
216
+ sourceMemoryId: "purge-delete-lock",
217
+ rawContent: content,
218
+ });
219
+ assert.ok(tombstoneId);
220
+ const result = await storage.writeMemory("fact", content, {
221
+ source: "test",
222
+ sourceConnector: "provider-a",
223
+ });
224
+ assert.equal(result.tombstoneBlocked, true);
225
+ const blocked = await storage.getMemoryById(result.id);
226
+ assert.ok(blocked);
227
+ const identity = buildExplicitCaptureDedupKey(content, "fact", "provider-a");
228
+ const release = Promise.withResolvers<void>();
229
+ const entered = Promise.withResolvers<void>();
230
+ const held = storage.withTombstoneBlockedCaptureWriteLock(async () => {
231
+ entered.resolve();
232
+ await release.promise;
233
+ }, identity);
234
+ await entered.promise;
235
+
236
+ let completed = false;
237
+ const pending = purgeMemories({
238
+ storage,
239
+ olderThanMs: 1,
240
+ tier: "all",
241
+ dryRun: false,
242
+ now: () => new Date(Date.now() + 86_400_000),
243
+ }).then((purged) => {
244
+ completed = true;
245
+ return purged;
246
+ });
247
+ await new Promise((resolve) => setTimeout(resolve, 50));
248
+ assert.equal(completed, false, "purge must wait for the blocked capture identity lock");
249
+ release.resolve();
250
+ await held;
251
+ const purged = await pending;
252
+ assert.equal(purged.purgedCount, 1);
253
+ assert.equal(await fileExists(blocked.path), false);
254
+ } finally {
255
+ await rm(dir, { recursive: true, force: true });
256
+ }
257
+ });
258
+
259
+ test("maintenance deletion prefers the candidate path when IDs overlap across tiers", async () => {
260
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-delete-tier-path-"));
261
+ try {
262
+ StorageManager.clearAllStaticCaches();
263
+ const storage = new StorageManager(dir);
264
+ await storage.ensureDirectories();
265
+ const content = "The cold candidate path must win when a hot copy shares its ID.";
266
+ const result = await storage.writeMemory("fact", content, {
267
+ source: "test",
268
+ sourceConnector: "provider-a",
269
+ });
270
+ const hot = await storage.getMemoryById(result.id);
271
+ assert.ok(hot);
272
+ const coldPath = storage.buildTierMemoryPath(hot, "cold");
273
+ await mkdir(path.dirname(coldPath), { recursive: true });
274
+ await writeFile(coldPath, await readFile(hot.path));
275
+ StorageManager.clearAllStaticCaches();
276
+
277
+ const cold = (await storage.readAllColdMemories()).find((memory) => memory.frontmatter.id === result.id);
278
+ assert.ok(cold);
279
+ const removed = await storage.deleteMemoryForMaintenance(cold);
280
+ assert.equal(removed?.path, coldPath);
281
+ assert.equal(await fileExists(coldPath), false);
282
+ assert.equal(await fileExists(hot.path), true);
283
+ } finally {
284
+ StorageManager.clearAllStaticCaches();
285
+ await rm(dir, { recursive: true, force: true });
286
+ }
287
+ });
288
+
133
289
  async function fileExists(filePath: string): Promise<boolean> {
134
290
  try {
135
291
  await access(filePath);
@@ -20,7 +20,7 @@
20
20
  */
21
21
 
22
22
  import path from "node:path";
23
- import { appendFile, mkdir, unlink } from "node:fs/promises";
23
+ import { appendFile, mkdir } from "node:fs/promises";
24
24
  import type { StorageManager } from "../storage.js";
25
25
  import type { MemoryFile } from "../types.js";
26
26
  import { markProjectedMemoryPathInvalid } from "../memory-projection-store.js";
@@ -168,7 +168,7 @@ export async function purgeMemories(
168
168
 
169
169
  // Build candidate list
170
170
  const candidates: PurgeCandidate[] = [];
171
- const candidateMemoriesById = new Map<string, MemoryFile>();
171
+ const candidateMemoriesByPath = new Map<string, MemoryFile>();
172
172
  for (const { memory, resolvedTier } of poolEntries) {
173
173
  const ts = resolveTimestamp(memory);
174
174
  if (ts.length === 0) continue;
@@ -193,7 +193,7 @@ export async function purgeMemories(
193
193
  updatedOrCreated: ts,
194
194
  ageMs,
195
195
  });
196
- candidateMemoriesById.set(memory.frontmatter.id, memory);
196
+ candidateMemoriesByPath.set(memory.path, memory);
197
197
  }
198
198
 
199
199
  if (dryRun) {
@@ -234,13 +234,19 @@ export async function purgeMemories(
234
234
 
235
235
  for (const candidate of candidates) {
236
236
  try {
237
- await unlink(candidate.path);
238
- actuallyPurged.push(candidate);
239
- addCollectionForCandidate(candidate);
240
- markProjectedMemoryPathInvalid(storage.dir, candidate.id);
237
+ const memory = candidateMemoriesByPath.get(candidate.path);
238
+ if (!memory) throw new Error(`purge candidate memory missing: ${candidate.id}`);
239
+ const removed = await storage.deleteMemoryForMaintenance(memory);
240
+ if (removed) {
241
+ actuallyPurged.push(candidate);
242
+ addCollectionForCandidate(candidate);
243
+ } else {
244
+ alreadyAbsent.push(candidate);
245
+ addCollectionForCandidate(candidate);
246
+ markProjectedMemoryPathInvalid(storage.dir, candidate.id);
247
+ }
241
248
  } catch (err) {
242
249
  const message = err instanceof Error ? err.message : String(err);
243
- // ENOENT is fine — already gone
244
250
  if (hasErrorCode(err, "ENOENT")) {
245
251
  alreadyAbsent.push(candidate);
246
252
  addCollectionForCandidate(candidate);
@@ -302,7 +308,7 @@ export async function purgeMemories(
302
308
  }
303
309
 
304
310
  const purgedFactMemories = resolvedPurges
305
- .map((candidate) => candidateMemoriesById.get(candidate.id))
311
+ .map((candidate) => candidateMemoriesByPath.get(candidate.path))
306
312
  .filter((memory): memory is MemoryFile => memory?.frontmatter.category === "fact");
307
313
  if (purgedFactMemories.length > 0) {
308
314
  const removeFactHashes = (
@@ -43,7 +43,7 @@
43
43
  * Naming: `secure-fs.ts` (not `vault-fs.ts`) — see `kdf.ts` naming note.
44
44
  */
45
45
 
46
- import { createCipheriv, randomBytes, randomUUID } from "node:crypto";
46
+ import { createCipheriv, createDecipheriv, randomBytes, randomUUID } from "node:crypto";
47
47
  import { lstat, mkdir, open as openFile, readFile, readdir, rename, unlink, writeFile } from "node:fs/promises";
48
48
  import path from "node:path";
49
49
 
@@ -416,6 +416,83 @@ export async function writeMaybeEncryptedFileFromChunks(
416
416
  }
417
417
  }
418
418
 
419
+ /**
420
+ * Stream a file through the secure-store reader without buffering the whole
421
+ * payload. Plaintext files are passed through unchanged; encrypted files are
422
+ * authenticated and decrypted incrementally.
423
+ */
424
+ export async function* readMaybeEncryptedFileFromChunks(
425
+ filePath: string,
426
+ key: Buffer | null,
427
+ memoryDir?: string,
428
+ chunkSize = 64 * 1024
429
+ ): AsyncIterable<Buffer> {
430
+ const handle = await openFile(filePath, "r");
431
+ const headerSize = MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE;
432
+ try {
433
+ const prefix = Buffer.alloc(headerSize);
434
+ const { bytesRead: prefixBytes } = await handle.read(prefix, 0, prefix.length, 0);
435
+ const prefixView = prefix.subarray(0, prefixBytes);
436
+ if (!isEncryptedFile(prefixView)) {
437
+ if (prefixBytes > 0) yield Buffer.from(prefixView);
438
+ let position = prefixBytes;
439
+ const buffer = Buffer.alloc(chunkSize);
440
+ for (;;) {
441
+ const { bytesRead } = await handle.read(buffer, 0, buffer.length, position);
442
+ if (bytesRead === 0) break;
443
+ position += bytesRead;
444
+ yield Buffer.from(buffer.subarray(0, bytesRead));
445
+ }
446
+ return;
447
+ }
448
+ if (prefixBytes < headerSize) {
449
+ throw new Error(`encrypted file header is truncated: ${filePath}`);
450
+ }
451
+ if (key === null) {
452
+ throw new SecureStoreLockedError(
453
+ `secure-store is locked — cannot read encrypted file at ${filePath}. ` +
454
+ "Run `remnic secure-store unlock` to decrypt."
455
+ );
456
+ }
457
+ const envelope = prefix.subarray(MAGIC_HEADER_SIZE);
458
+ const version = envelope.readUInt8(ENVELOPE_LAYOUT.version);
459
+ if (version !== ENVELOPE_VERSION) {
460
+ throw new Error(`secure-store: unsupported envelope version ${version}`);
461
+ }
462
+ const salt = envelope.subarray(
463
+ ENVELOPE_LAYOUT.salt,
464
+ ENVELOPE_LAYOUT.salt + ENVELOPE_SALT_LENGTH
465
+ );
466
+ const iv = envelope.subarray(ENVELOPE_LAYOUT.iv, ENVELOPE_LAYOUT.iv + IV_LENGTH);
467
+ const authTag = envelope.subarray(
468
+ ENVELOPE_LAYOUT.authTag,
469
+ ENVELOPE_LAYOUT.authTag + AUTH_TAG_LENGTH
470
+ );
471
+ const decipher = createDecipheriv("aes-256-gcm", key, iv, { authTagLength: AUTH_TAG_LENGTH });
472
+ decipher.setAAD(Buffer.concat([buildHeaderAad(salt), filePathAad(filePath, memoryDir)]));
473
+ decipher.setAuthTag(authTag);
474
+ let position = headerSize;
475
+ const buffer = Buffer.alloc(chunkSize);
476
+ try {
477
+ for (;;) {
478
+ const { bytesRead } = await handle.read(buffer, 0, buffer.length, position);
479
+ if (bytesRead === 0) break;
480
+ position += bytesRead;
481
+ const plain = decipher.update(buffer.subarray(0, bytesRead));
482
+ if (plain.length > 0) yield plain;
483
+ }
484
+ const final = decipher.final();
485
+ if (final.length > 0) yield final;
486
+ } catch (err) {
487
+ if (err instanceof SecureStoreDecryptError) throw err;
488
+ const message = err instanceof Error ? err.message : String(err);
489
+ throw new SecureStoreDecryptError(`secure-store decryption failed: ${message}`);
490
+ }
491
+ } finally {
492
+ await handle.close();
493
+ }
494
+ }
495
+
419
496
  // ---------------------------------------------------------------------------
420
497
  // Migration
421
498
  // ---------------------------------------------------------------------------
@@ -76,6 +76,14 @@ export class FactHashIndexNotAuthoritativeError extends Error {
76
76
  }
77
77
  }
78
78
 
79
+ type DiskFingerprint = {
80
+ mtimeMs: number;
81
+ size: number;
82
+ dev: number;
83
+ ino: number;
84
+ ctimeMs: number;
85
+ birthtimeMs: number;
86
+ };
79
87
  /**
80
88
  * Content-hash dedup index for facts.
81
89
  * Normalizes content (lowercase, strip punctuation, collapse whitespace),
@@ -120,15 +128,13 @@ export class ContentHashIndex {
120
128
  private reconcileRetryBarrier: Promise<void> | null = null;
121
129
  private reconcileRetryResolve: (() => void) | null = null;
122
130
  /**
123
- * On-disk fingerprint (mtime + byte size) of `fact-hashes.txt` captured at the
124
- * last point THIS instance's in-memory set matched disk — after `load()`,
125
- * `save()`, or a reconcile publish (PR #2016 review). A peer process that
126
- * advances the durable index changes this fingerprint;
127
- * {@link isDiskFingerprintCurrent} compares a single cheap `stat` against it so
128
- * a stale-but-"authoritative" snapshot is detected without an O(file-size)
129
- * re-read on the hot path.
131
+ * On-disk fingerprint captured at the last point THIS instance's in-memory
132
+ * set matched disk — after `load()`, `save()`, or a reconcile publish. A peer
133
+ * process that advances the durable index changes its file generation even
134
+ * when byte size and mtime collide, so the freshness check remains safe
135
+ * without an O(file-size) read on the hot path.
130
136
  */
131
- private lastSyncedFingerprint: { mtimeMs: number; size: number } | null = null;
137
+ private lastSyncedFingerprint: DiskFingerprint | null = null;
132
138
 
133
139
  constructor(
134
140
  stateDir: string,
@@ -166,10 +172,17 @@ export class ContentHashIndex {
166
172
  }
167
173
 
168
174
  /** Cheap `stat` of the durable index file; null when it does not exist yet. */
169
- private async statIndexFile(): Promise<{ mtimeMs: number; size: number } | null> {
175
+ private async statIndexFile(): Promise<DiskFingerprint | null> {
170
176
  try {
171
177
  const s = await stat(this.filePath);
172
- return { mtimeMs: s.mtimeMs, size: s.size };
178
+ return {
179
+ mtimeMs: s.mtimeMs,
180
+ size: s.size,
181
+ dev: s.dev,
182
+ ino: s.ino,
183
+ ctimeMs: s.ctimeMs,
184
+ birthtimeMs: s.birthtimeMs,
185
+ };
173
186
  } catch (err) {
174
187
  if (isErrnoCode(err, "ENOENT")) return null;
175
188
  throw err;
@@ -190,14 +203,15 @@ export class ContentHashIndex {
190
203
 
191
204
  /**
192
205
  * True when the durable index file is unchanged since this instance last
193
- * synced it (load / save / reconcile). False when a peer advanced it, when the
194
- * file appeared or vanished, or when freshness cannot be established (stat
195
- * error) — the caller then treats the in-memory snapshot as non-authoritative
196
- * and confirms a dedup miss against the durable corpus (PR #2016 review). One
197
- * `stat`, never an O(file-size) read, so the hot path stays cheap.
206
+ * synced it (load / save / reconcile). False when a peer advanced it, when
207
+ * the file appeared or vanished, or when freshness cannot be established
208
+ * (stat error) — the caller then treats the in-memory snapshot as
209
+ * non-authoritative and confirms a dedup miss against the durable corpus.
210
+ * The stat includes file identity and generation metadata so same-size,
211
+ * same-mtime atomic replacements are detected without reading the file body.
198
212
  */
199
213
  async isDiskFingerprintCurrent(): Promise<boolean> {
200
- let current: { mtimeMs: number; size: number } | null;
214
+ let current: DiskFingerprint | null;
201
215
  try {
202
216
  current = await this.statIndexFile();
203
217
  } catch {
@@ -207,7 +221,14 @@ export class ContentHashIndex {
207
221
  if (last === null || current === null) {
208
222
  return last === null && current === null;
209
223
  }
210
- return current.mtimeMs === last.mtimeMs && current.size === last.size;
224
+ return (
225
+ current.mtimeMs === last.mtimeMs &&
226
+ current.size === last.size &&
227
+ current.dev === last.dev &&
228
+ current.ino === last.ino &&
229
+ current.ctimeMs === last.ctimeMs &&
230
+ current.birthtimeMs === last.birthtimeMs
231
+ );
211
232
  }
212
233
 
213
234
  /** Check if content already exists in the index. */
@@ -475,6 +496,11 @@ export class ContentHashIndex {
475
496
  return this.reconcileRetryTimer !== null;
476
497
  }
477
498
 
499
+ /** True while this index has in-memory changes not yet published to disk. */
500
+ get hasPendingChanges(): boolean {
501
+ return this.dirty;
502
+ }
503
+
478
504
  /**
479
505
  * Resolve once any armed background reconcile-save retry chain has settled —
480
506
  * either it published the deferred additions, or it exhausted its bounded