@remnic/core 10.0.27 → 10.0.29

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 (372) hide show
  1. package/dist/access-admin-ops-surface.js +54 -53
  2. package/dist/access-authorization-probe.js +55 -54
  3. package/dist/access-boundary.js +54 -53
  4. package/dist/access-citation-namespace.js +3 -2
  5. package/dist/access-cli.js +106 -105
  6. package/dist/access-cli.js.map +1 -1
  7. package/dist/access-extraction-force-flush.js +54 -53
  8. package/dist/access-http-briefing.js +55 -54
  9. package/dist/access-http-query.js +56 -55
  10. package/dist/access-http.js +73 -72
  11. package/dist/access-identity-continuity-surface.js +54 -53
  12. package/dist/access-lcm-surface.js +54 -53
  13. package/dist/access-mcp.js +65 -64
  14. package/dist/access-namespace-preflight.js +54 -53
  15. package/dist/access-observe-write-category.js +11 -11
  16. package/dist/access-observe-write-surface.js +54 -53
  17. package/dist/access-offline-manifest.js +10 -10
  18. package/dist/access-operations-batch.js +56 -55
  19. package/dist/access-operations.js +63 -62
  20. package/dist/access-recall-concurrency.js +54 -53
  21. package/dist/access-recall-diagnostics.js +2 -2
  22. package/dist/access-recall-response.js +54 -53
  23. package/dist/access-recall-surface.js +54 -53
  24. package/dist/access-schema.js +6 -5
  25. package/dist/access-service.js +54 -53
  26. package/dist/access-surface-catalog.js +56 -55
  27. package/dist/access-surface-catalog.js.map +1 -1
  28. package/dist/active-recall.js +24 -23
  29. package/dist/active-recall.js.map +1 -1
  30. package/dist/{auto-sync-UQESPLCB.js → auto-sync-MX2AHVPQ.js} +8 -8
  31. package/dist/briefing.js +20 -19
  32. package/dist/buffer.js +8 -8
  33. package/dist/calibration.js +2 -2
  34. package/dist/{capsule-merge-LGYURS3C.js → capsule-merge-LGYZAMO4.js} +3 -3
  35. package/dist/causal-consolidation.js +22 -21
  36. package/dist/causal-consolidation.js.map +1 -1
  37. package/dist/{chunk-G6XEYFCO.js → chunk-27OJ5G3D.js} +14 -14
  38. package/dist/{chunk-5LRV557D.js → chunk-2FIJQNL7.js} +2 -2
  39. package/dist/{chunk-ETPIYK4J.js → chunk-2VBDSZ7U.js} +2 -2
  40. package/dist/{chunk-QNKEMFZY.js → chunk-2WDMUQOH.js} +2 -2
  41. package/dist/{chunk-W6MOLW5S.js → chunk-2XVLY424.js} +4 -4
  42. package/dist/{chunk-P55FACBG.js → chunk-3BOQPLCF.js} +6 -6
  43. package/dist/{chunk-27SAUQ5R.js → chunk-3CHHQXAR.js} +2 -2
  44. package/dist/{chunk-3GYSZHMT.js → chunk-3CZRBTJK.js} +2 -2
  45. package/dist/{chunk-FJJWA7NL.js → chunk-3EJQXF3B.js} +2 -2
  46. package/dist/{chunk-HFSPY26A.js → chunk-3IXNL6SK.js} +2 -2
  47. package/dist/{chunk-PLD6SOU7.js → chunk-3SN2D43X.js} +2 -2
  48. package/dist/{chunk-COGLFRXT.js → chunk-4HNINU7Q.js} +31 -31
  49. package/dist/{chunk-CCDHRDQ3.js → chunk-4HYP4OKH.js} +2 -2
  50. package/dist/{chunk-GKJJNO7C.js → chunk-4OE4UE2Y.js} +6 -6
  51. package/dist/{chunk-7RTNJ6M2.js → chunk-4QPW6JVI.js} +2 -2
  52. package/dist/{chunk-5SMR542T.js → chunk-5GT4ESLR.js} +2 -2
  53. package/dist/{chunk-DWL6YIZH.js → chunk-5JI3XWI2.js} +2 -2
  54. package/dist/{chunk-27LPB4NS.js → chunk-5NPZFXQH.js} +2 -2
  55. package/dist/{chunk-Y6IF6H2U.js → chunk-5SMHQW45.js} +2 -2
  56. package/dist/{chunk-VN3GHPBU.js → chunk-654GT5UP.js} +2 -2
  57. package/dist/{chunk-3E6DGSGZ.js → chunk-6MC7UQ6D.js} +2 -2
  58. package/dist/{chunk-655FVTCD.js → chunk-74IN6PV5.js} +2 -2
  59. package/dist/{chunk-WFUO7NWX.js → chunk-7FZ4YVOH.js} +2 -2
  60. package/dist/{chunk-MWWAQXZ6.js → chunk-7HFTCBCZ.js} +2 -2
  61. package/dist/{chunk-7IOB5F7Y.js → chunk-7VB3Y5OL.js} +3 -3
  62. package/dist/{chunk-YEF5AAWN.js → chunk-A54E2ZTD.js} +2 -2
  63. package/dist/{chunk-DEY7B77Y.js → chunk-AHCELJMH.js} +2 -2
  64. package/dist/{chunk-PIWFNPQT.js → chunk-AL3TCNSJ.js} +4 -4
  65. package/dist/{chunk-EET24NSB.js → chunk-AUYFUBBE.js} +6 -6
  66. package/dist/{chunk-L3IP56F4.js → chunk-BIE3ZH3N.js} +33 -33
  67. package/dist/{chunk-A3IURDU2.js → chunk-C2AOL6MK.js} +3 -3
  68. package/dist/{chunk-BDQMMX3M.js → chunk-C2QVDLQV.js} +2 -2
  69. package/dist/{chunk-H75L4ZOH.js → chunk-CKR7LXEK.js} +71 -49
  70. package/dist/chunk-CKR7LXEK.js.map +1 -0
  71. package/dist/{chunk-AWLQNLTM.js → chunk-CSGFGQBI.js} +2 -2
  72. package/dist/{chunk-JHQAXATW.js → chunk-D4RV54HH.js} +2 -2
  73. package/dist/{chunk-33UAWCBN.js → chunk-DDLRKPR2.js} +6 -6
  74. package/dist/{chunk-3X3PNU3T.js → chunk-DLH3ECZP.js} +5 -5
  75. package/dist/chunk-DNIG3JME.js +892 -0
  76. package/dist/chunk-DNIG3JME.js.map +1 -0
  77. package/dist/{chunk-SA6GMZJY.js → chunk-DP3TSAYT.js} +2 -2
  78. package/dist/{chunk-H2X22KZW.js → chunk-FN6OFDBZ.js} +2 -2
  79. package/dist/{chunk-SU5V2LWR.js → chunk-G6DAE2LT.js} +2 -2
  80. package/dist/{chunk-V7KGDLBC.js → chunk-GQ7VWY6N.js} +2 -2
  81. package/dist/{chunk-SYUNCM26.js → chunk-GSKW64NB.js} +2 -2
  82. package/dist/{chunk-4WT6I4VG.js → chunk-GWB7ZD2A.js} +2 -2
  83. package/dist/{chunk-JYZLDZ2R.js → chunk-HG2VVIKI.js} +9 -9
  84. package/dist/{chunk-3VRMUNWL.js → chunk-HJ444KNS.js} +15 -7
  85. package/dist/chunk-HJ444KNS.js.map +1 -0
  86. package/dist/{chunk-23ZQPP2G.js → chunk-HOSJESKO.js} +3 -3
  87. package/dist/{chunk-EU6IRUCY.js → chunk-IDPZCHET.js} +2 -2
  88. package/dist/{chunk-VMHCC7LO.js → chunk-IO2UQVR2.js} +2 -2
  89. package/dist/{chunk-BWXKJDDH.js → chunk-ISMZ5UNE.js} +3 -3
  90. package/dist/{chunk-SX4QDWXK.js → chunk-IWUFKS4J.js} +2 -2
  91. package/dist/{chunk-I27WOMJ7.js → chunk-IY7DGT2Z.js} +2 -2
  92. package/dist/{chunk-STBX5X6B.js → chunk-JAYNUYSJ.js} +2 -2
  93. package/dist/{chunk-N34ZW6E4.js → chunk-K2REHR42.js} +2 -2
  94. package/dist/{chunk-UJPGQCXD.js → chunk-KFKFK6G6.js} +10 -10
  95. package/dist/{chunk-2HLMFRZ7.js → chunk-LDEKVBVO.js} +4 -4
  96. package/dist/{chunk-42KSEX6C.js → chunk-LDXNKEYB.js} +1 -1
  97. package/dist/chunk-LDXNKEYB.js.map +1 -0
  98. package/dist/{chunk-MPZYCRC6.js → chunk-M236YHUH.js} +5 -5
  99. package/dist/{chunk-L5VCT7LU.js → chunk-MCLZM5G7.js} +2 -2
  100. package/dist/{chunk-7Z3DLNSD.js → chunk-MGKH5KO3.js} +2 -2
  101. package/dist/{chunk-PUDYANAX.js → chunk-MMBLOJJB.js} +2 -2
  102. package/dist/{chunk-EFHNFTWB.js → chunk-MND4YJSX.js} +2 -2
  103. package/dist/{chunk-HJQXHLQQ.js → chunk-MROA6OFU.js} +2 -2
  104. package/dist/{chunk-BQOGQULP.js → chunk-MZZEMPCI.js} +2 -2
  105. package/dist/{chunk-ERAVI25Z.js → chunk-NAPHQ2MG.js} +2 -2
  106. package/dist/{chunk-L5TJWQEF.js → chunk-NB2YX6X2.js} +6 -6
  107. package/dist/{chunk-IHGLQJW6.js → chunk-NCPR2FOJ.js} +3 -3
  108. package/dist/{chunk-UKWRCQWT.js → chunk-NOMHXZD7.js} +2 -2
  109. package/dist/{chunk-DF2G4IXN.js → chunk-NPO4ZQFY.js} +3 -3
  110. package/dist/{chunk-LWFWZTWX.js → chunk-NQV6G6MU.js} +2 -2
  111. package/dist/{chunk-5HT35H4L.js → chunk-NRLWHZVS.js} +2 -2
  112. package/dist/{chunk-GCZHKBY2.js → chunk-OANSZGAG.js} +2 -2
  113. package/dist/{chunk-BHQPOCQE.js → chunk-OIIAIY7J.js} +3 -3
  114. package/dist/{chunk-FFGHFU7A.js → chunk-OXX4ORRL.js} +17 -17
  115. package/dist/{chunk-RTTPBBAN.js → chunk-OXYXMGRH.js} +4 -4
  116. package/dist/{chunk-K7BN34IA.js → chunk-PL26BCRN.js} +5 -5
  117. package/dist/{chunk-PM72NSEW.js → chunk-PYCTZ2HX.js} +2 -2
  118. package/dist/{chunk-AQ52ZFBC.js → chunk-PZEADMX4.js} +2 -2
  119. package/dist/{chunk-QPH52AZB.js → chunk-QNDOTDJK.js} +2 -2
  120. package/dist/{chunk-LZACDIM2.js → chunk-RBGRQEW3.js} +4 -4
  121. package/dist/{chunk-H3AW6QZF.js → chunk-RRJ462HP.js} +2 -2
  122. package/dist/{chunk-V4JZCTMK.js → chunk-TKBW4YLS.js} +2 -2
  123. package/dist/{chunk-4D2YH47Z.js → chunk-TRW7N4FS.js} +2 -2
  124. package/dist/{chunk-IHS2UGYM.js → chunk-TTIEXXL3.js} +366 -1109
  125. package/dist/chunk-TTIEXXL3.js.map +1 -0
  126. package/dist/{chunk-OQJKY3Z5.js → chunk-UAAAXSKQ.js} +2 -2
  127. package/dist/{chunk-S36KJNQH.js → chunk-UM73Q46J.js} +2 -2
  128. package/dist/{chunk-7EJCAFMS.js → chunk-UTXYOWDR.js} +2 -2
  129. package/dist/{chunk-AYHPSYZI.js → chunk-UUYAW3JH.js} +2 -2
  130. package/dist/{chunk-MSMGQDVW.js → chunk-UVUBLLM3.js} +3 -3
  131. package/dist/{chunk-JZIZBJCW.js → chunk-V4FI2TG6.js} +3 -3
  132. package/dist/{chunk-MO6N4QYY.js → chunk-VARNSLUW.js} +4 -4
  133. package/dist/{chunk-WJAGO5LL.js → chunk-VEB7NEON.js} +4 -4
  134. package/dist/{chunk-GMZNJZRP.js → chunk-VLBFSD7B.js} +2 -2
  135. package/dist/{chunk-NZFFGO5O.js → chunk-VXWOJPSY.js} +36 -3
  136. package/dist/chunk-VXWOJPSY.js.map +1 -0
  137. package/dist/{chunk-JNIVZNIB.js → chunk-WKVL2G7X.js} +4 -4
  138. package/dist/{chunk-KJXP6RUG.js → chunk-WNEVEMJ3.js} +4 -4
  139. package/dist/{chunk-HNEOLXRF.js → chunk-WQIYGYY6.js} +2 -2
  140. package/dist/{chunk-GQJKVQJR.js → chunk-WYLBEJQI.js} +2 -2
  141. package/dist/{chunk-36DZ242S.js → chunk-XNROYP5E.js} +2 -2
  142. package/dist/{chunk-XNAOCY67.js → chunk-XVZIBMSY.js} +3 -3
  143. package/dist/{chunk-PXTLPC3P.js → chunk-YGVZ4QOZ.js} +4 -4
  144. package/dist/{chunk-JX32ROLZ.js → chunk-YZTFQBYY.js} +4 -4
  145. package/dist/{chunk-XSXM5LYZ.js → chunk-ZCRDYQL6.js} +2 -2
  146. package/dist/{chunk-MAAL6OZV.js → chunk-ZG3HZZ6K.js} +90 -36
  147. package/dist/chunk-ZG3HZZ6K.js.map +1 -0
  148. package/dist/{chunk-Z3XVYXQ3.js → chunk-ZXTAHSQU.js} +2 -2
  149. package/dist/cli.js +89 -88
  150. package/dist/coding/export-okf-codegraph.js +21 -20
  151. package/dist/coding/export-okf-codegraph.js.map +1 -1
  152. package/dist/compounding/engine.js +23 -22
  153. package/dist/config.js +24 -23
  154. package/dist/connectors/codex-materialize-runner.js +21 -20
  155. package/dist/connectors/codex-materialize.js +2 -2
  156. package/dist/connectors/index.js +21 -20
  157. package/dist/consolidation-provenance-check.js +3 -3
  158. package/dist/consolidation-undo.js +2 -2
  159. package/dist/contradiction/index.js +6 -5
  160. package/dist/convergence-refresh.js +22 -21
  161. package/dist/corpus-watermark.js +22 -21
  162. package/dist/deep-recall-http-glue.js +7 -6
  163. package/dist/entity-canonical-id-migration-GD5MPFUF.js +28 -0
  164. package/dist/entity-retrieval.js +20 -19
  165. package/dist/explicit-capture.js +8 -7
  166. package/dist/external-wiki-access.js +55 -54
  167. package/dist/extraction.js +27 -26
  168. package/dist/harmonic-retrieval.js +21 -20
  169. package/dist/harmonic-source-lookup.js +3 -2
  170. package/dist/index.js +106 -105
  171. package/dist/local-llm-rate-limit.d.ts +3 -1
  172. package/dist/local-llm-rate-limit.d.ts.map +1 -1
  173. package/dist/local-llm-rate-limit.js +1 -1
  174. package/dist/local-llm.js +2 -2
  175. package/dist/location/index.js +23 -22
  176. package/dist/maintenance/memory-governance.js +20 -19
  177. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +20 -19
  178. package/dist/maintenance/rebuild-memory-projection-runner.js +22 -21
  179. package/dist/maintenance/rebuild-memory-projection.js +21 -20
  180. package/dist/memory-browse-operations.js +55 -54
  181. package/dist/memory-subject.js +4 -3
  182. package/dist/namespaces/migrate.js +21 -20
  183. package/dist/namespaces/search.js +7 -7
  184. package/dist/namespaces/storage.js +20 -19
  185. package/dist/offline-sync-file-io.js +3 -2
  186. package/dist/offline-sync-impression-drain.js +4 -4
  187. package/dist/offline-sync-snapshot-stream.js +6 -5
  188. package/dist/offline-sync-upload-staging.js +4 -3
  189. package/dist/offline-sync.js +5 -4
  190. package/dist/operator-doctor-corpus.js +23 -22
  191. package/dist/operator-toolkit.js +34 -33
  192. package/dist/orchestration/maintenance.js +35 -34
  193. package/dist/orchestration/orchestrator-init.d.ts +3 -0
  194. package/dist/orchestration/orchestrator-init.d.ts.map +1 -1
  195. package/dist/orchestrator.d.ts.map +1 -1
  196. package/dist/orchestrator.js +106 -105
  197. package/dist/page-versioning.js +2 -2
  198. package/dist/recall-explain-renderer.js +3 -3
  199. package/dist/recall-navigate-access.js +2 -2
  200. package/dist/recall-navigate-disclosure.js +2 -2
  201. package/dist/recall-navigate.js +2 -2
  202. package/dist/recall-navigation-operations.js +55 -54
  203. package/dist/recall-navigation.js +54 -53
  204. package/dist/recall-state.js +2 -2
  205. package/dist/recall-xray-cli.js +4 -4
  206. package/dist/recall-xray-renderer.js +3 -3
  207. package/dist/recall-xray.js +2 -2
  208. package/dist/reconcile/manifest.js +4 -3
  209. package/dist/{resolution-ZU5BIAJA.js → resolution-AMYTPT5X.js} +7 -6
  210. package/dist/resolution-AMYTPT5X.js.map +1 -0
  211. package/dist/resume-bundles.js +25 -24
  212. package/dist/retrieval-agents.js +3 -2
  213. package/dist/salvage-envelope.js +6 -5
  214. package/dist/search/document-scanner.js +2 -2
  215. package/dist/search/factory.js +6 -6
  216. package/dist/search/index.js +6 -6
  217. package/dist/search/lancedb-backend.js +3 -3
  218. package/dist/search/meilisearch-backend.js +3 -3
  219. package/dist/search/orama-backend.js +3 -3
  220. package/dist/secure-store/entity-file-read.d.ts +9 -0
  221. package/dist/secure-store/entity-file-read.d.ts.map +1 -0
  222. package/dist/secure-store/index.js +3 -2
  223. package/dist/secure-store/secure-fs.d.ts.map +1 -1
  224. package/dist/semantic-consolidation.js +22 -21
  225. package/dist/semantic-rule-promotion.js +20 -19
  226. package/dist/semantic-rule-verifier.js +20 -19
  227. package/dist/shared-context/manager.js +2 -2
  228. package/dist/source-agent-qualifier.js +24 -23
  229. package/dist/standup/build.js +20 -19
  230. package/dist/storage/entity-canonical-id-migration-runner.d.ts +12 -0
  231. package/dist/storage/entity-canonical-id-migration-runner.d.ts.map +1 -1
  232. package/dist/storage/entity-canonical-id-migration.d.ts +1 -0
  233. package/dist/storage/entity-canonical-id-migration.d.ts.map +1 -1
  234. package/dist/storage/entity-canonical-id-references.d.ts +14 -0
  235. package/dist/storage/entity-canonical-id-references.d.ts.map +1 -1
  236. package/dist/storage/entity-store.d.ts +4 -0
  237. package/dist/storage/entity-store.d.ts.map +1 -1
  238. package/dist/storage.d.ts +7 -2
  239. package/dist/storage.d.ts.map +1 -1
  240. package/dist/storage.js +19 -18
  241. package/dist/subject-config.js +5 -4
  242. package/dist/summarizer.js +3 -3
  243. package/dist/support-passport/index.js +57 -56
  244. package/dist/transfer/capsule-import.js +3 -3
  245. package/dist/transfer/export-okf.js +21 -20
  246. package/dist/types.d.ts +1 -1
  247. package/dist/types.d.ts.map +1 -1
  248. package/dist/types.js +1 -1
  249. package/dist/verified-recall.js +20 -19
  250. package/dist/who-knows-cli.js +21 -20
  251. package/dist/who-knows.js +20 -19
  252. package/dist/write-envelope.js +5 -4
  253. package/package.json +2 -2
  254. package/src/local-llm-rate-limit.test.ts +59 -1
  255. package/src/local-llm-rate-limit.ts +22 -7
  256. package/src/orchestration/orchestrator-init.ts +26 -3
  257. package/src/orchestrator.ts +1 -0
  258. package/src/secure-store/entity-file-read.ts +55 -0
  259. package/src/secure-store/secure-fs.ts +2 -1
  260. package/src/storage/entity-canonical-id-migration-runner.ts +36 -0
  261. package/src/storage/entity-canonical-id-migration.ts +1 -1
  262. package/src/storage/entity-canonical-id-references.ts +57 -2
  263. package/src/storage/entity-store.ts +138 -25
  264. package/src/storage.ts +15 -15
  265. package/src/types.ts +1 -1
  266. package/dist/chunk-3VRMUNWL.js.map +0 -1
  267. package/dist/chunk-42KSEX6C.js.map +0 -1
  268. package/dist/chunk-H75L4ZOH.js.map +0 -1
  269. package/dist/chunk-IHS2UGYM.js.map +0 -1
  270. package/dist/chunk-MAAL6OZV.js.map +0 -1
  271. package/dist/chunk-NZFFGO5O.js.map +0 -1
  272. /package/dist/{auto-sync-UQESPLCB.js.map → auto-sync-MX2AHVPQ.js.map} +0 -0
  273. /package/dist/{capsule-merge-LGYURS3C.js.map → capsule-merge-LGYZAMO4.js.map} +0 -0
  274. /package/dist/{chunk-G6XEYFCO.js.map → chunk-27OJ5G3D.js.map} +0 -0
  275. /package/dist/{chunk-5LRV557D.js.map → chunk-2FIJQNL7.js.map} +0 -0
  276. /package/dist/{chunk-ETPIYK4J.js.map → chunk-2VBDSZ7U.js.map} +0 -0
  277. /package/dist/{chunk-QNKEMFZY.js.map → chunk-2WDMUQOH.js.map} +0 -0
  278. /package/dist/{chunk-W6MOLW5S.js.map → chunk-2XVLY424.js.map} +0 -0
  279. /package/dist/{chunk-P55FACBG.js.map → chunk-3BOQPLCF.js.map} +0 -0
  280. /package/dist/{chunk-27SAUQ5R.js.map → chunk-3CHHQXAR.js.map} +0 -0
  281. /package/dist/{chunk-3GYSZHMT.js.map → chunk-3CZRBTJK.js.map} +0 -0
  282. /package/dist/{chunk-FJJWA7NL.js.map → chunk-3EJQXF3B.js.map} +0 -0
  283. /package/dist/{chunk-HFSPY26A.js.map → chunk-3IXNL6SK.js.map} +0 -0
  284. /package/dist/{chunk-PLD6SOU7.js.map → chunk-3SN2D43X.js.map} +0 -0
  285. /package/dist/{chunk-COGLFRXT.js.map → chunk-4HNINU7Q.js.map} +0 -0
  286. /package/dist/{chunk-CCDHRDQ3.js.map → chunk-4HYP4OKH.js.map} +0 -0
  287. /package/dist/{chunk-GKJJNO7C.js.map → chunk-4OE4UE2Y.js.map} +0 -0
  288. /package/dist/{chunk-7RTNJ6M2.js.map → chunk-4QPW6JVI.js.map} +0 -0
  289. /package/dist/{chunk-5SMR542T.js.map → chunk-5GT4ESLR.js.map} +0 -0
  290. /package/dist/{chunk-DWL6YIZH.js.map → chunk-5JI3XWI2.js.map} +0 -0
  291. /package/dist/{chunk-27LPB4NS.js.map → chunk-5NPZFXQH.js.map} +0 -0
  292. /package/dist/{chunk-Y6IF6H2U.js.map → chunk-5SMHQW45.js.map} +0 -0
  293. /package/dist/{chunk-VN3GHPBU.js.map → chunk-654GT5UP.js.map} +0 -0
  294. /package/dist/{chunk-3E6DGSGZ.js.map → chunk-6MC7UQ6D.js.map} +0 -0
  295. /package/dist/{chunk-655FVTCD.js.map → chunk-74IN6PV5.js.map} +0 -0
  296. /package/dist/{chunk-WFUO7NWX.js.map → chunk-7FZ4YVOH.js.map} +0 -0
  297. /package/dist/{chunk-MWWAQXZ6.js.map → chunk-7HFTCBCZ.js.map} +0 -0
  298. /package/dist/{chunk-7IOB5F7Y.js.map → chunk-7VB3Y5OL.js.map} +0 -0
  299. /package/dist/{chunk-YEF5AAWN.js.map → chunk-A54E2ZTD.js.map} +0 -0
  300. /package/dist/{chunk-DEY7B77Y.js.map → chunk-AHCELJMH.js.map} +0 -0
  301. /package/dist/{chunk-PIWFNPQT.js.map → chunk-AL3TCNSJ.js.map} +0 -0
  302. /package/dist/{chunk-EET24NSB.js.map → chunk-AUYFUBBE.js.map} +0 -0
  303. /package/dist/{chunk-L3IP56F4.js.map → chunk-BIE3ZH3N.js.map} +0 -0
  304. /package/dist/{chunk-A3IURDU2.js.map → chunk-C2AOL6MK.js.map} +0 -0
  305. /package/dist/{chunk-BDQMMX3M.js.map → chunk-C2QVDLQV.js.map} +0 -0
  306. /package/dist/{chunk-AWLQNLTM.js.map → chunk-CSGFGQBI.js.map} +0 -0
  307. /package/dist/{chunk-JHQAXATW.js.map → chunk-D4RV54HH.js.map} +0 -0
  308. /package/dist/{chunk-33UAWCBN.js.map → chunk-DDLRKPR2.js.map} +0 -0
  309. /package/dist/{chunk-3X3PNU3T.js.map → chunk-DLH3ECZP.js.map} +0 -0
  310. /package/dist/{chunk-SA6GMZJY.js.map → chunk-DP3TSAYT.js.map} +0 -0
  311. /package/dist/{chunk-H2X22KZW.js.map → chunk-FN6OFDBZ.js.map} +0 -0
  312. /package/dist/{chunk-SU5V2LWR.js.map → chunk-G6DAE2LT.js.map} +0 -0
  313. /package/dist/{chunk-V7KGDLBC.js.map → chunk-GQ7VWY6N.js.map} +0 -0
  314. /package/dist/{chunk-SYUNCM26.js.map → chunk-GSKW64NB.js.map} +0 -0
  315. /package/dist/{chunk-4WT6I4VG.js.map → chunk-GWB7ZD2A.js.map} +0 -0
  316. /package/dist/{chunk-JYZLDZ2R.js.map → chunk-HG2VVIKI.js.map} +0 -0
  317. /package/dist/{chunk-23ZQPP2G.js.map → chunk-HOSJESKO.js.map} +0 -0
  318. /package/dist/{chunk-EU6IRUCY.js.map → chunk-IDPZCHET.js.map} +0 -0
  319. /package/dist/{chunk-VMHCC7LO.js.map → chunk-IO2UQVR2.js.map} +0 -0
  320. /package/dist/{chunk-BWXKJDDH.js.map → chunk-ISMZ5UNE.js.map} +0 -0
  321. /package/dist/{chunk-SX4QDWXK.js.map → chunk-IWUFKS4J.js.map} +0 -0
  322. /package/dist/{chunk-I27WOMJ7.js.map → chunk-IY7DGT2Z.js.map} +0 -0
  323. /package/dist/{chunk-STBX5X6B.js.map → chunk-JAYNUYSJ.js.map} +0 -0
  324. /package/dist/{chunk-N34ZW6E4.js.map → chunk-K2REHR42.js.map} +0 -0
  325. /package/dist/{chunk-UJPGQCXD.js.map → chunk-KFKFK6G6.js.map} +0 -0
  326. /package/dist/{chunk-2HLMFRZ7.js.map → chunk-LDEKVBVO.js.map} +0 -0
  327. /package/dist/{chunk-MPZYCRC6.js.map → chunk-M236YHUH.js.map} +0 -0
  328. /package/dist/{chunk-L5VCT7LU.js.map → chunk-MCLZM5G7.js.map} +0 -0
  329. /package/dist/{chunk-7Z3DLNSD.js.map → chunk-MGKH5KO3.js.map} +0 -0
  330. /package/dist/{chunk-PUDYANAX.js.map → chunk-MMBLOJJB.js.map} +0 -0
  331. /package/dist/{chunk-EFHNFTWB.js.map → chunk-MND4YJSX.js.map} +0 -0
  332. /package/dist/{chunk-HJQXHLQQ.js.map → chunk-MROA6OFU.js.map} +0 -0
  333. /package/dist/{chunk-BQOGQULP.js.map → chunk-MZZEMPCI.js.map} +0 -0
  334. /package/dist/{chunk-ERAVI25Z.js.map → chunk-NAPHQ2MG.js.map} +0 -0
  335. /package/dist/{chunk-L5TJWQEF.js.map → chunk-NB2YX6X2.js.map} +0 -0
  336. /package/dist/{chunk-IHGLQJW6.js.map → chunk-NCPR2FOJ.js.map} +0 -0
  337. /package/dist/{chunk-UKWRCQWT.js.map → chunk-NOMHXZD7.js.map} +0 -0
  338. /package/dist/{chunk-DF2G4IXN.js.map → chunk-NPO4ZQFY.js.map} +0 -0
  339. /package/dist/{chunk-LWFWZTWX.js.map → chunk-NQV6G6MU.js.map} +0 -0
  340. /package/dist/{chunk-5HT35H4L.js.map → chunk-NRLWHZVS.js.map} +0 -0
  341. /package/dist/{chunk-GCZHKBY2.js.map → chunk-OANSZGAG.js.map} +0 -0
  342. /package/dist/{chunk-BHQPOCQE.js.map → chunk-OIIAIY7J.js.map} +0 -0
  343. /package/dist/{chunk-FFGHFU7A.js.map → chunk-OXX4ORRL.js.map} +0 -0
  344. /package/dist/{chunk-RTTPBBAN.js.map → chunk-OXYXMGRH.js.map} +0 -0
  345. /package/dist/{chunk-K7BN34IA.js.map → chunk-PL26BCRN.js.map} +0 -0
  346. /package/dist/{chunk-PM72NSEW.js.map → chunk-PYCTZ2HX.js.map} +0 -0
  347. /package/dist/{chunk-AQ52ZFBC.js.map → chunk-PZEADMX4.js.map} +0 -0
  348. /package/dist/{chunk-QPH52AZB.js.map → chunk-QNDOTDJK.js.map} +0 -0
  349. /package/dist/{chunk-LZACDIM2.js.map → chunk-RBGRQEW3.js.map} +0 -0
  350. /package/dist/{chunk-H3AW6QZF.js.map → chunk-RRJ462HP.js.map} +0 -0
  351. /package/dist/{chunk-V4JZCTMK.js.map → chunk-TKBW4YLS.js.map} +0 -0
  352. /package/dist/{chunk-4D2YH47Z.js.map → chunk-TRW7N4FS.js.map} +0 -0
  353. /package/dist/{chunk-OQJKY3Z5.js.map → chunk-UAAAXSKQ.js.map} +0 -0
  354. /package/dist/{chunk-S36KJNQH.js.map → chunk-UM73Q46J.js.map} +0 -0
  355. /package/dist/{chunk-7EJCAFMS.js.map → chunk-UTXYOWDR.js.map} +0 -0
  356. /package/dist/{chunk-AYHPSYZI.js.map → chunk-UUYAW3JH.js.map} +0 -0
  357. /package/dist/{chunk-MSMGQDVW.js.map → chunk-UVUBLLM3.js.map} +0 -0
  358. /package/dist/{chunk-JZIZBJCW.js.map → chunk-V4FI2TG6.js.map} +0 -0
  359. /package/dist/{chunk-MO6N4QYY.js.map → chunk-VARNSLUW.js.map} +0 -0
  360. /package/dist/{chunk-WJAGO5LL.js.map → chunk-VEB7NEON.js.map} +0 -0
  361. /package/dist/{chunk-GMZNJZRP.js.map → chunk-VLBFSD7B.js.map} +0 -0
  362. /package/dist/{chunk-JNIVZNIB.js.map → chunk-WKVL2G7X.js.map} +0 -0
  363. /package/dist/{chunk-KJXP6RUG.js.map → chunk-WNEVEMJ3.js.map} +0 -0
  364. /package/dist/{chunk-HNEOLXRF.js.map → chunk-WQIYGYY6.js.map} +0 -0
  365. /package/dist/{chunk-GQJKVQJR.js.map → chunk-WYLBEJQI.js.map} +0 -0
  366. /package/dist/{chunk-36DZ242S.js.map → chunk-XNROYP5E.js.map} +0 -0
  367. /package/dist/{chunk-XNAOCY67.js.map → chunk-XVZIBMSY.js.map} +0 -0
  368. /package/dist/{chunk-PXTLPC3P.js.map → chunk-YGVZ4QOZ.js.map} +0 -0
  369. /package/dist/{chunk-JX32ROLZ.js.map → chunk-YZTFQBYY.js.map} +0 -0
  370. /package/dist/{chunk-XSXM5LYZ.js.map → chunk-ZCRDYQL6.js.map} +0 -0
  371. /package/dist/{chunk-Z3XVYXQ3.js.map → chunk-ZXTAHSQU.js.map} +0 -0
  372. /package/dist/{resolution-ZU5BIAJA.js.map → entity-canonical-id-migration-GD5MPFUF.js.map} +0 -0
