@remnic/core 9.29.1 → 9.30.1

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 (358) 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.js +3 -3
  36. package/dist/{access-service-DvPW_M5j.d.ts → access-service-B5RwVsTV.d.ts} +7 -7
  37. package/dist/access-service.d.ts +11 -11
  38. package/dist/access-service.js +19 -18
  39. package/dist/access-surface-catalog.d.ts +11 -11
  40. package/dist/access-wearables-meetings-surface.d.ts +4 -3
  41. package/dist/action-confidence.d.ts +1 -1
  42. package/dist/active-memory-bridge.d.ts +1 -1
  43. package/dist/active-recall.d.ts +1 -1
  44. package/dist/active-recall.js +3 -3
  45. package/dist/behavior-learner.d.ts +1 -1
  46. package/dist/behavior-signals.d.ts +1 -1
  47. package/dist/bootstrap.d.ts +8 -8
  48. package/dist/briefing.d.ts +3 -2
  49. package/dist/briefing.js +10 -9
  50. package/dist/buffer-surprise-report.d.ts +1 -1
  51. package/dist/buffer.d.ts +3 -2
  52. package/dist/bulk-import/index.d.ts +3 -3
  53. package/dist/calibration.d.ts +1 -1
  54. package/dist/capabilities.d.ts +1 -1
  55. package/dist/{catalog-BIVgftWu.d.ts → catalog-V7inUQdp.d.ts} +1 -1
  56. package/dist/causal-behavior.d.ts +1 -1
  57. package/dist/causal-consolidation.d.ts +1 -1
  58. package/dist/causal-consolidation.js +11 -10
  59. package/dist/causal-consolidation.js.map +1 -1
  60. package/dist/causal-trajectory-graph.d.ts +1 -1
  61. package/dist/{chunk-FZRQZW4H.js → chunk-2EUVEDF5.js} +2 -2
  62. package/dist/{chunk-PBUZNGMX.js → chunk-4WKA6I65.js} +20 -20
  63. package/dist/{chunk-PBUZNGMX.js.map → chunk-4WKA6I65.js.map} +1 -1
  64. package/dist/{chunk-AIK5W3IW.js → chunk-5TFP4CUL.js} +68 -2
  65. package/dist/chunk-5TFP4CUL.js.map +1 -0
  66. package/dist/{chunk-3JNDOAQ2.js → chunk-5W4ZLBEZ.js} +9 -9
  67. package/dist/{chunk-5ZCUDWD4.js → chunk-62U4J2GN.js} +2 -2
  68. package/dist/{chunk-IGPEJVBY.js → chunk-66772WBP.js} +2 -2
  69. package/dist/{chunk-EP5BVCRI.js → chunk-6BNE62PM.js} +2 -2
  70. package/dist/{chunk-AAP5T6QG.js → chunk-6DNMUYEE.js} +2 -2
  71. package/dist/{chunk-35DL7IOI.js → chunk-6FUPCJUL.js} +7 -7
  72. package/dist/{chunk-JP3YPDAW.js → chunk-6U7F52DE.js} +19 -19
  73. package/dist/{chunk-E4OCKU67.js → chunk-7XC2HX75.js} +2 -2
  74. package/dist/{chunk-OVRQLAYR.js → chunk-AZ5BTEKX.js} +2 -2
  75. package/dist/{chunk-2AXMQWCN.js → chunk-CZRYLSSW.js} +3 -3
  76. package/dist/chunk-FBUE6PD3.js +1769 -0
  77. package/dist/chunk-FBUE6PD3.js.map +1 -0
  78. package/dist/{chunk-PTSNLEXK.js → chunk-FDAMS4PK.js} +2 -2
  79. package/dist/{chunk-WL5EBRDH.js → chunk-FFAZ2XFU.js} +9 -8
  80. package/dist/chunk-FFAZ2XFU.js.map +1 -0
  81. package/dist/{chunk-2GXM5N5A.js → chunk-GIBMDSJ2.js} +2 -2
  82. package/dist/{chunk-E5OBR6CJ.js → chunk-H5CPS5JP.js} +3 -3
  83. package/dist/{chunk-2D7FEUCK.js → chunk-I5NLEENJ.js} +2 -2
  84. package/dist/{chunk-DRBXHRXE.js → chunk-IB26HVAJ.js} +2 -2
  85. package/dist/{chunk-QDKK63Y7.js → chunk-IC6CBHCA.js} +3 -3
  86. package/dist/{chunk-IAEAFLF2.js → chunk-JCBWCYEJ.js} +2 -2
  87. package/dist/{chunk-3PDOVUHC.js → chunk-KXB4VXHY.js} +2 -2
  88. package/dist/{chunk-WU7TTVOD.js → chunk-LBOD4U5B.js} +7 -7
  89. package/dist/{chunk-UBKEQOTD.js → chunk-LGHKJABJ.js} +3 -3
  90. package/dist/{chunk-VSURVXKY.js → chunk-M3C2V3PV.js} +10 -10
  91. package/dist/{chunk-OFHFH655.js → chunk-MJCGLM25.js} +8 -8
  92. package/dist/{chunk-OYJKSZIQ.js → chunk-NHWB6HG2.js} +2 -2
  93. package/dist/{chunk-TC3VNKGX.js → chunk-NM2WP3B7.js} +4 -4
  94. package/dist/{chunk-GAWOEQEQ.js → chunk-P5PXWTW7.js} +2 -2
  95. package/dist/chunk-PH3ZWL3W.js +786 -0
  96. package/dist/chunk-PH3ZWL3W.js.map +1 -0
  97. package/dist/{chunk-2QMKMVHH.js → chunk-QNWXCJ76.js} +2 -2
  98. package/dist/{chunk-JMQUBRV6.js → chunk-RGIWINDN.js} +340 -771
  99. package/dist/chunk-RGIWINDN.js.map +1 -0
  100. package/dist/{chunk-WRFBW2TT.js → chunk-SPJXKAVF.js} +3 -3
  101. package/dist/{chunk-HKJCMOT6.js → chunk-TH2LSRMG.js} +2 -2
  102. package/dist/{chunk-CW4AGY3G.js → chunk-VI2JQPNQ.js} +2 -2
  103. package/dist/{chunk-OP6F6L3S.js → chunk-W5EG6LE3.js} +2 -2
  104. package/dist/{chunk-DEBHXHJR.js → chunk-WIPEXG6R.js} +2 -2
  105. package/dist/{chunk-SH6YO3LT.js → chunk-WVO4G37W.js} +2 -2
  106. package/dist/{chunk-FUYEVEX7.js → chunk-YNQBRLC5.js} +24 -22
  107. package/dist/chunk-YNQBRLC5.js.map +1 -0
  108. package/dist/{chunk-7L45JFPW.js → chunk-YTQNQ4KB.js} +14 -14
  109. package/dist/{chunk-PKRIQL3V.js → chunk-YTSNAUXN.js} +2 -2
  110. package/dist/{chunk-5QDRGWT2.js → chunk-ZPSVBSOF.js} +4 -4
  111. package/dist/{cli-CxoSOiG0.d.ts → cli-C4GbETPC.d.ts} +5 -5
  112. package/dist/cli.d.ts +13 -13
  113. package/dist/cli.js +36 -35
  114. package/dist/compounding/engine.d.ts +3 -2
  115. package/dist/compounding/engine.js +10 -9
  116. package/dist/compounding/preference-consolidator.d.ts +1 -1
  117. package/dist/compression-optimizer.d.ts +1 -1
  118. package/dist/config.d.ts +1 -1
  119. package/dist/config.js +3 -3
  120. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  121. package/dist/connectors/codex-materialize-runner.js +10 -9
  122. package/dist/connectors/codex-materialize.d.ts +1 -1
  123. package/dist/connectors/index.d.ts +1 -1
  124. package/dist/connectors/index.js +10 -9
  125. package/dist/consolidation-provenance-check.d.ts +3 -2
  126. package/dist/consolidation-undo.d.ts +3 -2
  127. package/dist/contradiction/index.d.ts +3 -2
  128. package/dist/conversation-index/backend.d.ts +1 -1
  129. package/dist/conversation-index/chunker.d.ts +1 -1
  130. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  131. package/dist/conversation-index/indexer.d.ts +1 -1
  132. package/dist/conversation-index/search.d.ts +1 -1
  133. package/dist/corpus-watermark.d.ts +1 -1
  134. package/dist/corpus-watermark.js +12 -11
  135. package/dist/day-summary.d.ts +1 -1
  136. package/dist/delinearize.d.ts +1 -1
  137. package/dist/direct-answer-wiring.d.ts +1 -1
  138. package/dist/direct-answer.d.ts +1 -1
  139. package/dist/embedding-fallback.d.ts +1 -1
  140. package/dist/enrichment/index.d.ts +1 -1
  141. package/dist/entity-retrieval.d.ts +3 -2
  142. package/dist/entity-retrieval.js +10 -9
  143. package/dist/entity-schema.d.ts +1 -1
  144. package/dist/explicit-capture.d.ts +52 -10
  145. package/dist/explicit-capture.js +13 -1
  146. package/dist/extraction-error-classification.d.ts +1 -1
  147. package/dist/extraction-faithfulness.d.ts +1 -1
  148. package/dist/extraction-judge-telemetry.d.ts +1 -1
  149. package/dist/extraction-judge-training.d.ts +1 -1
  150. package/dist/extraction-judge.d.ts +1 -1
  151. package/dist/extraction-liveness.d.ts +1 -1
  152. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  153. package/dist/extraction-source-grounding.d.ts +1 -1
  154. package/dist/extraction.d.ts +1 -1
  155. package/dist/fallback-llm.d.ts +1 -1
  156. package/dist/{forget-HRPLVB3W.js → forget-4UY2EOKH.js} +3 -3
  157. package/dist/graph-dashboard-diff.d.ts +1 -1
  158. package/dist/graph-dashboard-key.d.ts +1 -1
  159. package/dist/graph-dashboard-parser.d.ts +1 -1
  160. package/dist/graph-edge-reinforcement.d.ts +1 -1
  161. package/dist/graph-snapshot.d.ts +1 -1
  162. package/dist/graph.d.ts +1 -1
  163. package/dist/importance.d.ts +1 -1
  164. package/dist/importers/index.d.ts +1 -1
  165. package/dist/in-flight-reads.d.ts +1 -1
  166. package/dist/index.d.ts +19 -19
  167. package/dist/index.js +47 -45
  168. package/dist/intent.d.ts +1 -1
  169. package/dist/lcm/engine.d.ts +1 -1
  170. package/dist/lcm/index.d.ts +1 -1
  171. package/dist/lcm/tools.d.ts +1 -1
  172. package/dist/lifecycle.d.ts +1 -1
  173. package/dist/live-connectors-runner.d.ts +1 -1
  174. package/dist/local-llm.d.ts +1 -1
  175. package/dist/local-model-endpoint.d.ts +1 -1
  176. package/dist/maintenance/memory-governance.d.ts +1 -1
  177. package/dist/maintenance/memory-governance.js +10 -9
  178. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  179. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +10 -9
  180. package/dist/maintenance/rebuild-memory-projection.d.ts +3 -2
  181. package/dist/maintenance/rebuild-memory-projection.js +11 -10
  182. package/dist/{maintenance-Cb-PjxQd.d.ts → maintenance-CL30NWtc.d.ts} +3 -3
  183. package/dist/mcp-memory-inspector-app.d.ts +11 -11
  184. package/dist/memory-action-policy.d.ts +1 -1
  185. package/dist/memory-cache.d.ts +1 -1
  186. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  187. package/dist/memory-projection-store.d.ts +1 -1
  188. package/dist/memory-provenance.d.ts +1 -1
  189. package/dist/memory-worth-outcomes.d.ts +3 -2
  190. package/dist/models-json.d.ts +1 -1
  191. package/dist/namespaces/migrate.d.ts +4 -3
  192. package/dist/namespaces/migrate.js +11 -10
  193. package/dist/namespaces/principal.d.ts +1 -1
  194. package/dist/namespaces/search.d.ts +1 -1
  195. package/dist/namespaces/storage.d.ts +4 -3
  196. package/dist/namespaces/storage.js +10 -9
  197. package/dist/native-knowledge.d.ts +1 -1
  198. package/dist/offline-sync-impression-drain.d.ts +1 -1
  199. package/dist/offline-sync-impression-drain.js +5 -5
  200. package/dist/offline-sync.js +2 -2
  201. package/dist/operator-doctor-corpus.d.ts +1 -1
  202. package/dist/operator-doctor-corpus.js +13 -12
  203. package/dist/operator-doctor-replica.d.ts +1 -1
  204. package/dist/operator-toolkit.d.ts +4 -3
  205. package/dist/operator-toolkit.js +18 -17
  206. package/dist/orchestration/compression-guideline-coordinator.d.ts +3 -2
  207. package/dist/orchestration/maintenance.d.ts +5 -4
  208. package/dist/orchestration/maintenance.js +15 -14
  209. package/dist/{orchestrator-5GKqb_HL.d.ts → orchestrator-CKTCRwWV.d.ts} +7 -7
  210. package/dist/orchestrator.d.ts +8 -8
  211. package/dist/orchestrator.js +45 -44
  212. package/dist/patterns-cli.d.ts +1 -1
  213. package/dist/{pipeline-3Qi1TpRo.d.ts → pipeline-B7wj4rRZ.d.ts} +1 -1
  214. package/dist/policy-runtime.d.ts +1 -1
  215. package/dist/proactive-contention.d.ts +1 -1
  216. package/dist/provenance.d.ts +1 -1
  217. package/dist/{purge-YSGX5BOG.js → purge-533FZLS4.js} +16 -9
  218. package/dist/purge-533FZLS4.js.map +1 -0
  219. package/dist/qmd-preflight.d.ts +2 -2
  220. package/dist/{qmd-D9JqzzRX.d.ts → qmd-q9tg4dHp.d.ts} +1 -1
  221. package/dist/qmd-recall-cache.d.ts +1 -1
  222. package/dist/qmd.d.ts +2 -2
  223. package/dist/recall-concurrency-config.d.ts +1 -1
  224. package/dist/recall-disclosure-escalation.d.ts +1 -1
  225. package/dist/recall-explain-renderer.d.ts +1 -1
  226. package/dist/recall-memory-map.d.ts +1 -1
  227. package/dist/recall-planner-llm.d.ts +1 -1
  228. package/dist/recall-state.d.ts +1 -1
  229. package/dist/recall-state.js +2 -2
  230. package/dist/recall-tag-filter.d.ts +1 -1
  231. package/dist/recall-timings.d.ts +1 -1
  232. package/dist/recall-xray-cli.d.ts +1 -1
  233. package/dist/recall-xray-renderer.d.ts +1 -1
  234. package/dist/recall-xray.d.ts +1 -1
  235. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  236. package/dist/replay/normalizers/claude.d.ts +1 -1
  237. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  238. package/dist/replay/normalizers/shared.d.ts +1 -1
  239. package/dist/replay/runner.d.ts +1 -1
  240. package/dist/replay/types.d.ts +1 -1
  241. package/dist/replica-divergence.d.ts +1 -1
  242. package/dist/replica-peers-config.d.ts +1 -1
  243. package/dist/resolve-auth-token.d.ts +1 -1
  244. package/dist/resume-bundles.js +4 -4
  245. package/dist/retrieval-agents.d.ts +2 -2
  246. package/dist/retrieval-tiers.d.ts +1 -1
  247. package/dist/routing/engine.d.ts +1 -1
  248. package/dist/routing/store.d.ts +1 -1
  249. package/dist/salvage-envelope.d.ts +1 -1
  250. package/dist/{scope-profiles-C4g6_UdP.d.ts → scope-profiles-CWDyglPM.d.ts} +1 -1
  251. package/dist/search/embed-helper.d.ts +1 -1
  252. package/dist/search/factory.d.ts +1 -1
  253. package/dist/search/index.d.ts +1 -1
  254. package/dist/search/lancedb-backend.d.ts +1 -1
  255. package/dist/search/meilisearch-backend.d.ts +1 -1
  256. package/dist/search/noop-backend.d.ts +1 -1
  257. package/dist/search/orama-backend.d.ts +1 -1
  258. package/dist/search/port.d.ts +1 -1
  259. package/dist/search/remote-backend.d.ts +1 -1
  260. package/dist/secure-store/index.js +2 -2
  261. package/dist/{semantic-consolidation-BrxqnzTW.d.ts → semantic-consolidation-BUE3deLn.d.ts} +1 -1
  262. package/dist/semantic-consolidation.d.ts +2 -2
  263. package/dist/semantic-consolidation.js +11 -10
  264. package/dist/semantic-rule-promotion.js +10 -9
  265. package/dist/semantic-rule-verifier.d.ts +1 -1
  266. package/dist/semantic-rule-verifier.js +10 -9
  267. package/dist/{service-Bi1JgxdP.d.ts → service-CXgM0bQG.d.ts} +2 -2
  268. package/dist/session-observer-bands.d.ts +1 -1
  269. package/dist/session-observer-state.d.ts +1 -1
  270. package/dist/shared-context/manager.d.ts +1 -1
  271. package/dist/signal.d.ts +1 -1
  272. package/dist/{storage-CcH6yPk2.d.ts → storage-DysJq-XH.d.ts} +163 -27
  273. package/dist/storage.d.ts +3 -2
  274. package/dist/storage.js +12 -10
  275. package/dist/summarizer.d.ts +1 -1
  276. package/dist/summarizer.js +3 -3
  277. package/dist/summary-snapshot.d.ts +1 -1
  278. package/dist/summary-snapshot.js +2 -2
  279. package/dist/temporal-supersession.d.ts +3 -2
  280. package/dist/temporal-timeline-recall.d.ts +1 -1
  281. package/dist/temporal-validity.d.ts +1 -1
  282. package/dist/threading.d.ts +1 -1
  283. package/dist/tier-migration.d.ts +3 -2
  284. package/dist/tier-routing.d.ts +1 -1
  285. package/dist/topics.d.ts +1 -1
  286. package/dist/transcript.d.ts +1 -1
  287. package/dist/trust-score-stage.d.ts +1 -1
  288. package/dist/trust-score.d.ts +1 -1
  289. package/dist/{types-Dg0w9ADr.d.ts → types-aPPzhnjT.d.ts} +1 -1
  290. package/dist/types.d.ts +1 -1
  291. package/dist/utility-runtime.d.ts +1 -1
  292. package/dist/utils/serialize-mutations.d.ts +11 -7
  293. package/dist/utils/serialize-mutations.js +1 -1
  294. package/dist/verified-recall.js +10 -9
  295. package/dist/write-envelope.d.ts +1 -1
  296. package/package.json +2 -2
  297. package/src/access-observe-write-surface.ts +1 -1
  298. package/src/access-service-coding-write.test.ts +40 -0
  299. package/src/explicit-capture.test.ts +1110 -1
  300. package/src/explicit-capture.ts +534 -135
  301. package/src/maintenance/purge.test.ts +157 -1
  302. package/src/maintenance/purge.ts +15 -9
  303. package/src/orchestration/recall-internal-deps.ts +385 -0
  304. package/src/orchestration/recall-internal.ts +16 -375
  305. package/src/secure-store/secure-fs.ts +78 -1
  306. package/src/storage/content-hash-index.ts +43 -17
  307. package/src/storage/tombstone-blocked-capture-index.ts +562 -0
  308. package/src/storage/tombstone-blocked-capture-mutation.ts +284 -0
  309. package/src/storage/tombstone-blocked-capture-sync.ts +872 -0
  310. package/src/storage-fact-hash-index-defer.test.ts +2900 -57
  311. package/src/storage.ts +266 -265
  312. package/src/testing/subjects/tombstone-blocked-capture.test.ts +181 -0
  313. package/src/utils/serialize-mutations.test.ts +4 -1
  314. package/src/utils/serialize-mutations.ts +26 -27
  315. package/dist/chunk-55MDBZLC.js +0 -490
  316. package/dist/chunk-55MDBZLC.js.map +0 -1
  317. package/dist/chunk-AIK5W3IW.js.map +0 -1
  318. package/dist/chunk-FUYEVEX7.js.map +0 -1
  319. package/dist/chunk-JMQUBRV6.js.map +0 -1
  320. package/dist/chunk-WL5EBRDH.js.map +0 -1
  321. package/dist/purge-YSGX5BOG.js.map +0 -1
  322. /package/dist/{chunk-FZRQZW4H.js.map → chunk-2EUVEDF5.js.map} +0 -0
  323. /package/dist/{chunk-3JNDOAQ2.js.map → chunk-5W4ZLBEZ.js.map} +0 -0
  324. /package/dist/{chunk-5ZCUDWD4.js.map → chunk-62U4J2GN.js.map} +0 -0
  325. /package/dist/{chunk-IGPEJVBY.js.map → chunk-66772WBP.js.map} +0 -0
  326. /package/dist/{chunk-EP5BVCRI.js.map → chunk-6BNE62PM.js.map} +0 -0
  327. /package/dist/{chunk-AAP5T6QG.js.map → chunk-6DNMUYEE.js.map} +0 -0
  328. /package/dist/{chunk-35DL7IOI.js.map → chunk-6FUPCJUL.js.map} +0 -0
  329. /package/dist/{chunk-JP3YPDAW.js.map → chunk-6U7F52DE.js.map} +0 -0
  330. /package/dist/{chunk-E4OCKU67.js.map → chunk-7XC2HX75.js.map} +0 -0
  331. /package/dist/{chunk-OVRQLAYR.js.map → chunk-AZ5BTEKX.js.map} +0 -0
  332. /package/dist/{chunk-2AXMQWCN.js.map → chunk-CZRYLSSW.js.map} +0 -0
  333. /package/dist/{chunk-PTSNLEXK.js.map → chunk-FDAMS4PK.js.map} +0 -0
  334. /package/dist/{chunk-2GXM5N5A.js.map → chunk-GIBMDSJ2.js.map} +0 -0
  335. /package/dist/{chunk-E5OBR6CJ.js.map → chunk-H5CPS5JP.js.map} +0 -0
  336. /package/dist/{chunk-2D7FEUCK.js.map → chunk-I5NLEENJ.js.map} +0 -0
  337. /package/dist/{chunk-DRBXHRXE.js.map → chunk-IB26HVAJ.js.map} +0 -0
  338. /package/dist/{chunk-QDKK63Y7.js.map → chunk-IC6CBHCA.js.map} +0 -0
  339. /package/dist/{chunk-IAEAFLF2.js.map → chunk-JCBWCYEJ.js.map} +0 -0
  340. /package/dist/{chunk-3PDOVUHC.js.map → chunk-KXB4VXHY.js.map} +0 -0
  341. /package/dist/{chunk-WU7TTVOD.js.map → chunk-LBOD4U5B.js.map} +0 -0
  342. /package/dist/{chunk-UBKEQOTD.js.map → chunk-LGHKJABJ.js.map} +0 -0
  343. /package/dist/{chunk-VSURVXKY.js.map → chunk-M3C2V3PV.js.map} +0 -0
  344. /package/dist/{chunk-OFHFH655.js.map → chunk-MJCGLM25.js.map} +0 -0
  345. /package/dist/{chunk-OYJKSZIQ.js.map → chunk-NHWB6HG2.js.map} +0 -0
  346. /package/dist/{chunk-TC3VNKGX.js.map → chunk-NM2WP3B7.js.map} +0 -0
  347. /package/dist/{chunk-GAWOEQEQ.js.map → chunk-P5PXWTW7.js.map} +0 -0
  348. /package/dist/{chunk-2QMKMVHH.js.map → chunk-QNWXCJ76.js.map} +0 -0
  349. /package/dist/{chunk-WRFBW2TT.js.map → chunk-SPJXKAVF.js.map} +0 -0
  350. /package/dist/{chunk-HKJCMOT6.js.map → chunk-TH2LSRMG.js.map} +0 -0
  351. /package/dist/{chunk-CW4AGY3G.js.map → chunk-VI2JQPNQ.js.map} +0 -0
  352. /package/dist/{chunk-OP6F6L3S.js.map → chunk-W5EG6LE3.js.map} +0 -0
  353. /package/dist/{chunk-DEBHXHJR.js.map → chunk-WIPEXG6R.js.map} +0 -0
  354. /package/dist/{chunk-SH6YO3LT.js.map → chunk-WVO4G37W.js.map} +0 -0
  355. /package/dist/{chunk-7L45JFPW.js.map → chunk-YTQNQ4KB.js.map} +0 -0
  356. /package/dist/{chunk-PKRIQL3V.js.map → chunk-YTSNAUXN.js.map} +0 -0
  357. /package/dist/{chunk-5QDRGWT2.js.map → chunk-ZPSVBSOF.js.map} +0 -0
  358. /package/dist/{forget-HRPLVB3W.js.map → forget-4UY2EOKH.js.map} +0 -0
