@remnic/core 9.27.0 → 9.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (515) hide show
  1. package/dist/access-admin-ops-surface.d.ts +13 -10
  2. package/dist/access-admin-ops-surface.js +46 -41
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-authorization-probe.d.ts +13 -10
  5. package/dist/access-authorization-probe.js +47 -42
  6. package/dist/access-boundary.d.ts +13 -10
  7. package/dist/access-boundary.js +46 -41
  8. package/dist/access-cli.js +105 -96
  9. package/dist/access-cli.js.map +1 -1
  10. package/dist/access-health-types.d.ts +10 -1
  11. package/dist/access-http-lcm-compaction.d.ts +13 -10
  12. package/dist/access-http.d.ts +13 -10
  13. package/dist/access-http.js +56 -51
  14. package/dist/access-identity-continuity-surface.d.ts +9 -8
  15. package/dist/access-identity-continuity-surface.js +46 -41
  16. package/dist/access-lcm-surface.d.ts +13 -10
  17. package/dist/access-lcm-surface.js +46 -41
  18. package/dist/access-mcp.d.ts +13 -10
  19. package/dist/access-mcp.js +51 -46
  20. package/dist/access-memory-search-fanout.d.ts +2 -2
  21. package/dist/access-memory-search-fanout.js +3 -3
  22. package/dist/{access-namespace-preflight-wRSZEO5V.d.ts → access-namespace-preflight-DCXBkDp0.d.ts} +1 -1
  23. package/dist/access-namespace-preflight.d.ts +3 -3
  24. package/dist/access-namespace-preflight.js +46 -41
  25. package/dist/access-observe-write-surface.d.ts +13 -10
  26. package/dist/access-observe-write-surface.js +46 -41
  27. package/dist/access-operations-batch.js +48 -43
  28. package/dist/access-operations.d.ts +16 -13
  29. package/dist/access-operations.js +50 -45
  30. package/dist/access-recall-concurrency.d.ts +13 -10
  31. package/dist/access-recall-concurrency.js +46 -41
  32. package/dist/access-recall-response.d.ts +13 -10
  33. package/dist/access-recall-response.js +46 -41
  34. package/dist/access-recall-surface.d.ts +13 -10
  35. package/dist/access-recall-surface.js +46 -41
  36. package/dist/access-schema.d.ts +80 -80
  37. package/dist/access-schema.js +3 -3
  38. package/dist/{access-service-B4-Fu9x2.d.ts → access-service-DvPW_M5j.d.ts} +12 -8
  39. package/dist/access-service.d.ts +13 -10
  40. package/dist/access-service.js +46 -41
  41. package/dist/access-surface-catalog.d.ts +13 -10
  42. package/dist/access-wearables-meetings-surface.d.ts +4 -3
  43. package/dist/action-confidence.d.ts +1 -1
  44. package/dist/active-memory-bridge.d.ts +1 -1
  45. package/dist/active-memory-bridge.js +3 -3
  46. package/dist/active-recall.d.ts +1 -1
  47. package/dist/active-recall.js +4 -2
  48. package/dist/active-recall.js.map +1 -1
  49. package/dist/adapters/index.js +4 -4
  50. package/dist/adapters/registry.js +2 -2
  51. package/dist/behavior-learner.d.ts +1 -1
  52. package/dist/behavior-signals.d.ts +1 -1
  53. package/dist/bootstrap.d.ts +9 -8
  54. package/dist/briefing.d.ts +3 -2
  55. package/dist/briefing.js +14 -12
  56. package/dist/buffer-surprise-report.d.ts +1 -1
  57. package/dist/buffer.d.ts +3 -2
  58. package/dist/buffer.js +2 -2
  59. package/dist/bulk-import/index.d.ts +3 -3
  60. package/dist/calibration.d.ts +1 -1
  61. package/dist/capabilities.d.ts +3 -2
  62. package/dist/capabilities.js +1 -1
  63. package/dist/{capsule-crypto-YO5QJ6L3.js → capsule-crypto-GWVG7LGC.js} +2 -2
  64. package/dist/{catalog-BLLxZ5L5.d.ts → catalog-BIVgftWu.d.ts} +1 -1
  65. package/dist/causal-behavior.d.ts +1 -1
  66. package/dist/causal-consolidation.d.ts +1 -1
  67. package/dist/causal-consolidation.js +15 -13
  68. package/dist/causal-consolidation.js.map +1 -1
  69. package/dist/causal-trajectory-graph.d.ts +1 -1
  70. package/dist/{chunk-CI26JDZA.js → chunk-2HNUMF5V.js} +6 -4
  71. package/dist/{chunk-CI26JDZA.js.map → chunk-2HNUMF5V.js.map} +1 -1
  72. package/dist/{chunk-NUWMZIYZ.js → chunk-2XC73SHY.js} +61 -43
  73. package/dist/chunk-2XC73SHY.js.map +1 -0
  74. package/dist/{chunk-RDQGLJRR.js → chunk-2XRE6FLM.js} +2 -1
  75. package/dist/{chunk-RDQGLJRR.js.map → chunk-2XRE6FLM.js.map} +1 -1
  76. package/dist/{chunk-2H7OEVPO.js → chunk-3GD2HFR6.js} +2 -2
  77. package/dist/{chunk-4TFIRMTE.js → chunk-4A6YGWQN.js} +2 -2
  78. package/dist/{chunk-JDOJZTFF.js → chunk-4PBVXX7L.js} +2 -2
  79. package/dist/{chunk-IKMAO55B.js → chunk-55MDBZLC.js} +2 -2
  80. package/dist/{chunk-VDX2J7OX.js → chunk-5W7CTZ2E.js} +4 -4
  81. package/dist/{chunk-B7GROTXD.js → chunk-6LKEUCEM.js} +2 -2
  82. package/dist/{chunk-2AJ72VVS.js → chunk-7BZOBA5J.js} +3 -3
  83. package/dist/{chunk-44DUJETW.js → chunk-7HXCF4RE.js} +2 -2
  84. package/dist/{chunk-X3SQYAPP.js → chunk-ACXPX4AG.js} +2 -2
  85. package/dist/{chunk-AJ7QCSIS.js → chunk-ALSGMEJR.js} +5 -5
  86. package/dist/{chunk-JGUXPJUQ.js → chunk-AS7YMSL6.js} +2 -2
  87. package/dist/{chunk-77CNV7DY.js → chunk-BLAKS3CP.js} +4 -4
  88. package/dist/{chunk-5BRT4Z2I.js → chunk-CMRQ34J5.js} +2 -2
  89. package/dist/{chunk-HEXSNYJD.js → chunk-CSMCNOPH.js} +8 -8
  90. package/dist/chunk-CVILPI77.js +432 -0
  91. package/dist/chunk-CVILPI77.js.map +1 -0
  92. package/dist/{chunk-SK3EYPKC.js → chunk-D2ANTDGO.js} +3 -3
  93. package/dist/{chunk-JCVQV6QX.js → chunk-D3LMYTBV.js} +7 -7
  94. package/dist/{chunk-GJJBPI6I.js → chunk-DRBXHRXE.js} +7 -3
  95. package/dist/chunk-DRBXHRXE.js.map +1 -0
  96. package/dist/{chunk-XY7QPJDA.js → chunk-E6EE5B67.js} +2 -2
  97. package/dist/{chunk-LLISELSY.js → chunk-EP5BVCRI.js} +2 -2
  98. package/dist/{chunk-PTN6UAUA.js → chunk-ES36HTSC.js} +4 -4
  99. package/dist/{chunk-WEAO45M4.js → chunk-ESBQWC3U.js} +4 -4
  100. package/dist/{chunk-EUSLKI4X.js → chunk-EVX44I7C.js} +5 -5
  101. package/dist/{chunk-CIQXI47W.js → chunk-FCDWWCLX.js} +1195 -271
  102. package/dist/chunk-FCDWWCLX.js.map +1 -0
  103. package/dist/{chunk-X6ROIHFE.js → chunk-G5R3D5UP.js} +2 -2
  104. package/dist/{chunk-MG6MNSP4.js → chunk-G6LBWZRF.js} +7 -7
  105. package/dist/{chunk-TKBDJTXG.js → chunk-GBJ4RDFR.js} +94 -20
  106. package/dist/chunk-GBJ4RDFR.js.map +1 -0
  107. package/dist/{chunk-FRVTCCGD.js → chunk-GGUBDXRR.js} +2 -2
  108. package/dist/{chunk-QH6CS6XJ.js → chunk-H24WNPA2.js} +2 -2
  109. package/dist/{chunk-V25OWXAC.js → chunk-HUHX2OCX.js} +1 -1
  110. package/dist/chunk-HUHX2OCX.js.map +1 -0
  111. package/dist/{chunk-TGQ2NTWH.js → chunk-IJ6WHMFB.js} +16 -2
  112. package/dist/{chunk-TGQ2NTWH.js.map → chunk-IJ6WHMFB.js.map} +1 -1
  113. package/dist/{chunk-EOLC6EXV.js → chunk-IMA2EWLV.js} +24 -3
  114. package/dist/chunk-IMA2EWLV.js.map +1 -0
  115. package/dist/{chunk-MQVINOJQ.js → chunk-IYZ5K7MU.js} +3 -3
  116. package/dist/{chunk-RPA2RX5P.js → chunk-JDZRYH2N.js} +2 -2
  117. package/dist/{chunk-M5EPMNS4.js → chunk-K5GB36ME.js} +2 -2
  118. package/dist/{chunk-UT3OQPFA.js → chunk-KUJQHXPH.js} +2 -2
  119. package/dist/{chunk-7RZJWZ46.js → chunk-LEPOP46W.js} +5 -5
  120. package/dist/{chunk-EYJSW2RV.js → chunk-NBDCZWP4.js} +4 -4
  121. package/dist/{chunk-XKGPIWGI.js → chunk-OFHFH655.js} +6 -6
  122. package/dist/{chunk-FGBJBYWP.js → chunk-OVRQLAYR.js} +3 -3
  123. package/dist/{chunk-BXLOS5AJ.js → chunk-OWHERGF2.js} +2 -2
  124. package/dist/chunk-P2BM76KT.js +528 -0
  125. package/dist/chunk-P2BM76KT.js.map +1 -0
  126. package/dist/{chunk-U3TH5Q2Q.js → chunk-P3MH72CI.js} +2 -2
  127. package/dist/{chunk-P2OZKKYP.js → chunk-PHWUFPCO.js} +2 -2
  128. package/dist/{chunk-KGTD2KZJ.js → chunk-PKRIQL3V.js} +2 -2
  129. package/dist/{chunk-BNGPHGVZ.js → chunk-Q6VFVAKZ.js} +13 -6
  130. package/dist/{chunk-BNGPHGVZ.js.map → chunk-Q6VFVAKZ.js.map} +1 -1
  131. package/dist/{chunk-4MJZTF42.js → chunk-QAOGGNE3.js} +3 -3
  132. package/dist/{chunk-RGJBM7Z3.js → chunk-QMBNMPQM.js} +84 -84
  133. package/dist/{chunk-RGJBM7Z3.js.map → chunk-QMBNMPQM.js.map} +1 -1
  134. package/dist/{chunk-2QSZNTDO.js → chunk-RKNJBZ55.js} +4 -4
  135. package/dist/chunk-RMMVQQA6.js +70 -0
  136. package/dist/chunk-RMMVQQA6.js.map +1 -0
  137. package/dist/{chunk-FCCMFVS6.js → chunk-RPSYDM6C.js} +2 -2
  138. package/dist/chunk-RPW2NOU6.js +33 -0
  139. package/dist/chunk-RPW2NOU6.js.map +1 -0
  140. package/dist/{chunk-RYHWZ52A.js → chunk-S2BBISHU.js} +4 -4
  141. package/dist/{chunk-RSYJV25N.js → chunk-SG265CVF.js} +10 -10
  142. package/dist/{chunk-UGH6VPPO.js → chunk-SH6YO3LT.js} +3 -3
  143. package/dist/{chunk-2RAC4JIG.js → chunk-T3GCXULH.js} +16 -16
  144. package/dist/chunk-T3GCXULH.js.map +1 -0
  145. package/dist/{chunk-FMLKOL2Z.js → chunk-TC3VNKGX.js} +4 -4
  146. package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
  147. package/dist/{chunk-BJJAX3IZ.js → chunk-UTRO5UJU.js} +2 -2
  148. package/dist/{chunk-DQEMWVMT.js → chunk-UVYI6VIX.js} +1 -1
  149. package/dist/chunk-VNA7W7QF.js +134 -0
  150. package/dist/chunk-VNA7W7QF.js.map +1 -0
  151. package/dist/{chunk-BHLN7L7M.js → chunk-VVIW3PTA.js} +17 -17
  152. package/dist/chunk-WNIUPHWV.js +152 -0
  153. package/dist/chunk-WNIUPHWV.js.map +1 -0
  154. package/dist/chunk-WOCNN776.js +742 -0
  155. package/dist/chunk-WOCNN776.js.map +1 -0
  156. package/dist/{chunk-XQ4EH6DI.js → chunk-WONS4RZ2.js} +3 -3
  157. package/dist/chunk-WRJVB3C2.js +118 -0
  158. package/dist/chunk-WRJVB3C2.js.map +1 -0
  159. package/dist/{chunk-HORJVJ6K.js → chunk-WZ7UB7XQ.js} +42 -37
  160. package/dist/chunk-WZ7UB7XQ.js.map +1 -0
  161. package/dist/{chunk-MEBQFQ26.js → chunk-XEQ7OT7U.js} +8 -6
  162. package/dist/chunk-XEQ7OT7U.js.map +1 -0
  163. package/dist/{chunk-CSXHRAJJ.js → chunk-XOZ4ALGB.js} +3 -3
  164. package/dist/{chunk-XKO7BM2C.js → chunk-YGHMSDLK.js} +187 -26
  165. package/dist/chunk-YGHMSDLK.js.map +1 -0
  166. package/dist/chunk-YXZG5TVN.js +40 -0
  167. package/dist/chunk-YXZG5TVN.js.map +1 -0
  168. package/dist/{chunk-6NNNURLK.js → chunk-Z54EM5YZ.js} +4 -4
  169. package/dist/{chunk-YSGBD3QN.js → chunk-ZGOQTOYA.js} +3 -3
  170. package/dist/{chunk-4DJQYKMN.js → chunk-ZIKENA2C.js} +2 -2
  171. package/dist/chunk-ZIKENA2C.js.map +1 -0
  172. package/dist/{chunk-RNY3BO35.js → chunk-ZXAGJFHJ.js} +4 -4
  173. package/dist/{cli-Bz7X7dGx.d.ts → cli-CxoSOiG0.d.ts} +5 -5
  174. package/dist/cli.d.ts +14 -12
  175. package/dist/cli.js +73 -68
  176. package/dist/compounding/engine.d.ts +3 -2
  177. package/dist/compounding/engine.js +15 -13
  178. package/dist/compounding/preference-consolidator.d.ts +1 -1
  179. package/dist/compression-optimizer.d.ts +1 -1
  180. package/dist/config.d.ts +1 -1
  181. package/dist/config.js +4 -2
  182. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  183. package/dist/connectors/codex-materialize-runner.js +14 -12
  184. package/dist/connectors/codex-materialize.d.ts +1 -1
  185. package/dist/connectors/index.d.ts +1 -1
  186. package/dist/connectors/index.js +15 -13
  187. package/dist/consolidation-provenance-check.d.ts +3 -2
  188. package/dist/consolidation-undo.d.ts +3 -2
  189. package/dist/contradiction/index.d.ts +3 -2
  190. package/dist/contradiction/index.js +6 -6
  191. package/dist/{contradiction-scan-HMF7CNKD.js → contradiction-scan-HYLIRMJ2.js} +3 -3
  192. package/dist/conversation-index/backend.d.ts +1 -1
  193. package/dist/conversation-index/backend.js +2 -2
  194. package/dist/conversation-index/chunker.d.ts +1 -1
  195. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  196. package/dist/conversation-index/indexer.d.ts +1 -1
  197. package/dist/conversation-index/search.d.ts +1 -1
  198. package/dist/corpus-watermark.d.ts +15 -2
  199. package/dist/corpus-watermark.js +27 -23
  200. package/dist/day-summary.d.ts +1 -1
  201. package/dist/day-summary.js +2 -2
  202. package/dist/delinearize.d.ts +1 -1
  203. package/dist/direct-answer-wiring.d.ts +1 -1
  204. package/dist/direct-answer.d.ts +1 -1
  205. package/dist/embedding-fallback.d.ts +1 -1
  206. package/dist/embedding-fallback.js +2 -2
  207. package/dist/enrichment/index.d.ts +1 -1
  208. package/dist/entity-id-normalization.d.ts +4 -0
  209. package/dist/entity-id-normalization.js +10 -0
  210. package/dist/entity-id-normalization.js.map +1 -0
  211. package/dist/entity-retrieval-boundaries.d.ts +3 -0
  212. package/dist/entity-retrieval-boundaries.js +8 -0
  213. package/dist/entity-retrieval-boundaries.js.map +1 -0
  214. package/dist/entity-retrieval.d.ts +3 -2
  215. package/dist/entity-retrieval.js +15 -12
  216. package/dist/entity-schema.d.ts +1 -1
  217. package/dist/entity-schema.js +1 -1
  218. package/dist/explicit-capture.d.ts +9 -8
  219. package/dist/explicit-capture.js +2 -2
  220. package/dist/extraction-error-classification.d.ts +1 -1
  221. package/dist/extraction-faithfulness.d.ts +1 -1
  222. package/dist/extraction-judge-telemetry.d.ts +1 -1
  223. package/dist/extraction-judge-training.d.ts +1 -1
  224. package/dist/extraction-judge.d.ts +1 -1
  225. package/dist/extraction-liveness.d.ts +1 -1
  226. package/dist/extraction-source-grounding-helpers.d.ts +34 -0
  227. package/dist/extraction-source-grounding-helpers.js +62 -0
  228. package/dist/extraction-source-grounding-helpers.js.map +1 -0
  229. package/dist/extraction-source-grounding-rules.d.ts +18 -0
  230. package/dist/extraction-source-grounding-rules.js +12 -0
  231. package/dist/extraction-source-grounding-rules.js.map +1 -0
  232. package/dist/extraction-source-grounding.d.ts +11 -0
  233. package/dist/extraction-source-grounding.js +13 -0
  234. package/dist/extraction-source-grounding.js.map +1 -0
  235. package/dist/extraction.d.ts +3 -1
  236. package/dist/extraction.js +7 -4
  237. package/dist/fallback-llm.d.ts +1 -1
  238. package/dist/{first-start-migration-LEXL3XYL.js → first-start-migration-F2QJD66E.js} +2 -2
  239. package/dist/graph-dashboard-diff.d.ts +1 -1
  240. package/dist/graph-dashboard-key.d.ts +1 -1
  241. package/dist/graph-dashboard-parser.d.ts +1 -1
  242. package/dist/graph-edge-reinforcement.d.ts +1 -1
  243. package/dist/graph-snapshot.d.ts +1 -1
  244. package/dist/graph.d.ts +1 -1
  245. package/dist/importance.d.ts +1 -1
  246. package/dist/importers/index.d.ts +1 -1
  247. package/dist/in-flight-reads.d.ts +1 -1
  248. package/dist/index.d.ts +407 -405
  249. package/dist/index.js +154 -145
  250. package/dist/intent.d.ts +1 -1
  251. package/dist/lcm/engine.d.ts +1 -1
  252. package/dist/lcm/engine.js +2 -2
  253. package/dist/lcm/index.d.ts +1 -1
  254. package/dist/lcm/index.js +2 -2
  255. package/dist/lcm/tools.d.ts +1 -1
  256. package/dist/lifecycle.d.ts +1 -1
  257. package/dist/live-connectors-runner.d.ts +1 -1
  258. package/dist/local-llm.d.ts +1 -1
  259. package/dist/local-llm.js +2 -2
  260. package/dist/local-model-endpoint.d.ts +1 -1
  261. package/dist/maintenance/memory-governance.d.ts +1 -1
  262. package/dist/maintenance/memory-governance.js +14 -12
  263. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +3 -2
  264. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +14 -12
  265. package/dist/maintenance/rebuild-memory-projection.d.ts +3 -2
  266. package/dist/maintenance/rebuild-memory-projection.js +15 -13
  267. package/dist/{maintenance-DgnD2z8S.d.ts → maintenance-Cb-PjxQd.d.ts} +3 -3
  268. package/dist/mcp-memory-inspector-app.d.ts +13 -10
  269. package/dist/memory-action-policy.d.ts +1 -1
  270. package/dist/memory-cache.d.ts +1 -1
  271. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  272. package/dist/memory-projection-mutations.d.ts +4 -0
  273. package/dist/memory-projection-mutations.js +15 -0
  274. package/dist/memory-projection-mutations.js.map +1 -0
  275. package/dist/memory-projection-store.d.ts +1 -1
  276. package/dist/memory-provenance.d.ts +1 -1
  277. package/dist/memory-worth-outcomes.d.ts +3 -2
  278. package/dist/models-json.d.ts +1 -1
  279. package/dist/namespaces/migrate.d.ts +4 -3
  280. package/dist/namespaces/migrate.js +24 -22
  281. package/dist/namespaces/principal.d.ts +1 -1
  282. package/dist/namespaces/principal.js +2 -2
  283. package/dist/namespaces/search.d.ts +1 -1
  284. package/dist/namespaces/search.js +10 -10
  285. package/dist/namespaces/storage.d.ts +4 -3
  286. package/dist/namespaces/storage.js +14 -12
  287. package/dist/native-knowledge.d.ts +1 -1
  288. package/dist/offline-sync-impression-drain.d.ts +1 -1
  289. package/dist/offline-sync-impression-drain.js +7 -7
  290. package/dist/operator-doctor-corpus.d.ts +22 -3
  291. package/dist/operator-doctor-corpus.js +34 -24
  292. package/dist/operator-doctor-replica.d.ts +52 -0
  293. package/dist/operator-doctor-replica.js +15 -0
  294. package/dist/operator-doctor-replica.js.map +1 -0
  295. package/dist/operator-toolkit.d.ts +7 -3
  296. package/dist/operator-toolkit.js +37 -31
  297. package/dist/orchestration/compression-guideline-coordinator.d.ts +3 -2
  298. package/dist/orchestration/compression-guideline-coordinator.js +2 -2
  299. package/dist/orchestration/maintenance.d.ts +5 -4
  300. package/dist/orchestration/maintenance.js +21 -19
  301. package/dist/{orchestrator-rIHmHpv1.d.ts → orchestrator-5GKqb_HL.d.ts} +7 -7
  302. package/dist/orchestrator.d.ts +9 -8
  303. package/dist/orchestrator.js +105 -96
  304. package/dist/patterns-cli.d.ts +1 -1
  305. package/dist/{pipeline-Bq5zU6Bp.d.ts → pipeline-3Qi1TpRo.d.ts} +1 -1
  306. package/dist/policy-runtime.d.ts +1 -1
  307. package/dist/proactive-contention.d.ts +1 -1
  308. package/dist/provenance.d.ts +1 -1
  309. package/dist/{qmd-3ILJkC70.d.ts → qmd-D9JqzzRX.d.ts} +1 -1
  310. package/dist/qmd-preflight.d.ts +2 -2
  311. package/dist/qmd-recall-cache.d.ts +1 -1
  312. package/dist/qmd.d.ts +2 -2
  313. package/dist/recall-concurrency-config.d.ts +1 -1
  314. package/dist/recall-disclosure-escalation.d.ts +1 -1
  315. package/dist/recall-explain-renderer.d.ts +1 -1
  316. package/dist/recall-explain-renderer.js +3 -3
  317. package/dist/recall-memory-map.d.ts +1 -1
  318. package/dist/recall-planner-llm.d.ts +1 -1
  319. package/dist/recall-state.d.ts +1 -1
  320. package/dist/recall-state.js +2 -2
  321. package/dist/recall-tag-filter.d.ts +1 -1
  322. package/dist/recall-timings.d.ts +1 -1
  323. package/dist/recall-xray-cli.d.ts +1 -1
  324. package/dist/recall-xray-cli.js +4 -4
  325. package/dist/recall-xray-renderer.d.ts +1 -1
  326. package/dist/recall-xray-renderer.js +3 -3
  327. package/dist/recall-xray.d.ts +1 -1
  328. package/dist/recall-xray.js +2 -2
  329. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  330. package/dist/replay/normalizers/claude.d.ts +1 -1
  331. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  332. package/dist/replay/normalizers/shared.d.ts +1 -1
  333. package/dist/replay/runner.d.ts +1 -1
  334. package/dist/replay/types.d.ts +1 -1
  335. package/dist/replica-divergence.d.ts +279 -0
  336. package/dist/replica-divergence.js +28 -0
  337. package/dist/replica-divergence.js.map +1 -0
  338. package/dist/replica-peers-config.d.ts +5 -0
  339. package/dist/replica-peers-config.js +13 -0
  340. package/dist/replica-peers-config.js.map +1 -0
  341. package/dist/resolve-auth-token.d.ts +21 -2
  342. package/dist/resolve-auth-token.js +5 -1
  343. package/dist/resume-bundles.js +5 -3
  344. package/dist/retrieval-agents.d.ts +2 -2
  345. package/dist/retrieval-tiers.d.ts +1 -1
  346. package/dist/routing/engine.d.ts +1 -1
  347. package/dist/routing/store.d.ts +1 -1
  348. package/dist/salvage-envelope.d.ts +1 -1
  349. package/dist/schemas.d.ts +54 -54
  350. package/dist/{scope-profiles-D0-ff4xT.d.ts → scope-profiles-C4g6_UdP.d.ts} +1 -1
  351. package/dist/search/embed-helper.d.ts +1 -1
  352. package/dist/search/embed-helper.js +2 -2
  353. package/dist/search/factory.d.ts +1 -1
  354. package/dist/search/factory.js +9 -9
  355. package/dist/search/index.d.ts +1 -1
  356. package/dist/search/index.js +9 -9
  357. package/dist/search/lancedb-backend.d.ts +1 -1
  358. package/dist/search/lancedb-backend.js +2 -2
  359. package/dist/search/meilisearch-backend.d.ts +1 -1
  360. package/dist/search/meilisearch-backend.js +2 -2
  361. package/dist/search/noop-backend.d.ts +1 -1
  362. package/dist/search/orama-backend.d.ts +1 -1
  363. package/dist/search/orama-backend.js +2 -2
  364. package/dist/search/port.d.ts +1 -1
  365. package/dist/search/remote-backend.d.ts +1 -1
  366. package/dist/{semantic-consolidation-4Tfh7c1g.d.ts → semantic-consolidation-BrxqnzTW.d.ts} +1 -1
  367. package/dist/semantic-consolidation.d.ts +2 -2
  368. package/dist/semantic-consolidation.js +15 -13
  369. package/dist/semantic-rule-promotion.js +14 -12
  370. package/dist/semantic-rule-verifier.d.ts +1 -1
  371. package/dist/semantic-rule-verifier.js +14 -12
  372. package/dist/{service-cTvil7D_.d.ts → service-Bi1JgxdP.d.ts} +2 -2
  373. package/dist/session-observer-bands.d.ts +1 -1
  374. package/dist/session-observer-state.d.ts +1 -1
  375. package/dist/shared-context/manager.d.ts +9 -9
  376. package/dist/shared-context/manager.js +2 -2
  377. package/dist/signal.d.ts +1 -1
  378. package/dist/{storage-C9ibpTme.d.ts → storage-CcH6yPk2.d.ts} +13 -19
  379. package/dist/storage.d.ts +3 -2
  380. package/dist/storage.js +15 -12
  381. package/dist/summarizer.d.ts +1 -1
  382. package/dist/summarizer.js +3 -3
  383. package/dist/summary-snapshot.d.ts +1 -1
  384. package/dist/temporal-supersession.d.ts +3 -2
  385. package/dist/temporal-timeline-recall.d.ts +1 -1
  386. package/dist/temporal-validity.d.ts +1 -1
  387. package/dist/threading.d.ts +1 -1
  388. package/dist/tier-migration.d.ts +3 -2
  389. package/dist/tier-routing.d.ts +1 -1
  390. package/dist/{tier-stats-XKD7SXYY.js → tier-stats-OPTSBNRH.js} +2 -2
  391. package/dist/topics.d.ts +1 -1
  392. package/dist/transcript.d.ts +1 -1
  393. package/dist/transfer/backup.js +2 -2
  394. package/dist/transfer/capsule-export.js +2 -2
  395. package/dist/transfer/capsule-import.js +2 -2
  396. package/dist/transfer/types.d.ts +66 -66
  397. package/dist/trust-score-stage.d.ts +1 -1
  398. package/dist/trust-score.d.ts +1 -1
  399. package/dist/{types-DHBxIF0s.d.ts → types-Dg0w9ADr.d.ts} +54 -4
  400. package/dist/types.d.ts +1 -1
  401. package/dist/types.js +1 -1
  402. package/dist/utility-runtime.d.ts +1 -1
  403. package/dist/verified-recall.js +14 -12
  404. package/dist/write-envelope.d.ts +1 -1
  405. package/package.json +2 -2
  406. package/src/access-health-types.ts +8 -0
  407. package/src/access-http.test.ts +4 -0
  408. package/src/access-service-health.test.ts +23 -0
  409. package/src/access-service.ts +27 -4
  410. package/src/capabilities.test.ts +1 -0
  411. package/src/capabilities.ts +7 -7
  412. package/src/cli.ts +9 -7
  413. package/src/config.test.ts +5 -0
  414. package/src/config.ts +3 -2
  415. package/src/corpus-watermark.test.ts +21 -0
  416. package/src/corpus-watermark.ts +25 -3
  417. package/src/entity-id-normalization.ts +55 -0
  418. package/src/entity-retrieval-boundaries.ts +134 -0
  419. package/src/entity-retrieval.ts +253 -27
  420. package/src/entity-schema.ts +2 -1
  421. package/src/extraction-source-grounding-helpers.ts +603 -0
  422. package/src/extraction-source-grounding-rules.ts +1031 -0
  423. package/src/extraction-source-grounding.test.ts +2337 -0
  424. package/src/extraction-source-grounding.ts +50 -0
  425. package/src/extraction.ts +120 -15
  426. package/src/memory-projection-mutations.ts +132 -0
  427. package/src/namespaces/storage.ts +5 -3
  428. package/src/operator-doctor-corpus.ts +41 -0
  429. package/src/operator-doctor-replica.test.ts +261 -0
  430. package/src/operator-doctor-replica.ts +129 -0
  431. package/src/operator-toolkit.ts +5 -4
  432. package/src/orchestration/orchestrator-init.ts +2 -2
  433. package/src/replica-divergence.test.ts +1475 -0
  434. package/src/replica-divergence.ts +910 -0
  435. package/src/replica-peers-config.ts +250 -0
  436. package/src/resolve-auth-token.ts +38 -0
  437. package/src/storage/entity-canonical-id-migration-adapter.ts +72 -0
  438. package/src/storage/entity-canonical-id-migration-runner.ts +68 -0
  439. package/src/storage/entity-canonical-id-migration.ts +904 -0
  440. package/src/storage/entity-store.ts +44 -0
  441. package/src/storage/memory-frontmatter-metadata.ts +17 -0
  442. package/src/storage/memory-migration-serialization.ts +37 -0
  443. package/src/storage/memory-read-store.ts +3 -2
  444. package/src/storage/profile-header.ts +8 -7
  445. package/src/storage-profile-timestamp.test.ts +68 -0
  446. package/src/storage.ts +68 -69
  447. package/src/types.ts +5 -5
  448. package/dist/chunk-2RAC4JIG.js.map +0 -1
  449. package/dist/chunk-4DJQYKMN.js.map +0 -1
  450. package/dist/chunk-CIQXI47W.js.map +0 -1
  451. package/dist/chunk-EOLC6EXV.js.map +0 -1
  452. package/dist/chunk-GJJBPI6I.js.map +0 -1
  453. package/dist/chunk-HORJVJ6K.js.map +0 -1
  454. package/dist/chunk-MEBQFQ26.js.map +0 -1
  455. package/dist/chunk-NUWMZIYZ.js.map +0 -1
  456. package/dist/chunk-TKBDJTXG.js.map +0 -1
  457. package/dist/chunk-V25OWXAC.js.map +0 -1
  458. package/dist/chunk-XKO7BM2C.js.map +0 -1
  459. /package/dist/{capsule-crypto-YO5QJ6L3.js.map → capsule-crypto-GWVG7LGC.js.map} +0 -0
  460. /package/dist/{chunk-2H7OEVPO.js.map → chunk-3GD2HFR6.js.map} +0 -0
  461. /package/dist/{chunk-4TFIRMTE.js.map → chunk-4A6YGWQN.js.map} +0 -0
  462. /package/dist/{chunk-JDOJZTFF.js.map → chunk-4PBVXX7L.js.map} +0 -0
  463. /package/dist/{chunk-IKMAO55B.js.map → chunk-55MDBZLC.js.map} +0 -0
  464. /package/dist/{chunk-VDX2J7OX.js.map → chunk-5W7CTZ2E.js.map} +0 -0
  465. /package/dist/{chunk-B7GROTXD.js.map → chunk-6LKEUCEM.js.map} +0 -0
  466. /package/dist/{chunk-2AJ72VVS.js.map → chunk-7BZOBA5J.js.map} +0 -0
  467. /package/dist/{chunk-44DUJETW.js.map → chunk-7HXCF4RE.js.map} +0 -0
  468. /package/dist/{chunk-X3SQYAPP.js.map → chunk-ACXPX4AG.js.map} +0 -0
  469. /package/dist/{chunk-AJ7QCSIS.js.map → chunk-ALSGMEJR.js.map} +0 -0
  470. /package/dist/{chunk-JGUXPJUQ.js.map → chunk-AS7YMSL6.js.map} +0 -0
  471. /package/dist/{chunk-77CNV7DY.js.map → chunk-BLAKS3CP.js.map} +0 -0
  472. /package/dist/{chunk-5BRT4Z2I.js.map → chunk-CMRQ34J5.js.map} +0 -0
  473. /package/dist/{chunk-HEXSNYJD.js.map → chunk-CSMCNOPH.js.map} +0 -0
  474. /package/dist/{chunk-SK3EYPKC.js.map → chunk-D2ANTDGO.js.map} +0 -0
  475. /package/dist/{chunk-JCVQV6QX.js.map → chunk-D3LMYTBV.js.map} +0 -0
  476. /package/dist/{chunk-XY7QPJDA.js.map → chunk-E6EE5B67.js.map} +0 -0
  477. /package/dist/{chunk-LLISELSY.js.map → chunk-EP5BVCRI.js.map} +0 -0
  478. /package/dist/{chunk-PTN6UAUA.js.map → chunk-ES36HTSC.js.map} +0 -0
  479. /package/dist/{chunk-WEAO45M4.js.map → chunk-ESBQWC3U.js.map} +0 -0
  480. /package/dist/{chunk-EUSLKI4X.js.map → chunk-EVX44I7C.js.map} +0 -0
  481. /package/dist/{chunk-X6ROIHFE.js.map → chunk-G5R3D5UP.js.map} +0 -0
  482. /package/dist/{chunk-MG6MNSP4.js.map → chunk-G6LBWZRF.js.map} +0 -0
  483. /package/dist/{chunk-FRVTCCGD.js.map → chunk-GGUBDXRR.js.map} +0 -0
  484. /package/dist/{chunk-QH6CS6XJ.js.map → chunk-H24WNPA2.js.map} +0 -0
  485. /package/dist/{chunk-MQVINOJQ.js.map → chunk-IYZ5K7MU.js.map} +0 -0
  486. /package/dist/{chunk-RPA2RX5P.js.map → chunk-JDZRYH2N.js.map} +0 -0
  487. /package/dist/{chunk-M5EPMNS4.js.map → chunk-K5GB36ME.js.map} +0 -0
  488. /package/dist/{chunk-UT3OQPFA.js.map → chunk-KUJQHXPH.js.map} +0 -0
  489. /package/dist/{chunk-7RZJWZ46.js.map → chunk-LEPOP46W.js.map} +0 -0
  490. /package/dist/{chunk-EYJSW2RV.js.map → chunk-NBDCZWP4.js.map} +0 -0
  491. /package/dist/{chunk-XKGPIWGI.js.map → chunk-OFHFH655.js.map} +0 -0
  492. /package/dist/{chunk-FGBJBYWP.js.map → chunk-OVRQLAYR.js.map} +0 -0
  493. /package/dist/{chunk-BXLOS5AJ.js.map → chunk-OWHERGF2.js.map} +0 -0
  494. /package/dist/{chunk-U3TH5Q2Q.js.map → chunk-P3MH72CI.js.map} +0 -0
  495. /package/dist/{chunk-P2OZKKYP.js.map → chunk-PHWUFPCO.js.map} +0 -0
  496. /package/dist/{chunk-KGTD2KZJ.js.map → chunk-PKRIQL3V.js.map} +0 -0
  497. /package/dist/{chunk-4MJZTF42.js.map → chunk-QAOGGNE3.js.map} +0 -0
  498. /package/dist/{chunk-2QSZNTDO.js.map → chunk-RKNJBZ55.js.map} +0 -0
  499. /package/dist/{chunk-FCCMFVS6.js.map → chunk-RPSYDM6C.js.map} +0 -0
  500. /package/dist/{chunk-RYHWZ52A.js.map → chunk-S2BBISHU.js.map} +0 -0
  501. /package/dist/{chunk-RSYJV25N.js.map → chunk-SG265CVF.js.map} +0 -0
  502. /package/dist/{chunk-UGH6VPPO.js.map → chunk-SH6YO3LT.js.map} +0 -0
  503. /package/dist/{chunk-FMLKOL2Z.js.map → chunk-TC3VNKGX.js.map} +0 -0
  504. /package/dist/{chunk-7K5Q6COX.js.map → chunk-TVVEYCNW.js.map} +0 -0
  505. /package/dist/{chunk-BJJAX3IZ.js.map → chunk-UTRO5UJU.js.map} +0 -0
  506. /package/dist/{chunk-DQEMWVMT.js.map → chunk-UVYI6VIX.js.map} +0 -0
  507. /package/dist/{chunk-BHLN7L7M.js.map → chunk-VVIW3PTA.js.map} +0 -0
  508. /package/dist/{chunk-XQ4EH6DI.js.map → chunk-WONS4RZ2.js.map} +0 -0
  509. /package/dist/{chunk-CSXHRAJJ.js.map → chunk-XOZ4ALGB.js.map} +0 -0
  510. /package/dist/{chunk-6NNNURLK.js.map → chunk-Z54EM5YZ.js.map} +0 -0
  511. /package/dist/{chunk-YSGBD3QN.js.map → chunk-ZGOQTOYA.js.map} +0 -0
  512. /package/dist/{chunk-RNY3BO35.js.map → chunk-ZXAGJFHJ.js.map} +0 -0
  513. /package/dist/{contradiction-scan-HMF7CNKD.js.map → contradiction-scan-HYLIRMJ2.js.map} +0 -0
  514. /package/dist/{first-start-migration-LEXL3XYL.js.map → first-start-migration-F2QJD66E.js.map} +0 -0
  515. /package/dist/{tier-stats-XKD7SXYY.js.map → tier-stats-OPTSBNRH.js.map} +0 -0