@@ -0,0 +1,892 @@
1
+ import {
2
+ isMalformedEntityRecord
3
+ } from "./chunk-PPUNC7UX.js";
4
+ import {
5
+ ENTITY_CANONICAL_ID_MIGRATION_FILE,
6
+ ENTITY_CANONICAL_ID_RECONCILE_CONSUMING_MARKER,
7
+ ENTITY_CANONICAL_ID_RECONCILE_MARKER,
8
+ assertSafeEntityId,
9
+ withEntityCanonicalMutationLock
10
+ } from "./chunk-VXWOJPSY.js";
11
+ import {
12
+ computeSupersessionKey,
13
+ normalizeSupersessionKey
14
+ } from "./chunk-5WITETWU.js";
15
+ import {
16
+ withHeldFileLock
17
+ } from "./chunk-5B5WYAHQ.js";
18
+ import {
19
+ isMacOsReplicationJunkBasename,
20
+ warnIgnoredMacOsReplicationJunk
21
+ } from "./chunk-QUIRIG2P.js";
22
+ import {
23
+ assertPathInsideRoot
24
+ } from "./chunk-C7HJ3NEI.js";
25
+ import {
26
+ RECALL_FALLBACK_DIRS
27
+ } from "./chunk-VS2IYZRU.js";
28
+ import {
29
+ isErrnoCode
30
+ } from "./chunk-KNA3BXXL.js";
31
+ import {
32
+ log
33
+ } from "./chunk-3WCASNQZ.js";
34
+
35
+ // src/storage/entity-canonical-id-migration.ts
36
+ import { createHash, randomUUID } from "crypto";
37
+ import {
38
+ access,
39
+ lstat,
40
+ readFile,
41
+ readdir,
42
+ realpath,
43
+ rename,
44
+ stat as statFile,
45
+ unlink,
46
+ writeFile
47
+ } from "fs/promises";
48
+ import path from "path";
49
+ import { z } from "zod";
50
+ var ENTITY_CANONICAL_ID_MIGRATION_VERSION = 1;
51
+ var ENTITY_CANONICAL_ID_MIGRATION_LOCK_STALE_MS = 6e4;
52
+ var ENTITY_CANONICAL_ID_MIGRATION_LOCK_MAX_WAIT_MS = 3e5;
53
+ var TOMBSTONE_LOCK_STALE_MS = 3e4;
54
+ var TOMBSTONE_LOCK_MAX_WAIT_MS = 5e3;
55
+ var MEMORY_REWRITE_MAX_PASSES = 3;
56
+ var ENTITY_MAPPING_RESCAN_MAX_PASSES = 3;
57
+ var EntityCanonicalIdMigrationStateSchema = z.object({
58
+ version: z.literal(ENTITY_CANONICAL_ID_MIGRATION_VERSION),
59
+ complete: z.boolean(),
60
+ mappings: z.record(z.string().min(1)),
61
+ /**
62
+ * Pairs the migration refused to resolve, PARKED rather than dropped.
63
+ * Deleting the record would strand the collision: once an operator removes
64
+ * the legacy file, no later scan can rediscover the mapping, so references
65
+ * still naming the legacy id would never be rewritten. Optional so a journal
66
+ * written by an older build still parses.
67
+ */
68
+ blocked: z.record(z.string().min(1)).optional()
69
+ });
70
+ async function fingerprintPath(filePath) {
71
+ let fileStat;
72
+ try {
73
+ fileStat = await lstat(filePath);
74
+ } catch (error) {
75
+ if (!isErrnoCode(error, "ENOENT")) throw error;
76
+ }
77
+ return fileStat ? `${fileStat.dev}:${fileStat.ino}:${fileStat.mtimeMs}:${fileStat.ctimeMs}:${fileStat.size}` : "missing";
78
+ }
79
+ async function fingerprintEntityEntries(entitiesDir) {
80
+ let names;
81
+ try {
82
+ names = (await readdir(entitiesDir)).filter((name) => path.extname(name) === ".md" && !isMacOsReplicationJunkBasename(name)).sort();
83
+ } catch (error) {
84
+ if (isErrnoCode(error, "ENOENT")) return "missing";
85
+ throw error;
86
+ }
87
+ const hash = createHash("sha256");
88
+ for (const name of names) {
89
+ hash.update(`${name.length}:${name}:`);
90
+ try {
91
+ const entry = await lstat(path.join(entitiesDir, name), { bigint: true });
92
+ hash.update(`${entry.dev}:${entry.ino}:${entry.size}:${entry.mtimeNs}:${entry.ctimeNs}`);
93
+ } catch (error) {
94
+ if (!isErrnoCode(error, "ENOENT")) throw error;
95
+ hash.update("missing");
96
+ }
97
+ hash.update("\n");
98
+ }
99
+ return hash.digest("hex");
100
+ }
101
+ async function getFingerprint(baseDir, entitiesDir, getEntityMutationVersion) {
102
+ const [
103
+ entityDirectoryFingerprint,
104
+ entityEntriesFingerprint,
105
+ aliasFingerprint,
106
+ reconcileFingerprint,
107
+ consumingFingerprint
108
+ ] = await Promise.all([
109
+ fingerprintPath(entitiesDir),
110
+ fingerprintEntityEntries(entitiesDir),
111
+ fingerprintPath(path.join(baseDir, "config", "aliases.json")),
112
+ fingerprintPath(path.join(baseDir, "state", ENTITY_CANONICAL_ID_RECONCILE_MARKER)),
113
+ fingerprintPath(path.join(baseDir, "state", ENTITY_CANONICAL_ID_RECONCILE_CONSUMING_MARKER))
114
+ ]);
115
+ return [
116
+ entityDirectoryFingerprint,
117
+ entityEntriesFingerprint,
118
+ aliasFingerprint,
119
+ reconcileFingerprint,
120
+ consumingFingerprint,
121
+ getEntityMutationVersion()
122
+ ].join(":");
123
+ }
124
+ async function validateRoots(baseDir, entitiesDir, stateDir, archiveDir) {
125
+ let baseStat;
126
+ try {
127
+ baseStat = await lstat(baseDir);
128
+ } catch (error) {
129
+ if (isErrnoCode(error, "ENOENT")) return;
130
+ throw error;
131
+ }
132
+ if (baseStat.isSymbolicLink() || !baseStat.isDirectory()) {
133
+ throw new Error(`Refusing entity canonical-id migration through unsafe memory root: ${baseDir}.`);
134
+ }
135
+ const memoryRoot = await realpath(baseDir);
136
+ const roots = [
137
+ entitiesDir,
138
+ stateDir,
139
+ ...RECALL_FALLBACK_DIRS.map((directory) => path.join(baseDir, directory)),
140
+ path.join(baseDir, "cold"),
141
+ archiveDir
142
+ ];
143
+ for (const root of roots) {
144
+ let rootStat;
145
+ try {
146
+ rootStat = await lstat(root);
147
+ } catch (error) {
148
+ if (isErrnoCode(error, "ENOENT")) continue;
149
+ throw error;
150
+ }
151
+ if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) {
152
+ throw new Error(`Refusing entity canonical-id migration through unsafe memory root: ${root}.`);
153
+ }
154
+ assertPathInsideRoot(memoryRoot, await realpath(root), root);
155
+ }
156
+ }
157
+ function statePath(deps) {
158
+ return path.join(deps.stateDir, ENTITY_CANONICAL_ID_MIGRATION_FILE);
159
+ }
160
+ async function assertSafeMigrationStateFile(deps) {
161
+ const migrationStatePath = statePath(deps);
162
+ let fileStat;
163
+ try {
164
+ fileStat = await lstat(migrationStatePath);
165
+ } catch (error) {
166
+ if (isErrnoCode(error, "ENOENT")) return;
167
+ throw error;
168
+ }
169
+ if (fileStat.isSymbolicLink() || !fileStat.isFile()) {
170
+ throw new Error(
171
+ `Refusing entity canonical-id migration through unsafe migration state file: ${migrationStatePath}.`
172
+ );
173
+ }
174
+ const [stateRoot, stateFile] = await Promise.all([
175
+ realpath(deps.stateDir),
176
+ realpath(migrationStatePath)
177
+ ]);
178
+ assertPathInsideRoot(stateRoot, stateFile, migrationStatePath);
179
+ }
180
+ async function assertSafeTombstoneFile(deps, tombstonePath) {
181
+ let fileStat;
182
+ try {
183
+ fileStat = await lstat(tombstonePath);
184
+ } catch (error) {
185
+ if (isErrnoCode(error, "ENOENT")) return false;
186
+ throw error;
187
+ }
188
+ if (fileStat.isSymbolicLink() || !fileStat.isFile()) {
189
+ throw new Error(
190
+ `Refusing entity canonical-id migration through unsafe tombstone ledger: ${tombstonePath}.`
191
+ );
192
+ }
193
+ const [stateRoot, tombstoneFile] = await Promise.all([
194
+ realpath(deps.stateDir),
195
+ realpath(tombstonePath)
196
+ ]);
197
+ assertPathInsideRoot(stateRoot, tombstoneFile, tombstonePath);
198
+ return true;
199
+ }
200
+ function lockPath(deps) {
201
+ return path.join(deps.stateDir, "entity-canonical-id-migration.lock");
202
+ }
203
+ async function readState(deps) {
204
+ await assertSafeMigrationStateFile(deps);
205
+ let raw;
206
+ try {
207
+ raw = await readFile(statePath(deps), "utf-8");
208
+ } catch (error) {
209
+ if (isErrnoCode(error, "ENOENT")) return null;
210
+ throw error;
211
+ }
212
+ let parsed;
213
+ try {
214
+ parsed = JSON.parse(raw);
215
+ } catch {
216
+ throw new Error("Invalid entity canonical-id migration state.");
217
+ }
218
+ const result = EntityCanonicalIdMigrationStateSchema.safeParse(parsed);
219
+ if (!result.success) throw new Error("Invalid entity canonical-id migration state.");
220
+ for (const mappings of [result.data.mappings, result.data.blocked ?? {}]) {
221
+ for (const [legacyId, canonicalId] of Object.entries(mappings)) {
222
+ assertSafeEntityId(legacyId);
223
+ assertSafeEntityId(canonicalId);
224
+ }
225
+ }
226
+ return result.data;
227
+ }
228
+ async function writeState(deps, state) {
229
+ const destination = statePath(deps);
230
+ const temporary = `${destination}.${process.pid}.${randomUUID()}.tmp`;
231
+ try {
232
+ await writeFile(temporary, `${JSON.stringify(state, null, 2)}
233
+ `, "utf-8");
234
+ await rename(temporary, destination);
235
+ } finally {
236
+ await unlink(temporary).catch(() => void 0);
237
+ }
238
+ }
239
+ async function publishState(deps, state) {
240
+ await withEntityCanonicalMutationLock(deps.stateDir, async () => {
241
+ await writeState(deps, state);
242
+ });
243
+ }
244
+ async function fileExists(filePath) {
245
+ try {
246
+ await access(filePath);
247
+ return true;
248
+ } catch (error) {
249
+ if (isErrnoCode(error, "ENOENT")) return false;
250
+ throw error;
251
+ }
252
+ }
253
+ async function sameFileIdentity(leftPath, rightPath) {
254
+ try {
255
+ const [left, right] = await Promise.all([statFile(leftPath), statFile(rightPath)]);
256
+ return left.dev === right.dev && left.ino === right.ino;
257
+ } catch (error) {
258
+ if (isErrnoCode(error, "ENOENT")) return false;
259
+ throw error;
260
+ }
261
+ }
262
+ async function assertNotSymlink(filePath, label) {
263
+ let stat;
264
+ try {
265
+ stat = await lstat(filePath);
266
+ } catch (error) {
267
+ if (isErrnoCode(error, "ENOENT")) return;
268
+ throw error;
269
+ }
270
+ if (stat.isSymbolicLink()) {
271
+ throw new Error(`Refusing entity canonical-id migration through symlink: ${label}.`);
272
+ }
273
+ }
274
+ async function assertNotMemorySymlink(filePath) {
275
+ let stat;
276
+ try {
277
+ stat = await lstat(filePath);
278
+ } catch (error) {
279
+ if (isErrnoCode(error, "ENOENT")) return;
280
+ throw error;
281
+ }
282
+ if (stat.isSymbolicLink()) {
283
+ throw new Error(`Refusing entity canonical-id migration through symlinked memory: ${filePath}.`);
284
+ }
285
+ }
286
+ async function assertEntityContentUnchanged(deps, filePath, expectedContent, legacyId) {
287
+ const latestContent = await deps.readStorageSecureFile(filePath);
288
+ if (latestContent !== expectedContent) {
289
+ throw new Error(`Legacy entity id ${legacyId} changed while migration was running; retry migration.`);
290
+ }
291
+ }
292
+ async function readSafeEntityEntries(entitiesDir) {
293
+ const rootStat = await lstat(entitiesDir);
294
+ if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) {
295
+ throw new Error("Refusing entity canonical-id migration through a symlinked or non-directory entities root.");
296
+ }
297
+ const entries = await readdir(entitiesDir);
298
+ for (const entry of entries) {
299
+ await assertNotSymlink(path.join(entitiesDir, entry), entry);
300
+ }
301
+ return entries;
302
+ }
303
+ async function discoverMappings(deps, knownMappings = {}, blocked = /* @__PURE__ */ new Map(), scanNotes) {
304
+ const mappings = {};
305
+ const canonicalOwners = /* @__PURE__ */ new Map();
306
+ blocked.clear();
307
+ const entityEntries = await readSafeEntityEntries(deps.entitiesDir);
308
+ for (const entry of entityEntries) {
309
+ if (isMacOsReplicationJunkBasename(entry)) {
310
+ scanNotes?.junk.add(entry);
311
+ continue;
312
+ }
313
+ if (!entry.endsWith(".md")) continue;
314
+ const legacyId = entry.slice(0, -".md".length);
315
+ assertSafeEntityId(legacyId);
316
+ const legacyPath = deps.resolveEntityFilePath(legacyId);
317
+ if (legacyPath === null) continue;
318
+ const entityContent = await deps.readStorageSecureFile(legacyPath);
319
+ if (isMalformedEntityRecord(entityContent)) {
320
+ scanNotes?.malformed.add(entry);
321
+ continue;
322
+ }
323
+ const entity = deps.parseEntityFile(entityContent);
324
+ if (!entity.name.trim() || !entity.type.trim()) {
325
+ scanNotes?.malformed.add(entry);
326
+ continue;
327
+ }
328
+ const canonicalId = deps.normalizeEntityName(entity.name, entity.type);
329
+ assertSafeEntityId(canonicalId);
330
+ if (legacyId === canonicalId) continue;
331
+ const canonicalPath = deps.resolveEntityFilePath(canonicalId);
332
+ if (canonicalPath === null) continue;
333
+ const canonicalExists = await fileExists(canonicalPath);
334
+ if (canonicalExists && await sameFileIdentity(legacyPath, canonicalPath) && knownMappings[legacyId] === canonicalId) continue;
335
+ if (canonicalExists) {
336
+ const canonicalContent = await deps.readStorageSecureFile(canonicalPath);
337
+ if (entityContent !== canonicalContent) {
338
+ blocked.set(legacyId, canonicalId);
339
+ continue;
340
+ }
341
+ }
342
+ canonicalOwners.set(canonicalId, [...canonicalOwners.get(canonicalId) ?? [], legacyId]);
343
+ mappings[legacyId] = canonicalId;
344
+ }
345
+ for (const [canonicalId, claimants] of canonicalOwners) {
346
+ if (claimants.length < 2) continue;
347
+ for (const legacyId of claimants) {
348
+ blocked.set(legacyId, canonicalId);
349
+ delete mappings[legacyId];
350
+ }
351
+ }
352
+ return mappings;
353
+ }
354
+ async function rewriteReferences(deps, mappings, refreshLock) {
355
+ let rewroteColdMemory = false;
356
+ for (let pass = 0; pass < MEMORY_REWRITE_MAX_PASSES; pass += 1) {
357
+ deps.invalidateAllMemoriesCache();
358
+ deps.invalidateColdMemoriesCache();
359
+ const [hotMemories, coldMemories, archivedMemories] = await Promise.all([
360
+ deps.readAllMemories(),
361
+ deps.readAllColdMemories(),
362
+ deps.readArchivedMemories()
363
+ ]);
364
+ const seenPaths = /* @__PURE__ */ new Set();
365
+ let rewroteAny = false;
366
+ for (const memory of [...hotMemories, ...coldMemories, ...archivedMemories]) {
367
+ const memoryPath = path.resolve(memory.path);
368
+ if (seenPaths.has(memoryPath)) continue;
369
+ seenPaths.add(memoryPath);
370
+ const previousEntityRef = memory.frontmatter.entityRef;
371
+ const canonicalId = previousEntityRef ? mappings[previousEntityRef] : void 0;
372
+ if (!previousEntityRef || !canonicalId) continue;
373
+ await assertNotMemorySymlink(memory.path);
374
+ const observedMemoryFingerprint = await fingerprintPath(memory.path);
375
+ if (observedMemoryFingerprint === "missing") continue;
376
+ if (!await refreshLock()) throw new Error("Lost entity canonical-id migration lock.");
377
+ const latestMemory = await deps.readMemoryByPath(memory.path);
378
+ if (!latestMemory) continue;
379
+ const latestMemoryFingerprint = await fingerprintPath(latestMemory.path);
380
+ if (latestMemoryFingerprint !== observedMemoryFingerprint) continue;
381
+ const latestPreviousEntityRef = latestMemory.frontmatter.entityRef;
382
+ const latestCanonicalId = latestPreviousEntityRef ? mappings[latestPreviousEntityRef] : void 0;
383
+ if (!latestPreviousEntityRef || !latestCanonicalId) continue;
384
+ const memoryEncrypted = await deps.isEncryptedStorageFile(latestMemory.path);
385
+ if (await fingerprintPath(latestMemory.path) !== latestMemoryFingerprint) continue;
386
+ await deps.snapshotBeforeWrite(latestMemory.path, "write");
387
+ if (await fingerprintPath(latestMemory.path) !== latestMemoryFingerprint) continue;
388
+ await deps.writeStorageSecureFile(
389
+ latestMemory.path,
390
+ deps.serializeMemoryWithEntityRef(latestMemory, latestCanonicalId),
391
+ memoryEncrypted
392
+ );
393
+ await deps.rewriteProjectedMemoryEntityReference(
394
+ latestMemory.frontmatter.id,
395
+ latestPreviousEntityRef,
396
+ latestCanonicalId
397
+ );
398
+ rewroteAny = true;
399
+ rewroteColdMemory ||= latestMemory.path.includes(`${path.sep}cold${path.sep}`);
400
+ }
401
+ if (!rewroteAny) return { rewroteColdMemory };
402
+ }
403
+ throw new Error("Memory references changed while entity canonical-id migration was running; retry migration.");
404
+ }
405
+ function rewriteTombstoneLine(line, mappings, normalizedMappings) {
406
+ let parsed;
407
+ try {
408
+ parsed = JSON.parse(line);
409
+ } catch {
410
+ return line;
411
+ }
412
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return line;
413
+ const tombstone = parsed;
414
+ let changed = false;
415
+ if (typeof tombstone.entityRef === "string") {
416
+ const canonicalId = mappings[tombstone.entityRef];
417
+ if (canonicalId) {
418
+ tombstone.entityRef = canonicalId;
419
+ changed = true;
420
+ }
421
+ }
422
+ if (typeof tombstone.supersessionKey === "string") {
423
+ const separator = tombstone.supersessionKey.indexOf("::");
424
+ if (separator < 0) return changed ? JSON.stringify(tombstone) : line;
425
+ const normalizedLegacyId = normalizeSupersessionKey(tombstone.supersessionKey.slice(0, separator));
426
+ const canonicalId = normalizedMappings.get(normalizedLegacyId);
427
+ if (canonicalId) {
428
+ const canonicalKey = computeSupersessionKey(canonicalId, tombstone.supersessionKey.slice(separator + 2));
429
+ if (canonicalKey) {
430
+ tombstone.supersessionKey = canonicalKey;
431
+ changed = true;
432
+ }
433
+ }
434
+ }
435
+ return changed ? JSON.stringify(tombstone) : line;
436
+ }
437
+ async function rewriteTombstoneReferences(deps, mappings, refreshLock) {
438
+ const tombstonePath = path.join(deps.stateDir, "tombstones.jsonl");
439
+ const normalizedMappings = /* @__PURE__ */ new Map();
440
+ for (const [legacyId, canonicalId] of Object.entries(mappings)) {
441
+ const normalizedLegacyId = normalizeSupersessionKey(legacyId);
442
+ if (normalizedLegacyId && !normalizedMappings.has(normalizedLegacyId)) {
443
+ normalizedMappings.set(normalizedLegacyId, canonicalId);
444
+ }
445
+ }
446
+ await withHeldFileLock(
447
+ path.join(deps.stateDir, "tombstones.lock"),
448
+ {
449
+ staleMs: TOMBSTONE_LOCK_STALE_MS,
450
+ maxWaitMs: TOMBSTONE_LOCK_MAX_WAIT_MS
451
+ },
452
+ async (acquired, tombstoneLock) => {
453
+ if (!acquired) throw new Error("Timed out waiting for active tombstone migration.");
454
+ if (!await assertSafeTombstoneFile(deps, tombstonePath)) return;
455
+ const tombstoneEncrypted = await deps.isEncryptedStorageFile(tombstonePath);
456
+ const original = await deps.readStorageSecureFile(tombstonePath);
457
+ let changed = false;
458
+ const rewritten = original.split("\n").map((line) => {
459
+ const next = rewriteTombstoneLine(line, mappings, normalizedMappings);
460
+ changed ||= next !== line;
461
+ return next;
462
+ }).join("\n");
463
+ if (!changed) return;
464
+ if (!await refreshLock()) throw new Error("Lost entity canonical-id migration lock.");
465
+ if (!await tombstoneLock.refresh()) throw new Error("Lost tombstone migration lock.");
466
+ await deps.snapshotBeforeWrite(tombstonePath, "write");
467
+ await deps.writeStorageSecureFile(tombstonePath, rewritten, tombstoneEncrypted);
468
+ }
469
+ );
470
+ }
471
+ async function rewriteRelationshipTargets(deps, mappings, refreshLock) {
472
+ let rewritten = false;
473
+ const entries = await readSafeEntityEntries(deps.entitiesDir);
474
+ for (const entry of entries) {
475
+ if (!entry.endsWith(".md") || isMacOsReplicationJunkBasename(entry)) continue;
476
+ const entityPath = deps.resolveEntityFilePath(entry.slice(0, -".md".length));
477
+ if (entityPath === null) continue;
478
+ const observedEntityFingerprint = await fingerprintPath(entityPath);
479
+ if (observedEntityFingerprint === "missing") continue;
480
+ const entityRaw = await deps.readStorageSecureFile(entityPath);
481
+ if (isMalformedEntityRecord(entityRaw)) continue;
482
+ const entity = deps.parseEntityFile(entityRaw);
483
+ const relationships = entity.relationships.map((relationship) => {
484
+ const target = mappings[relationship.target];
485
+ return target ? { ...relationship, target } : relationship;
486
+ });
487
+ if (relationships.every((relationship, index) => relationship === entity.relationships[index])) continue;
488
+ const rewroteEntity = await withEntityCanonicalMutationLock(
489
+ deps.stateDir,
490
+ async (refreshEntityLock) => {
491
+ if (!await refreshLock()) throw new Error("Lost entity canonical-id migration lock.");
492
+ const latestRaw = await deps.readStorageSecureFile(entityPath);
493
+ if (isMalformedEntityRecord(latestRaw)) return false;
494
+ const latestEntity = deps.parseEntityFile(latestRaw);
495
+ if (await fingerprintPath(entityPath) !== observedEntityFingerprint) return false;
496
+ const latestRelationships = latestEntity.relationships.map((relationship) => {
497
+ const target = mappings[relationship.target];
498
+ return target ? { ...relationship, target } : relationship;
499
+ });
500
+ if (latestRelationships.every((relationship, index) => relationship === latestEntity.relationships[index])) {
501
+ return false;
502
+ }
503
+ const entityEncrypted = await deps.isEncryptedStorageFile(entityPath);
504
+ if (!await refreshEntityLock()) throw new Error("Lost entity mutation lock.");
505
+ if (await fingerprintPath(entityPath) !== observedEntityFingerprint) return false;
506
+ await deps.snapshotBeforeWrite(entityPath, "write");
507
+ if (await fingerprintPath(entityPath) !== observedEntityFingerprint) return false;
508
+ await deps.writeStorageSecureFile(
509
+ entityPath,
510
+ deps.serializeEntityFile({ ...latestEntity, relationships: latestRelationships }),
511
+ entityEncrypted
512
+ );
513
+ return true;
514
+ }
515
+ );
516
+ rewritten ||= rewroteEntity;
517
+ }
518
+ return rewritten;
519
+ }
520
+ async function rewriteKnownReferences(deps, mappings, refreshLock) {
521
+ await rewriteRelationshipTargets(deps, mappings, refreshLock);
522
+ let rewroteColdMemory = (await rewriteReferences(deps, mappings, refreshLock)).rewroteColdMemory;
523
+ await rewriteTombstoneReferences(deps, mappings, refreshLock);
524
+ await deps.rewriteProjectedEntityReferences(mappings);
525
+ const finalMemoryPass = await rewriteReferences(deps, mappings, refreshLock);
526
+ rewroteColdMemory ||= finalMemoryPass.rewroteColdMemory;
527
+ return rewroteColdMemory;
528
+ }
529
+ function wouldCreateMappingCycle(mappings, legacyId, canonicalId) {
530
+ let current = canonicalId;
531
+ const seen = /* @__PURE__ */ new Set();
532
+ while (true) {
533
+ if (current === legacyId) return true;
534
+ if (seen.has(current)) return false;
535
+ seen.add(current);
536
+ const next = mappings[current];
537
+ if (!next || next === current) return false;
538
+ current = next;
539
+ }
540
+ }
541
+ function rejectMappingCycles(existing, discovered) {
542
+ const accepted = {};
543
+ const merged = { ...existing };
544
+ for (const [legacyId, canonicalId] of Object.entries(discovered)) {
545
+ if (merged[legacyId] === void 0 && wouldCreateMappingCycle(merged, legacyId, canonicalId)) continue;
546
+ accepted[legacyId] = canonicalId;
547
+ merged[legacyId] = canonicalId;
548
+ }
549
+ return accepted;
550
+ }
551
+ function mergeDiscoveredMappings(existing, discovered) {
552
+ const merged = { ...existing };
553
+ const canonicalOwners = /* @__PURE__ */ new Map();
554
+ for (const [legacyId, canonicalId] of Object.entries(discovered)) {
555
+ const previousMapping = merged[legacyId];
556
+ if (previousMapping !== void 0 && previousMapping !== canonicalId) {
557
+ continue;
558
+ }
559
+ if (previousMapping === void 0 && wouldCreateMappingCycle(merged, legacyId, canonicalId)) continue;
560
+ const previousOwner = canonicalOwners.get(canonicalId);
561
+ if (previousOwner !== void 0 && previousOwner !== legacyId) {
562
+ throw new Error(
563
+ `Cannot migrate legacy entity ids ${previousOwner} and ${legacyId}: both normalize to ${canonicalId}.`
564
+ );
565
+ }
566
+ merged[legacyId] = canonicalId;
567
+ canonicalOwners.set(canonicalId, legacyId);
568
+ }
569
+ return merged;
570
+ }
571
+ function collapseMappings(mappings) {
572
+ const collapsed = {};
573
+ for (const legacyId of Object.keys(mappings)) {
574
+ let current = legacyId;
575
+ const seen = /* @__PURE__ */ new Set();
576
+ while (true) {
577
+ const next = mappings[current];
578
+ if (!next || next === current) break;
579
+ if (seen.has(current)) {
580
+ throw new Error(`Entity canonical-id migration mapping cycle includes ${legacyId}.`);
581
+ }
582
+ seen.add(current);
583
+ current = next;
584
+ }
585
+ if (current !== legacyId) collapsed[legacyId] = current;
586
+ }
587
+ return collapsed;
588
+ }
589
+ async function migrateEntityFilePair(deps, legacyId, canonicalId, refreshMigrationLock) {
590
+ return withEntityCanonicalMutationLock(deps.stateDir, async (refreshEntityLock) => {
591
+ assertSafeEntityId(legacyId);
592
+ assertSafeEntityId(canonicalId);
593
+ const legacyPath = deps.resolveEntityFilePath(legacyId);
594
+ const canonicalPath = deps.resolveEntityFilePath(canonicalId);
595
+ if (legacyPath === null || canonicalPath === null) {
596
+ throw new Error("Invalid entity canonical-id migration path.");
597
+ }
598
+ await assertNotSymlink(legacyPath, legacyId);
599
+ await assertNotSymlink(canonicalPath, canonicalId);
600
+ const legacyExists = await fileExists(legacyPath);
601
+ const canonicalExists = await fileExists(canonicalPath);
602
+ if (!legacyExists && !canonicalExists) return { deferred: true, progressed: false };
603
+ if (legacyExists && canonicalExists) {
604
+ if (await sameFileIdentity(legacyPath, canonicalPath)) return { deferred: false, progressed: false };
605
+ const [legacyContent, canonicalContent, legacyEncrypted, canonicalEncrypted] = await Promise.all([
606
+ deps.readStorageSecureFile(legacyPath),
607
+ deps.readStorageSecureFile(canonicalPath),
608
+ deps.isEncryptedStorageFile(legacyPath),
609
+ deps.isEncryptedStorageFile(canonicalPath)
610
+ ]);
611
+ if (legacyContent !== canonicalContent) {
612
+ return { deferred: false, progressed: false, blocked: true };
613
+ }
614
+ if (legacyEncrypted && !canonicalEncrypted) {
615
+ if (!await refreshMigrationLock() || !await refreshEntityLock()) {
616
+ throw new Error("Lost entity canonical-id migration lock.");
617
+ }
618
+ await deps.snapshotBeforeWrite(canonicalPath, "write");
619
+ await deps.writeStorageSecureFile(canonicalPath, legacyContent, true);
620
+ if (await deps.readStorageSecureFile(canonicalPath) !== legacyContent) {
621
+ throw new Error(`Cannot verify migrated entity id ${canonicalId}.`);
622
+ }
623
+ }
624
+ if (!await refreshMigrationLock() || !await refreshEntityLock()) {
625
+ throw new Error("Lost entity canonical-id migration lock.");
626
+ }
627
+ await deps.snapshotBeforeWrite(legacyPath, "write");
628
+ await assertNotSymlink(legacyPath, legacyId);
629
+ await assertEntityContentUnchanged(deps, legacyPath, legacyContent, legacyId);
630
+ await unlink(legacyPath);
631
+ return { deferred: false, progressed: true };
632
+ }
633
+ if (!legacyExists) return { deferred: false, progressed: false };
634
+ if (!await refreshMigrationLock() || !await refreshEntityLock()) {
635
+ throw new Error("Lost entity canonical-id migration lock.");
636
+ }
637
+ const entityEncrypted = await deps.isEncryptedStorageFile(legacyPath);
638
+ const entityContent = await deps.readStorageSecureFile(legacyPath);
639
+ await assertNotSymlink(legacyPath, legacyId);
640
+ await assertEntityContentUnchanged(deps, legacyPath, entityContent, legacyId);
641
+ if (isMacOsReplicationJunkBasename(path.basename(legacyPath)) || isMalformedEntityRecord(entityContent)) {
642
+ return { deferred: false, progressed: false };
643
+ }
644
+ let canonicalFingerprintAfterWrite = null;
645
+ try {
646
+ await deps.writeStorageSecureFile(canonicalPath, entityContent, entityEncrypted);
647
+ canonicalFingerprintAfterWrite = await fingerprintPath(canonicalPath);
648
+ if (await deps.readStorageSecureFile(canonicalPath) !== entityContent) {
649
+ throw new Error(`Cannot verify migrated entity id ${canonicalId}.`);
650
+ }
651
+ if (!await refreshMigrationLock() || !await refreshEntityLock()) {
652
+ throw new Error("Lost entity canonical-id migration lock.");
653
+ }
654
+ await deps.snapshotBeforeWrite(legacyPath, "write");
655
+ await assertNotSymlink(legacyPath, legacyId);
656
+ await assertEntityContentUnchanged(deps, legacyPath, entityContent, legacyId);
657
+ await unlink(legacyPath);
658
+ } catch (error) {
659
+ if (!canonicalExists && canonicalFingerprintAfterWrite !== null) {
660
+ try {
661
+ if (await fingerprintPath(canonicalPath) === canonicalFingerprintAfterWrite) {
662
+ await assertNotSymlink(canonicalPath, canonicalId);
663
+ await unlink(canonicalPath);
664
+ }
665
+ } catch {
666
+ }
667
+ }
668
+ throw error;
669
+ }
670
+ return { deferred: false, progressed: true };
671
+ });
672
+ }
673
+ async function migrateLegacyEntityCanonicalIds(deps) {
674
+ return withHeldFileLock(
675
+ lockPath(deps),
676
+ {
677
+ staleMs: ENTITY_CANONICAL_ID_MIGRATION_LOCK_STALE_MS,
678
+ maxWaitMs: ENTITY_CANONICAL_ID_MIGRATION_LOCK_MAX_WAIT_MS
679
+ },
680
+ async (acquired, lock) => {
681
+ if (!acquired) throw new Error("Timed out waiting for active entity canonical-id migration.");
682
+ await deps.validateMemoryScanRoots?.();
683
+ await readSafeEntityEntries(deps.entitiesDir);
684
+ const reconcileMarkerPath = path.join(deps.stateDir, ENTITY_CANONICAL_ID_RECONCILE_MARKER);
685
+ const consumingMarkerPath = path.join(deps.stateDir, ENTITY_CANONICAL_ID_RECONCILE_CONSUMING_MARKER);
686
+ let reconcileRequested = await fileExists(consumingMarkerPath);
687
+ if (await fileExists(reconcileMarkerPath)) {
688
+ try {
689
+ await rename(reconcileMarkerPath, consumingMarkerPath);
690
+ reconcileRequested = true;
691
+ } catch (error) {
692
+ if (!isErrnoCode(error, "ENOENT")) throw error;
693
+ }
694
+ }
695
+ let state = await readState(deps);
696
+ if (!state) {
697
+ state = {
698
+ version: ENTITY_CANONICAL_ID_MIGRATION_VERSION,
699
+ complete: false,
700
+ mappings: {}
701
+ };
702
+ }
703
+ const blocked = /* @__PURE__ */ new Map();
704
+ const scanNotes = { junk: /* @__PURE__ */ new Set(), malformed: /* @__PURE__ */ new Set() };
705
+ const staleParked = /* @__PURE__ */ new Map();
706
+ const finish = async () => {
707
+ if (blocked.size > 0) {
708
+ const pairs = [...blocked].map(([legacyId, canonicalId]) => `${legacyId} -> ${canonicalId}`).join(", ");
709
+ log.warn(
710
+ `entity canonical-id migration skipped ${blocked.size} unresolvable pair(s): ${pairs}. Both files were kept and the legacy id still resolves; merge or delete one side to migrate it.`
711
+ );
712
+ }
713
+ if (staleParked.size > 0) {
714
+ const pairs = [...staleParked].map(([legacyId, canonicalId]) => `${legacyId} -> ${canonicalId}`).join(", ");
715
+ log.warn(
716
+ `entity canonical-id migration dropped ${staleParked.size} mapping(s) whose entity files are gone: ${pairs}. The stale journal entries were removed; references to those legacy ids do not resolve either way.`
717
+ );
718
+ }
719
+ warnIgnoredMacOsReplicationJunk(deps.entitiesDir, scanNotes.junk.size, (message) => {
720
+ log.warn(`entity canonical-id migration ${message}`);
721
+ });
722
+ if (scanNotes.malformed.size > 0) {
723
+ const names = [...scanNotes.malformed].sort().join(", ");
724
+ log.warn(
725
+ `entity canonical-id migration skipped ${scanNotes.malformed.size} malformed entity file(s): ${names}. Each file was left in place; startup continues. Fix or remove the file to migrate it.`
726
+ );
727
+ }
728
+ if (reconcileRequested) {
729
+ await unlink(consumingMarkerPath).catch((error) => {
730
+ if (!isErrnoCode(error, "ENOENT")) throw error;
731
+ });
732
+ }
733
+ const completionFingerprint = await deps.readMigrationFingerprint?.();
734
+ if (await fileExists(reconcileMarkerPath)) return void 0;
735
+ return completionFingerprint;
736
+ };
737
+ const pruneBlocked = async () => {
738
+ const current = state;
739
+ if (!current) return false;
740
+ let revived = false;
741
+ const parked = { ...current.blocked ?? {} };
742
+ const active = {};
743
+ for (const [legacyId, canonicalId] of Object.entries(current.mappings)) {
744
+ if (!blocked.has(legacyId)) active[legacyId] = canonicalId;
745
+ }
746
+ for (const [legacyId, canonicalId] of blocked) parked[legacyId] = canonicalId;
747
+ for (const [legacyId, canonicalId] of Object.entries(parked)) {
748
+ if (blocked.has(legacyId)) continue;
749
+ delete parked[legacyId];
750
+ if (active[legacyId] !== void 0) continue;
751
+ const legacyPath = deps.resolveEntityFilePath(legacyId);
752
+ if (legacyPath !== null && await fileExists(legacyPath)) continue;
753
+ let target = canonicalId;
754
+ const seenTargets = /* @__PURE__ */ new Set();
755
+ while (active[target] !== void 0 && !seenTargets.has(target)) {
756
+ seenTargets.add(target);
757
+ target = active[target];
758
+ }
759
+ const targetPath = deps.resolveEntityFilePath(target);
760
+ if (targetPath === null || !await fileExists(targetPath)) {
761
+ staleParked.set(legacyId, canonicalId);
762
+ continue;
763
+ }
764
+ active[legacyId] = target;
765
+ revived = true;
766
+ }
767
+ const collapsed = collapseMappings(active);
768
+ for (const [legacyId, canonicalId] of Object.entries(parked)) {
769
+ const moved = collapsed[canonicalId];
770
+ if (moved !== void 0 && moved !== legacyId) parked[legacyId] = moved;
771
+ }
772
+ const same = (a, b) => Object.keys(a).length === Object.keys(b).length && Object.entries(a).every(([key, value]) => b[key] === value);
773
+ if (same(collapsed, current.mappings) && same(parked, current.blocked ?? {})) return revived;
774
+ state = { ...current, mappings: collapsed, blocked: parked };
775
+ await publishState(deps, state);
776
+ return revived;
777
+ };
778
+ const previousMappings = state.mappings;
779
+ const collapsedMappings = collapseMappings(previousMappings);
780
+ const mappingsChanged = Object.keys(collapsedMappings).length !== Object.keys(previousMappings).length || Object.entries(collapsedMappings).some(
781
+ ([legacyId, canonicalId]) => previousMappings[legacyId] !== canonicalId
782
+ );
783
+ state = { ...state, mappings: collapsedMappings };
784
+ for (let migrationPass = 0; migrationPass < ENTITY_MAPPING_RESCAN_MAX_PASSES; migrationPass += 1) {
785
+ if (!await lock.refresh()) throw new Error("Lost entity canonical-id migration lock.");
786
+ const discoveredBefore = rejectMappingCycles(
787
+ state.mappings,
788
+ await discoverMappings(deps, state.mappings, blocked, scanNotes)
789
+ );
790
+ const revivedBefore = await pruneBlocked();
791
+ const mergedBefore = collapseMappings(mergeDiscoveredMappings(state.mappings, discoveredBefore));
792
+ if (state.complete && Object.keys(discoveredBefore).length === 0 && !mappingsChanged && !revivedBefore) {
793
+ if (reconcileRequested && Object.keys(state.mappings).length > 0) {
794
+ const rewroteColdMemory2 = await rewriteKnownReferences(
795
+ deps,
796
+ state.mappings,
797
+ () => lock.refresh()
798
+ );
799
+ deps.invalidateKnowledgeIndexCache();
800
+ deps.invalidateAllMemoriesCache();
801
+ if (rewroteColdMemory2) deps.invalidateColdMemoriesCache();
802
+ deps.bumpMemoryStatusVersion();
803
+ }
804
+ return finish();
805
+ }
806
+ if (state.complete || Object.keys(discoveredBefore).length > 0 || Object.keys(mergedBefore).length !== Object.keys(state.mappings).length) {
807
+ state = { ...state, complete: false, mappings: mergedBefore };
808
+ await publishState(deps, state);
809
+ }
810
+ if (Object.keys(state.mappings).length === 0) {
811
+ if (!await lock.refresh()) throw new Error("Lost entity canonical-id migration lock.");
812
+ const discoveredAfter2 = rejectMappingCycles(
813
+ state.mappings,
814
+ await discoverMappings(deps, state.mappings, blocked, scanNotes)
815
+ );
816
+ const revivedInRescan = await pruneBlocked();
817
+ if (Object.keys(discoveredAfter2).length === 0 && !revivedInRescan) {
818
+ await publishState(deps, { ...state, complete: true });
819
+ return finish();
820
+ }
821
+ state = {
822
+ ...state,
823
+ complete: false,
824
+ mappings: collapseMappings(mergeDiscoveredMappings(state.mappings, discoveredAfter2))
825
+ };
826
+ await publishState(deps, state);
827
+ continue;
828
+ }
829
+ let pendingMappings = Object.entries(state.mappings);
830
+ while (pendingMappings.length > 0) {
831
+ const deferredMappings = [];
832
+ let progressed = false;
833
+ for (const [legacyId, canonicalId] of pendingMappings) {
834
+ const result = await migrateEntityFilePair(
835
+ deps,
836
+ legacyId,
837
+ canonicalId,
838
+ () => lock.refresh()
839
+ );
840
+ if (result.blocked) blocked.set(legacyId, canonicalId);
841
+ else if (result.deferred) deferredMappings.push([legacyId, canonicalId]);
842
+ progressed ||= result.progressed;
843
+ }
844
+ if (deferredMappings.length === 0) break;
845
+ if (!progressed) {
846
+ for (const [legacyId, canonicalId] of deferredMappings) {
847
+ blocked.set(legacyId, canonicalId);
848
+ staleParked.set(legacyId, canonicalId);
849
+ }
850
+ break;
851
+ }
852
+ pendingMappings = deferredMappings;
853
+ }
854
+ await pruneBlocked();
855
+ const rewroteColdMemory = await rewriteKnownReferences(
856
+ deps,
857
+ state.mappings,
858
+ () => lock.refresh()
859
+ );
860
+ deps.invalidateKnowledgeIndexCache();
861
+ deps.invalidateAllMemoriesCache();
862
+ if (rewroteColdMemory) deps.invalidateColdMemoriesCache();
863
+ deps.bumpMemoryStatusVersion();
864
+ if (!await lock.refresh()) throw new Error("Lost entity canonical-id migration lock.");
865
+ const discoveredAfter = rejectMappingCycles(
866
+ state.mappings,
867
+ await discoverMappings(deps, state.mappings, blocked, scanNotes)
868
+ );
869
+ const revivedAfterRewrite = await pruneBlocked();
870
+ if (Object.keys(discoveredAfter).length === 0 && !revivedAfterRewrite) {
871
+ await publishState(deps, { ...state, complete: true });
872
+ return finish();
873
+ }
874
+ state = {
875
+ ...state,
876
+ complete: false,
877
+ mappings: collapseMappings(mergeDiscoveredMappings(state.mappings, discoveredAfter))
878
+ };
879
+ await publishState(deps, state);
880
+ }
881
+ throw new Error("Entity canonical-id migration mappings changed while migration was running; retry migration.");
882
+ }
883
+ );
884
+ }
885
+
886
+ export {
887
+ getFingerprint,
888
+ validateRoots,
889
+ readSafeEntityEntries,
890
+ migrateLegacyEntityCanonicalIds
891
+ };
892
+ //# sourceMappingURL=chunk-DNIG3JME.js.map