@@ -13,7 +13,7 @@ import {
13
13
  TombstoneStore,
14
14
  buildRetiredFactTombstoneInputs,
15
15
  collectRetiredMemoriesForRebuild
16
- } from "./chunk-2QMKMVHH.js";
16
+ } from "./chunk-QNWXCJ76.js";
17
17
  import {
18
18
  computeSupersessionKey,
19
19
  normalizeSupersessionKey,
@@ -42,13 +42,10 @@ import {
42
42
  readMaybeEncryptedLines,
43
43
  readMemoryActionEventRowsFromLines,
44
44
  serializeLifecycleAppendPayload
45
- } from "./chunk-OFHFH655.js";
45
+ } from "./chunk-MJCGLM25.js";
46
46
  import {
47
47
  namespaceIdentityFromToken
48
48
  } from "./chunk-EGGE52UU.js";
49
- import {
50
- withHeldFileLock
51
- } from "./chunk-WL5EBRDH.js";
52
49
  import {
53
50
  rewriteProjectedEntityReferences,
54
51
  rewriteProjectedMemoryEntityReference
@@ -57,15 +54,6 @@ import {
57
54
  assertPathInsideRoot,
58
55
  pathIsInside
59
56
  } from "./chunk-GCASGYIO.js";
60
- import {
61
- markProjectedMemoryPathInvalid,
62
- openProjectionReadonly,
63
- readProjectedGovernanceRecord,
64
- readProjectedMemoryBrowse,
65
- readProjectedMemoryState,
66
- readProjectedMemoryTimeline,
67
- updateProjectedMemoryPath
68
- } from "./chunk-3CSX3ETE.js";
69
57
  import {
70
58
  inferMemoryStatus,
71
59
  isArchivedMemoryPath,
@@ -91,6 +79,26 @@ import {
91
79
  parseFaithfulnessField,
92
80
  serializeFaithfulnessFields
93
81
  } from "./chunk-JYIJNNN3.js";
82
+ import {
83
+ CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS,
84
+ ContentHashIndex,
85
+ FactHashIndexNotAuthoritativeError,
86
+ TombstoneBlockedCaptureIndexHost,
87
+ buildExplicitCaptureDedupKey,
88
+ parseTombstoneBlockedOfflineSyncMemory
89
+ } from "./chunk-FBUE6PD3.js";
90
+ import {
91
+ withHeldFileLock
92
+ } from "./chunk-FFAZ2XFU.js";
93
+ import {
94
+ markProjectedMemoryPathInvalid,
95
+ openProjectionReadonly,
96
+ readProjectedGovernanceRecord,
97
+ readProjectedMemoryBrowse,
98
+ readProjectedMemoryState,
99
+ readProjectedMemoryTimeline,
100
+ updateProjectedMemoryPath
101
+ } from "./chunk-3CSX3ETE.js";
94
102
  import {
95
103
  composeMemoryEnvelope,
96
104
  isSealedMemoryEnvelope,
@@ -126,10 +134,6 @@ import {
126
134
  getInFlightRead,
127
135
  setInFlightRead
128
136
  } from "./chunk-PDJTHRAW.js";
129
- import {
130
- computeContentHash,
131
- normalizeContent
132
- } from "./chunk-W5H6ZRPT.js";
133
137
  import {
134
138
  isConsolidationOperator,
135
139
  isValidDerivedFromEntry
@@ -164,9 +168,8 @@ import {
164
168
  probeEncryptedRegularFileHeader,
165
169
  readMaybeEncryptedFile,
166
170
  readMaybeEncryptedFileBuffer,
167
- writeMaybeEncryptedFile,
168
- writeMaybeEncryptedFileFromChunks
169
- } from "./chunk-AIK5W3IW.js";
171
+ writeMaybeEncryptedFile
172
+ } from "./chunk-5TFP4CUL.js";
170
173
  import {
171
174
  isErrnoCode
172
175
  } from "./chunk-5UZXUTVO.js";
@@ -208,16 +211,16 @@ import {
208
211
  readdir as readdir5,
209
212
  readFile as readFile2,
210
213
  realpath as realpath3,
211
- stat as stat3,
214
+ stat as stat2,
212
215
  writeFile as writeFile2,
213
- mkdir as mkdir2,
216
+ mkdir,
214
217
  unlink as unlink3,
215
218
  appendFile,
216
219
  open
217
220
  } from "fs/promises";
218
221
  import { appendFileSync, createReadStream, mkdirSync, readFileSync as readFileSync2, statSync } from "fs";
219
222
  import { createHash as createHash5 } from "crypto";
220
- import path10 from "path";
223
+ import path9 from "path";
221
224
 
222
225
  // src/storage/memory-read-store.ts
223
226
  import { lstat, readdir, realpath, stat } from "fs/promises";
@@ -1650,26 +1653,26 @@ function assertSafeEntityId(entityId) {
1650
1653
  }
1651
1654
  }
1652
1655
  async function assertNotSymlink(filePath, label) {
1653
- let stat4;
1656
+ let stat3;
1654
1657
  try {
1655
- stat4 = await lstat2(filePath);
1658
+ stat3 = await lstat2(filePath);
1656
1659
  } catch (error) {
1657
1660
  if (isErrnoCode(error, "ENOENT")) return;
1658
1661
  throw error;
1659
1662
  }
1660
- if (stat4.isSymbolicLink()) {
1663
+ if (stat3.isSymbolicLink()) {
1661
1664
  throw new Error(`Refusing entity canonical-id migration through symlink: ${label}.`);
1662
1665
  }
1663
1666
  }
1664
1667
  async function assertNotMemorySymlink(filePath) {
1665
- let stat4;
1668
+ let stat3;
1666
1669
  try {
1667
- stat4 = await lstat2(filePath);
1670
+ stat3 = await lstat2(filePath);
1668
1671
  } catch (error) {
1669
1672
  if (isErrnoCode(error, "ENOENT")) return;
1670
1673
  throw error;
1671
1674
  }
1672
- if (stat4.isSymbolicLink()) {
1675
+ if (stat3.isSymbolicLink()) {
1673
1676
  throw new Error(`Refusing entity canonical-id migration through symlinked memory: ${filePath}.`);
1674
1677
  }
1675
1678
  }
@@ -4175,14 +4178,14 @@ var FusionArtifactStore = class {
4175
4178
  */
4176
4179
  async assertFusionDirNotSymlinked() {
4177
4180
  const fusionDir = path7.join(this.wearablesDir, FUSION_DIR_NAME);
4178
- let stat4;
4181
+ let stat3;
4179
4182
  try {
4180
- stat4 = await this.io.lstat(fusionDir);
4183
+ stat3 = await this.io.lstat(fusionDir);
4181
4184
  } catch (err) {
4182
4185
  if (err.code === "ENOENT") return;
4183
4186
  throw err;
4184
4187
  }
4185
- if (stat4.isSymbolicLink) {
4188
+ if (stat3.isSymbolicLink) {
4186
4189
  throw new Error(
4187
4190
  "wearable fusion dir '_fusion' is a symbolic link \u2014 refusing to follow it even when it resolves inside the memory dir (AGENTS.md pattern #3)"
4188
4191
  );
@@ -4614,14 +4617,14 @@ var MeetingRecordStore = class {
4614
4617
  return path8.join(this.meetingsDir, first);
4615
4618
  }
4616
4619
  async assertNotSymlink(target, kind) {
4617
- let stat4;
4620
+ let stat3;
4618
4621
  try {
4619
- stat4 = await this.io.lstat(target);
4622
+ stat3 = await this.io.lstat(target);
4620
4623
  } catch (err) {
4621
4624
  if (err.code === "ENOENT") return;
4622
4625
  throw err;
4623
4626
  }
4624
- if (stat4.isSymbolicLink) {
4627
+ if (stat3.isSymbolicLink) {
4625
4628
  const label = path8.relative(this.memoryDir, target) || MEETINGS_DIR_NAME;
4626
4629
  throw new Error(
4627
4630
  `meetings ${kind} '${label}' is a symbolic link \u2014 refusing to follow it even when it resolves inside the memory dir (AGENTS.md pattern #3)`
@@ -5038,471 +5041,6 @@ function isEntitySynthesisStale(entity) {
5038
5041
  return entity.timeline.length > entity.synthesisTimelineCount || structuredFactCount > (entity.synthesisStructuredFactCount ?? 0) || structuredFactDigest !== storedStructuredFactDigest;
5039
5042
  }
5040
5043
 
5041
- // src/storage/content-hash-index.ts
5042
- import { mkdir, stat as stat2 } from "fs/promises";
5043
- import path9 from "path";
5044
- var CONTENT_HASH_INDEX_LOCK_STALE_MS = 3e4;
5045
- var CONTENT_HASH_INDEX_RETRY_MAX_ATTEMPTS = 5;
5046
- var CONTENT_HASH_INDEX_RETRY_BASE_MS = 500;
5047
- var CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS = 5e3;
5048
- var FactHashIndexNotAuthoritativeError = class extends Error {
5049
- constructor(stateDir) {
5050
- super(
5051
- `fact-hash index is not authoritative: the cross-process rebuild lock for ${stateDir} could not be acquired within the bounded retry budget`
5052
- );
5053
- this.name = "FactHashIndexNotAuthoritativeError";
5054
- }
5055
- };
5056
- var ContentHashIndex = class _ContentHashIndex {
5057
- hashes = /* @__PURE__ */ new Set();
5058
- dirty = false;
5059
- /**
5060
- * Hashes explicitly removed since the last successful save (issue #1909 review
5061
- * round 8 thread 3). Tracked separately so `saveMergingWithDisk` can be
5062
- * removal-AWARE: under the file lock it reads the latest on-disk set, DROPS
5063
- * these, then unions our additions — so a removal batch cannot resurrect a
5064
- * hash (union alone would) and cannot clobber a concurrent extraction's
5065
- * appended hash (blind overwrite would). Consumed + cleared by every save.
5066
- */
5067
- removed = /* @__PURE__ */ new Set();
5068
- /**
5069
- * Hashes added by THIS instance since the last successful save (issue #1909
5070
- * review round 9 finding 3). Tracked separately from the loaded snapshot so a
5071
- * reconciling save publishes `(on-disk \ removed) ∪ added` — it re-applies only
5072
- * OUR additions, never the stale loaded entries. Without this, seeding the
5073
- * merge from `this.hashes` (loaded ∪ added) would resurrect a hash a peer
5074
- * removed on disk while this instance held a stale snapshot.
5075
- */
5076
- added = /* @__PURE__ */ new Set();
5077
- filePath;
5078
- secureStoreKeyProvider;
5079
- secureStoreWriteKeyProvider;
5080
- memoryDir;
5081
- lockOptions;
5082
- /**
5083
- * Deferred reconcile-save durable-retry state (issue #1909 / PR #2016). At
5084
- * most ONE retry is ever armed (`reconcileRetryTimer` is the reentrancy guard)
5085
- * so successive timed-out saves cannot stack duplicate/parallel retries.
5086
- * `reconcileRetryBarrier` resolves when the chain settles (published or gave
5087
- * up) — awaited by tests and any caller wanting the eventual result.
5088
- */
5089
- reconcileRetryTimer = null;
5090
- reconcileRetryAttempts = 0;
5091
- reconcileRetryBarrier = null;
5092
- reconcileRetryResolve = null;
5093
- /**
5094
- * On-disk fingerprint (mtime + byte size) of `fact-hashes.txt` captured at the
5095
- * last point THIS instance's in-memory set matched disk — after `load()`,
5096
- * `save()`, or a reconcile publish (PR #2016 review). A peer process that
5097
- * advances the durable index changes this fingerprint;
5098
- * {@link isDiskFingerprintCurrent} compares a single cheap `stat` against it so
5099
- * a stale-but-"authoritative" snapshot is detected without an O(file-size)
5100
- * re-read on the hot path.
5101
- */
5102
- lastSyncedFingerprint = null;
5103
- constructor(stateDir, secureStoreKeyProvider = () => null, secureStoreWriteKeyProvider = secureStoreKeyProvider, memoryDir = path9.dirname(stateDir), lockOptions = {}) {
5104
- this.filePath = path9.join(stateDir, "fact-hashes.txt");
5105
- this.secureStoreKeyProvider = secureStoreKeyProvider;
5106
- this.secureStoreWriteKeyProvider = secureStoreWriteKeyProvider;
5107
- this.memoryDir = memoryDir;
5108
- this.lockOptions = lockOptions;
5109
- }
5110
- /** Load existing hashes from disk. Safe to call multiple times. */
5111
- async load() {
5112
- try {
5113
- const raw = await readMaybeEncryptedFile(this.filePath, this.secureStoreKeyProvider(), this.memoryDir);
5114
- for (const line of raw.split("\n")) {
5115
- const trimmed = line.trim();
5116
- if (trimmed.length > 0) {
5117
- this.hashes.add(trimmed);
5118
- }
5119
- }
5120
- log.debug(`content-hash index: loaded ${this.hashes.size} hashes`);
5121
- } catch (err) {
5122
- if (err instanceof SecureStoreLockedError) throw err;
5123
- if (!isErrnoCode(err, "ENOENT")) throw err;
5124
- log.debug("content-hash index: no existing index \u2014 starting fresh");
5125
- }
5126
- await this.captureSyncedFingerprint();
5127
- }
5128
- /** Cheap `stat` of the durable index file; null when it does not exist yet. */
5129
- async statIndexFile() {
5130
- try {
5131
- const s = await stat2(this.filePath);
5132
- return { mtimeMs: s.mtimeMs, size: s.size };
5133
- } catch (err) {
5134
- if (isErrnoCode(err, "ENOENT")) return null;
5135
- throw err;
5136
- }
5137
- }
5138
- /** Record the current on-disk fingerprint as this instance's synced baseline. */
5139
- async captureSyncedFingerprint() {
5140
- try {
5141
- this.lastSyncedFingerprint = await this.statIndexFile();
5142
- } catch (err) {
5143
- this.lastSyncedFingerprint = null;
5144
- log.debug(`content-hash index: could not fingerprint ${this.filePath}: ${err}`);
5145
- }
5146
- }
5147
- /**
5148
- * True when the durable index file is unchanged since this instance last
5149
- * synced it (load / save / reconcile). False when a peer advanced it, when the
5150
- * file appeared or vanished, or when freshness cannot be established (stat
5151
- * error) — the caller then treats the in-memory snapshot as non-authoritative
5152
- * and confirms a dedup miss against the durable corpus (PR #2016 review). One
5153
- * `stat`, never an O(file-size) read, so the hot path stays cheap.
5154
- */
5155
- async isDiskFingerprintCurrent() {
5156
- let current;
5157
- try {
5158
- current = await this.statIndexFile();
5159
- } catch {
5160
- return false;
5161
- }
5162
- const last = this.lastSyncedFingerprint;
5163
- if (last === null || current === null) {
5164
- return last === null && current === null;
5165
- }
5166
- return current.mtimeMs === last.mtimeMs && current.size === last.size;
5167
- }
5168
- /** Check if content already exists in the index. */
5169
- has(content) {
5170
- return this.hashes.has(_ContentHashIndex.computeHash(content));
5171
- }
5172
- /** Add content hash to the index. */
5173
- add(content) {
5174
- const hash = _ContentHashIndex.computeHash(content);
5175
- this.removed.delete(hash);
5176
- this.hashes.add(hash);
5177
- this.added.add(hash);
5178
- this.dirty = true;
5179
- }
5180
- get size() {
5181
- return this.hashes.size;
5182
- }
5183
- /** Clear all loaded hashes so the next save rewrites the index from scratch. */
5184
- clear() {
5185
- if (this.hashes.size > 0) {
5186
- this.hashes.clear();
5187
- }
5188
- this.added.clear();
5189
- this.removed.clear();
5190
- this.cancelReconcileRetry();
5191
- this.dirty = true;
5192
- }
5193
- /** Persist index to disk if changed (plain whole-file overwrite). */
5194
- async save() {
5195
- if (!this.dirty) return;
5196
- await mkdir(path9.dirname(this.filePath), { recursive: true });
5197
- const publishedAdded = new Set(this.added);
5198
- const publishedRemoved = new Set(this.removed);
5199
- const serialized = [...this.hashes].join("\n") + "\n";
5200
- await writeMaybeEncryptedFile(
5201
- this.filePath,
5202
- serialized,
5203
- this.secureStoreWriteKeyProvider(),
5204
- {},
5205
- this.memoryDir
5206
- );
5207
- for (const h of publishedAdded) this.added.delete(h);
5208
- for (const h of publishedRemoved) this.removed.delete(h);
5209
- this.dirty = this.added.size > 0 || this.removed.size > 0;
5210
- await this.captureSyncedFingerprint();
5211
- if (this.dirty) {
5212
- this.scheduleReconcileRetry();
5213
- } else {
5214
- this.cancelReconcileRetry();
5215
- }
5216
- log.debug(`content-hash index: saved ${this.hashes.size} hashes`);
5217
- }
5218
- /**
5219
- * Persist the index by RECONCILING with the latest on-disk state under a
5220
- * cross-process lock (issue #1909). Used by the extraction-persist batch save
5221
- * for BOTH append and removal batches, so appends and removals to the same
5222
- * index serialize against each other:
5223
- * final = (on-disk \ this.removed) ∪ this.added
5224
- * Note it re-applies only OUR local additions (`added`), NOT the loaded
5225
- * snapshot (review round 9 finding 3): seeding from `this.hashes` would
5226
- * resurrect a hash a peer removed on disk while we held a stale snapshot. This
5227
- * preserves a concurrent writer's appended hashes (a blind overwrite would
5228
- * drop them), never resurrects a removed hash, and never loses our additions.
5229
- *
5230
- * Hardening:
5231
- * - Dirty short-circuit (round 7 finding 3): when this instance neither added
5232
- * nor removed anything this run, skip the O(file) read+rewrite entirely.
5233
- * - Cross-process lock (round 7 finding 2): serialize the read→reconcile→write
5234
- * window on a per-file advisory lock. If the lock is NOT acquired (timeout),
5235
- * do NOT publish (round 9 finding 2): keep `dirty` set AND schedule a bounded
5236
- * durable background retry (PR #2016) that keeps re-attempting the locked
5237
- * publish until the deferred additions land — never an unlocked write that
5238
- * could clobber a peer, and never a silent "batch save complete" that leaves
5239
- * the addition in this process's memory only.
5240
- */
5241
- async saveMergingWithDisk() {
5242
- if (!this.dirty) return;
5243
- await mkdir(path9.dirname(this.filePath), { recursive: true });
5244
- const publish = async () => {
5245
- const publishedAdded = new Set(this.added);
5246
- const publishedRemoved = new Set(this.removed);
5247
- const merged = new Set(publishedAdded);
5248
- try {
5249
- const raw = await readMaybeEncryptedFile(
5250
- this.filePath,
5251
- this.secureStoreKeyProvider(),
5252
- this.memoryDir
5253
- );
5254
- for (const line of raw.split("\n")) {
5255
- const trimmed = line.trim();
5256
- if (trimmed.length > 0 && !publishedRemoved.has(trimmed)) merged.add(trimmed);
5257
- }
5258
- } catch (err) {
5259
- if (err instanceof SecureStoreLockedError) throw err;
5260
- if (!isErrnoCode(err, "ENOENT")) throw err;
5261
- }
5262
- await mkdir(path9.dirname(this.filePath), { recursive: true });
5263
- await writeMaybeEncryptedFile(
5264
- this.filePath,
5265
- [...merged].join("\n") + "\n",
5266
- this.secureStoreWriteKeyProvider(),
5267
- {},
5268
- this.memoryDir
5269
- );
5270
- for (const h of publishedAdded) this.added.delete(h);
5271
- for (const h of publishedRemoved) this.removed.delete(h);
5272
- for (const h of this.added) merged.add(h);
5273
- for (const h of this.removed) merged.delete(h);
5274
- this.hashes = merged;
5275
- this.dirty = this.added.size > 0 || this.removed.size > 0;
5276
- await this.captureSyncedFingerprint();
5277
- };
5278
- await withHeldFileLock(
5279
- `${this.filePath}.lock`,
5280
- {
5281
- staleMs: CONTENT_HASH_INDEX_LOCK_STALE_MS,
5282
- ...this.lockOptions.maxWaitMs !== void 0 ? { maxWaitMs: this.lockOptions.maxWaitMs } : {},
5283
- ...this.lockOptions.pollMs !== void 0 ? { pollMs: this.lockOptions.pollMs } : {}
5284
- },
5285
- async (acquired) => {
5286
- if (!acquired) {
5287
- log.warn(
5288
- `content-hash index: lock not acquired for ${this.filePath}; deferring reconcile save (dirty retained, scheduling durable retry)`
5289
- );
5290
- this.scheduleReconcileRetry();
5291
- return;
5292
- }
5293
- await publish();
5294
- if (this.dirty) {
5295
- this.scheduleReconcileRetry();
5296
- } else {
5297
- this.cancelReconcileRetry();
5298
- }
5299
- }
5300
- );
5301
- log.debug(`content-hash index: reconcile-saved ${this.hashes.size} hashes`);
5302
- }
5303
- /**
5304
- * Rebuild-and-publish the index from an authoritative source (the durable
5305
- * corpus) under the SAME per-file cross-process lock the reconciling
5306
- * append/removal saves (`saveMergingWithDisk`) use (issue #1909 / PR #2016).
5307
- * The `populate` callback runs WHILE the lock is held and MUST repopulate this
5308
- * index from the corpus (`clear()` then `addByHash(...)` for every corpus
5309
- * hash); the rebuilt set is then published with a plain overwrite that is now
5310
- * serialized against every locked writer.
5311
- *
5312
- * This closes the finding where the previous unlocked clear→scan→save() could
5313
- * overwrite a peer's newer lock-merged or deferred additions: a locked writer
5314
- * that committed BEFORE the rebuild acquired the lock has its memory `.md` on
5315
- * disk and is re-scanned; one that commits AFTER the rebuild releases
5316
- * reconciles its additions on top of the freshly-published set. No union with
5317
- * the raw on-disk file is performed, so the rebuild keeps its
5318
- * garbage-collection property (orphaned hashes for deleted memories drop).
5319
- *
5320
- * Lock-acquisition failure is explicit and non-destructive: `populate` is NOT
5321
- * run and nothing is written (never an unlocked overwrite). Returns true when
5322
- * the rebuild was published under the lock, false when the lock timed out —
5323
- * the caller keeps the index non-authoritative and retries on next use. Uses
5324
- * the same non-reentrant file lock as the reconcile path, so it can never
5325
- * deadlock with the deferred reconcile-retry: a concurrent locked writer (or a
5326
- * fired retry) simply yields `acquired=false` after the bounded wait.
5327
- */
5328
- async rebuildUnderLock(populate) {
5329
- await mkdir(path9.dirname(this.filePath), { recursive: true });
5330
- let published = false;
5331
- await withHeldFileLock(
5332
- `${this.filePath}.lock`,
5333
- {
5334
- staleMs: CONTENT_HASH_INDEX_LOCK_STALE_MS,
5335
- ...this.lockOptions.maxWaitMs !== void 0 ? { maxWaitMs: this.lockOptions.maxWaitMs } : {},
5336
- ...this.lockOptions.pollMs !== void 0 ? { pollMs: this.lockOptions.pollMs } : {}
5337
- },
5338
- async (acquired) => {
5339
- if (!acquired) {
5340
- log.warn(
5341
- `content-hash index: lock not acquired for ${this.filePath}; deferring authoritative rebuild (index left non-authoritative, retried on next use)`
5342
- );
5343
- return;
5344
- }
5345
- await populate();
5346
- await this.save();
5347
- published = true;
5348
- }
5349
- );
5350
- return published;
5351
- }
5352
- /**
5353
- * True while a background durable reconcile-save retry is armed (PR #2016).
5354
- * Test/introspection hook.
5355
- */
5356
- get hasPendingReconcileRetry() {
5357
- return this.reconcileRetryTimer !== null;
5358
- }
5359
- /**
5360
- * Resolve once any armed background reconcile-save retry chain has settled —
5361
- * either it published the deferred additions, or it exhausted its bounded
5362
- * attempts and fell back to the corpus-rebuild safety net. Resolves
5363
- * immediately when nothing is armed. Lets a caller (or a test) await the
5364
- * eventual durability outcome of a lock-timed-out save.
5365
- */
5366
- async whenReconcileRetrySettled() {
5367
- await (this.reconcileRetryBarrier ?? Promise.resolve());
5368
- }
5369
- /**
5370
- * Drive any deferred lock-timeout reconcile save to completion INLINE at a
5371
- * lifecycle boundary (PR #2016 finding 3). The background retry timer is
5372
- * `unref`'d so it never keeps a long-lived daemon alive — but a short-lived
5373
- * writer (a one-shot CLI) can exit before it fires, leaving a durable fact
5374
- * `.md` whose hash never reached `fact-hashes.txt` for peers that already
5375
- * built their in-memory index. `orchestrator.destroy()` calls this so the
5376
- * addition publishes before the process exits; long-lived hosts only reach it
5377
- * at their own shutdown, so their in-flight retries keep running in the
5378
- * background until then. Bounded by the same attempt ceiling as the background
5379
- * retry; a permanently contended lock falls back to the corpus-rebuild-on-
5380
- * restart safety net (the fact `.md` is already durable). No deadlock: each
5381
- * attempt is the same non-reentrant, bounded-wait file lock.
5382
- */
5383
- async flushReconcileRetry() {
5384
- if (!this.dirty) return;
5385
- const maxAttempts = this.lockOptions.retryMaxAttempts ?? CONTENT_HASH_INDEX_RETRY_MAX_ATTEMPTS;
5386
- const baseMs = this.lockOptions.retryBaseMs ?? CONTENT_HASH_INDEX_RETRY_BASE_MS;
5387
- for (let attempt = 0; this.dirty && attempt < maxAttempts; attempt += 1) {
5388
- if (this.reconcileRetryTimer) {
5389
- clearTimeout(this.reconcileRetryTimer);
5390
- this.reconcileRetryTimer = null;
5391
- }
5392
- await this.saveMergingWithDisk();
5393
- if (!this.dirty) break;
5394
- if (attempt < maxAttempts - 1) {
5395
- const wait = Math.min(baseMs * 2 ** attempt, CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS);
5396
- await new Promise((resolve3) => setTimeout(resolve3, wait));
5397
- }
5398
- }
5399
- if (this.reconcileRetryTimer) {
5400
- clearTimeout(this.reconcileRetryTimer);
5401
- this.reconcileRetryTimer = null;
5402
- }
5403
- this.reconcileRetryAttempts = 0;
5404
- this.settleReconcileRetry();
5405
- }
5406
- /**
5407
- * Schedule ONE bounded, exponentially-backed-off background retry of the
5408
- * deferred reconcile save (PR #2016). Reentrant-safe: an already-armed timer
5409
- * short-circuits, so successive timed-out saves never stack duplicate retries.
5410
- * When attempts are exhausted the chain settles without publishing — the
5411
- * durable fact `.md` is on disk and a process restart rebuilds the index from
5412
- * the corpus, so this degrades to that safety net, never a fatal failure.
5413
- */
5414
- scheduleReconcileRetry() {
5415
- if (this.reconcileRetryTimer) return;
5416
- const maxAttempts = this.lockOptions.retryMaxAttempts ?? CONTENT_HASH_INDEX_RETRY_MAX_ATTEMPTS;
5417
- if (this.reconcileRetryAttempts >= maxAttempts) {
5418
- log.warn(
5419
- `content-hash index: exhausted ${maxAttempts} deferred reconcile-save retries for ${this.filePath}; ${this.added.size} addition(s) remain dirty in-memory (a process restart rebuilds the index from the durable corpus)`
5420
- );
5421
- this.reconcileRetryAttempts = 0;
5422
- this.settleReconcileRetry();
5423
- return;
5424
- }
5425
- if (!this.reconcileRetryBarrier) {
5426
- this.reconcileRetryBarrier = new Promise((resolve3) => {
5427
- this.reconcileRetryResolve = resolve3;
5428
- });
5429
- }
5430
- const attempt = this.reconcileRetryAttempts + 1;
5431
- const baseMs = this.lockOptions.retryBaseMs ?? CONTENT_HASH_INDEX_RETRY_BASE_MS;
5432
- const delay = Math.min(baseMs * 2 ** (attempt - 1), CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS);
5433
- this.reconcileRetryTimer = setTimeout(() => {
5434
- this.reconcileRetryTimer = null;
5435
- this.reconcileRetryAttempts = attempt;
5436
- void this.saveMergingWithDisk().catch((err) => {
5437
- log.warn(`content-hash index: deferred reconcile-save retry failed for ${this.filePath}: ${err}`);
5438
- }).finally(() => {
5439
- if (this.dirty && !this.reconcileRetryTimer) this.settleReconcileRetry();
5440
- });
5441
- }, delay);
5442
- this.reconcileRetryTimer.unref?.();
5443
- }
5444
- /** Cancel any armed reconcile-save retry and settle the barrier (a publish landed). */
5445
- cancelReconcileRetry() {
5446
- if (this.reconcileRetryTimer) {
5447
- clearTimeout(this.reconcileRetryTimer);
5448
- this.reconcileRetryTimer = null;
5449
- }
5450
- this.reconcileRetryAttempts = 0;
5451
- this.settleReconcileRetry();
5452
- }
5453
- /** Resolve and clear the retry barrier if one is outstanding. */
5454
- settleReconcileRetry() {
5455
- const resolve3 = this.reconcileRetryResolve;
5456
- this.reconcileRetryBarrier = null;
5457
- this.reconcileRetryResolve = null;
5458
- resolve3?.();
5459
- }
5460
- /** Remove a hash from the index (used when archiving/deleting). */
5461
- remove(content) {
5462
- const hash = _ContentHashIndex.computeHash(content);
5463
- this.added.delete(hash);
5464
- this.removed.add(hash);
5465
- this.hashes.delete(hash);
5466
- this.dirty = true;
5467
- }
5468
- /**
5469
- * Remove a pre-computed SHA-256 hash directly from the index without
5470
- * re-hashing. Use this when the caller already holds the stored hash
5471
- * (e.g. `memory.frontmatter.contentHash`) to avoid the double-hash bug
5472
- * where `remove(hash)` would compute `hash(hash)` and never match the
5473
- * entry.
5474
- */
5475
- removeByHash(hash) {
5476
- this.added.delete(hash);
5477
- this.removed.add(hash);
5478
- this.hashes.delete(hash);
5479
- this.dirty = true;
5480
- }
5481
- /**
5482
- * Add a pre-computed SHA-256 hash directly to the index without re-hashing.
5483
- * Use this when the caller already holds the stored hash
5484
- * (e.g. `memory.frontmatter.contentHash`) so that the index records the raw
5485
- * content hash rather than re-hashing the citation-annotated body.
5486
- *
5487
- * @internal Only called from `StorageManager.ensureFactHashIndexAuthoritative`.
5488
- * Not part of the public API — prefer `add(content)` for external callers.
5489
- */
5490
- addByHash(hash) {
5491
- this.removed.delete(hash);
5492
- this.hashes.add(hash);
5493
- this.added.add(hash);
5494
- this.dirty = true;
5495
- }
5496
- /** Normalize content (delegates to content-hash.ts for a single source of truth). */
5497
- static normalizeContent(content) {
5498
- return normalizeContent(content);
5499
- }
5500
- /** Compute SHA-256 hash (delegates to content-hash.ts for a single source of truth). */
5501
- static computeHash(content) {
5502
- return computeContentHash(content);
5503
- }
5504
- };
5505
-
5506
5044
  // src/storage.ts
5507
5045
  var ARTIFACT_SEARCH_STOPWORDS = /* @__PURE__ */ new Set([
5508
5046
  "a",
@@ -6127,17 +5665,17 @@ function inferEntityTypeFromContent(content) {
6127
5665
  }
6128
5666
  var KNOWN_ENTITY_FILENAME_PREFIXES = /* @__PURE__ */ new Set(["company", "other", "person", "place", "project", "tool", "topic"]);
6129
5667
  function inferEntityTypeFromFilename(pathRel) {
6130
- const basename = path10.basename(pathRel, ".md").toLowerCase();
5668
+ const basename = path9.basename(pathRel, ".md").toLowerCase();
6131
5669
  const separator = basename.indexOf("-");
6132
5670
  if (separator <= 0) return void 0;
6133
5671
  const candidate = basename.slice(0, separator);
6134
5672
  return KNOWN_ENTITY_FILENAME_PREFIXES.has(candidate) ? candidate : void 0;
6135
5673
  }
6136
5674
  function normalizeFrontmatterForPath(frontmatter, pathRel, content = "") {
6137
- const normalizedPath = pathRel.split(path10.sep).join("/");
5675
+ const normalizedPath = pathRel.split(path9.sep).join("/");
6138
5676
  let normalizedFrontmatter = frontmatter;
6139
5677
  if (normalizedPath === "entities" || normalizedPath.startsWith("entities/") || normalizedPath.includes("/entities/")) {
6140
- const basename = path10.basename(pathRel, ".md");
5678
+ const basename = path9.basename(pathRel, ".md");
6141
5679
  const inferredType = inferEntityTypeFromContent(content) || inferEntityTypeFromFilename(pathRel) || "entity";
6142
5680
  const existingTags = Array.isArray(frontmatter.tags) ? frontmatter.tags : [];
6143
5681
  normalizedFrontmatter = {
@@ -6597,8 +6135,9 @@ function parseExtractionRetryStateEntries(raw) {
6597
6135
  }
6598
6136
  return valid;
6599
6137
  }
6600
- var StorageManager3 = class _StorageManager {
6138
+ var StorageManager3 = class _StorageManager extends TombstoneBlockedCaptureIndexHost {
6601
6139
  constructor(baseDir, entitySchemas, hotMemoriesCacheEnabledOverride) {
6140
+ super();
6602
6141
  this.baseDir = baseDir;
6603
6142
  this.entitySchemas = entitySchemas;
6604
6143
  this.hotMemoriesCacheEnabled = hotMemoriesCacheEnabledOverride ?? _StorageManager.hotMemoriesCacheDefaultByDir.get(baseDir) ?? _StorageManager.hotMemoriesCacheDefault;
@@ -6783,8 +6322,8 @@ var StorageManager3 = class _StorageManager {
6783
6322
  }
6784
6323
  /** Whether `filePath` resolves to `stateDir` itself or a path contained in it. */
6785
6324
  isStateFilePath(filePath) {
6786
- const rel = path10.relative(this.stateDir, path10.resolve(filePath));
6787
- return rel === "" || !rel.startsWith("..") && !path10.isAbsolute(rel);
6325
+ const rel = path9.relative(this.stateDir, path9.resolve(filePath));
6326
+ return rel === "" || !rel.startsWith("..") && !path9.isAbsolute(rel);
6788
6327
  }
6789
6328
  // ── Tombstone store (issue #1579) ───────────────────────────────────────
6790
6329
  // Instance-scoped (rule 11) + namespace-scoped (rule 42) tombstone index.
@@ -6901,8 +6440,8 @@ var StorageManager3 = class _StorageManager {
6901
6440
  * /srv/cold/remnic), skipping the patch and stranding a stale hot entry.
6902
6441
  */
6903
6442
  isColdOrArchiveTierPath(p) {
6904
- const rel = path10.relative(this.baseDir, p);
6905
- return rel === "cold" || rel === "archive" || rel.startsWith(`cold${path10.sep}`) || rel.startsWith(`archive${path10.sep}`);
6443
+ const rel = path9.relative(this.baseDir, p);
6444
+ return rel === "cold" || rel === "archive" || rel.startsWith(`cold${path9.sep}`) || rel.startsWith(`archive${path9.sep}`);
6906
6445
  }
6907
6446
  /**
6908
6447
  * Mark the secure-store as required for this storage instance.
@@ -6989,7 +6528,7 @@ var StorageManager3 = class _StorageManager {
6989
6528
  void 0,
6990
6529
  this.baseDir
6991
6530
  );
6992
- const rel = path10.relative(this.baseDir, filePath).split(path10.sep).join("/");
6531
+ const rel = path9.relative(this.baseDir, filePath).split(path9.sep).join("/");
6993
6532
  return `${rel}:${version.versionId}`;
6994
6533
  } catch (err) {
6995
6534
  log.warn(
@@ -7069,13 +6608,13 @@ var StorageManager3 = class _StorageManager {
7069
6608
  }
7070
6609
  identityFilePath(workspaceDir, namespace) {
7071
6610
  const rawNamespace = typeof namespace === "string" ? namespace.trim() : "";
7072
- if (!rawNamespace) return path10.join(workspaceDir, "IDENTITY.md");
6611
+ if (!rawNamespace) return path9.join(workspaceDir, "IDENTITY.md");
7073
6612
  const safeNamespace = rawNamespace.replace(/[^a-zA-Z0-9._-]/g, "-");
7074
- return path10.join(workspaceDir, `IDENTITY.${safeNamespace}.md`);
6613
+ return path9.join(workspaceDir, `IDENTITY.${safeNamespace}.md`);
7075
6614
  }
7076
6615
  versionFilePath(kind) {
7077
6616
  const fileName = kind === "memory-status" ? ".memory-status-version.log" : kind === "artifact-write" ? ".artifact-write-version.log" : kind === "cold-write" ? ".cold-write-version.log" : ".memory-corpus-version.log";
7078
- return path10.join(this.stateDir, fileName);
6617
+ return path9.join(this.stateDir, fileName);
7079
6618
  }
7080
6619
  bumpSharedVersion(kind, fallbackMap) {
7081
6620
  const filePath = this.versionFilePath(kind);
@@ -7167,7 +6706,7 @@ var StorageManager3 = class _StorageManager {
7167
6706
  // memories.
7168
6707
  // -------------------------------------------------------------------------
7169
6708
  get wearablesDir() {
7170
- return path10.join(this.baseDir, WEARABLES_DIR_NAME);
6709
+ return path9.join(this.baseDir, WEARABLES_DIR_NAME);
7171
6710
  }
7172
6711
  /**
7173
6712
  * Resolve the on-disk path for a source/day transcript. Throws on
@@ -7183,7 +6722,7 @@ var StorageManager3 = class _StorageManager {
7183
6722
  if (!isValidTranscriptDate(date)) {
7184
6723
  throw new Error(`invalid wearable transcript date '${String(date)}' \u2014 expected YYYY-MM-DD`);
7185
6724
  }
7186
- return path10.join(this.wearablesDir, sourceId, `${date}.md`);
6725
+ return path9.join(this.wearablesDir, sourceId, `${date}.md`);
7187
6726
  }
7188
6727
  async writeWearableDayTranscript(sourceId, date, serialized) {
7189
6728
  const targetPath = this.wearableTranscriptPath(sourceId, date);
@@ -7299,25 +6838,25 @@ var StorageManager3 = class _StorageManager {
7299
6838
  });
7300
6839
  }
7301
6840
  get factsDir() {
7302
- return path10.join(this.baseDir, "facts");
6841
+ return path9.join(this.baseDir, "facts");
7303
6842
  }
7304
6843
  get correctionsDir() {
7305
- return path10.join(this.baseDir, "corrections");
6844
+ return path9.join(this.baseDir, "corrections");
7306
6845
  }
7307
6846
  get proceduresDir() {
7308
- return path10.join(this.baseDir, "procedures");
6847
+ return path9.join(this.baseDir, "procedures");
7309
6848
  }
7310
6849
  get reasoningTracesDir() {
7311
- return path10.join(this.baseDir, "reasoning-traces");
6850
+ return path9.join(this.baseDir, "reasoning-traces");
7312
6851
  }
7313
6852
  get entitiesDir() {
7314
- return path10.join(this.baseDir, "entities");
6853
+ return path9.join(this.baseDir, "entities");
7315
6854
  }
7316
6855
  resolveEntityFilePath(name) {
7317
6856
  if (typeof name !== "string") return null;
7318
- const filePath = path10.resolve(this.entitiesDir, `${name}.md`);
7319
- const relative2 = path10.relative(this.entitiesDir, filePath);
7320
- if (relative2 === "" || relative2.startsWith("..") || path10.isAbsolute(relative2)) {
6857
+ const filePath = path9.resolve(this.entitiesDir, `${name}.md`);
6858
+ const relative2 = path9.relative(this.entitiesDir, filePath);
6859
+ if (relative2 === "" || relative2.startsWith("..") || path9.isAbsolute(relative2)) {
7321
6860
  return null;
7322
6861
  }
7323
6862
  return filePath;
@@ -7331,17 +6870,11 @@ var StorageManager3 = class _StorageManager {
7331
6870
  this.notifyCatalogWriteForPath(filePath);
7332
6871
  });
7333
6872
  }
7334
- writeStorageSecureFileChunks(filePath, chunks) {
7335
- const writeKey = this.resolveWriteKey();
7336
- return writeMaybeEncryptedFileFromChunks(filePath, chunks, writeKey, {}, this.baseDir).then(() => {
7337
- this.notifyCatalogWriteForPath(filePath);
7338
- });
7339
- }
7340
6873
  assertManagedStoragePath(filePath, method) {
7341
- const resolved = path10.resolve(filePath);
7342
- const base = path10.resolve(this.baseDir);
7343
- const rel = path10.relative(base, resolved);
7344
- if (rel === "" || rel === ".." || rel.startsWith(`..${path10.sep}`) || path10.isAbsolute(rel)) {
6874
+ const resolved = path9.resolve(filePath);
6875
+ const base = path9.resolve(this.baseDir);
6876
+ const rel = path9.relative(base, resolved);
6877
+ if (rel === "" || rel === ".." || rel.startsWith(`..${path9.sep}`) || path9.isAbsolute(rel)) {
7345
6878
  throw new Error(`${method}: file path escapes memory dir`);
7346
6879
  }
7347
6880
  return resolved;
@@ -7352,8 +6885,8 @@ var StorageManager3 = class _StorageManager {
7352
6885
  }
7353
6886
  async digestOfflineSyncFile(filePath) {
7354
6887
  const target = this.assertManagedStoragePath(filePath, "storage.digestOfflineSyncFile");
7355
- const st = await stat3(target);
7356
- const relPath = path10.relative(this.baseDir, target).split(path10.sep).join("/");
6888
+ const st = await stat2(target);
6889
+ const relPath = path9.relative(this.baseDir, target).split(path9.sep).join("/");
7357
6890
  const cache = await this.loadOfflineSyncDigestCache();
7358
6891
  const cached = cache.get(relPath);
7359
6892
  if (cached && cached.statBytes === st.size && cached.mtimeMs === st.mtimeMs && cached.ctimeMs === st.ctimeMs && !cached.encrypted) {
@@ -7414,7 +6947,7 @@ var StorageManager3 = class _StorageManager {
7414
6947
  const bytes = typeof record.bytes === "number" ? record.bytes : NaN;
7415
6948
  const sha256 = typeof record.sha256 === "string" ? record.sha256 : "";
7416
6949
  const encrypted = record.encrypted === true;
7417
- if (cachePath.length === 0 || cachePath === ".." || cachePath.startsWith("../") || path10.isAbsolute(cachePath) || !Number.isFinite(statBytes) || !Number.isFinite(mtimeMs) || !Number.isFinite(ctimeMs) || !Number.isFinite(bytes) || !/^[a-f0-9]{64}$/i.test(sha256)) {
6950
+ if (cachePath.length === 0 || cachePath === ".." || cachePath.startsWith("../") || path9.isAbsolute(cachePath) || !Number.isFinite(statBytes) || !Number.isFinite(mtimeMs) || !Number.isFinite(ctimeMs) || !Number.isFinite(bytes) || !/^[a-f0-9]{64}$/i.test(sha256)) {
7418
6951
  continue;
7419
6952
  }
7420
6953
  cache.set(cachePath, { statBytes, mtimeMs, ctimeMs, encrypted, sha256, bytes });
@@ -7456,7 +6989,7 @@ var StorageManager3 = class _StorageManager {
7456
6989
  const cache = this.offlineSyncDigestCache;
7457
6990
  if (!cache) return;
7458
6991
  const entries = [...cache.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([entryPath, entry]) => ({ path: entryPath, ...entry }));
7459
- await mkdir2(path10.dirname(this.offlineSyncDigestCachePath), { recursive: true });
6992
+ await mkdir(path9.dirname(this.offlineSyncDigestCachePath), { recursive: true });
7460
6993
  await writeFile2(this.offlineSyncDigestCachePath, `${JSON.stringify({ version: 1, entries })}
7461
6994
  `, "utf-8");
7462
6995
  }).catch((err) => {
@@ -7475,40 +7008,10 @@ var StorageManager3 = class _StorageManager {
7475
7008
  await handle.close();
7476
7009
  }
7477
7010
  }
7478
- async writeOfflineSyncFile(filePath, content) {
7479
- const target = this.assertManagedStoragePath(filePath, "storage.writeOfflineSyncFile");
7480
- await this.writeStorageSecureFile(target, content);
7481
- await this.invalidateAfterOfflineSyncMutation(target);
7482
- }
7483
7011
  async writeOfflineSyncStagingFile(filePath, content) {
7484
7012
  const target = this.assertManagedStoragePath(filePath, "storage.writeOfflineSyncStagingFile");
7485
7013
  await this.writeStorageSecureFile(target, content);
7486
7014
  }
7487
- async writeOfflineSyncFileChunks(filePath, chunks) {
7488
- const target = this.assertManagedStoragePath(filePath, "storage.writeOfflineSyncFileChunks");
7489
- await this.writeStorageSecureFileChunks(target, chunks);
7490
- await this.invalidateAfterOfflineSyncMutation(target);
7491
- }
7492
- async deleteOfflineSyncFile(filePath) {
7493
- const target = this.assertManagedStoragePath(filePath, "storage.deleteOfflineSyncFile");
7494
- await unlink3(target).catch((error) => {
7495
- if (isErrnoCode(error, "ENOENT")) return;
7496
- throw error;
7497
- });
7498
- await this.invalidateAfterOfflineSyncMutation(target);
7499
- }
7500
- async invalidateAfterOfflineSyncMutation(filePath) {
7501
- this.invalidateAllMemoriesCache();
7502
- this.invalidateKnowledgeIndexCache();
7503
- this.factHashIndexAuthoritative = false;
7504
- if (filePath.includes(`${path10.sep}cold${path10.sep}`)) {
7505
- this.invalidateColdMemoriesCache();
7506
- }
7507
- if (filePath.includes(`${path10.sep}artifacts${path10.sep}`)) {
7508
- this.bumpArtifactWriteVersion();
7509
- }
7510
- this.bumpMemoryStatusVersion();
7511
- }
7512
7015
  createContentHashIndex() {
7513
7016
  return new ContentHashIndex(
7514
7017
  this.stateDir,
@@ -7544,7 +7047,7 @@ var StorageManager3 = class _StorageManager {
7544
7047
  async isEncryptedFileHeader(filePath) {
7545
7048
  let st;
7546
7049
  try {
7547
- st = await stat3(filePath);
7050
+ st = await stat2(filePath);
7548
7051
  } catch (err) {
7549
7052
  if (isErrnoCode(err, "ENOENT")) return false;
7550
7053
  throw err;
@@ -7575,7 +7078,7 @@ var StorageManager3 = class _StorageManager {
7575
7078
  }
7576
7079
  async appendStorageSecureFileUnlocked(filePath, content) {
7577
7080
  const writeKey = this.resolveWriteKey();
7578
- await mkdir2(path10.dirname(filePath), { recursive: true });
7081
+ await mkdir(path9.dirname(filePath), { recursive: true });
7579
7082
  if (writeKey === null) {
7580
7083
  try {
7581
7084
  if (await this.isEncryptedFileHeader(filePath)) {
@@ -7601,13 +7104,13 @@ var StorageManager3 = class _StorageManager {
7601
7104
  this.notifyCatalogWriteForPath(filePath);
7602
7105
  }
7603
7106
  get stateDir() {
7604
- return path10.join(this.baseDir, "state");
7107
+ return path9.join(this.baseDir, "state");
7605
7108
  }
7606
7109
  get offlineSyncDigestCachePath() {
7607
- return path10.join(this.baseDir, ".offline-sync", "digest-cache.v1.json");
7110
+ return path9.join(this.baseDir, ".offline-sync", "digest-cache.v1.json");
7608
7111
  }
7609
7112
  get entitySynthesisQueuePath() {
7610
- return path10.join(this.stateDir, "entity-synthesis-queue.json");
7113
+ return path9.join(this.stateDir, "entity-synthesis-queue.json");
7611
7114
  }
7612
7115
  // ── Tombstone store access (issue #1579) ─────────────────────────────────
7613
7116
  /**
@@ -7617,7 +7120,7 @@ var StorageManager3 = class _StorageManager {
7617
7120
  * helpers are injected into the store).
7618
7121
  */
7619
7122
  get tombstonesPath() {
7620
- return path10.join(this.stateDir, "tombstones.jsonl");
7123
+ return path9.join(this.stateDir, "tombstones.jsonl");
7621
7124
  }
7622
7125
  /**
7623
7126
  * Configure the tombstone invariant for this storage instance. Installed
@@ -7746,6 +7249,28 @@ var StorageManager3 = class _StorageManager {
7746
7249
  });
7747
7250
  return await store.rebuild(retired);
7748
7251
  }
7252
+ markFactHashIndexNotAuthoritative() {
7253
+ this.factHashIndexAuthoritative = false;
7254
+ }
7255
+ tombstoneBlockedCaptureIndexOptions() {
7256
+ return {
7257
+ stateDir: this.stateDir,
7258
+ memoryDir: this.baseDir,
7259
+ secureStoreKeyProvider: () => this._secureStoreKey,
7260
+ secureStoreWriteKeyProvider: () => this.resolveWriteKey(),
7261
+ lockOptions: () => this.factHashIndexLockOptions,
7262
+ parseMemory: (filePath, content) => parseTombstoneBlockedOfflineSyncMemory(
7263
+ filePath,
7264
+ content,
7265
+ this.baseDir,
7266
+ parseFrontmatter,
7267
+ normalizeFrontmatterForPath,
7268
+ toMemoryPathRel
7269
+ ),
7270
+ readAllMemories: () => this.readAllMemories(),
7271
+ readAllColdMemories: () => this.readAllColdMemories()
7272
+ };
7273
+ }
7749
7274
  async getFactHashIndex() {
7750
7275
  if (this.factHashIndex) {
7751
7276
  return this.factHashIndex;
@@ -7807,9 +7332,7 @@ var StorageManager3 = class _StorageManager {
7807
7332
  const baseMs = this.factHashIndexLockOptions.retryBaseMs ?? FACT_HASH_INDEX_REBUILD_RETRY_BASE_MS;
7808
7333
  let published = false;
7809
7334
  for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
7810
- published = await factHashIndex.rebuildUnderLock(
7811
- () => this.rebuildFactHashIndexFromCorpus(factHashIndex)
7812
- );
7335
+ published = await factHashIndex.rebuildUnderLock(() => this.rebuildFactHashIndexFromCorpus(factHashIndex));
7813
7336
  if (published || attempt === maxAttempts - 1) break;
7814
7337
  const wait = Math.min(baseMs * 2 ** attempt, CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS);
7815
7338
  await new Promise((resolve3) => setTimeout(resolve3, wait));
@@ -7835,10 +7358,7 @@ var StorageManager3 = class _StorageManager {
7835
7358
  async rebuildFactHashIndexFromCorpus(factHashIndex) {
7836
7359
  factHashIndex.clear();
7837
7360
  this.factOnlyHashes.clear();
7838
- const existing = [
7839
- ...await this.readAllMemories(),
7840
- ...await this.readAllColdMemories()
7841
- ];
7361
+ const existing = [...await this.readAllMemories(), ...await this.readAllColdMemories()];
7842
7362
  let legacyRecovered = 0;
7843
7363
  for (const memory of existing) {
7844
7364
  if (inferMemoryStatus(memory.frontmatter, memory.path) !== "active") continue;
@@ -7890,55 +7410,55 @@ var StorageManager3 = class _StorageManager {
7890
7410
  return null;
7891
7411
  }
7892
7412
  get questionsDir() {
7893
- return path10.join(this.baseDir, "questions");
7413
+ return path9.join(this.baseDir, "questions");
7894
7414
  }
7895
7415
  get artifactsDir() {
7896
- return path10.join(this.baseDir, "artifacts");
7416
+ return path9.join(this.baseDir, "artifacts");
7897
7417
  }
7898
7418
  get identityDir() {
7899
- return path10.join(this.baseDir, "identity");
7419
+ return path9.join(this.baseDir, "identity");
7900
7420
  }
7901
7421
  get identityAnchorPath() {
7902
- return path10.join(this.identityDir, "identity-anchor.md");
7422
+ return path9.join(this.identityDir, "identity-anchor.md");
7903
7423
  }
7904
7424
  get identityIncidentsDir() {
7905
- return path10.join(this.identityDir, "incidents");
7425
+ return path9.join(this.identityDir, "incidents");
7906
7426
  }
7907
7427
  get identityAuditsWeeklyDir() {
7908
- return path10.join(this.identityDir, "audits", "weekly");
7428
+ return path9.join(this.identityDir, "audits", "weekly");
7909
7429
  }
7910
7430
  get identityAuditsMonthlyDir() {
7911
- return path10.join(this.identityDir, "audits", "monthly");
7431
+ return path9.join(this.identityDir, "audits", "monthly");
7912
7432
  }
7913
7433
  get identityImprovementLoopsPath() {
7914
- return path10.join(this.identityDir, "improvement-loops.md");
7434
+ return path9.join(this.identityDir, "improvement-loops.md");
7915
7435
  }
7916
7436
  get identityReflectionsPath() {
7917
- return path10.join(this.identityDir, "reflections.md");
7437
+ return path9.join(this.identityDir, "reflections.md");
7918
7438
  }
7919
7439
  get profilePath() {
7920
- return path10.join(this.baseDir, "profile.md");
7440
+ return path9.join(this.baseDir, "profile.md");
7921
7441
  }
7922
7442
  get memoryActionsPath() {
7923
- return path10.join(this.stateDir, "memory-actions.jsonl");
7443
+ return path9.join(this.stateDir, "memory-actions.jsonl");
7924
7444
  }
7925
7445
  get memoryLifecycleLedgerPath() {
7926
- return path10.join(this.stateDir, "memory-lifecycle-ledger.jsonl");
7446
+ return path9.join(this.stateDir, "memory-lifecycle-ledger.jsonl");
7927
7447
  }
7928
7448
  get compressionGuidelinesPath() {
7929
- return path10.join(this.stateDir, "compression-guidelines.md");
7449
+ return path9.join(this.stateDir, "compression-guidelines.md");
7930
7450
  }
7931
7451
  get compressionGuidelineDraftPath() {
7932
- return path10.join(this.stateDir, "compression-guidelines.draft.md");
7452
+ return path9.join(this.stateDir, "compression-guidelines.draft.md");
7933
7453
  }
7934
7454
  get compressionGuidelineStatePath() {
7935
- return path10.join(this.stateDir, "compression-guideline-state.json");
7455
+ return path9.join(this.stateDir, "compression-guideline-state.json");
7936
7456
  }
7937
7457
  get compressionGuidelineDraftStatePath() {
7938
- return path10.join(this.stateDir, "compression-guideline-draft-state.json");
7458
+ return path9.join(this.stateDir, "compression-guideline-draft-state.json");
7939
7459
  }
7940
7460
  get behaviorSignalsPath() {
7941
- return path10.join(this.stateDir, "behavior-signals.jsonl");
7461
+ return path9.join(this.stateDir, "behavior-signals.jsonl");
7942
7462
  }
7943
7463
  /**
7944
7464
  * In-memory dedup key set for behavior-signals appends (issue #1909),
@@ -7970,7 +7490,7 @@ var StorageManager3 = class _StorageManager {
7970
7490
  * governance sweeps can treat it uniformly.
7971
7491
  */
7972
7492
  get bufferSurpriseLedgerPath() {
7973
- return path10.join(this.stateDir, "buffer-surprise-ledger.jsonl");
7493
+ return path9.join(this.stateDir, "buffer-surprise-ledger.jsonl");
7974
7494
  }
7975
7495
  /**
7976
7496
  * Entity alias table loaded from THIS store's config/aliases.json.
@@ -8010,7 +7530,7 @@ var StorageManager3 = class _StorageManager {
8010
7530
  this.loadAliasesSync();
8011
7531
  }
8012
7532
  loadAliasesSync() {
8013
- const aliasPath = path10.join(this.baseDir, "config", "aliases.json");
7533
+ const aliasPath = path9.join(this.baseDir, "config", "aliases.json");
8014
7534
  this.userAliases = {};
8015
7535
  try {
8016
7536
  const raw = readFileSync2(aliasPath, "utf-8");
@@ -8045,22 +7565,22 @@ var StorageManager3 = class _StorageManager {
8045
7565
  return completionFingerprint;
8046
7566
  }
8047
7567
  async ensureDirectories() {
8048
- await mkdir2(this.baseDir, { recursive: true });
7568
+ await mkdir(this.baseDir, { recursive: true });
8049
7569
  await validateRoots(this.baseDir, this.entitiesDir, this.stateDir, this.archiveDir);
8050
7570
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8051
- await mkdir2(path10.join(this.factsDir, today), { recursive: true });
8052
- await mkdir2(path10.join(this.proceduresDir, today), { recursive: true });
8053
- await mkdir2(path10.join(this.reasoningTracesDir, today), { recursive: true });
8054
- await mkdir2(this.correctionsDir, { recursive: true });
8055
- await mkdir2(this.entitiesDir, { recursive: true });
8056
- await mkdir2(this.stateDir, { recursive: true });
8057
- await mkdir2(this.questionsDir, { recursive: true });
8058
- await mkdir2(this.artifactsDir, { recursive: true });
8059
- await mkdir2(this.identityDir, { recursive: true });
8060
- await mkdir2(this.identityIncidentsDir, { recursive: true });
8061
- await mkdir2(this.identityAuditsWeeklyDir, { recursive: true });
8062
- await mkdir2(this.identityAuditsMonthlyDir, { recursive: true });
8063
- await mkdir2(path10.join(this.baseDir, "config"), { recursive: true });
7571
+ await mkdir(path9.join(this.factsDir, today), { recursive: true });
7572
+ await mkdir(path9.join(this.proceduresDir, today), { recursive: true });
7573
+ await mkdir(path9.join(this.reasoningTracesDir, today), { recursive: true });
7574
+ await mkdir(this.correctionsDir, { recursive: true });
7575
+ await mkdir(this.entitiesDir, { recursive: true });
7576
+ await mkdir(this.stateDir, { recursive: true });
7577
+ await mkdir(this.questionsDir, { recursive: true });
7578
+ await mkdir(this.artifactsDir, { recursive: true });
7579
+ await mkdir(this.identityDir, { recursive: true });
7580
+ await mkdir(this.identityIncidentsDir, { recursive: true });
7581
+ await mkdir(this.identityAuditsWeeklyDir, { recursive: true });
7582
+ await mkdir(this.identityAuditsMonthlyDir, { recursive: true });
7583
+ await mkdir(path9.join(this.baseDir, "config"), { recursive: true });
8064
7584
  await this.entityCanonicalIdMigration.ensure();
8065
7585
  if (this.hotMemoriesCacheEnabled && this.getMemoryCorpusVersion() === 0) {
8066
7586
  this.bumpMemoryCorpusVersion();
@@ -8081,12 +7601,24 @@ var StorageManager3 = class _StorageManager {
8081
7601
  */
8082
7602
  async resolveCategoryWritePath(category, id, today) {
8083
7603
  if (category === "correction") {
8084
- await mkdir2(this.correctionsDir, { recursive: true });
8085
- return path10.join(this.correctionsDir, `${id}.md`);
8086
- }
8087
- const datedDir = path10.join(getCategoryDir(this.baseDir, category), today);
8088
- await mkdir2(datedDir, { recursive: true });
8089
- return path10.join(datedDir, `${id}.md`);
7604
+ await mkdir(this.correctionsDir, { recursive: true });
7605
+ return path9.join(this.correctionsDir, `${id}.md`);
7606
+ }
7607
+ const datedDir = path9.join(getCategoryDir(this.baseDir, category), today);
7608
+ await mkdir(datedDir, { recursive: true });
7609
+ return path9.join(datedDir, `${id}.md`);
7610
+ }
7611
+ async findExistingTombstoneBlockedMemory(content, category, sourceConnector) {
7612
+ const identity = buildExplicitCaptureDedupKey(content, category, sourceConnector);
7613
+ const memories = [...await this.readAllMemories(), ...await this.readAllColdMemories()];
7614
+ return memories.find((memory) => {
7615
+ if (memory.frontmatter.status !== "pending_review" || !memory.frontmatter.blockedBy) return false;
7616
+ return buildExplicitCaptureDedupKey(
7617
+ memory.content,
7618
+ memory.frontmatter.category,
7619
+ memory.frontmatter.sourceConnector
7620
+ ) === identity;
7621
+ }) ?? null;
8090
7622
  }
8091
7623
  async writeMemory(category, content, options = {}) {
8092
7624
  await this.ensureDirectories();
@@ -8202,8 +7734,29 @@ var StorageManager3 = class _StorageManager {
8202
7734
  ${sanitized.text}
8203
7735
  `;
8204
7736
  const filePath = await this.resolveCategoryWritePath(category, id, today);
8205
- await this.snapshotBeforeWrite(filePath, "write");
8206
- await this.writeStorageSecureFile(filePath, fileContent);
7737
+ const persistFile = async () => {
7738
+ if (tombstoneBlocked) {
7739
+ const duplicate = await this.findExistingTombstoneBlockedMemory(sanitized.text, category, fm.sourceConnector);
7740
+ if (duplicate) return duplicate;
7741
+ }
7742
+ await this.snapshotBeforeWrite(filePath, "write");
7743
+ await this.writeTombstoneBlockedMemory(filePath, fileContent, fm, sanitized.text, async () => {
7744
+ this.invalidateAllMemoriesCache();
7745
+ });
7746
+ return null;
7747
+ };
7748
+ const duplicateBlocked = tombstoneBlocked ? await this.withTombstoneBlockedCaptureWriteLock(
7749
+ persistFile,
7750
+ buildExplicitCaptureDedupKey(sanitized.text, category, fm.sourceConnector)
7751
+ ) : await persistFile();
7752
+ if (duplicateBlocked) {
7753
+ return {
7754
+ id: duplicateBlocked.frontmatter.id,
7755
+ tombstoneBlocked: true,
7756
+ blockedBy: duplicateBlocked.frontmatter.blockedBy,
7757
+ duplicateOf: duplicateBlocked.frontmatter.id
7758
+ };
7759
+ }
8207
7760
  await this.patchHotMemoriesCache({ addedPath: filePath }, "memory-create");
8208
7761
  this.notifyMemoryWrite(filePath);
8209
7762
  await this.appendGeneratedMemoryLifecycleEventFailOpen("storage.writeMemory", {
@@ -8272,10 +7825,7 @@ ${sanitized.text}
8272
7825
  return await this.factContentHashPresentInCorpus(hash);
8273
7826
  }
8274
7827
  async factContentHashPresentInCorpus(targetHash) {
8275
- const existing = [
8276
- ...await this.readAllMemories(),
8277
- ...await this.readAllColdMemories()
8278
- ];
7828
+ const existing = [...await this.readAllMemories(), ...await this.readAllColdMemories()];
8279
7829
  for (const memory of existing) {
8280
7830
  if (memory.frontmatter.category !== "fact") continue;
8281
7831
  if (inferMemoryStatus(memory.frontmatter, memory.path) !== "active") continue;
@@ -8391,8 +7941,8 @@ ${sanitized.text}
8391
7941
  await this.ensureDirectories();
8392
7942
  const now = /* @__PURE__ */ new Date();
8393
7943
  const day = now.toISOString().slice(0, 10);
8394
- const dir = path10.join(this.artifactsDir, day);
8395
- await mkdir2(dir, { recursive: true });
7944
+ const dir = path9.join(this.artifactsDir, day);
7945
+ await mkdir(dir, { recursive: true });
8396
7946
  const id = `artifact-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
8397
7947
  const fm = {
8398
7948
  id,
@@ -8416,7 +7966,7 @@ ${sanitized.text}
8416
7966
  log.warn(`artifact content rejected for ${id}; violations=${sanitized.violations.join(", ")}`);
8417
7967
  return "";
8418
7968
  }
8419
- const filePath = path10.join(dir, `${id}.md`);
7969
+ const filePath = path9.join(dir, `${id}.md`);
8420
7970
  await this.writeStorageSecureFile(filePath, `${serializeFrontmatter(fm)}
8421
7971
 
8422
7972
  ${sanitized.text}
@@ -8687,7 +8237,7 @@ ${sanitized.text}
8687
8237
  * per-process in-memory cache safe across process boundaries.
8688
8238
  */
8689
8239
  invalidateColdMemoriesCache() {
8690
- const coldRoot = path10.join(this.baseDir, "cold");
8240
+ const coldRoot = path9.join(this.baseDir, "cold");
8691
8241
  _StorageManager.coldMemoriesCache.delete(coldRoot);
8692
8242
  this.bumpColdWriteVersion();
8693
8243
  invalidateAllForDir(this.baseDir);
@@ -8789,7 +8339,7 @@ ${sanitized.text}
8789
8339
  return updatedMs >= updatedAfterMs ? filePath : null;
8790
8340
  }
8791
8341
  try {
8792
- const fileStat = await stat3(filePath);
8342
+ const fileStat = await stat2(filePath);
8793
8343
  return fileStat.mtimeMs >= updatedAfterMs ? filePath : null;
8794
8344
  } catch {
8795
8345
  return filePath;
@@ -8802,7 +8352,7 @@ ${sanitized.text}
8802
8352
  const correctionPaths = [];
8803
8353
  const factPaths = [];
8804
8354
  for (const filePath of filePaths) {
8805
- if (filePath === this.correctionsDir || filePath.startsWith(`${this.correctionsDir}${path10.sep}`)) {
8355
+ if (filePath === this.correctionsDir || filePath.startsWith(`${this.correctionsDir}${path9.sep}`)) {
8806
8356
  correctionPaths.push(filePath);
8807
8357
  } else {
8808
8358
  factPaths.push(filePath);
@@ -8865,7 +8415,7 @@ ${sanitized.text}
8865
8415
  try {
8866
8416
  const entries = await readdir5(dir, { withFileTypes: true });
8867
8417
  for (const entry of entries) {
8868
- const fullPath = path10.join(dir, entry.name);
8418
+ const fullPath = path9.join(dir, entry.name);
8869
8419
  if (entry.isDirectory()) {
8870
8420
  await readDir(fullPath);
8871
8421
  } else if (entry.name.endsWith(".md")) {
@@ -8898,7 +8448,7 @@ ${sanitized.text}
8898
8448
  return this.memoryReadStore.readMemoryByPath(filePath);
8899
8449
  }
8900
8450
  resolveTierRootDir(tier) {
8901
- return tier === "cold" ? path10.join(this.baseDir, "cold") : this.baseDir;
8451
+ return tier === "cold" ? path9.join(this.baseDir, "cold") : this.baseDir;
8902
8452
  }
8903
8453
  resolveMemoryDateDir(memory) {
8904
8454
  const preferred = memory.frontmatter.created || memory.frontmatter.updated;
@@ -8913,13 +8463,13 @@ ${sanitized.text}
8913
8463
  buildTierMemoryPath(memory, tier) {
8914
8464
  const root = this.resolveTierRootDir(tier);
8915
8465
  if (this.isArtifactMemory(memory)) {
8916
- return path10.join(root, "artifacts", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
8466
+ return path9.join(root, "artifacts", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
8917
8467
  }
8918
8468
  if (memory.frontmatter.category === "correction") {
8919
- return path10.join(root, "corrections", `${memory.frontmatter.id}.md`);
8469
+ return path9.join(root, "corrections", `${memory.frontmatter.id}.md`);
8920
8470
  }
8921
8471
  const dir = categoryDirName(memory.frontmatter.category);
8922
- return path10.join(root, dir, this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
8472
+ return path9.join(root, dir, this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
8923
8473
  }
8924
8474
  async writeMemoryFileAtomic(targetPath, memory) {
8925
8475
  const fileContent = `${serializeFrontmatter(memory.frontmatter)}
@@ -8932,8 +8482,8 @@ ${memory.content}
8932
8482
  }
8933
8483
  async moveMemoryToPath(memory, targetPath) {
8934
8484
  await this.writeMemoryFileAtomic(targetPath, memory);
8935
- const sourcePath = path10.resolve(memory.path);
8936
- const destPath = path10.resolve(targetPath);
8485
+ const sourcePath = path9.resolve(memory.path);
8486
+ const destPath = path9.resolve(targetPath);
8937
8487
  if (sourcePath !== destPath) {
8938
8488
  try {
8939
8489
  await unlink3(memory.path);
@@ -8949,8 +8499,8 @@ ${memory.content}
8949
8499
  }
8950
8500
  async migrateMemoryToTier(memory, targetTier) {
8951
8501
  const targetPath = this.buildTierMemoryPath(memory, targetTier);
8952
- const sourcePath = path10.resolve(memory.path);
8953
- const destPath = path10.resolve(targetPath);
8502
+ const sourcePath = path9.resolve(memory.path);
8503
+ const destPath = path9.resolve(targetPath);
8954
8504
  if (sourcePath === destPath) {
8955
8505
  return { changed: false, targetPath };
8956
8506
  }
@@ -8977,7 +8527,7 @@ ${memory.content}
8977
8527
  return { changed: true, targetPath };
8978
8528
  }
8979
8529
  get archiveDir() {
8980
- return path10.join(this.baseDir, "archive");
8530
+ return path9.join(this.baseDir, "archive");
8981
8531
  }
8982
8532
  /**
8983
8533
  * Archive a memory by moving it from facts/ to archive/YYYY-MM-DD/.
@@ -8985,48 +8535,52 @@ ${memory.content}
8985
8535
  * Returns the new file path on success, null on failure.
8986
8536
  */
8987
8537
  async archiveMemory(memory, lifecycle) {
8988
- try {
8989
- const now = lifecycle?.at ?? /* @__PURE__ */ new Date();
8990
- const today = now.toISOString().slice(0, 10);
8991
- const destDir = path10.join(this.archiveDir, today);
8992
- await mkdir2(destDir, { recursive: true });
8993
- const updatedFm = {
8994
- ...memory.frontmatter,
8995
- status: "archived",
8996
- archivedAt: now.toISOString(),
8997
- updated: now.toISOString()
8998
- };
8999
- const fileContent = `${serializeFrontmatter(updatedFm)}
8538
+ const archiveCurrent = async (current, markDurable) => {
8539
+ try {
8540
+ const now = lifecycle?.at ?? /* @__PURE__ */ new Date();
8541
+ const today = now.toISOString().slice(0, 10);
8542
+ const destDir = path9.join(this.archiveDir, today);
8543
+ await mkdir(destDir, { recursive: true });
8544
+ const updatedFm = {
8545
+ ...current.frontmatter,
8546
+ status: "archived",
8547
+ archivedAt: now.toISOString(),
8548
+ updated: now.toISOString()
8549
+ };
8550
+ const fileContent = `${serializeFrontmatter(updatedFm)}
9000
8551
 
9001
- ${memory.content}
8552
+ ${current.content}
9002
8553
  `;
9003
- const destPath = path10.join(destDir, path10.basename(memory.path));
9004
- await this.writeStorageSecureFile(destPath, fileContent);
9005
- await unlink3(memory.path);
9006
- markProjectedMemoryPathInvalid(this.baseDir, memory.frontmatter.id);
9007
- this.invalidateAllMemoriesCache();
9008
- await this.appendGeneratedMemoryLifecycleEventFailOpen(
9009
- "storage.archiveMemory",
9010
- {
9011
- memoryId: memory.frontmatter.id,
9012
- eventType: "archived",
9013
- timestamp: updatedFm.archivedAt ?? updatedFm.updated,
9014
- actor: lifecycle?.actor ?? "storage.archiveMemory",
9015
- reasonCode: lifecycle?.reasonCode,
9016
- before: this.summarizeLifecycleState(memory.frontmatter, memory.path),
9017
- after: this.summarizeLifecycleState(updatedFm, destPath),
9018
- relatedMemoryIds: lifecycle?.relatedMemoryIds,
9019
- correlationId: lifecycle?.correlationId
9020
- },
9021
- lifecycle?.ruleVersion
9022
- );
9023
- this.bumpMemoryStatusVersion();
9024
- log.debug(`archived memory ${memory.frontmatter.id} \u2192 ${destPath}`);
9025
- return destPath;
9026
- } catch (err) {
9027
- log.warn(`failed to archive memory ${memory.frontmatter.id}: ${err}`);
9028
- return null;
9029
- }
8554
+ const destPath = path9.join(destDir, path9.basename(current.path));
8555
+ await this.writeStorageSecureFile(destPath, fileContent);
8556
+ await unlink3(current.path);
8557
+ markDurable();
8558
+ markProjectedMemoryPathInvalid(this.baseDir, current.frontmatter.id);
8559
+ this.invalidateAllMemoriesCache();
8560
+ await this.appendGeneratedMemoryLifecycleEventFailOpen(
8561
+ "storage.archiveMemory",
8562
+ {
8563
+ memoryId: current.frontmatter.id,
8564
+ eventType: "archived",
8565
+ timestamp: updatedFm.archivedAt ?? updatedFm.updated,
8566
+ actor: lifecycle?.actor ?? "storage.archiveMemory",
8567
+ reasonCode: lifecycle?.reasonCode,
8568
+ before: this.summarizeLifecycleState(current.frontmatter, current.path),
8569
+ after: this.summarizeLifecycleState(updatedFm, destPath),
8570
+ relatedMemoryIds: lifecycle?.relatedMemoryIds,
8571
+ correlationId: lifecycle?.correlationId
8572
+ },
8573
+ lifecycle?.ruleVersion
8574
+ );
8575
+ this.bumpMemoryStatusVersion();
8576
+ log.debug(`archived memory ${current.frontmatter.id} \u2192 ${destPath}`);
8577
+ return destPath;
8578
+ } catch (err) {
8579
+ log.warn(`failed to archive memory ${current.frontmatter.id}: ${err}`);
8580
+ return null;
8581
+ }
8582
+ };
8583
+ return await this.runTombstoneBlockedArchive(memory, archiveCurrent);
9030
8584
  }
9031
8585
  async readEntities() {
9032
8586
  try {
@@ -9079,18 +8633,21 @@ ${memory.content}
9079
8633
  }
9080
8634
  async invalidateMemory(id) {
9081
8635
  const memories = await this.readAllMemories();
9082
- const memory = memories.find((m) => m.frontmatter.id === id);
8636
+ const memory = memories.find((candidate) => candidate.frontmatter.id === id);
9083
8637
  if (!memory) return false;
9084
- try {
9085
- await unlink3(memory.path);
9086
- markProjectedMemoryPathInvalid(this.baseDir, id);
9087
- this.invalidateAllMemoriesCache();
9088
- this.bumpMemoryStatusVersion();
9089
- log.debug(`invalidated memory ${id}`);
9090
- return true;
9091
- } catch {
9092
- return false;
9093
- }
8638
+ return await this.runTombstoneBlockedInvalidation(
8639
+ memory,
8640
+ async (current, rebuildMarker, markDurable) => {
8641
+ await unlink3(current.path);
8642
+ markDurable();
8643
+ markProjectedMemoryPathInvalid(this.baseDir, id);
8644
+ this.invalidateAllMemoriesCache();
8645
+ await this.rebuildTombstoneBlockedCaptureAfterInvalidation(rebuildMarker);
8646
+ this.bumpMemoryStatusVersion();
8647
+ log.debug(`invalidated memory ${id}`);
8648
+ return true;
8649
+ }
8650
+ );
9094
8651
  }
9095
8652
  async updateMemory(id, newContent, options) {
9096
8653
  const memories = await this.readAllMemories();
@@ -9114,7 +8671,9 @@ ${memory.content}
9114
8671
 
9115
8672
  ${sanitized.text}
9116
8673
  `;
9117
- await this.writeStorageSecureFile(memory.path, fileContent);
8674
+ await this.writeTombstoneBlockedUpdate(memory, fileContent, updated, sanitized.text, async () => {
8675
+ this.invalidateAllMemoriesCache();
8676
+ });
9118
8677
  await this.patchHotMemoriesCache({ addedPath: memory.path });
9119
8678
  await this.appendGeneratedMemoryLifecycleEventFailOpen("storage.updateMemory", {
9120
8679
  memoryId: id,
@@ -9146,9 +8705,14 @@ ${sanitized.text}
9146
8705
 
9147
8706
  ${memory.content}
9148
8707
  `;
9149
- await this.writeStorageSecureFile(memory.path, fileContent);
8708
+ await this.writeTombstoneBlockedFrontmatter(memory, fileContent, updated, async () => {
8709
+ this.invalidateAllMemoriesCache();
8710
+ if (memory.path.includes(`${path9.sep}cold${path9.sep}`)) {
8711
+ this.invalidateColdMemoriesCache();
8712
+ }
8713
+ });
9150
8714
  await this.patchHotMemoriesCache({ addedPath: memory.path });
9151
- if (memory.path.includes(`${path10.sep}cold${path10.sep}`)) {
8715
+ if (memory.path.includes(`${path9.sep}cold${path9.sep}`)) {
9152
8716
  this.invalidateColdMemoriesCache();
9153
8717
  }
9154
8718
  try {
@@ -9201,15 +8765,14 @@ ${memory.content}
9201
8765
  for (const m of memories) {
9202
8766
  if (!m.frontmatter.expiresAt) continue;
9203
8767
  const expiresAt = new Date(m.frontmatter.expiresAt).getTime();
9204
- if (expiresAt < now) {
9205
- try {
9206
- await unlink3(m.path);
9207
- markProjectedMemoryPathInvalid(this.baseDir, m.frontmatter.id);
9208
- this.bumpMemoryCorpusVersion();
9209
- deleted.push(m);
9210
- log.debug(`cleaned expired memory ${m.frontmatter.id} (TTL expired)`);
9211
- } catch {
9212
- }
8768
+ if (expiresAt >= now) continue;
8769
+ const removed = await this.deleteMemoryForMaintenance(m, (current) => {
8770
+ const currentExpiresAt = current.frontmatter.expiresAt ? new Date(current.frontmatter.expiresAt).getTime() : Number.NaN;
8771
+ return Number.isFinite(currentExpiresAt) && currentExpiresAt < now;
8772
+ });
8773
+ if (removed) {
8774
+ deleted.push(removed);
8775
+ log.debug(`cleaned expired memory ${removed.frontmatter.id} (TTL expired)`);
9213
8776
  }
9214
8777
  }
9215
8778
  if (deleted.length > 0) {
@@ -9219,7 +8782,7 @@ ${memory.content}
9219
8782
  return deleted;
9220
8783
  }
9221
8784
  async loadBuffer() {
9222
- const bufferPath = path10.join(this.stateDir, "buffer.json");
8785
+ const bufferPath = path9.join(this.stateDir, "buffer.json");
9223
8786
  try {
9224
8787
  const raw = await this.readStorageSecureFile(bufferPath);
9225
8788
  return JSON.parse(raw);
@@ -9231,11 +8794,11 @@ ${memory.content}
9231
8794
  }
9232
8795
  async saveBuffer(state) {
9233
8796
  await this.ensureDirectories();
9234
- const bufferPath = path10.join(this.stateDir, "buffer.json");
8797
+ const bufferPath = path9.join(this.stateDir, "buffer.json");
9235
8798
  await this.writeStorageSecureFile(bufferPath, JSON.stringify(state, null, 2));
9236
8799
  }
9237
8800
  async loadMeta() {
9238
- const metaPath = path10.join(this.stateDir, "meta.json");
8801
+ const metaPath = path9.join(this.stateDir, "meta.json");
9239
8802
  try {
9240
8803
  const raw = await this.readStorageSecureFile(metaPath);
9241
8804
  const parsed = JSON.parse(raw);
@@ -9268,7 +8831,7 @@ ${memory.content}
9268
8831
  }
9269
8832
  async saveMeta(state) {
9270
8833
  await this.ensureDirectories();
9271
- const metaPath = path10.join(this.stateDir, "meta.json");
8834
+ const metaPath = path9.join(this.stateDir, "meta.json");
9272
8835
  await this.writeStorageSecureFile(metaPath, JSON.stringify(state, null, 2));
9273
8836
  }
9274
8837
  async appendMemoryActionEvents(events) {
@@ -9323,10 +8886,7 @@ ${memory.content}
9323
8886
  * The offline CLI uses this path-aware variant for per-namespace ledgers so
9324
8887
  * secure-store encryption and path-bound authentication remain consistent. */
9325
8888
  async drainPendingMemoryLifecycleEventsForSyncAt(ledgerPath) {
9326
- const target = this.assertManagedStoragePath(
9327
- ledgerPath,
9328
- "storage.drainPendingMemoryLifecycleEventsForSyncAt"
9329
- );
8889
+ const target = this.assertManagedStoragePath(ledgerPath, "storage.drainPendingMemoryLifecycleEventsForSyncAt");
9330
8890
  return drainPendingLifecycleLedgerForSync(
9331
8891
  target,
9332
8892
  {
@@ -9335,7 +8895,7 @@ ${memory.content}
9335
8895
  },
9336
8896
  (payload) => this.appendStorageSecureFile(target, payload),
9337
8897
  async () => {
9338
- await mkdir2(path10.dirname(target), { recursive: true });
8898
+ await mkdir(path9.dirname(target), { recursive: true });
9339
8899
  }
9340
8900
  );
9341
8901
  }
@@ -9367,7 +8927,7 @@ ${memory.content}
9367
8927
  let existingKeys;
9368
8928
  let identity = null;
9369
8929
  try {
9370
- const st = await stat3(this.behaviorSignalsPath);
8930
+ const st = await stat2(this.behaviorSignalsPath);
9371
8931
  identity = { size: st.size, mtimeMs: st.mtimeMs };
9372
8932
  if (this.behaviorSignalsKeyCache && this.behaviorSignalsKeyCache.identity.size === identity.size && this.behaviorSignalsKeyCache.identity.mtimeMs === identity.mtimeMs) {
9373
8933
  existingKeys = this.behaviorSignalsKeyCache.keys;
@@ -9415,7 +8975,7 @@ ${memory.content}
9415
8975
  await this.appendStorageSecureFile(this.behaviorSignalsPath, payload);
9416
8976
  for (const key of pending) existingKeys.add(key);
9417
8977
  try {
9418
- const st = await stat3(this.behaviorSignalsPath);
8978
+ const st = await stat2(this.behaviorSignalsPath);
9419
8979
  const expectedSize = (identity?.size ?? 0) + Buffer.byteLength(payload, "utf-8");
9420
8980
  if (st.size === expectedSize) {
9421
8981
  this.behaviorSignalsKeyCache = {
@@ -9433,7 +8993,7 @@ ${memory.content}
9433
8993
  async appendReextractJobs(events) {
9434
8994
  if (events.length === 0) return 0;
9435
8995
  await this.ensureDirectories();
9436
- const filePath = path10.join(this.stateDir, "reextract-jobs.jsonl");
8996
+ const filePath = path9.join(this.stateDir, "reextract-jobs.jsonl");
9437
8997
  const lines = events.map((event) => JSON.stringify(event)).join("\n") + "\n";
9438
8998
  try {
9439
8999
  await this.appendStorageSecureFile(filePath, lines);
@@ -9446,7 +9006,7 @@ ${memory.content}
9446
9006
  }
9447
9007
  async readReextractJobs(limit = 200) {
9448
9008
  const safeLimit = Number.isFinite(limit) ? Math.max(1, Math.min(1e3, Math.floor(limit))) : 200;
9449
- const filePath = path10.join(this.stateDir, "reextract-jobs.jsonl");
9009
+ const filePath = path9.join(this.stateDir, "reextract-jobs.jsonl");
9450
9010
  try {
9451
9011
  const raw = await this.readStorageSecureFile(filePath);
9452
9012
  const lines = raw.split("\n").filter((line) => line.trim().length > 0);
@@ -9526,10 +9086,7 @@ ${memory.content}
9526
9086
  }
9527
9087
  async readAllMemoryLifecycleEventsForCompaction() {
9528
9088
  if (!await probeEncryptedRegularFileHeader(this.memoryLifecycleLedgerPath)) {
9529
- return readAllLifecycleEventsFromLedger(
9530
- this.memoryLifecycleLedgerPath,
9531
- (p) => this.readStorageSecureFile(p)
9532
- );
9089
+ return readAllLifecycleEventsFromLedger(this.memoryLifecycleLedgerPath, (p) => this.readStorageSecureFile(p));
9533
9090
  }
9534
9091
  return readAllLifecycleEventsFromLedgerBuffer(
9535
9092
  this.memoryLifecycleLedgerPath,
@@ -9660,7 +9217,7 @@ ${memory.content}
9660
9217
  return `${prefix}-${ts}-${rand}`;
9661
9218
  }
9662
9219
  async writeQuestion(question, context, priority) {
9663
- await mkdir2(this.questionsDir, { recursive: true });
9220
+ await mkdir(this.questionsDir, { recursive: true });
9664
9221
  const id = this.generateId("q");
9665
9222
  const frontmatter = {
9666
9223
  id,
@@ -9676,7 +9233,7 @@ ${question}
9676
9233
 
9677
9234
  **Context:** ${context}
9678
9235
  `;
9679
- const filePath = path10.join(this.questionsDir, `${id}.md`);
9236
+ const filePath = path9.join(this.questionsDir, `${id}.md`);
9680
9237
  await this.writeStorageSecureFile(filePath, content);
9681
9238
  log.debug(`wrote question ${id} to ${filePath}`);
9682
9239
  this.invalidateQuestionsCache();
@@ -9694,7 +9251,7 @@ ${question}
9694
9251
  if (!match) return null;
9695
9252
  const frontmatterStr = match[1];
9696
9253
  const body = match[2].trim();
9697
- const id = this.extractFrontmatterValue(frontmatterStr, "id") ?? path10.basename(filePath, ".md");
9254
+ const id = this.extractFrontmatterValue(frontmatterStr, "id") ?? path9.basename(filePath, ".md");
9698
9255
  const created = this.extractFrontmatterValue(frontmatterStr, "created") ?? "";
9699
9256
  const priority = parseFloat(this.extractFrontmatterValue(frontmatterStr, "priority") ?? "0.5");
9700
9257
  const resolved = this.extractFrontmatterValue(frontmatterStr, "resolved") === "true";
@@ -9750,11 +9307,11 @@ ${question}
9750
9307
  } catch {
9751
9308
  }
9752
9309
  const hygiene = opts?.hygiene;
9753
- const rotateEnabled = hygiene?.enabled === true && hygiene.rotateEnabled === true && Array.isArray(hygiene.rotatePaths) && hygiene.rotatePaths.includes(path10.basename(identityPath));
9310
+ const rotateEnabled = hygiene?.enabled === true && hygiene.rotateEnabled === true && Array.isArray(hygiene.rotatePaths) && hygiene.rotatePaths.includes(path9.basename(identityPath));
9754
9311
  if (rotateEnabled) {
9755
9312
  const maxBytes = hygiene.rotateMaxBytes;
9756
9313
  if (existing.length > maxBytes) {
9757
- const archiveDir = path10.join(workspaceDir, hygiene.archiveDir);
9314
+ const archiveDir = path9.join(workspaceDir, hygiene.archiveDir);
9758
9315
  const { newContent } = await rotateMarkdownFileToArchive({
9759
9316
  filePath: identityPath,
9760
9317
  archiveDir,
@@ -9806,7 +9363,7 @@ ${reflection}
9806
9363
  }
9807
9364
  }
9808
9365
  async writeIdentityReflections(content) {
9809
- await mkdir2(this.identityDir, { recursive: true });
9366
+ await mkdir(this.identityDir, { recursive: true });
9810
9367
  await this.writeStorageSecureFile(this.identityReflectionsPath, content);
9811
9368
  }
9812
9369
  async appendIdentityReflection(reflection) {
@@ -9838,7 +9395,7 @@ ${reflection}
9838
9395
 
9839
9396
  ${reflection}
9840
9397
  `;
9841
- await mkdir2(this.identityDir, { recursive: true });
9398
+ await mkdir(this.identityDir, { recursive: true });
9842
9399
  await this.writeStorageSecureFile(this.identityReflectionsPath, `${existing.trimEnd()}${section}`);
9843
9400
  log.debug(`appended namespace-local reflection to ${this.identityReflectionsPath}`);
9844
9401
  }
@@ -9850,7 +9407,7 @@ ${reflection}
9850
9407
  * Deduplicates by target+label.
9851
9408
  */
9852
9409
  async addEntityRelationship(name, rel) {
9853
- const filePath = path10.join(this.entitiesDir, `${name}.md`);
9410
+ const filePath = path9.join(this.entitiesDir, `${name}.md`);
9854
9411
  let entity;
9855
9412
  try {
9856
9413
  const content = await this.readStorageSecureFile(filePath);
@@ -9873,7 +9430,7 @@ ${reflection}
9873
9430
  * Prepends to the beginning, prunes oldest entries beyond maxEntries.
9874
9431
  */
9875
9432
  async addEntityActivity(name, entry, maxEntries) {
9876
- const filePath = path10.join(this.entitiesDir, `${name}.md`);
9433
+ const filePath = path9.join(this.entitiesDir, `${name}.md`);
9877
9434
  let entity;
9878
9435
  try {
9879
9436
  const content = await this.readStorageSecureFile(filePath);
@@ -9893,7 +9450,7 @@ ${reflection}
9893
9450
  this.invalidateKnowledgeIndexCache();
9894
9451
  }
9895
9452
  async addEntityAlias(name, alias) {
9896
- const filePath = path10.join(this.entitiesDir, `${name}.md`);
9453
+ const filePath = path9.join(this.entitiesDir, `${name}.md`);
9897
9454
  let entity;
9898
9455
  try {
9899
9456
  const content = await this.readStorageSecureFile(filePath);
@@ -9921,7 +9478,7 @@ ${reflection}
9921
9478
  const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
9922
9479
  let synthesisTimelineCount;
9923
9480
  try {
9924
- const filePath = path10.join(this.entitiesDir, `${name}.md`);
9481
+ const filePath = path9.join(this.entitiesDir, `${name}.md`);
9925
9482
  const content = await this.readStorageSecureFile(filePath);
9926
9483
  synthesisTimelineCount = parseEntityFile(content, this.entitySchemas).timeline.length;
9927
9484
  } catch (err) {
@@ -9963,7 +9520,7 @@ ${reflection}
9963
9520
  const rightTs = latestEntityTimelineTimestamp(right.entity) ?? "";
9964
9521
  return compareEntityTimestamps(rightTs, leftTs);
9965
9522
  }).map(({ entityName }) => entityName);
9966
- await mkdir2(this.stateDir, { recursive: true });
9523
+ await mkdir(this.stateDir, { recursive: true });
9967
9524
  await this.writeStorageSecureFile(
9968
9525
  this.entitySynthesisQueuePath,
9969
9526
  JSON.stringify(
@@ -9983,7 +9540,7 @@ ${reflection}
9983
9540
  if (queue.length === 0) return;
9984
9541
  const removals = new Set(entityNames);
9985
9542
  const nextQueue = queue.filter((name) => !removals.has(name));
9986
- await mkdir2(this.stateDir, { recursive: true });
9543
+ await mkdir(this.stateDir, { recursive: true });
9987
9544
  await this.writeStorageSecureFile(
9988
9545
  this.entitySynthesisQueuePath,
9989
9546
  JSON.stringify(
@@ -10004,7 +9561,7 @@ ${reflection}
10004
9561
  if (!raw) continue;
10005
9562
  const serialized = serializeEntityFile(parseEntityFile(raw, this.entitySchemas), this.entitySchemas);
10006
9563
  if (raw.trimEnd() === serialized.trimEnd()) continue;
10007
- await this.writeStorageSecureFile(path10.join(this.entitiesDir, `${entityName}.md`), serialized);
9564
+ await this.writeStorageSecureFile(path9.join(this.entitiesDir, `${entityName}.md`), serialized);
10008
9565
  migrated += 1;
10009
9566
  }
10010
9567
  if (migrated > 0) {
@@ -10070,15 +9627,18 @@ ${reflection}
10070
9627
  const isResolved = m.frontmatter.tags.some((t) => t === "fulfilled" || t === "expired");
10071
9628
  if (!isResolved) continue;
10072
9629
  const updatedAt = new Date(m.frontmatter.updated).getTime();
10073
- if (updatedAt < cutoff) {
10074
- try {
10075
- await unlink3(m.path);
10076
- markProjectedMemoryPathInvalid(this.baseDir, m.frontmatter.id);
10077
- this.bumpMemoryCorpusVersion();
10078
- deleted.push(m);
10079
- log.debug(`cleaned expired commitment ${m.frontmatter.id}`);
10080
- } catch {
9630
+ if (updatedAt >= cutoff) continue;
9631
+ try {
9632
+ const removed = await this.deleteMemoryForMaintenance(m, (current) => {
9633
+ const currentResolved = current.frontmatter.tags.some((tag) => tag === "fulfilled" || tag === "expired");
9634
+ const currentUpdatedAt = new Date(current.frontmatter.updated).getTime();
9635
+ return currentResolved && currentUpdatedAt < cutoff;
9636
+ });
9637
+ if (removed) {
9638
+ deleted.push(removed);
9639
+ log.debug(`cleaned expired commitment ${removed.frontmatter.id}`);
10081
9640
  }
9641
+ } catch {
10082
9642
  }
10083
9643
  }
10084
9644
  if (deleted.length > 0) {
@@ -10097,14 +9657,14 @@ ${reflection}
10097
9657
  if (entries.length === 0) return 0;
10098
9658
  const memories = await this.readAllMemories();
10099
9659
  const memoryMap = new Map(memories.map((m) => [m.frontmatter.id, m]));
10100
- const memoryPathMap = new Map(memories.map((m) => [path10.resolve(m.path), m]));
9660
+ const memoryPathMap = new Map(memories.map((m) => [path9.resolve(m.path), m]));
10101
9661
  let updated = 0;
10102
9662
  const prevVersion = this.getMemoryCorpusVersion();
10103
9663
  const keyId = this.hotCacheKeyId();
10104
9664
  const warm = this.hotMemoriesCacheEnabled && getCachedMemories(this.baseDir, prevVersion, keyId, this.hotCacheTtlMs()) !== null;
10105
9665
  const appliedPatches = /* @__PURE__ */ new Map();
10106
9666
  for (const entry of entries) {
10107
- const memory = entry.memoryPath ? memoryPathMap.get(path10.resolve(entry.memoryPath)) : memoryMap.get(entry.memoryId);
9667
+ const memory = entry.memoryPath ? memoryPathMap.get(path9.resolve(entry.memoryPath)) : memoryMap.get(entry.memoryId);
10108
9668
  if (!memory) continue;
10109
9669
  const newFm = {
10110
9670
  ...memory.frontmatter,
@@ -10120,7 +9680,7 @@ ${memory.content}
10120
9680
  if (warm) {
10121
9681
  updateCacheOnWrite(this.baseDir, { ...memory, frontmatter: newFm }, keyId);
10122
9682
  }
10123
- appliedPatches.set(path10.resolve(memory.path), {
9683
+ appliedPatches.set(path9.resolve(memory.path), {
10124
9684
  accessCount: entry.newCount,
10125
9685
  lastAccessed: entry.lastAccessed
10126
9686
  });
@@ -10136,8 +9696,11 @@ ${memory.content}
10136
9696
  const cur = getCachedMemories(this.baseDir, prevVersion, keyId);
10137
9697
  if (cur) {
10138
9698
  const reapplied = cur.map((m) => {
10139
- const patch = appliedPatches.get(path10.resolve(m.path));
10140
- return patch ? { ...m, frontmatter: { ...m.frontmatter, accessCount: patch.accessCount, lastAccessed: patch.lastAccessed } } : m;
9699
+ const patch = appliedPatches.get(path9.resolve(m.path));
9700
+ return patch ? {
9701
+ ...m,
9702
+ frontmatter: { ...m.frontmatter, accessCount: patch.accessCount, lastAccessed: patch.lastAccessed }
9703
+ } : m;
10141
9704
  });
10142
9705
  setCachedMemories(this.baseDir, reapplied, produced, keyId, this.hotCacheTtlMs());
10143
9706
  }
@@ -10168,7 +9731,7 @@ ${memory.content}
10168
9731
  const pathsById = /* @__PURE__ */ new Map();
10169
9732
  const filePathsById = /* @__PURE__ */ new Map();
10170
9733
  for (const filePath of filePaths) {
10171
- const memoryId = path10.basename(filePath, ".md");
9734
+ const memoryId = path9.basename(filePath, ".md");
10172
9735
  if (!wantedIds.has(memoryId)) continue;
10173
9736
  const paths = filePathsById.get(memoryId) ?? [];
10174
9737
  paths.push(filePath);
@@ -10179,12 +9742,8 @@ ${memory.content}
10179
9742
  const preferred = preferredPaths.get(id) ?? [];
10180
9743
  const preferredMatches = [];
10181
9744
  for (const preferredPath of preferred) {
10182
- const directCandidates = new Set(
10183
- qmdResultPathCandidates(this.baseDir, preferredPath)
10184
- );
10185
- const directMatch = existingPaths.find(
10186
- (filePath) => directCandidates.has(path10.resolve(filePath))
10187
- );
9745
+ const directCandidates = new Set(qmdResultPathCandidates(this.baseDir, preferredPath));
9746
+ const directMatch = existingPaths.find((filePath) => directCandidates.has(path9.resolve(filePath)));
10188
9747
  if (directMatch) {
10189
9748
  preferredMatches.push(directMatch);
10190
9749
  continue;
@@ -10196,7 +9755,7 @@ ${memory.content}
10196
9755
  candidates.add(candidate);
10197
9756
  }
10198
9757
  }
10199
- const match = existingPaths.find((filePath) => candidates.has(path10.resolve(filePath)));
9758
+ const match = existingPaths.find((filePath) => candidates.has(path9.resolve(filePath)));
10200
9759
  if (match) preferredMatches.push(match);
10201
9760
  }
10202
9761
  if (preferredMatches.length > 0) {
@@ -10329,10 +9888,17 @@ ${memory.content}
10329
9888
  ${sanitized.text}
10330
9889
  `;
10331
9890
  const filePath = await this.resolveCategoryWritePath(category, id, today);
10332
- await this.writeStorageSecureFile(filePath, fileContent);
10333
- await this.patchHotMemoriesCache({ addedPath: filePath }, "memory-create");
10334
- log.debug(`wrote chunk ${id} (${chunkIndex + 1}/${chunkTotal}) to ${filePath}`);
10335
- return id;
9891
+ return await this.writeTombstoneBlockedChunk(
9892
+ filePath,
9893
+ fileContent,
9894
+ fm,
9895
+ sanitized.text,
9896
+ () => this.findExistingTombstoneBlockedMemory(sanitized.text, category, fm.sourceConnector),
9897
+ async () => {
9898
+ await this.patchHotMemoriesCache({ addedPath: filePath }, "memory-create");
9899
+ log.debug(`wrote chunk ${id} (${chunkIndex + 1}/${chunkTotal}) to ${filePath}`);
9900
+ }
9901
+ );
10336
9902
  }
10337
9903
  /**
10338
9904
  * Get all chunks for a given parent memory ID.
@@ -10402,7 +9968,12 @@ ${oldMemory.content}
10402
9968
  const auditBody = `Superseded: ${oldMemory.content}
10403
9969
 
10404
9970
  Reason: ${reason}`;
10405
- const auditInput = { content: auditBody, category: "correction", confidence: 1, tags: ["supersession", "auto-resolved"] };
9971
+ const auditInput = {
9972
+ content: auditBody,
9973
+ category: "correction",
9974
+ confidence: 1,
9975
+ tags: ["supersession", "auto-resolved"]
9976
+ };
10406
9977
  const auditEnvelope = composeMemoryEnvelope(auditInput, { source: "contradiction-detection" });
10407
9978
  await this.writeSealedMemory(auditEnvelope, { lineage: [oldMemoryId, newMemoryId] });
10408
9979
  return true;
@@ -10415,14 +9986,14 @@ Reason: ${reason}`;
10415
9986
  // Memory Summarization (Phase 4A)
10416
9987
  // ---------------------------------------------------------------------------
10417
9988
  get summariesDir() {
10418
- return path10.join(this.baseDir, "summaries");
9989
+ return path9.join(this.baseDir, "summaries");
10419
9990
  }
10420
9991
  /**
10421
9992
  * Write a memory summary.
10422
9993
  */
10423
9994
  async writeSummary(summary) {
10424
- await mkdir2(this.summariesDir, { recursive: true });
10425
- const filePath = path10.join(this.summariesDir, `${summary.id}.json`);
9995
+ await mkdir(this.summariesDir, { recursive: true });
9996
+ const filePath = path9.join(this.summariesDir, `${summary.id}.json`);
10426
9997
  await this.writeStorageSecureFile(filePath, JSON.stringify(summary, null, 2));
10427
9998
  log.debug(`wrote summary ${summary.id}`);
10428
9999
  }
@@ -10435,7 +10006,7 @@ Reason: ${reason}`;
10435
10006
  const summaries = [];
10436
10007
  for (const file of files) {
10437
10008
  if (!file.endsWith(".json")) continue;
10438
- const filePath = path10.join(this.summariesDir, file);
10009
+ const filePath = path9.join(this.summariesDir, file);
10439
10010
  const raw = await this.readStorageSecureFile(filePath);
10440
10011
  summaries.push(JSON.parse(raw));
10441
10012
  }
@@ -10497,8 +10068,8 @@ ${memory.content}
10497
10068
  * Save topic scores to meta.json.
10498
10069
  */
10499
10070
  async saveTopics(topics) {
10500
- const metaPath = path10.join(this.stateDir, "topics.json");
10501
- await mkdir2(this.stateDir, { recursive: true });
10071
+ const metaPath = path9.join(this.stateDir, "topics.json");
10072
+ await mkdir(this.stateDir, { recursive: true });
10502
10073
  await this.writeStorageSecureFile(
10503
10074
  metaPath,
10504
10075
  JSON.stringify({ topics, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)
@@ -10509,7 +10080,7 @@ ${memory.content}
10509
10080
  * Load topic scores from meta.json.
10510
10081
  */
10511
10082
  async loadTopics() {
10512
- const metaPath = path10.join(this.stateDir, "topics.json");
10083
+ const metaPath = path9.join(this.stateDir, "topics.json");
10513
10084
  try {
10514
10085
  const raw = await this.readStorageSecureFile(metaPath);
10515
10086
  return JSON.parse(raw);
@@ -10620,8 +10191,6 @@ export {
10620
10191
  countEntityStructuredFacts,
10621
10192
  fingerprintEntityStructuredFacts,
10622
10193
  isEntitySynthesisStale,
10623
- FactHashIndexNotAuthoritativeError,
10624
- ContentHashIndex,
10625
10194
  parseFrontmatterStringValue,
10626
10195
  parseFrontmatter,
10627
10196
  normalizeFrontmatterForPath,
@@ -10631,4 +10200,4 @@ export {
10631
10200
  isValidBufferSurpriseEvent,
10632
10201
  StorageManager3 as StorageManager
10633
10202
  };
10634
- //# sourceMappingURL=chunk-JMQUBRV6.js.map
10203
+ //# sourceMappingURL=chunk-RGIWINDN.js.map