@remnic/core 9.69.23 → 9.69.25

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 (438) hide show
  1. package/dist/abstraction-nodes.js +3 -2
  2. package/dist/access-admin-ops-surface.d.ts +1 -1
  3. package/dist/access-admin-ops-surface.js +53 -53
  4. package/dist/access-authorization-probe.d.ts +1 -1
  5. package/dist/access-authorization-probe.js +54 -54
  6. package/dist/access-boundary.d.ts +1 -1
  7. package/dist/access-boundary.js +53 -53
  8. package/dist/access-citation-namespace.js +3 -3
  9. package/dist/access-cli.js +112 -112
  10. package/dist/access-extraction-force-flush.d.ts +1 -1
  11. package/dist/access-extraction-force-flush.js +53 -53
  12. package/dist/access-http-briefing.d.ts +1 -1
  13. package/dist/access-http-briefing.js +54 -54
  14. package/dist/access-http-lcm-compaction.d.ts +1 -1
  15. package/dist/access-http-lifecycle-flush.d.ts +1 -1
  16. package/dist/access-http-offline-stream.d.ts +1 -1
  17. package/dist/access-http-query.js +55 -55
  18. package/dist/access-http.d.ts +2 -2
  19. package/dist/access-http.js +72 -72
  20. package/dist/access-identity-continuity-surface.js +53 -53
  21. package/dist/access-lcm-surface.d.ts +1 -1
  22. package/dist/access-lcm-surface.js +53 -53
  23. package/dist/access-mcp.d.ts +1 -1
  24. package/dist/access-mcp.js +64 -64
  25. package/dist/access-namespace-preflight.js +53 -53
  26. package/dist/access-observe-write-surface.d.ts +1 -1
  27. package/dist/access-observe-write-surface.js +53 -53
  28. package/dist/access-offline-manifest.js +10 -10
  29. package/dist/access-operations-batch.js +58 -58
  30. package/dist/access-operations.d.ts +1 -1
  31. package/dist/access-operations.js +63 -63
  32. package/dist/access-recall-concurrency.d.ts +1 -1
  33. package/dist/access-recall-concurrency.js +53 -53
  34. package/dist/access-recall-response.d.ts +1 -1
  35. package/dist/access-recall-response.js +53 -53
  36. package/dist/access-recall-surface.d.ts +1 -1
  37. package/dist/access-recall-surface.js +53 -53
  38. package/dist/access-schema.js +6 -5
  39. package/dist/access-service-helpers.d.ts +1 -1
  40. package/dist/access-service.d.ts +1 -1
  41. package/dist/access-service.js +53 -53
  42. package/dist/access-surface-catalog.d.ts +1 -1
  43. package/dist/access-surface-catalog.js +55 -55
  44. package/dist/active-recall.js +12 -11
  45. package/dist/active-recall.js.map +1 -1
  46. package/dist/{auto-sync-TTIEWJ5X.js → auto-sync-WNGG2GC2.js} +7 -7
  47. package/dist/briefing.js +20 -20
  48. package/dist/buffer.js +9 -9
  49. package/dist/calibration.js +2 -1
  50. package/dist/calibration.js.map +1 -1
  51. package/dist/{capsule-merge-CU6QJBSV.js → capsule-merge-IPG4IOFP.js} +4 -4
  52. package/dist/causal-behavior.js +4 -3
  53. package/dist/causal-behavior.js.map +1 -1
  54. package/dist/causal-chain.js +4 -3
  55. package/dist/causal-consolidation.js +25 -25
  56. package/dist/causal-retrieval.js +4 -3
  57. package/dist/causal-retrieval.js.map +1 -1
  58. package/dist/causal-trajectory-graph.js +2 -1
  59. package/dist/causal-trajectory-graph.js.map +1 -1
  60. package/dist/causal-trajectory.js +3 -2
  61. package/dist/{chunk-5RWHODVF.js → chunk-27QVNSQ3.js} +2 -2
  62. package/dist/{chunk-2MX7RU7B.js → chunk-2EKJDQZB.js} +2 -2
  63. package/dist/{chunk-XLRM6PPI.js → chunk-2IOHTUP3.js} +4 -4
  64. package/dist/{chunk-ZGQDTD5T.js → chunk-2ITE4C2Z.js} +2 -2
  65. package/dist/{chunk-O5ZR7SXV.js → chunk-2SGLMP2E.js} +2 -2
  66. package/dist/{chunk-FYWLSFFS.js → chunk-2Z4GS5E6.js} +2 -2
  67. package/dist/{chunk-WELP4CG6.js → chunk-37KUQPX4.js} +6 -6
  68. package/dist/{chunk-DDQQY2E3.js → chunk-3BTFBQLO.js} +7 -7
  69. package/dist/chunk-3BTFBQLO.js.map +1 -0
  70. package/dist/{chunk-UR6PBX2J.js → chunk-3K7V3HE6.js} +35 -60
  71. package/dist/chunk-3K7V3HE6.js.map +1 -0
  72. package/dist/{chunk-MRSLR6TB.js → chunk-3QQTXYZ6.js} +2 -2
  73. package/dist/{chunk-DJUKBGAD.js → chunk-46EST7JO.js} +5 -5
  74. package/dist/chunk-46EST7JO.js.map +1 -0
  75. package/dist/{chunk-CI6C33EO.js → chunk-46ZPIGWI.js} +3 -3
  76. package/dist/{chunk-HTIIXNJQ.js → chunk-4FIH6MPS.js} +6 -3
  77. package/dist/chunk-4FIH6MPS.js.map +1 -0
  78. package/dist/{chunk-MCA2X4WH.js → chunk-4IHBN6WU.js} +2 -2
  79. package/dist/{chunk-W7IGLX4G.js → chunk-4O6WRBGE.js} +7 -7
  80. package/dist/chunk-4O6WRBGE.js.map +1 -0
  81. package/dist/{chunk-TOZCM7WN.js → chunk-4TKJGOCJ.js} +2 -2
  82. package/dist/{chunk-3ADRFFRO.js → chunk-54WHLA65.js} +4 -4
  83. package/dist/{chunk-Z2N2AHEM.js → chunk-56Y6EKZN.js} +2 -2
  84. package/dist/{chunk-2H2N5UQW.js → chunk-5ATKSPEQ.js} +2 -2
  85. package/dist/{chunk-MSOXFXCA.js → chunk-5FAGCOZD.js} +5 -5
  86. package/dist/chunk-5FAGCOZD.js.map +1 -0
  87. package/dist/{chunk-ZVZHG7AI.js → chunk-5UBH37SL.js} +3 -3
  88. package/dist/{chunk-YZYZ2BEU.js → chunk-66OJSCI6.js} +2 -2
  89. package/dist/{chunk-HNPE66LB.js → chunk-6CVNSDCZ.js} +4 -4
  90. package/dist/{chunk-ERVJFFTR.js → chunk-6NXSYYGP.js} +2 -2
  91. package/dist/{chunk-2HIJHXB3.js → chunk-6WHJ2EAB.js} +2 -2
  92. package/dist/{chunk-34VTBPNE.js → chunk-6XL73HQ4.js} +4 -4
  93. package/dist/{chunk-YK3UIF7X.js → chunk-AQ7SYDVO.js} +2 -2
  94. package/dist/{chunk-DSCCM66R.js → chunk-B3O3IRZN.js} +2 -2
  95. package/dist/{chunk-P77QX3ID.js → chunk-B6O2YLUR.js} +21 -20
  96. package/dist/chunk-B6O2YLUR.js.map +1 -0
  97. package/dist/{chunk-N37X5RU7.js → chunk-BD7JTBYP.js} +2 -2
  98. package/dist/{chunk-VO43BJ2F.js → chunk-BLJWYCNO.js} +5 -5
  99. package/dist/{chunk-ACPCA4NO.js → chunk-BMWN7B3Y.js} +6 -6
  100. package/dist/chunk-BMWN7B3Y.js.map +1 -0
  101. package/dist/{chunk-HSKSVY3Q.js → chunk-C553ZTLF.js} +15 -15
  102. package/dist/{chunk-GCASGYIO.js → chunk-C7HJ3NEI.js} +2 -2
  103. package/dist/{chunk-WVGXCBOC.js → chunk-D5F7TKMH.js} +2 -2
  104. package/dist/{chunk-UFT2XNBW.js → chunk-DGS34QSY.js} +2 -2
  105. package/dist/{chunk-VAOL3SOT.js → chunk-DZD3WGCD.js} +4 -4
  106. package/dist/{chunk-KHMS2FQS.js → chunk-E2P7TZTF.js} +2 -2
  107. package/dist/{chunk-6FC3IZ26.js → chunk-EBA5DA77.js} +2 -2
  108. package/dist/{chunk-E6EANYLD.js → chunk-EOQ6FSQP.js} +2 -2
  109. package/dist/{chunk-7RPPCA26.js → chunk-FVOP3NT7.js} +2 -2
  110. package/dist/{chunk-NRLELHAY.js → chunk-G7NYVKD6.js} +2 -2
  111. package/dist/{chunk-QY34X2QJ.js → chunk-GHTSNGBZ.js} +2 -2
  112. package/dist/{chunk-SLIOMMPF.js → chunk-H272ZPQ3.js} +5 -5
  113. package/dist/{chunk-ZZBQNQS6.js → chunk-H3TKENU4.js} +2 -2
  114. package/dist/{chunk-5OPNUUBX.js → chunk-H4SEGIZY.js} +2 -2
  115. package/dist/{chunk-F2HMDGLC.js → chunk-H54VWRPS.js} +13 -13
  116. package/dist/{chunk-HTP6XRUI.js → chunk-HM7RHKS4.js} +2 -2
  117. package/dist/{chunk-O7H3P2SJ.js → chunk-HWLIMQE2.js} +2 -2
  118. package/dist/{chunk-62WZDHTW.js → chunk-ICKJ52PE.js} +33 -33
  119. package/dist/chunk-ICKJ52PE.js.map +1 -0
  120. package/dist/{chunk-I3FDDCY3.js → chunk-JEC4DVM3.js} +8 -8
  121. package/dist/chunk-JEC4DVM3.js.map +1 -0
  122. package/dist/{chunk-ET2CNMLD.js → chunk-JN72EPOE.js} +2 -2
  123. package/dist/{chunk-E7UQOS4C.js → chunk-JPKK466T.js} +2 -2
  124. package/dist/{chunk-JCCWJHOP.js → chunk-JYZSRNR7.js} +2 -2
  125. package/dist/{chunk-7IUESBLV.js → chunk-K7724CH2.js} +2 -2
  126. package/dist/{chunk-UK7HXNNJ.js → chunk-KAXCYM66.js} +3 -3
  127. package/dist/{chunk-7XVP4P4O.js → chunk-KB2G2I6Q.js} +3 -3
  128. package/dist/{chunk-K7LTRJZU.js → chunk-KEF46KL2.js} +2 -2
  129. package/dist/{chunk-5UZXUTVO.js → chunk-KNA3BXXL.js} +6 -2
  130. package/dist/chunk-KNA3BXXL.js.map +1 -0
  131. package/dist/{chunk-JYYTWCPU.js → chunk-KTWG7CNY.js} +6 -6
  132. package/dist/{chunk-XTYDEO7M.js → chunk-L7Z57SID.js} +2 -2
  133. package/dist/{chunk-EYMPUXAN.js → chunk-LO4UKPKX.js} +3 -3
  134. package/dist/{chunk-LDWIPYJ6.js → chunk-LS2FHUML.js} +3 -3
  135. package/dist/{chunk-GDB4J2H3.js → chunk-MPC7TYTZ.js} +2 -2
  136. package/dist/{chunk-2GF27PGH.js → chunk-MRPOZBJC.js} +3 -3
  137. package/dist/{chunk-7OLKAQMG.js → chunk-MWN6QEI2.js} +2 -2
  138. package/dist/{chunk-J62HG52Z.js → chunk-MY5EDR46.js} +4 -4
  139. package/dist/{chunk-IZRMWPGS.js → chunk-N3ZOP7KC.js} +2 -2
  140. package/dist/{chunk-N6A2RP5S.js → chunk-NB3LRY4T.js} +3 -3
  141. package/dist/{chunk-4N5BIR2U.js → chunk-ND6IQGSZ.js} +2 -2
  142. package/dist/{chunk-NOB2T2FC.js → chunk-NHLLKEKK.js} +2 -2
  143. package/dist/{chunk-WW6B7NQJ.js → chunk-NLYVH66G.js} +6 -6
  144. package/dist/chunk-NLYVH66G.js.map +1 -0
  145. package/dist/{chunk-M5CQNOQN.js → chunk-O6ZNNVSP.js} +2 -2
  146. package/dist/{chunk-NNBZS3DY.js → chunk-OB3XMWX5.js} +2 -2
  147. package/dist/{chunk-TXJNRGMI.js → chunk-OEYZXDQI.js} +6 -6
  148. package/dist/chunk-OEYZXDQI.js.map +1 -0
  149. package/dist/{chunk-SIBVIP2Y.js → chunk-PAZY2ZKP.js} +2 -2
  150. package/dist/{chunk-LXESHEBP.js → chunk-PX4UMA5Z.js} +2 -2
  151. package/dist/{chunk-4KNRKJXQ.js → chunk-QOOBICJF.js} +5 -5
  152. package/dist/chunk-QOOBICJF.js.map +1 -0
  153. package/dist/{chunk-NNZFPYYX.js → chunk-R7QY5ZVB.js} +2 -2
  154. package/dist/{chunk-WTRTFIIN.js → chunk-R7RTXEYG.js} +2 -2
  155. package/dist/{chunk-XRBJ5R3P.js → chunk-RBCQVOVJ.js} +3 -3
  156. package/dist/{chunk-WFZNT4KB.js → chunk-RC5DXXWC.js} +2 -2
  157. package/dist/{chunk-OH7LZHGJ.js → chunk-RJYJ7KR7.js} +52 -52
  158. package/dist/{chunk-OH7LZHGJ.js.map → chunk-RJYJ7KR7.js.map} +1 -1
  159. package/dist/{chunk-5QZR2RA3.js → chunk-ROBHL3GL.js} +2 -2
  160. package/dist/{chunk-6PST2SFW.js → chunk-SCXURCVT.js} +3 -3
  161. package/dist/{chunk-AYG7ML7O.js → chunk-SJDQ5RSN.js} +3 -3
  162. package/dist/{chunk-3ZBLKIHJ.js → chunk-SMWTZLHE.js} +51 -41
  163. package/dist/{chunk-3ZBLKIHJ.js.map → chunk-SMWTZLHE.js.map} +1 -1
  164. package/dist/{chunk-IQXDSKTL.js → chunk-SVXJLDDC.js} +6 -6
  165. package/dist/{chunk-SEF4IOFE.js → chunk-SWIKABKI.js} +2 -2
  166. package/dist/{chunk-ZJABRLCZ.js → chunk-TBXAY2SS.js} +4 -4
  167. package/dist/{chunk-GIC6BASP.js → chunk-TNSCIPBQ.js} +2 -2
  168. package/dist/{chunk-ZMDMHSV2.js → chunk-TVEONGBU.js} +2 -2
  169. package/dist/{chunk-4FSEZRGK.js → chunk-TWF35IC6.js} +2 -2
  170. package/dist/{chunk-LS2SGMQE.js → chunk-U6N5IBVY.js} +2 -2
  171. package/dist/{chunk-62YW6OYI.js → chunk-UCKYTA2T.js} +3 -3
  172. package/dist/{chunk-YFCHNOGJ.js → chunk-UNNPNBR2.js} +9 -9
  173. package/dist/{chunk-Z2M7F4QM.js → chunk-VVX5PZFS.js} +3 -3
  174. package/dist/{chunk-NTYLZXDX.js → chunk-VYCOJKSX.js} +2 -2
  175. package/dist/{chunk-UICSQESY.js → chunk-W24T5YMW.js} +2 -2
  176. package/dist/{chunk-HDQUQBPW.js → chunk-W3K3HITK.js} +2 -2
  177. package/dist/{chunk-GDASG7NC.js → chunk-W4F3C7N7.js} +2 -2
  178. package/dist/{chunk-YBLZFNIQ.js → chunk-WJHGDE7X.js} +2 -2
  179. package/dist/{chunk-ZBPXG5PJ.js → chunk-WMLEPWMO.js} +9 -9
  180. package/dist/chunk-WMLEPWMO.js.map +1 -0
  181. package/dist/{chunk-4F24PHNX.js → chunk-WQZZDN5M.js} +2 -2
  182. package/dist/{chunk-CDZEUCV7.js → chunk-X5K5TAQZ.js} +4 -4
  183. package/dist/{chunk-5AUODSOQ.js → chunk-XM24CDZX.js} +3 -3
  184. package/dist/{chunk-6VML2LII.js → chunk-XOVKXJEP.js} +3 -3
  185. package/dist/{chunk-OU5TIWDQ.js → chunk-XSGUMQQQ.js} +12 -12
  186. package/dist/{chunk-7CFVBWDC.js → chunk-XUE46UYW.js} +3 -3
  187. package/dist/{chunk-DJORULH3.js → chunk-YRLHEEQT.js} +2 -2
  188. package/dist/{chunk-YRWDPE32.js → chunk-Z3O53WZR.js} +2 -2
  189. package/dist/{chunk-CSY5DA7O.js → chunk-Z6COGHHN.js} +2 -2
  190. package/dist/{chunk-OYR3IPHD.js → chunk-ZIW5JVRM.js} +2 -2
  191. package/dist/{cli-B_YwqoIr.d.ts → cli-BqMNkQn5.d.ts} +1 -1
  192. package/dist/cli.d.ts +2 -2
  193. package/dist/cli.js +94 -94
  194. package/dist/coding/export-okf-codegraph.js +21 -21
  195. package/dist/coding/pre-action-gate.js +4 -3
  196. package/dist/commitment-ledger.js +3 -2
  197. package/dist/compounding/engine.js +21 -21
  198. package/dist/config.js +12 -11
  199. package/dist/connectors/codex-materialize-runner.js +21 -21
  200. package/dist/connectors/codex-materialize.js +3 -3
  201. package/dist/connectors/index.js +21 -21
  202. package/dist/consolidation-provenance-check.js +4 -4
  203. package/dist/consolidation-undo.js +3 -3
  204. package/dist/contradiction/index.js +7 -7
  205. package/dist/convergence-refresh.js +22 -22
  206. package/dist/corpus-watermark.js +22 -22
  207. package/dist/cue-anchors.js +4 -3
  208. package/dist/deep-recall-http-glue.d.ts +1 -1
  209. package/dist/deep-recall-http-glue.js +7 -6
  210. package/dist/deep-recall-mcp-tools.d.ts +1 -1
  211. package/dist/entity-retrieval.js +20 -20
  212. package/dist/eval-trajectory-store.js +4 -3
  213. package/dist/eval-trajectory.js +4 -3
  214. package/dist/evals.js +3 -2
  215. package/dist/explicit-capture.js +8 -8
  216. package/dist/external-wiki-access.d.ts +1 -1
  217. package/dist/external-wiki-access.js +54 -54
  218. package/dist/external-wiki-mcp-tools.d.ts +1 -1
  219. package/dist/extraction.js +25 -25
  220. package/dist/{first-start-migration-KHIMCBIC.js → first-start-migration-RC345GPL.js} +6 -5
  221. package/dist/{first-start-migration-KHIMCBIC.js.map → first-start-migration-RC345GPL.js.map} +1 -1
  222. package/dist/{graph-edge-decay-CJW4OT2X.js → graph-edge-decay-MKIRZ762.js} +5 -4
  223. package/dist/graph-jsonl.js +3 -2
  224. package/dist/graph-snapshot.js +3 -2
  225. package/dist/graph.js +2 -1
  226. package/dist/harmonic-construction.js +5 -4
  227. package/dist/harmonic-retrieval.js +5 -4
  228. package/dist/index.d.ts +19 -7
  229. package/dist/index.js +114 -112
  230. package/dist/json-store.js +2 -1
  231. package/dist/live-connectors-runner.js +3 -2
  232. package/dist/location/index.js +23 -23
  233. package/dist/maintenance/memory-governance.js +20 -20
  234. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +20 -20
  235. package/dist/maintenance/rebuild-memory-projection.js +21 -21
  236. package/dist/mcp-memory-inspector-app.d.ts +1 -1
  237. package/dist/memory-projection-mutations.js +3 -3
  238. package/dist/memory-subject-cli.d.ts +1 -1
  239. package/dist/memory-subject.d.ts +1 -1
  240. package/dist/memory-subject.js +4 -4
  241. package/dist/namespaces/migrate.js +21 -21
  242. package/dist/namespaces/search.js +8 -8
  243. package/dist/namespaces/storage.js +20 -20
  244. package/dist/objective-state-writers.js +4 -3
  245. package/dist/objective-state.js +3 -2
  246. package/dist/offline-sync-file-io.js +4 -3
  247. package/dist/offline-sync-impression-drain.js +5 -5
  248. package/dist/offline-sync.js +5 -4
  249. package/dist/operator-doctor-corpus.js +23 -23
  250. package/dist/operator-toolkit.js +38 -38
  251. package/dist/orchestration/maintenance.js +29 -29
  252. package/dist/orchestrator.js +112 -112
  253. package/dist/page-versioning.js +3 -3
  254. package/dist/{public-http-D6d4W8x-.d.ts → public-http-ByX2eTla.d.ts} +1 -1
  255. package/dist/{purge-OP6BEDFY.js → purge-TZKRE6ZQ.js} +5 -5
  256. package/dist/purge-TZKRE6ZQ.js.map +1 -0
  257. package/dist/recall-state.js +3 -3
  258. package/dist/reconcile/manifest.js +4 -4
  259. package/dist/{resolution-U5O4QANY.js → resolution-VKATP2HT.js} +8 -8
  260. package/dist/resume-bundles.js +16 -15
  261. package/dist/salvage-envelope.js +6 -6
  262. package/dist/schemas.d.ts +42 -42
  263. package/dist/search/document-scanner.js +3 -3
  264. package/dist/search/factory.js +7 -7
  265. package/dist/search/index.js +7 -7
  266. package/dist/search/lancedb-backend.js +4 -4
  267. package/dist/search/meilisearch-backend.js +4 -4
  268. package/dist/search/orama-backend.js +4 -4
  269. package/dist/secure-store/index.js +3 -3
  270. package/dist/semantic-consolidation.js +22 -22
  271. package/dist/semantic-rule-promotion.js +20 -20
  272. package/dist/semantic-rule-verifier.js +20 -20
  273. package/dist/source-agent-qualifier.js +24 -24
  274. package/dist/standup/build.js +20 -20
  275. package/dist/storage.js +19 -19
  276. package/dist/subject-config.js +5 -5
  277. package/dist/support-passport/index.d.ts +4 -4
  278. package/dist/support-passport/index.js +56 -56
  279. package/dist/{tier-stats-2TOW3QNL.js → tier-stats-KA6OZX2C.js} +6 -5
  280. package/dist/{tier-stats-2TOW3QNL.js.map → tier-stats-KA6OZX2C.js.map} +1 -1
  281. package/dist/transfer/capsule-import.js +4 -4
  282. package/dist/transfer/export-okf.js +21 -21
  283. package/dist/transfer/types.d.ts +12 -12
  284. package/dist/trust-zones.js +3 -2
  285. package/dist/utility-learner.js +4 -3
  286. package/dist/utility-runtime.js +5 -4
  287. package/dist/utility-telemetry.js +3 -2
  288. package/dist/verified-recall.js +20 -20
  289. package/dist/who-knows-cli.d.ts +1 -1
  290. package/dist/who-knows-cli.js +21 -21
  291. package/dist/who-knows.d.ts +1 -1
  292. package/dist/who-knows.js +20 -20
  293. package/dist/work/board.js +3 -3
  294. package/dist/work/storage.js +2 -2
  295. package/dist/work-product-ledger.js +3 -2
  296. package/dist/write-envelope.js +5 -5
  297. package/package.json +2 -2
  298. package/src/abstraction-nodes.ts +1 -4
  299. package/src/binary-lifecycle/backend.ts +2 -1
  300. package/src/connectors/live/github.ts +10 -17
  301. package/src/connectors/live/gmail.ts +8 -19
  302. package/src/connectors/live/google-drive.ts +6 -13
  303. package/src/connectors/live/notion.ts +11 -21
  304. package/src/cue-anchors.ts +1 -6
  305. package/src/graph.ts +2 -4
  306. package/src/json-store.ts +17 -20
  307. package/src/live-connectors-runner.ts +2 -1
  308. package/src/location/store.ts +1 -4
  309. package/src/maintenance/purge.ts +2 -5
  310. package/src/maintenance/rebuild-memory-lifecycle-ledger.ts +3 -6
  311. package/src/maintenance/rebuild-memory-projection.ts +2 -5
  312. package/src/namespaces/catalog.ts +1 -9
  313. package/src/offline-sync-file-io.test.ts +39 -0
  314. package/src/offline-sync-file-io.ts +3 -7
  315. package/src/procedural/procedure-miner.ts +1 -9
  316. package/src/search/document-scanner.ts +3 -6
  317. package/src/semantic-rule-promotion.ts +1 -4
  318. package/src/utils/errno.test.ts +31 -0
  319. package/src/utils/errno.ts +5 -0
  320. package/src/wearables/index.ts +1 -0
  321. package/src/wearables/registry.ts +23 -0
  322. package/dist/chunk-4KNRKJXQ.js.map +0 -1
  323. package/dist/chunk-5UZXUTVO.js.map +0 -1
  324. package/dist/chunk-62WZDHTW.js.map +0 -1
  325. package/dist/chunk-ACPCA4NO.js.map +0 -1
  326. package/dist/chunk-DDQQY2E3.js.map +0 -1
  327. package/dist/chunk-DJUKBGAD.js.map +0 -1
  328. package/dist/chunk-HTIIXNJQ.js.map +0 -1
  329. package/dist/chunk-I3FDDCY3.js.map +0 -1
  330. package/dist/chunk-MSOXFXCA.js.map +0 -1
  331. package/dist/chunk-P77QX3ID.js.map +0 -1
  332. package/dist/chunk-TXJNRGMI.js.map +0 -1
  333. package/dist/chunk-UR6PBX2J.js.map +0 -1
  334. package/dist/chunk-W7IGLX4G.js.map +0 -1
  335. package/dist/chunk-WW6B7NQJ.js.map +0 -1
  336. package/dist/chunk-ZBPXG5PJ.js.map +0 -1
  337. package/dist/purge-OP6BEDFY.js.map +0 -1
  338. package/dist/{access-service-Cv8Rizo0.d.ts → access-service-GrdVg_-Z.d.ts} +6 -6
  339. /package/dist/{auto-sync-TTIEWJ5X.js.map → auto-sync-WNGG2GC2.js.map} +0 -0
  340. /package/dist/{capsule-merge-CU6QJBSV.js.map → capsule-merge-IPG4IOFP.js.map} +0 -0
  341. /package/dist/{chunk-5RWHODVF.js.map → chunk-27QVNSQ3.js.map} +0 -0
  342. /package/dist/{chunk-2MX7RU7B.js.map → chunk-2EKJDQZB.js.map} +0 -0
  343. /package/dist/{chunk-XLRM6PPI.js.map → chunk-2IOHTUP3.js.map} +0 -0
  344. /package/dist/{chunk-ZGQDTD5T.js.map → chunk-2ITE4C2Z.js.map} +0 -0
  345. /package/dist/{chunk-O5ZR7SXV.js.map → chunk-2SGLMP2E.js.map} +0 -0
  346. /package/dist/{chunk-FYWLSFFS.js.map → chunk-2Z4GS5E6.js.map} +0 -0
  347. /package/dist/{chunk-WELP4CG6.js.map → chunk-37KUQPX4.js.map} +0 -0
  348. /package/dist/{chunk-MRSLR6TB.js.map → chunk-3QQTXYZ6.js.map} +0 -0
  349. /package/dist/{chunk-CI6C33EO.js.map → chunk-46ZPIGWI.js.map} +0 -0
  350. /package/dist/{chunk-MCA2X4WH.js.map → chunk-4IHBN6WU.js.map} +0 -0
  351. /package/dist/{chunk-TOZCM7WN.js.map → chunk-4TKJGOCJ.js.map} +0 -0
  352. /package/dist/{chunk-3ADRFFRO.js.map → chunk-54WHLA65.js.map} +0 -0
  353. /package/dist/{chunk-Z2N2AHEM.js.map → chunk-56Y6EKZN.js.map} +0 -0
  354. /package/dist/{chunk-2H2N5UQW.js.map → chunk-5ATKSPEQ.js.map} +0 -0
  355. /package/dist/{chunk-ZVZHG7AI.js.map → chunk-5UBH37SL.js.map} +0 -0
  356. /package/dist/{chunk-YZYZ2BEU.js.map → chunk-66OJSCI6.js.map} +0 -0
  357. /package/dist/{chunk-HNPE66LB.js.map → chunk-6CVNSDCZ.js.map} +0 -0
  358. /package/dist/{chunk-ERVJFFTR.js.map → chunk-6NXSYYGP.js.map} +0 -0
  359. /package/dist/{chunk-2HIJHXB3.js.map → chunk-6WHJ2EAB.js.map} +0 -0
  360. /package/dist/{chunk-34VTBPNE.js.map → chunk-6XL73HQ4.js.map} +0 -0
  361. /package/dist/{chunk-YK3UIF7X.js.map → chunk-AQ7SYDVO.js.map} +0 -0
  362. /package/dist/{chunk-DSCCM66R.js.map → chunk-B3O3IRZN.js.map} +0 -0
  363. /package/dist/{chunk-N37X5RU7.js.map → chunk-BD7JTBYP.js.map} +0 -0
  364. /package/dist/{chunk-VO43BJ2F.js.map → chunk-BLJWYCNO.js.map} +0 -0
  365. /package/dist/{chunk-HSKSVY3Q.js.map → chunk-C553ZTLF.js.map} +0 -0
  366. /package/dist/{chunk-GCASGYIO.js.map → chunk-C7HJ3NEI.js.map} +0 -0
  367. /package/dist/{chunk-WVGXCBOC.js.map → chunk-D5F7TKMH.js.map} +0 -0
  368. /package/dist/{chunk-UFT2XNBW.js.map → chunk-DGS34QSY.js.map} +0 -0
  369. /package/dist/{chunk-VAOL3SOT.js.map → chunk-DZD3WGCD.js.map} +0 -0
  370. /package/dist/{chunk-KHMS2FQS.js.map → chunk-E2P7TZTF.js.map} +0 -0
  371. /package/dist/{chunk-6FC3IZ26.js.map → chunk-EBA5DA77.js.map} +0 -0
  372. /package/dist/{chunk-E6EANYLD.js.map → chunk-EOQ6FSQP.js.map} +0 -0
  373. /package/dist/{chunk-7RPPCA26.js.map → chunk-FVOP3NT7.js.map} +0 -0
  374. /package/dist/{chunk-NRLELHAY.js.map → chunk-G7NYVKD6.js.map} +0 -0
  375. /package/dist/{chunk-QY34X2QJ.js.map → chunk-GHTSNGBZ.js.map} +0 -0
  376. /package/dist/{chunk-SLIOMMPF.js.map → chunk-H272ZPQ3.js.map} +0 -0
  377. /package/dist/{chunk-ZZBQNQS6.js.map → chunk-H3TKENU4.js.map} +0 -0
  378. /package/dist/{chunk-5OPNUUBX.js.map → chunk-H4SEGIZY.js.map} +0 -0
  379. /package/dist/{chunk-F2HMDGLC.js.map → chunk-H54VWRPS.js.map} +0 -0
  380. /package/dist/{chunk-HTP6XRUI.js.map → chunk-HM7RHKS4.js.map} +0 -0
  381. /package/dist/{chunk-O7H3P2SJ.js.map → chunk-HWLIMQE2.js.map} +0 -0
  382. /package/dist/{chunk-ET2CNMLD.js.map → chunk-JN72EPOE.js.map} +0 -0
  383. /package/dist/{chunk-E7UQOS4C.js.map → chunk-JPKK466T.js.map} +0 -0
  384. /package/dist/{chunk-JCCWJHOP.js.map → chunk-JYZSRNR7.js.map} +0 -0
  385. /package/dist/{chunk-7IUESBLV.js.map → chunk-K7724CH2.js.map} +0 -0
  386. /package/dist/{chunk-UK7HXNNJ.js.map → chunk-KAXCYM66.js.map} +0 -0
  387. /package/dist/{chunk-7XVP4P4O.js.map → chunk-KB2G2I6Q.js.map} +0 -0
  388. /package/dist/{chunk-K7LTRJZU.js.map → chunk-KEF46KL2.js.map} +0 -0
  389. /package/dist/{chunk-JYYTWCPU.js.map → chunk-KTWG7CNY.js.map} +0 -0
  390. /package/dist/{chunk-XTYDEO7M.js.map → chunk-L7Z57SID.js.map} +0 -0
  391. /package/dist/{chunk-EYMPUXAN.js.map → chunk-LO4UKPKX.js.map} +0 -0
  392. /package/dist/{chunk-LDWIPYJ6.js.map → chunk-LS2FHUML.js.map} +0 -0
  393. /package/dist/{chunk-GDB4J2H3.js.map → chunk-MPC7TYTZ.js.map} +0 -0
  394. /package/dist/{chunk-2GF27PGH.js.map → chunk-MRPOZBJC.js.map} +0 -0
  395. /package/dist/{chunk-7OLKAQMG.js.map → chunk-MWN6QEI2.js.map} +0 -0
  396. /package/dist/{chunk-J62HG52Z.js.map → chunk-MY5EDR46.js.map} +0 -0
  397. /package/dist/{chunk-IZRMWPGS.js.map → chunk-N3ZOP7KC.js.map} +0 -0
  398. /package/dist/{chunk-N6A2RP5S.js.map → chunk-NB3LRY4T.js.map} +0 -0
  399. /package/dist/{chunk-4N5BIR2U.js.map → chunk-ND6IQGSZ.js.map} +0 -0
  400. /package/dist/{chunk-NOB2T2FC.js.map → chunk-NHLLKEKK.js.map} +0 -0
  401. /package/dist/{chunk-M5CQNOQN.js.map → chunk-O6ZNNVSP.js.map} +0 -0
  402. /package/dist/{chunk-NNBZS3DY.js.map → chunk-OB3XMWX5.js.map} +0 -0
  403. /package/dist/{chunk-SIBVIP2Y.js.map → chunk-PAZY2ZKP.js.map} +0 -0
  404. /package/dist/{chunk-LXESHEBP.js.map → chunk-PX4UMA5Z.js.map} +0 -0
  405. /package/dist/{chunk-NNZFPYYX.js.map → chunk-R7QY5ZVB.js.map} +0 -0
  406. /package/dist/{chunk-WTRTFIIN.js.map → chunk-R7RTXEYG.js.map} +0 -0
  407. /package/dist/{chunk-XRBJ5R3P.js.map → chunk-RBCQVOVJ.js.map} +0 -0
  408. /package/dist/{chunk-WFZNT4KB.js.map → chunk-RC5DXXWC.js.map} +0 -0
  409. /package/dist/{chunk-5QZR2RA3.js.map → chunk-ROBHL3GL.js.map} +0 -0
  410. /package/dist/{chunk-6PST2SFW.js.map → chunk-SCXURCVT.js.map} +0 -0
  411. /package/dist/{chunk-AYG7ML7O.js.map → chunk-SJDQ5RSN.js.map} +0 -0
  412. /package/dist/{chunk-IQXDSKTL.js.map → chunk-SVXJLDDC.js.map} +0 -0
  413. /package/dist/{chunk-SEF4IOFE.js.map → chunk-SWIKABKI.js.map} +0 -0
  414. /package/dist/{chunk-ZJABRLCZ.js.map → chunk-TBXAY2SS.js.map} +0 -0
  415. /package/dist/{chunk-GIC6BASP.js.map → chunk-TNSCIPBQ.js.map} +0 -0
  416. /package/dist/{chunk-ZMDMHSV2.js.map → chunk-TVEONGBU.js.map} +0 -0
  417. /package/dist/{chunk-4FSEZRGK.js.map → chunk-TWF35IC6.js.map} +0 -0
  418. /package/dist/{chunk-LS2SGMQE.js.map → chunk-U6N5IBVY.js.map} +0 -0
  419. /package/dist/{chunk-62YW6OYI.js.map → chunk-UCKYTA2T.js.map} +0 -0
  420. /package/dist/{chunk-YFCHNOGJ.js.map → chunk-UNNPNBR2.js.map} +0 -0
  421. /package/dist/{chunk-Z2M7F4QM.js.map → chunk-VVX5PZFS.js.map} +0 -0
  422. /package/dist/{chunk-NTYLZXDX.js.map → chunk-VYCOJKSX.js.map} +0 -0
  423. /package/dist/{chunk-UICSQESY.js.map → chunk-W24T5YMW.js.map} +0 -0
  424. /package/dist/{chunk-HDQUQBPW.js.map → chunk-W3K3HITK.js.map} +0 -0
  425. /package/dist/{chunk-GDASG7NC.js.map → chunk-W4F3C7N7.js.map} +0 -0
  426. /package/dist/{chunk-YBLZFNIQ.js.map → chunk-WJHGDE7X.js.map} +0 -0
  427. /package/dist/{chunk-4F24PHNX.js.map → chunk-WQZZDN5M.js.map} +0 -0
  428. /package/dist/{chunk-CDZEUCV7.js.map → chunk-X5K5TAQZ.js.map} +0 -0
  429. /package/dist/{chunk-5AUODSOQ.js.map → chunk-XM24CDZX.js.map} +0 -0
  430. /package/dist/{chunk-6VML2LII.js.map → chunk-XOVKXJEP.js.map} +0 -0
  431. /package/dist/{chunk-OU5TIWDQ.js.map → chunk-XSGUMQQQ.js.map} +0 -0
  432. /package/dist/{chunk-7CFVBWDC.js.map → chunk-XUE46UYW.js.map} +0 -0
  433. /package/dist/{chunk-DJORULH3.js.map → chunk-YRLHEEQT.js.map} +0 -0
  434. /package/dist/{chunk-YRWDPE32.js.map → chunk-Z3O53WZR.js.map} +0 -0
  435. /package/dist/{chunk-CSY5DA7O.js.map → chunk-Z6COGHHN.js.map} +0 -0
  436. /package/dist/{chunk-OYR3IPHD.js.map → chunk-ZIW5JVRM.js.map} +0 -0
  437. /package/dist/{graph-edge-decay-CJW4OT2X.js.map → graph-edge-decay-MKIRZ762.js.map} +0 -0
  438. /package/dist/{resolution-U5O4QANY.js.map → resolution-VKATP2HT.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cue-anchors.ts"],"sourcesContent":["import { mkdir, unlink, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { resolveAbstractionNodeStoreDir, validateAbstractionNode, type AbstractionNode } from \"./abstraction-nodes.js\";\nimport { listJsonFilesStrict, readJsonFile, withJsonStoreMutationLock, writeJsonFileAtomic } from \"./json-store.js\";\nimport { compareDeterministicStrings, mergeSortedUniqueStrings } from \"./deterministic-order.js\";\nimport {\n assertIsoRecordedAt,\n assertSafePathSegment,\n assertString,\n isRecord,\n optionalStringArray,\n validateStringRecord,\n} from \"./store-contract.js\";\n\nexport type CueAnchorType = \"entity\" | \"file\" | \"tool\" | \"outcome\" | \"constraint\" | \"date\";\n\nexport interface CueAnchor {\n schemaVersion: 1;\n anchorId: string;\n anchorType: CueAnchorType;\n anchorValue: string;\n normalizedCue: string;\n recordedAt: string;\n sessionKey: string;\n nodeRefs: string[];\n sourceMemoryIdsByNodeRef?: Record<string, string[]>;\n tags?: string[];\n metadata?: Record<string, string>;\n}\n\nexport interface CueAnchorStoreStatus {\n enabled: boolean;\n anchorsEnabled: boolean;\n rootDir: string;\n anchors: {\n total: number;\n valid: number;\n invalid: number;\n byType: Partial<Record<CueAnchorType, number>>;\n totalNodeRefs: number;\n latestAnchorId?: string;\n latestRecordedAt?: string;\n latestSessionKey?: string;\n };\n latestAnchor?: CueAnchor;\n invalidAnchors: Array<{\n path: string;\n error: string;\n }>;\n}\n\nfunction validateAnchorType(raw: unknown): CueAnchorType {\n const value = assertString(raw, \"anchorType\");\n if (![\"entity\", \"file\", \"tool\", \"outcome\", \"constraint\", \"date\"].includes(value)) {\n throw new Error(\"anchorType must be one of entity|file|tool|outcome|constraint|date\");\n }\n return value as CueAnchorType;\n}\n\nfunction validateNodeRefs(raw: unknown): string[] {\n const nodeRefs = optionalStringArray(raw, \"nodeRefs\");\n if (!nodeRefs || nodeRefs.length === 0) {\n throw new Error(\"nodeRefs must contain at least one node reference\");\n }\n return nodeRefs.map((nodeRef, index) => assertSafePathSegment(nodeRef, `nodeRefs[${index}]`));\n}\n\nfunction validateSourceMemoryIdsByNodeRef(raw: unknown): Record<string, string[]> | undefined {\n if (raw === undefined) return undefined;\n if (!isRecord(raw)) throw new Error(\"sourceMemoryIdsByNodeRef must be an object of string arrays\");\n const entries: Array<[string, string[]]> = [];\n for (const [rawNodeRef, rawSourceMemoryIds] of Object.entries(raw)) {\n const nodeRef = assertSafePathSegment(\n assertString(rawNodeRef, \"sourceMemoryIdsByNodeRef key\"),\n \"sourceMemoryIdsByNodeRef.nodeRef\"\n );\n const sourceMemoryIds = optionalStringArray(rawSourceMemoryIds, `sourceMemoryIdsByNodeRef.${nodeRef}`);\n if (sourceMemoryIds) entries.push([nodeRef, mergeSortedUniqueStrings(sourceMemoryIds)]);\n }\n if (entries.length === 0) return undefined;\n return Object.fromEntries(entries.sort(([left], [right]) => compareDeterministicStrings(left, right)));\n}\n\nfunction mergeSourceMemoryIdsByNodeRef(\n existing: Record<string, string[]> | undefined,\n incoming: Record<string, string[]> | undefined\n): Record<string, string[]> | undefined {\n const merged = new Map<string, string[]>();\n for (const [nodeRef, sourceMemoryIds] of Object.entries(existing ?? {})) {\n merged.set(nodeRef, [...sourceMemoryIds]);\n }\n for (const [nodeRef, sourceMemoryIds] of Object.entries(incoming ?? {})) {\n merged.set(nodeRef, mergeSortedUniqueStrings(merged.get(nodeRef), sourceMemoryIds));\n }\n return validateSourceMemoryIdsByNodeRef(Object.fromEntries(merged));\n}\n\nfunction boundSourceMemoryIdsByNodeRef(\n sourceMemoryIdsByNodeRef: Record<string, string[]> | undefined,\n nodeRefs: string[],\n liveNodes?: Map<string, AbstractionNode>\n): Record<string, string[]> | undefined {\n if (!sourceMemoryIdsByNodeRef) return undefined;\n const retained = Object.fromEntries(\n nodeRefs.flatMap((nodeRef) => {\n const sourceMemoryIds = sourceMemoryIdsByNodeRef[nodeRef];\n if (!sourceMemoryIds) return [];\n const liveSourceMemoryIds = liveNodes?.get(nodeRef)?.sourceMemoryIds;\n if (liveNodes && !liveSourceMemoryIds) return [];\n const retainedSourceMemoryIds = mergeSortedUniqueStrings(sourceMemoryIds).filter((sourceMemoryId) =>\n liveSourceMemoryIds ? liveSourceMemoryIds.includes(sourceMemoryId) : true\n );\n return retainedSourceMemoryIds.length > 0 ? [[nodeRef, retainedSourceMemoryIds] as const] : [];\n })\n );\n return validateSourceMemoryIdsByNodeRef(retained);\n}\n\nexport function resolveCueAnchorStoreDir(abstractionNodeStoreDir: string, overrideDir?: string): string {\n if (typeof overrideDir === \"string\" && overrideDir.trim().length > 0) {\n return overrideDir.trim();\n }\n return path.join(abstractionNodeStoreDir, \"anchors\");\n}\n\nexport function validateCueAnchor(raw: unknown): CueAnchor {\n if (!isRecord(raw)) throw new Error(\"cue anchor must be an object\");\n if (raw.schemaVersion !== 1) throw new Error(\"schemaVersion must be 1\");\n\n return {\n schemaVersion: 1,\n anchorId: assertSafePathSegment(assertString(raw.anchorId, \"anchorId\"), \"anchorId\"),\n anchorType: validateAnchorType(raw.anchorType),\n anchorValue: assertString(raw.anchorValue, \"anchorValue\"),\n normalizedCue: assertString(raw.normalizedCue, \"normalizedCue\"),\n recordedAt: assertIsoRecordedAt(assertString(raw.recordedAt, \"recordedAt\")),\n sessionKey: assertString(raw.sessionKey, \"sessionKey\"),\n nodeRefs: validateNodeRefs(raw.nodeRefs),\n sourceMemoryIdsByNodeRef: validateSourceMemoryIdsByNodeRef(raw.sourceMemoryIdsByNodeRef),\n tags: optionalStringArray(raw.tags, \"tags\"),\n metadata: validateStringRecord(raw.metadata, \"metadata\"),\n };\n}\n\nexport async function recordCueAnchor(options: {\n memoryDir: string;\n abstractionNodeStoreDir?: string;\n cueAnchorStoreDir?: string;\n anchor: CueAnchor;\n}): Promise<string> {\n const abstractionNodeStoreDir = options.abstractionNodeStoreDir?.trim().length\n ? options.abstractionNodeStoreDir.trim()\n : path.join(options.memoryDir, \"state\", \"abstraction-nodes\");\n const rootDir = resolveCueAnchorStoreDir(abstractionNodeStoreDir, options.cueAnchorStoreDir);\n const validated = validateCueAnchor(options.anchor);\n const boundedNodeRefs = boundNodeRefs(validated.nodeRefs);\n const bounded = validateCueAnchor({\n ...validated,\n nodeRefs: boundedNodeRefs,\n sourceMemoryIdsByNodeRef: boundSourceMemoryIdsByNodeRef(validated.sourceMemoryIdsByNodeRef, boundedNodeRefs),\n });\n const anchorDir = path.join(rootDir, bounded.anchorType);\n const filePath = path.join(anchorDir, `${bounded.anchorId}.json`);\n await mkdir(anchorDir, { recursive: true });\n await writeFile(filePath, JSON.stringify(bounded, null, 2), \"utf8\");\n return filePath;\n}\n\nfunction mergeSortedValues(existing: string[] | undefined, incoming: string[] | undefined): string[] {\n return mergeSortedUniqueStrings(existing, incoming);\n}\n\nfunction isNotFoundError(error: unknown): boolean {\n return (\n typeof error === \"object\" && error !== null && \"code\" in error && (error as { code?: unknown }).code === \"ENOENT\"\n );\n}\n\nfunction boundNodeRefs(nodeRefs: string[], liveNodes?: Map<string, AbstractionNode>): string[] {\n const uniqueRefs = mergeSortedUniqueStrings(nodeRefs);\n if (!liveNodes) return uniqueRefs.slice(0, 50);\n return uniqueRefs\n .filter((nodeRef) => liveNodes.has(nodeRef))\n .sort(\n (left, right) =>\n Date.parse(liveNodes.get(right)?.recordedAt ?? \"\") - Date.parse(liveNodes.get(left)?.recordedAt ?? \"\") ||\n compareDeterministicStrings(left, right)\n )\n .slice(0, 50);\n}\n\nasync function readLiveNodes(nodesDir: string): Promise<Map<string, AbstractionNode> | undefined> {\n const liveNodes = new Map<string, AbstractionNode>();\n let nodeFiles: string[];\n try {\n nodeFiles = await listJsonFilesStrict(nodesDir);\n } catch (error) {\n if (isNotFoundError(error)) return undefined;\n throw error;\n }\n for (const filePath of nodeFiles) {\n const node = validateAbstractionNode(await readJsonFile(filePath));\n const previous = liveNodes.get(node.nodeId);\n if (\n !previous ||\n Date.parse(previous.recordedAt) < Date.parse(node.recordedAt) ||\n (Date.parse(previous.recordedAt) === Date.parse(node.recordedAt) &&\n compareDeterministicStrings(previous.sessionKey, node.sessionKey) < 0)\n ) {\n liveNodes.set(node.nodeId, node);\n }\n }\n return liveNodes;\n}\n\nexport async function upsertCueAnchors(options: {\n memoryDir: string;\n abstractionNodeStoreDir?: string;\n cueAnchorStoreDir?: string;\n anchors: CueAnchor[];\n}): Promise<string[]> {\n const abstractionNodeStoreDir = resolveAbstractionNodeStoreDir(options.memoryDir, options.abstractionNodeStoreDir);\n const incomingAnchors = options.anchors.map(validateCueAnchor);\n if (incomingAnchors.length === 0) return [];\n\n return withJsonStoreMutationLock(abstractionNodeStoreDir, async () => {\n const rootDir = resolveCueAnchorStoreDir(abstractionNodeStoreDir, options.cueAnchorStoreDir);\n const liveNodes = await readLiveNodes(path.join(abstractionNodeStoreDir, \"nodes\"));\n const incomingByKey = new Map<string, CueAnchor[]>();\n for (const anchor of incomingAnchors) {\n const key = `${anchor.anchorType}\\u0000${anchor.anchorId}`;\n const grouped = incomingByKey.get(key) ?? [];\n grouped.push(anchor);\n incomingByKey.set(key, grouped);\n }\n const filePaths: string[] = [];\n for (const key of [...incomingByKey.keys()].sort(compareDeterministicStrings)) {\n const grouped = incomingByKey.get(key) ?? [];\n grouped.sort(compareIncomingCueAnchors);\n const incoming = grouped.shift();\n if (!incoming) throw new Error(`cue anchor batch has no anchor: ${key}`);\n const filePath = path.join(rootDir, incoming.anchorType, `${incoming.anchorId}.json`);\n let existing: CueAnchor | undefined;\n try {\n existing = validateCueAnchor(await readJsonFile(filePath));\n } catch (error) {\n if (!isNotFoundError(error)) throw error;\n }\n let merged = mergeCueAnchors(existing, incoming, liveNodes);\n for (const next of grouped) merged = mergeCueAnchors(merged, next, liveNodes);\n await writeJsonFileAtomic(filePath, merged);\n filePaths.push(filePath);\n }\n return filePaths;\n });\n}\n\nfunction compareIncomingCueAnchors(left: CueAnchor, right: CueAnchor): number {\n const recordedAtComparison = Date.parse(left.recordedAt) - Date.parse(right.recordedAt);\n if (recordedAtComparison < 0) return -1;\n if (recordedAtComparison > 0) return 1;\n return compareDeterministicStrings(canonicalCueAnchorKey(left), canonicalCueAnchorKey(right));\n}\n\nfunction canonicalMetadata(metadata: Record<string, string> | undefined): Record<string, string> {\n return Object.fromEntries(\n Object.entries(metadata ?? {}).sort(([left], [right]) => compareDeterministicStrings(left, right))\n );\n}\n\nfunction canonicalCueAnchorKey(anchor: CueAnchor): string {\n return JSON.stringify({\n ...anchor,\n metadata: canonicalMetadata(anchor.metadata),\n });\n}\n\nfunction mergeCueAnchors(\n existing: CueAnchor | undefined,\n incoming: CueAnchor,\n liveNodes: Map<string, AbstractionNode> | undefined\n): CueAnchor {\n const incomingIsNewest = !existing || Date.parse(existing.recordedAt) <= Date.parse(incoming.recordedAt);\n const newest = incomingIsNewest ? incoming : existing;\n const older = incomingIsNewest ? existing : incoming;\n const mergedMetadata = canonicalMetadata({\n ...(older?.metadata ?? {}),\n ...(newest.metadata ?? {}),\n });\n const nodeRefs = boundNodeRefs(mergeSortedValues(existing?.nodeRefs, incoming.nodeRefs), liveNodes);\n return validateCueAnchor({\n ...newest,\n nodeRefs,\n sourceMemoryIdsByNodeRef: boundSourceMemoryIdsByNodeRef(\n mergeSourceMemoryIdsByNodeRef(existing?.sourceMemoryIdsByNodeRef, incoming.sourceMemoryIdsByNodeRef),\n nodeRefs,\n liveNodes\n ),\n tags: mergeSortedValues(existing?.tags, incoming.tags),\n metadata: mergedMetadata,\n });\n}\n\nexport async function upsertCueAnchor(options: {\n memoryDir: string;\n abstractionNodeStoreDir?: string;\n cueAnchorStoreDir?: string;\n anchor: CueAnchor;\n}): Promise<string> {\n const [filePath] = await upsertCueAnchors({ ...options, anchors: [options.anchor] });\n if (!filePath) throw new Error(\"cue anchor upsert did not write a file\");\n return filePath;\n}\n\nexport async function pruneOrphanCueAnchors(options: {\n memoryDir: string;\n abstractionNodeStoreDir?: string;\n cueAnchorStoreDir?: string;\n}): Promise<number> {\n const abstractionNodeStoreDir = resolveAbstractionNodeStoreDir(options.memoryDir, options.abstractionNodeStoreDir);\n return withJsonStoreMutationLock(abstractionNodeStoreDir, async () => {\n const cueAnchorStoreDir = resolveCueAnchorStoreDir(abstractionNodeStoreDir, options.cueAnchorStoreDir);\n const liveNodes = (await readLiveNodes(path.join(abstractionNodeStoreDir, \"nodes\"))) ?? new Map();\n let removed = 0;\n const anchorFiles = await listJsonFilesStrict(cueAnchorStoreDir, {\n allowMissingDirectory: true,\n });\n for (const filePath of anchorFiles) {\n let anchor: CueAnchor;\n try {\n anchor = validateCueAnchor(await readJsonFile(filePath));\n } catch {\n continue;\n }\n const nodeRefs = boundNodeRefs(anchor.nodeRefs, liveNodes);\n const sourceMemoryIdsByNodeRef = boundSourceMemoryIdsByNodeRef(\n anchor.sourceMemoryIdsByNodeRef,\n nodeRefs,\n liveNodes\n );\n if (nodeRefs.length === 0) {\n try {\n await unlink(filePath);\n removed++;\n } catch (error) {\n if (!isNotFoundError(error)) throw error;\n }\n continue;\n }\n if (\n nodeRefs.length !== anchor.nodeRefs.length ||\n nodeRefs.some((nodeRef, index) => nodeRef !== anchor.nodeRefs[index]) ||\n JSON.stringify(sourceMemoryIdsByNodeRef) !== JSON.stringify(anchor.sourceMemoryIdsByNodeRef)\n ) {\n await writeJsonFileAtomic(filePath, validateCueAnchor({ ...anchor, nodeRefs, sourceMemoryIdsByNodeRef }));\n }\n }\n return removed;\n });\n}\n\nexport async function getCueAnchorStoreStatus(options: {\n memoryDir: string;\n abstractionNodeStoreDir?: string;\n cueAnchorStoreDir?: string;\n enabled: boolean;\n anchorsEnabled: boolean;\n}): Promise<CueAnchorStoreStatus> {\n const abstractionNodeStoreDir = options.abstractionNodeStoreDir?.trim().length\n ? options.abstractionNodeStoreDir.trim()\n : path.join(options.memoryDir, \"state\", \"abstraction-nodes\");\n const rootDir = resolveCueAnchorStoreDir(abstractionNodeStoreDir, options.cueAnchorStoreDir);\n const files = await listJsonFilesStrict(rootDir, { allowMissingDirectory: true });\n const anchors: CueAnchor[] = [];\n const invalidAnchors: Array<{ path: string; error: string }> = [];\n\n for (const filePath of files) {\n try {\n anchors.push(validateCueAnchor(await readJsonFile(filePath)));\n } catch (error) {\n invalidAnchors.push({\n path: filePath,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n anchors.sort(\n (a, b) => Date.parse(b.recordedAt) - Date.parse(a.recordedAt) || compareDeterministicStrings(a.anchorId, b.anchorId)\n );\n\n const byType: Partial<Record<CueAnchorType, number>> = {};\n let totalNodeRefs = 0;\n for (const anchor of anchors) {\n byType[anchor.anchorType] = (byType[anchor.anchorType] ?? 0) + 1;\n totalNodeRefs += anchor.nodeRefs.length;\n }\n\n return {\n enabled: options.enabled,\n anchorsEnabled: options.anchorsEnabled,\n rootDir,\n anchors: {\n total: files.length,\n valid: anchors.length,\n invalid: invalidAnchors.length,\n byType,\n totalNodeRefs,\n latestAnchorId: anchors[0]?.anchorId,\n latestRecordedAt: anchors[0]?.recordedAt,\n latestSessionKey: anchors[0]?.sessionKey,\n },\n latestAnchor: anchors[0],\n invalidAnchors,\n };\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/offline-sync-file-io.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { createReadStream } from \"node:fs\";\nimport { open } from \"node:fs/promises\";\nimport { MAGIC_HEADER_SIZE, isEncryptedFile } from \"./secure-store/secure-fs.js\";\n\nexport interface OfflineSyncFileTarget {\n root: string;\n path: string;\n filePath: string;\n}\n\nexport type OfflineSyncExcludeFile = (target: OfflineSyncFileTarget) => boolean | Promise<boolean>;\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) throw new Error(\"offline sync request aborted\");\n}\n\nexport async function shouldExcludeOfflineSyncFile(\n excludeFile: OfflineSyncExcludeFile | undefined,\n target: OfflineSyncFileTarget\n): Promise<boolean> {\n return excludeFile ? await excludeFile(target) : false;\n}\n\nexport async function sha256OfflineSyncFile(\n filePath: string,\n signal?: AbortSignal\n): Promise<{ sha256: string; bytes: number }> {\n const hash = createHash(\"sha256\");\n let bytes = 0;\n for await (const chunk of createReadStream(filePath)) {\n throwIfAborted(signal);\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n hash.update(buffer);\n bytes += buffer.length;\n }\n throwIfAborted(signal);\n return { sha256: hash.digest(\"hex\"), bytes };\n}\n\nexport async function isEncryptedOfflineSyncFile(filePath: string): Promise<boolean> {\n const handle = await open(filePath, \"r\");\n try {\n const header = Buffer.alloc(MAGIC_HEADER_SIZE);\n const { bytesRead } = await handle.read(header, 0, header.length, 0);\n return bytesRead >= MAGIC_HEADER_SIZE && isEncryptedFile(header);\n } finally {\n await handle.close();\n }\n}\n\nexport async function readPlainOfflineSyncFileChunk(options: {\n filePath: string;\n offset: number;\n length: number;\n bytes: number;\n}): Promise<Buffer> {\n const chunkBytes = Math.min(options.length, options.bytes - options.offset);\n const chunk = Buffer.alloc(chunkBytes);\n if (chunkBytes === 0) return chunk;\n const handle = await open(options.filePath, \"r\");\n try {\n const { bytesRead } = await handle.read(chunk, 0, chunk.length, options.offset);\n return bytesRead === chunk.length ? chunk : chunk.subarray(0, bytesRead);\n } finally {\n await handle.close();\n }\n}\n\n/** Streamed whole-file sha256 for plain-file chunk reads — the value the\n * file-content response contract exposes as x-remnic-file-sha256. Deliberately\n * UNCACHED: identity keys like (path, size, mtimeMs) are spoofable (a rewrite\n * that preserves size and mtime would serve a stale digest, defeating the\n * uploader's verify-before-idempotent-skip check). One bounded-memory hash\n * pass per chunk request; content reads stay windowed. */\nexport async function plainFileDigest(filePath: string): Promise<string> {\n const hash = createHash(\"sha256\");\n for await (const piece of createReadStream(filePath)) {\n hash.update(piece as Buffer);\n }\n return hash.digest(\"hex\");\n}\n"],"mappings":";;;;;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,wBAAwB;AACjC,SAAS,YAAY;AAWrB,SAAS,eAAe,QAAuC;AAC7D,MAAI,QAAQ,QAAS,OAAM,IAAI,MAAM,8BAA8B;AACrE;AAEA,eAAsB,6BACpB,aACA,QACkB;AAClB,SAAO,cAAc,MAAM,YAAY,MAAM,IAAI;AACnD;AAEA,eAAsB,sBACpB,UACA,QAC4C;AAC5C,QAAM,OAAO,WAAW,QAAQ;AAChC,MAAI,QAAQ;AACZ,mBAAiB,SAAS,iBAAiB,QAAQ,GAAG;AACpD,mBAAe,MAAM;AACrB,UAAM,SAAS,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK;AACjE,SAAK,OAAO,MAAM;AAClB,aAAS,OAAO;AAAA,EAClB;AACA,iBAAe,MAAM;AACrB,SAAO,EAAE,QAAQ,KAAK,OAAO,KAAK,GAAG,MAAM;AAC7C;AAEA,eAAsB,2BAA2B,UAAoC;AACnF,QAAM,SAAS,MAAM,KAAK,UAAU,GAAG;AACvC,MAAI;AACF,UAAM,SAAS,OAAO,MAAM,iBAAiB;AAC7C,UAAM,EAAE,UAAU,IAAI,MAAM,OAAO,KAAK,QAAQ,GAAG,OAAO,QAAQ,CAAC;AACnE,WAAO,aAAa,qBAAqB,gBAAgB,MAAM;AAAA,EACjE,UAAE;AACA,UAAM,OAAO,MAAM;AAAA,EACrB;AACF;AAEA,eAAsB,8BAA8B,SAKhC;AAClB,QAAM,aAAa,KAAK,IAAI,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,MAAM;AAC1E,QAAM,QAAQ,OAAO,MAAM,UAAU;AACrC,MAAI,eAAe,EAAG,QAAO;AAC7B,QAAM,SAAS,MAAM,KAAK,QAAQ,UAAU,GAAG;AAC/C,MAAI;AACF,UAAM,EAAE,UAAU,IAAI,MAAM,OAAO,KAAK,OAAO,GAAG,MAAM,QAAQ,QAAQ,MAAM;AAC9E,WAAO,cAAc,MAAM,SAAS,QAAQ,MAAM,SAAS,GAAG,SAAS;AAAA,EACzE,UAAE;AACA,UAAM,OAAO,MAAM;AAAA,EACrB;AACF;AAQA,eAAsB,gBAAgB,UAAmC;AACvE,QAAM,OAAO,WAAW,QAAQ;AAChC,mBAAiB,SAAS,iBAAiB,QAAQ,GAAG;AACpD,SAAK,OAAO,KAAe;AAAA,EAC7B;AACA,SAAO,KAAK,OAAO,KAAK;AAC1B;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/abstraction-nodes.ts"],"sourcesContent":["import { mkdir, unlink, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { listJsonFilesStrict, readJsonFile, withJsonStoreMutationLock, writeJsonFileAtomic } from \"./json-store.js\";\nimport { compareDeterministicStrings, mergeSortedUniqueStrings } from \"./deterministic-order.js\";\nimport {\n assertIsoRecordedAt,\n assertSafePathSegment,\n assertString,\n isRecord,\n optionalStringArray,\n recordStoreDay,\n validateStringRecord,\n} from \"./store-contract.js\";\n\nfunction isNotFoundError(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\";\n}\n\nexport type AbstractionNodeKind = \"episode\" | \"topic\" | \"project\" | \"workflow\" | \"constraint\";\nexport type AbstractionLevel = \"micro\" | \"meso\" | \"macro\";\n\nexport interface AbstractionNode {\n schemaVersion: 1;\n nodeId: string;\n recordedAt: string;\n sessionKey: string;\n kind: AbstractionNodeKind;\n abstractionLevel: AbstractionLevel;\n title: string;\n summary: string;\n sourceMemoryIds?: string[];\n entityRefs?: string[];\n tags?: string[];\n metadata?: Record<string, string>;\n}\n\nexport interface AbstractionNodeStoreStatus {\n enabled: boolean;\n anchorsEnabled: boolean;\n rootDir: string;\n nodesDir: string;\n nodes: {\n total: number;\n valid: number;\n invalid: number;\n byKind: Partial<Record<AbstractionNodeKind, number>>;\n byLevel: Partial<Record<AbstractionLevel, number>>;\n latestNodeId?: string;\n latestRecordedAt?: string;\n latestSessionKey?: string;\n };\n latestNode?: AbstractionNode;\n invalidNodes: Array<{\n path: string;\n error: string;\n }>;\n}\n\nfunction validateKind(raw: unknown): AbstractionNodeKind {\n const value = assertString(raw, \"kind\");\n if (![\"episode\", \"topic\", \"project\", \"workflow\", \"constraint\"].includes(value)) {\n throw new Error(\"kind must be one of episode|topic|project|workflow|constraint\");\n }\n return value as AbstractionNodeKind;\n}\n\nfunction validateLevel(raw: unknown): AbstractionLevel {\n const value = assertString(raw, \"abstractionLevel\");\n if (![\"micro\", \"meso\", \"macro\"].includes(value)) {\n throw new Error(\"abstractionLevel must be one of micro|meso|macro\");\n }\n return value as AbstractionLevel;\n}\n\nexport function resolveAbstractionNodeStoreDir(memoryDir: string, overrideDir?: string): string {\n if (typeof overrideDir === \"string\" && overrideDir.trim().length > 0) {\n return overrideDir.trim();\n }\n return path.join(memoryDir, \"state\", \"abstraction-nodes\");\n}\n\nexport function validateAbstractionNode(raw: unknown): AbstractionNode {\n if (!isRecord(raw)) throw new Error(\"abstraction node must be an object\");\n if (raw.schemaVersion !== 1) throw new Error(\"schemaVersion must be 1\");\n\n return {\n schemaVersion: 1,\n nodeId: assertSafePathSegment(assertString(raw.nodeId, \"nodeId\"), \"nodeId\"),\n recordedAt: assertIsoRecordedAt(assertString(raw.recordedAt, \"recordedAt\")),\n sessionKey: assertString(raw.sessionKey, \"sessionKey\"),\n kind: validateKind(raw.kind),\n abstractionLevel: validateLevel(raw.abstractionLevel),\n title: assertString(raw.title, \"title\"),\n summary: assertString(raw.summary, \"summary\"),\n sourceMemoryIds: optionalStringArray(raw.sourceMemoryIds, \"sourceMemoryIds\"),\n entityRefs: optionalStringArray(raw.entityRefs, \"entityRefs\"),\n tags: optionalStringArray(raw.tags, \"tags\"),\n metadata: validateStringRecord(raw.metadata, \"metadata\"),\n };\n}\n\nexport async function recordAbstractionNode(options: {\n memoryDir: string;\n abstractionNodeStoreDir?: string;\n node: AbstractionNode;\n}): Promise<string> {\n const rootDir = resolveAbstractionNodeStoreDir(options.memoryDir, options.abstractionNodeStoreDir);\n const validated = validateAbstractionNode(options.node);\n const day = recordStoreDay(validated.recordedAt);\n const nodesDir = path.join(rootDir, \"nodes\", day);\n const filePath = path.join(nodesDir, `${validated.nodeId}.json`);\n await mkdir(nodesDir, { recursive: true });\n await writeFile(filePath, JSON.stringify(validated, null, 2), \"utf8\");\n return filePath;\n}\n\nconst MAX_ABSTRACTION_NODE_VALUES = 50;\n\nfunction mergeSortedValues(existing: string[] | undefined, incoming: string[] | undefined): string[] {\n return mergeSortedUniqueStrings(existing, incoming).slice(0, MAX_ABSTRACTION_NODE_VALUES);\n}\n\nexport const HARMONIC_SOURCE_MEMORY_INSERTED_AT_KEY = \"remnic.harmonic.sourceMemoryInsertedAt.v1\";\n\nfunction sourceMemoryInsertedAt(node: AbstractionNode | undefined): Map<string, string> {\n const insertedAtById = new Map<string, string>();\n if (!node) return insertedAtById;\n let stored: Record<string, unknown> = {};\n try {\n const parsed = JSON.parse(node.metadata?.[HARMONIC_SOURCE_MEMORY_INSERTED_AT_KEY] ?? \"{}\") as unknown;\n stored = isRecord(parsed) ? parsed : {};\n } catch {\n stored = {};\n }\n for (const memoryId of node.sourceMemoryIds ?? []) {\n const insertedAt = stored[memoryId];\n insertedAtById.set(\n memoryId,\n typeof insertedAt === \"string\" && Number.isFinite(Date.parse(insertedAt)) ? insertedAt : node.recordedAt\n );\n }\n return insertedAtById;\n}\n\nfunction mergeRecentSourceMemoryIds(\n existing: AbstractionNode | undefined,\n incoming: AbstractionNode\n): { ids: string[]; insertedAtJson: string } {\n const insertedAtById = sourceMemoryInsertedAt(existing);\n const incomingSources = [...sourceMemoryInsertedAt(incoming).entries()].sort(\n ([leftId, leftAt], [rightId, rightAt]) =>\n Date.parse(leftAt) - Date.parse(rightAt) || compareDeterministicStrings(leftId, rightId)\n );\n let nextInsertedAtMs = Math.max(\n Date.now(),\n [...insertedAtById.values()].reduce((latest, insertedAt) => Math.max(latest, Date.parse(insertedAt) + 1), 0)\n );\n for (const [memoryId] of incomingSources) {\n if (insertedAtById.has(memoryId)) continue;\n insertedAtById.set(memoryId, new Date(nextInsertedAtMs).toISOString());\n nextInsertedAtMs++;\n }\n const retained = [...insertedAtById.entries()]\n .sort(\n ([leftId, leftAt], [rightId, rightAt]) =>\n Date.parse(rightAt) - Date.parse(leftAt) || compareDeterministicStrings(leftId, rightId)\n )\n .slice(0, MAX_ABSTRACTION_NODE_VALUES);\n const ids = retained.map(([memoryId]) => memoryId).sort(compareDeterministicStrings);\n const retainedInsertedAt = Object.fromEntries(ids.map((memoryId) => [memoryId, insertedAtById.get(memoryId)]));\n return { ids, insertedAtJson: JSON.stringify(retainedInsertedAt) };\n}\n\ntype AbstractionNodeFile = {\n filePath: string;\n node: AbstractionNode;\n};\n\nfunction compareNodeFiles(left: AbstractionNodeFile, right: AbstractionNodeFile): number {\n return (\n Date.parse(right.node.recordedAt) - Date.parse(left.node.recordedAt) ||\n compareDeterministicStrings(left.filePath, right.filePath)\n );\n}\n\nfunction compareIncomingNodes(left: AbstractionNode, right: AbstractionNode): number {\n return (\n Date.parse(left.recordedAt) - Date.parse(right.recordedAt) ||\n compareDeterministicStrings(canonicalNodeKey(left), canonicalNodeKey(right))\n );\n}\n\nfunction canonicalMetadata(metadata: Record<string, string> | undefined): Record<string, string> {\n return Object.fromEntries(\n Object.entries(metadata ?? {}).sort(([left], [right]) => compareDeterministicStrings(left, right))\n );\n}\n\nfunction canonicalNodeKey(node: AbstractionNode): string {\n return JSON.stringify({\n ...node,\n metadata: canonicalMetadata(node.metadata),\n });\n}\n\nfunction mergeAbstractionNodes(existing: AbstractionNode | undefined, incoming: AbstractionNode): AbstractionNode {\n const incomingIsNewest = !existing || Date.parse(existing.recordedAt) <= Date.parse(incoming.recordedAt);\n const newest = incomingIsNewest ? incoming : existing;\n const older = incomingIsNewest ? existing : incoming;\n if (!newest) throw new Error(\"abstraction node merge requires a node\");\n const retainedSources = mergeRecentSourceMemoryIds(existing, incoming);\n const mergedMetadata = canonicalMetadata({\n ...(older?.metadata ?? {}),\n ...(newest.metadata ?? {}),\n [HARMONIC_SOURCE_MEMORY_INSERTED_AT_KEY]: retainedSources.insertedAtJson,\n });\n return validateAbstractionNode({\n ...newest,\n sourceMemoryIds: retainedSources.ids,\n entityRefs: mergeSortedValues(existing?.entityRefs, incoming.entityRefs),\n tags: mergeSortedValues(existing?.tags, incoming.tags),\n metadata: mergedMetadata,\n });\n}\n\nexport async function upsertAbstractionNodes(options: {\n memoryDir: string;\n abstractionNodeStoreDir?: string;\n nodes: AbstractionNode[];\n}): Promise<string[]> {\n const rootDir = resolveAbstractionNodeStoreDir(options.memoryDir, options.abstractionNodeStoreDir);\n const incomingNodes = options.nodes.map(validateAbstractionNode);\n if (incomingNodes.length === 0) return [];\n return withJsonStoreMutationLock(rootDir, async () => {\n const nodesDir = path.join(rootDir, \"nodes\");\n const nodeFiles = await listJsonFilesStrict(nodesDir, { allowMissingDirectory: true });\n const existingNodes = await Promise.all(\n nodeFiles.map(async (filePath) => ({\n filePath,\n node: validateAbstractionNode(await readJsonFile(filePath)),\n }))\n );\n const existingById = new Map<string, AbstractionNodeFile[]>();\n for (const existing of existingNodes) {\n const records = existingById.get(existing.node.nodeId) ?? [];\n records.push(existing);\n existingById.set(existing.node.nodeId, records);\n }\n const incomingById = new Map<string, AbstractionNode[]>();\n for (const incoming of incomingNodes) {\n const records = incomingById.get(incoming.nodeId) ?? [];\n records.push(incoming);\n incomingById.set(incoming.nodeId, records);\n }\n\n const filePaths: string[] = [];\n for (const nodeId of [...incomingById.keys()].sort(compareDeterministicStrings)) {\n const existing = (existingById.get(nodeId) ?? []).sort(compareNodeFiles);\n const incoming = (incomingById.get(nodeId) ?? []).sort(compareIncomingNodes);\n let merged: AbstractionNode | undefined;\n for (const next of [...existing].reverse()) merged = mergeAbstractionNodes(merged, next.node);\n for (const next of incoming) merged = mergeAbstractionNodes(merged, next);\n if (!merged) throw new Error(`abstraction node batch has no node: ${nodeId}`);\n const filePath =\n existing[0]?.filePath ?? path.join(nodesDir, recordStoreDay(merged.recordedAt), `${merged.nodeId}.json`);\n await writeJsonFileAtomic(filePath, merged);\n for (const duplicate of existing.slice(1)) {\n await unlink(duplicate.filePath).catch((error) => {\n if (!isNotFoundError(error)) throw error;\n });\n }\n filePaths.push(filePath);\n }\n return filePaths;\n });\n}\n\nexport async function upsertAbstractionNode(options: {\n memoryDir: string;\n abstractionNodeStoreDir?: string;\n node: AbstractionNode;\n}): Promise<string> {\n const [filePath] = await upsertAbstractionNodes({ ...options, nodes: [options.node] });\n if (!filePath) throw new Error(\"abstraction node upsert did not write a file\");\n return filePath;\n}\n\nexport async function getAbstractionNodeStoreStatus(options: {\n memoryDir: string;\n abstractionNodeStoreDir?: string;\n enabled: boolean;\n anchorsEnabled: boolean;\n}): Promise<AbstractionNodeStoreStatus> {\n const rootDir = resolveAbstractionNodeStoreDir(options.memoryDir, options.abstractionNodeStoreDir);\n const nodesDir = path.join(rootDir, \"nodes\");\n const files = await listJsonFilesStrict(nodesDir, { allowMissingDirectory: true });\n const nodes: AbstractionNode[] = [];\n const invalidNodes: Array<{ path: string; error: string }> = [];\n\n for (const filePath of files) {\n try {\n nodes.push(validateAbstractionNode(await readJsonFile(filePath)));\n } catch (error) {\n invalidNodes.push({\n path: filePath,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n nodes.sort(\n (a, b) => Date.parse(b.recordedAt) - Date.parse(a.recordedAt) || compareDeterministicStrings(a.nodeId, b.nodeId)\n );\n\n const byKind: Partial<Record<AbstractionNodeKind, number>> = {};\n const byLevel: Partial<Record<AbstractionLevel, number>> = {};\n for (const node of nodes) {\n byKind[node.kind] = (byKind[node.kind] ?? 0) + 1;\n byLevel[node.abstractionLevel] = (byLevel[node.abstractionLevel] ?? 0) + 1;\n }\n\n return {\n enabled: options.enabled,\n anchorsEnabled: options.anchorsEnabled,\n rootDir,\n nodesDir,\n nodes: {\n total: files.length,\n valid: nodes.length,\n invalid: invalidNodes.length,\n byKind,\n byLevel,\n latestNodeId: nodes[0]?.nodeId,\n latestRecordedAt: nodes[0]?.recordedAt,\n latestSessionKey: nodes[0]?.sessionKey,\n },\n latestNode: nodes[0],\n invalidNodes,\n };\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/live-connectors-runner.ts"],"sourcesContent":["import {\n runConnectorPollOnce,\n type ConnectorRunResult,\n} from \"./connectors-cli.js\";\nimport {\n createGitHubConnector,\n createGmailConnector,\n createGoogleDriveConnector,\n createNotionConnector,\n GITHUB_CONNECTOR_ID,\n GITHUB_DEFAULT_POLL_INTERVAL_MS,\n GMAIL_CONNECTOR_ID,\n GMAIL_DEFAULT_POLL_INTERVAL_MS,\n GOOGLE_DRIVE_CONNECTOR_ID,\n GOOGLE_DRIVE_DEFAULT_POLL_INTERVAL_MS,\n NOTION_CONNECTOR_ID,\n NOTION_DEFAULT_POLL_INTERVAL_MS,\n ConnectorStateLockLostError,\n readConnectorState,\n withConnectorStateLock,\n writeConnectorState,\n validateGitHubConfig,\n validateGmailConfig,\n validateGoogleDriveConfig,\n validateNotionConfig,\n type ConnectorConfig,\n type ConnectorCursor,\n type ConnectorDocument,\n type ConnectorState,\n type LiveConnector,\n} from \"./connectors/live/index.js\";\nimport type { LiveConnectorsConfig } from \"./types.js\";\n\nexport type LiveConnectorSkipReason =\n | \"disabled\"\n | \"not_due\"\n | \"invalid_config\"\n | \"state_read_error\"\n | \"connector_error\";\n\nexport interface LiveConnectorRunItem {\n id: string;\n displayName: string;\n enabled: boolean;\n ran: boolean;\n skippedReason?: LiveConnectorSkipReason;\n docsImported: number;\n error?: string;\n stateWriteError?: string;\n lastSyncAt: string | null;\n nextDueAt: string | null;\n}\n\nexport interface LiveConnectorsRunSummary {\n ranAt: string;\n force: boolean;\n totalDocsImported: number;\n ranCount: number;\n skippedCount: number;\n errorCount: number;\n results: LiveConnectorRunItem[];\n}\n\nexport interface LiveConnectorDefinition {\n id: string;\n displayName: string;\n enabled: boolean;\n pollIntervalMs: number;\n rawConfig: unknown;\n createConnector: () => LiveConnector;\n validateConfig: (raw: unknown) => ConnectorConfig;\n}\n\ntype LiveConnectorsNow = Date | (() => Date);\n\nexport function builtInLiveConnectorDefinitions(\n config: LiveConnectorsConfig,\n): LiveConnectorDefinition[] {\n return [\n {\n id: GOOGLE_DRIVE_CONNECTOR_ID,\n displayName: \"Google Drive\",\n enabled: config.googleDrive.enabled,\n pollIntervalMs:\n config.googleDrive.pollIntervalMs ?? GOOGLE_DRIVE_DEFAULT_POLL_INTERVAL_MS,\n rawConfig: config.googleDrive,\n createConnector: createGoogleDriveConnector,\n validateConfig: (raw) =>\n validateGoogleDriveConfig(raw) as unknown as ConnectorConfig,\n },\n {\n id: NOTION_CONNECTOR_ID,\n displayName: \"Notion\",\n enabled: config.notion.enabled,\n pollIntervalMs: config.notion.pollIntervalMs ?? NOTION_DEFAULT_POLL_INTERVAL_MS,\n rawConfig: config.notion,\n createConnector: createNotionConnector,\n validateConfig: (raw) =>\n validateNotionConfig(raw) as unknown as ConnectorConfig,\n },\n {\n id: GMAIL_CONNECTOR_ID,\n displayName: \"Gmail\",\n enabled: config.gmail.enabled,\n pollIntervalMs: config.gmail.pollIntervalMs ?? GMAIL_DEFAULT_POLL_INTERVAL_MS,\n rawConfig: config.gmail,\n createConnector: createGmailConnector,\n validateConfig: (raw) => validateGmailConfig(raw) as unknown as ConnectorConfig,\n },\n {\n id: GITHUB_CONNECTOR_ID,\n displayName: \"GitHub\",\n enabled: config.github.enabled,\n pollIntervalMs:\n config.github.pollIntervalMs ?? GITHUB_DEFAULT_POLL_INTERVAL_MS,\n rawConfig: config.github,\n createConnector: createGitHubConnector,\n validateConfig: (raw) => validateGitHubConfig(raw) as unknown as ConnectorConfig,\n },\n ];\n}\n\nexport function hasEnabledLiveConnector(config: LiveConnectorsConfig): boolean {\n return (\n config.googleDrive.enabled ||\n config.notion.enabled ||\n config.gmail.enabled ||\n config.github.enabled\n );\n}\n\nexport async function runLiveConnectorsOnce(options: {\n memoryDir: string;\n connectors: LiveConnectorsConfig;\n ingestDocuments: (docs: ConnectorDocument[]) => Promise<void>;\n force?: boolean;\n now?: LiveConnectorsNow;\n abortSignal?: AbortSignal;\n definitions?: LiveConnectorDefinition[];\n}): Promise<LiveConnectorsRunSummary> {\n const ranAt = resolveNow(options.now);\n const force = options.force === true;\n const definitions =\n options.definitions ?? builtInLiveConnectorDefinitions(options.connectors);\n const results: LiveConnectorRunItem[] = [];\n\n for (const definition of definitions) {\n const checkAt = resolveNow(options.now);\n if (!definition.enabled) {\n results.push(skipResult(definition, null, \"disabled\"));\n continue;\n }\n let state: ConnectorState | null;\n try {\n state = await readConnectorState(options.memoryDir, definition.id);\n } catch (err) {\n results.push({\n id: definition.id,\n displayName: definition.displayName,\n enabled: true,\n ran: false,\n skippedReason: \"state_read_error\",\n docsImported: 0,\n error: err instanceof Error ? err.message : String(err),\n lastSyncAt: null,\n nextDueAt: null,\n });\n continue;\n }\n if (!force && !isConnectorDue(state, definition.pollIntervalMs, checkAt)) {\n results.push(skipResult(definition, state, \"not_due\"));\n continue;\n }\n\n let validatedConfig: ConnectorConfig;\n try {\n validatedConfig = definition.validateConfig(definition.rawConfig);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n let stateWriteError: string | undefined;\n let writtenErrorState: ConnectorState | undefined;\n const errorAt = resolveNow(options.now);\n try {\n writtenErrorState = await writeConnectorErrorState({\n memoryDir: options.memoryDir,\n connectorId: definition.id,\n state,\n error: message,\n now: errorAt,\n });\n } catch (writeErr) {\n stateWriteError =\n writeErr instanceof Error ? writeErr.message : String(writeErr);\n }\n const reportedState = writtenErrorState ?? state;\n results.push({\n id: definition.id,\n displayName: definition.displayName,\n enabled: true,\n ran: false,\n skippedReason: \"invalid_config\",\n docsImported: 0,\n error: message,\n ...(stateWriteError !== undefined ? { stateWriteError } : {}),\n lastSyncAt: reportedState?.lastSyncAt ?? null,\n nextDueAt: nextDueAt(reportedState, definition.pollIntervalMs),\n });\n continue;\n }\n\n let runResult: ConnectorRunResult;\n let lastStateWrittenAt: Date | undefined;\n try {\n const connector = definition.createConnector();\n runResult = await withConnectorStateLock(options.memoryDir, definition.id, async (lockSignal) => {\n const pollAbortSignal = combineAbortSignals(options.abortSignal, lockSignal);\n const lockedState = await readConnectorState(options.memoryDir, definition.id);\n if (!force && !isConnectorDue(lockedState, definition.pollIntervalMs, checkAt)) {\n return { docsImported: 0 };\n }\n state = lockedState;\n return runConnectorPollOnce({\n connectorId: definition.id,\n priorState: lockedState,\n syncFn: (cursor: ConnectorCursor | null) =>\n connector.syncIncremental({\n cursor,\n config: validatedConfig,\n abortSignal: pollAbortSignal,\n }),\n ingestFn: async (docs) => {\n throwIfAborted(pollAbortSignal);\n await options.ingestDocuments(docs);\n throwIfAborted(pollAbortSignal);\n },\n writeCursorFn: (writeState) => {\n throwIfAborted(pollAbortSignal);\n const writeAt = resolveNow(options.now);\n return writeConnectorState(options.memoryDir, definition.id, {\n id: definition.id,\n cursor: writeState.cursor,\n lastSyncAt: writeAt.toISOString(),\n lastSyncStatus: writeState.lastSyncStatus,\n ...(writeState.lastSyncError !== undefined\n ? { lastSyncError: writeState.lastSyncError }\n : {}),\n totalDocsImported: writeState.totalDocsImported,\n }).then(() => {\n lastStateWrittenAt = writeAt;\n });\n },\n });\n });\n if (\n runResult.docsImported === 0 &&\n runResult.error === undefined &&\n runResult.stateWriteError === undefined &&\n lastStateWrittenAt === undefined\n ) {\n const lockedState = await readConnectorState(options.memoryDir, definition.id);\n if (!force && !isConnectorDue(lockedState, definition.pollIntervalMs, checkAt)) {\n results.push(skipResult(definition, lockedState, \"not_due\"));\n continue;\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n let stateWriteError: string | undefined;\n let writtenErrorState: ConnectorState | undefined;\n const errorAt = resolveNow(options.now);\n if (!(err instanceof ConnectorStateLockLostError)) {\n try {\n writtenErrorState = await writeConnectorErrorState({\n memoryDir: options.memoryDir,\n connectorId: definition.id,\n state,\n error: message,\n now: errorAt,\n });\n } catch (writeErr) {\n stateWriteError =\n writeErr instanceof Error ? writeErr.message : String(writeErr);\n }\n }\n const reportedState = writtenErrorState ?? state;\n results.push({\n id: definition.id,\n displayName: definition.displayName,\n enabled: true,\n ran: false,\n skippedReason: \"connector_error\",\n docsImported: 0,\n error: message,\n ...(stateWriteError !== undefined ? { stateWriteError } : {}),\n lastSyncAt: reportedState?.lastSyncAt ?? null,\n nextDueAt: nextDueAt(reportedState, definition.pollIntervalMs),\n });\n continue;\n }\n results.push(\n runItemFromResult(\n definition,\n runResult,\n state,\n lastStateWrittenAt ?? resolveNow(options.now),\n ),\n );\n }\n\n return {\n ranAt: ranAt.toISOString(),\n force,\n totalDocsImported: results.reduce((sum, item) => sum + item.docsImported, 0),\n ranCount: results.filter((item) => item.ran).length,\n skippedCount: results.filter((item) => !item.ran).length,\n errorCount: results.filter(\n (item) => item.error !== undefined || item.stateWriteError !== undefined,\n ).length,\n results,\n };\n}\n\nfunction resolveNow(now: LiveConnectorsNow | undefined): Date {\n return typeof now === \"function\" ? now() : now ?? new Date();\n}\n\nfunction isConnectorDue(\n state: ConnectorState | null,\n pollIntervalMs: number,\n now: Date,\n): boolean {\n if (state?.lastSyncAt === null || state?.lastSyncAt === undefined) return true;\n const lastMs = Date.parse(state.lastSyncAt);\n if (!Number.isFinite(lastMs)) return true;\n return now.getTime() - lastMs >= Math.max(1, Math.floor(pollIntervalMs));\n}\n\nfunction nextDueAt(\n state: ConnectorState | null,\n pollIntervalMs: number,\n): string | null {\n if (state?.lastSyncAt === null || state?.lastSyncAt === undefined) return null;\n const lastMs = Date.parse(state.lastSyncAt);\n if (!Number.isFinite(lastMs)) return null;\n return new Date(lastMs + Math.max(1, Math.floor(pollIntervalMs))).toISOString();\n}\n\nfunction skipResult(\n definition: LiveConnectorDefinition,\n state: ConnectorState | null,\n skippedReason: LiveConnectorSkipReason,\n): LiveConnectorRunItem {\n return {\n id: definition.id,\n displayName: definition.displayName,\n enabled: definition.enabled,\n ran: false,\n skippedReason,\n docsImported: 0,\n lastSyncAt: state?.lastSyncAt ?? null,\n nextDueAt:\n skippedReason === \"not_due\"\n ? nextDueAt(state, definition.pollIntervalMs)\n : null,\n };\n}\n\nfunction runItemFromResult(\n definition: LiveConnectorDefinition,\n result: ConnectorRunResult,\n priorState: ConnectorState | null,\n now: Date,\n): LiveConnectorRunItem {\n const stateWriteFailed = result.stateWriteError !== undefined;\n const reportedLastSyncAt = stateWriteFailed\n ? priorState?.lastSyncAt ?? null\n : now.toISOString();\n const reportedNextDueAt = stateWriteFailed\n ? nextDueAt(priorState, definition.pollIntervalMs)\n : new Date(\n now.getTime() + Math.max(1, Math.floor(definition.pollIntervalMs)),\n ).toISOString();\n\n return {\n id: definition.id,\n displayName: definition.displayName,\n enabled: definition.enabled,\n ran: true,\n docsImported: result.docsImported,\n ...(result.error !== undefined ? { error: result.error } : {}),\n ...(result.stateWriteError !== undefined\n ? { stateWriteError: result.stateWriteError }\n : {}),\n lastSyncAt: reportedLastSyncAt,\n nextDueAt: reportedNextDueAt,\n };\n}\n\nfunction combineAbortSignals(...signals: Array<AbortSignal | undefined>): AbortSignal | undefined {\n const activeSignals = signals.filter((signal): signal is AbortSignal => signal !== undefined);\n if (activeSignals.length === 0) return undefined;\n if (activeSignals.length === 1) return activeSignals[0];\n const abortSignalAny = (AbortSignal as typeof AbortSignal & {\n any?: (signals: AbortSignal[]) => AbortSignal;\n }).any;\n if (abortSignalAny !== undefined) {\n return abortSignalAny(activeSignals);\n }\n const controller = new AbortController();\n const abort = (signal: AbortSignal): void => {\n if (!controller.signal.aborted) {\n controller.abort(signal.reason);\n }\n };\n for (const signal of activeSignals) {\n if (signal.aborted) {\n abort(signal);\n break;\n }\n signal.addEventListener(\"abort\", () => abort(signal), { once: true });\n }\n return controller.signal;\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted !== true) return;\n const reason = signal.reason;\n if (reason instanceof Error) {\n throw reason;\n }\n throw new Error(reason === undefined ? \"operation aborted\" : String(reason));\n}\n\nasync function writeConnectorErrorState(options: {\n memoryDir: string;\n connectorId: string;\n state: ConnectorState | null;\n error: string;\n now: Date;\n}): Promise<ConnectorState> {\n return writeConnectorState(options.memoryDir, options.connectorId, {\n id: options.connectorId,\n cursor: options.state?.cursor ?? null,\n lastSyncAt: options.now.toISOString(),\n lastSyncStatus: \"error\",\n lastSyncError: options.error,\n totalDocsImported: options.state?.totalDocsImported ?? 0,\n });\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/maintenance/rebuild-memory-projection.ts"],"sourcesContent":["import path from \"node:path\";\nimport { mkdir, rm, stat } from \"node:fs/promises\";\nimport { StorageManager } from \"../storage.js\";\nimport { log } from \"../logger.js\";\nimport {\n listMemoryGovernanceRuns,\n readMemoryGovernanceRunArtifact,\n} from \"./memory-governance.js\";\nimport { loadPersistedNativeKnowledgeChunks } from \"../native-knowledge.js\";\nimport { toBackupStamp } from \"./backup-stamp.js\";\nimport type {\n MemoryFile,\n MemoryLifecycleEvent,\n MemoryProjectionCurrentState,\n MemoryStatus,\n} from \"../types.js\";\nimport {\n buildLifecycleEventsForMemory,\n inferMemoryStatus,\n MEMORY_LIFECYCLE_EVENT_SORT_ORDER,\n memoryLifecycleEventProjectionIdentity,\n sortMemoryLifecycleEvents,\n toMemoryPathRel,\n} from \"../memory-lifecycle-ledger-utils.js\";\nimport {\n getMemoryProjectionPath,\n initializeMemoryProjectionDb,\n isProjectedMemoryPathValid,\n type ProjectedEntityMentionRow,\n type MemoryProjectionGovernanceAppliedActionRow,\n type MemoryProjectionGovernanceReviewQueueRow,\n type ProjectedNativeKnowledgeChunkRow,\n MEMORY_PROJECTION_SCHEMA_VERSION,\n memoryCurrentSelectExpressions,\n parseCurrentRow,\n readProjectedEntityMentions,\n readProjectedGovernanceRecord,\n readProjectedNativeKnowledgeChunks,\n parseTimelineRows,\n} from \"../memory-projection-store.js\";\nimport {\n normalizeProjectionPreview,\n normalizeProjectionTags,\n} from \"../memory-projection-format.js\";\nimport { openBetterSqlite3 } from \"../runtime/better-sqlite.js\";\nimport { commitPreparedFileAtomically } from \"./atomic-file.js\";\nimport { isSupportPassportPrivateMemory } from \"../support-passport/card-projection.js\";\n\nexport interface RebuildMemoryProjectionOptions {\n memoryDir: string;\n /** Reuse the caller's live StorageManager (must be rooted at memoryDir). */\n storage?: StorageManager;\n defaultNamespace?: string;\n dryRun?: boolean;\n now?: Date;\n updatedAfter?: string;\n updatedBefore?: string;\n}\n\nexport type {\n SkippedBlankIdMemory,\n SkippedBlankIdTimelineEvent,\n SkippedDuplicateMemory,\n SkippedDuplicateTimelineEvent,\n} from \"./projection-support.js\";\nimport {\n assertInjectedStorageRooted,\n readProjectedEntityMentionRows,\n readProjectedGovernanceRows,\n readProjectedNativeKnowledgeRows,\n writeProjectionMetaHighWater,\n} from \"./projection-support.js\";\nimport type {\n SkippedBlankIdMemory,\n SkippedBlankIdTimelineEvent,\n SkippedDuplicateMemory,\n SkippedDuplicateTimelineEvent,\n} from \"./projection-support.js\";\n\n\nexport interface RebuildMemoryProjectionResult {\n dryRun: boolean;\n scannedMemories: number;\n currentRows: number;\n timelineRows: number;\n entityMentionRows: number;\n nativeKnowledgeRows: number;\n reviewQueueRows: number;\n outputPath: string;\n backupPath?: string;\n usedLifecycleLedger: boolean;\n skippedDuplicateMemories: SkippedDuplicateMemory[];\n skippedBlankIdMemories: SkippedBlankIdMemory[];\n skippedDuplicateTimelineEvents: SkippedDuplicateTimelineEvent[];\n skippedBlankIdTimelineEvents: SkippedBlankIdTimelineEvent[];\n scope: {\n updatedAfter: string | null;\n updatedBefore: string | null;\n };\n}\n\nexport interface VerifyMemoryProjectionOptions {\n memoryDir: string;\n defaultNamespace?: string;\n updatedAfter?: string;\n updatedBefore?: string;\n}\n\nexport interface VerifyMemoryProjectionResult {\n outputPath: string;\n projectionExists: boolean;\n ok: boolean;\n expectedCurrentRows: number;\n actualCurrentRows: number;\n expectedTimelineRows: number;\n actualTimelineRows: number;\n expectedEntityMentionRows: number;\n actualEntityMentionRows: number;\n expectedNativeKnowledgeRows: number;\n actualNativeKnowledgeRows: number;\n expectedReviewQueueRows: number;\n actualReviewQueueRows: number;\n missingCurrentMemoryIds: string[];\n extraCurrentMemoryIds: string[];\n mismatchedCurrentMemoryIds: string[];\n missingTimelineEventIds: string[];\n extraTimelineEventIds: string[];\n missingEntityMentionKeys: string[];\n extraEntityMentionKeys: string[];\n mismatchedEntityMentionKeys: string[];\n missingNativeKnowledgeChunkIds: string[];\n extraNativeKnowledgeChunkIds: string[];\n mismatchedNativeKnowledgeChunkIds: string[];\n missingReviewQueueEntryIds: string[];\n extraReviewQueueEntryIds: string[];\n mismatchedReviewQueueEntryIds: string[];\n usedLifecycleLedger: boolean;\n scope: {\n updatedAfter: string | null;\n updatedBefore: string | null;\n };\n}\n\nexport interface RepairMemoryProjectionOptions extends RebuildMemoryProjectionOptions {}\n\nexport interface RepairMemoryProjectionResult {\n dryRun: boolean;\n repaired: boolean;\n verify: VerifyMemoryProjectionResult;\n rebuild?: RebuildMemoryProjectionResult;\n}\n\nfunction isNodeError(err: unknown): err is NodeJS.ErrnoException {\n return typeof err === \"object\" && err !== null && \"code\" in err;\n}\n\nexport async function backupExistingProjection(\n memoryDir: string,\n outputPath: string,\n now: Date,\n): Promise<string | undefined> {\n try {\n await stat(outputPath);\n } catch (err) {\n if (isNodeError(err) && err.code === \"ENOENT\") {\n return undefined;\n }\n throw err;\n }\n\n const backupPath = path.join(\n memoryDir,\n \"archive\",\n \"memory-projection\",\n toBackupStamp(now),\n \"state\",\n \"memory-projection.sqlite\",\n );\n return backupPath;\n}\n\nfunction inferProjectedStatus(pathRel: string, memory: MemoryFile): MemoryStatus {\n return inferMemoryStatus(memory.frontmatter, pathRel);\n}\n\nfunction toCurrentStateRow(memoryDir: string, memory: MemoryFile): MemoryProjectionCurrentState {\n const pathRel = toMemoryPathRel(memoryDir, memory.path);\n return {\n memoryId: memory.frontmatter.id,\n category: memory.frontmatter.category,\n status: inferProjectedStatus(pathRel, memory),\n lifecycleState: memory.frontmatter.lifecycleState,\n path: memory.path,\n pathRel,\n created: memory.frontmatter.created,\n updated: memory.frontmatter.updated,\n archivedAt: memory.frontmatter.archivedAt,\n supersededAt: memory.frontmatter.supersededAt,\n entityRef: memory.frontmatter.entityRef,\n source: memory.frontmatter.source,\n confidence: memory.frontmatter.confidence,\n confidenceTier: memory.frontmatter.confidenceTier,\n memoryKind: memory.frontmatter.memoryKind,\n accessCount: memory.frontmatter.accessCount,\n lastAccessed: memory.frontmatter.lastAccessed,\n tags: normalizeProjectionTags(memory.frontmatter.tags),\n preview: normalizeProjectionPreview(memory.content),\n privateRecord: isSupportPassportPrivateMemory(memory),\n };\n}\n\nfunction buildEntityMentionRows(\n currentRows: MemoryProjectionCurrentState[],\n): ProjectedEntityMentionRow[] {\n return currentRows.flatMap((row) => {\n const mentions: ProjectedEntityMentionRow[] = [];\n if (row.entityRef) {\n mentions.push({\n memoryId: row.memoryId,\n entityRef: row.entityRef,\n mentionSource: \"frontmatter.entityRef\",\n created: row.created,\n updated: row.updated,\n });\n }\n for (const tag of row.tags ?? []) {\n if (!tag.includes(\":\")) continue;\n mentions.push({\n memoryId: row.memoryId,\n entityRef: tag,\n mentionSource: \"tag\",\n created: row.created,\n updated: row.updated,\n });\n }\n return mentions;\n });\n}\n\nfunction buildGovernanceActionRowKey(action: {\n action: string;\n memoryId: string;\n reasonCode: string;\n originalPath: string;\n currentPath: string;\n}): string {\n return [\n action.action,\n action.memoryId,\n action.reasonCode,\n action.originalPath,\n action.currentPath,\n ].join(\"::\");\n}\n\nasync function loadLatestGovernanceProjection(memoryDir: string): Promise<{\n runId: string;\n summary: unknown;\n metrics: unknown;\n reviewQueueRows: MemoryProjectionGovernanceReviewQueueRow[];\n appliedActionRows: MemoryProjectionGovernanceAppliedActionRow[];\n report: string;\n} | null> {\n const runId = (await listMemoryGovernanceRuns(memoryDir))[0];\n if (!runId) return null;\n try {\n const artifact = await readMemoryGovernanceRunArtifact(memoryDir, runId);\n return {\n runId,\n summary: artifact.summary,\n metrics: artifact.metrics,\n reviewQueueRows: artifact.reviewQueue.map((entry) => ({\n runId,\n entryId: entry.entryId,\n memoryId: entry.memoryId,\n path: entry.path,\n reasonCode: entry.reasonCode,\n severity: entry.severity,\n suggestedAction: entry.suggestedAction,\n suggestedStatus: entry.suggestedStatus,\n relatedMemoryIds: [...entry.relatedMemoryIds],\n })),\n appliedActionRows: artifact.appliedActions.map((action) => ({\n runId,\n rowKey: buildGovernanceActionRowKey(action),\n action: action.action,\n memoryId: action.memoryId,\n reasonCode: action.reasonCode,\n beforeStatus: action.beforeStatus,\n afterStatus: action.afterStatus,\n originalPath: action.originalPath,\n currentPath: action.currentPath,\n })),\n report: artifact.report,\n };\n } catch {\n return null;\n }\n}\n\nfunction loadTimelineEvents(\n memories: MemoryFile[],\n lifecycleEvents: MemoryLifecycleEvent[],\n): { events: MemoryLifecycleEvent[]; usedLifecycleLedger: boolean } {\n if (lifecycleEvents.length > 0) {\n return {\n events: sortMemoryLifecycleEvents(lifecycleEvents),\n usedLifecycleLedger: true,\n };\n }\n\n return {\n events: sortMemoryLifecycleEvents(memories.flatMap((memory) => buildLifecycleEventsForMemory(memory))),\n usedLifecycleLedger: false,\n };\n}\n\nfunction normalizeScopedIso(value: string | undefined): string | null {\n if (!value) return null;\n const trimmed = value.trim();\n if (!trimmed) return null;\n const parsed = new Date(trimmed);\n if (Number.isNaN(parsed.getTime())) {\n throw new Error(`invalid projection scope timestamp: ${value}`);\n }\n return parsed.toISOString();\n}\n\nfunction normalizeProjectionScope(options: {\n updatedAfter?: string;\n updatedBefore?: string;\n}): {\n updatedAfter: string | null;\n updatedBefore: string | null;\n} {\n const updatedAfter = normalizeScopedIso(options.updatedAfter);\n const updatedBefore = normalizeScopedIso(options.updatedBefore);\n if (\n updatedAfter &&\n updatedBefore &&\n new Date(updatedAfter).getTime() > new Date(updatedBefore).getTime()\n ) {\n throw new Error(\"updatedAfter must be less than or equal to updatedBefore\");\n }\n return {\n updatedAfter,\n updatedBefore,\n };\n}\n\nfunction hasScopedProjectionFilter(scope: {\n updatedAfter: string | null;\n updatedBefore: string | null;\n}): boolean {\n return scope.updatedAfter !== null || scope.updatedBefore !== null;\n}\n\nfunction memoryScopeTimestamp(memory: MemoryFile): string {\n const candidate = memory.frontmatter.updated || memory.frontmatter.created;\n return candidate;\n}\n\nfunction isTimestampInProjectionScope(\n timestamp: string,\n scope: { updatedAfter: string | null; updatedBefore: string | null },\n): boolean {\n if (!scope.updatedAfter && !scope.updatedBefore) return true;\n const parsed = new Date(timestamp);\n if (Number.isNaN(parsed.getTime())) return false;\n if (scope.updatedAfter && parsed.getTime() < new Date(scope.updatedAfter).getTime()) return false;\n if (scope.updatedBefore && parsed.getTime() >= new Date(scope.updatedBefore).getTime()) return false;\n return true;\n}\n\nfunction filterMemoriesForProjectionScope(\n memories: MemoryFile[],\n scope: { updatedAfter: string | null; updatedBefore: string | null },\n): MemoryFile[] {\n if (!scope.updatedAfter && !scope.updatedBefore) return memories;\n return memories.filter((memory) => isTimestampInProjectionScope(memoryScopeTimestamp(memory), scope));\n}\n\nfunction filterCurrentStateRowsForProjectionScope(\n rows: MemoryProjectionCurrentState[],\n scope: { updatedAfter: string | null; updatedBefore: string | null },\n): MemoryProjectionCurrentState[] {\n if (!scope.updatedAfter && !scope.updatedBefore) return rows;\n return rows.filter((row) => isTimestampInProjectionScope(row.updated || row.created, scope));\n}\n\nfunction serializeCurrentStateRow(row: MemoryProjectionCurrentState): string {\n return JSON.stringify({\n memoryId: row.memoryId,\n category: row.category,\n status: row.status,\n lifecycleState: row.lifecycleState ?? null,\n pathRel: row.pathRel,\n created: row.created,\n updated: row.updated,\n archivedAt: row.archivedAt ?? null,\n supersededAt: row.supersededAt ?? null,\n entityRef: row.entityRef ?? null,\n source: row.source,\n confidence: row.confidence,\n confidenceTier: row.confidenceTier,\n memoryKind: row.memoryKind ?? null,\n accessCount: row.accessCount ?? null,\n lastAccessed: row.lastAccessed ?? null,\n tags: row.tags ?? [],\n preview: row.preview ?? \"\",\n privateRecord: row.privateRecord === true,\n });\n}\n\nfunction serializeTimelineEvent(event: MemoryLifecycleEvent): string {\n return JSON.stringify({\n eventId: event.eventId,\n memoryId: event.memoryId,\n eventType: event.eventType,\n timestamp: event.timestamp,\n actor: event.actor,\n reasonCode: event.reasonCode ?? null,\n ruleVersion: event.ruleVersion,\n relatedMemoryIds: event.relatedMemoryIds ?? [],\n before: event.before ?? null,\n after: event.after ?? null,\n correlationId: event.correlationId ?? null,\n });\n}\n\nfunction serializeEntityMentionRow(row: ProjectedEntityMentionRow): string {\n return JSON.stringify(row);\n}\n\nfunction serializeNativeKnowledgeRow(row: ProjectedNativeKnowledgeChunkRow): string {\n return JSON.stringify({\n chunkId: row.chunkId,\n sourceKind: row.sourceKind,\n sourcePath: row.sourcePath,\n title: row.title,\n startLine: row.startLine,\n endLine: row.endLine,\n namespace: row.namespace ?? null,\n privacyClass: row.privacyClass ?? null,\n derivedDate: row.derivedDate ?? null,\n sessionKey: row.sessionKey ?? null,\n workflowKey: row.workflowKey ?? null,\n author: row.author ?? null,\n agent: row.agent ?? null,\n sourceHash: row.sourceHash ?? null,\n preview: row.preview,\n });\n}\n\nfunction serializeGovernanceReviewQueueRow(\n row: MemoryProjectionGovernanceReviewQueueRow,\n): string {\n return JSON.stringify({\n runId: row.runId,\n entryId: row.entryId,\n memoryId: row.memoryId,\n path: row.path,\n reasonCode: row.reasonCode,\n severity: row.severity,\n suggestedAction: row.suggestedAction,\n suggestedStatus: row.suggestedStatus ?? null,\n relatedMemoryIds: row.relatedMemoryIds,\n });\n}\n\nfunction selectProjectionMemories(\n tiers: MemoryFile[][],\n): {\n allMemories: MemoryFile[];\n memories: MemoryFile[];\n skippedDuplicateMemories: SkippedDuplicateMemory[];\n skippedBlankIdMemories: SkippedBlankIdMemory[];\n} {\n const allMemories = tiers.flat();\n const memories: MemoryFile[] = [];\n const keptById = new Map<string, MemoryFile>();\n const skippedDuplicateMemories: SkippedDuplicateMemory[] = [];\n const skippedBlankIdMemories: SkippedBlankIdMemory[] = [];\n\n // Tier order is authoritative: hot wins over cold, and cold wins over archive.\n // Paths break ties within a tier so the winner does not depend on readdir order.\n for (const tier of tiers) {\n for (const memory of [...tier].sort((left, right) => left.path.localeCompare(right.path))) {\n const memoryId = memory.frontmatter.id.trim();\n if (!memoryId) {\n skippedBlankIdMemories.push({ path: memory.path });\n log.warn(`projection rebuild skipped blank memory id: path=${memory.path}`);\n continue;\n }\n const kept = keptById.get(memoryId);\n if (kept) {\n skippedDuplicateMemories.push({\n memoryId,\n keptPath: kept.path,\n skippedPath: memory.path,\n });\n log.warn(\n `projection rebuild skipped duplicate memory id=${memoryId}: kept=${kept.path} skipped=${memory.path}`,\n );\n continue;\n }\n keptById.set(memoryId, memory);\n memories.push(memory);\n }\n }\n\n return { allMemories, memories, skippedDuplicateMemories, skippedBlankIdMemories };\n}\n\nfunction deduplicateTimelineEvents(\n events: MemoryLifecycleEvent[],\n sourcePathFor: (event: MemoryLifecycleEvent) => string,\n): {\n events: MemoryLifecycleEvent[];\n skipped: SkippedDuplicateTimelineEvent[];\n skippedBlankIds: SkippedBlankIdTimelineEvent[];\n} {\n const keptById = new Map<string, { event: MemoryLifecycleEvent; path: string }>();\n const unique: MemoryLifecycleEvent[] = [];\n const skipped: SkippedDuplicateTimelineEvent[] = [];\n const skippedBlankIds: SkippedBlankIdTimelineEvent[] = [];\n for (const event of sortMemoryLifecycleEvents(events)) {\n const sourcePath = sourcePathFor(event);\n if (!event.memoryId.trim()) {\n skippedBlankIds.push({ eventId: event.eventId, path: sourcePath });\n log.warn(\n `projection rebuild skipped timeline event with blank memory id: `\n + `event_id=${event.eventId} path=${sourcePath}`,\n );\n continue;\n }\n const kept = keptById.get(event.eventId);\n if (kept) {\n skipped.push({\n eventId: event.eventId,\n keptPath: kept.path,\n skippedPath: sourcePath,\n });\n log.warn(\n `projection rebuild skipped duplicate timeline event_id=${event.eventId}: `\n + `kept=${kept.path} skipped=${sourcePath}`,\n );\n continue;\n }\n keptById.set(event.eventId, { event, path: sourcePath });\n unique.push(event);\n }\n return { events: unique, skipped, skippedBlankIds };\n}\n\nasync function loadAuthoritativeProjectionSnapshot(options: {\n memoryDir: string;\n defaultNamespace?: string;\n storage?: StorageManager;\n updatedAfter?: string;\n updatedBefore?: string;\n}): Promise<{\n allMemories: MemoryFile[];\n currentRows: MemoryProjectionCurrentState[];\n timelineRows: MemoryLifecycleEvent[];\n scopedCurrentRows: MemoryProjectionCurrentState[];\n scopedTimelineRows: MemoryLifecycleEvent[];\n entityMentionRows: ProjectedEntityMentionRow[];\n scopedEntityMentionRows: ProjectedEntityMentionRow[];\n nativeKnowledgeRows: ProjectedNativeKnowledgeChunkRow[];\n governance:\n | {\n runId: string;\n summary: unknown;\n metrics: unknown;\n reviewQueueRows: MemoryProjectionGovernanceReviewQueueRow[];\n appliedActionRows: MemoryProjectionGovernanceAppliedActionRow[];\n report: string;\n }\n | null;\n usedLifecycleLedger: boolean;\n sourceLifecycleLedgerEventCount: number;\n scope: {\n updatedAfter: string | null;\n updatedBefore: string | null;\n };\n skippedDuplicateMemories: SkippedDuplicateMemory[];\n skippedBlankIdMemories: SkippedBlankIdMemory[];\n skippedDuplicateTimelineEvents: SkippedDuplicateTimelineEvent[];\n skippedBlankIdTimelineEvents: SkippedBlankIdTimelineEvent[];\n}> {\n const storage = assertInjectedStorageRooted(\"rebuildMemoryProjection\", options.memoryDir, options.storage) ?? new StorageManager(options.memoryDir);\n // Force a fresh disk read — projection verify/rebuild must see the true\n // on-disk state, not a potentially stale in-process cache.\n storage.invalidateAllMemoriesCacheForDir();\n const selected = selectProjectionMemories([\n await storage.readAllMemories(),\n await storage.readAllColdMemories(),\n await storage.readArchivedMemories(),\n ]);\n const allMemories = selected.allMemories;\n const projectionMemories = selected.memories;\n const lifecycleEvents = await storage.readAllMemoryLifecycleEvents();\n const timeline = loadTimelineEvents(projectionMemories, lifecycleEvents);\n const lifecycleLedgerPath = path.join(\n options.memoryDir,\n \"state\",\n \"memory-lifecycle-ledger.jsonl\",\n );\n const memoryPathById = new Map(\n projectionMemories.map((memory) => [memory.frontmatter.id, memory.path]),\n );\n const deduplicatedTimeline = deduplicateTimelineEvents(\n timeline.events,\n (event) => timeline.usedLifecycleLedger\n ? lifecycleLedgerPath\n : memoryPathById.get(event.memoryId) ?? lifecycleLedgerPath,\n );\n const events = deduplicatedTimeline.events;\n const usedLifecycleLedger = timeline.usedLifecycleLedger;\n const sourceLifecycleLedgerEventCount = new Set(\n lifecycleEvents.map(memoryLifecycleEventProjectionIdentity),\n ).size;\n const currentRows = projectionMemories.map((memory) => toCurrentStateRow(options.memoryDir, memory));\n const scope = normalizeProjectionScope(options);\n const scopedMemories = filterMemoriesForProjectionScope(projectionMemories, scope);\n const scopedMemoryIds = new Set(scopedMemories.map((memory) => memory.frontmatter.id));\n const nativeKnowledgeRows = await loadPersistedNativeKnowledgeChunks({\n memoryDir: options.memoryDir,\n defaultNamespace: options.defaultNamespace ?? \"default\",\n }).then((rows) => rows.map((row) => ({\n chunkId: row.chunkId,\n sourceKind: row.sourceKind,\n sourcePath: row.sourcePath,\n title: row.title,\n startLine: row.startLine,\n endLine: row.endLine,\n namespace: row.namespace ?? options.defaultNamespace ?? \"default\",\n privacyClass: row.privacyClass,\n derivedDate: row.derivedDate,\n sessionKey: row.sessionKey,\n workflowKey: row.workflowKey,\n author: row.author,\n agent: row.agent,\n sourceHash: row.sourceHash,\n preview: normalizeProjectionPreview(row.content),\n })));\n const governance = await loadLatestGovernanceProjection(options.memoryDir);\n const entityMentionRows = buildEntityMentionRows(currentRows);\n\n return {\n allMemories,\n currentRows,\n timelineRows: events,\n scopedCurrentRows: currentRows.filter((row) => scopedMemoryIds.has(row.memoryId)),\n scopedTimelineRows: events.filter((event) => scopedMemoryIds.has(event.memoryId)),\n entityMentionRows,\n scopedEntityMentionRows: entityMentionRows.filter((row) => scopedMemoryIds.has(row.memoryId)),\n nativeKnowledgeRows,\n governance,\n usedLifecycleLedger,\n sourceLifecycleLedgerEventCount,\n scope,\n skippedDuplicateMemories: selected.skippedDuplicateMemories,\n skippedBlankIdMemories: selected.skippedBlankIdMemories,\n skippedDuplicateTimelineEvents: deduplicatedTimeline.skipped,\n skippedBlankIdTimelineEvents: deduplicatedTimeline.skippedBlankIds,\n };\n}\n\nfunction readProjectedCurrentRows(\n memoryDir: string,\n): { projectionExists: boolean; rows: MemoryProjectionCurrentState[] } {\n const dbPath = getMemoryProjectionPath(memoryDir);\n try {\n const db = openBetterSqlite3(dbPath, { readonly: true, fileMustExist: true });\n try {\n const selectExpressions = memoryCurrentSelectExpressions(db);\n const rows = db.prepare(`\n SELECT\n memory_id,\n category,\n status,\n lifecycle_state,\n path_rel,\n created_at,\n updated_at,\n archived_at,\n superseded_at,\n entity_ref,\n source,\n confidence,\n confidence_tier,\n memory_kind,\n access_count,\n last_accessed,\n ${selectExpressions.tagsJson}, ${selectExpressions.previewText}, ${selectExpressions.privateRecord}\n FROM memory_current\n `).all() as Array<Record<string, unknown>>;\n\n return {\n projectionExists: true,\n rows: rows\n .map((row) => parseCurrentRow(memoryDir, row))\n .filter((row): row is MemoryProjectionCurrentState => row !== null),\n };\n } finally {\n db.close();\n }\n } catch {\n return { projectionExists: false, rows: [] };\n }\n}\n\nfunction readProjectedTimelineRows(\n memoryDir: string,\n): { projectionExists: boolean; rows: MemoryLifecycleEvent[] } {\n const dbPath = getMemoryProjectionPath(memoryDir);\n try {\n const db = openBetterSqlite3(dbPath, { readonly: true, fileMustExist: true });\n try {\n const rows = db.prepare(`\n SELECT\n event_id,\n memory_id,\n event_type,\n timestamp,\n actor,\n reason_code,\n rule_version,\n related_memory_ids_json,\n before_json,\n after_json,\n correlation_id\n FROM memory_timeline\n `).all() as Array<Record<string, unknown>>;\n\n return {\n projectionExists: true,\n rows: parseTimelineRows(rows),\n };\n } finally {\n db.close();\n }\n } catch {\n return { projectionExists: false, rows: [] };\n }\n}\n\n\nfunction writeProjectionDb(\n dbPath: string,\n nowIso: string,\n currentRows: MemoryProjectionCurrentState[],\n timelineRows: MemoryLifecycleEvent[],\n entityMentionRows: ProjectedEntityMentionRow[],\n nativeKnowledgeRows: ProjectedNativeKnowledgeChunkRow[],\n governance: Awaited<ReturnType<typeof loadLatestGovernanceProjection>>,\n usedLifecycleLedger: boolean,\n sourceLifecycleLedgerEventCount: number,\n): void {\n const db = openBetterSqlite3(dbPath);\n const memoryDir = path.dirname(path.dirname(dbPath));\n try {\n initializeMemoryProjectionDb(db);\n\n const insertMeta = db.prepare(\"INSERT OR REPLACE INTO meta(key, value) VALUES (?, ?)\");\n insertMeta.run(\"schemaVersion\", String(MEMORY_PROJECTION_SCHEMA_VERSION));\n insertMeta.run(\"rebuiltAt\", nowIso);\n insertMeta.run(\"usedLifecycleLedger\", usedLifecycleLedger ? \"true\" : \"false\");\n writeProjectionMetaHighWater(insertMeta, sourceLifecycleLedgerEventCount, timelineRows);\n insertMeta.run(\"latestGovernanceRunId\", governance?.runId ?? \"\");\n\n const insertCurrent = db.prepare(`\n INSERT INTO memory_current (\n memory_id,\n category,\n status,\n lifecycle_state,\n path_rel,\n path_valid,\n created_at,\n updated_at,\n archived_at,\n superseded_at,\n entity_ref,\n source,\n confidence,\n confidence_tier,\n memory_kind,\n access_count,\n last_accessed,\n tags_json, preview_text, private_record\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n const insertTimeline = db.prepare(`\n INSERT INTO memory_timeline (\n event_id,\n memory_id,\n event_type,\n timestamp,\n event_order,\n actor,\n reason_code,\n rule_version,\n related_memory_ids_json,\n before_json,\n after_json,\n correlation_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n const insertEntityMention = db.prepare(`\n INSERT INTO memory_entity_mentions (\n memory_id,\n entity_ref,\n mention_source,\n created_at,\n updated_at\n ) VALUES (?, ?, ?, ?, ?)\n `);\n\n const insertNativeKnowledge = db.prepare(`\n INSERT INTO native_knowledge_chunks (\n chunk_id,\n source_kind,\n source_path,\n title,\n start_line,\n end_line,\n namespace,\n privacy_class,\n derived_date,\n session_key,\n workflow_key,\n author,\n agent,\n source_hash,\n preview_text\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n const insertGovernanceReviewQueue = db.prepare(`\n INSERT INTO memory_review_queue (\n entry_id,\n run_id,\n memory_id,\n path,\n reason_code,\n severity,\n suggested_action,\n suggested_status,\n related_memory_ids_json\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n const insertGovernanceAppliedAction = db.prepare(`\n INSERT INTO memory_review_actions (\n row_key,\n run_id,\n action,\n memory_id,\n reason_code,\n before_status,\n after_status,\n original_path,\n current_path\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n const insertGovernanceRun = db.prepare(`\n INSERT INTO memory_review_runs (\n run_id,\n created_at,\n mode,\n summary_json,\n metrics_json,\n applied_actions_json,\n report_markdown\n ) VALUES (?, ?, ?, ?, ?, ?, ?)\n `);\n\n const writeTx = db.transaction(() => {\n for (const row of currentRows) {\n insertCurrent.run(\n row.memoryId,\n row.category,\n row.status,\n row.lifecycleState ?? null,\n row.pathRel,\n isProjectedMemoryPathValid(memoryDir, row.pathRel) ? 1 : 0,\n row.created,\n row.updated,\n row.archivedAt ?? null,\n row.supersededAt ?? null,\n row.entityRef ?? null,\n row.source,\n row.confidence,\n row.confidenceTier,\n row.memoryKind ?? null,\n row.accessCount ?? null,\n row.lastAccessed ?? null, JSON.stringify(row.tags ?? []), row.preview ?? \"\",\n row.privateRecord === true ? 1 : 0,\n );\n }\n\n for (const event of timelineRows) {\n insertTimeline.run(\n event.eventId,\n event.memoryId,\n event.eventType,\n event.timestamp,\n MEMORY_LIFECYCLE_EVENT_SORT_ORDER[event.eventType],\n event.actor,\n event.reasonCode ?? null,\n event.ruleVersion,\n JSON.stringify(event.relatedMemoryIds ?? []),\n event.before ? JSON.stringify(event.before) : null,\n event.after ? JSON.stringify(event.after) : null,\n event.correlationId ?? null,\n );\n }\n\n for (const row of entityMentionRows) {\n insertEntityMention.run(\n row.memoryId,\n row.entityRef,\n row.mentionSource,\n row.created,\n row.updated,\n );\n }\n\n for (const row of nativeKnowledgeRows) {\n insertNativeKnowledge.run(\n row.chunkId,\n row.sourceKind,\n row.sourcePath,\n row.title,\n row.startLine,\n row.endLine,\n row.namespace ?? null,\n row.privacyClass ?? null,\n row.derivedDate ?? null,\n row.sessionKey ?? null,\n row.workflowKey ?? null,\n row.author ?? null,\n row.agent ?? null,\n row.sourceHash ?? null,\n row.preview,\n );\n }\n\n for (const row of governance?.reviewQueueRows ?? []) {\n insertGovernanceReviewQueue.run(\n row.entryId,\n row.runId,\n row.memoryId,\n row.path,\n row.reasonCode,\n row.severity,\n row.suggestedAction,\n row.suggestedStatus ?? null,\n JSON.stringify(row.relatedMemoryIds),\n );\n }\n\n for (const row of governance?.appliedActionRows ?? []) {\n insertGovernanceAppliedAction.run(\n row.rowKey,\n row.runId,\n row.action,\n row.memoryId,\n row.reasonCode,\n row.beforeStatus,\n row.afterStatus ?? null,\n row.originalPath,\n row.currentPath,\n );\n }\n\n if (governance) {\n const createdAt =\n typeof (governance.summary as { createdAt?: unknown } | undefined)?.createdAt === \"string\"\n ? (governance.summary as { createdAt: string }).createdAt\n : nowIso;\n const mode =\n typeof (governance.summary as { mode?: unknown } | undefined)?.mode === \"string\"\n ? (governance.summary as { mode: string }).mode\n : \"shadow\";\n insertGovernanceRun.run(\n governance.runId,\n createdAt,\n mode,\n JSON.stringify(governance.summary ?? null),\n JSON.stringify(governance.metrics ?? null),\n JSON.stringify(\n (governance.appliedActionRows ?? []).map((row) => ({\n action: row.action,\n memoryId: row.memoryId,\n reasonCode: row.reasonCode,\n beforeStatus: row.beforeStatus,\n afterStatus: row.afterStatus,\n originalPath: row.originalPath,\n currentPath: row.currentPath,\n })),\n ),\n governance.report,\n );\n }\n });\n\n writeTx();\n } finally {\n db.close();\n }\n}\n\nfunction mergeScopedCurrentRows(\n existingRows: MemoryProjectionCurrentState[],\n replacementRows: MemoryProjectionCurrentState[],\n scopedMemoryIds: Set<string>,\n): MemoryProjectionCurrentState[] {\n return [...existingRows.filter((row) => !scopedMemoryIds.has(row.memoryId)), ...replacementRows]\n .sort((a, b) => a.memoryId.localeCompare(b.memoryId));\n}\n\nfunction mergeScopedTimelineRows(\n existingRows: MemoryLifecycleEvent[],\n replacementRows: MemoryLifecycleEvent[],\n scopedMemoryIds: Set<string>,\n): MemoryLifecycleEvent[] {\n return sortMemoryLifecycleEvents([\n ...existingRows.filter((event) => !scopedMemoryIds.has(event.memoryId)),\n ...replacementRows,\n ]);\n}\n\nfunction mergeScopedEntityMentionRows(\n existingRows: ProjectedEntityMentionRow[],\n replacementRows: ProjectedEntityMentionRow[],\n scopedMemoryIds: Set<string>,\n): ProjectedEntityMentionRow[] {\n return [\n ...existingRows.filter((row) => !scopedMemoryIds.has(row.memoryId)),\n ...replacementRows,\n ].sort((left, right) =>\n [left.entityRef, left.memoryId, left.mentionSource].join(\"::\").localeCompare(\n [right.entityRef, right.memoryId, right.mentionSource].join(\"::\"),\n )\n );\n}\n\nexport async function rebuildMemoryProjection(\n options: RebuildMemoryProjectionOptions,\n): Promise<RebuildMemoryProjectionResult> {\n const dryRun = options.dryRun !== false;\n const now = options.now ?? new Date();\n const outputPath = getMemoryProjectionPath(options.memoryDir);\n const snapshot = await loadAuthoritativeProjectionSnapshot(options);\n\n let backupPath: string | undefined;\n if (!dryRun) {\n let nextCurrentRows = snapshot.currentRows;\n let nextTimelineRows = snapshot.timelineRows;\n let nextEntityMentionRows = snapshot.entityMentionRows;\n let nextNativeKnowledgeRows = snapshot.nativeKnowledgeRows;\n let nextGovernance = snapshot.governance;\n if (hasScopedProjectionFilter(snapshot.scope)) {\n nextCurrentRows = snapshot.scopedCurrentRows;\n nextTimelineRows = snapshot.scopedTimelineRows;\n nextEntityMentionRows = snapshot.scopedEntityMentionRows;\n const projectedCurrent = readProjectedCurrentRows(options.memoryDir);\n const projectedTimeline = readProjectedTimelineRows(options.memoryDir);\n const projectedEntityMentions = readProjectedEntityMentionRows(options.memoryDir);\n const projectedNativeKnowledge = readProjectedNativeKnowledgeRows(options.memoryDir);\n const projectedGovernance = readProjectedGovernanceRows(options.memoryDir);\n if (projectedCurrent.projectionExists && projectedTimeline.projectionExists) {\n const actualScopedCurrentRows = filterCurrentStateRowsForProjectionScope(\n projectedCurrent.rows,\n snapshot.scope,\n );\n const scopedMemoryIds = new Set([\n ...snapshot.scopedCurrentRows.map((row) => row.memoryId),\n ...snapshot.scopedTimelineRows.map((event) => event.memoryId),\n ...actualScopedCurrentRows.map((row) => row.memoryId),\n ]);\n nextCurrentRows = mergeScopedCurrentRows(\n projectedCurrent.rows,\n snapshot.scopedCurrentRows,\n scopedMemoryIds,\n );\n nextTimelineRows = mergeScopedTimelineRows(\n projectedTimeline.rows,\n snapshot.scopedTimelineRows,\n scopedMemoryIds,\n );\n nextEntityMentionRows = mergeScopedEntityMentionRows(\n projectedEntityMentions.rows,\n snapshot.scopedEntityMentionRows,\n scopedMemoryIds,\n );\n }\n if (projectedNativeKnowledge.projectionExists) {\n // Native knowledge rows are always loaded from the full persisted sync state,\n // so scoped memory rebuilds should publish the fresh snapshot instead of\n // pinning the projection to stale previously projected rows.\n nextNativeKnowledgeRows = snapshot.nativeKnowledgeRows;\n }\n if (projectedGovernance.projectionExists && projectedGovernance.runId) {\n // Governance rows are also sourced from standalone artifact snapshots, so\n // scoped memory rebuilds should keep the latest governance artifact data\n // instead of restoring whatever happened to be in the prior projection.\n nextGovernance = snapshot.governance;\n }\n }\n\n const tempPath = `${outputPath}.tmp`;\n await mkdir(path.dirname(outputPath), { recursive: true });\n await rm(tempPath, { force: true });\n writeProjectionDb(\n tempPath,\n now.toISOString(),\n nextCurrentRows,\n nextTimelineRows,\n nextEntityMentionRows,\n nextNativeKnowledgeRows,\n nextGovernance,\n snapshot.usedLifecycleLedger,\n snapshot.sourceLifecycleLedgerEventCount,\n );\n backupPath = await backupExistingProjection(options.memoryDir, outputPath, now);\n backupPath = await commitPreparedFileAtomically(tempPath, outputPath, backupPath);\n }\n\n return {\n dryRun,\n scannedMemories: snapshot.allMemories.length,\n currentRows: snapshot.scopedCurrentRows.length,\n timelineRows: snapshot.scopedTimelineRows.length,\n entityMentionRows: snapshot.scopedEntityMentionRows.length,\n nativeKnowledgeRows: snapshot.nativeKnowledgeRows.length,\n reviewQueueRows: snapshot.governance?.reviewQueueRows.length ?? 0,\n outputPath,\n backupPath,\n usedLifecycleLedger: snapshot.usedLifecycleLedger,\n skippedDuplicateMemories: snapshot.skippedDuplicateMemories,\n skippedBlankIdMemories: snapshot.skippedBlankIdMemories,\n skippedDuplicateTimelineEvents: snapshot.skippedDuplicateTimelineEvents,\n skippedBlankIdTimelineEvents: snapshot.skippedBlankIdTimelineEvents,\n scope: snapshot.scope,\n };\n}\n\nexport async function verifyMemoryProjection(\n options: VerifyMemoryProjectionOptions,\n): Promise<VerifyMemoryProjectionResult> {\n const outputPath = getMemoryProjectionPath(options.memoryDir);\n const snapshot = await loadAuthoritativeProjectionSnapshot(options);\n const projectedCurrent = readProjectedCurrentRows(options.memoryDir);\n const projectedTimeline = readProjectedTimelineRows(options.memoryDir);\n const projectedEntityMentions = readProjectedEntityMentionRows(options.memoryDir);\n const projectedNativeKnowledge = readProjectedNativeKnowledgeRows(options.memoryDir);\n const projectedGovernance = readProjectedGovernanceRows(options.memoryDir);\n const projectionExists = projectedCurrent.projectionExists\n || projectedTimeline.projectionExists\n || projectedEntityMentions.projectionExists\n || projectedNativeKnowledge.projectionExists\n || projectedGovernance.projectionExists;\n\n const actualScopedCurrentRows = filterCurrentStateRowsForProjectionScope(projectedCurrent.rows, snapshot.scope);\n const expectedCurrentById = new Map(\n snapshot.scopedCurrentRows.map((row) => [row.memoryId, serializeCurrentStateRow(row)]),\n );\n const actualCurrentById = new Map(\n actualScopedCurrentRows.map((row) => [row.memoryId, serializeCurrentStateRow(row)]),\n );\n\n const missingCurrentMemoryIds = [...expectedCurrentById.keys()]\n .filter((memoryId) => !actualCurrentById.has(memoryId))\n .sort();\n const extraCurrentMemoryIds = [...actualCurrentById.keys()]\n .filter((memoryId) => !expectedCurrentById.has(memoryId))\n .sort();\n const mismatchedCurrentMemoryIds = [...expectedCurrentById.keys()]\n .filter((memoryId) =>\n actualCurrentById.has(memoryId) && actualCurrentById.get(memoryId) !== expectedCurrentById.get(memoryId)\n )\n .sort();\n\n const selectedMemoryIds = new Set([\n ...snapshot.scopedCurrentRows.map((row) => row.memoryId),\n ...actualScopedCurrentRows.map((row) => row.memoryId),\n ]);\n const expectedTimelineById = new Map(\n snapshot.scopedTimelineRows.map((event) => [event.eventId, serializeTimelineEvent(event)]),\n );\n const actualTimelineRows = projectedTimeline.rows.filter((event) => selectedMemoryIds.has(event.memoryId));\n const actualTimelineById = new Map(\n actualTimelineRows.map((event) => [event.eventId, serializeTimelineEvent(event)]),\n );\n const missingTimelineEventIds = [...expectedTimelineById.keys()]\n .filter((eventId) => !actualTimelineById.has(eventId))\n .sort();\n const extraTimelineEventIds = [...actualTimelineById.keys()]\n .filter((eventId) => !expectedTimelineById.has(eventId))\n .sort();\n\n const expectedEntityMentionsByKey = new Map(\n snapshot.scopedEntityMentionRows.map((row) => [\n `${row.memoryId}::${row.entityRef}::${row.mentionSource}`,\n serializeEntityMentionRow(row),\n ]),\n );\n const actualScopedEntityMentionRows = projectedEntityMentions.rows.filter((row) => selectedMemoryIds.has(row.memoryId));\n const actualEntityMentionsByKey = new Map(\n actualScopedEntityMentionRows.map((row) => [\n `${row.memoryId}::${row.entityRef}::${row.mentionSource}`,\n serializeEntityMentionRow(row),\n ]),\n );\n const missingEntityMentionKeys = [...expectedEntityMentionsByKey.keys()]\n .filter((key) => !actualEntityMentionsByKey.has(key))\n .sort();\n const extraEntityMentionKeys = [...actualEntityMentionsByKey.keys()]\n .filter((key) => !expectedEntityMentionsByKey.has(key))\n .sort();\n const mismatchedEntityMentionKeys = [...expectedEntityMentionsByKey.keys()]\n .filter((key) =>\n actualEntityMentionsByKey.has(key) && actualEntityMentionsByKey.get(key) !== expectedEntityMentionsByKey.get(key)\n )\n .sort();\n\n const expectedNativeKnowledgeById = new Map(\n snapshot.nativeKnowledgeRows.map((row) => [row.chunkId, serializeNativeKnowledgeRow(row)]),\n );\n const actualNativeKnowledgeById = new Map(\n projectedNativeKnowledge.rows.map((row) => [row.chunkId, serializeNativeKnowledgeRow(row)]),\n );\n const missingNativeKnowledgeChunkIds = [...expectedNativeKnowledgeById.keys()]\n .filter((chunkId) => !actualNativeKnowledgeById.has(chunkId))\n .sort();\n const extraNativeKnowledgeChunkIds = [...actualNativeKnowledgeById.keys()]\n .filter((chunkId) => !expectedNativeKnowledgeById.has(chunkId))\n .sort();\n const mismatchedNativeKnowledgeChunkIds = [...expectedNativeKnowledgeById.keys()]\n .filter((chunkId) =>\n actualNativeKnowledgeById.has(chunkId) && actualNativeKnowledgeById.get(chunkId) !== expectedNativeKnowledgeById.get(chunkId)\n )\n .sort();\n\n const expectedReviewQueueById = new Map(\n (snapshot.governance?.reviewQueueRows ?? []).map((row) => [\n `${row.runId}::${row.entryId}`,\n serializeGovernanceReviewQueueRow(row),\n ]),\n );\n const actualReviewQueueById = new Map(\n projectedGovernance.reviewQueueRows.map((row) => [\n `${row.runId}::${row.entryId}`,\n serializeGovernanceReviewQueueRow(row),\n ]),\n );\n const missingReviewQueueEntryIds = [...expectedReviewQueueById.keys()]\n .filter((entryId) => !actualReviewQueueById.has(entryId))\n .sort();\n const extraReviewQueueEntryIds = [...actualReviewQueueById.keys()]\n .filter((entryId) => !expectedReviewQueueById.has(entryId))\n .sort();\n const mismatchedReviewQueueEntryIds = [...expectedReviewQueueById.keys()]\n .filter((entryId) =>\n actualReviewQueueById.has(entryId) && actualReviewQueueById.get(entryId) !== expectedReviewQueueById.get(entryId)\n )\n .sort();\n\n return {\n outputPath,\n projectionExists,\n ok:\n projectionExists &&\n missingCurrentMemoryIds.length === 0 &&\n extraCurrentMemoryIds.length === 0 &&\n mismatchedCurrentMemoryIds.length === 0 &&\n missingTimelineEventIds.length === 0 &&\n extraTimelineEventIds.length === 0 &&\n missingEntityMentionKeys.length === 0 &&\n extraEntityMentionKeys.length === 0 &&\n mismatchedEntityMentionKeys.length === 0 &&\n missingNativeKnowledgeChunkIds.length === 0 &&\n extraNativeKnowledgeChunkIds.length === 0 &&\n mismatchedNativeKnowledgeChunkIds.length === 0 &&\n missingReviewQueueEntryIds.length === 0 &&\n extraReviewQueueEntryIds.length === 0 &&\n mismatchedReviewQueueEntryIds.length === 0,\n expectedCurrentRows: snapshot.scopedCurrentRows.length,\n actualCurrentRows: actualScopedCurrentRows.length,\n expectedTimelineRows: snapshot.scopedTimelineRows.length,\n actualTimelineRows: actualTimelineRows.length,\n expectedEntityMentionRows: snapshot.scopedEntityMentionRows.length,\n actualEntityMentionRows: actualScopedEntityMentionRows.length,\n expectedNativeKnowledgeRows: snapshot.nativeKnowledgeRows.length,\n actualNativeKnowledgeRows: projectedNativeKnowledge.rows.length,\n expectedReviewQueueRows: snapshot.governance?.reviewQueueRows.length ?? 0,\n actualReviewQueueRows: projectedGovernance.reviewQueueRows.length,\n missingCurrentMemoryIds,\n extraCurrentMemoryIds,\n mismatchedCurrentMemoryIds,\n missingTimelineEventIds,\n extraTimelineEventIds,\n missingEntityMentionKeys,\n extraEntityMentionKeys,\n mismatchedEntityMentionKeys,\n missingNativeKnowledgeChunkIds,\n extraNativeKnowledgeChunkIds,\n mismatchedNativeKnowledgeChunkIds,\n missingReviewQueueEntryIds,\n extraReviewQueueEntryIds,\n mismatchedReviewQueueEntryIds,\n usedLifecycleLedger: snapshot.usedLifecycleLedger,\n scope: snapshot.scope,\n };\n}\n\nexport async function repairMemoryProjection(\n options: RepairMemoryProjectionOptions,\n): Promise<RepairMemoryProjectionResult> {\n const dryRun = options.dryRun !== false;\n const verify = await verifyMemoryProjection(options);\n if (verify.ok) {\n return {\n dryRun,\n repaired: false,\n verify,\n };\n }\n if (dryRun) {\n return {\n dryRun: true,\n repaired: false,\n verify,\n };\n }\n\n const rebuild = await rebuildMemoryProjection({\n ...options,\n dryRun: false,\n });\n const verified = await verifyMemoryProjection(options);\n return {\n dryRun: false,\n repaired: verified.ok,\n verify: verified,\n rebuild,\n };\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/graph.ts"],"sourcesContent":["/**\n * Multi-Graph Memory (MAGMA/SYNAPSE-inspired, v8.2)\n *\n * Maintains three typed edge graphs:\n * entity.jsonl — memories sharing a named entity (entityRef)\n * time.jsonl — consecutive memories in the same thread/session\n * causal.jsonl — memories linked by causal language heuristics\n *\n * Stored under `<memoryDir>/state/graphs/`.\n * All writes are fail-open: errors are caught/logged, never thrown.\n */\n\nimport { appendFile, mkdir, readFile, stat } from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { GraphEdgeAppendError } from \"./graph-append-error.js\";\nimport { readEdgeConfidence } from \"./graph-edge-reinforcement.js\";\nimport { emitGraphEvent } from \"./graph-events.js\";\nimport type { GraphConstructionCapabilitySet } from \"./capabilities.js\";\nimport {\n ActivationPathTracker,\n compareActivationPathCandidates,\n reconstructActivationPath,\n type ActivationPathCandidate,\n type ActivationPredecessor,\n} from \"./graph-path-reconstruction.js\";\nexport { reconstructActivationPath, type ActivationPredecessor };\nimport {\n assertGraphLockHeld,\n GraphLockLostError,\n withGraphWriteLock,\n yieldForLockHeartbeat,\n} from \"./graph-write-lock.js\";\n\nexport type GraphType = \"entity\" | \"time\" | \"causal\";\n\nexport interface ActivationPath {\n /** Node ids from the seed (inclusive) to the reached node (inclusive). */\n nodeIds: string[];\n /** Edge confidences, parallel to the hops in {@link nodeIds}. */\n edgeConfidences: number[];\n /** Graph types, parallel to the hops in {@link nodeIds}. */\n graphTypes: GraphType[];\n}\n\nexport interface GraphEdge {\n from: string; // relative memory path (e.g. \"facts/2026-02-22/abc.md\")\n to: string; // relative memory path\n type: GraphType;\n weight: number; // 1.0 default, decay applied during traversal\n label: string; // entity name, threadId, or matched causal phrase\n ts: string; // ISO timestamp of edge creation\n\n // Issue #681 — edge confidence + reinforcement (PR 1/3: schema + primitive only).\n // Both fields are optional so existing edges without confidence still validate.\n // Treat a missing `confidence` as 1.0 (legacy behavior) at read sites.\n // PR 2/3 wires the maintenance decay job; PR 3/3 weights PageRank traversal by confidence.\n confidence?: number; // [0, 1]; missing = 1.0\n lastReinforcedAt?: string; // ISO timestamp of most recent reinforcement\n}\n\nexport interface GraphConfig {\n multiGraphMemoryEnabled: boolean;\n entityGraphEnabled: boolean;\n timeGraphEnabled: boolean;\n causalGraphEnabled: boolean;\n maxGraphTraversalSteps: number;\n graphActivationDecay: number;\n maxEntityGraphEdgesPerMemory: number;\n graphLateralInhibitionEnabled: boolean;\n graphLateralInhibitionBeta: number;\n graphLateralInhibitionTopM: number;\n /**\n * Issue #681 PR 3/3 — minimum edge confidence required for traversal.\n * Edges with confidence below this floor are pruned. Legacy edges\n * (no `confidence` field) are treated as 1.0 and always pass.\n * Range `[0, 1]`. Default 0.2.\n */\n graphTraversalConfidenceFloor: number;\n /**\n * Issue #681 PR 3/3 — number of PageRank-style refinement iterations\n * applied on top of BFS activation. Set to 0 to disable refinement\n * and return raw BFS scores. Default 8.\n */\n graphTraversalPageRankIterations: number;\n /**\n * Issue #1904 — incremental GraphIndex edge cache. When true (the default,\n * and the value when omitted), a single-writer edge append is pushed into the\n * warm edge cache in place (revalidated by file size for cross-process\n * coherence) instead of nulling the cache and paying a full 6 MB re-read +\n * parse on the next traversal. Set false to restore the pre-#1904\n * null-on-every-write behavior. Optional here (unlike the required\n * PluginConfig field parseConfig always sets) so GraphConfig can still be\n * constructed directly with a partial config; only an explicit `false` opts\n * out, so an omitted field keeps the incremental default.\n */\n graphEdgeCacheIncrementalEnabled?: boolean;\n}\n\n/** Default minimum edge confidence required for traversal (issue #681 PR 3/3). */\nexport const DEFAULT_GRAPH_TRAVERSAL_CONFIDENCE_FLOOR = 0.2;\n/** Default PageRank-style refinement iteration count (issue #681 PR 3/3). */\nexport const DEFAULT_GRAPH_TRAVERSAL_PAGERANK_ITERATIONS = 8;\n\n// Causal signal phrases — order matters (most specific first)\nexport const CAUSAL_PHRASES = [\"as a result\", \"led to\", \"because of\", \"therefore\", \"caused\", \"because\"];\n\nexport function graphsDir(memoryDir: string): string {\n return path.join(memoryDir, \"state\", \"graphs\");\n}\n\nexport function graphFilePath(memoryDir: string, type: GraphType): string {\n return path.join(graphsDir(memoryDir), `${type}.jsonl`);\n}\n\nexport async function ensureGraphsDir(memoryDir: string): Promise<void> {\n await mkdir(graphsDir(memoryDir), { recursive: true });\n}\n\n// Per-graph-file write lock lives in the graph-write-lock.ts sibling (the\n// in-process chain plus the cross-process advisory lock, issue #2330 round\n// N+18 A). Re-exported here because `@remnic/core/graph` is a public\n// subpath export whose consumers import `withGraphWriteLock` from it.\nexport { withGraphWriteLock, GraphLockLostError };\n\nexport async function appendEdge(memoryDir: string, edge: GraphEdge): Promise<void> {\n await ensureGraphsDir(memoryDir);\n const filePath = graphFilePath(memoryDir, edge.type);\n const line = `${JSON.stringify(edge)}\\n`;\n await withGraphWriteLock(filePath, async (lock) => {\n // Round N+19 A: never append into a file a peer that broke this lock may rename over.\n await assertGraphLockHeld(filePath, lock);\n await appendFile(filePath, line, \"utf8\");\n });\n // Emit edge-added event for SSE subscribers (issue #691 PR 5/5).\n // Fail-open: emitGraphEvent catches listener errors so a bad SSE client\n // can never surface into the extraction pipeline.\n emitGraphEvent(memoryDir, \"edge-added\", {\n source: edge.from,\n target: edge.to,\n kind: edge.type,\n weight: edge.weight,\n label: edge.label,\n confidence: typeof edge.confidence === \"number\" ? edge.confidence : 1.0,\n });\n}\nfunction isNodeError(err: unknown): err is NodeJS.ErrnoException {\n return typeof err === \"object\" && err !== null && \"code\" in err;\n}\n\nfunction parseEdgesJsonl(raw: string, expectedType: GraphType): GraphEdge[] {\n const edges: GraphEdge[] = [];\n for (const line of raw.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n if (isValidGraphEdge(parsed, expectedType)) {\n edges.push(parsed);\n }\n } catch {\n // skip corrupt lines — fail-open for partial JSONL recovery\n }\n }\n return edges;\n}\n\n/** Parse batch size at which locked-section parsing yields to the event loop\n * so the graph lock's heartbeat timer can fire (round N+19 A). */\nconst EDGE_PARSE_YIELD_BATCH = 5_000;\n\n/** Chunked {@link parseEdgesJsonl} yielding between batches; used by\n * {@link readEdgesStrict} (the locked-section reader) — the hot recall path\n * (`readEdges`) keeps the synchronous parse. */\nasync function parseEdgesJsonlYielding(raw: string, expectedType: GraphType): Promise<GraphEdge[]> {\n const lines = raw.split(\"\\n\");\n const edges: GraphEdge[] = [];\n for (let i = 0; i < lines.length; i += EDGE_PARSE_YIELD_BATCH) {\n if (i > 0) await yieldForLockHeartbeat();\n edges.push(...parseEdgesJsonl(lines.slice(i, i + EDGE_PARSE_YIELD_BATCH).join(\"\\n\"), expectedType));\n }\n return edges;\n}\n\n/**\n * Read all edges of a given type from the JSONL file.\n * Returns [] if the file doesn't exist or any read error occurs (fail-open).\n *\n * Production traversal callers (recall/PageRank) depend on this fail-open\n * posture so a temporarily missing or unreadable graph file never blocks\n * a recall. Maintenance jobs that need to distinguish ENOENT from real\n * I/O failures must use {@link readEdgesStrict} instead.\n */\nexport async function readEdges(memoryDir: string, type: GraphType): Promise<GraphEdge[]> {\n const filePath = graphFilePath(memoryDir, type);\n try {\n const raw = await readFile(filePath, \"utf8\");\n return parseEdgesJsonl(raw, type);\n } catch {\n return [];\n }\n}\n\n/**\n * Same as {@link readEdges} but only swallows `ENOENT`; all other read\n * errors (`EACCES`, `EIO`, …) are propagated. Used by the graph-edge\n * decay maintenance job so I/O outages surface as a failed run instead\n * of being silently reported as \"no edges to decay\" (issue #729 /\n * Codex P1, line 120).\n */\nexport async function readEdgesStrict(memoryDir: string, type: GraphType): Promise<GraphEdge[]> {\n const filePath = graphFilePath(memoryDir, type);\n try {\n const raw = await readFile(filePath, \"utf8\");\n return await parseEdgesJsonlYielding(raw, type);\n } catch (err) {\n if (isNodeError(err) && err.code === \"ENOENT\") {\n return [];\n }\n throw err;\n }\n}\n\n/**\n * Read edges from all enabled graph types.\n */\nexport async function readAllEdges(\n memoryDir: string,\n graphCaps: Pick<GraphConstructionCapabilitySet, \"entityGraph\" | \"timeGraph\" | \"causalGraph\">,\n): Promise<GraphEdge[]> {\n const parts: GraphEdge[][] = await Promise.all([\n graphCaps.entityGraph ? readEdges(memoryDir, \"entity\") : Promise.resolve([]),\n graphCaps.timeGraph ? readEdges(memoryDir, \"time\") : Promise.resolve([]),\n graphCaps.causalGraph ? readEdges(memoryDir, \"causal\") : Promise.resolve([]),\n ]);\n return parts.flat();\n}\n\nexport interface GraphHealthFileStats {\n type: GraphType;\n filePath: string;\n exists: boolean;\n totalLines: number;\n validEdges: number;\n corruptLines: number;\n uniqueNodes: number;\n}\n\nexport interface GraphHealthReport {\n generatedAt: string;\n enabledTypes: GraphType[];\n totals: {\n totalLines: number;\n validEdges: number;\n corruptLines: number;\n uniqueNodes: number;\n };\n files: GraphHealthFileStats[];\n repairGuidance?: string[];\n}\n\nfunction isValidGraphEdge(raw: unknown, expectedType: GraphType): raw is GraphEdge {\n if (!raw || typeof raw !== \"object\") return false;\n const edge = raw as Record<string, unknown>;\n return (\n edge.type === expectedType &&\n typeof edge.from === \"string\" &&\n edge.from.length > 0 &&\n typeof edge.to === \"string\" &&\n edge.to.length > 0 &&\n typeof edge.weight === \"number\" &&\n Number.isFinite(edge.weight) &&\n typeof edge.label === \"string\" &&\n typeof edge.ts === \"string\"\n );\n}\n\nexport async function analyzeGraphHealth(\n memoryDir: string,\n options?: {\n entityGraphEnabled?: boolean;\n timeGraphEnabled?: boolean;\n causalGraphEnabled?: boolean;\n includeRepairGuidance?: boolean;\n }\n): Promise<GraphHealthReport> {\n const enabledTypes: GraphType[] = [];\n if (options?.entityGraphEnabled !== false) enabledTypes.push(\"entity\");\n if (options?.timeGraphEnabled !== false) enabledTypes.push(\"time\");\n if (options?.causalGraphEnabled !== false) enabledTypes.push(\"causal\");\n\n const files: GraphHealthFileStats[] = [];\n const globalNodes = new Set<string>();\n\n for (const type of enabledTypes) {\n const filePath = graphFilePath(memoryDir, type);\n let exists = true;\n let totalLines = 0;\n let validEdges = 0;\n let corruptLines = 0;\n const nodes = new Set<string>();\n\n try {\n const raw = await readFile(filePath, \"utf8\");\n for (const line of raw.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n totalLines += 1;\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n if (!isValidGraphEdge(parsed, type)) {\n corruptLines += 1;\n continue;\n }\n validEdges += 1;\n nodes.add(parsed.from);\n nodes.add(parsed.to);\n globalNodes.add(parsed.from);\n globalNodes.add(parsed.to);\n } catch {\n corruptLines += 1;\n }\n }\n } catch {\n exists = false;\n }\n\n files.push({\n type,\n filePath,\n exists,\n totalLines,\n validEdges,\n corruptLines,\n uniqueNodes: nodes.size,\n });\n }\n\n const totals = files.reduce(\n (acc, item) => {\n acc.totalLines += item.totalLines;\n acc.validEdges += item.validEdges;\n acc.corruptLines += item.corruptLines;\n return acc;\n },\n {\n totalLines: 0,\n validEdges: 0,\n corruptLines: 0,\n uniqueNodes: globalNodes.size,\n }\n );\n totals.uniqueNodes = globalNodes.size;\n\n const report: GraphHealthReport = {\n generatedAt: new Date().toISOString(),\n enabledTypes,\n totals,\n files,\n };\n\n if (options?.includeRepairGuidance === true) {\n const guidance: string[] = [];\n if (totals.corruptLines > 0) {\n guidance.push(\n \"Corrupt graph lines detected: back up memory/state/graphs, then rebuild graphs from clean memory replay/extraction runs.\"\n );\n }\n if (totals.validEdges === 0) {\n guidance.push(\n \"No valid edges detected yet: run normal extraction traffic (or replay ingestion) to seed graph files.\"\n );\n }\n if (guidance.length > 0) report.repairGuidance = guidance;\n }\n\n return report;\n}\n\n/**\n * Detect causal signal phrases in text. Returns the first matched phrase, or null.\n */\nexport function detectCausalPhrase(text: string): string | null {\n const lower = text.toLowerCase();\n for (const phrase of CAUSAL_PHRASES) {\n if (lower.includes(phrase)) return phrase;\n }\n return null;\n}\n\n/**\n * GraphIndex — builds and updates the three memory graphs.\n *\n * Usage (orchestrator):\n * this.graphIndex = new GraphIndex(config.memoryDir, config);\n *\n * // After each memory write:\n * await this.graphIndex.onMemoryWritten(memoryPath, frontmatter, threadId, recentInThread);\n */\n/**\n * Identity of one graph JSONL file used to validate the incremental edge cache\n * (issue #1904). An absent file (ENOENT) is recorded as the all-zero sentinel\n * `{ size: 0, mtimeMs: 0, ino: 0 }` so a later peer creation (ino becomes\n * non-zero) is detected as a change.\n */\ninterface GraphFileMeta {\n size: number;\n mtimeMs: number;\n ino: number;\n}\n\nexport class GraphIndex {\n private readonly memoryDir: string;\n private readonly cfg: GraphConfig;\n\n // Cache for readAllEdges() result. With 30k+ entity edges (6 MB JSONL) the\n // file read + JSON parse takes 2-4 s per call. This instance-level cache\n // eliminates that overhead on every spreadingActivation() call; it is\n // invalidated (set to null) in onMemoryWritten() so new edges appear promptly.\n private edgeCache: {\n allEdges: GraphEdge[];\n loadedAt: number;\n // Per-file identity of each enabled graph file observed at load (issue\n // #1904). An incremental push is trusted only when every file's identity is\n // explained entirely by OUR own append: size grows by exactly the bytes we\n // appended and the inode is unchanged (a local append keeps the inode; an\n // external atomic temp+rename rewrite — e.g. the edge-decay job — changes\n // it). Untouched files must match size AND mtime AND inode exactly. This\n // closes the size-only holes Codex flagged: a peer append racing cache\n // construction, and an equal-length atomic rewrite (e.g. confidence\n // 0.9->0.8) that preserves byte length. Any divergence forces a full reload.\n meta: Partial<Record<GraphType, GraphFileMeta>>;\n } | null = null;\n private static readonly EDGE_CACHE_TTL_MS = 300_000; // 5 minutes\n\n constructor(memoryDir: string, cfg: GraphConfig) {\n this.memoryDir = memoryDir;\n this.cfg = cfg;\n }\n\n /** Clear the edge cache so the next spreadingActivation() re-reads from disk.\n * Call after any code path that appends edges outside of onMemoryWritten(). */\n invalidateEdgeCache(): void {\n this.edgeCache = null;\n }\n\n private async loadEdgesCached(): Promise<GraphEdge[]> {\n if (this.edgeCache && Date.now() - this.edgeCache.loadedAt < GraphIndex.EDGE_CACHE_TTL_MS) {\n return this.edgeCache.allEdges;\n }\n // Consistent snapshot (issue #1904, Codex): capture file identity BEFORE and\n // AFTER reading edges and retry if it changed, so `allEdges` and the recorded\n // `meta` baseline reflect the SAME on-disk state. Without this a peer append\n // landing mid-read would leave the cache holding edges that exclude the peer\n // edge while the baseline already counts its bytes — a later local append\n // would then pass the size-delta check and silently omit the peer edge.\n let allEdges: GraphEdge[] = [];\n let meta = await this.readEnabledGraphFileMeta();\n let stable = false;\n for (let attempt = 0; attempt < 3; attempt++) {\n const before = meta;\n allEdges = await readAllEdges(this.memoryDir, {\n entityGraph: this.cfg.entityGraphEnabled,\n timeGraph: this.cfg.timeGraphEnabled,\n causalGraph: this.cfg.causalGraphEnabled,\n });\n meta = await this.readEnabledGraphFileMeta();\n if (this.graphFileMetaEqual(before, meta)) {\n stable = true;\n break;\n }\n // A write landed during the read; the just-captured `meta` is the new\n // baseline for the next attempt's before-snapshot.\n }\n if (stable) {\n this.edgeCache = { allEdges, loadedAt: Date.now(), meta };\n } else {\n // Contended: a peer kept writing across every attempt, so the final\n // allEdges/meta pair is not guaranteed consistent. Serve THIS read's edges\n // (best effort) but do NOT poison the cache — leave it null so the next\n // call re-reads, instead of installing a baseline that could hide a peer\n // edge for the TTL (Codex).\n this.edgeCache = null;\n }\n return allEdges;\n }\n\n /**\n * Identity ({ size, mtimeMs, ino }) of each ENABLED graph file (issue #1904).\n * Missing files (ENOENT) and any stat error map to the all-zero sentinel so\n * the baseline is fail-open: a later revalidation sees a mismatch (or a peer\n * creation flipping ino from 0 to non-zero) and forces a full reload rather\n * than trusting a stale incremental push.\n */\n private async readEnabledGraphFileMeta(): Promise<Partial<Record<GraphType, GraphFileMeta>>> {\n const enabled: GraphType[] = [];\n if (this.cfg.entityGraphEnabled) enabled.push(\"entity\");\n if (this.cfg.timeGraphEnabled) enabled.push(\"time\");\n if (this.cfg.causalGraphEnabled) enabled.push(\"causal\");\n const meta: Partial<Record<GraphType, GraphFileMeta>> = {};\n for (const type of enabled) {\n try {\n const st = await stat(graphFilePath(this.memoryDir, type));\n meta[type] = { size: st.size, mtimeMs: st.mtimeMs, ino: Number(st.ino) };\n } catch {\n meta[type] = { size: 0, mtimeMs: 0, ino: 0 };\n }\n }\n return meta;\n }\n\n /** True iff both metadata maps carry identical identity for every key. */\n private graphFileMetaEqual(\n a: Partial<Record<GraphType, GraphFileMeta>>,\n b: Partial<Record<GraphType, GraphFileMeta>>,\n ): boolean {\n const types: GraphType[] = [\"entity\", \"time\", \"causal\"];\n for (const type of types) {\n const x = a[type];\n const y = b[type];\n if (!x && !y) continue;\n if (!x || !y) return false;\n if (x.size !== y.size || x.mtimeMs !== y.mtimeMs || x.ino !== y.ino) return false;\n }\n return true;\n }\n\n /**\n * Re-stat every graph file whose identity the cache just committed and return\n * false if any has moved since (issue #1904, Codex). Closes the validation→\n * in-place-push TOCTOU window: a peer process (concurrent CLI / daemon /\n * decay job) can append between edgeFilesUnchangedExceptOurAppends()'s final\n * stat and the allEdges.push(...). Without this re-check the cache would be\n * accepted with identity predating the peer write and miss the peer edge for\n * the TTL. A residual infinitesimal window (peer writes during this re-stat)\n * remains and is TTL-bounded.\n */\n private async edgeCacheIdentityUnchangedSinceCommit(): Promise<boolean> {\n if (!this.edgeCache) return false;\n for (const type of Object.keys(this.edgeCache.meta) as GraphType[]) {\n const committed = this.edgeCache.meta[type];\n if (!committed) continue;\n let cur: GraphFileMeta;\n try {\n const st = await stat(graphFilePath(this.memoryDir, type));\n cur = { size: st.size, mtimeMs: st.mtimeMs, ino: Number(st.ino) };\n } catch (err) {\n if ((err as NodeJS.ErrnoException)?.code === \"ENOENT\") {\n cur = { size: 0, mtimeMs: 0, ino: 0 };\n } else {\n return false;\n }\n }\n if (\n cur.size !== committed.size ||\n cur.mtimeMs !== committed.mtimeMs ||\n cur.ino !== committed.ino\n ) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Called after a memory is written to disk.\n *\n * Throws when an edge append fails (after logging): the merged-target rewrite\n * path depends on the rejection to restore the edges `removeNodeEdgesForRewrite`\n * dropped — swallowing here left that restore dead and the prior edge set\n * permanently lost (#2330). Fail-open is the CALLER's decision; the create\n * paths already catch (see persistence-index.buildGraphEdge).\n *\n * @param memoryPath - relative path from memoryDir (e.g. \"facts/2026-02-22/abc.md\")\n * @param entityRef - entityRef frontmatter field (if any)\n * @param content - full memory text (for causal detection)\n * @param created - ISO timestamp of this memory\n * @param threadId - current thread ID (for time graph)\n * @param recentInThread - paths of the N most-recent memories in this thread (for time graph)\n * @param entitySiblings - paths of other memories that share the same entityRef (for entity graph)\n */\n async onMemoryWritten(opts: {\n memoryPath: string;\n entityRef?: string;\n content: string;\n created: string;\n threadId?: string;\n recentInThread?: string[];\n entitySiblings?: string[];\n causalPredecessor?: string;\n /**\n * Optional frozen gate overrides (from GraphConstructionCapabilitySet).\n * When provided, these take precedence over `this.cfg` so the caller's\n * operation-scoped snapshot is the single source of truth (#1566).\n */\n graphCapsOverride?: {\n entityGraph: boolean;\n timeGraph: boolean;\n causalGraph: boolean;\n multiGraphMemory: boolean;\n };\n }): Promise<GraphEdge[]> {\n const g = opts.graphCapsOverride;\n const multiGraphOn = g ? g.multiGraphMemory : this.cfg.multiGraphMemoryEnabled;\n if (!multiGraphOn) return [];\n const entityOn = g ? g.entityGraph : this.cfg.entityGraphEnabled;\n const timeOn = g ? g.timeGraph : this.cfg.timeGraphEnabled;\n const causalOn = g ? g.causalGraph : this.cfg.causalGraphEnabled;\n const ts = new Date().toISOString();\n // Appended this call: warm-cache in-place push (#1904) + surgical rollback rows (N+14).\n const appended: GraphEdge[] = [];\n\n try {\n // Entity graph\n if (entityOn && opts.entityRef && opts.entitySiblings?.length) {\n const siblings = opts.entitySiblings.slice(0, this.cfg.maxEntityGraphEdgesPerMemory);\n for (const sibling of siblings) {\n const edge: GraphEdge = {\n from: opts.memoryPath,\n to: sibling,\n type: \"entity\",\n weight: 1.0,\n label: opts.entityRef,\n ts,\n };\n appended.push(edge);\n await appendEdge(this.memoryDir, edge);\n }\n }\n\n // Time graph — link to most recent memory in same thread\n if (timeOn && opts.threadId && opts.recentInThread?.length) {\n const predecessor = opts.recentInThread[opts.recentInThread.length - 1];\n if (predecessor && predecessor !== opts.memoryPath) {\n const edge: GraphEdge = {\n from: predecessor,\n to: opts.memoryPath,\n type: \"time\",\n weight: 1.0,\n label: opts.threadId,\n ts,\n };\n appended.push(edge);\n await appendEdge(this.memoryDir, edge);\n }\n }\n\n // Causal graph\n if (causalOn && opts.causalPredecessor) {\n const phrase = detectCausalPhrase(opts.content);\n if (phrase) {\n const edge: GraphEdge = {\n from: opts.causalPredecessor,\n to: opts.memoryPath,\n type: \"causal\",\n weight: 1.0,\n label: phrase,\n ts,\n };\n appended.push(edge);\n await appendEdge(this.memoryDir, edge);\n }\n }\n } catch (err) {\n // Log, then rethrow (#2330): the rewrite path's restore step only runs\n // when this rejection reaches its caller (fail-open callers catch). The\n // error carries the rows already appended (N+16 A) — surgical rollback.\n const { log } = await import(\"./logger.js\");\n log.warn(`[graph] onMemoryWritten error: ${err}`);\n throw new GraphEdgeAppendError(err, appended);\n } finally {\n // Edge-cache coherence (issue #1904). Legacy behavior nulled the cache on\n // every write, paying a 2-4 s full re-read + parse on the next traversal.\n if (!this.edgeCache || Date.now() - this.edgeCache.loadedAt >= GraphIndex.EDGE_CACHE_TTL_MS) {\n // Nothing warm, or the entry is past its 5-min TTL backstop — reload.\n this.edgeCache = null;\n } else if (this.cfg.graphEdgeCacheIncrementalEnabled === false) {\n // Rollback lever: restore the pre-#1904 null-on-every-write behavior.\n this.edgeCache = null;\n } else {\n // Trust an in-place push ONLY when WE are the sole writer since load:\n // every enabled graph file's on-disk size must equal our baseline plus\n // exactly the bytes we appended to it. A divergence means a peer process\n // (backup daemon / CLI / decay job) also wrote — force a full reload for\n // cross-process coherence. Any stat error fails open to a full reload.\n try {\n if (await this.edgeFilesUnchangedExceptOurAppends(appended)) {\n if (appended.length > 0) {\n this.edgeCache.allEdges.push(...appended);\n // Close the validation→push TOCTOU window (#1904, Codex): a peer\n // process can append between the validation stat above and this\n // in-place push. Re-verify every committed identity; if any file\n // moved, the cache would miss the peer edge for the TTL, so null\n // it and let the next traversal reload. (Skipped when this call\n // pushed nothing — no new window was opened, and the validation\n // already confirmed no peer wrote.)\n if (this.edgeCache && !(await this.edgeCacheIdentityUnchangedSinceCommit())) {\n this.edgeCache = null;\n }\n }\n } else {\n this.edgeCache = null;\n }\n } catch {\n this.edgeCache = null;\n }\n }\n }\n return appended;\n }\n\n /**\n * Cross-process coherence check for the incremental edge cache (issue #1904).\n *\n * Returns true iff every ENABLED graph file's current identity is explained\n * ENTIRELY by THIS call's own append — no other process wrote to any graph\n * file since load. Per file:\n * - inode must be unchanged. A local append (`appendFile`) keeps the inode;\n * an external atomic temp+rename rewrite (e.g. the edge-decay job) changes\n * it, so an inode change — even one that preserves byte length, such as\n * decaying confidence 0.9->0.8 — forces a reload (Codex).\n * - a file WE appended to (delta > 0): size must equal baseline + our exact\n * appended bytes. If it was absent at load (sentinel ino 0), our append\n * created it, so we accept size === delta and adopt the new identity.\n * - a file we did NOT touch (delta 0): size AND mtime must be unchanged, so\n * an in-place equal-length rewrite (mtime bump) or a peer append (size\n * bump) both force a reload.\n * On success it commits the new identity baseline so the next append\n * revalidates against post-this-write truth. Fail-open: an unreadable file\n * (non-ENOENT) returns false, forcing a full reload.\n */\n private async edgeFilesUnchangedExceptOurAppends(appended: GraphEdge[]): Promise<boolean> {\n if (!this.edgeCache) return false;\n const expectedDelta: Partial<Record<GraphType, number>> = {};\n for (const edge of appended) {\n const bytes = Buffer.byteLength(`${JSON.stringify(edge)}\\n`, \"utf8\");\n expectedDelta[edge.type] = (expectedDelta[edge.type] ?? 0) + bytes;\n }\n const enabled: GraphType[] = [];\n if (this.cfg.entityGraphEnabled) enabled.push(\"entity\");\n if (this.cfg.timeGraphEnabled) enabled.push(\"time\");\n if (this.cfg.causalGraphEnabled) enabled.push(\"causal\");\n const observed: Partial<Record<GraphType, GraphFileMeta>> = {};\n for (const type of enabled) {\n let cur: GraphFileMeta;\n try {\n const st = await stat(graphFilePath(this.memoryDir, type));\n cur = { size: st.size, mtimeMs: st.mtimeMs, ino: Number(st.ino) };\n } catch (err) {\n // An absent graph file (ENOENT) is the normal partially-populated state\n // (e.g. entity edges written before any causal edge): treat it as the\n // all-zero sentinel so the incremental cache stays warm. Only a genuine\n // stat failure forces a full reload (#1904, Codex).\n if ((err as NodeJS.ErrnoException)?.code === \"ENOENT\") {\n cur = { size: 0, mtimeMs: 0, ino: 0 };\n } else {\n return false;\n }\n }\n const base = this.edgeCache.meta[type] ?? { size: 0, mtimeMs: 0, ino: 0 };\n const delta = expectedDelta[type] ?? 0;\n if (delta > 0) {\n if (base.ino === 0) {\n // File was absent at load; our append created it. Accept iff its whole\n // size is exactly our appended bytes (nothing else wrote it).\n if (cur.ino === 0 || cur.size !== delta) return false;\n } else {\n // Existing file: our append keeps the inode and grows size by exactly\n // our bytes. An atomic rewrite (ino change) or a peer append (size\n // mismatch) both fail here.\n if (cur.ino !== base.ino || cur.size !== base.size + delta) return false;\n }\n } else {\n // Untouched file: identity must be byte-for-byte unchanged.\n if (cur.ino !== base.ino || cur.size !== base.size || cur.mtimeMs !== base.mtimeMs) {\n return false;\n }\n }\n observed[type] = cur;\n }\n this.edgeCache.meta = observed;\n return true;\n }\n\n /**\n * Spreading activation BFS (SYNAPSE-inspired).\n *\n * Starting from `seeds`, traverse the combined graph for up to `maxSteps` hops.\n * Each candidate gets an activation score = edge.weight × edgeConfidence × decay^hop.\n *\n * Issue #681 PR 3/3 — confidence-aware traversal:\n * - Each edge's `weight` is multiplied by its `confidence` (legacy edges\n * missing `confidence` are treated as 1.0, preserving prior behavior).\n * - Edges with `confidence < graphTraversalConfidenceFloor` are pruned and\n * contribute neither activation nor downstream neighbors.\n * - When `graphTraversalPageRankIterations > 0`, an additional PageRank-\n * style refinement pass redistributes activation along confidence-weighted\n * edges, sharpening the ranking among multi-hop candidates.\n * - Per-result provenance includes the highest-confidence edge that landed\n * on each candidate, so the X-ray surface can attribute pruning and\n * ranking decisions back to specific edges.\n *\n * @param seeds - initial memory paths to expand from (e.g. QMD top results)\n * @param maxSteps - max BFS hops (from config: maxGraphTraversalSteps)\n * @returns Array of {path, score, edgeConfidence, ...} sorted descending, not including seed paths\n */\n async spreadingActivation(\n seeds: string[],\n maxSteps?: number,\n opts?: {\n /**\n * Issue #681 — when `true`, bypasses the configured\n * `graphTraversalConfidenceFloor` and includes low-confidence\n * edges in traversal. Equivalent to forcing the floor to `0`.\n * Default `false` (floor from config is applied).\n */\n includeLowConfidence?: boolean;\n /** Record one shortest seed-to-candidate path in each result. */\n recordPaths?: boolean;\n /** Absolute deadline in ms-since-epoch for post-retrieval assembly. */\n deadlineAtMs?: number;\n }\n ): Promise<\n Array<{\n path: string;\n score: number;\n seed: string;\n hopDepth: number;\n decayedWeight: number;\n graphType: \"entity\" | \"time\" | \"causal\";\n /**\n * Confidence of the edge that produced this candidate's recorded\n * provenance (the strongest edge along the chosen entry path).\n * In `[0, 1]`. Legacy edges without `confidence` surface as 1.0.\n */\n edgeConfidence: number;\n activationPath?: ActivationPath | null;\n }>\n > {\n if (!this.cfg.multiGraphMemoryEnabled) return [];\n const steps = maxSteps ?? this.cfg.maxGraphTraversalSteps;\n const decay = this.cfg.graphActivationDecay;\n // When `includeLowConfidence` is set, use floor=0 so all edges\n // participate in traversal regardless of their decay state.\n // Otherwise clamp the configured floor into [0, 1] so misconfiguration\n // cannot (a) admit edges with negative confidence or (b) reject every\n // edge.\n const floor =\n opts?.includeLowConfidence === true ? 0 : clampConfidenceFloor(this.cfg.graphTraversalConfidenceFloor);\n const iterations = clampPageRankIterations(this.cfg.graphTraversalPageRankIterations);\n const recordPaths = opts?.recordPaths === true;\n const deadlineAtMs = opts?.deadlineAtMs;\n const deadlineExpired = (): boolean =>\n typeof deadlineAtMs === \"number\" && Date.now() >= deadlineAtMs;\n\n try {\n if (deadlineExpired()) return [];\n const allEdges = await this.loadEdgesCached();\n if (deadlineExpired()) return [];\n\n // Build adjacency index: from → edges, to → edges (bidirectional for entity/time, directional for causal).\n // Edges below the confidence floor are pruned at index time so neither\n // direct activation nor downstream BFS expansion can re-introduce them.\n const adj = new Map<string, GraphEdge[]>();\n for (let i = 0; i < allEdges.length; i += 1) {\n if ((i & 1023) === 0 && deadlineExpired()) return [];\n const edge = allEdges[i];\n const conf = readEdgeConfidence(edge);\n if (conf < floor) continue;\n if (!adj.has(edge.from)) adj.set(edge.from, []);\n adj.get(edge.from)!.push(edge);\n // Entity and time edges are bidirectional\n if (edge.type !== \"causal\") {\n if (!adj.has(edge.to)) adj.set(edge.to, []);\n adj.get(edge.to)!.push({ ...edge, from: edge.to, to: edge.from });\n }\n }\n const seedSet = new Set(seeds);\n const scores = new Map<string, number>(); // candidate path → accumulated activation score\n\n const provenance = new Map<\n string,\n {\n seed: string;\n hopDepth: number;\n decayedWeight: number;\n graphType: \"entity\" | \"time\" | \"causal\";\n edgeConfidence: number;\n pathKey: string;\n }\n >();\n let frontier = new Map<string, { node: string; seed: string; activation: number }>();\n const reachedBySeed = new Map<string, Set<string>>();\n const pathTracker = recordPaths ? new ActivationPathTracker(seeds) : null;\n const predecessors = pathTracker?.predecessors ?? null;\n for (const seed of seeds) {\n frontier.set(`${seed}\\0${seed}`, { node: seed, seed, activation: 1 });\n reachedBySeed.set(seed, new Set([seed]));\n }\n const finalizeScores = () => {\n const results = Array.from(scores.entries())\n .map(([p, score]) => ({\n path: p,\n score,\n seed: provenance.get(p)?.seed ?? \"\",\n hopDepth: provenance.get(p)?.hopDepth ?? 0,\n decayedWeight: provenance.get(p)?.decayedWeight ?? 0,\n graphType: provenance.get(p)?.graphType ?? \"entity\",\n edgeConfidence: provenance.get(p)?.edgeConfidence ?? 1,\n }))\n .sort((a, b) => {\n const scoreDelta = b.score - a.score;\n if (scoreDelta !== 0 || !recordPaths) return scoreDelta;\n return a.path < b.path ? -1 : a.path > b.path ? 1 : 0;\n });\n if (!recordPaths || !predecessors) return results;\n return results.map((result) => {\n const seed = provenance.get(result.path)?.seed;\n return {\n ...result,\n activationPath:\n seed === undefined ? null : reconstructActivationPath(seed, result.path, predecessors, steps),\n };\n });\n };\n\n for (let hop = 0; hop < steps && frontier.size > 0; hop++) {\n if (deadlineExpired()) return finalizeScores();\n const nextFrontier = new Map<string, { node: string; seed: string; activation: number }>();\n\n for (const { node, seed: sourceSeed, activation } of frontier.values()) {\n const edges = adj.get(node) ?? [];\n for (let i = 0; i < edges.length; i += 1) {\n if ((i & 1023) === 0 && deadlineExpired()) return finalizeScores();\n const edge = edges[i];\n const neighbor = edge.to === node ? edge.from : edge.to;\n const conf = readEdgeConfidence(edge);\n // Defense in depth: the adjacency build already drops sub-floor\n // edges, but if a synthesized reverse edge ever bypassed that\n // path, this guard keeps spreading activation honest.\n if (conf < floor) continue;\n const score = activation * edge.weight * conf * decay;\n const reachedForSeed = reachedBySeed.get(sourceSeed);\n if (reachedForSeed?.has(neighbor)) {\n continue;\n }\n const candidatePathKey =\n pathTracker && !seedSet.has(neighbor)\n ? pathTracker.consider(\n sourceSeed,\n node,\n neighbor,\n hop + 1,\n score,\n conf,\n edge.type,\n )\n : \"\";\n\n if (!seedSet.has(neighbor)) {\n const existing = scores.get(neighbor) ?? 0;\n scores.set(neighbor, existing + score);\n\n const prev = provenance.get(neighbor);\n const candidateWinner: ActivationPathCandidate = {\n hopDepth: hop + 1,\n landingStrength: score,\n pathKey: candidatePathKey,\n };\n const shouldReplace =\n !prev ||\n (recordPaths\n ? compareActivationPathCandidates(candidateWinner, {\n hopDepth: prev.hopDepth,\n landingStrength: prev.decayedWeight,\n pathKey: prev.pathKey,\n }) > 0\n : hop + 1 < prev.hopDepth ||\n (hop + 1 === prev.hopDepth && score > prev.decayedWeight));\n if (shouldReplace) {\n provenance.set(neighbor, {\n seed: sourceSeed,\n hopDepth: hop + 1,\n decayedWeight: score,\n graphType: edge.type,\n edgeConfidence: conf,\n pathKey: candidatePathKey,\n });\n }\n\n\n if (hop + 1 < steps) {\n const frontierKey = `${sourceSeed}\\0${neighbor}`;\n const existingFrontier = nextFrontier.get(frontierKey);\n if (existingFrontier) {\n existingFrontier.activation += score;\n } else {\n nextFrontier.set(frontierKey, {\n node: neighbor,\n seed: sourceSeed,\n activation: score,\n });\n }\n }\n }\n }\n }\n\n for (const { node, seed } of nextFrontier.values()) {\n reachedBySeed.get(seed)?.add(node);\n }\n frontier = nextFrontier;\n }\n\n // Issue #681 PR 3/3 — optional PageRank-style refinement.\n // Redistributes a node's accumulated activation along its outgoing\n // edges, weighted by edge confidence. Damping is fixed at the\n // canonical 0.85 so the ranking stays comparable across queries;\n // the `iterations` knob bounds compute, not behavior shape.\n if (!deadlineExpired() && iterations > 0 && scores.size > 1) {\n applyPageRankRefinement(scores, adj, {\n iterations,\n floor,\n damping: 0.85,\n deadlineAtMs,\n });\n }\n\n // Apply lateral inhibition if enabled (Synapse-inspired competitive suppression)\n if (deadlineExpired()) return finalizeScores();\n if (this.cfg.graphLateralInhibitionEnabled && scores.size > 1) {\n const inhibited = applyLateralInhibition(scores, {\n beta: this.cfg.graphLateralInhibitionBeta,\n topM: this.cfg.graphLateralInhibitionTopM,\n });\n for (const [k, v] of inhibited) {\n scores.set(k, v);\n }\n }\n\n return finalizeScores();\n } catch (err) {\n const { log } = await import(\"./logger.js\");\n log.warn(`[graph] spreadingActivation error: ${err}`);\n return [];\n }\n }\n}\n\n/**\n * Clamp `graphTraversalConfidenceFloor` into the legal range `[0, 1]`.\n * Non-finite or non-numeric values fall back to the documented default\n * so misconfiguration cannot silently disable the floor or reject every edge.\n *\n * Exported for tests; call sites in `spreadingActivation` use it to make\n * the contract explicit at every boundary.\n */\nexport function clampConfidenceFloor(raw: unknown): number {\n if (typeof raw !== \"number\" || !Number.isFinite(raw)) {\n return DEFAULT_GRAPH_TRAVERSAL_CONFIDENCE_FLOOR;\n }\n if (raw < 0) return 0;\n if (raw > 1) return 1;\n return raw;\n}\n\n/**\n * Clamp `graphTraversalPageRankIterations` into a non-negative integer.\n * Negative or non-finite values fall back to 0 (disable refinement) so\n * misconfiguration cannot stall recall in an unbounded loop.\n */\nexport function clampPageRankIterations(raw: unknown): number {\n if (typeof raw !== \"number\" || !Number.isFinite(raw)) return 0;\n if (raw <= 0) return 0;\n return Math.floor(raw);\n}\n\n/**\n * PageRank-style refinement on top of the BFS activation map.\n *\n * Each iteration redistributes a fraction of every node's score along\n * its outgoing edges, scaled by edge confidence. Confidence below\n * `floor` is filtered out before redistribution, mirroring the BFS\n * pruning rule. Mutates `scores` in place.\n *\n * Exported for tests; in production, call sites pass the same adjacency\n * map already used by BFS so behavior stays consistent.\n */\nexport function applyPageRankRefinement(\n scores: Map<string, number>,\n adj: Map<string, GraphEdge[]>,\n opts: { iterations: number; floor: number; damping: number; deadlineAtMs?: number }\n): void {\n const { iterations, floor, damping, deadlineAtMs } = opts;\n if (iterations <= 0 || scores.size === 0) return;\n const safeDamping = Math.min(1, Math.max(0, damping));\n const deadlineExpired = (): boolean =>\n typeof deadlineAtMs === \"number\" && Date.now() >= deadlineAtMs;\n\n // Pre-compute confidence-weighted out-edge totals for normalization.\n // Done once per refinement, not per iteration, since adjacency is\n // immutable inside the loop.\n //\n // Codex P1 (#735): the denominator MUST be computed over the same\n // eligible-neighbor set the iteration redistributes into — i.e.\n // edges whose neighbor is in `scores`. Counting edges-to-seeds (or\n // edges-to-unseen-nodes) in the denominator while dropping their\n // flow during iteration leaks `safeDamping × score` every pass and\n // collapses leaf candidates' scores instead of just re-ranking them.\n const eligible = (edge: GraphEdge, fromNode: string): boolean => {\n if (readEdgeConfidence(edge) < floor) return false;\n const neighbor = edge.to === fromNode ? edge.from : edge.to;\n return scores.has(neighbor);\n };\n const outboundTotal = new Map<string, number>();\n for (const [node, edges] of adj.entries()) {\n if (deadlineExpired()) return;\n if (!scores.has(node)) continue; // only candidate nodes redistribute\n let sum = 0;\n for (const edge of edges) {\n if (!eligible(edge, node)) continue;\n sum += readEdgeConfidence(edge) * edge.weight;\n }\n if (sum > 0) outboundTotal.set(node, sum);\n }\n\n for (let i = 0; i < iterations; i += 1) {\n if (deadlineExpired()) return;\n const next = new Map<string, number>();\n // Teleport / damping floor: every node retains `(1 - damping) * score`\n // of its current activation so dangling nodes do not bleed to zero.\n for (const [node, score] of scores) {\n next.set(node, (1 - safeDamping) * score);\n }\n for (const [node, score] of scores) {\n const outEdges = adj.get(node);\n const total = outboundTotal.get(node);\n // Dangling-node fallback: when a candidate has zero eligible\n // outflow (no in-scores neighbors above the floor), the\n // `safeDamping × score` portion would otherwise evaporate. Keep\n // it on `node` so total mass is conserved and the score reflects\n // the candidate's standing rather than its in-degree topology.\n if (!outEdges || outEdges.length === 0 || !total || total <= 0) {\n next.set(node, (next.get(node) ?? 0) + safeDamping * score);\n continue;\n }\n for (let edgeIndex = 0; edgeIndex < outEdges.length; edgeIndex += 1) {\n if ((edgeIndex & 1023) === 0 && deadlineExpired()) return;\n const edge = outEdges[edgeIndex];\n if (!eligible(edge, node)) continue;\n const conf = readEdgeConfidence(edge);\n const neighbor = edge.to === node ? edge.from : edge.to;\n const flow = safeDamping * score * ((conf * edge.weight) / total);\n next.set(neighbor, (next.get(neighbor) ?? 0) + flow);\n }\n }\n for (const [node, score] of next) {\n scores.set(node, score);\n }\n }\n}\n\n/**\n * Lateral inhibition (Synapse-inspired).\n *\n * For each node, the top-M higher-activation competitors exert inhibition\n * proportional to their activation difference. Output is clamped to [0, ∞).\n *\n * No sigmoid is applied here — downstream `normalizeGraphActivationScore`\n * already applies x/(1+x) soft squash, so adding a sigmoid would double-\n * normalize and cap graph influence at ~50%.\n *\n * Formula: u_hat_i = max(0, u_i - beta * sum_{k in top-M where u_k > u_i}(u_k - u_i))\n *\n * When beta=0 or topM=0, returns original scores unchanged (no-op).\n */\nexport function applyLateralInhibition(\n scores: Map<string, number>,\n opts: { beta: number; topM: number }\n): Map<string, number> {\n const { beta, topM } = opts;\n if (beta === 0 || topM === 0) return new Map(scores);\n\n const sorted = Array.from(scores.entries()).sort((a, b) => b[1] - a[1]);\n const topCompetitors = sorted.slice(0, topM);\n\n const result = new Map<string, number>();\n for (const [node, u] of scores) {\n let inhibition = 0;\n for (const [, uK] of topCompetitors) {\n if (uK > u) {\n inhibition += uK - u;\n }\n }\n result.set(node, Math.max(0, u - beta * inhibition));\n }\n\n return result;\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/json-store.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { Dirent } from \"node:fs\";\nimport {\n lstat,\n mkdir,\n open,\n readFile,\n readdir,\n rename,\n unlink,\n utimes,\n writeFile,\n type FileHandle,\n} from \"node:fs/promises\";\nimport path from \"node:path\";\n\nfunction hasErrorCode(error: unknown, code: string): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && (error as { code?: unknown }).code === code;\n}\n\nasync function listJsonFilesStrictInner(dir: string, allowMissingDirectory: boolean): Promise<string[]> {\n let entries: Dirent[];\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch (error) {\n if (allowMissingDirectory && hasErrorCode(error, \"ENOENT\")) return [];\n throw error;\n }\n const out: string[] = [];\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n out.push(...(await listJsonFilesStrictInner(fullPath, false)));\n } else if (entry.isFile() && entry.name.endsWith(\".json\")) {\n out.push(fullPath);\n }\n }\n return out.sort();\n}\n\nexport async function listJsonFilesStrict(\n dir: string,\n options: { allowMissingDirectory?: boolean } = {}\n): Promise<string[]> {\n return listJsonFilesStrictInner(dir, options.allowMissingDirectory === true);\n}\n\nexport async function listJsonFiles(dir: string): Promise<string[]> {\n try {\n return await listJsonFilesStrict(dir);\n } catch {\n return [];\n }\n}\n\nexport async function listNamedFiles(dir: string, fileName: string): Promise<string[]> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n const out: string[] = [];\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n out.push(...(await listNamedFiles(fullPath, fileName)));\n } else if (entry.isFile() && entry.name === fileName) {\n out.push(fullPath);\n }\n }\n return out.sort();\n } catch {\n return [];\n }\n}\n\nconst jsonStoreMutationTails = new Map<string, Promise<void>>();\n\nconst JSON_STORE_LOCK_RETRY_MS = 25;\nconst JSON_STORE_LOCK_STALE_MS = 60_000;\nconst JSON_STORE_LOCK_TIMEOUT_MS = 10_000;\n\ntype JsonStoreMutationLockTestHooks = {\n beforeLockOwnerWrite?: (lockPath: string, ownerToken: string) => Promise<void> | void;\n beforeLockOwnershipConfirm?: (lockPath: string, ownerToken: string) => Promise<void> | void;\n afterReclaimGuardWrite?: (reclaimPath: string, ownerToken: string) => Promise<void> | void;\n retryMs?: number;\n staleLockMs?: number;\n timeoutMs?: number;\n};\n\nlet jsonStoreMutationLockTestHooks: JsonStoreMutationLockTestHooks | null = null;\n\nexport function setJsonStoreMutationLockTestHooks(hooks: JsonStoreMutationLockTestHooks | null): void {\n jsonStoreMutationLockTestHooks = hooks;\n}\n\nfunction jsonStoreLockRetryMs(): number {\n return jsonStoreMutationLockTestHooks?.retryMs ?? JSON_STORE_LOCK_RETRY_MS;\n}\n\nfunction jsonStoreLockStaleMs(): number {\n return jsonStoreMutationLockTestHooks?.staleLockMs ?? JSON_STORE_LOCK_STALE_MS;\n}\n\nfunction jsonStoreLockTimeoutMs(): number {\n return jsonStoreMutationLockTestHooks?.timeoutMs ?? JSON_STORE_LOCK_TIMEOUT_MS;\n}\n\nasync function closeAndRemoveJsonStoreReclaimGuard(reclaimPath: string, reclaimHandle: FileHandle): Promise<void> {\n await reclaimHandle.close().catch(() => undefined);\n await unlink(reclaimPath).catch((error) => {\n if (!hasErrorCode(error, \"ENOENT\")) throw error;\n });\n}\n\nasync function removeStaleJsonStoreReclaimGuard(reclaimPath: string): Promise<void> {\n let initial: JsonStoreLockState;\n try {\n initial = await readJsonStoreLockState(reclaimPath);\n } catch (error) {\n if (hasErrorCode(error, \"ENOENT\")) return;\n throw error;\n }\n if (Date.now() - initial.mtimeMs <= jsonStoreLockStaleMs()) return;\n\n let ownerPid: number | undefined;\n try {\n const metadata = JSON.parse(initial.content) as { pid?: unknown };\n ownerPid = typeof metadata.pid === \"number\" && Number.isInteger(metadata.pid) ? metadata.pid : undefined;\n } catch {\n ownerPid = undefined;\n }\n if (ownerPid !== undefined && processIsRunning(ownerPid)) return;\n\n let confirmed: JsonStoreLockState;\n try {\n confirmed = await readJsonStoreLockState(reclaimPath);\n } catch (error) {\n if (hasErrorCode(error, \"ENOENT\")) return;\n throw error;\n }\n if (!sameJsonStoreLockState(initial, confirmed)) return;\n await unlink(reclaimPath).catch((error) => {\n if (!hasErrorCode(error, \"ENOENT\")) throw error;\n });\n}\n\nasync function acquireJsonStoreReclaimGuard(reclaimPath: string): Promise<FileHandle | undefined> {\n try {\n return await open(reclaimPath, \"wx\", 0o600);\n } catch (error) {\n if (!hasErrorCode(error, \"EEXIST\")) throw error;\n await removeStaleJsonStoreReclaimGuard(reclaimPath);\n try {\n return await open(reclaimPath, \"wx\", 0o600);\n } catch (retryError) {\n if (hasErrorCode(retryError, \"EEXIST\")) return undefined;\n throw retryError;\n }\n }\n}\n\nfunction waitForJsonStoreLock(): Promise<void> {\n const { promise, resolve } = Promise.withResolvers<void>();\n setTimeout(resolve, jsonStoreLockRetryMs());\n return promise;\n}\n\nfunction processIsRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return !hasErrorCode(error, \"ESRCH\");\n }\n}\n\ntype JsonStoreLockState = {\n mtimeMs: number;\n size: number;\n ino: number | undefined;\n content: string;\n};\n\nasync function readJsonStoreLockState(lockPath: string): Promise<JsonStoreLockState> {\n const lockStat = await lstat(lockPath);\n if (!lockStat.isFile()) {\n throw new Error(`JSON store mutation lock is not a regular file: ${lockPath}`);\n }\n return {\n mtimeMs: lockStat.mtimeMs,\n size: lockStat.size,\n ino: typeof lockStat.ino === \"number\" ? lockStat.ino : undefined,\n content: await readFile(lockPath, \"utf8\"),\n };\n}\n\nfunction sameJsonStoreLockState(left: JsonStoreLockState, right: JsonStoreLockState): boolean {\n return (\n left.mtimeMs === right.mtimeMs &&\n left.size === right.size &&\n left.ino === right.ino &&\n left.content === right.content\n );\n}\n\nasync function removeJsonStoreMutationLockIfOwned(lockPath: string, token: string): Promise<void> {\n try {\n const state = await readJsonStoreLockState(lockPath);\n const metadata = JSON.parse(state.content) as { token?: unknown };\n if (metadata.token === token) await unlink(lockPath);\n } catch (error) {\n if (!hasErrorCode(error, \"ENOENT\") && !(error instanceof SyntaxError)) throw error;\n }\n}\n\nasync function removeStaleJsonStoreLock(lockPath: string): Promise<void> {\n const reclaimPath = `${lockPath}.reclaim`;\n const reclaimHandle = await acquireJsonStoreReclaimGuard(reclaimPath);\n if (!reclaimHandle) return;\n try {\n await reclaimHandle.writeFile(JSON.stringify({ pid: process.pid }), \"utf8\");\n await jsonStoreMutationLockTestHooks?.afterReclaimGuardWrite?.(reclaimPath, String(process.pid));\n\n let initial: JsonStoreLockState;\n try {\n initial = await readJsonStoreLockState(lockPath);\n } catch (error) {\n if (hasErrorCode(error, \"ENOENT\")) return;\n throw error;\n }\n if (Date.now() - initial.mtimeMs <= jsonStoreLockStaleMs()) return;\n let ownerPid: number | undefined;\n try {\n const metadata = JSON.parse(initial.content) as { pid?: unknown };\n ownerPid = typeof metadata.pid === \"number\" && Number.isInteger(metadata.pid) ? metadata.pid : undefined;\n } catch {\n ownerPid = undefined;\n }\n if (ownerPid !== undefined && processIsRunning(ownerPid)) return;\n\n let confirmed: JsonStoreLockState;\n try {\n confirmed = await readJsonStoreLockState(lockPath);\n } catch (error) {\n if (hasErrorCode(error, \"ENOENT\")) return;\n throw error;\n }\n if (!sameJsonStoreLockState(initial, confirmed)) return;\n await unlink(lockPath).catch((error) => {\n if (!hasErrorCode(error, \"ENOENT\")) throw error;\n });\n } finally {\n await closeAndRemoveJsonStoreReclaimGuard(reclaimPath, reclaimHandle);\n }\n}\n\nasync function confirmJsonStoreMutationLockOwnership(\n lockPath: string,\n token: string,\n deadline: number\n): Promise<boolean> {\n const reclaimPath = `${lockPath}.reclaim`;\n while (true) {\n const reclaimHandle = await acquireJsonStoreReclaimGuard(reclaimPath);\n if (!reclaimHandle) {\n if (Date.now() >= deadline) return false;\n await waitForJsonStoreLock();\n continue;\n }\n try {\n try {\n const state = await readJsonStoreLockState(lockPath);\n const metadata = JSON.parse(state.content) as { token?: unknown };\n return metadata.token === token;\n } catch (error) {\n if (hasErrorCode(error, \"ENOENT\") || error instanceof SyntaxError) return false;\n throw error;\n }\n } finally {\n await closeAndRemoveJsonStoreReclaimGuard(reclaimPath, reclaimHandle);\n }\n }\n}\n\nasync function acquireJsonStoreMutationFileLock(key: string): Promise<() => Promise<void>> {\n const lockPath = `${path.resolve(key)}.mutation.lock`;\n await mkdir(path.dirname(lockPath), { recursive: true });\n const token = randomUUID();\n const deadline = Date.now() + jsonStoreLockTimeoutMs();\n while (true) {\n let handle: FileHandle;\n try {\n handle = await open(lockPath, \"wx\", 0o600);\n } catch (error) {\n if (!hasErrorCode(error, \"EEXIST\")) throw error;\n await removeStaleJsonStoreLock(lockPath).catch((staleError) => {\n if (!hasErrorCode(staleError, \"ENOENT\")) throw staleError;\n });\n if (Date.now() >= deadline) {\n throw new Error(`Timed out acquiring JSON store mutation lock: ${lockPath}`);\n }\n await waitForJsonStoreLock();\n continue;\n }\n try {\n await jsonStoreMutationLockTestHooks?.beforeLockOwnerWrite?.(lockPath, token);\n await handle.writeFile(JSON.stringify({ pid: process.pid, token }), \"utf8\");\n } finally {\n await handle.close().catch(() => undefined);\n }\n await jsonStoreMutationLockTestHooks?.beforeLockOwnershipConfirm?.(lockPath, token);\n\n if (!(await confirmJsonStoreMutationLockOwnership(lockPath, token, deadline))) {\n await removeJsonStoreMutationLockIfOwned(lockPath, token);\n if (Date.now() >= deadline) {\n throw new Error(`Timed out acquiring JSON store mutation lock: ${lockPath}`);\n }\n await waitForJsonStoreLock();\n continue;\n }\n\n const heartbeat = setInterval(\n () => {\n void readFile(lockPath, \"utf8\")\n .then((content) => {\n const metadata = JSON.parse(content) as { token?: unknown };\n if (metadata.token !== token) return;\n const now = new Date();\n return utimes(lockPath, now, now);\n })\n .catch(() => undefined);\n },\n Math.max(1, Math.floor(jsonStoreLockStaleMs() / 3))\n );\n heartbeat.unref();\n return async () => {\n clearInterval(heartbeat);\n try {\n const metadata = JSON.parse(await readFile(lockPath, \"utf8\")) as { token?: unknown };\n if (metadata.token === token) await unlink(lockPath);\n } catch (error) {\n if (!hasErrorCode(error, \"ENOENT\")) throw error;\n }\n };\n }\n}\n\nexport async function withJsonStoreMutationLock<T>(key: string, operation: () => Promise<T>): Promise<T> {\n const normalizedKey = path.resolve(key);\n const previous = jsonStoreMutationTails.get(normalizedKey) ?? Promise.resolve();\n const { promise: current, resolve: release } = Promise.withResolvers<void>();\n const tail = previous.catch(() => undefined).then(() => current);\n jsonStoreMutationTails.set(normalizedKey, tail);\n await previous.catch(() => undefined);\n let releaseFileLock: (() => Promise<void>) | undefined;\n try {\n releaseFileLock = await acquireJsonStoreMutationFileLock(normalizedKey);\n return await operation();\n } finally {\n try {\n await releaseFileLock?.();\n } finally {\n release();\n if (jsonStoreMutationTails.get(normalizedKey) === tail) {\n jsonStoreMutationTails.delete(normalizedKey);\n }\n }\n }\n}\n\nexport async function readJsonFile(filePath: string): Promise<unknown> {\n return JSON.parse(await readFile(filePath, \"utf8\")) as unknown;\n}\n\nexport async function writeJsonFileAtomic(filePath: string, value: unknown): Promise<void> {\n await mkdir(path.dirname(filePath), { recursive: true });\n const tempPath = `${filePath}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`;\n try {\n await writeFile(tempPath, JSON.stringify(value, null, 2), \"utf8\");\n await rename(tempPath, filePath);\n } catch (error) {\n await unlink(tempPath).catch(() => undefined);\n throw error;\n }\n}\n"],"mappings":"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","names":[]}