@@ -15,21 +15,23 @@ import {
15
15
  collectRetiredMemoriesForRebuild
16
16
  } from "./chunk-2QMKMVHH.js";
17
17
  import {
18
+ computeSupersessionKey,
19
+ normalizeSupersessionKey,
18
20
  supersessionKeysForFact
19
21
  } from "./chunk-DNHVPZOD.js";
20
- import {
21
- assertMemoryFrontmatterId,
22
- warnProjectionFallback
23
- } from "./chunk-HKF5VASQ.js";
24
22
  import {
25
23
  DEFAULT_CITATION_FORMAT,
26
24
  hasCitation,
27
25
  stripCitationForTemplate
28
26
  } from "./chunk-J6A3CX5N.js";
27
+ import {
28
+ assertMemoryFrontmatterId,
29
+ warnProjectionFallback
30
+ } from "./chunk-HKF5VASQ.js";
29
31
  import {
30
32
  SPECULATIVE_TTL_DAYS,
31
33
  confidenceTier
32
- } from "./chunk-V25OWXAC.js";
34
+ } from "./chunk-HUHX2OCX.js";
33
35
  import {
34
36
  appendLifecycleEventsSerialized,
35
37
  drainPendingLifecycleLedgerForSync,
@@ -40,26 +42,21 @@ import {
40
42
  readMaybeEncryptedLines,
41
43
  readMemoryActionEventRowsFromLines,
42
44
  serializeLifecycleAppendPayload
43
- } from "./chunk-XKGPIWGI.js";
45
+ } from "./chunk-OFHFH655.js";
44
46
  import {
45
47
  namespaceIdentityFromToken
46
48
  } from "./chunk-EGGE52UU.js";
47
- import {
48
- assertPathInsideRoot,
49
- pathIsInside
50
- } from "./chunk-GCASGYIO.js";
51
49
  import {
52
50
  withHeldFileLock
53
51
  } from "./chunk-WL5EBRDH.js";
54
52
  import {
55
- inferMemoryStatus,
56
- isArchivedMemoryPath,
57
- toMemoryPathRel
58
- } from "./chunk-ILGC6JH6.js";
53
+ rewriteProjectedEntityReferences,
54
+ rewriteProjectedMemoryEntityReference
55
+ } from "./chunk-WRJVB3C2.js";
59
56
  import {
60
- normalizeProjectionPreview,
61
- normalizeProjectionTags
62
- } from "./chunk-SCU65EZI.js";
57
+ assertPathInsideRoot,
58
+ pathIsInside
59
+ } from "./chunk-GCASGYIO.js";
63
60
  import {
64
61
  markProjectedMemoryPathInvalid,
65
62
  openProjectionReadonly,
@@ -69,6 +66,15 @@ import {
69
66
  readProjectedMemoryTimeline,
70
67
  updateProjectedMemoryPath
71
68
  } from "./chunk-3CSX3ETE.js";
69
+ import {
70
+ inferMemoryStatus,
71
+ isArchivedMemoryPath,
72
+ toMemoryPathRel
73
+ } from "./chunk-ILGC6JH6.js";
74
+ import {
75
+ normalizeProjectionPreview,
76
+ normalizeProjectionTags
77
+ } from "./chunk-SCU65EZI.js";
72
78
  import {
73
79
  rotateMarkdownFileToArchive
74
80
  } from "./chunk-DM2T26WE.js";
@@ -81,6 +87,10 @@ import {
81
87
  serializeContinuityIncident,
82
88
  upsertContinuityLoopInMarkdown
83
89
  } from "./chunk-LDXUBPMO.js";
90
+ import {
91
+ parseFaithfulnessField,
92
+ serializeFaithfulnessFields
93
+ } from "./chunk-JYIJNNN3.js";
84
94
  import {
85
95
  composeMemoryEnvelope,
86
96
  isSealedMemoryEnvelope,
@@ -91,9 +101,8 @@ import {
91
101
  stripAttributesSuffix
92
102
  } from "./chunk-R3DJVOSM.js";
93
103
  import {
94
- parseFaithfulnessField,
95
- serializeFaithfulnessFields
96
- } from "./chunk-JYIJNNN3.js";
104
+ normalizeEntityName
105
+ } from "./chunk-YXZG5TVN.js";
97
106
  import {
98
107
  createVersion
99
108
  } from "./chunk-5VQJBH2G.js";
@@ -131,20 +140,20 @@ import {
131
140
  reconcileProvenanceRead,
132
141
  serializeProvenanceFields
133
142
  } from "./chunk-5I4M26Q7.js";
134
- import {
135
- sanitizeMemoryContent
136
- } from "./chunk-5GKPFL3S.js";
137
143
  import {
138
144
  matchEntitySchemaSection,
139
145
  normalizeEntityStructuredSection,
140
146
  sortStructuredSectionsBySchema
141
- } from "./chunk-4DJQYKMN.js";
147
+ } from "./chunk-ZIKENA2C.js";
148
+ import {
149
+ sanitizeMemoryContent
150
+ } from "./chunk-5GKPFL3S.js";
142
151
  import {
143
152
  parseFlexibleIsoTimestamp
144
153
  } from "./chunk-P7FMDTKL.js";
145
154
  import {
146
155
  resolveNamespaceCapabilities
147
- } from "./chunk-RDQGLJRR.js";
156
+ } from "./chunk-2XRE6FLM.js";
148
157
  import {
149
158
  isPathInsideStorageRoot
150
159
  } from "./chunk-FF4KLI5W.js";
@@ -195,24 +204,40 @@ function assertInjectedStorageRooted(label, memoryDir, injected) {
195
204
 
196
205
  // src/storage.ts
197
206
  import {
198
- lstat as lstat2,
199
- readdir as readdir4,
200
- readFile,
201
- realpath as realpath2,
207
+ lstat as lstat3,
208
+ readdir as readdir5,
209
+ readFile as readFile2,
210
+ realpath as realpath3,
202
211
  stat as stat3,
203
- writeFile,
212
+ writeFile as writeFile2,
204
213
  mkdir as mkdir2,
205
- unlink as unlink2,
214
+ unlink as unlink3,
206
215
  appendFile,
207
216
  open
208
217
  } from "fs/promises";
209
- import { appendFileSync, createReadStream, mkdirSync, readFileSync, statSync } from "fs";
218
+ import { appendFileSync, createReadStream, mkdirSync, readFileSync as readFileSync2, statSync } from "fs";
210
219
  import { createHash as createHash5 } from "crypto";
211
- import path9 from "path";
220
+ import path10 from "path";
212
221
 
213
222
  // src/storage/memory-read-store.ts
214
223
  import { lstat, readdir, realpath, stat } from "fs/promises";
215
224
  import path2 from "path";
225
+
226
+ // src/storage/memory-frontmatter-metadata.ts
227
+ var rawFrontmatterByMemory = /* @__PURE__ */ new WeakMap();
228
+ function extractRawFrontmatter(raw) {
229
+ return raw.match(/^---\n([\s\S]*?)\n---\n?/)?.[1] ?? null;
230
+ }
231
+ function rememberRawFrontmatter(owner, raw) {
232
+ const frontmatter = extractRawFrontmatter(raw);
233
+ if (frontmatter !== null) rawFrontmatterByMemory.set(owner, frontmatter);
234
+ return owner;
235
+ }
236
+ function readRawFrontmatter(owner) {
237
+ return rawFrontmatterByMemory.get(owner);
238
+ }
239
+
240
+ // src/storage/memory-read-store.ts
216
241
  function isPropagatableReadError(err) {
217
242
  const code = err.code;
218
243
  return typeof code === "string" && code !== "ENOENT";
@@ -491,7 +516,7 @@ var MemoryReadStore = class {
491
516
  const raw = await readMaybeEncryptedFile(filePath, this.deps._secureStoreKey, this.deps.baseDir);
492
517
  const parsed = parseFrontmatter(raw);
493
518
  if (parsed) {
494
- return {
519
+ return rememberRawFrontmatter({
495
520
  path: filePath,
496
521
  frontmatter: normalizeFrontmatterForPath(
497
522
  parsed.frontmatter,
@@ -499,7 +524,7 @@ var MemoryReadStore = class {
499
524
  parsed.content
500
525
  ),
501
526
  content: parsed.content
502
- };
527
+ }, raw);
503
528
  }
504
529
  const normalizedPath = filePath.split(path2.sep).join("/");
505
530
  if (normalizedPath.includes("/entities/") && filePath.endsWith(".md")) {
@@ -714,10 +739,10 @@ var MARKDOWN_LIST_ITEM_CAN_INTERRUPT = /^(?:[-+*]|1[.)])[ \t]+/;
714
739
  var MARKDOWN_THEMATIC_BREAK = /^(?:(?:\*[ \t]*){3,}|(?:-[ \t]*){3,}|(?:_[ \t]*){3,})$/;
715
740
  var MARKDOWN_SETEXT_UNDERLINE = /^(?:=+|-+)$/;
716
741
  var MARKDOWN_BLOCK_QUOTE = /^>/;
717
- var MARKDOWN_LINK_REFERENCE = /^\[(?:\\.|[^\\\[\]])+\]:\s*(?:<[^>\n]*>|([^\s]+))(?:\s+(?:"[^"\n]*"|'[^'\n]*'|\([^)\n]*\)))?$/;
718
- var MARKDOWN_LINK_REFERENCE_LABEL = /^\[(?:\\.|[^\\\[\]])+\]:\s*$/;
742
+ var MARKDOWN_LINK_REFERENCE = /^\[(?:\\.|[^\\\[\]])+\]:[ \t]*(?:<[^>\n]*>|([^\s]+))(?:[ \t]+(?:"[^"\n]*"|'[^'\n]*'|\([^)\n]*\)))?$/;
743
+ var MARKDOWN_LINK_REFERENCE_LABEL = /^\[(?:\\.|[^\\\[\]])+\]:[ \t]*$/;
719
744
  var MARKDOWN_LINK_REFERENCE_CONTINUATION = /^ {1,3}(?:"[^"\n]*"|'[^'\n]*'|\([^)\n]*\))$/;
720
- var MARKDOWN_LINK_REFERENCE_DESTINATION_CONTINUATION = /^ {1,3}(?:<[^>\n]*>|(?!["'(])[^\s]+(?:\s+(?:"[^"\n]*"|'[^'\n]*'|\([^)\n]*\)))?)$/;
745
+ var MARKDOWN_LINK_REFERENCE_DESTINATION_CONTINUATION = /^ {1,3}(?:<[^>\n]*>|(?!["'(])[^\s]+(?:[ \t]+(?:"[^"\n]*"|'[^'\n]*'|\([^)\n]*\)))?)$/;
721
746
  var UTF8_BOM = "\uFEFF";
722
747
  function isLastUpdatedHeader(line) {
723
748
  const withoutBom = line.startsWith(UTF8_BOM) ? line.slice(1) : line;
@@ -1036,7 +1061,7 @@ function shouldCloseHtmlBlock(line, endMarker) {
1036
1061
  function canStartGenericHtmlBlock(lines, index, previousHtmlTerminator) {
1037
1062
  const previousLine = lines[index - 1]?.content.trim() ?? "";
1038
1063
  if (previousLine === "") return true;
1039
- return isMetadataBoundary(previousLine, previousHtmlTerminator) && !isLastUpdatedHeader(previousLine) && !MARKDOWN_LIST_ITEM.test(previousLine) && !MARKDOWN_BLOCK_QUOTE.test(previousLine);
1064
+ return isCompletedIndentedCodeBlock(lines, index) || isMetadataBoundary(previousLine, previousHtmlTerminator) && !isLastUpdatedHeader(previousLine) && !MARKDOWN_LIST_ITEM.test(previousLine) && !MARKDOWN_BLOCK_QUOTE.test(previousLine);
1040
1065
  }
1041
1066
  function isHtmlBlockBoundary(lines, index, htmlTerminatorIndexes) {
1042
1067
  if (htmlTerminatorIndexes.has(index)) return true;
@@ -1392,8 +1417,748 @@ function selfDeps(self) {
1392
1417
  }
1393
1418
 
1394
1419
  // src/storage/entity-store.ts
1395
- import { readdir as readdir2, unlink } from "fs/promises";
1420
+ import { readdir as readdir3, unlink as unlink2 } from "fs/promises";
1421
+ import path4 from "path";
1422
+
1423
+ // src/storage/entity-canonical-id-migration.ts
1424
+ import { randomUUID } from "crypto";
1425
+ import {
1426
+ access,
1427
+ lstat as lstat2,
1428
+ readFile,
1429
+ readdir as readdir2,
1430
+ realpath as realpath2,
1431
+ rename,
1432
+ stat as statFile,
1433
+ unlink,
1434
+ writeFile
1435
+ } from "fs/promises";
1396
1436
  import path3 from "path";
1437
+ import { readFileSync } from "fs";
1438
+ import { z } from "zod";
1439
+ var ENTITY_CANONICAL_ID_MIGRATION_VERSION = 1;
1440
+ var ENTITY_CANONICAL_ID_MIGRATION_FILE = "entity-canonical-id-migration-v1.json";
1441
+ var ENTITY_CANONICAL_ID_MIGRATION_LOCK_STALE_MS = 6e4;
1442
+ var ENTITY_CANONICAL_ID_MIGRATION_LOCK_MAX_WAIT_MS = 3e5;
1443
+ var TOMBSTONE_LOCK_STALE_MS = 3e4;
1444
+ var TOMBSTONE_LOCK_MAX_WAIT_MS = 5e3;
1445
+ var ENTITY_CANONICAL_ID_MUTATION_LOCK_STALE_MS = 6e4;
1446
+ var ENTITY_CANONICAL_ID_MUTATION_LOCK_MAX_WAIT_MS = 3e5;
1447
+ var MEMORY_REWRITE_MAX_PASSES = 3;
1448
+ var ENTITY_MAPPING_RESCAN_MAX_PASSES = 3;
1449
+ function loadHistoricalEntityCanonicalIds(stateDir) {
1450
+ const statePath2 = path3.join(stateDir, ENTITY_CANONICAL_ID_MIGRATION_FILE);
1451
+ try {
1452
+ const parsed = JSON.parse(readFileSync(statePath2, "utf-8"));
1453
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
1454
+ const mappings = parsed.mappings;
1455
+ if (!mappings || typeof mappings !== "object" || Array.isArray(mappings)) return {};
1456
+ const cleaned = {};
1457
+ for (const [legacyId, canonicalId] of Object.entries(mappings)) {
1458
+ if (legacyId.length > 0 && typeof canonicalId === "string" && canonicalId.length > 0) {
1459
+ cleaned[legacyId] = canonicalId;
1460
+ }
1461
+ }
1462
+ return cleaned;
1463
+ } catch {
1464
+ return {};
1465
+ }
1466
+ }
1467
+ function resolveHistoricalEntityCanonicalId(normalized, mappings) {
1468
+ let current = normalized;
1469
+ const seen = /* @__PURE__ */ new Set();
1470
+ while (!seen.has(current)) {
1471
+ seen.add(current);
1472
+ const next = mappings[current];
1473
+ if (!next || next === current) break;
1474
+ current = next;
1475
+ }
1476
+ return current;
1477
+ }
1478
+ var EntityCanonicalIdMigrationStateSchema = z.object({
1479
+ version: z.literal(ENTITY_CANONICAL_ID_MIGRATION_VERSION),
1480
+ complete: z.boolean(),
1481
+ mappings: z.record(z.string().min(1))
1482
+ });
1483
+ async function fingerprintPath(filePath) {
1484
+ let fileStat;
1485
+ try {
1486
+ fileStat = await lstat2(filePath);
1487
+ } catch (error) {
1488
+ if (!isErrnoCode(error, "ENOENT")) throw error;
1489
+ }
1490
+ return fileStat ? `${fileStat.dev}:${fileStat.ino}:${fileStat.mtimeMs}:${fileStat.ctimeMs}:${fileStat.size}` : "missing";
1491
+ }
1492
+ async function getFingerprint(baseDir, entitiesDir, getCorpusScanVersion) {
1493
+ const [entityFingerprint, aliasFingerprint] = await Promise.all([
1494
+ fingerprintPath(entitiesDir),
1495
+ fingerprintPath(path3.join(baseDir, "config", "aliases.json"))
1496
+ ]);
1497
+ return `${entityFingerprint}:${aliasFingerprint}:${getCorpusScanVersion()}`;
1498
+ }
1499
+ async function validateRoots(baseDir, entitiesDir, stateDir, archiveDir) {
1500
+ let baseStat;
1501
+ try {
1502
+ baseStat = await lstat2(baseDir);
1503
+ } catch (error) {
1504
+ if (isErrnoCode(error, "ENOENT")) return;
1505
+ throw error;
1506
+ }
1507
+ if (baseStat.isSymbolicLink() || !baseStat.isDirectory()) {
1508
+ throw new Error(`Refusing entity canonical-id migration through unsafe memory root: ${baseDir}.`);
1509
+ }
1510
+ const memoryRoot = await realpath2(baseDir);
1511
+ const roots = [
1512
+ entitiesDir,
1513
+ stateDir,
1514
+ ...RECALL_FALLBACK_DIRS.map((directory) => path3.join(baseDir, directory)),
1515
+ path3.join(baseDir, "cold"),
1516
+ archiveDir
1517
+ ];
1518
+ for (const root of roots) {
1519
+ let rootStat;
1520
+ try {
1521
+ rootStat = await lstat2(root);
1522
+ } catch (error) {
1523
+ if (isErrnoCode(error, "ENOENT")) continue;
1524
+ throw error;
1525
+ }
1526
+ if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) {
1527
+ throw new Error(`Refusing entity canonical-id migration through unsafe memory root: ${root}.`);
1528
+ }
1529
+ assertPathInsideRoot(memoryRoot, await realpath2(root), root);
1530
+ }
1531
+ }
1532
+ function statePath(deps) {
1533
+ return path3.join(deps.stateDir, ENTITY_CANONICAL_ID_MIGRATION_FILE);
1534
+ }
1535
+ async function assertSafeMigrationStateFile(deps) {
1536
+ const migrationStatePath = statePath(deps);
1537
+ let fileStat;
1538
+ try {
1539
+ fileStat = await lstat2(migrationStatePath);
1540
+ } catch (error) {
1541
+ if (isErrnoCode(error, "ENOENT")) return;
1542
+ throw error;
1543
+ }
1544
+ if (fileStat.isSymbolicLink() || !fileStat.isFile()) {
1545
+ throw new Error(
1546
+ `Refusing entity canonical-id migration through unsafe migration state file: ${migrationStatePath}.`
1547
+ );
1548
+ }
1549
+ const [stateRoot, stateFile] = await Promise.all([
1550
+ realpath2(deps.stateDir),
1551
+ realpath2(migrationStatePath)
1552
+ ]);
1553
+ assertPathInsideRoot(stateRoot, stateFile, migrationStatePath);
1554
+ }
1555
+ async function assertSafeTombstoneFile(deps, tombstonePath) {
1556
+ let fileStat;
1557
+ try {
1558
+ fileStat = await lstat2(tombstonePath);
1559
+ } catch (error) {
1560
+ if (isErrnoCode(error, "ENOENT")) return false;
1561
+ throw error;
1562
+ }
1563
+ if (fileStat.isSymbolicLink() || !fileStat.isFile()) {
1564
+ throw new Error(
1565
+ `Refusing entity canonical-id migration through unsafe tombstone ledger: ${tombstonePath}.`
1566
+ );
1567
+ }
1568
+ const [stateRoot, tombstoneFile] = await Promise.all([
1569
+ realpath2(deps.stateDir),
1570
+ realpath2(tombstonePath)
1571
+ ]);
1572
+ assertPathInsideRoot(stateRoot, tombstoneFile, tombstonePath);
1573
+ return true;
1574
+ }
1575
+ function lockPath(deps) {
1576
+ return path3.join(deps.stateDir, "entity-canonical-id-migration.lock");
1577
+ }
1578
+ async function withEntityCanonicalMutationLock(stateDir, task) {
1579
+ return withHeldFileLock(
1580
+ path3.join(stateDir, "entity-canonical-id-mutation.lock"),
1581
+ {
1582
+ staleMs: ENTITY_CANONICAL_ID_MUTATION_LOCK_STALE_MS,
1583
+ maxWaitMs: ENTITY_CANONICAL_ID_MUTATION_LOCK_MAX_WAIT_MS
1584
+ },
1585
+ async (acquired, lock) => {
1586
+ if (!acquired) throw new Error("Timed out waiting for entity mutation lock.");
1587
+ return task(() => lock.refresh());
1588
+ }
1589
+ );
1590
+ }
1591
+ async function readState(deps) {
1592
+ await assertSafeMigrationStateFile(deps);
1593
+ let raw;
1594
+ try {
1595
+ raw = await readFile(statePath(deps), "utf-8");
1596
+ } catch (error) {
1597
+ if (isErrnoCode(error, "ENOENT")) return null;
1598
+ throw error;
1599
+ }
1600
+ let parsed;
1601
+ try {
1602
+ parsed = JSON.parse(raw);
1603
+ } catch {
1604
+ throw new Error("Invalid entity canonical-id migration state.");
1605
+ }
1606
+ const result = EntityCanonicalIdMigrationStateSchema.safeParse(parsed);
1607
+ if (!result.success) throw new Error("Invalid entity canonical-id migration state.");
1608
+ return result.data;
1609
+ }
1610
+ async function writeState(deps, state) {
1611
+ const destination = statePath(deps);
1612
+ const temporary = `${destination}.${process.pid}.${randomUUID()}.tmp`;
1613
+ try {
1614
+ await writeFile(temporary, `${JSON.stringify(state, null, 2)}
1615
+ `, "utf-8");
1616
+ await rename(temporary, destination);
1617
+ } finally {
1618
+ await unlink(temporary).catch(() => void 0);
1619
+ }
1620
+ }
1621
+ async function fileExists(filePath) {
1622
+ try {
1623
+ await access(filePath);
1624
+ return true;
1625
+ } catch (error) {
1626
+ if (isErrnoCode(error, "ENOENT")) return false;
1627
+ throw error;
1628
+ }
1629
+ }
1630
+ async function sameFileIdentity(leftPath, rightPath) {
1631
+ try {
1632
+ const [left, right] = await Promise.all([statFile(leftPath), statFile(rightPath)]);
1633
+ return left.dev === right.dev && left.ino === right.ino;
1634
+ } catch (error) {
1635
+ if (isErrnoCode(error, "ENOENT")) return false;
1636
+ throw error;
1637
+ }
1638
+ }
1639
+ function assertSafeEntityId(entityId) {
1640
+ if (/[\/\\\0]/.test(entityId)) {
1641
+ throw new Error(`Refusing entity canonical-id migration through unsafe entity id: ${entityId}.`);
1642
+ }
1643
+ }
1644
+ async function assertNotSymlink(filePath, label) {
1645
+ let stat4;
1646
+ try {
1647
+ stat4 = await lstat2(filePath);
1648
+ } catch (error) {
1649
+ if (isErrnoCode(error, "ENOENT")) return;
1650
+ throw error;
1651
+ }
1652
+ if (stat4.isSymbolicLink()) {
1653
+ throw new Error(`Refusing entity canonical-id migration through symlink: ${label}.`);
1654
+ }
1655
+ }
1656
+ async function assertNotMemorySymlink(filePath) {
1657
+ let stat4;
1658
+ try {
1659
+ stat4 = await lstat2(filePath);
1660
+ } catch (error) {
1661
+ if (isErrnoCode(error, "ENOENT")) return;
1662
+ throw error;
1663
+ }
1664
+ if (stat4.isSymbolicLink()) {
1665
+ throw new Error(`Refusing entity canonical-id migration through symlinked memory: ${filePath}.`);
1666
+ }
1667
+ }
1668
+ async function assertEntityContentUnchanged(deps, filePath, expectedContent, legacyId) {
1669
+ const latestContent = await deps.readStorageSecureFile(filePath);
1670
+ if (latestContent !== expectedContent) {
1671
+ throw new Error(`Legacy entity id ${legacyId} changed while migration was running; retry migration.`);
1672
+ }
1673
+ }
1674
+ async function readSafeEntityEntries(entitiesDir) {
1675
+ const rootStat = await lstat2(entitiesDir);
1676
+ if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) {
1677
+ throw new Error("Refusing entity canonical-id migration through a symlinked or non-directory entities root.");
1678
+ }
1679
+ const entries = await readdir2(entitiesDir);
1680
+ for (const entry of entries) {
1681
+ await assertNotSymlink(path3.join(entitiesDir, entry), entry);
1682
+ }
1683
+ return entries;
1684
+ }
1685
+ async function discoverMappings(deps, knownMappings = {}) {
1686
+ const mappings = {};
1687
+ const canonicalOwners = /* @__PURE__ */ new Map();
1688
+ const entityEntries = await readSafeEntityEntries(deps.entitiesDir);
1689
+ for (const entry of entityEntries) {
1690
+ if (!entry.endsWith(".md")) continue;
1691
+ const legacyId = entry.slice(0, -".md".length);
1692
+ assertSafeEntityId(legacyId);
1693
+ const legacyPath = deps.resolveEntityFilePath(legacyId);
1694
+ if (legacyPath === null) continue;
1695
+ const entityContent = await deps.readStorageSecureFile(legacyPath);
1696
+ if (!/^#[ \t]+[^\r\n \t]/m.test(entityContent) || !/^\*\*Type:\*\*[ \t]*[^\r\n \t]/m.test(entityContent)) {
1697
+ throw new Error(`Cannot migrate malformed entity file ${entry}: missing name heading or type.`);
1698
+ }
1699
+ const entity = deps.parseEntityFile(entityContent);
1700
+ if (!entity.name.trim() || !entity.type.trim()) {
1701
+ throw new Error(`Cannot migrate malformed entity file ${entry}: missing name or type.`);
1702
+ }
1703
+ const canonicalId = deps.normalizeEntityName(entity.name, entity.type);
1704
+ assertSafeEntityId(canonicalId);
1705
+ if (legacyId === canonicalId) continue;
1706
+ const canonicalPath = deps.resolveEntityFilePath(canonicalId);
1707
+ if (canonicalPath === null) continue;
1708
+ const canonicalExists = await fileExists(canonicalPath);
1709
+ if (canonicalExists && await sameFileIdentity(legacyPath, canonicalPath) && knownMappings[legacyId] === canonicalId) continue;
1710
+ if (canonicalExists) {
1711
+ const canonicalContent2 = await deps.readStorageSecureFile(canonicalPath);
1712
+ if (entityContent !== canonicalContent2) {
1713
+ throw new Error(`Cannot migrate legacy entity id ${legacyId}: ${canonicalId} already exists.`);
1714
+ }
1715
+ }
1716
+ const previousOwner = canonicalOwners.get(canonicalId);
1717
+ if (previousOwner !== void 0 && previousOwner !== legacyId) {
1718
+ throw new Error(
1719
+ `Cannot migrate legacy entity ids ${previousOwner} and ${legacyId}: both normalize to ${canonicalId}.`
1720
+ );
1721
+ }
1722
+ canonicalOwners.set(canonicalId, legacyId);
1723
+ mappings[legacyId] = canonicalId;
1724
+ }
1725
+ return mappings;
1726
+ }
1727
+ async function rewriteReferences(deps, mappings, refreshLock) {
1728
+ let rewroteColdMemory = false;
1729
+ for (let pass = 0; pass < MEMORY_REWRITE_MAX_PASSES; pass += 1) {
1730
+ deps.invalidateAllMemoriesCache();
1731
+ deps.invalidateColdMemoriesCache();
1732
+ const [hotMemories, coldMemories, archivedMemories] = await Promise.all([
1733
+ deps.readAllMemories(),
1734
+ deps.readAllColdMemories(),
1735
+ deps.readArchivedMemories()
1736
+ ]);
1737
+ const seenPaths = /* @__PURE__ */ new Set();
1738
+ let rewroteAny = false;
1739
+ for (const memory of [...hotMemories, ...coldMemories, ...archivedMemories]) {
1740
+ const memoryPath = path3.resolve(memory.path);
1741
+ if (seenPaths.has(memoryPath)) continue;
1742
+ seenPaths.add(memoryPath);
1743
+ const previousEntityRef = memory.frontmatter.entityRef;
1744
+ const canonicalId = previousEntityRef ? mappings[previousEntityRef] : void 0;
1745
+ if (!previousEntityRef || !canonicalId) continue;
1746
+ await assertNotMemorySymlink(memory.path);
1747
+ const observedMemoryFingerprint = await fingerprintPath(memory.path);
1748
+ if (observedMemoryFingerprint === "missing") continue;
1749
+ if (!await refreshLock()) throw new Error("Lost entity canonical-id migration lock.");
1750
+ const latestMemory = await deps.readMemoryByPath(memory.path);
1751
+ if (!latestMemory) continue;
1752
+ const latestMemoryFingerprint = await fingerprintPath(latestMemory.path);
1753
+ if (latestMemoryFingerprint !== observedMemoryFingerprint) continue;
1754
+ const latestPreviousEntityRef = latestMemory.frontmatter.entityRef;
1755
+ const latestCanonicalId = latestPreviousEntityRef ? mappings[latestPreviousEntityRef] : void 0;
1756
+ if (!latestPreviousEntityRef || !latestCanonicalId) continue;
1757
+ const memoryEncrypted = await deps.isEncryptedStorageFile(latestMemory.path);
1758
+ if (await fingerprintPath(latestMemory.path) !== latestMemoryFingerprint) continue;
1759
+ await deps.snapshotBeforeWrite(latestMemory.path, "write");
1760
+ if (await fingerprintPath(latestMemory.path) !== latestMemoryFingerprint) continue;
1761
+ await deps.writeStorageSecureFile(
1762
+ latestMemory.path,
1763
+ deps.serializeMemoryWithEntityRef(latestMemory, latestCanonicalId),
1764
+ memoryEncrypted
1765
+ );
1766
+ await deps.rewriteProjectedMemoryEntityReference(
1767
+ latestMemory.frontmatter.id,
1768
+ latestPreviousEntityRef,
1769
+ latestCanonicalId
1770
+ );
1771
+ rewroteAny = true;
1772
+ rewroteColdMemory ||= latestMemory.path.includes(`${path3.sep}cold${path3.sep}`);
1773
+ }
1774
+ if (!rewroteAny) return { rewroteColdMemory };
1775
+ }
1776
+ throw new Error("Memory references changed while entity canonical-id migration was running; retry migration.");
1777
+ }
1778
+ function rewriteTombstoneLine(line, mappings, normalizedMappings) {
1779
+ let parsed;
1780
+ try {
1781
+ parsed = JSON.parse(line);
1782
+ } catch {
1783
+ return line;
1784
+ }
1785
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return line;
1786
+ const tombstone = parsed;
1787
+ let changed = false;
1788
+ if (typeof tombstone.entityRef === "string") {
1789
+ const canonicalId = mappings[tombstone.entityRef];
1790
+ if (canonicalId) {
1791
+ tombstone.entityRef = canonicalId;
1792
+ changed = true;
1793
+ }
1794
+ }
1795
+ if (typeof tombstone.supersessionKey === "string") {
1796
+ const separator = tombstone.supersessionKey.indexOf("::");
1797
+ if (separator < 0) return changed ? JSON.stringify(tombstone) : line;
1798
+ const normalizedLegacyId = normalizeSupersessionKey(tombstone.supersessionKey.slice(0, separator));
1799
+ const canonicalId = normalizedMappings.get(normalizedLegacyId);
1800
+ if (canonicalId) {
1801
+ const canonicalKey = computeSupersessionKey(canonicalId, tombstone.supersessionKey.slice(separator + 2));
1802
+ if (canonicalKey) {
1803
+ tombstone.supersessionKey = canonicalKey;
1804
+ changed = true;
1805
+ }
1806
+ }
1807
+ }
1808
+ return changed ? JSON.stringify(tombstone) : line;
1809
+ }
1810
+ async function rewriteTombstoneReferences(deps, mappings, refreshLock) {
1811
+ const tombstonePath = path3.join(deps.stateDir, "tombstones.jsonl");
1812
+ const normalizedMappings = /* @__PURE__ */ new Map();
1813
+ for (const [legacyId, canonicalId] of Object.entries(mappings)) {
1814
+ const normalizedLegacyId = normalizeSupersessionKey(legacyId);
1815
+ if (normalizedLegacyId && !normalizedMappings.has(normalizedLegacyId)) {
1816
+ normalizedMappings.set(normalizedLegacyId, canonicalId);
1817
+ }
1818
+ }
1819
+ await withHeldFileLock(
1820
+ path3.join(deps.stateDir, "tombstones.lock"),
1821
+ {
1822
+ staleMs: TOMBSTONE_LOCK_STALE_MS,
1823
+ maxWaitMs: TOMBSTONE_LOCK_MAX_WAIT_MS
1824
+ },
1825
+ async (acquired, tombstoneLock) => {
1826
+ if (!acquired) throw new Error("Timed out waiting for active tombstone migration.");
1827
+ if (!await assertSafeTombstoneFile(deps, tombstonePath)) return;
1828
+ const tombstoneEncrypted = await deps.isEncryptedStorageFile(tombstonePath);
1829
+ const original = await deps.readStorageSecureFile(tombstonePath);
1830
+ let changed = false;
1831
+ const rewritten = original.split("\n").map((line) => {
1832
+ const next = rewriteTombstoneLine(line, mappings, normalizedMappings);
1833
+ changed ||= next !== line;
1834
+ return next;
1835
+ }).join("\n");
1836
+ if (!changed) return;
1837
+ if (!await refreshLock()) throw new Error("Lost entity canonical-id migration lock.");
1838
+ if (!await tombstoneLock.refresh()) throw new Error("Lost tombstone migration lock.");
1839
+ await deps.snapshotBeforeWrite(tombstonePath, "write");
1840
+ await deps.writeStorageSecureFile(tombstonePath, rewritten, tombstoneEncrypted);
1841
+ }
1842
+ );
1843
+ }
1844
+ async function rewriteRelationshipTargets(deps, mappings, refreshLock) {
1845
+ let rewritten = false;
1846
+ const entries = await readSafeEntityEntries(deps.entitiesDir);
1847
+ for (const entry of entries) {
1848
+ if (!entry.endsWith(".md")) continue;
1849
+ const entityPath = deps.resolveEntityFilePath(entry.slice(0, -".md".length));
1850
+ if (entityPath === null) continue;
1851
+ const observedEntityFingerprint = await fingerprintPath(entityPath);
1852
+ if (observedEntityFingerprint === "missing") continue;
1853
+ const entity = deps.parseEntityFile(await deps.readStorageSecureFile(entityPath));
1854
+ const relationships = entity.relationships.map((relationship) => {
1855
+ const target = mappings[relationship.target];
1856
+ return target ? { ...relationship, target } : relationship;
1857
+ });
1858
+ if (relationships.every((relationship, index) => relationship === entity.relationships[index])) continue;
1859
+ const rewroteEntity = await withEntityCanonicalMutationLock(
1860
+ deps.stateDir,
1861
+ async (refreshEntityLock) => {
1862
+ if (!await refreshLock()) throw new Error("Lost entity canonical-id migration lock.");
1863
+ const latestEntity = deps.parseEntityFile(await deps.readStorageSecureFile(entityPath));
1864
+ if (await fingerprintPath(entityPath) !== observedEntityFingerprint) return false;
1865
+ const latestRelationships = latestEntity.relationships.map((relationship) => {
1866
+ const target = mappings[relationship.target];
1867
+ return target ? { ...relationship, target } : relationship;
1868
+ });
1869
+ if (latestRelationships.every((relationship, index) => relationship === latestEntity.relationships[index])) {
1870
+ return false;
1871
+ }
1872
+ const entityEncrypted = await deps.isEncryptedStorageFile(entityPath);
1873
+ if (!await refreshEntityLock()) throw new Error("Lost entity mutation lock.");
1874
+ if (await fingerprintPath(entityPath) !== observedEntityFingerprint) return false;
1875
+ await deps.snapshotBeforeWrite(entityPath, "write");
1876
+ if (await fingerprintPath(entityPath) !== observedEntityFingerprint) return false;
1877
+ await deps.writeStorageSecureFile(
1878
+ entityPath,
1879
+ deps.serializeEntityFile({ ...latestEntity, relationships: latestRelationships }),
1880
+ entityEncrypted
1881
+ );
1882
+ return true;
1883
+ }
1884
+ );
1885
+ rewritten ||= rewroteEntity;
1886
+ }
1887
+ return rewritten;
1888
+ }
1889
+ async function rewriteKnownReferences(deps, mappings, refreshLock) {
1890
+ await rewriteRelationshipTargets(deps, mappings, refreshLock);
1891
+ let rewroteColdMemory = (await rewriteReferences(deps, mappings, refreshLock)).rewroteColdMemory;
1892
+ await rewriteTombstoneReferences(deps, mappings, refreshLock);
1893
+ await deps.rewriteProjectedEntityReferences(mappings);
1894
+ const finalMemoryPass = await rewriteReferences(deps, mappings, refreshLock);
1895
+ rewroteColdMemory ||= finalMemoryPass.rewroteColdMemory;
1896
+ return rewroteColdMemory;
1897
+ }
1898
+ function wouldCreateMappingCycle(mappings, legacyId, canonicalId) {
1899
+ let current = canonicalId;
1900
+ const seen = /* @__PURE__ */ new Set();
1901
+ while (true) {
1902
+ if (current === legacyId) return true;
1903
+ if (seen.has(current)) return false;
1904
+ seen.add(current);
1905
+ const next = mappings[current];
1906
+ if (!next || next === current) return false;
1907
+ current = next;
1908
+ }
1909
+ }
1910
+ function rejectMappingCycles(existing, discovered) {
1911
+ const accepted = {};
1912
+ const merged = { ...existing };
1913
+ for (const [legacyId, canonicalId] of Object.entries(discovered)) {
1914
+ if (merged[legacyId] === void 0 && wouldCreateMappingCycle(merged, legacyId, canonicalId)) continue;
1915
+ accepted[legacyId] = canonicalId;
1916
+ merged[legacyId] = canonicalId;
1917
+ }
1918
+ return accepted;
1919
+ }
1920
+ function mergeDiscoveredMappings(existing, discovered) {
1921
+ const merged = { ...existing };
1922
+ const canonicalOwners = /* @__PURE__ */ new Map();
1923
+ for (const [legacyId, canonicalId] of Object.entries(discovered)) {
1924
+ const previousMapping = merged[legacyId];
1925
+ if (previousMapping !== void 0 && previousMapping !== canonicalId) {
1926
+ throw new Error(`Legacy entity id ${legacyId} changed canonical target during migration.`);
1927
+ }
1928
+ if (previousMapping === void 0 && wouldCreateMappingCycle(merged, legacyId, canonicalId)) continue;
1929
+ const previousOwner = canonicalOwners.get(canonicalId);
1930
+ if (previousOwner !== void 0 && previousOwner !== legacyId) {
1931
+ throw new Error(
1932
+ `Cannot migrate legacy entity ids ${previousOwner} and ${legacyId}: both normalize to ${canonicalId}.`
1933
+ );
1934
+ }
1935
+ merged[legacyId] = canonicalId;
1936
+ canonicalOwners.set(canonicalId, legacyId);
1937
+ }
1938
+ return merged;
1939
+ }
1940
+ function collapseMappings(mappings) {
1941
+ const collapsed = {};
1942
+ for (const legacyId of Object.keys(mappings)) {
1943
+ let current = legacyId;
1944
+ const seen = /* @__PURE__ */ new Set();
1945
+ while (true) {
1946
+ const next = mappings[current];
1947
+ if (!next || next === current) break;
1948
+ if (seen.has(current)) {
1949
+ throw new Error(`Entity canonical-id migration mapping cycle includes ${legacyId}.`);
1950
+ }
1951
+ seen.add(current);
1952
+ current = next;
1953
+ }
1954
+ if (current !== legacyId) collapsed[legacyId] = current;
1955
+ }
1956
+ return collapsed;
1957
+ }
1958
+ async function migrateEntityFilePair(deps, legacyId, canonicalId, refreshMigrationLock) {
1959
+ return withEntityCanonicalMutationLock(deps.stateDir, async (refreshEntityLock) => {
1960
+ assertSafeEntityId(legacyId);
1961
+ assertSafeEntityId(canonicalId);
1962
+ const legacyPath = deps.resolveEntityFilePath(legacyId);
1963
+ const canonicalPath = deps.resolveEntityFilePath(canonicalId);
1964
+ if (legacyPath === null || canonicalPath === null) {
1965
+ throw new Error("Invalid entity canonical-id migration path.");
1966
+ }
1967
+ await assertNotSymlink(legacyPath, legacyId);
1968
+ await assertNotSymlink(canonicalPath, canonicalId);
1969
+ const legacyExists = await fileExists(legacyPath);
1970
+ const canonicalExists = await fileExists(canonicalPath);
1971
+ if (!legacyExists && !canonicalExists) return { deferred: true, progressed: false };
1972
+ if (legacyExists && canonicalExists) {
1973
+ if (await sameFileIdentity(legacyPath, canonicalPath)) return { deferred: false, progressed: false };
1974
+ const [legacyContent, canonicalContent2, legacyEncrypted, canonicalEncrypted] = await Promise.all([
1975
+ deps.readStorageSecureFile(legacyPath),
1976
+ deps.readStorageSecureFile(canonicalPath),
1977
+ deps.isEncryptedStorageFile(legacyPath),
1978
+ deps.isEncryptedStorageFile(canonicalPath)
1979
+ ]);
1980
+ if (legacyContent !== canonicalContent2) {
1981
+ throw new Error(`Cannot migrate legacy entity id ${legacyId}: ${canonicalId} already exists.`);
1982
+ }
1983
+ if (legacyEncrypted && !canonicalEncrypted) {
1984
+ if (!await refreshMigrationLock() || !await refreshEntityLock()) {
1985
+ throw new Error("Lost entity canonical-id migration lock.");
1986
+ }
1987
+ await deps.snapshotBeforeWrite(canonicalPath, "write");
1988
+ await deps.writeStorageSecureFile(canonicalPath, legacyContent, true);
1989
+ if (await deps.readStorageSecureFile(canonicalPath) !== legacyContent) {
1990
+ throw new Error(`Cannot verify migrated entity id ${canonicalId}.`);
1991
+ }
1992
+ }
1993
+ if (!await refreshMigrationLock() || !await refreshEntityLock()) {
1994
+ throw new Error("Lost entity canonical-id migration lock.");
1995
+ }
1996
+ await deps.snapshotBeforeWrite(legacyPath, "write");
1997
+ await assertNotSymlink(legacyPath, legacyId);
1998
+ await assertEntityContentUnchanged(deps, legacyPath, legacyContent, legacyId);
1999
+ await unlink(legacyPath);
2000
+ return { deferred: false, progressed: true };
2001
+ }
2002
+ if (!legacyExists) return { deferred: false, progressed: false };
2003
+ if (!await refreshMigrationLock() || !await refreshEntityLock()) {
2004
+ throw new Error("Lost entity canonical-id migration lock.");
2005
+ }
2006
+ const entityEncrypted = await deps.isEncryptedStorageFile(legacyPath);
2007
+ const entityContent = await deps.readStorageSecureFile(legacyPath);
2008
+ await assertNotSymlink(legacyPath, legacyId);
2009
+ await assertEntityContentUnchanged(deps, legacyPath, entityContent, legacyId);
2010
+ let canonicalFingerprintAfterWrite = null;
2011
+ try {
2012
+ await deps.writeStorageSecureFile(canonicalPath, entityContent, entityEncrypted);
2013
+ canonicalFingerprintAfterWrite = await fingerprintPath(canonicalPath);
2014
+ if (await deps.readStorageSecureFile(canonicalPath) !== entityContent) {
2015
+ throw new Error(`Cannot verify migrated entity id ${canonicalId}.`);
2016
+ }
2017
+ if (!await refreshMigrationLock() || !await refreshEntityLock()) {
2018
+ throw new Error("Lost entity canonical-id migration lock.");
2019
+ }
2020
+ await deps.snapshotBeforeWrite(legacyPath, "write");
2021
+ await assertNotSymlink(legacyPath, legacyId);
2022
+ await assertEntityContentUnchanged(deps, legacyPath, entityContent, legacyId);
2023
+ await unlink(legacyPath);
2024
+ } catch (error) {
2025
+ if (!canonicalExists && canonicalFingerprintAfterWrite !== null) {
2026
+ try {
2027
+ if (await fingerprintPath(canonicalPath) === canonicalFingerprintAfterWrite) {
2028
+ await assertNotSymlink(canonicalPath, canonicalId);
2029
+ await unlink(canonicalPath);
2030
+ }
2031
+ } catch {
2032
+ }
2033
+ }
2034
+ throw error;
2035
+ }
2036
+ return { deferred: false, progressed: true };
2037
+ });
2038
+ }
2039
+ async function migrateLegacyEntityCanonicalIds(deps) {
2040
+ return withHeldFileLock(
2041
+ lockPath(deps),
2042
+ {
2043
+ staleMs: ENTITY_CANONICAL_ID_MIGRATION_LOCK_STALE_MS,
2044
+ maxWaitMs: ENTITY_CANONICAL_ID_MIGRATION_LOCK_MAX_WAIT_MS
2045
+ },
2046
+ async (acquired, lock) => {
2047
+ if (!acquired) throw new Error("Timed out waiting for active entity canonical-id migration.");
2048
+ await deps.validateMemoryScanRoots?.();
2049
+ await readSafeEntityEntries(deps.entitiesDir);
2050
+ let state = await readState(deps);
2051
+ if (!state) {
2052
+ state = {
2053
+ version: ENTITY_CANONICAL_ID_MIGRATION_VERSION,
2054
+ complete: false,
2055
+ mappings: {}
2056
+ };
2057
+ }
2058
+ const previousMappings = state.mappings;
2059
+ const collapsedMappings = collapseMappings(previousMappings);
2060
+ const mappingsChanged = Object.keys(collapsedMappings).length !== Object.keys(previousMappings).length || Object.entries(collapsedMappings).some(
2061
+ ([legacyId, canonicalId]) => previousMappings[legacyId] !== canonicalId
2062
+ );
2063
+ state = { ...state, mappings: collapsedMappings };
2064
+ for (let migrationPass = 0; migrationPass < ENTITY_MAPPING_RESCAN_MAX_PASSES; migrationPass += 1) {
2065
+ if (!await lock.refresh()) throw new Error("Lost entity canonical-id migration lock.");
2066
+ const discoveredBefore = rejectMappingCycles(
2067
+ state.mappings,
2068
+ await discoverMappings(deps, state.mappings)
2069
+ );
2070
+ const mergedBefore = collapseMappings(mergeDiscoveredMappings(state.mappings, discoveredBefore));
2071
+ if (state.complete && Object.keys(discoveredBefore).length === 0 && !mappingsChanged) {
2072
+ if (Object.keys(state.mappings).length === 0) return deps.readMigrationFingerprint?.();
2073
+ const rewroteColdMemory2 = await rewriteKnownReferences(
2074
+ deps,
2075
+ state.mappings,
2076
+ () => lock.refresh()
2077
+ );
2078
+ deps.invalidateKnowledgeIndexCache();
2079
+ deps.invalidateAllMemoriesCache();
2080
+ if (rewroteColdMemory2) deps.invalidateColdMemoriesCache();
2081
+ deps.bumpMemoryStatusVersion();
2082
+ return deps.readMigrationFingerprint?.();
2083
+ }
2084
+ if (state.complete || Object.keys(discoveredBefore).length > 0 || Object.keys(mergedBefore).length !== Object.keys(state.mappings).length) {
2085
+ state = { ...state, complete: false, mappings: mergedBefore };
2086
+ await writeState(deps, state);
2087
+ }
2088
+ if (Object.keys(state.mappings).length === 0) {
2089
+ if (!await lock.refresh()) throw new Error("Lost entity canonical-id migration lock.");
2090
+ const discoveredAfter2 = rejectMappingCycles(
2091
+ state.mappings,
2092
+ await discoverMappings(deps, state.mappings)
2093
+ );
2094
+ if (Object.keys(discoveredAfter2).length === 0) {
2095
+ await writeState(deps, { ...state, complete: true });
2096
+ return deps.readMigrationFingerprint?.();
2097
+ }
2098
+ state = {
2099
+ ...state,
2100
+ complete: false,
2101
+ mappings: collapseMappings(mergeDiscoveredMappings(state.mappings, discoveredAfter2))
2102
+ };
2103
+ await writeState(deps, state);
2104
+ continue;
2105
+ }
2106
+ let pendingMappings = Object.entries(state.mappings);
2107
+ while (pendingMappings.length > 0) {
2108
+ const deferredMappings = [];
2109
+ let progressed = false;
2110
+ for (const [legacyId, canonicalId] of pendingMappings) {
2111
+ const result = await migrateEntityFilePair(
2112
+ deps,
2113
+ legacyId,
2114
+ canonicalId,
2115
+ () => lock.refresh()
2116
+ );
2117
+ if (result.deferred) {
2118
+ deferredMappings.push([legacyId, canonicalId]);
2119
+ }
2120
+ progressed ||= result.progressed;
2121
+ }
2122
+ if (deferredMappings.length === 0) break;
2123
+ if (!progressed) {
2124
+ const [legacyId, canonicalId] = deferredMappings[0];
2125
+ throw new Error(
2126
+ `Cannot migrate legacy entity id ${legacyId}: both files are missing and no intermediate mapping can advance migration.`
2127
+ );
2128
+ }
2129
+ pendingMappings = deferredMappings;
2130
+ }
2131
+ const rewroteColdMemory = await rewriteKnownReferences(
2132
+ deps,
2133
+ state.mappings,
2134
+ () => lock.refresh()
2135
+ );
2136
+ deps.invalidateKnowledgeIndexCache();
2137
+ deps.invalidateAllMemoriesCache();
2138
+ if (rewroteColdMemory) deps.invalidateColdMemoriesCache();
2139
+ deps.bumpMemoryStatusVersion();
2140
+ if (!await lock.refresh()) throw new Error("Lost entity canonical-id migration lock.");
2141
+ const discoveredAfter = rejectMappingCycles(
2142
+ state.mappings,
2143
+ await discoverMappings(deps, state.mappings)
2144
+ );
2145
+ if (Object.keys(discoveredAfter).length === 0) {
2146
+ await writeState(deps, { ...state, complete: true });
2147
+ return deps.readMigrationFingerprint?.();
2148
+ }
2149
+ state = {
2150
+ ...state,
2151
+ complete: false,
2152
+ mappings: collapseMappings(mergeDiscoveredMappings(state.mappings, discoveredAfter))
2153
+ };
2154
+ await writeState(deps, state);
2155
+ }
2156
+ throw new Error("Entity canonical-id migration mappings changed while migration was running; retry migration.");
2157
+ }
2158
+ );
2159
+ }
2160
+
2161
+ // src/storage/entity-store.ts
1397
2162
  var EntityStore = class {
1398
2163
  constructor(deps) {
1399
2164
  this.deps = deps;
@@ -1405,6 +2170,12 @@ var EntityStore = class {
1405
2170
  }
1406
2171
  async writeEntity(name, type, facts, options = {}) {
1407
2172
  await this.deps.ensureDirectories();
2173
+ return withEntityCanonicalMutationLock(
2174
+ path4.join(this.deps.baseDir, "state"),
2175
+ () => this.writeEntityUnlocked(name, type, facts, options)
2176
+ );
2177
+ }
2178
+ async writeEntityUnlocked(name, type, facts, options = {}) {
1408
2179
  if (typeof name !== "string" || !name.trim() || typeof type !== "string" || !type.trim()) {
1409
2180
  log.warn("writeEntity: invalid entity payload, skipping", {
1410
2181
  nameType: typeof name,
@@ -1421,7 +2192,7 @@ var EntityStore = class {
1421
2192
  log.debug(`fuzzy match: "${normalized}" \u2192 existing "${match}"`);
1422
2193
  normalized = match;
1423
2194
  }
1424
- const filePath = path3.join(this.deps.entitiesDir, `${normalized}.md`);
2195
+ const filePath = path4.join(this.deps.entitiesDir, `${normalized}.md`);
1425
2196
  let entity = {
1426
2197
  name,
1427
2198
  type,
@@ -1522,7 +2293,7 @@ var EntityStore = class {
1522
2293
  /** Return sorted list of entity filenames (without .md extension) */
1523
2294
  async listEntityNames() {
1524
2295
  try {
1525
- const entries = await readdir2(this.deps.entitiesDir);
2296
+ const entries = await readdir3(this.deps.entitiesDir);
1526
2297
  return entries.filter((e) => e.endsWith(".md")).map((e) => e.replace(".md", "")).sort();
1527
2298
  } catch {
1528
2299
  return [];
@@ -1532,7 +2303,13 @@ var EntityStore = class {
1532
2303
  * Set or rewrite the synthesis layer of an entity file.
1533
2304
  */
1534
2305
  async updateEntitySynthesis(name, synthesis, options = {}) {
1535
- const filePath = path3.join(this.deps.entitiesDir, `${name}.md`);
2306
+ return withEntityCanonicalMutationLock(
2307
+ path4.join(this.deps.baseDir, "state"),
2308
+ () => this.updateEntitySynthesisUnlocked(name, synthesis, options)
2309
+ );
2310
+ }
2311
+ async updateEntitySynthesisUnlocked(name, synthesis, options = {}) {
2312
+ const filePath = path4.join(this.deps.entitiesDir, `${name}.md`);
1536
2313
  let entity;
1537
2314
  try {
1538
2315
  const content = await this.deps.readStorageSecureFile(filePath);
@@ -1574,7 +2351,7 @@ var EntityStore = class {
1574
2351
  const cached = getCachedEntities(this.deps.baseDir, currentVersion, cacheKey);
1575
2352
  if (cached) return cached;
1576
2353
  try {
1577
- const entries = await readdir2(this.deps.entitiesDir);
2354
+ const entries = await readdir3(this.deps.entitiesDir);
1578
2355
  const mdFiles = entries.filter((e) => e.endsWith(".md"));
1579
2356
  if (mdFiles.length === 0) return [];
1580
2357
  const BATCH_SIZE = 100;
@@ -1584,7 +2361,7 @@ var EntityStore = class {
1584
2361
  const results = await Promise.all(
1585
2362
  batch.map(async (entry) => {
1586
2363
  try {
1587
- return await this.deps.readStorageSecureFile(path3.join(this.deps.entitiesDir, entry));
2364
+ return await this.deps.readStorageSecureFile(path4.join(this.deps.entitiesDir, entry));
1588
2365
  } catch (err) {
1589
2366
  if (err instanceof SecureStoreLockedError) throw err;
1590
2367
  if (!isErrnoCode(err, "ENOENT")) throw err;
@@ -1657,9 +2434,15 @@ ${rows.join("\n")}
1657
2434
  * Returns count of files merged.
1658
2435
  */
1659
2436
  async mergeFragmentedEntities() {
2437
+ return withEntityCanonicalMutationLock(
2438
+ path4.join(this.deps.baseDir, "state"),
2439
+ () => this.mergeFragmentedEntitiesUnlocked()
2440
+ );
2441
+ }
2442
+ async mergeFragmentedEntitiesUnlocked() {
1660
2443
  let merged = 0;
1661
2444
  try {
1662
- const entries = await readdir2(this.deps.entitiesDir);
2445
+ const entries = await readdir3(this.deps.entitiesDir);
1663
2446
  const mdFiles = entries.filter((e) => e.endsWith(".md"));
1664
2447
  const groups = /* @__PURE__ */ new Map();
1665
2448
  for (const file of mdFiles) {
@@ -1697,7 +2480,7 @@ ${rows.join("\n")}
1697
2480
  extraSections: []
1698
2481
  };
1699
2482
  for (const file of files) {
1700
- const filePath = path3.join(this.deps.entitiesDir, file);
2483
+ const filePath = path4.join(this.deps.entitiesDir, file);
1701
2484
  try {
1702
2485
  const content = await this.deps.readStorageSecureFile(filePath);
1703
2486
  const parsed = parseEntityFile(content, this.deps.entitySchemas);
@@ -1828,13 +2611,13 @@ ${rows.join("\n")}
1828
2611
  }
1829
2612
  mergedEntity.created = mergedEntity.created || mergedEntity.updated || (/* @__PURE__ */ new Date()).toISOString();
1830
2613
  mergedEntity.updated = mergedEntity.updated || (/* @__PURE__ */ new Date()).toISOString();
1831
- const canonicalPath = path3.join(this.deps.entitiesDir, `${canonical}.md`);
2614
+ const canonicalPath = path4.join(this.deps.entitiesDir, `${canonical}.md`);
1832
2615
  await this.deps.writeStorageSecureFile(canonicalPath, serializeEntityFile(mergedEntity, this.deps.entitySchemas));
1833
2616
  for (const file of files) {
1834
- const filePath = path3.join(this.deps.entitiesDir, file);
2617
+ const filePath = path4.join(this.deps.entitiesDir, file);
1835
2618
  if (filePath !== canonicalPath) {
1836
2619
  try {
1837
- await unlink(filePath);
2620
+ await unlink2(filePath);
1838
2621
  merged++;
1839
2622
  log.debug(`merged entity ${file} \u2192 ${canonical}.md`);
1840
2623
  } catch {
@@ -1850,8 +2633,8 @@ ${rows.join("\n")}
1850
2633
  };
1851
2634
 
1852
2635
  // src/storage/identity-continuity-store.ts
1853
- import { readdir as readdir3 } from "fs/promises";
1854
- import path4 from "path";
2636
+ import { readdir as readdir4 } from "fs/promises";
2637
+ import path5 from "path";
1855
2638
  var IdentityContinuityStore = class {
1856
2639
  constructor(deps) {
1857
2640
  this.deps = deps;
@@ -1876,7 +2659,7 @@ var IdentityContinuityStore = class {
1876
2659
  const date = nowIso.slice(0, 10);
1877
2660
  const id = this.deps.generateId("incident");
1878
2661
  const incident = createContinuityIncidentRecord(id, input, nowIso);
1879
- const filePath = path4.join(this.deps.identityIncidentsDir, `${date}-${id}.md`);
2662
+ const filePath = path5.join(this.deps.identityIncidentsDir, `${date}-${id}.md`);
1880
2663
  await this.deps.writeStorageSecureFile(filePath, serializeContinuityIncident(incident));
1881
2664
  return { ...incident, filePath };
1882
2665
  }
@@ -1889,7 +2672,7 @@ var IdentityContinuityStore = class {
1889
2672
  const incidents = [];
1890
2673
  for (const file of candidates) {
1891
2674
  if (incidents.length >= cappedLimit) break;
1892
- const filePath = path4.join(this.deps.identityIncidentsDir, file);
2675
+ const filePath = path5.join(this.deps.identityIncidentsDir, file);
1893
2676
  try {
1894
2677
  const raw = await this.deps.readStorageSecureFile(filePath);
1895
2678
  const parsed = parseContinuityIncident(raw);
@@ -1920,7 +2703,7 @@ var IdentityContinuityStore = class {
1920
2703
  await this.deps.ensureDirectories();
1921
2704
  const safeKey = this.sanitizeIdentityAuditKey(key);
1922
2705
  const dir = period === "weekly" ? this.deps.identityAuditsWeeklyDir : this.deps.identityAuditsMonthlyDir;
1923
- const filePath = path4.join(dir, `${safeKey}.md`);
2706
+ const filePath = path5.join(dir, `${safeKey}.md`);
1924
2707
  await this.deps.writeStorageSecureFile(filePath, content);
1925
2708
  return filePath;
1926
2709
  }
@@ -1928,7 +2711,7 @@ var IdentityContinuityStore = class {
1928
2711
  try {
1929
2712
  const safeKey = this.sanitizeIdentityAuditKey(key);
1930
2713
  const dir = period === "weekly" ? this.deps.identityAuditsWeeklyDir : this.deps.identityAuditsMonthlyDir;
1931
- return await this.deps.readStorageSecureFile(path4.join(dir, `${safeKey}.md`));
2714
+ return await this.deps.readStorageSecureFile(path5.join(dir, `${safeKey}.md`));
1932
2715
  } catch (err) {
1933
2716
  if (err instanceof Error && err.message === "Invalid identity audit key") return null;
1934
2717
  if (!isErrnoCode(err, "ENOENT")) throw err;
@@ -1967,7 +2750,7 @@ var IdentityContinuityStore = class {
1967
2750
  return loop;
1968
2751
  }
1969
2752
  async readContinuityIncidentFileNames() {
1970
- const files = await readdir3(this.deps.identityIncidentsDir);
2753
+ const files = await readdir4(this.deps.identityIncidentsDir);
1971
2754
  return files.filter((file) => file.endsWith(".md")).sort().reverse();
1972
2755
  }
1973
2756
  async readContinuityIncidentFile(filePath) {
@@ -1984,12 +2767,12 @@ var IdentityContinuityStore = class {
1984
2767
  const fileNames = await this.readContinuityIncidentFileNames();
1985
2768
  const directMatch = fileNames.find((name) => name.endsWith(`-${id}.md`));
1986
2769
  if (directMatch) {
1987
- const directPath = path4.join(this.deps.identityIncidentsDir, directMatch);
2770
+ const directPath = path5.join(this.deps.identityIncidentsDir, directMatch);
1988
2771
  const parsed = await this.readContinuityIncidentFile(directPath);
1989
2772
  if (parsed?.id === id) return directPath;
1990
2773
  }
1991
2774
  for (const fileName of fileNames) {
1992
- const filePath = path4.join(this.deps.identityIncidentsDir, fileName);
2775
+ const filePath = path5.join(this.deps.identityIncidentsDir, fileName);
1993
2776
  const parsed = await this.readContinuityIncidentFile(filePath);
1994
2777
  if (parsed?.id === id) return filePath;
1995
2778
  }
@@ -2004,6 +2787,127 @@ var IdentityContinuityStore = class {
2004
2787
  }
2005
2788
  };
2006
2789
 
2790
+ // src/storage/entity-canonical-id-migration-adapter.ts
2791
+ async function runLegacyEntityCanonicalIdMigration(host, parseEntityFile2, serializeEntityFile2, serializeMemoryWithEntityRef2) {
2792
+ const readMigrationFingerprint = () => getFingerprint(host.baseDir, host.entitiesDir, () => host.getCorpusScanVersion());
2793
+ const completionFingerprint = await migrateLegacyEntityCanonicalIds({
2794
+ stateDir: host.stateDir,
2795
+ entitiesDir: host.entitiesDir,
2796
+ normalizeEntityName: host.normalizeEntityName.bind(host),
2797
+ resolveEntityFilePath: host.resolveEntityFilePath.bind(host),
2798
+ readStorageSecureFile: host.readStorageSecureFile.bind(host),
2799
+ writeStorageSecureFile: host.writeStorageSecureFile.bind(host),
2800
+ isEncryptedStorageFile: host.isEncryptedFileHeader.bind(host),
2801
+ snapshotBeforeWrite: host.snapshotBeforeWrite.bind(host),
2802
+ parseEntityFile: parseEntityFile2,
2803
+ serializeEntityFile: serializeEntityFile2,
2804
+ serializeMemoryWithEntityRef: serializeMemoryWithEntityRef2,
2805
+ readMemoryByPath: host.readMemoryByPath.bind(host),
2806
+ readAllMemories: host.readAllMemories.bind(host),
2807
+ readAllColdMemories: host.readAllColdMemories.bind(host),
2808
+ readArchivedMemories: host.readArchivedMemories.bind(host),
2809
+ validateMemoryScanRoots: () => validateRoots(host.baseDir, host.entitiesDir, host.stateDir, host.archiveDir),
2810
+ rewriteProjectedEntityReferences: (mappings) => rewriteProjectedEntityReferences(host.baseDir, mappings),
2811
+ rewriteProjectedMemoryEntityReference: (memoryId, previousEntityRef, nextEntityRef) => rewriteProjectedMemoryEntityReference(host.baseDir, memoryId, previousEntityRef, nextEntityRef),
2812
+ invalidateKnowledgeIndexCache: host.invalidateKnowledgeIndexCache.bind(host),
2813
+ invalidateAllMemoriesCache: host.invalidateAllMemoriesCache.bind(host),
2814
+ invalidateColdMemoriesCache: host.invalidateColdMemoriesCache.bind(host),
2815
+ bumpMemoryStatusVersion: host.bumpMemoryStatusVersion.bind(host),
2816
+ readMigrationFingerprint
2817
+ });
2818
+ return completionFingerprint ?? readMigrationFingerprint();
2819
+ }
2820
+
2821
+ // src/storage/entity-canonical-id-migration-runner.ts
2822
+ var EntityCanonicalIdMigrationRunner = class {
2823
+ constructor(canRun, runMigration, readFingerprint = async () => "static") {
2824
+ this.canRun = canRun;
2825
+ this.runMigration = runMigration;
2826
+ this.readFingerprint = readFingerprint;
2827
+ }
2828
+ canRun;
2829
+ runMigration;
2830
+ readFingerprint;
2831
+ inFlight = null;
2832
+ directoriesInitialized = false;
2833
+ migrationComplete = false;
2834
+ completedFingerprint = null;
2835
+ async markDirectoriesInitialized() {
2836
+ this.directoriesInitialized = true;
2837
+ await this.ensure();
2838
+ }
2839
+ ensure() {
2840
+ if (!this.canRun()) return Promise.resolve();
2841
+ if (this.inFlight) return this.inFlight;
2842
+ const migration = this.runOrReuse();
2843
+ this.inFlight = migration;
2844
+ void migration.then(
2845
+ () => this.clearInFlight(migration),
2846
+ () => this.clearInFlight(migration)
2847
+ );
2848
+ return migration;
2849
+ }
2850
+ triggerAfterUnlock() {
2851
+ if (!this.directoriesInitialized) return Promise.resolve();
2852
+ return this.ensure();
2853
+ }
2854
+ async runOrReuse() {
2855
+ let fingerprintAtStart = await this.readFingerprint();
2856
+ if (this.migrationComplete && fingerprintAtStart === this.completedFingerprint) return;
2857
+ for (let attempt = 0; attempt < 3; attempt += 1) {
2858
+ const completionFingerprint = await this.runMigration();
2859
+ const fingerprintAfterMigration = await this.readFingerprint();
2860
+ const fingerprintAfterStabilityRead = await this.readFingerprint();
2861
+ const returnedFingerprint = typeof completionFingerprint === "string" ? completionFingerprint : fingerprintAfterMigration;
2862
+ if (returnedFingerprint === fingerprintAfterMigration && fingerprintAfterMigration === fingerprintAfterStabilityRead && (typeof completionFingerprint === "string" || fingerprintAfterMigration === fingerprintAtStart)) {
2863
+ this.migrationComplete = true;
2864
+ this.completedFingerprint = fingerprintAfterStabilityRead;
2865
+ return;
2866
+ }
2867
+ fingerprintAtStart = fingerprintAfterStabilityRead;
2868
+ }
2869
+ this.migrationComplete = false;
2870
+ this.completedFingerprint = null;
2871
+ throw new Error("Entity canonical-id migration fingerprint changed while migration was completing; retry migration.");
2872
+ }
2873
+ clearInFlight(migration) {
2874
+ if (this.inFlight === migration) this.inFlight = null;
2875
+ }
2876
+ };
2877
+
2878
+ // src/storage/memory-migration-serialization.ts
2879
+ function serializeMemoryWithEntityRef(memory, entityRef, fallback) {
2880
+ const rawFrontmatter = readRawFrontmatter(memory);
2881
+ if (rawFrontmatter === void 0) return fallback(memory, entityRef);
2882
+ const lines = rawFrontmatter.split("\n");
2883
+ let entityRefLine = -1;
2884
+ for (let index = 0; index < lines.length; index += 1) {
2885
+ if (/^\s*entityRef\s*:/.test(lines[index] ?? "")) entityRefLine = index;
2886
+ }
2887
+ if (entityRefLine >= 0) {
2888
+ const indent = lines[entityRefLine].match(/^\s*/)?.[0] ?? "";
2889
+ lines[entityRefLine] = `${indent}entityRef: ${entityRef}`;
2890
+ } else {
2891
+ lines.push(`entityRef: ${entityRef}`);
2892
+ }
2893
+ return `---
2894
+ ${lines.join("\n")}
2895
+ ---
2896
+
2897
+ ${memory.content}
2898
+ `;
2899
+ }
2900
+ function createMemoryEntityRefSerializer(serializeFrontmatter2) {
2901
+ return (memory, entityRef) => serializeMemoryWithEntityRef(
2902
+ memory,
2903
+ entityRef,
2904
+ (fallbackMemory, fallbackEntityRef) => `${serializeFrontmatter2({ ...fallbackMemory.frontmatter, entityRef: fallbackEntityRef })}
2905
+
2906
+ ${fallbackMemory.content}
2907
+ `
2908
+ );
2909
+ }
2910
+
2007
2911
  // src/utils/yaml-scalar.ts
2008
2912
  function decodeYamlScalar(value) {
2009
2913
  const trimmed = value.trim();
@@ -2019,9 +2923,9 @@ function decodeYamlScalar(value) {
2019
2923
  }
2020
2924
 
2021
2925
  // src/orchestration/qmd-result-resolver.ts
2022
- import path5 from "path";
2926
+ import path6 from "path";
2023
2927
  function qmdCollectionPathParts(resultPath) {
2024
- if (!resultPath || path5.isAbsolute(resultPath)) return null;
2928
+ if (!resultPath || path6.isAbsolute(resultPath)) return null;
2025
2929
  const normalized = resultPath.replace(/\\/g, "/").replace(/^\/+/, "");
2026
2930
  const slashIndex = normalized.indexOf("/");
2027
2931
  if (slashIndex <= 0 || slashIndex >= normalized.length - 1) return null;
@@ -2034,9 +2938,9 @@ function qmdCollectionPathParts(resultPath) {
2034
2938
  }
2035
2939
  function qmdResultPathCandidates(storageDir, resultPath) {
2036
2940
  const candidates = /* @__PURE__ */ new Set();
2037
- const storageRoot = path5.resolve(storageDir);
2941
+ const storageRoot = path6.resolve(storageDir);
2038
2942
  const addCandidate = (candidate) => {
2039
- const resolved = path5.resolve(candidate);
2943
+ const resolved = path6.resolve(candidate);
2040
2944
  if (isPathInsideStorageRoot(storageRoot, resolved)) {
2041
2945
  candidates.add(resolved);
2042
2946
  }
@@ -2044,18 +2948,18 @@ function qmdResultPathCandidates(storageDir, resultPath) {
2044
2948
  const addRelativeCandidates = (relativePath) => {
2045
2949
  const normalized = relativePath.replace(/\\/g, "/").replace(/^\/+/, "");
2046
2950
  if (!normalized) return;
2047
- addCandidate(path5.join(storageRoot, normalized));
2951
+ addCandidate(path6.join(storageRoot, normalized));
2048
2952
  if (/^\d{4}-\d{2}-\d{2}\//.test(normalized)) {
2049
- addCandidate(path5.join(storageRoot, "facts", normalized));
2953
+ addCandidate(path6.join(storageRoot, "facts", normalized));
2050
2954
  }
2051
2955
  };
2052
- if (path5.isAbsolute(resultPath)) {
2956
+ if (path6.isAbsolute(resultPath)) {
2053
2957
  addCandidate(resultPath);
2054
- const relative2 = path5.relative(storageRoot, path5.resolve(resultPath));
2055
- if (relative2 && !relative2.startsWith("..") && !path5.isAbsolute(relative2)) {
2056
- const normalized = relative2.split(path5.sep).join("/");
2958
+ const relative2 = path6.relative(storageRoot, path6.resolve(resultPath));
2959
+ if (relative2 && !relative2.startsWith("..") && !path6.isAbsolute(relative2)) {
2960
+ const normalized = relative2.split(path6.sep).join("/");
2057
2961
  if (/^\d{4}-\d{2}-\d{2}\//.test(normalized)) {
2058
- addCandidate(path5.join(storageRoot, "facts", normalized));
2962
+ addCandidate(path6.join(storageRoot, "facts", normalized));
2059
2963
  }
2060
2964
  }
2061
2965
  } else {
@@ -2090,7 +2994,7 @@ var QmdResultResolver = class {
2090
2994
  const seenStorageDirs = /* @__PURE__ */ new Set();
2091
2995
  const addStorage = (storage) => {
2092
2996
  const storageDir = storageDirOrNull(storage);
2093
- const storageKey = storageDir ? path5.resolve(storageDir) : `storage-without-dir-${storages.length}`;
2997
+ const storageKey = storageDir ? path6.resolve(storageDir) : `storage-without-dir-${storages.length}`;
2094
2998
  if (seenStorageDirs.has(storageKey)) return;
2095
2999
  seenStorageDirs.add(storageKey);
2096
3000
  storages.push(storage);
@@ -2120,7 +3024,7 @@ var QmdResultResolver = class {
2120
3024
  continue;
2121
3025
  }
2122
3026
  try {
2123
- const coldRoot = path5.join(storageDir, "cold");
3027
+ const coldRoot = path6.join(storageDir, "cold");
2124
3028
  for (const candidate of qmdResultPathCandidates(
2125
3029
  coldRoot,
2126
3030
  parts.relativePath
@@ -2179,9 +3083,9 @@ var QmdResultResolver = class {
2179
3083
  error: err.message
2180
3084
  });
2181
3085
  }
2182
- if (!path5.isAbsolute(resultPath)) return null;
3086
+ if (!path6.isAbsolute(resultPath)) return null;
2183
3087
  }
2184
- if (path5.isAbsolute(resultPath)) {
3088
+ if (path6.isAbsolute(resultPath)) {
2185
3089
  if (!fallbackStorageDir) {
2186
3090
  return await fallbackStorage.readMemoryByPath(resultPath);
2187
3091
  }
@@ -2221,7 +3125,7 @@ var QmdResultResolver = class {
2221
3125
  );
2222
3126
  if (!memory) return null;
2223
3127
  let ownerNamespace = null;
2224
- if (path5.isAbsolute(memory.path)) {
3128
+ if (path6.isAbsolute(memory.path)) {
2225
3129
  const ownerStorage = await this.storageForAbsoluteQmdResultPath(
2226
3130
  memory.path,
2227
3131
  fallbackStorage,
@@ -2245,17 +3149,17 @@ var QmdResultResolver = class {
2245
3149
  };
2246
3150
  }
2247
3151
  async storageForAbsoluteQmdResultPath(resultPath, fallbackStorage, recallNamespaces = []) {
2248
- const resolvedPath = path5.resolve(resultPath);
3152
+ const resolvedPath = path6.resolve(resultPath);
2249
3153
  const config = this.getConfig();
2250
- const memoryRoot = path5.resolve(config.memoryDir);
2251
- const namespacesRoot = path5.join(memoryRoot, "namespaces");
3154
+ const memoryRoot = path6.resolve(config.memoryDir);
3155
+ const namespacesRoot = path6.join(memoryRoot, "namespaces");
2252
3156
  const fallbackStorageDir = storageDirOrNull(fallbackStorage);
2253
3157
  const matches = [];
2254
3158
  const seenDirs = /* @__PURE__ */ new Set();
2255
3159
  const maybeAddStorage = (storage, namespace) => {
2256
3160
  const storageDir = storageDirOrNull(storage);
2257
3161
  if (!storageDir) return;
2258
- const candidateRoot = path5.resolve(storageDir);
3162
+ const candidateRoot = path6.resolve(storageDir);
2259
3163
  if (seenDirs.has(candidateRoot)) return;
2260
3164
  if (!isPathInsideStorageRoot(candidateRoot, resolvedPath)) return;
2261
3165
  if (candidateRoot === memoryRoot && isPathInsideStorageRoot(namespacesRoot, resolvedPath)) {
@@ -2273,7 +3177,7 @@ var QmdResultResolver = class {
2273
3177
  candidateNamespaces.add(ns);
2274
3178
  }
2275
3179
  if (isPathInsideStorageRoot(namespacesRoot, resolvedPath)) {
2276
- const relativeToNamespaces = path5.relative(namespacesRoot, resolvedPath);
3180
+ const relativeToNamespaces = path6.relative(namespacesRoot, resolvedPath);
2277
3181
  const [namespaceSegment] = relativeToNamespaces.split(/[\\/]/);
2278
3182
  if (namespaceSegment) {
2279
3183
  candidateNamespaces.add(
@@ -2922,7 +3826,7 @@ function fuseDay(date, inputs, options = {}) {
2922
3826
 
2923
3827
  // src/wearables/fusion/store.ts
2924
3828
  import { createHash as createHash2 } from "crypto";
2925
- import * as path6 from "path";
3829
+ import * as path7 from "path";
2926
3830
  var FUSION_KIND = "wearable-fusion";
2927
3831
  function hashFusionBody(conversations) {
2928
3832
  return createHash2("sha256").update(JSON.stringify(conversations), "utf-8").digest("hex");
@@ -3109,7 +4013,7 @@ var FusionArtifactStore = class {
3109
4013
  `invalid wearable fusion date '${String(date)}' \u2014 expected YYYY-MM-DD`
3110
4014
  );
3111
4015
  }
3112
- return path6.join(this.wearablesDir, FUSION_DIR_NAME, `${date}.md`);
4016
+ return path7.join(this.wearablesDir, FUSION_DIR_NAME, `${date}.md`);
3113
4017
  }
3114
4018
  async writeFusedDay(date, serialized) {
3115
4019
  const filePath = this.fusedDayPath(date);
@@ -3146,7 +4050,7 @@ var FusionArtifactStore = class {
3146
4050
  }
3147
4051
  /** List dates with stored fused artifacts, newest first. */
3148
4052
  async listFusedDays() {
3149
- const fusionDir = path6.join(this.wearablesDir, FUSION_DIR_NAME);
4053
+ const fusionDir = path7.join(this.wearablesDir, FUSION_DIR_NAME);
3150
4054
  await this.assertPathContained(fusionDir);
3151
4055
  let entries;
3152
4056
  try {
@@ -3190,10 +4094,10 @@ var FusionArtifactStore = class {
3190
4094
  try {
3191
4095
  rootReal = await this.io.realpath(this.memoryDir);
3192
4096
  } catch {
3193
- rootReal = path6.resolve(this.memoryDir);
4097
+ rootReal = path7.resolve(this.memoryDir);
3194
4098
  }
3195
4099
  await this.assertNoEscape(rootReal, this.wearablesDir);
3196
- await this.assertNoEscape(rootReal, path6.dirname(targetPath));
4100
+ await this.assertNoEscape(rootReal, path7.dirname(targetPath));
3197
4101
  await this.assertNoEscape(rootReal, targetPath);
3198
4102
  await this.assertFusionDirNotSymlinked();
3199
4103
  }
@@ -3207,7 +4111,7 @@ var FusionArtifactStore = class {
3207
4111
  * (a fresh write creates a real directory lexically under the root).
3208
4112
  */
3209
4113
  async assertFusionDirNotSymlinked() {
3210
- const fusionDir = path6.join(this.wearablesDir, FUSION_DIR_NAME);
4114
+ const fusionDir = path7.join(this.wearablesDir, FUSION_DIR_NAME);
3211
4115
  let stat4;
3212
4116
  try {
3213
4117
  stat4 = await this.io.lstat(fusionDir);
@@ -3343,7 +4247,7 @@ function reconstructFusionInputs(date, dayTranscripts) {
3343
4247
 
3344
4248
  // src/meetings/store.ts
3345
4249
  import { createHash as createHash3 } from "crypto";
3346
- import * as path7 from "path";
4250
+ import * as path8 from "path";
3347
4251
  var MEETINGS_DIR_NAME = "meetings";
3348
4252
  var MEETING_KIND = "meeting";
3349
4253
  var MEETING_FORMAT_VERSION = 1;
@@ -3512,7 +4416,7 @@ var MeetingRecordStore = class {
3512
4416
  constructor(memoryDir, io) {
3513
4417
  this.memoryDir = memoryDir;
3514
4418
  this.io = io;
3515
- this.meetingsDir = path7.join(memoryDir, MEETINGS_DIR_NAME);
4419
+ this.meetingsDir = path8.join(memoryDir, MEETINGS_DIR_NAME);
3516
4420
  }
3517
4421
  memoryDir;
3518
4422
  io;
@@ -3528,7 +4432,7 @@ var MeetingRecordStore = class {
3528
4432
  if (idDate !== date) {
3529
4433
  throw new Error(`meeting id '${id}' does not belong to date '${date}'`);
3530
4434
  }
3531
- return path7.join(this.meetingsDir, date, `${id}.md`);
4435
+ return path8.join(this.meetingsDir, date, `${id}.md`);
3532
4436
  }
3533
4437
  /** Idempotently persist a record: skip the write when contentHash is unchanged. */
3534
4438
  async saveMeetingRecord(record) {
@@ -3559,7 +4463,7 @@ var MeetingRecordStore = class {
3559
4463
  if (!isValidTranscriptDate(date)) {
3560
4464
  throw new Error(`invalid meeting date '${String(date)}' \u2014 expected YYYY-MM-DD`);
3561
4465
  }
3562
- const dayDir = path7.join(this.meetingsDir, date);
4466
+ const dayDir = path8.join(this.meetingsDir, date);
3563
4467
  await this.assertPathContained(dayDir);
3564
4468
  let entries;
3565
4469
  try {
@@ -3627,10 +4531,10 @@ var MeetingRecordStore = class {
3627
4531
  try {
3628
4532
  rootReal = await this.io.realpath(this.memoryDir);
3629
4533
  } catch {
3630
- rootReal = path7.resolve(this.memoryDir);
4534
+ rootReal = path8.resolve(this.memoryDir);
3631
4535
  }
3632
4536
  await this.assertNoEscape(rootReal, this.meetingsDir);
3633
- await this.assertNoEscape(rootReal, path7.dirname(targetPath));
4537
+ await this.assertNoEscape(rootReal, path8.dirname(targetPath));
3634
4538
  await this.assertNoEscape(rootReal, targetPath);
3635
4539
  await this.assertNotSymlink(this.meetingsDir, "directory");
3636
4540
  const dayDir = this.dayDirWithin(targetPath);
@@ -3640,11 +4544,11 @@ var MeetingRecordStore = class {
3640
4544
  /** The `<meetings>/<date>` directory on the path to `targetPath`, or null when
3641
4545
  * `targetPath` is the meetings root itself. */
3642
4546
  dayDirWithin(targetPath) {
3643
- const rel = path7.relative(this.meetingsDir, targetPath);
3644
- if (rel === "" || rel.startsWith("..") || path7.isAbsolute(rel)) return null;
3645
- const first = rel.split(path7.sep)[0];
4547
+ const rel = path8.relative(this.meetingsDir, targetPath);
4548
+ if (rel === "" || rel.startsWith("..") || path8.isAbsolute(rel)) return null;
4549
+ const first = rel.split(path8.sep)[0];
3646
4550
  if (first === void 0 || first.length === 0) return null;
3647
- return path7.join(this.meetingsDir, first);
4551
+ return path8.join(this.meetingsDir, first);
3648
4552
  }
3649
4553
  async assertNotSymlink(target, kind) {
3650
4554
  let stat4;
@@ -3655,7 +4559,7 @@ var MeetingRecordStore = class {
3655
4559
  throw err;
3656
4560
  }
3657
4561
  if (stat4.isSymbolicLink) {
3658
- const label = path7.relative(this.memoryDir, target) || MEETINGS_DIR_NAME;
4562
+ const label = path8.relative(this.memoryDir, target) || MEETINGS_DIR_NAME;
3659
4563
  throw new Error(
3660
4564
  `meetings ${kind} '${label}' is a symbolic link \u2014 refusing to follow it even when it resolves inside the memory dir (AGENTS.md pattern #3)`
3661
4565
  );
@@ -4073,7 +4977,7 @@ function isEntitySynthesisStale(entity) {
4073
4977
 
4074
4978
  // src/storage/content-hash-index.ts
4075
4979
  import { mkdir, stat as stat2 } from "fs/promises";
4076
- import path8 from "path";
4980
+ import path9 from "path";
4077
4981
  var CONTENT_HASH_INDEX_LOCK_STALE_MS = 3e4;
4078
4982
  var CONTENT_HASH_INDEX_RETRY_MAX_ATTEMPTS = 5;
4079
4983
  var CONTENT_HASH_INDEX_RETRY_BASE_MS = 500;
@@ -4133,8 +5037,8 @@ var ContentHashIndex = class _ContentHashIndex {
4133
5037
  * re-read on the hot path.
4134
5038
  */
4135
5039
  lastSyncedFingerprint = null;
4136
- constructor(stateDir, secureStoreKeyProvider = () => null, secureStoreWriteKeyProvider = secureStoreKeyProvider, memoryDir = path8.dirname(stateDir), lockOptions = {}) {
4137
- this.filePath = path8.join(stateDir, "fact-hashes.txt");
5040
+ constructor(stateDir, secureStoreKeyProvider = () => null, secureStoreWriteKeyProvider = secureStoreKeyProvider, memoryDir = path9.dirname(stateDir), lockOptions = {}) {
5041
+ this.filePath = path9.join(stateDir, "fact-hashes.txt");
4138
5042
  this.secureStoreKeyProvider = secureStoreKeyProvider;
4139
5043
  this.secureStoreWriteKeyProvider = secureStoreWriteKeyProvider;
4140
5044
  this.memoryDir = memoryDir;
@@ -4226,7 +5130,7 @@ var ContentHashIndex = class _ContentHashIndex {
4226
5130
  /** Persist index to disk if changed (plain whole-file overwrite). */
4227
5131
  async save() {
4228
5132
  if (!this.dirty) return;
4229
- await mkdir(path8.dirname(this.filePath), { recursive: true });
5133
+ await mkdir(path9.dirname(this.filePath), { recursive: true });
4230
5134
  const publishedAdded = new Set(this.added);
4231
5135
  const publishedRemoved = new Set(this.removed);
4232
5136
  const serialized = [...this.hashes].join("\n") + "\n";
@@ -4273,7 +5177,7 @@ var ContentHashIndex = class _ContentHashIndex {
4273
5177
  */
4274
5178
  async saveMergingWithDisk() {
4275
5179
  if (!this.dirty) return;
4276
- await mkdir(path8.dirname(this.filePath), { recursive: true });
5180
+ await mkdir(path9.dirname(this.filePath), { recursive: true });
4277
5181
  const publish = async () => {
4278
5182
  const publishedAdded = new Set(this.added);
4279
5183
  const publishedRemoved = new Set(this.removed);
@@ -4292,7 +5196,7 @@ var ContentHashIndex = class _ContentHashIndex {
4292
5196
  if (err instanceof SecureStoreLockedError) throw err;
4293
5197
  if (!isErrnoCode(err, "ENOENT")) throw err;
4294
5198
  }
4295
- await mkdir(path8.dirname(this.filePath), { recursive: true });
5199
+ await mkdir(path9.dirname(this.filePath), { recursive: true });
4296
5200
  await writeMaybeEncryptedFile(
4297
5201
  this.filePath,
4298
5202
  [...merged].join("\n") + "\n",
@@ -4359,7 +5263,7 @@ var ContentHashIndex = class _ContentHashIndex {
4359
5263
  * fired retry) simply yields `acquired=false` after the bounded wait.
4360
5264
  */
4361
5265
  async rebuildUnderLock(populate) {
4362
- await mkdir(path8.dirname(this.filePath), { recursive: true });
5266
+ await mkdir(path9.dirname(this.filePath), { recursive: true });
4363
5267
  let published = false;
4364
5268
  await withHeldFileLock(
4365
5269
  `${this.filePath}.lock`,
@@ -5160,17 +6064,17 @@ function inferEntityTypeFromContent(content) {
5160
6064
  }
5161
6065
  var KNOWN_ENTITY_FILENAME_PREFIXES = /* @__PURE__ */ new Set(["company", "other", "person", "place", "project", "tool", "topic"]);
5162
6066
  function inferEntityTypeFromFilename(pathRel) {
5163
- const basename = path9.basename(pathRel, ".md").toLowerCase();
6067
+ const basename = path10.basename(pathRel, ".md").toLowerCase();
5164
6068
  const separator = basename.indexOf("-");
5165
6069
  if (separator <= 0) return void 0;
5166
6070
  const candidate = basename.slice(0, separator);
5167
6071
  return KNOWN_ENTITY_FILENAME_PREFIXES.has(candidate) ? candidate : void 0;
5168
6072
  }
5169
6073
  function normalizeFrontmatterForPath(frontmatter, pathRel, content = "") {
5170
- const normalizedPath = pathRel.split(path9.sep).join("/");
6074
+ const normalizedPath = pathRel.split(path10.sep).join("/");
5171
6075
  let normalizedFrontmatter = frontmatter;
5172
6076
  if (normalizedPath === "entities" || normalizedPath.startsWith("entities/") || normalizedPath.includes("/entities/")) {
5173
- const basename = path9.basename(pathRel, ".md");
6077
+ const basename = path10.basename(pathRel, ".md");
5174
6078
  const inferredType = inferEntityTypeFromContent(content) || inferEntityTypeFromFilename(pathRel) || "entity";
5175
6079
  const existingTags = Array.isArray(frontmatter.tags) ? frontmatter.tags : [];
5176
6080
  normalizedFrontmatter = {
@@ -5191,27 +6095,6 @@ function normalizeFrontmatterForPath(frontmatter, pathRel, content = "") {
5191
6095
  function inferCurrentStateStatus(frontmatter, pathRel, fallbackStatus) {
5192
6096
  return inferMemoryStatus(frontmatter, pathRel, fallbackStatus);
5193
6097
  }
5194
- var BUILTIN_ALIASES = {
5195
- openclaw: "openclaw",
5196
- "open-claw": "openclaw"
5197
- };
5198
- function normalizeEntityName(raw, type, aliases) {
5199
- const rawStr = typeof raw === "string" ? raw : "";
5200
- const typeStr = typeof type === "string" && type.trim().length > 0 ? type : "entity";
5201
- let name = rawStr.toLowerCase().trim();
5202
- const typePrefix = `${typeStr.toLowerCase()}-`;
5203
- if (name.startsWith(typePrefix)) {
5204
- name = name.slice(typePrefix.length);
5205
- }
5206
- let normalized = name.replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
5207
- const userAlias = aliases !== void 0 && Object.hasOwn(aliases, normalized) ? aliases[normalized] : void 0;
5208
- if (typeof userAlias === "string" && userAlias.length > 0) {
5209
- normalized = userAlias;
5210
- } else if (Object.hasOwn(BUILTIN_ALIASES, normalized)) {
5211
- normalized = BUILTIN_ALIASES[normalized];
5212
- }
5213
- return `${typeStr.toLowerCase()}-${normalized}`;
5214
- }
5215
6098
  function levenshtein(a, b) {
5216
6099
  const m = a.length;
5217
6100
  const n = b.length;
@@ -5657,6 +6540,7 @@ var StorageManager3 = class _StorageManager {
5657
6540
  this.entitySchemas = entitySchemas;
5658
6541
  this.hotMemoriesCacheEnabled = hotMemoriesCacheEnabledOverride ?? _StorageManager.hotMemoriesCacheDefaultByDir.get(baseDir) ?? _StorageManager.hotMemoriesCacheDefault;
5659
6542
  this.loadAliasesSync();
6543
+ this.loadHistoricalEntityCanonicalIdsSync();
5660
6544
  }
5661
6545
  baseDir;
5662
6546
  entitySchemas;
@@ -5836,8 +6720,8 @@ var StorageManager3 = class _StorageManager {
5836
6720
  }
5837
6721
  /** Whether `filePath` resolves to `stateDir` itself or a path contained in it. */
5838
6722
  isStateFilePath(filePath) {
5839
- const rel = path9.relative(this.stateDir, path9.resolve(filePath));
5840
- return rel === "" || !rel.startsWith("..") && !path9.isAbsolute(rel);
6723
+ const rel = path10.relative(this.stateDir, path10.resolve(filePath));
6724
+ return rel === "" || !rel.startsWith("..") && !path10.isAbsolute(rel);
5841
6725
  }
5842
6726
  // ── Tombstone store (issue #1579) ───────────────────────────────────────
5843
6727
  // Instance-scoped (rule 11) + namespace-scoped (rule 42) tombstone index.
@@ -5880,17 +6764,34 @@ var StorageManager3 = class _StorageManager {
5880
6764
  * Set or clear the at-rest encryption key.
5881
6765
  *
5882
6766
  * Pass a 32-byte Buffer to enable encryption; pass null to clear
5883
- * (lock) the store. The caller is responsible for key lifecycle —
6767
+ * (lock) the store. The caller is responsible for key lifecycle —
5884
6768
  * this method does not zero the buffer on replacement; the keyring
5885
- * module (`keyring.ts`) owns zeroization.
6769
+ * module (`keyring.ts`) owns zeroization. The setter remains synchronous
6770
+ * for existing consumers; call `setSecureStoreKeyAndWait` when unlock must
6771
+ * await migration.
5886
6772
  */
5887
6773
  setSecureStoreKey(key, encryptOnWrite = true) {
6774
+ if (!this.applySecureStoreKey(key, encryptOnWrite) || key === null) return;
6775
+ void this.entityCanonicalIdMigration.triggerAfterUnlock().catch((error) => {
6776
+ log.warn(
6777
+ `secure-store unlock migration failed: ${error instanceof Error ? error.message : String(error)}`
6778
+ );
6779
+ });
6780
+ }
6781
+ async setSecureStoreKeyAndWait(key, encryptOnWrite = true) {
6782
+ if (!this.applySecureStoreKey(key, encryptOnWrite) || key === null) return;
6783
+ await this.entityCanonicalIdMigration.triggerAfterUnlock();
6784
+ }
6785
+ applySecureStoreKey(key, encryptOnWrite) {
6786
+ const sameKey = this._secureStoreKey === key || this._secureStoreKey !== null && key !== null && this._secureStoreKey.equals(key);
6787
+ if (sameKey && this._secureStoreEncryptOnWrite === encryptOnWrite) return false;
5888
6788
  this._secureStoreKey = key;
5889
6789
  this._secureStoreEncryptOnWrite = encryptOnWrite;
5890
6790
  invalidateAllForDir(this.baseDir);
5891
6791
  this.invalidateKnowledgeIndexCache();
5892
6792
  this.secureFileEncryptionSniffCache.clear();
5893
6793
  this.behaviorSignalsKeyCache = null;
6794
+ return true;
5894
6795
  }
5895
6796
  getEntityCacheSecureStoreKey() {
5896
6797
  if (!this._secureStoreKey) return "secure-store:locked";
@@ -5937,8 +6838,8 @@ var StorageManager3 = class _StorageManager {
5937
6838
  * /srv/cold/remnic), skipping the patch and stranding a stale hot entry.
5938
6839
  */
5939
6840
  isColdOrArchiveTierPath(p) {
5940
- const rel = path9.relative(this.baseDir, p);
5941
- return rel === "cold" || rel === "archive" || rel.startsWith(`cold${path9.sep}`) || rel.startsWith(`archive${path9.sep}`);
6841
+ const rel = path10.relative(this.baseDir, p);
6842
+ return rel === "cold" || rel === "archive" || rel.startsWith(`cold${path10.sep}`) || rel.startsWith(`archive${path10.sep}`);
5942
6843
  }
5943
6844
  /**
5944
6845
  * Mark the secure-store as required for this storage instance.
@@ -6025,7 +6926,7 @@ var StorageManager3 = class _StorageManager {
6025
6926
  void 0,
6026
6927
  this.baseDir
6027
6928
  );
6028
- const rel = path9.relative(this.baseDir, filePath).split(path9.sep).join("/");
6929
+ const rel = path10.relative(this.baseDir, filePath).split(path10.sep).join("/");
6029
6930
  return `${rel}:${version.versionId}`;
6030
6931
  } catch (err) {
6031
6932
  log.warn(
@@ -6105,13 +7006,13 @@ var StorageManager3 = class _StorageManager {
6105
7006
  }
6106
7007
  identityFilePath(workspaceDir, namespace) {
6107
7008
  const rawNamespace = typeof namespace === "string" ? namespace.trim() : "";
6108
- if (!rawNamespace) return path9.join(workspaceDir, "IDENTITY.md");
7009
+ if (!rawNamespace) return path10.join(workspaceDir, "IDENTITY.md");
6109
7010
  const safeNamespace = rawNamespace.replace(/[^a-zA-Z0-9._-]/g, "-");
6110
- return path9.join(workspaceDir, `IDENTITY.${safeNamespace}.md`);
7011
+ return path10.join(workspaceDir, `IDENTITY.${safeNamespace}.md`);
6111
7012
  }
6112
7013
  versionFilePath(kind) {
6113
7014
  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";
6114
- return path9.join(this.stateDir, fileName);
7015
+ return path10.join(this.stateDir, fileName);
6115
7016
  }
6116
7017
  bumpSharedVersion(kind, fallbackMap) {
6117
7018
  const filePath = this.versionFilePath(kind);
@@ -6203,7 +7104,7 @@ var StorageManager3 = class _StorageManager {
6203
7104
  // memories.
6204
7105
  // -------------------------------------------------------------------------
6205
7106
  get wearablesDir() {
6206
- return path9.join(this.baseDir, WEARABLES_DIR_NAME);
7107
+ return path10.join(this.baseDir, WEARABLES_DIR_NAME);
6207
7108
  }
6208
7109
  /**
6209
7110
  * Resolve the on-disk path for a source/day transcript. Throws on
@@ -6219,7 +7120,7 @@ var StorageManager3 = class _StorageManager {
6219
7120
  if (!isValidTranscriptDate(date)) {
6220
7121
  throw new Error(`invalid wearable transcript date '${String(date)}' \u2014 expected YYYY-MM-DD`);
6221
7122
  }
6222
- return path9.join(this.wearablesDir, sourceId, `${date}.md`);
7123
+ return path10.join(this.wearablesDir, sourceId, `${date}.md`);
6223
7124
  }
6224
7125
  async writeWearableDayTranscript(sourceId, date, serialized) {
6225
7126
  const targetPath = this.wearableTranscriptPath(sourceId, date);
@@ -6245,10 +7146,10 @@ var StorageManager3 = class _StorageManager {
6245
7146
  return this._fusionStore = new FusionArtifactStore(this.wearablesDir, this.baseDir, {
6246
7147
  writeFile: (p, c) => this.writeStorageSecureFile(p, c),
6247
7148
  readFile: (p) => readMaybeEncryptedFile(p, this._secureStoreKey, this.baseDir),
6248
- readDir: (d) => readdir4(d),
6249
- deleteFile: (p) => unlink2(p),
6250
- realpath: (p) => realpath2(p),
6251
- lstat: (p) => lstat2(p).then((st) => ({ isSymbolicLink: st.isSymbolicLink() }))
7149
+ readDir: (d) => readdir5(d),
7150
+ deleteFile: (p) => unlink3(p),
7151
+ realpath: (p) => realpath3(p),
7152
+ lstat: (p) => lstat3(p).then((st) => ({ isSymbolicLink: st.isSymbolicLink() }))
6252
7153
  });
6253
7154
  }
6254
7155
  _meetingRecordStore;
@@ -6263,10 +7164,10 @@ var StorageManager3 = class _StorageManager {
6263
7164
  return this._meetingRecordStore = new MeetingRecordStore(this.baseDir, {
6264
7165
  writeFile: (p, c) => this.writeStorageSecureFile(p, c),
6265
7166
  readFile: (p) => readMaybeEncryptedFile(p, this._secureStoreKey, this.baseDir),
6266
- readDir: (d) => readdir4(d),
6267
- deleteFile: (p) => unlink2(p),
6268
- realpath: (p) => realpath2(p),
6269
- lstat: (p) => lstat2(p).then((st) => ({ isSymbolicLink: st.isSymbolicLink() }))
7167
+ readDir: (d) => readdir5(d),
7168
+ deleteFile: (p) => unlink3(p),
7169
+ realpath: (p) => realpath3(p),
7170
+ lstat: (p) => lstat3(p).then((st) => ({ isSymbolicLink: st.isSymbolicLink() }))
6270
7171
  });
6271
7172
  }
6272
7173
  /**
@@ -6335,25 +7236,25 @@ var StorageManager3 = class _StorageManager {
6335
7236
  });
6336
7237
  }
6337
7238
  get factsDir() {
6338
- return path9.join(this.baseDir, "facts");
7239
+ return path10.join(this.baseDir, "facts");
6339
7240
  }
6340
7241
  get correctionsDir() {
6341
- return path9.join(this.baseDir, "corrections");
7242
+ return path10.join(this.baseDir, "corrections");
6342
7243
  }
6343
7244
  get proceduresDir() {
6344
- return path9.join(this.baseDir, "procedures");
7245
+ return path10.join(this.baseDir, "procedures");
6345
7246
  }
6346
7247
  get reasoningTracesDir() {
6347
- return path9.join(this.baseDir, "reasoning-traces");
7248
+ return path10.join(this.baseDir, "reasoning-traces");
6348
7249
  }
6349
7250
  get entitiesDir() {
6350
- return path9.join(this.baseDir, "entities");
7251
+ return path10.join(this.baseDir, "entities");
6351
7252
  }
6352
7253
  resolveEntityFilePath(name) {
6353
7254
  if (typeof name !== "string") return null;
6354
- const filePath = path9.resolve(this.entitiesDir, `${name}.md`);
6355
- const relative2 = path9.relative(this.entitiesDir, filePath);
6356
- if (relative2 === "" || relative2.startsWith("..") || path9.isAbsolute(relative2)) {
7255
+ const filePath = path10.resolve(this.entitiesDir, `${name}.md`);
7256
+ const relative2 = path10.relative(this.entitiesDir, filePath);
7257
+ if (relative2 === "" || relative2.startsWith("..") || path10.isAbsolute(relative2)) {
6357
7258
  return null;
6358
7259
  }
6359
7260
  return filePath;
@@ -6374,10 +7275,10 @@ var StorageManager3 = class _StorageManager {
6374
7275
  });
6375
7276
  }
6376
7277
  assertManagedStoragePath(filePath, method) {
6377
- const resolved = path9.resolve(filePath);
6378
- const base = path9.resolve(this.baseDir);
6379
- const rel = path9.relative(base, resolved);
6380
- if (rel === "" || rel === ".." || rel.startsWith(`..${path9.sep}`) || path9.isAbsolute(rel)) {
7278
+ const resolved = path10.resolve(filePath);
7279
+ const base = path10.resolve(this.baseDir);
7280
+ const rel = path10.relative(base, resolved);
7281
+ if (rel === "" || rel === ".." || rel.startsWith(`..${path10.sep}`) || path10.isAbsolute(rel)) {
6381
7282
  throw new Error(`${method}: file path escapes memory dir`);
6382
7283
  }
6383
7284
  return resolved;
@@ -6389,7 +7290,7 @@ var StorageManager3 = class _StorageManager {
6389
7290
  async digestOfflineSyncFile(filePath) {
6390
7291
  const target = this.assertManagedStoragePath(filePath, "storage.digestOfflineSyncFile");
6391
7292
  const st = await stat3(target);
6392
- const relPath = path9.relative(this.baseDir, target).split(path9.sep).join("/");
7293
+ const relPath = path10.relative(this.baseDir, target).split(path10.sep).join("/");
6393
7294
  const cache = await this.loadOfflineSyncDigestCache();
6394
7295
  const cached = cache.get(relPath);
6395
7296
  if (cached && cached.statBytes === st.size && cached.mtimeMs === st.mtimeMs && cached.ctimeMs === st.ctimeMs && !cached.encrypted) {
@@ -6435,7 +7336,7 @@ var StorageManager3 = class _StorageManager {
6435
7336
  async readOfflineSyncDigestCache() {
6436
7337
  const cache = /* @__PURE__ */ new Map();
6437
7338
  try {
6438
- const raw = await readFile(this.offlineSyncDigestCachePath, "utf-8");
7339
+ const raw = await readFile2(this.offlineSyncDigestCachePath, "utf-8");
6439
7340
  const parsed = JSON.parse(raw);
6440
7341
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return cache;
6441
7342
  const entries = parsed.entries;
@@ -6450,7 +7351,7 @@ var StorageManager3 = class _StorageManager {
6450
7351
  const bytes = typeof record.bytes === "number" ? record.bytes : NaN;
6451
7352
  const sha256 = typeof record.sha256 === "string" ? record.sha256 : "";
6452
7353
  const encrypted = record.encrypted === true;
6453
- 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)) {
7354
+ 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)) {
6454
7355
  continue;
6455
7356
  }
6456
7357
  cache.set(cachePath, { statBytes, mtimeMs, ctimeMs, encrypted, sha256, bytes });
@@ -6492,8 +7393,8 @@ var StorageManager3 = class _StorageManager {
6492
7393
  const cache = this.offlineSyncDigestCache;
6493
7394
  if (!cache) return;
6494
7395
  const entries = [...cache.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([entryPath, entry]) => ({ path: entryPath, ...entry }));
6495
- await mkdir2(path9.dirname(this.offlineSyncDigestCachePath), { recursive: true });
6496
- await writeFile(this.offlineSyncDigestCachePath, `${JSON.stringify({ version: 1, entries })}
7396
+ await mkdir2(path10.dirname(this.offlineSyncDigestCachePath), { recursive: true });
7397
+ await writeFile2(this.offlineSyncDigestCachePath, `${JSON.stringify({ version: 1, entries })}
6497
7398
  `, "utf-8");
6498
7399
  }).catch((err) => {
6499
7400
  log.warn(
@@ -6527,7 +7428,7 @@ var StorageManager3 = class _StorageManager {
6527
7428
  }
6528
7429
  async deleteOfflineSyncFile(filePath) {
6529
7430
  const target = this.assertManagedStoragePath(filePath, "storage.deleteOfflineSyncFile");
6530
- await unlink2(target).catch((error) => {
7431
+ await unlink3(target).catch((error) => {
6531
7432
  if (isErrnoCode(error, "ENOENT")) return;
6532
7433
  throw error;
6533
7434
  });
@@ -6537,10 +7438,10 @@ var StorageManager3 = class _StorageManager {
6537
7438
  this.invalidateAllMemoriesCache();
6538
7439
  this.invalidateKnowledgeIndexCache();
6539
7440
  this.factHashIndexAuthoritative = false;
6540
- if (filePath.includes(`${path9.sep}cold${path9.sep}`)) {
7441
+ if (filePath.includes(`${path10.sep}cold${path10.sep}`)) {
6541
7442
  this.invalidateColdMemoriesCache();
6542
7443
  }
6543
- if (filePath.includes(`${path9.sep}artifacts${path9.sep}`)) {
7444
+ if (filePath.includes(`${path10.sep}artifacts${path10.sep}`)) {
6544
7445
  this.bumpArtifactWriteVersion();
6545
7446
  }
6546
7447
  this.bumpMemoryStatusVersion();
@@ -6611,7 +7512,7 @@ var StorageManager3 = class _StorageManager {
6611
7512
  }
6612
7513
  async appendStorageSecureFileUnlocked(filePath, content) {
6613
7514
  const writeKey = this.resolveWriteKey();
6614
- await mkdir2(path9.dirname(filePath), { recursive: true });
7515
+ await mkdir2(path10.dirname(filePath), { recursive: true });
6615
7516
  if (writeKey === null) {
6616
7517
  try {
6617
7518
  if (await this.isEncryptedFileHeader(filePath)) {
@@ -6637,13 +7538,13 @@ var StorageManager3 = class _StorageManager {
6637
7538
  this.notifyCatalogWriteForPath(filePath);
6638
7539
  }
6639
7540
  get stateDir() {
6640
- return path9.join(this.baseDir, "state");
7541
+ return path10.join(this.baseDir, "state");
6641
7542
  }
6642
7543
  get offlineSyncDigestCachePath() {
6643
- return path9.join(this.baseDir, ".offline-sync", "digest-cache.v1.json");
7544
+ return path10.join(this.baseDir, ".offline-sync", "digest-cache.v1.json");
6644
7545
  }
6645
7546
  get entitySynthesisQueuePath() {
6646
- return path9.join(this.stateDir, "entity-synthesis-queue.json");
7547
+ return path10.join(this.stateDir, "entity-synthesis-queue.json");
6647
7548
  }
6648
7549
  // ── Tombstone store access (issue #1579) ─────────────────────────────────
6649
7550
  /**
@@ -6653,7 +7554,7 @@ var StorageManager3 = class _StorageManager {
6653
7554
  * helpers are injected into the store).
6654
7555
  */
6655
7556
  get tombstonesPath() {
6656
- return path9.join(this.stateDir, "tombstones.jsonl");
7557
+ return path10.join(this.stateDir, "tombstones.jsonl");
6657
7558
  }
6658
7559
  /**
6659
7560
  * Configure the tombstone invariant for this storage instance. Installed
@@ -6926,55 +7827,55 @@ var StorageManager3 = class _StorageManager {
6926
7827
  return null;
6927
7828
  }
6928
7829
  get questionsDir() {
6929
- return path9.join(this.baseDir, "questions");
7830
+ return path10.join(this.baseDir, "questions");
6930
7831
  }
6931
7832
  get artifactsDir() {
6932
- return path9.join(this.baseDir, "artifacts");
7833
+ return path10.join(this.baseDir, "artifacts");
6933
7834
  }
6934
7835
  get identityDir() {
6935
- return path9.join(this.baseDir, "identity");
7836
+ return path10.join(this.baseDir, "identity");
6936
7837
  }
6937
7838
  get identityAnchorPath() {
6938
- return path9.join(this.identityDir, "identity-anchor.md");
7839
+ return path10.join(this.identityDir, "identity-anchor.md");
6939
7840
  }
6940
7841
  get identityIncidentsDir() {
6941
- return path9.join(this.identityDir, "incidents");
7842
+ return path10.join(this.identityDir, "incidents");
6942
7843
  }
6943
7844
  get identityAuditsWeeklyDir() {
6944
- return path9.join(this.identityDir, "audits", "weekly");
7845
+ return path10.join(this.identityDir, "audits", "weekly");
6945
7846
  }
6946
7847
  get identityAuditsMonthlyDir() {
6947
- return path9.join(this.identityDir, "audits", "monthly");
7848
+ return path10.join(this.identityDir, "audits", "monthly");
6948
7849
  }
6949
7850
  get identityImprovementLoopsPath() {
6950
- return path9.join(this.identityDir, "improvement-loops.md");
7851
+ return path10.join(this.identityDir, "improvement-loops.md");
6951
7852
  }
6952
7853
  get identityReflectionsPath() {
6953
- return path9.join(this.identityDir, "reflections.md");
7854
+ return path10.join(this.identityDir, "reflections.md");
6954
7855
  }
6955
7856
  get profilePath() {
6956
- return path9.join(this.baseDir, "profile.md");
7857
+ return path10.join(this.baseDir, "profile.md");
6957
7858
  }
6958
7859
  get memoryActionsPath() {
6959
- return path9.join(this.stateDir, "memory-actions.jsonl");
7860
+ return path10.join(this.stateDir, "memory-actions.jsonl");
6960
7861
  }
6961
7862
  get memoryLifecycleLedgerPath() {
6962
- return path9.join(this.stateDir, "memory-lifecycle-ledger.jsonl");
7863
+ return path10.join(this.stateDir, "memory-lifecycle-ledger.jsonl");
6963
7864
  }
6964
7865
  get compressionGuidelinesPath() {
6965
- return path9.join(this.stateDir, "compression-guidelines.md");
7866
+ return path10.join(this.stateDir, "compression-guidelines.md");
6966
7867
  }
6967
7868
  get compressionGuidelineDraftPath() {
6968
- return path9.join(this.stateDir, "compression-guidelines.draft.md");
7869
+ return path10.join(this.stateDir, "compression-guidelines.draft.md");
6969
7870
  }
6970
7871
  get compressionGuidelineStatePath() {
6971
- return path9.join(this.stateDir, "compression-guideline-state.json");
7872
+ return path10.join(this.stateDir, "compression-guideline-state.json");
6972
7873
  }
6973
7874
  get compressionGuidelineDraftStatePath() {
6974
- return path9.join(this.stateDir, "compression-guideline-draft-state.json");
7875
+ return path10.join(this.stateDir, "compression-guideline-draft-state.json");
6975
7876
  }
6976
7877
  get behaviorSignalsPath() {
6977
- return path9.join(this.stateDir, "behavior-signals.jsonl");
7878
+ return path10.join(this.stateDir, "behavior-signals.jsonl");
6978
7879
  }
6979
7880
  /**
6980
7881
  * In-memory dedup key set for behavior-signals appends (issue #1909),
@@ -7006,7 +7907,7 @@ var StorageManager3 = class _StorageManager {
7006
7907
  * governance sweeps can treat it uniformly.
7007
7908
  */
7008
7909
  get bufferSurpriseLedgerPath() {
7009
- return path9.join(this.stateDir, "buffer-surprise-ledger.jsonl");
7910
+ return path10.join(this.stateDir, "buffer-surprise-ledger.jsonl");
7010
7911
  }
7011
7912
  /**
7012
7913
  * Entity alias table loaded from THIS store's config/aliases.json.
@@ -7016,8 +7917,17 @@ var StorageManager3 = class _StorageManager {
7016
7917
  * store loaded last rewrite every other store's canonical entity ids.
7017
7918
  */
7018
7919
  userAliases = {};
7920
+ historicalEntityCanonicalIds = {};
7921
+ entityCanonicalIdMigration = new EntityCanonicalIdMigrationRunner(
7922
+ () => !(this._secureStoreRequired && !this.isSecureStoreUnlocked()),
7923
+ () => this.runLegacyEntityCanonicalIdMigration(),
7924
+ () => getFingerprint(this.baseDir, this.entitiesDir, () => this.getCorpusScanVersion())
7925
+ );
7019
7926
  normalizeEntityName(raw, type) {
7020
- return this.entityStore.normalizeEntityName(raw, type);
7927
+ return resolveHistoricalEntityCanonicalId(
7928
+ this.entityStore.normalizeEntityName(raw, type),
7929
+ this.historicalEntityCanonicalIds
7930
+ );
7021
7931
  }
7022
7932
  /**
7023
7933
  * Read-only view of this store's user alias table, for call sites that
@@ -7037,10 +7947,10 @@ var StorageManager3 = class _StorageManager {
7037
7947
  this.loadAliasesSync();
7038
7948
  }
7039
7949
  loadAliasesSync() {
7040
- const aliasPath = path9.join(this.baseDir, "config", "aliases.json");
7950
+ const aliasPath = path10.join(this.baseDir, "config", "aliases.json");
7041
7951
  this.userAliases = {};
7042
7952
  try {
7043
- const raw = readFileSync(aliasPath, "utf-8");
7953
+ const raw = readFileSync2(aliasPath, "utf-8");
7044
7954
  const parsed = JSON.parse(raw);
7045
7955
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
7046
7956
  const cleaned = {};
@@ -7058,11 +7968,26 @@ var StorageManager3 = class _StorageManager {
7058
7968
  log.debug("no config/aliases.json found \u2014 using built-in aliases only");
7059
7969
  }
7060
7970
  }
7971
+ loadHistoricalEntityCanonicalIdsSync() {
7972
+ this.historicalEntityCanonicalIds = loadHistoricalEntityCanonicalIds(this.stateDir);
7973
+ }
7974
+ async runLegacyEntityCanonicalIdMigration() {
7975
+ const completionFingerprint = await runLegacyEntityCanonicalIdMigration(
7976
+ this,
7977
+ (content) => parseEntityFile(content, this.entitySchemas),
7978
+ (entity) => serializeEntityFile(entity, this.entitySchemas),
7979
+ createMemoryEntityRefSerializer(serializeFrontmatter)
7980
+ );
7981
+ this.loadHistoricalEntityCanonicalIdsSync();
7982
+ return completionFingerprint;
7983
+ }
7061
7984
  async ensureDirectories() {
7985
+ await mkdir2(this.baseDir, { recursive: true });
7986
+ await validateRoots(this.baseDir, this.entitiesDir, this.stateDir, this.archiveDir);
7062
7987
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
7063
- await mkdir2(path9.join(this.factsDir, today), { recursive: true });
7064
- await mkdir2(path9.join(this.proceduresDir, today), { recursive: true });
7065
- await mkdir2(path9.join(this.reasoningTracesDir, today), { recursive: true });
7988
+ await mkdir2(path10.join(this.factsDir, today), { recursive: true });
7989
+ await mkdir2(path10.join(this.proceduresDir, today), { recursive: true });
7990
+ await mkdir2(path10.join(this.reasoningTracesDir, today), { recursive: true });
7066
7991
  await mkdir2(this.correctionsDir, { recursive: true });
7067
7992
  await mkdir2(this.entitiesDir, { recursive: true });
7068
7993
  await mkdir2(this.stateDir, { recursive: true });
@@ -7072,10 +7997,12 @@ var StorageManager3 = class _StorageManager {
7072
7997
  await mkdir2(this.identityIncidentsDir, { recursive: true });
7073
7998
  await mkdir2(this.identityAuditsWeeklyDir, { recursive: true });
7074
7999
  await mkdir2(this.identityAuditsMonthlyDir, { recursive: true });
7075
- await mkdir2(path9.join(this.baseDir, "config"), { recursive: true });
8000
+ await mkdir2(path10.join(this.baseDir, "config"), { recursive: true });
8001
+ await this.entityCanonicalIdMigration.ensure();
7076
8002
  if (this.hotMemoriesCacheEnabled && this.getMemoryCorpusVersion() === 0) {
7077
8003
  this.bumpMemoryCorpusVersion();
7078
8004
  }
8005
+ await this.entityCanonicalIdMigration.markDirectoriesInitialized();
7079
8006
  }
7080
8007
  /**
7081
8008
  * Resolve the on-disk write path for a memory of the given category, creating
@@ -7092,11 +8019,11 @@ var StorageManager3 = class _StorageManager {
7092
8019
  async resolveCategoryWritePath(category, id, today) {
7093
8020
  if (category === "correction") {
7094
8021
  await mkdir2(this.correctionsDir, { recursive: true });
7095
- return path9.join(this.correctionsDir, `${id}.md`);
8022
+ return path10.join(this.correctionsDir, `${id}.md`);
7096
8023
  }
7097
- const datedDir = path9.join(getCategoryDir(this.baseDir, category), today);
8024
+ const datedDir = path10.join(getCategoryDir(this.baseDir, category), today);
7098
8025
  await mkdir2(datedDir, { recursive: true });
7099
- return path9.join(datedDir, `${id}.md`);
8026
+ return path10.join(datedDir, `${id}.md`);
7100
8027
  }
7101
8028
  async writeMemory(category, content, options = {}) {
7102
8029
  await this.ensureDirectories();
@@ -7401,7 +8328,7 @@ ${sanitized.text}
7401
8328
  await this.ensureDirectories();
7402
8329
  const now = /* @__PURE__ */ new Date();
7403
8330
  const day = now.toISOString().slice(0, 10);
7404
- const dir = path9.join(this.artifactsDir, day);
8331
+ const dir = path10.join(this.artifactsDir, day);
7405
8332
  await mkdir2(dir, { recursive: true });
7406
8333
  const id = `artifact-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
7407
8334
  const fm = {
@@ -7426,7 +8353,7 @@ ${sanitized.text}
7426
8353
  log.warn(`artifact content rejected for ${id}; violations=${sanitized.violations.join(", ")}`);
7427
8354
  return "";
7428
8355
  }
7429
- const filePath = path9.join(dir, `${id}.md`);
8356
+ const filePath = path10.join(dir, `${id}.md`);
7430
8357
  await this.writeStorageSecureFile(filePath, `${serializeFrontmatter(fm)}
7431
8358
 
7432
8359
  ${sanitized.text}
@@ -7697,7 +8624,7 @@ ${sanitized.text}
7697
8624
  * per-process in-memory cache safe across process boundaries.
7698
8625
  */
7699
8626
  invalidateColdMemoriesCache() {
7700
- const coldRoot = path9.join(this.baseDir, "cold");
8627
+ const coldRoot = path10.join(this.baseDir, "cold");
7701
8628
  _StorageManager.coldMemoriesCache.delete(coldRoot);
7702
8629
  this.bumpColdWriteVersion();
7703
8630
  invalidateAllForDir(this.baseDir);
@@ -7757,7 +8684,7 @@ ${sanitized.text}
7757
8684
  const raw = await readMaybeEncryptedFile(fullPath, this._secureStoreKey, this.baseDir);
7758
8685
  const parsed = parseFrontmatter(raw);
7759
8686
  if (!parsed) return null;
7760
- return {
8687
+ return rememberRawFrontmatter({
7761
8688
  path: fullPath,
7762
8689
  frontmatter: normalizeFrontmatterForPath(
7763
8690
  parsed.frontmatter,
@@ -7765,7 +8692,7 @@ ${sanitized.text}
7765
8692
  parsed.content
7766
8693
  ),
7767
8694
  content: parsed.content
7768
- };
8695
+ }, raw);
7769
8696
  } catch (err) {
7770
8697
  if (err instanceof SecureStoreLockedError) throw err;
7771
8698
  return null;
@@ -7812,7 +8739,7 @@ ${sanitized.text}
7812
8739
  const correctionPaths = [];
7813
8740
  const factPaths = [];
7814
8741
  for (const filePath of filePaths) {
7815
- if (filePath === this.correctionsDir || filePath.startsWith(`${this.correctionsDir}${path9.sep}`)) {
8742
+ if (filePath === this.correctionsDir || filePath.startsWith(`${this.correctionsDir}${path10.sep}`)) {
7816
8743
  correctionPaths.push(filePath);
7817
8744
  } else {
7818
8745
  factPaths.push(filePath);
@@ -7873,9 +8800,9 @@ ${sanitized.text}
7873
8800
  const root = this.archiveDir;
7874
8801
  const readDir = async (dir) => {
7875
8802
  try {
7876
- const entries = await readdir4(dir, { withFileTypes: true });
8803
+ const entries = await readdir5(dir, { withFileTypes: true });
7877
8804
  for (const entry of entries) {
7878
- const fullPath = path9.join(dir, entry.name);
8805
+ const fullPath = path10.join(dir, entry.name);
7879
8806
  if (entry.isDirectory()) {
7880
8807
  await readDir(fullPath);
7881
8808
  } else if (entry.name.endsWith(".md")) {
@@ -7883,7 +8810,7 @@ ${sanitized.text}
7883
8810
  const raw = await readMaybeEncryptedFile(fullPath, this._secureStoreKey, this.baseDir);
7884
8811
  const parsed = parseFrontmatter(raw);
7885
8812
  if (parsed) {
7886
- memories.push({
8813
+ memories.push(rememberRawFrontmatter({
7887
8814
  path: fullPath,
7888
8815
  frontmatter: normalizeFrontmatterForPath(
7889
8816
  parsed.frontmatter,
@@ -7891,7 +8818,7 @@ ${sanitized.text}
7891
8818
  parsed.content
7892
8819
  ),
7893
8820
  content: parsed.content
7894
- });
8821
+ }, raw));
7895
8822
  }
7896
8823
  } catch (err) {
7897
8824
  if (err instanceof SecureStoreLockedError) throw err;
@@ -7908,7 +8835,7 @@ ${sanitized.text}
7908
8835
  return this.memoryReadStore.readMemoryByPath(filePath);
7909
8836
  }
7910
8837
  resolveTierRootDir(tier) {
7911
- return tier === "cold" ? path9.join(this.baseDir, "cold") : this.baseDir;
8838
+ return tier === "cold" ? path10.join(this.baseDir, "cold") : this.baseDir;
7912
8839
  }
7913
8840
  resolveMemoryDateDir(memory) {
7914
8841
  const preferred = memory.frontmatter.created || memory.frontmatter.updated;
@@ -7923,13 +8850,13 @@ ${sanitized.text}
7923
8850
  buildTierMemoryPath(memory, tier) {
7924
8851
  const root = this.resolveTierRootDir(tier);
7925
8852
  if (this.isArtifactMemory(memory)) {
7926
- return path9.join(root, "artifacts", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
8853
+ return path10.join(root, "artifacts", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
7927
8854
  }
7928
8855
  if (memory.frontmatter.category === "correction") {
7929
- return path9.join(root, "corrections", `${memory.frontmatter.id}.md`);
8856
+ return path10.join(root, "corrections", `${memory.frontmatter.id}.md`);
7930
8857
  }
7931
8858
  const dir = categoryDirName(memory.frontmatter.category);
7932
- return path9.join(root, dir, this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
8859
+ return path10.join(root, dir, this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
7933
8860
  }
7934
8861
  async writeMemoryFileAtomic(targetPath, memory) {
7935
8862
  const fileContent = `${serializeFrontmatter(memory.frontmatter)}
@@ -7942,11 +8869,11 @@ ${memory.content}
7942
8869
  }
7943
8870
  async moveMemoryToPath(memory, targetPath) {
7944
8871
  await this.writeMemoryFileAtomic(targetPath, memory);
7945
- const sourcePath = path9.resolve(memory.path);
7946
- const destPath = path9.resolve(targetPath);
8872
+ const sourcePath = path10.resolve(memory.path);
8873
+ const destPath = path10.resolve(targetPath);
7947
8874
  if (sourcePath !== destPath) {
7948
8875
  try {
7949
- await unlink2(memory.path);
8876
+ await unlink3(memory.path);
7950
8877
  } catch (err) {
7951
8878
  const message = err instanceof Error ? err.message : String(err);
7952
8879
  if (!message.includes("ENOENT")) {
@@ -7959,15 +8886,15 @@ ${memory.content}
7959
8886
  }
7960
8887
  async migrateMemoryToTier(memory, targetTier) {
7961
8888
  const targetPath = this.buildTierMemoryPath(memory, targetTier);
7962
- const sourcePath = path9.resolve(memory.path);
7963
- const destPath = path9.resolve(targetPath);
8889
+ const sourcePath = path10.resolve(memory.path);
8890
+ const destPath = path10.resolve(targetPath);
7964
8891
  if (sourcePath === destPath) {
7965
8892
  return { changed: false, targetPath };
7966
8893
  }
7967
8894
  const existing = await this.readMemoryByPath(targetPath);
7968
8895
  if (existing?.frontmatter.id === memory.frontmatter.id) {
7969
8896
  try {
7970
- await unlink2(memory.path);
8897
+ await unlink3(memory.path);
7971
8898
  } catch (err) {
7972
8899
  const message = err instanceof Error ? err.message : String(err);
7973
8900
  if (!message.includes("ENOENT")) {
@@ -7987,7 +8914,7 @@ ${memory.content}
7987
8914
  return { changed: true, targetPath };
7988
8915
  }
7989
8916
  get archiveDir() {
7990
- return path9.join(this.baseDir, "archive");
8917
+ return path10.join(this.baseDir, "archive");
7991
8918
  }
7992
8919
  /**
7993
8920
  * Archive a memory by moving it from facts/ to archive/YYYY-MM-DD/.
@@ -7998,7 +8925,7 @@ ${memory.content}
7998
8925
  try {
7999
8926
  const now = lifecycle?.at ?? /* @__PURE__ */ new Date();
8000
8927
  const today = now.toISOString().slice(0, 10);
8001
- const destDir = path9.join(this.archiveDir, today);
8928
+ const destDir = path10.join(this.archiveDir, today);
8002
8929
  await mkdir2(destDir, { recursive: true });
8003
8930
  const updatedFm = {
8004
8931
  ...memory.frontmatter,
@@ -8010,9 +8937,9 @@ ${memory.content}
8010
8937
 
8011
8938
  ${memory.content}
8012
8939
  `;
8013
- const destPath = path9.join(destDir, path9.basename(memory.path));
8940
+ const destPath = path10.join(destDir, path10.basename(memory.path));
8014
8941
  await this.writeStorageSecureFile(destPath, fileContent);
8015
- await unlink2(memory.path);
8942
+ await unlink3(memory.path);
8016
8943
  markProjectedMemoryPathInvalid(this.baseDir, memory.frontmatter.id);
8017
8944
  this.invalidateAllMemoriesCache();
8018
8945
  await this.appendGeneratedMemoryLifecycleEventFailOpen(
@@ -8040,7 +8967,7 @@ ${memory.content}
8040
8967
  }
8041
8968
  async readEntities() {
8042
8969
  try {
8043
- const entries = await readdir4(this.entitiesDir);
8970
+ const entries = await readdir5(this.entitiesDir);
8044
8971
  return entries.filter((e) => e.endsWith(".md")).map((e) => e.replace(".md", ""));
8045
8972
  } catch {
8046
8973
  return [];
@@ -8092,7 +9019,7 @@ ${memory.content}
8092
9019
  const memory = memories.find((m) => m.frontmatter.id === id);
8093
9020
  if (!memory) return false;
8094
9021
  try {
8095
- await unlink2(memory.path);
9022
+ await unlink3(memory.path);
8096
9023
  markProjectedMemoryPathInvalid(this.baseDir, id);
8097
9024
  this.invalidateAllMemoriesCache();
8098
9025
  this.bumpMemoryStatusVersion();
@@ -8158,7 +9085,7 @@ ${memory.content}
8158
9085
  `;
8159
9086
  await this.writeStorageSecureFile(memory.path, fileContent);
8160
9087
  await this.patchHotMemoriesCache({ addedPath: memory.path });
8161
- if (memory.path.includes(`${path9.sep}cold${path9.sep}`)) {
9088
+ if (memory.path.includes(`${path10.sep}cold${path10.sep}`)) {
8162
9089
  this.invalidateColdMemoriesCache();
8163
9090
  }
8164
9091
  try {
@@ -8213,7 +9140,7 @@ ${memory.content}
8213
9140
  const expiresAt = new Date(m.frontmatter.expiresAt).getTime();
8214
9141
  if (expiresAt < now) {
8215
9142
  try {
8216
- await unlink2(m.path);
9143
+ await unlink3(m.path);
8217
9144
  markProjectedMemoryPathInvalid(this.baseDir, m.frontmatter.id);
8218
9145
  this.bumpMemoryCorpusVersion();
8219
9146
  deleted.push(m);
@@ -8229,7 +9156,7 @@ ${memory.content}
8229
9156
  return deleted;
8230
9157
  }
8231
9158
  async loadBuffer() {
8232
- const bufferPath = path9.join(this.stateDir, "buffer.json");
9159
+ const bufferPath = path10.join(this.stateDir, "buffer.json");
8233
9160
  try {
8234
9161
  const raw = await this.readStorageSecureFile(bufferPath);
8235
9162
  return JSON.parse(raw);
@@ -8241,11 +9168,11 @@ ${memory.content}
8241
9168
  }
8242
9169
  async saveBuffer(state) {
8243
9170
  await this.ensureDirectories();
8244
- const bufferPath = path9.join(this.stateDir, "buffer.json");
9171
+ const bufferPath = path10.join(this.stateDir, "buffer.json");
8245
9172
  await this.writeStorageSecureFile(bufferPath, JSON.stringify(state, null, 2));
8246
9173
  }
8247
9174
  async loadMeta() {
8248
- const metaPath = path9.join(this.stateDir, "meta.json");
9175
+ const metaPath = path10.join(this.stateDir, "meta.json");
8249
9176
  try {
8250
9177
  const raw = await this.readStorageSecureFile(metaPath);
8251
9178
  const parsed = JSON.parse(raw);
@@ -8278,7 +9205,7 @@ ${memory.content}
8278
9205
  }
8279
9206
  async saveMeta(state) {
8280
9207
  await this.ensureDirectories();
8281
- const metaPath = path9.join(this.stateDir, "meta.json");
9208
+ const metaPath = path10.join(this.stateDir, "meta.json");
8282
9209
  await this.writeStorageSecureFile(metaPath, JSON.stringify(state, null, 2));
8283
9210
  }
8284
9211
  async appendMemoryActionEvents(events) {
@@ -8345,7 +9272,7 @@ ${memory.content}
8345
9272
  },
8346
9273
  (payload) => this.appendStorageSecureFile(target, payload),
8347
9274
  async () => {
8348
- await mkdir2(path9.dirname(target), { recursive: true });
9275
+ await mkdir2(path10.dirname(target), { recursive: true });
8349
9276
  }
8350
9277
  );
8351
9278
  }
@@ -8443,7 +9370,7 @@ ${memory.content}
8443
9370
  async appendReextractJobs(events) {
8444
9371
  if (events.length === 0) return 0;
8445
9372
  await this.ensureDirectories();
8446
- const filePath = path9.join(this.stateDir, "reextract-jobs.jsonl");
9373
+ const filePath = path10.join(this.stateDir, "reextract-jobs.jsonl");
8447
9374
  const lines = events.map((event) => JSON.stringify(event)).join("\n") + "\n";
8448
9375
  try {
8449
9376
  await this.appendStorageSecureFile(filePath, lines);
@@ -8456,7 +9383,7 @@ ${memory.content}
8456
9383
  }
8457
9384
  async readReextractJobs(limit = 200) {
8458
9385
  const safeLimit = Number.isFinite(limit) ? Math.max(1, Math.min(1e3, Math.floor(limit))) : 200;
8459
- const filePath = path9.join(this.stateDir, "reextract-jobs.jsonl");
9386
+ const filePath = path10.join(this.stateDir, "reextract-jobs.jsonl");
8460
9387
  try {
8461
9388
  const raw = await this.readStorageSecureFile(filePath);
8462
9389
  const lines = raw.split("\n").filter((line) => line.trim().length > 0);
@@ -8617,8 +9544,8 @@ ${memory.content}
8617
9544
  activationState: "active"
8618
9545
  });
8619
9546
  await Promise.all([
8620
- unlink2(this.compressionGuidelineDraftPath).catch(() => void 0),
8621
- unlink2(this.compressionGuidelineDraftStatePath).catch(() => void 0)
9547
+ unlink3(this.compressionGuidelineDraftPath).catch(() => void 0),
9548
+ unlink3(this.compressionGuidelineDraftStatePath).catch(() => void 0)
8622
9549
  ]);
8623
9550
  return true;
8624
9551
  }
@@ -8686,7 +9613,7 @@ ${question}
8686
9613
 
8687
9614
  **Context:** ${context}
8688
9615
  `;
8689
- const filePath = path9.join(this.questionsDir, `${id}.md`);
9616
+ const filePath = path10.join(this.questionsDir, `${id}.md`);
8690
9617
  await this.writeStorageSecureFile(filePath, content);
8691
9618
  log.debug(`wrote question ${id} to ${filePath}`);
8692
9619
  this.invalidateQuestionsCache();
@@ -8704,7 +9631,7 @@ ${question}
8704
9631
  if (!match) return null;
8705
9632
  const frontmatterStr = match[1];
8706
9633
  const body = match[2].trim();
8707
- const id = this.extractFrontmatterValue(frontmatterStr, "id") ?? path9.basename(filePath, ".md");
9634
+ const id = this.extractFrontmatterValue(frontmatterStr, "id") ?? path10.basename(filePath, ".md");
8708
9635
  const created = this.extractFrontmatterValue(frontmatterStr, "created") ?? "";
8709
9636
  const priority = parseFloat(this.extractFrontmatterValue(frontmatterStr, "priority") ?? "0.5");
8710
9637
  const resolved = this.extractFrontmatterValue(frontmatterStr, "resolved") === "true";
@@ -8738,14 +9665,14 @@ ${question}
8738
9665
  async readIdentity(workspaceDir, namespace) {
8739
9666
  const identityPath = this.identityFilePath(workspaceDir, namespace);
8740
9667
  try {
8741
- return await readFile(identityPath, "utf-8");
9668
+ return await readFile2(identityPath, "utf-8");
8742
9669
  } catch {
8743
9670
  return "";
8744
9671
  }
8745
9672
  }
8746
9673
  async writeIdentity(workspaceDir, content, namespace) {
8747
9674
  const identityPath = this.identityFilePath(workspaceDir, namespace);
8748
- await writeFile(identityPath, content, "utf-8");
9675
+ await writeFile2(identityPath, content, "utf-8");
8749
9676
  log.debug(`wrote consolidated IDENTITY.md (${content.length} chars)`);
8750
9677
  }
8751
9678
  /** Max size for IDENTITY.md before we stop appending reflections (15KB leaves room under 20KB gateway limit) */
@@ -8756,22 +9683,22 @@ ${question}
8756
9683
  const identityPath = this.identityFilePath(workspaceDir, opts?.namespace);
8757
9684
  let existing = "";
8758
9685
  try {
8759
- existing = await readFile(identityPath, "utf-8");
9686
+ existing = await readFile2(identityPath, "utf-8");
8760
9687
  } catch {
8761
9688
  }
8762
9689
  const hygiene = opts?.hygiene;
8763
- const rotateEnabled = hygiene?.enabled === true && hygiene.rotateEnabled === true && Array.isArray(hygiene.rotatePaths) && hygiene.rotatePaths.includes(path9.basename(identityPath));
9690
+ const rotateEnabled = hygiene?.enabled === true && hygiene.rotateEnabled === true && Array.isArray(hygiene.rotatePaths) && hygiene.rotatePaths.includes(path10.basename(identityPath));
8764
9691
  if (rotateEnabled) {
8765
9692
  const maxBytes = hygiene.rotateMaxBytes;
8766
9693
  if (existing.length > maxBytes) {
8767
- const archiveDir = path9.join(workspaceDir, hygiene.archiveDir);
9694
+ const archiveDir = path10.join(workspaceDir, hygiene.archiveDir);
8768
9695
  const { newContent } = await rotateMarkdownFileToArchive({
8769
9696
  filePath: identityPath,
8770
9697
  archiveDir,
8771
9698
  archivePrefix: "IDENTITY",
8772
9699
  keepTailChars: hygiene.rotateKeepTailChars
8773
9700
  });
8774
- await writeFile(identityPath, newContent, "utf-8");
9701
+ await writeFile2(identityPath, newContent, "utf-8");
8775
9702
  existing = newContent;
8776
9703
  log.info(`rotated IDENTITY.md to archive (size=${existing.length} chars, maxBytes=${maxBytes})`);
8777
9704
  }
@@ -8804,7 +9731,7 @@ ${question}
8804
9731
 
8805
9732
  ${reflection}
8806
9733
  `;
8807
- await writeFile(identityPath, existing + section, "utf-8");
9734
+ await writeFile2(identityPath, existing + section, "utf-8");
8808
9735
  log.debug(`appended reflection to ${identityPath}`);
8809
9736
  }
8810
9737
  async readIdentityReflections() {
@@ -8860,7 +9787,7 @@ ${reflection}
8860
9787
  * Deduplicates by target+label.
8861
9788
  */
8862
9789
  async addEntityRelationship(name, rel) {
8863
- const filePath = path9.join(this.entitiesDir, `${name}.md`);
9790
+ const filePath = path10.join(this.entitiesDir, `${name}.md`);
8864
9791
  let entity;
8865
9792
  try {
8866
9793
  const content = await this.readStorageSecureFile(filePath);
@@ -8883,7 +9810,7 @@ ${reflection}
8883
9810
  * Prepends to the beginning, prunes oldest entries beyond maxEntries.
8884
9811
  */
8885
9812
  async addEntityActivity(name, entry, maxEntries) {
8886
- const filePath = path9.join(this.entitiesDir, `${name}.md`);
9813
+ const filePath = path10.join(this.entitiesDir, `${name}.md`);
8887
9814
  let entity;
8888
9815
  try {
8889
9816
  const content = await this.readStorageSecureFile(filePath);
@@ -8902,11 +9829,8 @@ ${reflection}
8902
9829
  await this.writeStorageSecureFile(filePath, serializeEntityFile(entity, this.entitySchemas));
8903
9830
  this.invalidateKnowledgeIndexCache();
8904
9831
  }
8905
- /**
8906
- * Add an alias to an entity file. Deduplicates.
8907
- */
8908
9832
  async addEntityAlias(name, alias) {
8909
- const filePath = path9.join(this.entitiesDir, `${name}.md`);
9833
+ const filePath = path10.join(this.entitiesDir, `${name}.md`);
8910
9834
  let entity;
8911
9835
  try {
8912
9836
  const content = await this.readStorageSecureFile(filePath);
@@ -8922,6 +9846,7 @@ ${reflection}
8922
9846
  entity.updated = (/* @__PURE__ */ new Date()).toISOString();
8923
9847
  await this.writeStorageSecureFile(filePath, serializeEntityFile(entity, this.entitySchemas));
8924
9848
  this.invalidateKnowledgeIndexCache();
9849
+ this.bumpMemoryStatusVersion();
8925
9850
  }
8926
9851
  async updateEntitySynthesis(name, synthesis, options = {}) {
8927
9852
  return this.entityStore.updateEntitySynthesis(name, synthesis, options);
@@ -8933,7 +9858,7 @@ ${reflection}
8933
9858
  const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
8934
9859
  let synthesisTimelineCount;
8935
9860
  try {
8936
- const filePath = path9.join(this.entitiesDir, `${name}.md`);
9861
+ const filePath = path10.join(this.entitiesDir, `${name}.md`);
8937
9862
  const content = await this.readStorageSecureFile(filePath);
8938
9863
  synthesisTimelineCount = parseEntityFile(content, this.entitySchemas).timeline.length;
8939
9864
  } catch (err) {
@@ -9016,7 +9941,7 @@ ${reflection}
9016
9941
  if (!raw) continue;
9017
9942
  const serialized = serializeEntityFile(parseEntityFile(raw, this.entitySchemas), this.entitySchemas);
9018
9943
  if (raw.trimEnd() === serialized.trimEnd()) continue;
9019
- await this.writeStorageSecureFile(path9.join(this.entitiesDir, `${entityName}.md`), serialized);
9944
+ await this.writeStorageSecureFile(path10.join(this.entitiesDir, `${entityName}.md`), serialized);
9020
9945
  migrated += 1;
9021
9946
  }
9022
9947
  if (migrated > 0) {
@@ -9084,7 +10009,7 @@ ${reflection}
9084
10009
  const updatedAt = new Date(m.frontmatter.updated).getTime();
9085
10010
  if (updatedAt < cutoff) {
9086
10011
  try {
9087
- await unlink2(m.path);
10012
+ await unlink3(m.path);
9088
10013
  markProjectedMemoryPathInvalid(this.baseDir, m.frontmatter.id);
9089
10014
  this.bumpMemoryCorpusVersion();
9090
10015
  deleted.push(m);
@@ -9109,14 +10034,14 @@ ${reflection}
9109
10034
  if (entries.length === 0) return 0;
9110
10035
  const memories = await this.readAllMemories();
9111
10036
  const memoryMap = new Map(memories.map((m) => [m.frontmatter.id, m]));
9112
- const memoryPathMap = new Map(memories.map((m) => [path9.resolve(m.path), m]));
10037
+ const memoryPathMap = new Map(memories.map((m) => [path10.resolve(m.path), m]));
9113
10038
  let updated = 0;
9114
10039
  const prevVersion = this.getMemoryCorpusVersion();
9115
10040
  const keyId = this.hotCacheKeyId();
9116
10041
  const warm = this.hotMemoriesCacheEnabled && getCachedMemories(this.baseDir, prevVersion, keyId, this.hotCacheTtlMs()) !== null;
9117
10042
  const appliedPatches = /* @__PURE__ */ new Map();
9118
10043
  for (const entry of entries) {
9119
- const memory = entry.memoryPath ? memoryPathMap.get(path9.resolve(entry.memoryPath)) : memoryMap.get(entry.memoryId);
10044
+ const memory = entry.memoryPath ? memoryPathMap.get(path10.resolve(entry.memoryPath)) : memoryMap.get(entry.memoryId);
9120
10045
  if (!memory) continue;
9121
10046
  const newFm = {
9122
10047
  ...memory.frontmatter,
@@ -9132,7 +10057,7 @@ ${memory.content}
9132
10057
  if (warm) {
9133
10058
  updateCacheOnWrite(this.baseDir, { ...memory, frontmatter: newFm }, keyId);
9134
10059
  }
9135
- appliedPatches.set(path9.resolve(memory.path), {
10060
+ appliedPatches.set(path10.resolve(memory.path), {
9136
10061
  accessCount: entry.newCount,
9137
10062
  lastAccessed: entry.lastAccessed
9138
10063
  });
@@ -9148,7 +10073,7 @@ ${memory.content}
9148
10073
  const cur = getCachedMemories(this.baseDir, prevVersion, keyId);
9149
10074
  if (cur) {
9150
10075
  const reapplied = cur.map((m) => {
9151
- const patch = appliedPatches.get(path9.resolve(m.path));
10076
+ const patch = appliedPatches.get(path10.resolve(m.path));
9152
10077
  return patch ? { ...m, frontmatter: { ...m.frontmatter, accessCount: patch.accessCount, lastAccessed: patch.lastAccessed } } : m;
9153
10078
  });
9154
10079
  setCachedMemories(this.baseDir, reapplied, produced, keyId, this.hotCacheTtlMs());
@@ -9180,7 +10105,7 @@ ${memory.content}
9180
10105
  const pathsById = /* @__PURE__ */ new Map();
9181
10106
  const filePathsById = /* @__PURE__ */ new Map();
9182
10107
  for (const filePath of filePaths) {
9183
- const memoryId = path9.basename(filePath, ".md");
10108
+ const memoryId = path10.basename(filePath, ".md");
9184
10109
  if (!wantedIds.has(memoryId)) continue;
9185
10110
  const paths = filePathsById.get(memoryId) ?? [];
9186
10111
  paths.push(filePath);
@@ -9195,7 +10120,7 @@ ${memory.content}
9195
10120
  qmdResultPathCandidates(this.baseDir, preferredPath)
9196
10121
  );
9197
10122
  const directMatch = existingPaths.find(
9198
- (filePath) => directCandidates.has(path9.resolve(filePath))
10123
+ (filePath) => directCandidates.has(path10.resolve(filePath))
9199
10124
  );
9200
10125
  if (directMatch) {
9201
10126
  preferredMatches.push(directMatch);
@@ -9208,7 +10133,7 @@ ${memory.content}
9208
10133
  candidates.add(candidate);
9209
10134
  }
9210
10135
  }
9211
- const match = existingPaths.find((filePath) => candidates.has(path9.resolve(filePath)));
10136
+ const match = existingPaths.find((filePath) => candidates.has(path10.resolve(filePath)));
9212
10137
  if (match) preferredMatches.push(match);
9213
10138
  }
9214
10139
  if (preferredMatches.length > 0) {
@@ -9427,14 +10352,14 @@ Reason: ${reason}`;
9427
10352
  // Memory Summarization (Phase 4A)
9428
10353
  // ---------------------------------------------------------------------------
9429
10354
  get summariesDir() {
9430
- return path9.join(this.baseDir, "summaries");
10355
+ return path10.join(this.baseDir, "summaries");
9431
10356
  }
9432
10357
  /**
9433
10358
  * Write a memory summary.
9434
10359
  */
9435
10360
  async writeSummary(summary) {
9436
10361
  await mkdir2(this.summariesDir, { recursive: true });
9437
- const filePath = path9.join(this.summariesDir, `${summary.id}.json`);
10362
+ const filePath = path10.join(this.summariesDir, `${summary.id}.json`);
9438
10363
  await this.writeStorageSecureFile(filePath, JSON.stringify(summary, null, 2));
9439
10364
  log.debug(`wrote summary ${summary.id}`);
9440
10365
  }
@@ -9443,11 +10368,11 @@ Reason: ${reason}`;
9443
10368
  */
9444
10369
  async readSummaries() {
9445
10370
  try {
9446
- const files = await readdir4(this.summariesDir);
10371
+ const files = await readdir5(this.summariesDir);
9447
10372
  const summaries = [];
9448
10373
  for (const file of files) {
9449
10374
  if (!file.endsWith(".json")) continue;
9450
- const filePath = path9.join(this.summariesDir, file);
10375
+ const filePath = path10.join(this.summariesDir, file);
9451
10376
  const raw = await this.readStorageSecureFile(filePath);
9452
10377
  summaries.push(JSON.parse(raw));
9453
10378
  }
@@ -9509,7 +10434,7 @@ ${memory.content}
9509
10434
  * Save topic scores to meta.json.
9510
10435
  */
9511
10436
  async saveTopics(topics) {
9512
- const metaPath = path9.join(this.stateDir, "topics.json");
10437
+ const metaPath = path10.join(this.stateDir, "topics.json");
9513
10438
  await mkdir2(this.stateDir, { recursive: true });
9514
10439
  await this.writeStorageSecureFile(
9515
10440
  metaPath,
@@ -9521,7 +10446,7 @@ ${memory.content}
9521
10446
  * Load topic scores from meta.json.
9522
10447
  */
9523
10448
  async loadTopics() {
9524
- const metaPath = path9.join(this.stateDir, "topics.json");
10449
+ const metaPath = path10.join(this.stateDir, "topics.json");
9525
10450
  try {
9526
10451
  const raw = await this.readStorageSecureFile(metaPath);
9527
10452
  return JSON.parse(raw);
@@ -9637,11 +10562,10 @@ export {
9637
10562
  parseFrontmatterStringValue,
9638
10563
  parseFrontmatter,
9639
10564
  normalizeFrontmatterForPath,
9640
- normalizeEntityName,
9641
10565
  parseEntityFile,
9642
10566
  serializeEntityFile,
9643
10567
  buildEntitySchemaCacheKey,
9644
10568
  isValidBufferSurpriseEvent,
9645
10569
  StorageManager3 as StorageManager
9646
10570
  };
9647
- //# sourceMappingURL=chunk-CIQXI47W.js.map
10571
+ //# sourceMappingURL=chunk-FCDWWCLX.js.map