@remnic/core 9.69.22 → 9.69.24

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 (772) hide show
  1. package/dist/abstraction-nodes.js +3 -2
  2. package/dist/access-admin-ops-surface.d.ts +14 -12
  3. package/dist/access-admin-ops-surface.js +94 -91
  4. package/dist/access-authorization-probe.d.ts +14 -12
  5. package/dist/access-authorization-probe.js +95 -92
  6. package/dist/access-boundary.d.ts +14 -12
  7. package/dist/access-boundary.js +94 -91
  8. package/dist/access-citation-namespace.js +3 -3
  9. package/dist/access-cli.js +200 -195
  10. package/dist/access-cli.js.map +1 -1
  11. package/dist/access-coding-context-resolution.d.ts +2 -1
  12. package/dist/access-extraction-force-flush.d.ts +14 -12
  13. package/dist/access-extraction-force-flush.js +94 -91
  14. package/dist/access-health-types.d.ts +2 -1
  15. package/dist/access-http-briefing.d.ts +156 -0
  16. package/dist/access-http-briefing.js +233 -0
  17. package/dist/access-http-lcm-compaction.d.ts +14 -12
  18. package/dist/access-http-lifecycle-flush.d.ts +14 -12
  19. package/dist/access-http-offline-stream.d.ts +14 -12
  20. package/dist/access-http-query.d.ts +3 -2
  21. package/dist/access-http-query.js +96 -93
  22. package/dist/access-http.d.ts +15 -13
  23. package/dist/access-http.js +119 -114
  24. package/dist/access-identity-continuity-surface.d.ts +12 -10
  25. package/dist/access-identity-continuity-surface.js +94 -91
  26. package/dist/access-lcm-surface.d.ts +14 -12
  27. package/dist/access-lcm-surface.js +94 -91
  28. package/dist/access-mcp.d.ts +14 -12
  29. package/dist/access-mcp.js +105 -101
  30. package/dist/access-memory-search-fanout.d.ts +3 -2
  31. package/dist/{access-namespace-preflight-BMHhxoL9.d.ts → access-namespace-preflight-BsvmyENS.d.ts} +1 -1
  32. package/dist/access-namespace-preflight.d.ts +4 -3
  33. package/dist/access-namespace-preflight.js +94 -91
  34. package/dist/access-observe-transcript.d.ts +12 -10
  35. package/dist/access-observe-write-surface.d.ts +14 -12
  36. package/dist/access-observe-write-surface.js +94 -91
  37. package/dist/access-offline-manifest.d.ts +12 -10
  38. package/dist/access-offline-manifest.js +15 -15
  39. package/dist/access-operations-batch.js +99 -95
  40. package/dist/access-operations.d.ts +14 -12
  41. package/dist/access-operations.js +104 -100
  42. package/dist/access-recall-concurrency.d.ts +14 -12
  43. package/dist/access-recall-concurrency.js +94 -91
  44. package/dist/access-recall-response.d.ts +14 -12
  45. package/dist/access-recall-response.js +94 -91
  46. package/dist/access-recall-surface.d.ts +14 -12
  47. package/dist/access-recall-surface.js +94 -91
  48. package/dist/access-schema.js +8 -7
  49. package/dist/{access-service-BlsNXFwx.d.ts → access-service-DWdY9Mlk.d.ts} +7 -7
  50. package/dist/access-service-helpers.d.ts +14 -12
  51. package/dist/access-service.d.ts +14 -12
  52. package/dist/access-service.js +94 -91
  53. package/dist/access-surface-catalog.d.ts +14 -12
  54. package/dist/access-surface-catalog.js +97 -93
  55. package/dist/access-surface-catalog.js.map +1 -1
  56. package/dist/access-wearables-meetings-surface.d.ts +4 -3
  57. package/dist/action-confidence.d.ts +2 -1
  58. package/dist/active-memory-bridge.d.ts +2 -1
  59. package/dist/active-recall.d.ts +2 -1
  60. package/dist/active-recall.js +16 -13
  61. package/dist/active-recall.js.map +1 -1
  62. package/dist/adapters/index.js +7 -7
  63. package/dist/adapters/registry.js +3 -3
  64. package/dist/ambient-provenance.d.ts +2 -1
  65. package/dist/artifact-search.d.ts +2 -1
  66. package/dist/{auto-sync-GRUJFD2F.js → auto-sync-WNGG2GC2.js} +9 -9
  67. package/dist/behavior-learner.d.ts +2 -1
  68. package/dist/behavior-signals.d.ts +2 -1
  69. package/dist/bootstrap.d.ts +12 -10
  70. package/dist/briefing-window.d.ts +3 -2
  71. package/dist/briefing.d.ts +3 -2
  72. package/dist/briefing.js +36 -36
  73. package/dist/buffer-surprise-report.d.ts +2 -1
  74. package/dist/buffer-turn-helpers.d.ts +2 -1
  75. package/dist/buffer.d.ts +3 -2
  76. package/dist/buffer.js +13 -13
  77. package/dist/bulk-import/index.d.ts +4 -3
  78. package/dist/calibration.d.ts +2 -1
  79. package/dist/calibration.js +2 -1
  80. package/dist/calibration.js.map +1 -1
  81. package/dist/capabilities.d.ts +2 -1
  82. package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-YO5QJ6L3.js} +2 -2
  83. package/dist/{capsule-merge-SEHERWWP.js → capsule-merge-IPG4IOFP.js} +5 -5
  84. package/dist/{catalog-C1qHsGew.d.ts → catalog-CDZLyiXL.d.ts} +1 -1
  85. package/dist/causal-behavior.d.ts +2 -1
  86. package/dist/causal-behavior.js +4 -3
  87. package/dist/causal-behavior.js.map +1 -1
  88. package/dist/causal-chain.js +4 -3
  89. package/dist/causal-consolidation.d.ts +2 -1
  90. package/dist/causal-consolidation.js +42 -42
  91. package/dist/causal-retrieval.js +4 -3
  92. package/dist/causal-retrieval.js.map +1 -1
  93. package/dist/causal-trajectory-graph.d.ts +5 -2
  94. package/dist/causal-trajectory-graph.js +6 -2
  95. package/dist/causal-trajectory-graph.js.map +1 -1
  96. package/dist/causal-trajectory.js +3 -2
  97. package/dist/{chunk-KTVSPFCQ.js → chunk-22FVR2KE.js} +2 -2
  98. package/dist/{chunk-7Y5V3LAP.js → chunk-27QVNSQ3.js} +2 -2
  99. package/dist/{chunk-R7LY4YKF.js → chunk-2EKJDQZB.js} +2 -2
  100. package/dist/{chunk-FCATYKQA.js → chunk-2IOHTUP3.js} +263 -13
  101. package/dist/chunk-2IOHTUP3.js.map +1 -0
  102. package/dist/{chunk-HOUST5UX.js → chunk-2ITE4C2Z.js} +2 -2
  103. package/dist/{chunk-JOYC4RYC.js → chunk-2JVJ7UHC.js} +2 -2
  104. package/dist/{chunk-X2NFFBTO.js → chunk-2L5FSNPC.js} +7 -7
  105. package/dist/{chunk-DUAJKRR2.js → chunk-2SGLMP2E.js} +2 -2
  106. package/dist/{chunk-6FUMA6AA.js → chunk-2Z4GS5E6.js} +2 -2
  107. package/dist/{chunk-G6MXN2G5.js → chunk-37KUQPX4.js} +6 -6
  108. package/dist/{chunk-DDQQY2E3.js → chunk-3BTFBQLO.js} +7 -7
  109. package/dist/chunk-3BTFBQLO.js.map +1 -0
  110. package/dist/{chunk-UR6PBX2J.js → chunk-3K7V3HE6.js} +35 -60
  111. package/dist/chunk-3K7V3HE6.js.map +1 -0
  112. package/dist/{chunk-WKAXBXVA.js → chunk-3QQTXYZ6.js} +2 -2
  113. package/dist/{chunk-DJUKBGAD.js → chunk-46EST7JO.js} +5 -5
  114. package/dist/chunk-46EST7JO.js.map +1 -0
  115. package/dist/{chunk-4ZWCQJNM.js → chunk-46WM6JX2.js} +5 -5
  116. package/dist/{chunk-CASWJ2HM.js → chunk-46ZPIGWI.js} +3 -3
  117. package/dist/{chunk-HTIIXNJQ.js → chunk-4FIH6MPS.js} +6 -3
  118. package/dist/chunk-4FIH6MPS.js.map +1 -0
  119. package/dist/{chunk-MCA2X4WH.js → chunk-4IHBN6WU.js} +2 -2
  120. package/dist/{chunk-W7IGLX4G.js → chunk-4O6WRBGE.js} +7 -7
  121. package/dist/chunk-4O6WRBGE.js.map +1 -0
  122. package/dist/{chunk-FB7LAJQM.js → chunk-4TKJGOCJ.js} +2 -2
  123. package/dist/{chunk-H7BZBSP6.js → chunk-52II7PB6.js} +4 -4
  124. package/dist/{chunk-N4Y5T6VD.js → chunk-54WHLA65.js} +4 -4
  125. package/dist/chunk-56Y6EKZN.js +24 -0
  126. package/dist/chunk-56Y6EKZN.js.map +1 -0
  127. package/dist/{chunk-YVLENSNS.js → chunk-5ATKSPEQ.js} +2 -2
  128. package/dist/{chunk-OLT3YTDH.js → chunk-5FAGCOZD.js} +37 -24
  129. package/dist/chunk-5FAGCOZD.js.map +1 -0
  130. package/dist/{chunk-ZVZHG7AI.js → chunk-5UBH37SL.js} +3 -3
  131. package/dist/{chunk-N3WZU76A.js → chunk-66OJSCI6.js} +2 -2
  132. package/dist/{chunk-D35XLYQ7.js → chunk-6CVNSDCZ.js} +11 -11
  133. package/dist/{chunk-KA2HZCMG.js → chunk-6NXSYYGP.js} +2 -2
  134. package/dist/{chunk-2HIJHXB3.js → chunk-6WHJ2EAB.js} +2 -2
  135. package/dist/{chunk-ZZM476NV.js → chunk-6XL73HQ4.js} +4 -4
  136. package/dist/{chunk-EJ5RKUXW.js → chunk-AQ7SYDVO.js} +2 -2
  137. package/dist/{chunk-2Z3DG5CQ.js → chunk-B3O3IRZN.js} +2 -2
  138. package/dist/{chunk-P77QX3ID.js → chunk-B6O2YLUR.js} +21 -20
  139. package/dist/chunk-B6O2YLUR.js.map +1 -0
  140. package/dist/{chunk-RACZB5HT.js → chunk-BD7JTBYP.js} +4 -4
  141. package/dist/{chunk-I762GW7V.js → chunk-BLJWYCNO.js} +5 -5
  142. package/dist/{chunk-ACPCA4NO.js → chunk-BMWN7B3Y.js} +6 -6
  143. package/dist/chunk-BMWN7B3Y.js.map +1 -0
  144. package/dist/{chunk-2NLLXCJG.js → chunk-BXLOS5AJ.js} +2 -2
  145. package/dist/{chunk-KK66P5GQ.js → chunk-C553ZTLF.js} +46 -48
  146. package/dist/chunk-C553ZTLF.js.map +1 -0
  147. package/dist/{chunk-GCASGYIO.js → chunk-C7HJ3NEI.js} +2 -2
  148. package/dist/{chunk-C24UZSFW.js → chunk-CEH2AFXG.js} +6 -6
  149. package/dist/{chunk-WVGXCBOC.js → chunk-D5F7TKMH.js} +2 -2
  150. package/dist/chunk-DGS34QSY.js +141 -0
  151. package/dist/chunk-DGS34QSY.js.map +1 -0
  152. package/dist/{chunk-X7Y7WX73.js → chunk-DQEMWVMT.js} +1 -1
  153. package/dist/{chunk-2OXIPF3A.js → chunk-DZD3WGCD.js} +4 -4
  154. package/dist/{chunk-UMEOXLIZ.js → chunk-E2P7TZTF.js} +5 -5
  155. package/dist/{chunk-6FC3IZ26.js → chunk-EBA5DA77.js} +2 -2
  156. package/dist/{chunk-N7JK2RKG.js → chunk-EOQ6FSQP.js} +2 -2
  157. package/dist/chunk-EUT2WCWS.js +54 -0
  158. package/dist/chunk-EUT2WCWS.js.map +1 -0
  159. package/dist/{chunk-YNDLCWXS.js → chunk-EZ25VE3G.js} +4 -4
  160. package/dist/{chunk-XDMI5VKE.js → chunk-FVOP3NT7.js} +2 -2
  161. package/dist/{chunk-NRLELHAY.js → chunk-G7NYVKD6.js} +2 -2
  162. package/dist/{chunk-B3W7GWQB.js → chunk-GHTSNGBZ.js} +2 -2
  163. package/dist/chunk-GKCXTSFF.js +17 -0
  164. package/dist/chunk-GKCXTSFF.js.map +1 -0
  165. package/dist/{chunk-LUDBXTBJ.js → chunk-H272ZPQ3.js} +5 -5
  166. package/dist/{chunk-SN4JXNLL.js → chunk-H3TKENU4.js} +2 -2
  167. package/dist/{chunk-4HYNMLT6.js → chunk-H4SEGIZY.js} +2 -2
  168. package/dist/{chunk-ACZN5ZXD.js → chunk-H54VWRPS.js} +13 -13
  169. package/dist/{chunk-HTP6XRUI.js → chunk-HM7RHKS4.js} +2 -2
  170. package/dist/{chunk-Z3SQEEB6.js → chunk-HWLIMQE2.js} +2 -2
  171. package/dist/{chunk-NQFCLAYT.js → chunk-ICKJ52PE.js} +99 -322
  172. package/dist/chunk-ICKJ52PE.js.map +1 -0
  173. package/dist/{chunk-2QSZNTDO.js → chunk-JBPKEARU.js} +7 -7
  174. package/dist/{chunk-DK6GMO6D.js → chunk-JEC4DVM3.js} +16 -16
  175. package/dist/chunk-JEC4DVM3.js.map +1 -0
  176. package/dist/{chunk-ET2CNMLD.js → chunk-JN72EPOE.js} +2 -2
  177. package/dist/{chunk-U62OK7BB.js → chunk-JPKK466T.js} +188 -21
  178. package/dist/chunk-JPKK466T.js.map +1 -0
  179. package/dist/{chunk-JCCWJHOP.js → chunk-JYZSRNR7.js} +2 -2
  180. package/dist/{chunk-7D6HXODY.js → chunk-K7724CH2.js} +2 -2
  181. package/dist/{chunk-X33MJFD2.js → chunk-KAXCYM66.js} +3 -3
  182. package/dist/{chunk-7RRUHJPG.js → chunk-KB2G2I6Q.js} +3 -3
  183. package/dist/{chunk-ZXBTTMGZ.js → chunk-KEF46KL2.js} +5 -5
  184. package/dist/{chunk-5UZXUTVO.js → chunk-KNA3BXXL.js} +6 -2
  185. package/dist/chunk-KNA3BXXL.js.map +1 -0
  186. package/dist/{chunk-UWTDARPF.js → chunk-KTWG7CNY.js} +6 -6
  187. package/dist/{chunk-XQYTSZW3.js → chunk-L7Z57SID.js} +6 -6
  188. package/dist/{chunk-JMAG7WZ7.js → chunk-LO4UKPKX.js} +3 -3
  189. package/dist/{chunk-LDWIPYJ6.js → chunk-LS2FHUML.js} +3 -3
  190. package/dist/{chunk-GDB4J2H3.js → chunk-MPC7TYTZ.js} +2 -2
  191. package/dist/{chunk-2GF27PGH.js → chunk-MRPOZBJC.js} +3 -3
  192. package/dist/{chunk-BR3OOQZQ.js → chunk-MWN6QEI2.js} +2 -2
  193. package/dist/{chunk-NZGO2GKL.js → chunk-MY5EDR46.js} +4 -4
  194. package/dist/{chunk-LCMUZDBZ.js → chunk-N3ZOP7KC.js} +3 -3
  195. package/dist/{chunk-TVW4C7PV.js → chunk-NB3LRY4T.js} +6 -6
  196. package/dist/{chunk-QJCWK2A7.js → chunk-ND6IQGSZ.js} +2 -2
  197. package/dist/{chunk-NOB2T2FC.js → chunk-NHLLKEKK.js} +2 -2
  198. package/dist/{chunk-7GSSHAXC.js → chunk-NLYVH66G.js} +6 -6
  199. package/dist/chunk-NLYVH66G.js.map +1 -0
  200. package/dist/{chunk-EJIWBTVM.js → chunk-O6ZNNVSP.js} +2 -2
  201. package/dist/{chunk-AG46P24C.js → chunk-OB3XMWX5.js} +4 -4
  202. package/dist/{chunk-NYRB7BKY.js → chunk-OEYZXDQI.js} +6 -6
  203. package/dist/chunk-OEYZXDQI.js.map +1 -0
  204. package/dist/{chunk-46QMN7I7.js → chunk-PAZY2ZKP.js} +6 -6
  205. package/dist/{chunk-EF4JUM55.js → chunk-PX4UMA5Z.js} +2 -2
  206. package/dist/chunk-QLK3SL7Q.js +242 -0
  207. package/dist/chunk-QLK3SL7Q.js.map +1 -0
  208. package/dist/{chunk-GGYDJJBO.js → chunk-QOOBICJF.js} +5 -5
  209. package/dist/chunk-QOOBICJF.js.map +1 -0
  210. package/dist/{chunk-NNZFPYYX.js → chunk-R7QY5ZVB.js} +2 -2
  211. package/dist/{chunk-RO2X2EYM.js → chunk-R7RTXEYG.js} +2 -2
  212. package/dist/{chunk-3LJPSRAN.js → chunk-RBCQVOVJ.js} +3 -3
  213. package/dist/{chunk-N4F7ZSSG.js → chunk-RC5DXXWC.js} +2 -2
  214. package/dist/{chunk-VLAQV4HT.js → chunk-RJYJ7KR7.js} +1636 -611
  215. package/dist/chunk-RJYJ7KR7.js.map +1 -0
  216. package/dist/{chunk-5CF2R4NS.js → chunk-RKBLRTNT.js} +2 -2
  217. package/dist/{chunk-5QZR2RA3.js → chunk-ROBHL3GL.js} +2 -2
  218. package/dist/{chunk-D5ZNOKR7.js → chunk-S7T2TY65.js} +3 -3
  219. package/dist/{chunk-C2JCVZWX.js → chunk-SCXURCVT.js} +25 -13
  220. package/dist/chunk-SCXURCVT.js.map +1 -0
  221. package/dist/{chunk-3LADWWMA.js → chunk-SJDQ5RSN.js} +3 -3
  222. package/dist/{chunk-45XVII3J.js → chunk-SMWTZLHE.js} +99 -89
  223. package/dist/{chunk-45XVII3J.js.map → chunk-SMWTZLHE.js.map} +1 -1
  224. package/dist/{chunk-XOQGUGJL.js → chunk-SO7SV523.js} +1 -1
  225. package/dist/{chunk-XOQGUGJL.js.map → chunk-SO7SV523.js.map} +1 -1
  226. package/dist/{chunk-CHWUICVY.js → chunk-SV4Z2S67.js} +4 -4
  227. package/dist/{chunk-JHP45LO5.js → chunk-SVXJLDDC.js} +9 -7
  228. package/dist/{chunk-JHP45LO5.js.map → chunk-SVXJLDDC.js.map} +1 -1
  229. package/dist/{chunk-SEF4IOFE.js → chunk-SWIKABKI.js} +2 -2
  230. package/dist/{chunk-JRRQ747T.js → chunk-TBXAY2SS.js} +13 -13
  231. package/dist/{chunk-J6A3CX5N.js → chunk-TG3FAM2S.js} +33 -8
  232. package/dist/{chunk-J6A3CX5N.js.map → chunk-TG3FAM2S.js.map} +1 -1
  233. package/dist/{chunk-XZBXINXZ.js → chunk-TNSCIPBQ.js} +4 -4
  234. package/dist/{chunk-S37NN23M.js → chunk-TVEONGBU.js} +2 -2
  235. package/dist/{chunk-5RPMTFB6.js → chunk-TWF35IC6.js} +3 -3
  236. package/dist/{chunk-BZTJEILZ.js → chunk-U6N5IBVY.js} +2 -2
  237. package/dist/{chunk-7TUB6JWA.js → chunk-UCKYTA2T.js} +3 -3
  238. package/dist/{chunk-PPOT6SPR.js → chunk-UNNPNBR2.js} +11 -11
  239. package/dist/{chunk-KQAFEZQX.js → chunk-VDX2J7OX.js} +2 -2
  240. package/dist/{chunk-J2R275FN.js → chunk-VVX5PZFS.js} +4 -4
  241. package/dist/{chunk-ME35HVDJ.js → chunk-VYCOJKSX.js} +2 -2
  242. package/dist/{chunk-F5UWQ4LX.js → chunk-W24T5YMW.js} +2 -2
  243. package/dist/{chunk-HDQUQBPW.js → chunk-W3K3HITK.js} +2 -2
  244. package/dist/{chunk-GDASG7NC.js → chunk-W4F3C7N7.js} +2 -2
  245. package/dist/{chunk-LFK623SF.js → chunk-WJHGDE7X.js} +5 -5
  246. package/dist/{chunk-DP4EBV7C.js → chunk-WMLEPWMO.js} +16 -16
  247. package/dist/chunk-WMLEPWMO.js.map +1 -0
  248. package/dist/{chunk-3Q6RD76J.js → chunk-WQZZDN5M.js} +5 -5
  249. package/dist/{chunk-ZJWDWPX6.js → chunk-X5K5TAQZ.js} +4 -4
  250. package/dist/{chunk-ZL3XX5LW.js → chunk-XM24CDZX.js} +3 -3
  251. package/dist/{chunk-JTWZKNUH.js → chunk-XOVKXJEP.js} +3 -3
  252. package/dist/{chunk-OGTKQ5MJ.js → chunk-XSGUMQQQ.js} +62 -50
  253. package/dist/chunk-XSGUMQQQ.js.map +1 -0
  254. package/dist/{chunk-X5YYSAZX.js → chunk-XUE46UYW.js} +3 -3
  255. package/dist/{chunk-DJORULH3.js → chunk-YRLHEEQT.js} +2 -2
  256. package/dist/{chunk-TA7UZZMW.js → chunk-Z3O53WZR.js} +2 -2
  257. package/dist/{chunk-4LG4CPOC.js → chunk-Z6COGHHN.js} +2 -2
  258. package/dist/{chunk-RE3H6Y2X.js → chunk-ZIW5JVRM.js} +2 -2
  259. package/dist/{cli-BNtvR-nU.d.ts → cli-DD0P-lu8.d.ts} +6 -6
  260. package/dist/cli.d.ts +16 -14
  261. package/dist/cli.js +154 -149
  262. package/dist/coding/export-okf-codegraph.d.ts +2 -1
  263. package/dist/coding/export-okf-codegraph.js +37 -37
  264. package/dist/coding/pre-action-gate.d.ts +2 -1
  265. package/dist/coding/pre-action-gate.js +4 -3
  266. package/dist/commitment-ledger.js +3 -2
  267. package/dist/compounding/engine.d.ts +3 -2
  268. package/dist/compounding/engine.js +37 -37
  269. package/dist/compounding/preference-consolidator.d.ts +2 -1
  270. package/dist/compression-optimizer.d.ts +2 -1
  271. package/dist/config.d.ts +2 -1
  272. package/dist/config.js +16 -13
  273. package/dist/connectors/codex-materialize-runner.d.ts +2 -1
  274. package/dist/connectors/codex-materialize-runner.js +38 -38
  275. package/dist/connectors/codex-materialize.d.ts +2 -1
  276. package/dist/connectors/codex-materialize.js +4 -4
  277. package/dist/connectors/index.d.ts +2 -1
  278. package/dist/connectors/index.js +38 -38
  279. package/dist/consolidation-provenance-check.d.ts +3 -2
  280. package/dist/consolidation-provenance-check.js +4 -4
  281. package/dist/consolidation-undo.d.ts +3 -2
  282. package/dist/consolidation-undo.js +3 -3
  283. package/dist/contradiction/index.d.ts +4 -3
  284. package/dist/contradiction/index.js +9 -9
  285. package/dist/converge-config.d.ts +2 -1
  286. package/dist/convergence-refresh.d.ts +3 -2
  287. package/dist/convergence-refresh.js +38 -38
  288. package/dist/conversation-index/backend.d.ts +2 -1
  289. package/dist/conversation-index/chunker.d.ts +2 -1
  290. package/dist/conversation-index/faiss-adapter.d.ts +2 -1
  291. package/dist/conversation-index/indexer.d.ts +2 -1
  292. package/dist/conversation-index/search.d.ts +2 -1
  293. package/dist/corpus-watermark.d.ts +2 -1
  294. package/dist/corpus-watermark.js +38 -38
  295. package/dist/cross-lingual-recall.d.ts +2 -1
  296. package/dist/cue-anchors.js +4 -3
  297. package/dist/dashboard-runtime.js +2 -2
  298. package/dist/day-summary.d.ts +2 -1
  299. package/dist/deep-recall-http-glue.d.ts +14 -12
  300. package/dist/deep-recall-http-glue.js +9 -8
  301. package/dist/deep-recall-mcp-tools.d.ts +14 -12
  302. package/dist/deep-recall-policy-llm.d.ts +2 -1
  303. package/dist/deep-recall-seeds.d.ts +2 -1
  304. package/dist/deep-recall.js +2 -2
  305. package/dist/delinearize.d.ts +2 -1
  306. package/dist/dependency-propagation-config.d.ts +2 -1
  307. package/dist/{dependency-propagation-delivery-DjpUlhLi.d.ts → dependency-propagation-delivery-CQPCu0o5.d.ts} +1 -1
  308. package/dist/direct-answer-wiring.d.ts +2 -1
  309. package/dist/direct-answer.d.ts +2 -1
  310. package/dist/embedding-fallback.d.ts +2 -1
  311. package/dist/enrichment/index.d.ts +2 -1
  312. package/dist/entity-origin-fields.d.ts +2 -1
  313. package/dist/entity-retrieval.d.ts +3 -2
  314. package/dist/entity-retrieval.js +36 -36
  315. package/dist/entity-schema.d.ts +2 -1
  316. package/dist/episodic-context.d.ts +2 -1
  317. package/dist/eval-trajectory-contracts.d.ts +2 -1
  318. package/dist/eval-trajectory-store.d.ts +2 -1
  319. package/dist/eval-trajectory-store.js +4 -3
  320. package/dist/eval-trajectory.d.ts +2 -1
  321. package/dist/eval-trajectory.js +4 -3
  322. package/dist/evals.js +3 -2
  323. package/dist/event-order-recall.js +2 -2
  324. package/dist/explicit-capture.d.ts +12 -10
  325. package/dist/explicit-capture.js +10 -10
  326. package/dist/external-wiki-access.d.ts +14 -12
  327. package/dist/external-wiki-access.js +95 -92
  328. package/dist/external-wiki-collection-registration.d.ts +2 -1
  329. package/dist/external-wiki-collection.d.ts +2 -1
  330. package/dist/external-wiki-mcp-tools.d.ts +14 -12
  331. package/dist/extraction-error-classification.d.ts +2 -1
  332. package/dist/extraction-faithfulness.d.ts +2 -1
  333. package/dist/extraction-judge-telemetry.d.ts +2 -1
  334. package/dist/extraction-judge-training.d.ts +2 -1
  335. package/dist/extraction-judge.d.ts +2 -1
  336. package/dist/extraction-liveness.d.ts +2 -1
  337. package/dist/extraction-normalization.d.ts +2 -1
  338. package/dist/extraction-prompt.d.ts +2 -1
  339. package/dist/extraction-source-grounding-rules.d.ts +2 -1
  340. package/dist/extraction-source-grounding.d.ts +2 -1
  341. package/dist/extraction.d.ts +2 -1
  342. package/dist/extraction.js +43 -43
  343. package/dist/fallback-llm.d.ts +2 -1
  344. package/dist/{first-start-migration-KHIMCBIC.js → first-start-migration-RC345GPL.js} +6 -5
  345. package/dist/{first-start-migration-KHIMCBIC.js.map → first-start-migration-RC345GPL.js.map} +1 -1
  346. package/dist/{forget-2AE4MDK3.js → forget-SZ2BXDGF.js} +3 -3
  347. package/dist/{graph-444E-DrF.d.ts → graph-DRkl22KE.d.ts} +10 -12
  348. package/dist/graph-append-error.d.ts +40 -0
  349. package/dist/graph-append-error.js +8 -0
  350. package/dist/graph-dashboard-diff.d.ts +5 -2
  351. package/dist/graph-dashboard-key.d.ts +5 -2
  352. package/dist/graph-dashboard-parser.d.ts +5 -2
  353. package/dist/{graph-edge-decay-DGTBFALQ.js → graph-edge-decay-MKIRZ762.js} +10 -4
  354. package/dist/graph-edge-decay-MKIRZ762.js.map +1 -0
  355. package/dist/graph-edge-reinforcement.d.ts +5 -2
  356. package/dist/graph-jsonl.d.ts +82 -0
  357. package/dist/graph-jsonl.js +23 -0
  358. package/dist/graph-jsonl.js.map +1 -0
  359. package/dist/graph-path-reconstruction.d.ts +5 -2
  360. package/dist/graph-path-scoring.d.ts +5 -2
  361. package/dist/graph-snapshot.d.ts +5 -2
  362. package/dist/graph-snapshot.js +7 -3
  363. package/dist/graph-write-lock.d.ts +84 -0
  364. package/dist/graph-write-lock.js +15 -0
  365. package/dist/graph-write-lock.js.map +1 -0
  366. package/dist/graph.d.ts +5 -2
  367. package/dist/graph.js +10 -3
  368. package/dist/harmonic-construction.js +5 -4
  369. package/dist/harmonic-retrieval.js +5 -4
  370. package/dist/importance.d.ts +2 -1
  371. package/dist/importers/index.d.ts +2 -1
  372. package/dist/in-flight-reads.d.ts +2 -1
  373. package/dist/{index-CsUrdMyL.d.ts → index-C9VXenR8.d.ts} +2 -2
  374. package/dist/index.d.ts +39 -25
  375. package/dist/index.js +291 -284
  376. package/dist/intent.d.ts +2 -1
  377. package/dist/json-store.js +2 -1
  378. package/dist/lcm/engine.d.ts +2 -1
  379. package/dist/lcm/engine.js +3 -3
  380. package/dist/lcm/index.d.ts +2 -1
  381. package/dist/lcm/index.js +6 -6
  382. package/dist/lcm/tools.d.ts +2 -1
  383. package/dist/lifecycle.d.ts +2 -1
  384. package/dist/live-connectors-runner.d.ts +2 -1
  385. package/dist/live-connectors-runner.js +3 -2
  386. package/dist/local-llm.d.ts +2 -1
  387. package/dist/local-model-endpoint.d.ts +2 -1
  388. package/dist/location/index.d.ts +4 -3
  389. package/dist/location/index.js +39 -39
  390. package/dist/maintenance/memory-governance.d.ts +2 -1
  391. package/dist/maintenance/memory-governance.js +36 -36
  392. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +3 -2
  393. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +36 -36
  394. package/dist/maintenance/rebuild-memory-projection.d.ts +3 -2
  395. package/dist/maintenance/rebuild-memory-projection.js +37 -37
  396. package/dist/{maintenance-D1GRGLTE.d.ts → maintenance-C14sorKa.d.ts} +3 -3
  397. package/dist/mcp-memory-inspector-app.d.ts +14 -12
  398. package/dist/memory-action-policy.d.ts +2 -1
  399. package/dist/memory-cache.d.ts +2 -1
  400. package/dist/memory-controller.d.ts +2 -1
  401. package/dist/memory-lifecycle-ledger-utils.d.ts +2 -1
  402. package/dist/memory-projection-mutations.js +3 -3
  403. package/dist/memory-projection-store.d.ts +2 -1
  404. package/dist/memory-provenance.d.ts +2 -1
  405. package/dist/memory-snapshot.d.ts +2 -1
  406. package/dist/memory-subject-cli.d.ts +14 -12
  407. package/dist/memory-subject.d.ts +14 -12
  408. package/dist/memory-subject.js +5 -5
  409. package/dist/memory-worth-outcomes.d.ts +3 -2
  410. package/dist/models-json.d.ts +2 -1
  411. package/dist/namespaces/migrate.d.ts +4 -3
  412. package/dist/namespaces/migrate.js +37 -37
  413. package/dist/namespaces/principal.d.ts +2 -1
  414. package/dist/namespaces/search.d.ts +2 -1
  415. package/dist/namespaces/search.js +11 -11
  416. package/dist/namespaces/storage.d.ts +4 -3
  417. package/dist/namespaces/storage.js +36 -36
  418. package/dist/native-knowledge.d.ts +2 -1
  419. package/dist/objective-state-writers.js +4 -3
  420. package/dist/objective-state.js +3 -2
  421. package/dist/offline-sync-file-io.js +4 -3
  422. package/dist/offline-sync-impression-drain.d.ts +2 -1
  423. package/dist/offline-sync-impression-drain.js +7 -7
  424. package/dist/offline-sync.js +5 -4
  425. package/dist/operator-doctor-corpus.d.ts +2 -1
  426. package/dist/operator-doctor-corpus.js +39 -39
  427. package/dist/operator-doctor-replica.d.ts +2 -1
  428. package/dist/operator-toolkit.d.ts +6 -4
  429. package/dist/operator-toolkit.js +61 -58
  430. package/dist/orchestration/compression-guideline-coordinator.d.ts +3 -2
  431. package/dist/orchestration/maintenance.d.ts +5 -4
  432. package/dist/orchestration/maintenance.js +46 -46
  433. package/dist/{orchestrator-DeqaPGT5.d.ts → orchestrator-DgyvFfPR.d.ts} +9 -9
  434. package/dist/orchestrator.d.ts +12 -10
  435. package/dist/orchestrator.js +201 -196
  436. package/dist/page-versioning.d.ts +73 -4
  437. package/dist/page-versioning.js +11 -3
  438. package/dist/patterns-cli.d.ts +2 -1
  439. package/dist/{pipeline-umUzU0D1.d.ts → pipeline-DRUwHb1X.d.ts} +1 -1
  440. package/dist/policy-runtime.d.ts +2 -1
  441. package/dist/proactive-contention.d.ts +2 -1
  442. package/dist/provenance.d.ts +2 -1
  443. package/dist/{public-http-Bevrjll9.d.ts → public-http-C4i8Opxc.d.ts} +1 -1
  444. package/dist/{purge-OP6BEDFY.js → purge-TZKRE6ZQ.js} +5 -5
  445. package/dist/purge-TZKRE6ZQ.js.map +1 -0
  446. package/dist/{qmd-BasT78PP.d.ts → qmd-BVWlg1YS.d.ts} +1 -1
  447. package/dist/qmd-preflight.d.ts +3 -2
  448. package/dist/qmd-recall-cache.d.ts +2 -1
  449. package/dist/qmd.d.ts +3 -2
  450. package/dist/qmd.js +4 -4
  451. package/dist/recall-concurrency-config.d.ts +2 -1
  452. package/dist/recall-disclosure-escalation.d.ts +2 -1
  453. package/dist/recall-explain-renderer.d.ts +2 -1
  454. package/dist/recall-explain-renderer.js +3 -3
  455. package/dist/recall-memory-map.d.ts +2 -1
  456. package/dist/recall-navigate-access.d.ts +2 -1
  457. package/dist/recall-navigate-access.js +2 -2
  458. package/dist/recall-navigate-disclosure.d.ts +2 -1
  459. package/dist/recall-navigate-disclosure.js +1 -1
  460. package/dist/recall-navigate.d.ts +2 -1
  461. package/dist/recall-navigate.js +2 -2
  462. package/dist/recall-planner-llm.d.ts +2 -1
  463. package/dist/recall-state.d.ts +2 -1
  464. package/dist/recall-state.js +3 -3
  465. package/dist/recall-tag-filter.d.ts +2 -1
  466. package/dist/recall-timings.d.ts +2 -1
  467. package/dist/recall-xray-cli.d.ts +2 -1
  468. package/dist/recall-xray-cli.js +4 -4
  469. package/dist/recall-xray-renderer.d.ts +2 -1
  470. package/dist/recall-xray-renderer.js +3 -3
  471. package/dist/recall-xray.d.ts +2 -1
  472. package/dist/recall-xray.js +2 -2
  473. package/dist/reconcile/cursor.d.ts +2 -1
  474. package/dist/reconcile/manifest.d.ts +2 -1
  475. package/dist/reconcile/manifest.js +7 -7
  476. package/dist/reconcile/plan.d.ts +2 -1
  477. package/dist/replay/normalizers/chatgpt.d.ts +2 -1
  478. package/dist/replay/normalizers/claude.d.ts +2 -1
  479. package/dist/replay/normalizers/openclaw.d.ts +2 -1
  480. package/dist/replay/normalizers/shared.d.ts +2 -1
  481. package/dist/replay/runner.d.ts +2 -1
  482. package/dist/replay/types.d.ts +2 -1
  483. package/dist/replica-divergence.d.ts +2 -1
  484. package/dist/replica-peers-config.d.ts +2 -1
  485. package/dist/{resolution-4DLI3IOR.js → resolution-VKATP2HT.js} +10 -10
  486. package/dist/resolution-VKATP2HT.js.map +1 -0
  487. package/dist/resolve-auth-token.d.ts +2 -1
  488. package/dist/resume-bundles.js +21 -18
  489. package/dist/retrieval-agents.d.ts +3 -2
  490. package/dist/retrieval-tiers.d.ts +2 -1
  491. package/dist/routing/engine.d.ts +2 -1
  492. package/dist/routing/store.d.ts +2 -1
  493. package/dist/salvage-envelope.d.ts +2 -1
  494. package/dist/salvage-envelope.js +7 -7
  495. package/dist/{scope-profiles-DXYzyOXW.d.ts → scope-profiles-Vl00B1KU.d.ts} +1 -1
  496. package/dist/search/document-scanner.js +3 -3
  497. package/dist/search/embed-helper.d.ts +2 -1
  498. package/dist/search/factory.d.ts +2 -1
  499. package/dist/search/factory.js +10 -10
  500. package/dist/search/index.d.ts +2 -1
  501. package/dist/search/index.js +16 -16
  502. package/dist/search/lancedb-backend.d.ts +2 -1
  503. package/dist/search/lancedb-backend.js +4 -4
  504. package/dist/search/meilisearch-backend.d.ts +2 -1
  505. package/dist/search/meilisearch-backend.js +4 -4
  506. package/dist/search/noop-backend.d.ts +2 -1
  507. package/dist/search/orama-backend.d.ts +2 -1
  508. package/dist/search/orama-backend.js +4 -4
  509. package/dist/search/port.d.ts +2 -1
  510. package/dist/search/remote-backend.d.ts +2 -1
  511. package/dist/secure-store/index.js +3 -3
  512. package/dist/{semantic-consolidation-CqDeaY0U.d.ts → semantic-consolidation-BC9-GFuT.d.ts} +1 -1
  513. package/dist/semantic-consolidation.d.ts +3 -2
  514. package/dist/semantic-consolidation.js +39 -39
  515. package/dist/semantic-merge-config.d.ts +17 -0
  516. package/dist/semantic-merge-config.js +1 -0
  517. package/dist/semantic-merge-config.js.map +1 -0
  518. package/dist/semantic-rule-promotion.js +36 -36
  519. package/dist/semantic-rule-verifier.d.ts +2 -1
  520. package/dist/semantic-rule-verifier.js +36 -36
  521. package/dist/{service-BKD-DVYZ.d.ts → service-BOy6dHfc.d.ts} +2 -2
  522. package/dist/session-observer-bands.d.ts +2 -1
  523. package/dist/session-observer-state.d.ts +2 -1
  524. package/dist/shared-context/manager.d.ts +2 -1
  525. package/dist/signal.d.ts +2 -1
  526. package/dist/source-agent-qualifier.d.ts +2 -1
  527. package/dist/source-agent-qualifier.js +42 -42
  528. package/dist/source-attribution.d.ts +18 -6
  529. package/dist/source-attribution.js +3 -1
  530. package/dist/standup/build.js +36 -36
  531. package/dist/{storage-BcFd1lN_.d.ts → storage-BLJRnFi6.d.ts} +15 -8
  532. package/dist/storage.d.ts +3 -2
  533. package/dist/storage.js +35 -35
  534. package/dist/subject-config.d.ts +2 -1
  535. package/dist/subject-config.js +6 -6
  536. package/dist/summarizer.d.ts +2 -1
  537. package/dist/summary-snapshot.d.ts +2 -1
  538. package/dist/support-passport/index.d.ts +17 -15
  539. package/dist/support-passport/index.js +97 -94
  540. package/dist/temporal-supersession.d.ts +3 -2
  541. package/dist/temporal-timeline-recall.d.ts +2 -1
  542. package/dist/temporal-validity.d.ts +2 -1
  543. package/dist/threading.d.ts +2 -1
  544. package/dist/tier-migration.d.ts +3 -2
  545. package/dist/tier-routing.d.ts +2 -1
  546. package/dist/{tier-stats-2TOW3QNL.js → tier-stats-KA6OZX2C.js} +6 -5
  547. package/dist/{tier-stats-2TOW3QNL.js.map → tier-stats-KA6OZX2C.js.map} +1 -1
  548. package/dist/topics.d.ts +2 -1
  549. package/dist/transcript.d.ts +2 -1
  550. package/dist/transfer/backup.js +2 -2
  551. package/dist/transfer/capsule-export.js +2 -2
  552. package/dist/transfer/capsule-import.js +6 -6
  553. package/dist/transfer/export-okf.d.ts +2 -1
  554. package/dist/transfer/export-okf.js +37 -37
  555. package/dist/trust-score-stage.d.ts +2 -1
  556. package/dist/trust-score.d.ts +2 -1
  557. package/dist/trust-zones.js +3 -2
  558. package/dist/{types-BRg3tMyp.d.ts → types-YY-eKKU7.d.ts} +3 -0
  559. package/dist/types.d.ts +2 -1
  560. package/dist/types.js +1 -1
  561. package/dist/utility-learner.js +4 -3
  562. package/dist/utility-runtime.d.ts +2 -1
  563. package/dist/utility-runtime.js +5 -4
  564. package/dist/utility-telemetry.js +3 -2
  565. package/dist/verified-recall.js +36 -36
  566. package/dist/who-knows-cli.d.ts +14 -12
  567. package/dist/who-knows-cli.js +37 -37
  568. package/dist/who-knows.d.ts +14 -12
  569. package/dist/who-knows.js +36 -36
  570. package/dist/work/board.js +3 -3
  571. package/dist/work/storage.js +2 -2
  572. package/dist/work-product-ledger.js +3 -2
  573. package/dist/write-envelope.d.ts +2 -1
  574. package/dist/write-envelope.js +6 -6
  575. package/package.json +2 -2
  576. package/src/abstraction-nodes.ts +1 -4
  577. package/src/access-http-briefing.ts +35 -0
  578. package/src/access-http.test.ts +76 -0
  579. package/src/access-http.ts +20 -23
  580. package/src/access-surface-catalog.test.ts +9 -0
  581. package/src/access-surface-catalog.ts +1 -0
  582. package/src/binary-lifecycle/backend.ts +2 -1
  583. package/src/config.ts +2 -0
  584. package/src/connectors/live/github.ts +10 -17
  585. package/src/connectors/live/gmail.ts +8 -19
  586. package/src/connectors/live/google-drive.ts +6 -13
  587. package/src/connectors/live/notion.ts +11 -21
  588. package/src/cue-anchors.ts +1 -6
  589. package/src/dedup/connector-scope.ts +39 -0
  590. package/src/dedup/merge-content.test.ts +21 -0
  591. package/src/dedup/merge-content.ts +21 -7
  592. package/src/dedup/merge-judge.ts +146 -0
  593. package/src/dedup/merge.test.ts +3542 -0
  594. package/src/dedup/merge.ts +384 -0
  595. package/src/dedup/novelty-gate.ts +12 -10
  596. package/src/dedup/semantic.ts +7 -9
  597. package/src/graph-append-error.ts +28 -0
  598. package/src/graph-jsonl.ts +267 -0
  599. package/src/graph-write-lock.test.ts +228 -0
  600. package/src/graph-write-lock.ts +132 -0
  601. package/src/graph.ts +49 -45
  602. package/src/harmonic-construction.test.ts +329 -0
  603. package/src/json-store.ts +17 -20
  604. package/src/live-connectors-runner.ts +2 -1
  605. package/src/location/store.ts +1 -4
  606. package/src/maintenance/graph-edge-decay.ts +24 -13
  607. package/src/maintenance/purge.ts +2 -5
  608. package/src/maintenance/rebuild-memory-lifecycle-ledger.ts +3 -6
  609. package/src/maintenance/rebuild-memory-projection.ts +2 -5
  610. package/src/namespaces/catalog.ts +1 -9
  611. package/src/offline-sync-file-io.test.ts +39 -0
  612. package/src/offline-sync-file-io.ts +3 -7
  613. package/src/orchestration/contradiction-localization.integration.test.ts +35 -0
  614. package/src/orchestration/extraction-anchor-snapshot.ts +6 -1
  615. package/src/orchestration/extraction-persist-deps.ts +2 -1
  616. package/src/orchestration/extraction-persist-profile-promotion.test.ts +456 -0
  617. package/src/orchestration/extraction-persist-promotion.test.ts +534 -0
  618. package/src/orchestration/extraction-persist-promotion.ts +387 -1
  619. package/src/orchestration/extraction-persist.ts +95 -94
  620. package/src/orchestration/harmonic-construction-persist.test.ts +69 -0
  621. package/src/orchestration/harmonic-construction-persist.ts +55 -0
  622. package/src/orchestration/persistence-index.ts +35 -7
  623. package/src/orchestration/semantic-merge-commit-effects.ts +354 -0
  624. package/src/orchestration/semantic-merge-persist.ts +1095 -0
  625. package/src/orchestration/semantic-merge-promotion-payload.ts +161 -0
  626. package/src/orchestrator.ts +2 -2
  627. package/src/page-versioning.ts +396 -22
  628. package/src/procedural/procedure-miner.ts +1 -9
  629. package/src/search/document-scanner.ts +3 -6
  630. package/src/semantic-merge-config.ts +16 -0
  631. package/src/semantic-rule-promotion.ts +1 -4
  632. package/src/source-attribution-roundtrip.test.ts +21 -0
  633. package/src/source-attribution.ts +57 -17
  634. package/src/storage-contract/versioning.test.ts +500 -1
  635. package/src/storage.ts +30 -30
  636. package/src/testing/subjects/graph-edge-decay.test.ts +163 -0
  637. package/src/testing/subjects/semantic-merge-lifecycle.test.ts +1175 -0
  638. package/src/types.ts +2 -0
  639. package/src/utils/errno.test.ts +31 -0
  640. package/src/utils/errno.ts +5 -0
  641. package/src/wearables/index.ts +1 -0
  642. package/src/wearables/registry.ts +23 -0
  643. package/dist/chunk-5UZXUTVO.js.map +0 -1
  644. package/dist/chunk-7GSSHAXC.js.map +0 -1
  645. package/dist/chunk-ACPCA4NO.js.map +0 -1
  646. package/dist/chunk-C2JCVZWX.js.map +0 -1
  647. package/dist/chunk-DDQQY2E3.js.map +0 -1
  648. package/dist/chunk-DJUKBGAD.js.map +0 -1
  649. package/dist/chunk-DK6GMO6D.js.map +0 -1
  650. package/dist/chunk-DP4EBV7C.js.map +0 -1
  651. package/dist/chunk-FCATYKQA.js.map +0 -1
  652. package/dist/chunk-GGYDJJBO.js.map +0 -1
  653. package/dist/chunk-HTIIXNJQ.js.map +0 -1
  654. package/dist/chunk-KK66P5GQ.js.map +0 -1
  655. package/dist/chunk-NQFCLAYT.js.map +0 -1
  656. package/dist/chunk-NYRB7BKY.js.map +0 -1
  657. package/dist/chunk-OGTKQ5MJ.js.map +0 -1
  658. package/dist/chunk-OLT3YTDH.js.map +0 -1
  659. package/dist/chunk-P77QX3ID.js.map +0 -1
  660. package/dist/chunk-U62OK7BB.js.map +0 -1
  661. package/dist/chunk-UR6PBX2J.js.map +0 -1
  662. package/dist/chunk-VLAQV4HT.js.map +0 -1
  663. package/dist/chunk-W7IGLX4G.js.map +0 -1
  664. package/dist/purge-OP6BEDFY.js.map +0 -1
  665. /package/dist/{capsule-crypto-7FJQINUR.js.map → access-http-briefing.js.map} +0 -0
  666. /package/dist/{auto-sync-GRUJFD2F.js.map → auto-sync-WNGG2GC2.js.map} +0 -0
  667. /package/dist/{graph-edge-decay-DGTBFALQ.js.map → capsule-crypto-YO5QJ6L3.js.map} +0 -0
  668. /package/dist/{capsule-merge-SEHERWWP.js.map → capsule-merge-IPG4IOFP.js.map} +0 -0
  669. /package/dist/{chunk-KTVSPFCQ.js.map → chunk-22FVR2KE.js.map} +0 -0
  670. /package/dist/{chunk-7Y5V3LAP.js.map → chunk-27QVNSQ3.js.map} +0 -0
  671. /package/dist/{chunk-R7LY4YKF.js.map → chunk-2EKJDQZB.js.map} +0 -0
  672. /package/dist/{chunk-HOUST5UX.js.map → chunk-2ITE4C2Z.js.map} +0 -0
  673. /package/dist/{chunk-JOYC4RYC.js.map → chunk-2JVJ7UHC.js.map} +0 -0
  674. /package/dist/{chunk-X2NFFBTO.js.map → chunk-2L5FSNPC.js.map} +0 -0
  675. /package/dist/{chunk-DUAJKRR2.js.map → chunk-2SGLMP2E.js.map} +0 -0
  676. /package/dist/{chunk-6FUMA6AA.js.map → chunk-2Z4GS5E6.js.map} +0 -0
  677. /package/dist/{chunk-G6MXN2G5.js.map → chunk-37KUQPX4.js.map} +0 -0
  678. /package/dist/{chunk-WKAXBXVA.js.map → chunk-3QQTXYZ6.js.map} +0 -0
  679. /package/dist/{chunk-4ZWCQJNM.js.map → chunk-46WM6JX2.js.map} +0 -0
  680. /package/dist/{chunk-CASWJ2HM.js.map → chunk-46ZPIGWI.js.map} +0 -0
  681. /package/dist/{chunk-MCA2X4WH.js.map → chunk-4IHBN6WU.js.map} +0 -0
  682. /package/dist/{chunk-FB7LAJQM.js.map → chunk-4TKJGOCJ.js.map} +0 -0
  683. /package/dist/{chunk-H7BZBSP6.js.map → chunk-52II7PB6.js.map} +0 -0
  684. /package/dist/{chunk-N4Y5T6VD.js.map → chunk-54WHLA65.js.map} +0 -0
  685. /package/dist/{chunk-YVLENSNS.js.map → chunk-5ATKSPEQ.js.map} +0 -0
  686. /package/dist/{chunk-ZVZHG7AI.js.map → chunk-5UBH37SL.js.map} +0 -0
  687. /package/dist/{chunk-N3WZU76A.js.map → chunk-66OJSCI6.js.map} +0 -0
  688. /package/dist/{chunk-D35XLYQ7.js.map → chunk-6CVNSDCZ.js.map} +0 -0
  689. /package/dist/{chunk-KA2HZCMG.js.map → chunk-6NXSYYGP.js.map} +0 -0
  690. /package/dist/{chunk-2HIJHXB3.js.map → chunk-6WHJ2EAB.js.map} +0 -0
  691. /package/dist/{chunk-ZZM476NV.js.map → chunk-6XL73HQ4.js.map} +0 -0
  692. /package/dist/{chunk-EJ5RKUXW.js.map → chunk-AQ7SYDVO.js.map} +0 -0
  693. /package/dist/{chunk-2Z3DG5CQ.js.map → chunk-B3O3IRZN.js.map} +0 -0
  694. /package/dist/{chunk-RACZB5HT.js.map → chunk-BD7JTBYP.js.map} +0 -0
  695. /package/dist/{chunk-I762GW7V.js.map → chunk-BLJWYCNO.js.map} +0 -0
  696. /package/dist/{chunk-2NLLXCJG.js.map → chunk-BXLOS5AJ.js.map} +0 -0
  697. /package/dist/{chunk-GCASGYIO.js.map → chunk-C7HJ3NEI.js.map} +0 -0
  698. /package/dist/{chunk-C24UZSFW.js.map → chunk-CEH2AFXG.js.map} +0 -0
  699. /package/dist/{chunk-WVGXCBOC.js.map → chunk-D5F7TKMH.js.map} +0 -0
  700. /package/dist/{chunk-X7Y7WX73.js.map → chunk-DQEMWVMT.js.map} +0 -0
  701. /package/dist/{chunk-2OXIPF3A.js.map → chunk-DZD3WGCD.js.map} +0 -0
  702. /package/dist/{chunk-UMEOXLIZ.js.map → chunk-E2P7TZTF.js.map} +0 -0
  703. /package/dist/{chunk-6FC3IZ26.js.map → chunk-EBA5DA77.js.map} +0 -0
  704. /package/dist/{chunk-N7JK2RKG.js.map → chunk-EOQ6FSQP.js.map} +0 -0
  705. /package/dist/{chunk-YNDLCWXS.js.map → chunk-EZ25VE3G.js.map} +0 -0
  706. /package/dist/{chunk-XDMI5VKE.js.map → chunk-FVOP3NT7.js.map} +0 -0
  707. /package/dist/{chunk-NRLELHAY.js.map → chunk-G7NYVKD6.js.map} +0 -0
  708. /package/dist/{chunk-B3W7GWQB.js.map → chunk-GHTSNGBZ.js.map} +0 -0
  709. /package/dist/{chunk-LUDBXTBJ.js.map → chunk-H272ZPQ3.js.map} +0 -0
  710. /package/dist/{chunk-SN4JXNLL.js.map → chunk-H3TKENU4.js.map} +0 -0
  711. /package/dist/{chunk-4HYNMLT6.js.map → chunk-H4SEGIZY.js.map} +0 -0
  712. /package/dist/{chunk-ACZN5ZXD.js.map → chunk-H54VWRPS.js.map} +0 -0
  713. /package/dist/{chunk-HTP6XRUI.js.map → chunk-HM7RHKS4.js.map} +0 -0
  714. /package/dist/{chunk-Z3SQEEB6.js.map → chunk-HWLIMQE2.js.map} +0 -0
  715. /package/dist/{chunk-2QSZNTDO.js.map → chunk-JBPKEARU.js.map} +0 -0
  716. /package/dist/{chunk-ET2CNMLD.js.map → chunk-JN72EPOE.js.map} +0 -0
  717. /package/dist/{chunk-JCCWJHOP.js.map → chunk-JYZSRNR7.js.map} +0 -0
  718. /package/dist/{chunk-7D6HXODY.js.map → chunk-K7724CH2.js.map} +0 -0
  719. /package/dist/{chunk-X33MJFD2.js.map → chunk-KAXCYM66.js.map} +0 -0
  720. /package/dist/{chunk-7RRUHJPG.js.map → chunk-KB2G2I6Q.js.map} +0 -0
  721. /package/dist/{chunk-ZXBTTMGZ.js.map → chunk-KEF46KL2.js.map} +0 -0
  722. /package/dist/{chunk-UWTDARPF.js.map → chunk-KTWG7CNY.js.map} +0 -0
  723. /package/dist/{chunk-XQYTSZW3.js.map → chunk-L7Z57SID.js.map} +0 -0
  724. /package/dist/{chunk-JMAG7WZ7.js.map → chunk-LO4UKPKX.js.map} +0 -0
  725. /package/dist/{chunk-LDWIPYJ6.js.map → chunk-LS2FHUML.js.map} +0 -0
  726. /package/dist/{chunk-GDB4J2H3.js.map → chunk-MPC7TYTZ.js.map} +0 -0
  727. /package/dist/{chunk-2GF27PGH.js.map → chunk-MRPOZBJC.js.map} +0 -0
  728. /package/dist/{chunk-BR3OOQZQ.js.map → chunk-MWN6QEI2.js.map} +0 -0
  729. /package/dist/{chunk-NZGO2GKL.js.map → chunk-MY5EDR46.js.map} +0 -0
  730. /package/dist/{chunk-LCMUZDBZ.js.map → chunk-N3ZOP7KC.js.map} +0 -0
  731. /package/dist/{chunk-TVW4C7PV.js.map → chunk-NB3LRY4T.js.map} +0 -0
  732. /package/dist/{chunk-QJCWK2A7.js.map → chunk-ND6IQGSZ.js.map} +0 -0
  733. /package/dist/{chunk-NOB2T2FC.js.map → chunk-NHLLKEKK.js.map} +0 -0
  734. /package/dist/{chunk-EJIWBTVM.js.map → chunk-O6ZNNVSP.js.map} +0 -0
  735. /package/dist/{chunk-AG46P24C.js.map → chunk-OB3XMWX5.js.map} +0 -0
  736. /package/dist/{chunk-46QMN7I7.js.map → chunk-PAZY2ZKP.js.map} +0 -0
  737. /package/dist/{chunk-EF4JUM55.js.map → chunk-PX4UMA5Z.js.map} +0 -0
  738. /package/dist/{chunk-NNZFPYYX.js.map → chunk-R7QY5ZVB.js.map} +0 -0
  739. /package/dist/{chunk-RO2X2EYM.js.map → chunk-R7RTXEYG.js.map} +0 -0
  740. /package/dist/{chunk-3LJPSRAN.js.map → chunk-RBCQVOVJ.js.map} +0 -0
  741. /package/dist/{chunk-N4F7ZSSG.js.map → chunk-RC5DXXWC.js.map} +0 -0
  742. /package/dist/{chunk-5CF2R4NS.js.map → chunk-RKBLRTNT.js.map} +0 -0
  743. /package/dist/{chunk-5QZR2RA3.js.map → chunk-ROBHL3GL.js.map} +0 -0
  744. /package/dist/{chunk-D5ZNOKR7.js.map → chunk-S7T2TY65.js.map} +0 -0
  745. /package/dist/{chunk-3LADWWMA.js.map → chunk-SJDQ5RSN.js.map} +0 -0
  746. /package/dist/{chunk-CHWUICVY.js.map → chunk-SV4Z2S67.js.map} +0 -0
  747. /package/dist/{chunk-SEF4IOFE.js.map → chunk-SWIKABKI.js.map} +0 -0
  748. /package/dist/{chunk-JRRQ747T.js.map → chunk-TBXAY2SS.js.map} +0 -0
  749. /package/dist/{chunk-XZBXINXZ.js.map → chunk-TNSCIPBQ.js.map} +0 -0
  750. /package/dist/{chunk-S37NN23M.js.map → chunk-TVEONGBU.js.map} +0 -0
  751. /package/dist/{chunk-5RPMTFB6.js.map → chunk-TWF35IC6.js.map} +0 -0
  752. /package/dist/{chunk-BZTJEILZ.js.map → chunk-U6N5IBVY.js.map} +0 -0
  753. /package/dist/{chunk-7TUB6JWA.js.map → chunk-UCKYTA2T.js.map} +0 -0
  754. /package/dist/{chunk-PPOT6SPR.js.map → chunk-UNNPNBR2.js.map} +0 -0
  755. /package/dist/{chunk-KQAFEZQX.js.map → chunk-VDX2J7OX.js.map} +0 -0
  756. /package/dist/{chunk-J2R275FN.js.map → chunk-VVX5PZFS.js.map} +0 -0
  757. /package/dist/{chunk-ME35HVDJ.js.map → chunk-VYCOJKSX.js.map} +0 -0
  758. /package/dist/{chunk-F5UWQ4LX.js.map → chunk-W24T5YMW.js.map} +0 -0
  759. /package/dist/{chunk-HDQUQBPW.js.map → chunk-W3K3HITK.js.map} +0 -0
  760. /package/dist/{chunk-GDASG7NC.js.map → chunk-W4F3C7N7.js.map} +0 -0
  761. /package/dist/{chunk-LFK623SF.js.map → chunk-WJHGDE7X.js.map} +0 -0
  762. /package/dist/{chunk-3Q6RD76J.js.map → chunk-WQZZDN5M.js.map} +0 -0
  763. /package/dist/{chunk-ZJWDWPX6.js.map → chunk-X5K5TAQZ.js.map} +0 -0
  764. /package/dist/{chunk-ZL3XX5LW.js.map → chunk-XM24CDZX.js.map} +0 -0
  765. /package/dist/{chunk-JTWZKNUH.js.map → chunk-XOVKXJEP.js.map} +0 -0
  766. /package/dist/{chunk-X5YYSAZX.js.map → chunk-XUE46UYW.js.map} +0 -0
  767. /package/dist/{chunk-DJORULH3.js.map → chunk-YRLHEEQT.js.map} +0 -0
  768. /package/dist/{chunk-TA7UZZMW.js.map → chunk-Z3O53WZR.js.map} +0 -0
  769. /package/dist/{chunk-4LG4CPOC.js.map → chunk-Z6COGHHN.js.map} +0 -0
  770. /package/dist/{chunk-RE3H6Y2X.js.map → chunk-ZIW5JVRM.js.map} +0 -0
  771. /package/dist/{forget-2AE4MDK3.js.map → forget-SZ2BXDGF.js.map} +0 -0
  772. /package/dist/{resolution-4DLI3IOR.js.map → graph-append-error.js.map} +0 -0
package/src/types.ts CHANGED
@@ -1950,6 +1950,7 @@ export interface PluginConfig
1950
1950
  semanticDedupEnabled: boolean;
1951
1951
  semanticDedupThreshold: number;
1952
1952
  semanticDedupCandidates: number;
1953
+ semanticMerge: SemanticMergeConfig; // judge-mediated merge-on-write (#2330); default off
1953
1954
  noveltyGateEnabled: boolean;
1954
1955
  noveltyAddThreshold: number;
1955
1956
  noveltyNoopThreshold: number;
@@ -2342,6 +2343,7 @@ export interface PluginConfig
2342
2343
  */
2343
2344
  offlineSyncExcludes: string[];
2344
2345
  }
2346
+ import type { SemanticMergeConfig } from "./semantic-merge-config.js"; export type { SemanticMergeConfig };
2345
2347
 
2346
2348
  /** Runtime configuration for the daily context briefing feature. */
2347
2349
  export interface BriefingConfig {
@@ -0,0 +1,31 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import { isErrnoCode, isNotFoundError } from "./errno.js";
5
+
6
+ /** Shapes accepted by every local helper this module replaced (issue #2795). */
7
+ test("isErrnoCode matches code-carrying errors and rejects everything else", () => {
8
+ const enoent = Object.assign(new Error("no such file"), { code: "ENOENT" });
9
+ assert.equal(isErrnoCode(enoent, "ENOENT"), true);
10
+ assert.equal(isErrnoCode({ code: "ENOENT" }, "ENOENT"), true, "plain objects with a code match");
11
+ assert.equal(isErrnoCode(enoent, "EEXIST"), false, "different code does not match");
12
+ assert.equal(isErrnoCode(new Error("no code"), "ENOENT"), false);
13
+ assert.equal(isErrnoCode(null, "ENOENT"), false);
14
+ assert.equal(isErrnoCode(undefined, "ENOENT"), false);
15
+ assert.equal(isErrnoCode("ENOENT", "ENOENT"), false);
16
+ assert.equal(isErrnoCode({}, "ENOENT"), false);
17
+ });
18
+
19
+ test("isNotFoundError is equivalent to isErrnoCode(error, \"ENOENT\")", () => {
20
+ const enoent = Object.assign(new Error("no such file"), { code: "ENOENT" });
21
+ const eexist = Object.assign(new Error("file exists"), { code: "EEXIST" });
22
+ for (const candidate of [enoent, eexist, { code: "ENOENT" }, {}, null, undefined, "ENOENT", 42]) {
23
+ assert.equal(
24
+ isNotFoundError(candidate),
25
+ isErrnoCode(candidate, "ENOENT"),
26
+ `isNotFoundError must agree with isErrnoCode(_, "ENOENT") for ${JSON.stringify(candidate) ?? String(candidate)}`,
27
+ );
28
+ }
29
+ assert.equal(isNotFoundError(enoent), true);
30
+ assert.equal(isNotFoundError(eexist), false);
31
+ });
@@ -4,3 +4,8 @@ export function isErrnoCode(error: unknown, code: string): boolean {
4
4
  && "code" in error
5
5
  && (error as { code?: unknown }).code === code;
6
6
  }
7
+
8
+ /** True iff `error` carries Node's `ENOENT` code (missing file or directory). */
9
+ export function isNotFoundError(error: unknown): boolean {
10
+ return isErrnoCode(error, "ENOENT");
11
+ }
@@ -18,6 +18,7 @@ export {
18
18
  export {
19
19
  builtInConnectorPackageSpecifier,
20
20
  registerWearableConnector,
21
+ selfRegisterWearableConnector,
21
22
  getWearableConnector,
22
23
  listWearableConnectors,
23
24
  clearWearableConnectors,
@@ -64,6 +64,29 @@ export function getWearableConnector(
64
64
  return registrations.get(key);
65
65
  }
66
66
 
67
+ /**
68
+ * Register a connector package with this registry immediately (idempotent)
69
+ * and return its `ensure*Registered()` companion.
70
+ *
71
+ * Connector packages call this once at module scope with their registration
72
+ * record, so importing the module registers the connector as a side effect.
73
+ * The returned companion re-checks the live registry on every call — so it
74
+ * also re-registers after a test-only registry reset — and returns false
75
+ * while the connector stays registered. `registerWearableConnector` throws
76
+ * on duplicate ids, which is why the registry is checked before each call.
77
+ */
78
+ export function selfRegisterWearableConnector(
79
+ registration: WearableConnectorRegistration,
80
+ ): () => boolean {
81
+ const ensureRegistered = (): boolean => {
82
+ if (getWearableConnector(registration.id) !== undefined) return false;
83
+ registerWearableConnector(registration);
84
+ return true;
85
+ };
86
+ ensureRegistered();
87
+ return ensureRegistered;
88
+ }
89
+
67
90
  export function listWearableConnectors(): string[] {
68
91
  return [...registrations.keys()];
69
92
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/errno.ts"],"sourcesContent":["export function isErrnoCode(error: unknown, code: string): boolean {\n return typeof error === \"object\"\n && error !== null\n && \"code\" in error\n && (error as { code?: unknown }).code === code;\n}\n"],"mappings":";AAAO,SAAS,YAAY,OAAgB,MAAuB;AACjE,SAAO,OAAO,UAAU,YACnB,UAAU,QACV,UAAU,SACT,MAA6B,SAAS;AAC9C;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/location/intervals.ts","../src/location/matching.ts","../src/location/store.ts","../src/location/tagging.ts"],"sourcesContent":["/**\n * Location interval math (issue #2044).\n *\n * Pure, deterministic helpers over UTC ISO-8601 instants: half-open\n * [start, end) day windows (reusing the DST-correct activity day-window), IANA\n * local-day bucketing, overlap, observation→segment dwell, and dominant-place\n * selection with stable tie-breaking. No IO, no clocks, no randomness.\n */\n\nimport { activityDayWindow, isValidActivityDate } from \"../activity/digest.js\";\nimport type { LocationObservation, LocationPlace, LocationSegment } from \"./types.js\";\n\nexport function isValidLocationDate(date: string): boolean {\n return isValidActivityDate(date);\n}\n\n/** Half-open [start, end) UTC ISO bounds of a local day. */\nexport function locationDayWindow(date: string, timezone: string): { startUtc: string; endUtc: string } {\n if (!isValidActivityDate(date)) {\n throw new RangeError(`Invalid location date \"${date}\"; expected a real YYYY-MM-DD day.`);\n }\n return activityDayWindow(date, timezone);\n}\n\nfunction assertFiniteInstant(iso: string, what: string): number {\n const ms = Date.parse(iso);\n if (typeof iso !== \"string\" || !Number.isFinite(ms)) {\n throw new RangeError(`${what} must be a UTC ISO-8601 instant; got \"${String(iso)}\"`);\n }\n return ms;\n}\n\n/** The IANA local calendar day (YYYY-MM-DD) an instant falls in. */\nexport function localDayKey(instantUtc: string, timezone: string): string {\n assertFiniteInstant(instantUtc, \"instantUtc\");\n return new Intl.DateTimeFormat(\"en-CA\", {\n timeZone: timezone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n }).format(new Date(instantUtc));\n}\n\nfunction compareObservations(a: LocationObservation, b: LocationObservation): number {\n if (a.observedAtUtc !== b.observedAtUtc) {\n return a.observedAtUtc < b.observedAtUtc ? -1 : 1;\n }\n // Total comparator (§12): equal-key observations fall back to place id so\n // ordering — and therefore dwell attribution — is deterministic.\n if (a.place.id !== b.place.id) {\n return a.place.id < b.place.id ? -1 : 1;\n }\n return 0;\n}\n\n/** Bucket observations into their IANA local days, sorted within each day. */\nexport function bucketObservationsByDay(\n observations: readonly LocationObservation[],\n timezone: string,\n): Map<string, LocationObservation[]> {\n const buckets = new Map<string, LocationObservation[]>();\n for (const observation of observations) {\n assertFiniteInstant(observation.observedAtUtc, \"observation observedAtUtc\");\n const key = localDayKey(observation.observedAtUtc, timezone);\n const bucket = buckets.get(key);\n if (bucket === undefined) buckets.set(key, [observation]);\n else bucket.push(observation);\n }\n for (const bucket of buckets.values()) bucket.sort(compareObservations);\n return buckets;\n}\n\n/** Overlap in ms of two half-open intervals; 0 when disjoint. */\nexport function intervalOverlapMs(\n a: { startUtc: string; endUtc: string },\n b: { startUtc: string; endUtc: string },\n): number {\n const overlap =\n Math.min(Date.parse(a.endUtc), Date.parse(b.endUtc)) - Math.max(Date.parse(a.startUtc), Date.parse(b.startUtc));\n return Math.max(0, overlap);\n}\n\nfunction placeForSegment(place: LocationPlace, retainCoordinates: boolean): LocationPlace {\n if (retainCoordinates || place.latitude === undefined || place.longitude === undefined) {\n return place;\n }\n return {\n id: place.id,\n label: place.label,\n ...(place.kind === undefined ? {} : { kind: place.kind }),\n };\n}\n\n/**\n * Derive place-visit segments from a day's observations: each observation\n * covers [its instant, the next observation's instant ∩ window end). The last\n * observation is capped by the window end, so dwell never crosses the day\n * boundary. Out-of-window observations are a provider contract violation and\n * are rejected loudly rather than silently reshaping the day. Coordinates are\n * stripped unless `retainCoordinates` is set.\n */\nexport function observationSegments(\n observations: readonly LocationObservation[],\n window: { startUtc: string; endUtc: string },\n options: { retainCoordinates: boolean },\n): LocationSegment[] {\n const startMs = assertFiniteInstant(window.startUtc, \"window startUtc\");\n const endMs = assertFiniteInstant(window.endUtc, \"window endUtc\");\n if (startMs >= endMs) {\n throw new RangeError(\"location window must satisfy startUtc < endUtc\");\n }\n const ordered = [...observations].sort(compareObservations);\n const segments: LocationSegment[] = [];\n for (let index = 0; index < ordered.length; index += 1) {\n const current = ordered[index]!;\n const currentMs = Date.parse(current.observedAtUtc);\n if (currentMs < startMs || currentMs >= endMs) {\n throw new RangeError(\n `location observation at \"${current.observedAtUtc}\" falls outside the requested [${window.startUtc}, ${window.endUtc}) window`,\n );\n }\n const nextMs =\n index + 1 < ordered.length ? Date.parse(ordered[index + 1]!.observedAtUtc) : endMs;\n const segmentEndMs = Math.min(nextMs, endMs);\n if (currentMs >= segmentEndMs) continue;\n segments.push({\n startUtc: new Date(currentMs).toISOString(),\n endUtc: new Date(segmentEndMs).toISOString(),\n place: placeForSegment(current.place, options.retainCoordinates),\n ...(current.confidence !== undefined ? { confidence: current.confidence } : {}),\n });\n }\n return segments;\n}\n\n/** Total time a place was occupied (union of its segment intervals, ms). */\nexport interface PlaceDuration {\n place: LocationPlace;\n totalMs: number;\n /** Earliest segment start contributing to this place's total. */\n firstStartUtc: string;\n}\n\nfunction unionIntervalMs(segments: readonly LocationSegment[]): number {\n // Merge overlapping [start, end) intervals per place so two providers\n // observing the same visit do not double-count its duration.\n const bounds = segments\n .map((segment) => ({ start: Date.parse(segment.startUtc), end: Date.parse(segment.endUtc) }))\n .sort((a, b) => (a.start !== b.start ? a.start - b.start : a.end - b.end));\n let total = 0;\n let sweepStart: number | null = null;\n let sweepEnd = 0;\n for (const bound of bounds) {\n if (sweepStart === null || bound.start > sweepEnd) {\n if (sweepStart !== null) total += sweepEnd - sweepStart;\n sweepStart = bound.start;\n sweepEnd = bound.end;\n } else if (bound.end > sweepEnd) {\n sweepEnd = bound.end;\n }\n }\n if (sweepStart !== null) total += sweepEnd - sweepStart;\n return total;\n}\n\n/** Per-place totals across every segment given (multi-source safe). */\nexport function placeDurations(segments: readonly LocationSegment[]): PlaceDuration[] {\n const byPlace = new Map<string, { place: LocationPlace; segments: LocationSegment[]; firstStartUtc: string }>();\n for (const segment of segments) {\n const existing = byPlace.get(segment.place.id);\n if (existing === undefined) {\n byPlace.set(segment.place.id, { place: segment.place, segments: [segment], firstStartUtc: segment.startUtc });\n continue;\n }\n existing.segments.push(segment);\n if (segment.startUtc < existing.firstStartUtc) existing.firstStartUtc = segment.startUtc;\n // Two providers may label the same place id differently; keep the\n // lexicographically smallest label so rendering stays deterministic.\n if (segment.place.label < existing.place.label) existing.place = segment.place;\n }\n const durations: PlaceDuration[] = [...byPlace.values()].map((entry) => ({\n place: entry.place,\n totalMs: unionIntervalMs(entry.segments),\n firstStartUtc: entry.firstStartUtc,\n }));\n durations.sort((a, b) => {\n if (a.place.id !== b.place.id) return a.place.id < b.place.id ? -1 : 1;\n return 0;\n });\n return durations;\n}\n\nexport interface DominantPlaceResult {\n place: LocationPlace;\n totalMs: number;\n}\n\n/**\n * The place with the longest total occupancy. Ties are stable and\n * deterministic: earlier first start wins, then the lexicographically smaller\n * place id — never insertion order.\n */\nexport function dominantPlace(segments: readonly LocationSegment[]): DominantPlaceResult | null {\n const durations = placeDurations(segments);\n let best: PlaceDuration | null = null;\n for (const duration of durations) {\n if (best === null) {\n best = duration;\n continue;\n }\n if (duration.totalMs !== best.totalMs) {\n if (duration.totalMs > best.totalMs) best = duration;\n continue;\n }\n if (duration.firstStartUtc !== best.firstStartUtc) {\n if (duration.firstStartUtc < best.firstStartUtc) best = duration;\n continue;\n }\n if (duration.place.id < best.place.id) best = duration;\n }\n return best === null ? null : { place: best.place, totalMs: best.totalMs };\n}\n","/**\n * Core location matcher (issue #2046) — the ONE place that decides whether a\n * memory or wearable conversation gets provider location context.\n *\n * Pure and deterministic: no IO, no clocks, no randomness. Inputs are UTC\n * ISO-8601 instants and half-open [start, end) intervals everywhere.\n *\n * Rules (issue #2046 / umbrella #2043 decision D):\n * 1. A valid memory interval is required — derived ONLY from the memory's own\n * bi-temporal frontmatter (`valid_at` / `observedAt` / `invalid_at`), never\n * from wall-clock time or message order. Untimed memories stay untagged.\n * 2. Intervals longer than 24h describe long-lived facts, not events at a\n * place; they stay untagged.\n * 3. A place is tagged only when it is DOMINANT (strictly the longest overlap\n * among candidate places; ties are conflicts and leave the memory untagged)\n * and meets `minimumOverlapSeconds` and `minimumConfidence`.\n * 4. Only resolved named places participate (`kind` home/work/poi): transit\n * legs and unnamed visits never tag a memory.\n * 5. No address is ever inferred from text, coordinates, IP, or proximity —\n * only provider-supplied place metadata is echoed, and coordinates only\n * when `retainCoordinates` is enabled.\n *\n * Provider-owned metadata contract: the tag is `location:<stable-place-slug>`\n * and the opaque provider place id lives in structured attributes. Every\n * field the matcher writes is provider-owned; a memory that carries\n * location-ish metadata WITHOUT the `locationSource` marker is treated as\n * manual/user-authored and is never touched.\n */\n\nimport { TAG_LIMITS, STRUCTURED_ATTRIBUTE_LIMITS } from \"../write-envelope.js\";\nimport type { LocationPlace, LocationSegment } from \"./types.js\";\n\n/** Maximum memory span eligible for location tagging. */\nexport const LOCATION_MATCH_MAX_MEMORY_SPAN_MS = 24 * 60 * 60 * 1000;\n\n/** Prefix of provider-owned location tags. */\nexport const LOCATION_TAG_PREFIX = \"location:\";\n\n/** Structured-attribute keys owned by the tagging pipeline (never manual). */\nexport const LOCATION_ATTRIBUTE_KEYS = [\n \"locationSource\",\n \"locationPlaceId\",\n \"locationPlace\",\n \"locationConfidence\",\n \"locationVisitStart\",\n \"locationVisitEnd\",\n \"locationLatitude\",\n \"locationLongitude\",\n] as const;\n\n/** Place kinds eligible for tagging: resolved, named places only. */\nconst TAGGABLE_PLACE_KINDS: Record<string, true> = { home: true, work: true, poi: true };\n\nexport interface LocationTagPolicy {\n minimumOverlapSeconds: number;\n minimumConfidence: number;\n retainCoordinates: boolean;\n}\n\n/** The memory side of a match: a half-open interval, or a single instant. */\nexport type MemoryLocationWindow =\n | { kind: \"interval\"; startUtc: string; endUtc: string }\n | { kind: \"instant\"; atUtc: string };\n\n/** Why a window was rejected before matching. */\nexport type WindowRejectReason = \"untimed\" | \"span-too-long\";\n\nexport interface WindowResult {\n window?: MemoryLocationWindow;\n /** Local days (YYYY-MM-DD in the tag policy timezone) the window touches. */\n days?: string[];\n rejected?: WindowRejectReason;\n}\n\n/**\n * Derive the match window from a memory's own frontmatter. `validAt` (the\n * event start; assumed copies carry the ingestion anchor) opens the window;\n * `invalid_at` closes it. An end-only memory (no start bound) is untimed.\n */\nexport function memoryLocationWindow(\n frontmatter: { valid_at?: string; observedAt?: string; invalid_at?: string },\n localDay: (instantUtc: string) => string,\n): WindowResult {\n const start = frontmatter.valid_at ?? frontmatter.observedAt;\n if (start === undefined || Number.isNaN(Date.parse(start))) {\n return { rejected: \"untimed\" };\n }\n const end = frontmatter.invalid_at;\n if (end === undefined || Number.isNaN(Date.parse(end)) || Date.parse(end) <= Date.parse(start)) {\n return { window: { kind: \"instant\", atUtc: start }, days: [localDay(start)] };\n }\n if (Date.parse(end) - Date.parse(start) > LOCATION_MATCH_MAX_MEMORY_SPAN_MS) {\n return { rejected: \"span-too-long\" };\n }\n // The interval is half-open [start, end): its last instant is end-1ms, so a\n // memory ending exactly at local midnight never touches the next day.\n const lastInstant = new Date(Date.parse(end) - 1).toISOString();\n const days = [localDay(start)];\n const endDay = localDay(lastInstant);\n if (endDay !== days[0]) days.push(endDay);\n return { window: { kind: \"interval\", startUtc: start, endUtc: end }, days };\n}\n\n/** One source's segments for a day, keyed by the configured source id. */\nexport interface LocationSourceSegments {\n sourceId: string;\n segments: LocationSegment[];\n}\n\nexport interface LocationMatch {\n sourceId: string;\n place: LocationPlace;\n /** Overlap (ms) with the window — interval mode; see `visitMs` otherwise. */\n overlapMs: number;\n /** Total dwell (ms) of the dominant place inside the window's day(s). */\n visitMs: number;\n /** Minimum contributing segment confidence, when any source reported one. */\n confidence?: number;\n /** Envelope [start, end) of the segments that produced the match. */\n visitStartUtc: string;\n visitEndUtc: string;\n}\n\nexport type MatchOutcome =\n | { status: \"matched\"; match: LocationMatch }\n | { status: \"unmatched\"; reason: \"no-overlap\" | \"ambiguous\" | \"below-minimum-overlap\" | \"below-minimum-confidence\" };\n\ninterface PlaceAccumulator {\n sourceId: string;\n place: LocationPlace;\n overlapMs: number;\n visitMs: number;\n confidence: number | undefined;\n startUtc: string;\n endUtc: string;\n}\n\nfunction overlapMsOf(\n window: MemoryLocationWindow,\n segment: { startUtc: string; endUtc: string },\n): number {\n if (window.kind === \"instant\") {\n const at = Date.parse(window.atUtc);\n return at >= Date.parse(segment.startUtc) && at < Date.parse(segment.endUtc) ? 1 : 0;\n }\n return Math.max(\n 0,\n Math.min(Date.parse(window.endUtc), Date.parse(segment.endUtc)) -\n Math.max(Date.parse(window.startUtc), Date.parse(segment.startUtc)),\n );\n}\n\n/**\n * The dominant qualifying place for a window, across every source's\n * segments. Deterministic: strict overlap comparison, ties (conflicts) are\n * rejected, and equal-place contributions merge across sources.\n */\nexport function matchDominantPlace(\n window: MemoryLocationWindow,\n sources: readonly LocationSourceSegments[],\n policy: LocationTagPolicy,\n): MatchOutcome {\n const byPlace = new Map<string, PlaceAccumulator>();\n for (const source of sources) {\n for (const segment of source.segments) {\n if (TAGGABLE_PLACE_KINDS[segment.place.kind ?? \"\"] !== true) continue;\n const overlap = overlapMsOf(window, segment);\n if (overlap <= 0) continue;\n const duration = Date.parse(segment.endUtc) - Date.parse(segment.startUtc);\n const existing = byPlace.get(segment.place.id);\n if (existing === undefined) {\n byPlace.set(segment.place.id, {\n sourceId: source.sourceId,\n place: segment.place,\n overlapMs: overlap,\n visitMs: duration,\n confidence: segment.confidence,\n startUtc: segment.startUtc,\n endUtc: segment.endUtc,\n });\n continue;\n }\n // Same place from another source (or a revisit): accumulate.\n existing.overlapMs += overlap;\n existing.visitMs += duration;\n existing.confidence =\n existing.confidence === undefined\n ? segment.confidence\n : segment.confidence === undefined\n ? existing.confidence\n : Math.min(existing.confidence, segment.confidence);\n if (segment.startUtc < existing.startUtc) existing.startUtc = segment.startUtc;\n if (segment.endUtc > existing.endUtc) existing.endUtc = segment.endUtc;\n }\n }\n if (byPlace.size === 0) return { status: \"unmatched\", reason: \"no-overlap\" };\n\n let best: PlaceAccumulator | null = null;\n let tie = false;\n for (const candidate of byPlace.values()) {\n if (best === null || candidate.overlapMs > best.overlapMs) {\n best = candidate;\n tie = false;\n continue;\n }\n if (candidate.overlapMs === best.overlapMs) tie = true;\n }\n if (best === null || tie) return { status: \"unmatched\", reason: \"ambiguous\" };\n\n const overlapForThreshold = window.kind === \"instant\" ? best.visitMs : best.overlapMs;\n if (policy.minimumOverlapSeconds > 0 && overlapForThreshold < policy.minimumOverlapSeconds * 1000) {\n return { status: \"unmatched\", reason: \"below-minimum-overlap\" };\n }\n if (best.confidence !== undefined && best.confidence < policy.minimumConfidence) {\n return { status: \"unmatched\", reason: \"below-minimum-confidence\" };\n }\n return {\n status: \"matched\",\n match: {\n sourceId: best.sourceId,\n place: best.place,\n overlapMs: best.overlapMs,\n visitMs: best.visitMs,\n ...(best.confidence !== undefined ? { confidence: best.confidence } : {}),\n visitStartUtc: best.startUtc,\n visitEndUtc: best.endUtc,\n },\n };\n}\n\n/** Deterministic tag slug for a provider place id (`reitti:place:7` → `reitti-place-7`). */\nexport function locationTagSlug(placeId: string): string {\n const slug = placeId\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n // The collapse above leaves at most one dash at each edge, so single-char\n // strips are complete. The old /^-+|-+$/ alternation backtracked\n // quadratically on unsanitized dash runs (CodeQL js/polynomial-redos);\n // single-character anchors are linear.\n .replace(/^-/, \"\")\n .replace(/-$/, \"\");\n return slug.slice(0, TAG_LIMITS.maxTagLength - LOCATION_TAG_PREFIX.length);\n}\n\n/** The provider-owned tag for a matched place. */\nexport function locationTagForPlace(placeId: string): string {\n return `${LOCATION_TAG_PREFIX}${locationTagSlug(placeId)}`;\n}\n\nfunction boundedAttributeValue(value: string): string {\n return value.slice(0, STRUCTURED_ATTRIBUTE_LIMITS.maxValueLength);\n}\n\n/** Provider-owned structured attributes describing a match. */\nexport function locationAttributesForMatch(\n match: LocationMatch,\n policy: LocationTagPolicy,\n): Record<string, string> {\n const attributes: Record<string, string> = {\n locationSource: match.sourceId,\n locationPlaceId: boundedAttributeValue(match.place.id),\n locationPlace: boundedAttributeValue(match.place.label),\n ...(match.confidence !== undefined ? { locationConfidence: match.confidence.toFixed(3) } : {}),\n locationVisitStart: match.visitStartUtc,\n locationVisitEnd: match.visitEndUtc,\n };\n if (policy.retainCoordinates && match.place.latitude !== undefined && match.place.longitude !== undefined) {\n attributes.locationLatitude = String(match.place.latitude);\n attributes.locationLongitude = String(match.place.longitude);\n }\n return attributes;\n}\n\nexport interface LocationUpdatePlan {\n /** Patch for `writeMemoryFrontmatter`; absent when nothing changes. */\n patch?: { tags: string[]; structuredAttributes: Record<string, string> };\n /** Outcome for reporting. */\n outcome:\n | \"tagged\"\n | \"updated\"\n | \"removed\"\n | \"unchanged\"\n | \"manual-metadata\"\n | \"unmatched\"\n | \"untimed\"\n | \"span-too-long\";\n}\n\nfunction frontmatterHasLocationMetadata(\n frontmatter: { tags?: string[]; structuredAttributes?: Record<string, string> },\n): boolean {\n if ((frontmatter.tags ?? []).some((tag) => tag.startsWith(LOCATION_TAG_PREFIX))) return true;\n return Object.keys(frontmatter.structuredAttributes ?? {}).some((key) =>\n (LOCATION_ATTRIBUTE_KEYS as readonly string[]).includes(key),\n );\n}\n\nfunction isProviderOwned(frontmatter: { structuredAttributes?: Record<string, string> }): boolean {\n const source = frontmatter.structuredAttributes?.locationSource;\n return typeof source === \"string\" && source.length > 0;\n}\n\n/**\n * Plan the provider-owned update for one memory: a match adds/replaces ONLY\n * provider-owned fields; a lost match removes them (corrected observations);\n * manual location metadata (no `locationSource` marker) always wins and is\n * never touched. Unrelated tags and attributes survive every path.\n */\nexport function planLocationUpdate(\n frontmatter: { tags?: string[]; structuredAttributes?: Record<string, string> },\n outcome: MatchOutcome,\n policy: LocationTagPolicy,\n): LocationUpdatePlan {\n if (frontmatterHasLocationMetadata(frontmatter) && !isProviderOwned(frontmatter)) {\n return { outcome: \"manual-metadata\" };\n }\n const tags = [...(frontmatter.tags ?? [])];\n const attributes = { ...(frontmatter.structuredAttributes ?? {}) };\n const providerTagIndex = tags.findIndex((tag) => tag.startsWith(LOCATION_TAG_PREFIX));\n const stripProviderFields = (): void => {\n if (providerTagIndex >= 0) tags.splice(providerTagIndex, 1);\n for (const key of LOCATION_ATTRIBUTE_KEYS) delete attributes[key];\n };\n\n if (outcome.status !== \"matched\") {\n if (!isProviderOwned(frontmatter)) return { outcome: \"unmatched\" };\n if (providerTagIndex < 0 && !(\"locationPlaceId\" in attributes)) {\n return { outcome: \"unchanged\" };\n }\n stripProviderFields();\n return { patch: { tags, structuredAttributes: attributes }, outcome: \"removed\" };\n }\n\n const desiredTag = locationTagForPlace(outcome.match.place.id);\n const desiredAttributes = locationAttributesForMatch(outcome.match, policy);\n if (tags.length >= TAG_LIMITS.maxTags && providerTagIndex < 0) {\n // Full tag budget with no provider slot to reuse — leave the memory alone.\n return { outcome: \"unchanged\" };\n }\n const alreadyCurrent =\n providerTagIndex >= 0 &&\n tags[providerTagIndex] === desiredTag &&\n LOCATION_ATTRIBUTE_KEYS.every((key) => {\n const want = desiredAttributes[key];\n const have = attributes[key];\n return want === undefined ? have === undefined : have === want;\n });\n if (alreadyCurrent) return { outcome: \"unchanged\" };\n\n if (providerTagIndex >= 0) tags[providerTagIndex] = desiredTag;\n else tags.push(desiredTag);\n for (const key of LOCATION_ATTRIBUTE_KEYS) delete attributes[key];\n Object.assign(attributes, desiredAttributes);\n const wasProviderOwned = isProviderOwned(frontmatter);\n return {\n patch: { tags, structuredAttributes: attributes },\n outcome: wasProviderOwned ? \"updated\" : \"tagged\",\n };\n}\n","/**\n * Location day-file + sync-state store (issue #2044).\n *\n * Day documents live at `<memoryDir>/locations/<YYYY-MM-DD>.md` — OUTSIDE the\n * memory scan roots (facts/, entities/, …) so raw location history never\n * surfaces as a memory in recall or governance passes, and INSIDE the QMD\n * collection root so the markdown stays full-text searchable once an index\n * update runs. Per-source sync state lives at\n * `<memoryDir>/state/locations/sync.json` and is written only after the day\n * document is durable (see pipeline.ts).\n *\n * Both writes are atomic (temp file + rename) and containment-checked: a\n * symlinked `locations/` root or day file is rejected even when it resolves\n * inside the memory dir (AGENTS.md pattern #3), and a path that escapes the\n * memory dir is refused outright.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { lstat, mkdir, readFile, readdir, realpath } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { writeFileAtomically } from \"../maintenance/atomic-file.js\";\nimport { pathIsInside } from \"../utils/path-containment.js\";\nimport { isValidLocationDate, placeDurations } from \"./intervals.js\";\nimport type { LocationSegment } from \"./types.js\";\n\nexport const LOCATIONS_DIR_NAME = \"locations\";\nexport const LOCATION_DAY_KIND = \"location-day\";\nexport const LOCATION_DAY_FORMAT_VERSION = 1;\n\n/** Cap on remembered day payloads per source (~3 months of days). */\nconst MAX_TRACKED_LOCATION_DAYS = 90;\n\nconst DAY_FILE_NAME_PATTERN = /^\\d{4}-\\d{2}-\\d{2}\\.md$/;\n\n// Serializes state load→mutate→save sections per state file so two sources\n// syncing concurrently cannot lose-update each other's entries.\nconst stateLocks = new Map<string, Promise<unknown>>();\n\nfunction withStateLock<T>(key: string, fn: () => Promise<T>): Promise<T> {\n const prior = stateLocks.get(key) ?? Promise.resolve();\n const next = prior.then(fn, fn);\n const tail = next.then(\n () => undefined,\n () => undefined,\n );\n stateLocks.set(key, tail);\n void tail.then(() => {\n if (stateLocks.get(key) === tail) stateLocks.delete(key);\n });\n return next;\n}\n\nexport function locationDayFilePath(memoryDir: string, date: string): string {\n if (!isValidLocationDate(date)) {\n // Never interpolate an unvalidated date into a filesystem path (a `../`\n // would escape <memoryDir>/locations/). Reject loudly.\n throw new RangeError(`Invalid location date \"${date}\"; expected a real YYYY-MM-DD day.`);\n }\n return path.join(memoryDir, LOCATIONS_DIR_NAME, `${date}.md`);\n}\n\nexport function locationSyncStateFilePath(memoryDir: string): string {\n return path.join(memoryDir, \"state\", \"locations\", \"sync.json\");\n}\n\n/** A source's derived day payload, kept in sync state for multi-source merges. */\nexport interface LocationSourceDayPayload {\n observationCount: number;\n segments: LocationSegment[];\n providerDisplayName?: string;\n}\n\nexport interface LocationSourceSyncState {\n lastSyncedAtUtc?: string;\n days?: Record<string, LocationSourceDayPayload>;\n}\n\nexport interface LocationSyncStateFile {\n version: 1;\n sources: Record<string, LocationSourceSyncState>;\n}\n\nexport function emptyLocationSyncState(): LocationSyncStateFile {\n return { version: 1, sources: {} };\n}\n\nexport async function loadLocationSyncState(memoryDir: string): Promise<LocationSyncStateFile> {\n let raw: string;\n try {\n raw = await readFile(locationSyncStateFilePath(memoryDir), \"utf-8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return emptyLocationSyncState();\n throw err;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n // A corrupt state file must not brick syncing forever; treat it as a cold\n // start. The worst case is re-syncing days already on disk, and the day\n // file's contentHash makes that rewrite idempotent.\n return emptyLocationSyncState();\n }\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n Array.isArray(parsed) ||\n typeof (parsed as LocationSyncStateFile).sources !== \"object\" ||\n (parsed as LocationSyncStateFile).sources === null\n ) {\n return emptyLocationSyncState();\n }\n return { version: 1, sources: (parsed as LocationSyncStateFile).sources };\n}\n\nexport async function saveLocationSyncState(\n memoryDir: string,\n state: LocationSyncStateFile,\n): Promise<void> {\n await mkdir(path.dirname(locationSyncStateFilePath(memoryDir)), { recursive: true, mode: 0o700 });\n await writeFileAtomically(\n locationSyncStateFilePath(memoryDir),\n `${JSON.stringify(state, null, 2)}\\n`,\n );\n}\n\nfunction pruneSourceDays(source: LocationSourceSyncState): void {\n const days = source.days;\n if (days === undefined) return;\n const keys = Object.keys(days).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));\n for (const key of keys.slice(0, Math.max(0, keys.length - MAX_TRACKED_LOCATION_DAYS))) {\n delete days[key];\n }\n}\n\n/**\n * Record one source's completed day sync. Runs the whole read-modify-write\n * under the per-directory state lock so concurrent sources cannot clobber\n * each other, and prunes day payloads beyond the retention cap.\n */\nexport async function updateLocationSourceDay(\n memoryDir: string,\n sourceId: string,\n date: string,\n payload: LocationSourceDayPayload,\n completedAtUtc: string,\n): Promise<LocationSyncStateFile> {\n if (!isValidLocationDate(date)) {\n throw new RangeError(`Invalid location date \"${date}\"; expected a real YYYY-MM-DD day.`);\n }\n return withStateLock(locationSyncStateFilePath(memoryDir), async () => {\n const state = await loadLocationSyncState(memoryDir);\n const source = state.sources[sourceId] ?? {};\n const days = source.days ?? {};\n days[date] = payload;\n source.days = days;\n source.lastSyncedAtUtc = completedAtUtc;\n state.sources[sourceId] = source;\n for (const candidate of Object.values(state.sources)) pruneSourceDays(candidate);\n await saveLocationSyncState(memoryDir, state);\n return state;\n });\n}\n/** Frontmatter persisted on a rendered day document. */\nexport interface LocationDayMeta {\n kind: typeof LOCATION_DAY_KIND;\n date: string;\n timezone: string;\n formatVersion: number;\n sources: string[];\n observationCount: number;\n /** SHA-256 of the rendered body (rebuild idempotency). */\n contentHash: string;\n}\n\n/** A parsed day document (frontmatter + rendered body). */\nexport interface LocationDayDocument {\n meta: LocationDayMeta;\n body: string;\n}\n\n/** The per-source view a day document is composed from. */\nexport interface LocationDaySourceEntry extends LocationSourceDayPayload {\n /** Provider display name for the timeline heading; falls back to the id. */\n providerDisplayName?: string;\n}\n\nexport function hashLocationBody(body: string): string {\n return createHash(\"sha256\").update(body, \"utf8\").digest(\"hex\");\n}\n\nfunction clockHhMm(iso: string, timezone: string): string {\n return new Intl.DateTimeFormat(\"en-GB\", {\n timeZone: timezone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false,\n }).format(new Date(iso));\n}\n\nfunction formatDuration(ms: number): string {\n const totalMinutes = Math.round(ms / 60_000);\n const hours = Math.floor(totalMinutes / 60);\n const minutes = totalMinutes % 60;\n if (hours <= 0) return `${minutes}m`;\n return `${hours}h ${String(minutes).padStart(2, \"0\")}m`;\n}\n\n/** Collapse whitespace and strip markdown emphasis/backticks from a label. */\nfunction safeLabel(label: string): string {\n return label.replace(/\\s+/g, \" \").replace(/[`*_]/g, \"\").trim();\n}\n\nfunction formatPlaceLabel(segment: LocationSegment): string {\n const label = safeLabel(segment.place.label);\n return segment.place.kind === undefined ? label : `${label} (${segment.place.kind})`;\n}\n\nfunction formatCoordinates(segment: LocationSegment): string {\n if (segment.place.latitude === undefined || segment.place.longitude === undefined) return \"\";\n return ` @ ${segment.place.latitude.toFixed(4)},${segment.place.longitude.toFixed(4)}`;\n}\n\nexport function composeLocationDayBody(\n date: string,\n timezone: string,\n sources: Record<string, LocationDaySourceEntry>,\n): string {\n const lines: string[] = [`# Location day — ${date} (${timezone})`, \"\"];\n const allSegments: LocationSegment[] = [];\n let observationCount = 0;\n for (const entry of Object.values(sources)) {\n allSegments.push(...entry.segments);\n observationCount += entry.observationCount;\n }\n\n lines.push(\"## Summary\", \"\");\n if (observationCount === 0) {\n lines.push(\"No location observations recorded.\", \"\");\n } else {\n const durations = placeDurations(allSegments).sort((a, b) => b.totalMs - a.totalMs);\n lines.push(\n `- Places visited: ${durations.length}`,\n ...durations.map(\n (duration) => `- ${safeLabel(duration.place.label)}: ${formatDuration(duration.totalMs)}`,\n ),\n \"\",\n );\n }\n\n const sourceIds = Object.keys(sources).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));\n for (const sourceId of sourceIds) {\n const entry = sources[sourceId]!;\n lines.push(`## Timeline — ${safeLabel(entry.providerDisplayName ?? sourceId)}`, \"\");\n if (entry.segments.length === 0) {\n lines.push(\"No observations.\", \"\");\n continue;\n }\n for (const segment of entry.segments) {\n lines.push(\n `- ${clockHhMm(segment.startUtc, timezone)}–${clockHhMm(segment.endUtc, timezone)} — ${formatPlaceLabel(segment)}${formatCoordinates(segment)}`,\n );\n }\n lines.push(\"\");\n }\n return `${lines.join(\"\\n\").trimEnd()}\\n`;\n}\n\nexport function composeLocationDayMeta(\n date: string,\n timezone: string,\n sources: Record<string, LocationDaySourceEntry>,\n body: string,\n): LocationDayMeta {\n let observationCount = 0;\n for (const entry of Object.values(sources)) observationCount += entry.observationCount;\n return {\n kind: LOCATION_DAY_KIND,\n date,\n timezone,\n formatVersion: LOCATION_DAY_FORMAT_VERSION,\n sources: Object.keys(sources).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)),\n observationCount,\n contentHash: hashLocationBody(body),\n };\n}\n\nfunction frontmatterScalar(key: string, value: string | number): string {\n return `${key}: ${typeof value === \"number\" ? value : JSON.stringify(value)}`;\n}\n\nfunction frontmatterList(key: string, values: readonly string[]): string[] {\n if (values.length === 0) return [`${key}: []`];\n const lines = [`${key}:`];\n for (const value of values) lines.push(` - ${JSON.stringify(value)}`);\n return lines;\n}\n\nexport function serializeLocationDay(meta: LocationDayMeta, body: string): string {\n const lines: string[] = [\"---\"];\n lines.push(frontmatterScalar(\"kind\", meta.kind));\n lines.push(frontmatterScalar(\"date\", meta.date));\n lines.push(frontmatterScalar(\"timezone\", meta.timezone));\n lines.push(frontmatterScalar(\"formatVersion\", meta.formatVersion));\n lines.push(...frontmatterList(\"sources\", meta.sources));\n lines.push(frontmatterScalar(\"observationCount\", meta.observationCount));\n lines.push(frontmatterScalar(\"contentHash\", meta.contentHash));\n lines.push(\"---\", \"\", body);\n return lines.join(\"\\n\");\n}\n\nfunction parseScalar(raw: string): string {\n try {\n const parsed = JSON.parse(raw);\n return typeof parsed === \"string\" ? parsed : raw;\n } catch {\n return raw;\n }\n}\n\n/** A day document's frontmatter, parsed for idempotency checks and status. */\nexport interface LocationDaySummary {\n date: string;\n timezone: string;\n sources: string[];\n observationCount: number;\n contentHash: string;\n}\n\n/**\n * Parse a day document's frontmatter. Returns null when the content is not a\n * location day document (wrong kind, missing frontmatter) so callers can\n * distinguish a foreign file from a corrupt one.\n */\nexport function parseLocationDaySummary(raw: string): LocationDaySummary | null {\n if (!raw.startsWith(\"---\\n\")) return null;\n const closeIndex = raw.indexOf(\"\\n---\\n\", 4);\n if (closeIndex === -1) return null;\n const scalars: Record<string, string> = {};\n const lists: Record<string, string[]> = {};\n let currentList: string | null = null;\n for (const line of raw.slice(4, closeIndex).split(\"\\n\")) {\n const listItem = /^ {2}- (.*)$/.exec(line);\n if (listItem !== null && currentList !== null) {\n lists[currentList]!.push(parseScalar(listItem[1]!));\n continue;\n }\n currentList = null;\n const separator = line.indexOf(\":\");\n if (separator === -1) continue;\n const key = line.slice(0, separator);\n const value = line.slice(separator + 1).trim();\n if (value === \"\" || value === \"[]\") {\n lists[key] = [];\n currentList = key;\n continue;\n }\n if (value.startsWith(\"[\")) {\n lists[key] = [parseScalar(value)];\n currentList = key;\n continue;\n }\n scalars[key] = value;\n }\n if (scalars.kind === undefined || parseScalar(scalars.kind) !== LOCATION_DAY_KIND) return null;\n if (scalars.date === undefined || scalars.contentHash === undefined) return null;\n return {\n date: parseScalar(scalars.date),\n timezone: scalars.timezone === undefined ? \"UTC\" : parseScalar(scalars.timezone),\n sources: lists.sources ?? [],\n observationCount: scalars.observationCount === undefined ? 0 : Number(scalars.observationCount) || 0,\n contentHash: parseScalar(scalars.contentHash),\n };\n}\n\n// ── Containment-checked day-file IO ─────────────────────────────────────────\n\nfunction isErrnoCode(err: unknown, code: string): boolean {\n return err instanceof Error && (err as NodeJS.ErrnoException).code === code;\n}\n\nasync function assertNotSymlink(target: string, kind: \"directory\" | \"day file\"): Promise<void> {\n let stat: { isSymbolicLink(): boolean };\n try {\n stat = await lstat(target);\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) return;\n throw err;\n }\n if (stat.isSymbolicLink()) {\n throw new Error(\n `locations ${kind} '${path.basename(target)}' is a symbolic link — refusing to follow it even when it resolves inside the memory dir (AGENTS.md pattern #3)`,\n );\n }\n}\n\nasync function assertNoEscape(rootReal: string, candidate: string): Promise<void> {\n let candidateReal: string;\n try {\n candidateReal = await realpath(candidate);\n } catch {\n return;\n }\n if (!pathIsInside(rootReal, candidateReal)) {\n throw new Error(\n \"location day path resolves outside the memory dir — refusing to follow a symlink/traversal (AGENTS.md pattern #3)\",\n );\n }\n}\n\nasync function assertDayPathContained(memoryDir: string, targetPath: string): Promise<void> {\n let rootReal: string;\n try {\n rootReal = await realpath(memoryDir);\n } catch {\n rootReal = path.resolve(memoryDir);\n }\n const locationsDir = path.join(memoryDir, LOCATIONS_DIR_NAME);\n await assertNoEscape(rootReal, locationsDir);\n await assertNoEscape(rootReal, targetPath);\n // Reject a symlinked locations root or day file outright — even when the\n // link resolves inside the memory dir (aliasing / tampering) — before IO.\n await assertNotSymlink(locationsDir, \"directory\");\n await assertNotSymlink(targetPath, \"day file\");\n}\n\n/**\n * Idempotently persist a day document: skip the write when the on-disk\n * contentHash already matches. The write is atomic and containment-checked;\n * the caller (pipeline) advances sync state only after this resolves.\n */\nexport async function writeLocationDay(\n memoryDir: string,\n date: string,\n serialized: string,\n): Promise<boolean> {\n const target = locationDayFilePath(memoryDir, date);\n await assertDayPathContained(memoryDir, target);\n try {\n if ((await readFile(target, \"utf-8\")) === serialized) return false;\n } catch (err) {\n if (!isErrnoCode(err, \"ENOENT\")) throw err;\n }\n await mkdir(path.dirname(target), { recursive: true, mode: 0o700 });\n await writeFileAtomically(target, serialized);\n return true;\n}\n\n/** Read a stored day document's raw markdown; null when absent. */\nexport async function readLocationDay(memoryDir: string, date: string): Promise<string | null> {\n const target = locationDayFilePath(memoryDir, date);\n await assertDayPathContained(memoryDir, target);\n try {\n return await readFile(target, \"utf-8\");\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) return null;\n throw err;\n }\n}\n\n/** List dates that have a stored day document, newest first. */\nexport async function listLocationDayDates(memoryDir: string): Promise<string[]> {\n const locationsDir = path.join(memoryDir, LOCATIONS_DIR_NAME);\n await assertDayPathContained(memoryDir, locationsDir);\n let entries: string[];\n try {\n entries = await readdir(locationsDir);\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) return [];\n throw err;\n }\n const dates = entries\n .filter((entry) => DAY_FILE_NAME_PATTERN.test(entry))\n .map((entry) => entry.slice(0, -3));\n dates.sort((a, b) => (a > b ? -1 : a < b ? 1 : 0));\n return dates;\n}\n","/**\n * Location tagging service (issue #2046) — the IO half around the pure\n * matcher in `matching.ts`. Three consumers share it so the policy can never\n * fork:\n *\n * 1. Write-time enrichment: after an extraction batch has cleared the\n * trust/importance/content-hash gates and persisted, the caller tags the\n * new memories (post-write, best-effort, never fails the extraction).\n * 2. Historical backfill (`location/backfill.ts`): the same plan/apply core\n * over a bounded date range, idempotent by construction.\n * 3. Wearable conversation fill: `WearableConversation.location` is filled\n * ONLY when the source did not provide one and the match passes policy.\n *\n * Segment data comes from the machine-global location sync state\n * (`state/locations/sync.json`, ≤ 90 tracked days — matching the bounded\n * backfill range). Reads are plain file loads; every memory mutation goes\n * through `StorageManager.writeMemoryFrontmatter`, the atomic frontmatter\n * chokepoint that preserves content (and therefore the content hash),\n * lifecycle, and versioning invariants.\n */\n\nimport type { StorageManager } from \"../index.js\";\nimport { log } from \"../logger.js\";\nimport type { MemoryFile } from \"../types.js\";\nimport type { WearableConversation } from \"../wearables/types.js\";\nimport { localDayKey, placeDurations } from \"./intervals.js\";\nimport {\n matchDominantPlace,\n memoryLocationWindow,\n planLocationUpdate,\n type LocationSourceSegments,\n type LocationTagPolicy,\n type LocationUpdatePlan,\n} from \"./matching.js\";\nimport { loadLocationSyncState } from \"./store.js\";\nimport type { LocationConfig } from \"./types.js\";\n\n/** Segments for one local day, per source id, from the sync state. */\nexport type DaySegmentIndex = Map<string, LocationSourceSegments[]>;\n\n/** Load every tracked day's per-source segments (one file read). */\nexport async function loadDaySegmentIndex(memoryDir: string): Promise<DaySegmentIndex> {\n const state = await loadLocationSyncState(memoryDir);\n const index: DaySegmentIndex = new Map();\n for (const [sourceId, source] of Object.entries(state.sources)) {\n for (const [date, payload] of Object.entries(source.days ?? {})) {\n const entry: LocationSourceSegments = { sourceId, segments: payload.segments ?? [] };\n const existing = index.get(date);\n if (existing === undefined) index.set(date, [entry]);\n else existing.push(entry);\n }\n }\n return index;\n}\n\nexport function locationTagPolicy(config: LocationConfig): LocationTagPolicy {\n return {\n minimumOverlapSeconds: config.minimumOverlapSeconds,\n minimumConfidence: config.minimumConfidence,\n retainCoordinates: config.retainCoordinates,\n };\n}\n\n/** Every tagging path is off unless BOTH gates are on. */\nexport function locationTaggingEnabled(config: LocationConfig): boolean {\n return config.enabled && config.tagging.enabled;\n}\n\n/**\n * Write-time post-persist hook (issue #2046): tag the memories an extraction\n * batch just made durable. Best-effort by contract — gated on both location\n * gates, and a location failure must never fail the extraction that already\n * persisted.\n */\nexport async function tagPersistedMemories(\n storage: StorageManager,\n memoryIds: string[],\n config: { memoryDir: string; location?: LocationConfig },\n): Promise<void> {\n if (memoryIds.length === 0 || !config.location || !locationTaggingEnabled(config.location)) return;\n try {\n await enrichMemoriesWithLocation({\n storage,\n memoryIds,\n memoryDir: config.memoryDir,\n config: config.location,\n });\n } catch (locationError) {\n log.warn(\"[location] post-write tagging failed (non-fatal)\", locationError);\n }\n}\n\nfunction segmentsForDays(index: DaySegmentIndex, days: readonly string[]): LocationSourceSegments[] {\n const merged = new Map<string, LocationSourceSegments>();\n for (const day of days) {\n for (const entry of index.get(day) ?? []) {\n const existing = merged.get(entry.sourceId);\n if (existing === undefined) {\n merged.set(entry.sourceId, { sourceId: entry.sourceId, segments: [...entry.segments] });\n continue;\n }\n existing.segments.push(...entry.segments);\n }\n }\n return [...merged.values()];\n}\n\n/** The full plan for one memory: window → segments → match → provider-owned diff. */\nfunction planForMemory(\n frontmatter: Pick<MemoryFile[\"frontmatter\"], \"valid_at\" | \"observedAt\" | \"invalid_at\" | \"tags\" | \"structuredAttributes\">,\n index: DaySegmentIndex,\n config: LocationConfig,\n): LocationUpdatePlan {\n const policy = locationTagPolicy(config);\n const result = memoryLocationWindow(frontmatter, (instant) => localDayKey(instant, config.timezone));\n if (result.rejected === \"span-too-long\") return { outcome: \"span-too-long\" };\n if (result.rejected === \"untimed\" || result.window === undefined || result.days === undefined) {\n return { outcome: \"untimed\" };\n }\n const sources = segmentsForDays(index, result.days);\n return planLocationUpdate(frontmatter, matchDominantPlace(result.window, sources, policy), policy);\n}\n\nexport interface LocationEnrichmentCounts {\n tagged: number;\n updated: number;\n removed: number;\n unchanged: number;\n unmatched: number;\n manual: number;\n untimed: number;\n spanTooLong: number;\n failed: number;\n}\n\nexport function emptyEnrichmentCounts(): LocationEnrichmentCounts {\n return {\n tagged: 0,\n updated: 0,\n removed: 0,\n unchanged: 0,\n unmatched: 0,\n manual: 0,\n untimed: 0,\n spanTooLong: 0,\n failed: 0,\n };\n}\n\nfunction countOutcome(counts: LocationEnrichmentCounts, outcome: LocationUpdatePlan[\"outcome\"]): void {\n if (outcome === \"tagged\") counts.tagged += 1;\n else if (outcome === \"updated\") counts.updated += 1;\n else if (outcome === \"removed\") counts.removed += 1;\n else if (outcome === \"unchanged\") counts.unchanged += 1;\n else if (outcome === \"manual-metadata\") counts.manual += 1;\n else if (outcome === \"unmatched\") counts.unmatched += 1;\n else if (outcome === \"untimed\") counts.untimed += 1;\n else if (outcome === \"span-too-long\") counts.spanTooLong += 1;\n}\n\nexport interface EnrichMemoriesOptions {\n storage: Pick<StorageManager, \"getMemoryById\" | \"writeMemoryFrontmatter\">;\n memoryDir: string;\n config: LocationConfig;\n /** Enrich exactly these memory ids (write-time path). */\n memoryIds?: string[];\n /** Pre-loaded memories (backfill path — one readAllMemories per run). */\n memories?: MemoryFile[];\n /** Reuse a caller-loaded segment index (backfill). */\n index?: DaySegmentIndex;\n /** Skip every mutation and only report (dry-run). */\n dryRun?: boolean;\n}\n\n/**\n * Apply the matcher to a set of memories and patch provider-owned location\n * metadata. A failure on ONE memory is counted and skipped — it never blocks\n * the others (failure isolation, issue #2046).\n */\nexport async function enrichMemoriesWithLocation(\n options: EnrichMemoriesOptions,\n): Promise<LocationEnrichmentCounts> {\n if (!locationTaggingEnabled(options.config)) return emptyEnrichmentCounts();\n const counts = emptyEnrichmentCounts();\n const index = options.index ?? (await loadDaySegmentIndex(options.memoryDir));\n\n let memories = options.memories;\n if (memories === undefined && options.memoryIds !== undefined) {\n memories = [];\n for (const id of options.memoryIds) {\n const memory = await options.storage.getMemoryById(id);\n if (memory !== null) memories.push(memory);\n }\n }\n if (memories === undefined) return counts;\n\n for (const memory of memories) {\n try {\n const plan = planForMemory(memory.frontmatter, index, options.config);\n // Count patch outcomes (tagged/updated/removed) only after the write\n // lands — a rejected write is `failed`, never also `tagged`.\n if (plan.patch === undefined || options.dryRun === true) {\n countOutcome(counts, plan.outcome);\n continue;\n }\n await options.storage.writeMemoryFrontmatter(memory, plan.patch, { actor: \"location-tagging\" });\n countOutcome(counts, plan.outcome);\n } catch {\n counts.failed += 1;\n }\n }\n return counts;\n}\n\n/**\n * Fill `WearableConversation.location` for conversations whose source did not\n * provide one. Missing-only and source-aware: a provider-supplied value is\n * never overwritten, and a failing conversation never blocks the others.\n */\nexport async function fillWearableConversationLocations(\n conversations: WearableConversation[],\n deps: { memoryDir: string; config: LocationConfig },\n): Promise<void> {\n if (!locationTaggingEnabled(deps.config) || conversations.length === 0) return;\n let index: DaySegmentIndex;\n try {\n index = await loadDaySegmentIndex(deps.memoryDir);\n } catch {\n return;\n }\n const policy = locationTagPolicy(deps.config);\n for (const conversation of conversations) {\n if (conversation.location !== undefined && conversation.location.length > 0) continue;\n try {\n const startMs = Date.parse(conversation.startIso);\n const endMs = conversation.endIso !== undefined ? Date.parse(conversation.endIso) : Number.NaN;\n const window =\n Number.isFinite(startMs) && Number.isFinite(endMs) && endMs > startMs\n ? { kind: \"interval\" as const, startUtc: conversation.startIso, endUtc: conversation.endIso as string }\n : { kind: \"instant\" as const, atUtc: conversation.startIso };\n const anchor = window.kind === \"interval\" ? new Date(Date.parse(window.endUtc) - 1).toISOString() : window.atUtc;\n const days = [...new Set([localDayKey(anchor, deps.config.timezone), localDayKey(conversation.startIso, deps.config.timezone)])];\n const outcome = matchDominantPlace(window, segmentsForDays(index, days), policy);\n if (outcome.status === \"matched\") {\n conversation.location = outcome.match.place.label;\n }\n } catch {\n // One bad conversation never blocks the rest of the day's fill.\n }\n }\n}\n\n/** Render an opt-in, labels-only location context section for a day summary. */\nexport async function renderDayLocationContext(\n memoryDir: string,\n date: string,\n config: LocationConfig,\n): Promise<string | null> {\n if (!locationTaggingEnabled(config)) return null;\n const state = await loadLocationSyncState(memoryDir);\n const segments = [];\n for (const source of Object.values(state.sources)) {\n for (const segment of source.days?.[date]?.segments ?? []) segments.push(segment);\n }\n if (segments.length === 0) return null;\n const durations = placeDurations(segments)\n .filter((duration) => [\"home\", \"work\", \"poi\"].includes(duration.place.kind ?? \"poi\"))\n .sort((a, b) => (a.totalMs !== b.totalMs ? b.totalMs - a.totalMs : a.place.id < b.place.id ? -1 : 1));\n if (durations.length === 0) return null;\n const lines = durations.map((duration) => {\n const minutes = Math.round(duration.totalMs / 60_000);\n const hours = Math.floor(minutes / 60);\n const rendered = hours <= 0 ? `${minutes}m` : `${hours}h ${String(minutes % 60).padStart(2, \"0\")}m`;\n return `- ${duration.place.label.replace(/\\s+/g, \" \").replace(/[`*_]/g, \"\").trim()}: ${rendered}`;\n });\n return `## Location context\\n\\n${lines.join(\"\\n\")}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAYO,SAAS,oBAAoB,MAAuB;AACzD,SAAO,oBAAoB,IAAI;AACjC;AAGO,SAAS,kBAAkB,MAAc,UAAwD;AACtG,MAAI,CAAC,oBAAoB,IAAI,GAAG;AAC9B,UAAM,IAAI,WAAW,0BAA0B,IAAI,oCAAoC;AAAA,EACzF;AACA,SAAO,kBAAkB,MAAM,QAAQ;AACzC;AAEA,SAAS,oBAAoB,KAAa,MAAsB;AAC9D,QAAM,KAAK,KAAK,MAAM,GAAG;AACzB,MAAI,OAAO,QAAQ,YAAY,CAAC,OAAO,SAAS,EAAE,GAAG;AACnD,UAAM,IAAI,WAAW,GAAG,IAAI,yCAAyC,OAAO,GAAG,CAAC,GAAG;AAAA,EACrF;AACA,SAAO;AACT;AAGO,SAAS,YAAY,YAAoB,UAA0B;AACxE,sBAAoB,YAAY,YAAY;AAC5C,SAAO,IAAI,KAAK,eAAe,SAAS;AAAA,IACtC,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,EACP,CAAC,EAAE,OAAO,IAAI,KAAK,UAAU,CAAC;AAChC;AAEA,SAAS,oBAAoB,GAAwB,GAAgC;AACnF,MAAI,EAAE,kBAAkB,EAAE,eAAe;AACvC,WAAO,EAAE,gBAAgB,EAAE,gBAAgB,KAAK;AAAA,EAClD;AAGA,MAAI,EAAE,MAAM,OAAO,EAAE,MAAM,IAAI;AAC7B,WAAO,EAAE,MAAM,KAAK,EAAE,MAAM,KAAK,KAAK;AAAA,EACxC;AACA,SAAO;AACT;AAGO,SAAS,wBACd,cACA,UACoC;AACpC,QAAM,UAAU,oBAAI,IAAmC;AACvD,aAAW,eAAe,cAAc;AACtC,wBAAoB,YAAY,eAAe,2BAA2B;AAC1E,UAAM,MAAM,YAAY,YAAY,eAAe,QAAQ;AAC3D,UAAM,SAAS,QAAQ,IAAI,GAAG;AAC9B,QAAI,WAAW,OAAW,SAAQ,IAAI,KAAK,CAAC,WAAW,CAAC;AAAA,QACnD,QAAO,KAAK,WAAW;AAAA,EAC9B;AACA,aAAW,UAAU,QAAQ,OAAO,EAAG,QAAO,KAAK,mBAAmB;AACtE,SAAO;AACT;AAGO,SAAS,kBACd,GACA,GACQ;AACR,QAAM,UACJ,KAAK,IAAI,KAAK,MAAM,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,MAAM,CAAC,IAAI,KAAK,IAAI,KAAK,MAAM,EAAE,QAAQ,GAAG,KAAK,MAAM,EAAE,QAAQ,CAAC;AAChH,SAAO,KAAK,IAAI,GAAG,OAAO;AAC5B;AAEA,SAAS,gBAAgB,OAAsB,mBAA2C;AACxF,MAAI,qBAAqB,MAAM,aAAa,UAAa,MAAM,cAAc,QAAW;AACtF,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,IAAI,MAAM;AAAA,IACV,OAAO,MAAM;AAAA,IACb,GAAI,MAAM,SAAS,SAAY,CAAC,IAAI,EAAE,MAAM,MAAM,KAAK;AAAA,EACzD;AACF;AAUO,SAAS,oBACd,cACA,QACA,SACmB;AACnB,QAAM,UAAU,oBAAoB,OAAO,UAAU,iBAAiB;AACtE,QAAM,QAAQ,oBAAoB,OAAO,QAAQ,eAAe;AAChE,MAAI,WAAW,OAAO;AACpB,UAAM,IAAI,WAAW,gDAAgD;AAAA,EACvE;AACA,QAAM,UAAU,CAAC,GAAG,YAAY,EAAE,KAAK,mBAAmB;AAC1D,QAAM,WAA8B,CAAC;AACrC,WAAS,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACtD,UAAM,UAAU,QAAQ,KAAK;AAC7B,UAAM,YAAY,KAAK,MAAM,QAAQ,aAAa;AAClD,QAAI,YAAY,WAAW,aAAa,OAAO;AAC7C,YAAM,IAAI;AAAA,QACR,4BAA4B,QAAQ,aAAa,kCAAkC,OAAO,QAAQ,KAAK,OAAO,MAAM;AAAA,MACtH;AAAA,IACF;AACA,UAAM,SACJ,QAAQ,IAAI,QAAQ,SAAS,KAAK,MAAM,QAAQ,QAAQ,CAAC,EAAG,aAAa,IAAI;AAC/E,UAAM,eAAe,KAAK,IAAI,QAAQ,KAAK;AAC3C,QAAI,aAAa,aAAc;AAC/B,aAAS,KAAK;AAAA,MACZ,UAAU,IAAI,KAAK,SAAS,EAAE,YAAY;AAAA,MAC1C,QAAQ,IAAI,KAAK,YAAY,EAAE,YAAY;AAAA,MAC3C,OAAO,gBAAgB,QAAQ,OAAO,QAAQ,iBAAiB;AAAA,MAC/D,GAAI,QAAQ,eAAe,SAAY,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;AAAA,IAC/E,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAUA,SAAS,gBAAgB,UAA8C;AAGrE,QAAM,SAAS,SACZ,IAAI,CAAC,aAAa,EAAE,OAAO,KAAK,MAAM,QAAQ,QAAQ,GAAG,KAAK,KAAK,MAAM,QAAQ,MAAM,EAAE,EAAE,EAC3F,KAAK,CAAC,GAAG,MAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAI;AAC3E,MAAI,QAAQ;AACZ,MAAI,aAA4B;AAChC,MAAI,WAAW;AACf,aAAW,SAAS,QAAQ;AAC1B,QAAI,eAAe,QAAQ,MAAM,QAAQ,UAAU;AACjD,UAAI,eAAe,KAAM,UAAS,WAAW;AAC7C,mBAAa,MAAM;AACnB,iBAAW,MAAM;AAAA,IACnB,WAAW,MAAM,MAAM,UAAU;AAC/B,iBAAW,MAAM;AAAA,IACnB;AAAA,EACF;AACA,MAAI,eAAe,KAAM,UAAS,WAAW;AAC7C,SAAO;AACT;AAGO,SAAS,eAAe,UAAuD;AACpF,QAAM,UAAU,oBAAI,IAA0F;AAC9G,aAAW,WAAW,UAAU;AAC9B,UAAM,WAAW,QAAQ,IAAI,QAAQ,MAAM,EAAE;AAC7C,QAAI,aAAa,QAAW;AAC1B,cAAQ,IAAI,QAAQ,MAAM,IAAI,EAAE,OAAO,QAAQ,OAAO,UAAU,CAAC,OAAO,GAAG,eAAe,QAAQ,SAAS,CAAC;AAC5G;AAAA,IACF;AACA,aAAS,SAAS,KAAK,OAAO;AAC9B,QAAI,QAAQ,WAAW,SAAS,cAAe,UAAS,gBAAgB,QAAQ;AAGhF,QAAI,QAAQ,MAAM,QAAQ,SAAS,MAAM,MAAO,UAAS,QAAQ,QAAQ;AAAA,EAC3E;AACA,QAAM,YAA6B,CAAC,GAAG,QAAQ,OAAO,CAAC,EAAE,IAAI,CAAC,WAAW;AAAA,IACvE,OAAO,MAAM;AAAA,IACb,SAAS,gBAAgB,MAAM,QAAQ;AAAA,IACvC,eAAe,MAAM;AAAA,EACvB,EAAE;AACF,YAAU,KAAK,CAAC,GAAG,MAAM;AACvB,QAAI,EAAE,MAAM,OAAO,EAAE,MAAM,GAAI,QAAO,EAAE,MAAM,KAAK,EAAE,MAAM,KAAK,KAAK;AACrE,WAAO;AAAA,EACT,CAAC;AACD,SAAO;AACT;AAYO,SAAS,cAAc,UAAkE;AAC9F,QAAM,YAAY,eAAe,QAAQ;AACzC,MAAI,OAA6B;AACjC,aAAW,YAAY,WAAW;AAChC,QAAI,SAAS,MAAM;AACjB,aAAO;AACP;AAAA,IACF;AACA,QAAI,SAAS,YAAY,KAAK,SAAS;AACrC,UAAI,SAAS,UAAU,KAAK,QAAS,QAAO;AAC5C;AAAA,IACF;AACA,QAAI,SAAS,kBAAkB,KAAK,eAAe;AACjD,UAAI,SAAS,gBAAgB,KAAK,cAAe,QAAO;AACxD;AAAA,IACF;AACA,QAAI,SAAS,MAAM,KAAK,KAAK,MAAM,GAAI,QAAO;AAAA,EAChD;AACA,SAAO,SAAS,OAAO,OAAO,EAAE,OAAO,KAAK,OAAO,SAAS,KAAK,QAAQ;AAC3E;;;AC5LO,IAAM,oCAAoC,KAAK,KAAK,KAAK;AAGzD,IAAM,sBAAsB;AAG5B,IAAM,0BAA0B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,IAAM,uBAA6C,EAAE,MAAM,MAAM,MAAM,MAAM,KAAK,KAAK;AA4BhF,SAAS,qBACd,aACA,UACc;AACd,QAAM,QAAQ,YAAY,YAAY,YAAY;AAClD,MAAI,UAAU,UAAa,OAAO,MAAM,KAAK,MAAM,KAAK,CAAC,GAAG;AAC1D,WAAO,EAAE,UAAU,UAAU;AAAA,EAC/B;AACA,QAAM,MAAM,YAAY;AACxB,MAAI,QAAQ,UAAa,OAAO,MAAM,KAAK,MAAM,GAAG,CAAC,KAAK,KAAK,MAAM,GAAG,KAAK,KAAK,MAAM,KAAK,GAAG;AAC9F,WAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,OAAO,MAAM,GAAG,MAAM,CAAC,SAAS,KAAK,CAAC,EAAE;AAAA,EAC9E;AACA,MAAI,KAAK,MAAM,GAAG,IAAI,KAAK,MAAM,KAAK,IAAI,mCAAmC;AAC3E,WAAO,EAAE,UAAU,gBAAgB;AAAA,EACrC;AAGA,QAAM,cAAc,IAAI,KAAK,KAAK,MAAM,GAAG,IAAI,CAAC,EAAE,YAAY;AAC9D,QAAM,OAAO,CAAC,SAAS,KAAK,CAAC;AAC7B,QAAM,SAAS,SAAS,WAAW;AACnC,MAAI,WAAW,KAAK,CAAC,EAAG,MAAK,KAAK,MAAM;AACxC,SAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,UAAU,OAAO,QAAQ,IAAI,GAAG,KAAK;AAC5E;AAoCA,SAAS,YACP,QACA,SACQ;AACR,MAAI,OAAO,SAAS,WAAW;AAC7B,UAAM,KAAK,KAAK,MAAM,OAAO,KAAK;AAClC,WAAO,MAAM,KAAK,MAAM,QAAQ,QAAQ,KAAK,KAAK,KAAK,MAAM,QAAQ,MAAM,IAAI,IAAI;AAAA,EACrF;AACA,SAAO,KAAK;AAAA,IACV;AAAA,IACA,KAAK,IAAI,KAAK,MAAM,OAAO,MAAM,GAAG,KAAK,MAAM,QAAQ,MAAM,CAAC,IAC5D,KAAK,IAAI,KAAK,MAAM,OAAO,QAAQ,GAAG,KAAK,MAAM,QAAQ,QAAQ,CAAC;AAAA,EACtE;AACF;AAOO,SAAS,mBACd,QACA,SACA,QACc;AACd,QAAM,UAAU,oBAAI,IAA8B;AAClD,aAAW,UAAU,SAAS;AAC5B,eAAW,WAAW,OAAO,UAAU;AACrC,UAAI,qBAAqB,QAAQ,MAAM,QAAQ,EAAE,MAAM,KAAM;AAC7D,YAAM,UAAU,YAAY,QAAQ,OAAO;AAC3C,UAAI,WAAW,EAAG;AAClB,YAAM,WAAW,KAAK,MAAM,QAAQ,MAAM,IAAI,KAAK,MAAM,QAAQ,QAAQ;AACzE,YAAM,WAAW,QAAQ,IAAI,QAAQ,MAAM,EAAE;AAC7C,UAAI,aAAa,QAAW;AAC1B,gBAAQ,IAAI,QAAQ,MAAM,IAAI;AAAA,UAC5B,UAAU,OAAO;AAAA,UACjB,OAAO,QAAQ;AAAA,UACf,WAAW;AAAA,UACX,SAAS;AAAA,UACT,YAAY,QAAQ;AAAA,UACpB,UAAU,QAAQ;AAAA,UAClB,QAAQ,QAAQ;AAAA,QAClB,CAAC;AACD;AAAA,MACF;AAEA,eAAS,aAAa;AACtB,eAAS,WAAW;AACpB,eAAS,aACP,SAAS,eAAe,SACpB,QAAQ,aACR,QAAQ,eAAe,SACrB,SAAS,aACT,KAAK,IAAI,SAAS,YAAY,QAAQ,UAAU;AACxD,UAAI,QAAQ,WAAW,SAAS,SAAU,UAAS,WAAW,QAAQ;AACtE,UAAI,QAAQ,SAAS,SAAS,OAAQ,UAAS,SAAS,QAAQ;AAAA,IAClE;AAAA,EACF;AACA,MAAI,QAAQ,SAAS,EAAG,QAAO,EAAE,QAAQ,aAAa,QAAQ,aAAa;AAE3E,MAAI,OAAgC;AACpC,MAAI,MAAM;AACV,aAAW,aAAa,QAAQ,OAAO,GAAG;AACxC,QAAI,SAAS,QAAQ,UAAU,YAAY,KAAK,WAAW;AACzD,aAAO;AACP,YAAM;AACN;AAAA,IACF;AACA,QAAI,UAAU,cAAc,KAAK,UAAW,OAAM;AAAA,EACpD;AACA,MAAI,SAAS,QAAQ,IAAK,QAAO,EAAE,QAAQ,aAAa,QAAQ,YAAY;AAE5E,QAAM,sBAAsB,OAAO,SAAS,YAAY,KAAK,UAAU,KAAK;AAC5E,MAAI,OAAO,wBAAwB,KAAK,sBAAsB,OAAO,wBAAwB,KAAM;AACjG,WAAO,EAAE,QAAQ,aAAa,QAAQ,wBAAwB;AAAA,EAChE;AACA,MAAI,KAAK,eAAe,UAAa,KAAK,aAAa,OAAO,mBAAmB;AAC/E,WAAO,EAAE,QAAQ,aAAa,QAAQ,2BAA2B;AAAA,EACnE;AACA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,OAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf,OAAO,KAAK;AAAA,MACZ,WAAW,KAAK;AAAA,MAChB,SAAS,KAAK;AAAA,MACd,GAAI,KAAK,eAAe,SAAY,EAAE,YAAY,KAAK,WAAW,IAAI,CAAC;AAAA,MACvE,eAAe,KAAK;AAAA,MACpB,aAAa,KAAK;AAAA,IACpB;AAAA,EACF;AACF;AAGO,SAAS,gBAAgB,SAAyB;AACvD,QAAM,OAAO,QACV,YAAY,EACZ,QAAQ,eAAe,GAAG,EAK1B,QAAQ,MAAM,EAAE,EAChB,QAAQ,MAAM,EAAE;AACnB,SAAO,KAAK,MAAM,GAAG,WAAW,eAAe,oBAAoB,MAAM;AAC3E;AAGO,SAAS,oBAAoB,SAAyB;AAC3D,SAAO,GAAG,mBAAmB,GAAG,gBAAgB,OAAO,CAAC;AAC1D;AAEA,SAAS,sBAAsB,OAAuB;AACpD,SAAO,MAAM,MAAM,GAAG,4BAA4B,cAAc;AAClE;AAGO,SAAS,2BACd,OACA,QACwB;AACxB,QAAM,aAAqC;AAAA,IACzC,gBAAgB,MAAM;AAAA,IACtB,iBAAiB,sBAAsB,MAAM,MAAM,EAAE;AAAA,IACrD,eAAe,sBAAsB,MAAM,MAAM,KAAK;AAAA,IACtD,GAAI,MAAM,eAAe,SAAY,EAAE,oBAAoB,MAAM,WAAW,QAAQ,CAAC,EAAE,IAAI,CAAC;AAAA,IAC5F,oBAAoB,MAAM;AAAA,IAC1B,kBAAkB,MAAM;AAAA,EAC1B;AACA,MAAI,OAAO,qBAAqB,MAAM,MAAM,aAAa,UAAa,MAAM,MAAM,cAAc,QAAW;AACzG,eAAW,mBAAmB,OAAO,MAAM,MAAM,QAAQ;AACzD,eAAW,oBAAoB,OAAO,MAAM,MAAM,SAAS;AAAA,EAC7D;AACA,SAAO;AACT;AAiBA,SAAS,+BACP,aACS;AACT,OAAK,YAAY,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,IAAI,WAAW,mBAAmB,CAAC,EAAG,QAAO;AACxF,SAAO,OAAO,KAAK,YAAY,wBAAwB,CAAC,CAAC,EAAE;AAAA,IAAK,CAAC,QAC9D,wBAA8C,SAAS,GAAG;AAAA,EAC7D;AACF;AAEA,SAAS,gBAAgB,aAAyE;AAChG,QAAM,SAAS,YAAY,sBAAsB;AACjD,SAAO,OAAO,WAAW,YAAY,OAAO,SAAS;AACvD;AAQO,SAAS,mBACd,aACA,SACA,QACoB;AACpB,MAAI,+BAA+B,WAAW,KAAK,CAAC,gBAAgB,WAAW,GAAG;AAChF,WAAO,EAAE,SAAS,kBAAkB;AAAA,EACtC;AACA,QAAM,OAAO,CAAC,GAAI,YAAY,QAAQ,CAAC,CAAE;AACzC,QAAM,aAAa,EAAE,GAAI,YAAY,wBAAwB,CAAC,EAAG;AACjE,QAAM,mBAAmB,KAAK,UAAU,CAAC,QAAQ,IAAI,WAAW,mBAAmB,CAAC;AACpF,QAAM,sBAAsB,MAAY;AACtC,QAAI,oBAAoB,EAAG,MAAK,OAAO,kBAAkB,CAAC;AAC1D,eAAW,OAAO,wBAAyB,QAAO,WAAW,GAAG;AAAA,EAClE;AAEA,MAAI,QAAQ,WAAW,WAAW;AAChC,QAAI,CAAC,gBAAgB,WAAW,EAAG,QAAO,EAAE,SAAS,YAAY;AACjE,QAAI,mBAAmB,KAAK,EAAE,qBAAqB,aAAa;AAC9D,aAAO,EAAE,SAAS,YAAY;AAAA,IAChC;AACA,wBAAoB;AACpB,WAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,WAAW,GAAG,SAAS,UAAU;AAAA,EACjF;AAEA,QAAM,aAAa,oBAAoB,QAAQ,MAAM,MAAM,EAAE;AAC7D,QAAM,oBAAoB,2BAA2B,QAAQ,OAAO,MAAM;AAC1E,MAAI,KAAK,UAAU,WAAW,WAAW,mBAAmB,GAAG;AAE7D,WAAO,EAAE,SAAS,YAAY;AAAA,EAChC;AACA,QAAM,iBACJ,oBAAoB,KACpB,KAAK,gBAAgB,MAAM,cAC3B,wBAAwB,MAAM,CAAC,QAAQ;AACrC,UAAM,OAAO,kBAAkB,GAAG;AAClC,UAAM,OAAO,WAAW,GAAG;AAC3B,WAAO,SAAS,SAAY,SAAS,SAAY,SAAS;AAAA,EAC5D,CAAC;AACH,MAAI,eAAgB,QAAO,EAAE,SAAS,YAAY;AAElD,MAAI,oBAAoB,EAAG,MAAK,gBAAgB,IAAI;AAAA,MAC/C,MAAK,KAAK,UAAU;AACzB,aAAW,OAAO,wBAAyB,QAAO,WAAW,GAAG;AAChE,SAAO,OAAO,YAAY,iBAAiB;AAC3C,QAAM,mBAAmB,gBAAgB,WAAW;AACpD,SAAO;AAAA,IACL,OAAO,EAAE,MAAM,sBAAsB,WAAW;AAAA,IAChD,SAAS,mBAAmB,YAAY;AAAA,EAC1C;AACF;;;ACrVA,SAAS,kBAAkB;AAC3B,SAAS,OAAO,OAAO,UAAU,SAAS,gBAAgB;AAC1D,OAAO,UAAU;AAOV,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB;AAC1B,IAAM,8BAA8B;AAG3C,IAAM,4BAA4B;AAElC,IAAM,wBAAwB;AAI9B,IAAM,aAAa,oBAAI,IAA8B;AAErD,SAAS,cAAiB,KAAa,IAAkC;AACvE,QAAM,QAAQ,WAAW,IAAI,GAAG,KAAK,QAAQ,QAAQ;AACrD,QAAM,OAAO,MAAM,KAAK,IAAI,EAAE;AAC9B,QAAM,OAAO,KAAK;AAAA,IAChB,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACA,aAAW,IAAI,KAAK,IAAI;AACxB,OAAK,KAAK,KAAK,MAAM;AACnB,QAAI,WAAW,IAAI,GAAG,MAAM,KAAM,YAAW,OAAO,GAAG;AAAA,EACzD,CAAC;AACD,SAAO;AACT;AAEO,SAAS,oBAAoB,WAAmB,MAAsB;AAC3E,MAAI,CAAC,oBAAoB,IAAI,GAAG;AAG9B,UAAM,IAAI,WAAW,0BAA0B,IAAI,oCAAoC;AAAA,EACzF;AACA,SAAO,KAAK,KAAK,WAAW,oBAAoB,GAAG,IAAI,KAAK;AAC9D;AAEO,SAAS,0BAA0B,WAA2B;AACnE,SAAO,KAAK,KAAK,WAAW,SAAS,aAAa,WAAW;AAC/D;AAmBO,SAAS,yBAAgD;AAC9D,SAAO,EAAE,SAAS,GAAG,SAAS,CAAC,EAAE;AACnC;AAEA,eAAsB,sBAAsB,WAAmD;AAC7F,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,SAAS,0BAA0B,SAAS,GAAG,OAAO;AAAA,EACpE,SAAS,KAAK;AACZ,QAAK,IAA8B,SAAS,SAAU,QAAO,uBAAuB;AACpF,UAAM;AAAA,EACR;AACA,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,GAAG;AAAA,EACzB,QAAQ;AAIN,WAAO,uBAAuB;AAAA,EAChC;AACA,MACE,OAAO,WAAW,YAClB,WAAW,QACX,MAAM,QAAQ,MAAM,KACpB,OAAQ,OAAiC,YAAY,YACpD,OAAiC,YAAY,MAC9C;AACA,WAAO,uBAAuB;AAAA,EAChC;AACA,SAAO,EAAE,SAAS,GAAG,SAAU,OAAiC,QAAQ;AAC1E;AAEA,eAAsB,sBACpB,WACA,OACe;AACf,QAAM,MAAM,KAAK,QAAQ,0BAA0B,SAAS,CAAC,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAChG,QAAM;AAAA,IACJ,0BAA0B,SAAS;AAAA,IACnC,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA;AAAA,EACnC;AACF;AAEA,SAAS,gBAAgB,QAAuC;AAC9D,QAAM,OAAO,OAAO;AACpB,MAAI,SAAS,OAAW;AACxB,QAAM,OAAO,OAAO,KAAK,IAAI,EAAE,KAAK,CAAC,GAAG,MAAO,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAE;AAC1E,aAAW,OAAO,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,KAAK,SAAS,yBAAyB,CAAC,GAAG;AACrF,WAAO,KAAK,GAAG;AAAA,EACjB;AACF;AAOA,eAAsB,wBACpB,WACA,UACA,MACA,SACA,gBACgC;AAChC,MAAI,CAAC,oBAAoB,IAAI,GAAG;AAC9B,UAAM,IAAI,WAAW,0BAA0B,IAAI,oCAAoC;AAAA,EACzF;AACA,SAAO,cAAc,0BAA0B,SAAS,GAAG,YAAY;AACrE,UAAM,QAAQ,MAAM,sBAAsB,SAAS;AACnD,UAAM,SAAS,MAAM,QAAQ,QAAQ,KAAK,CAAC;AAC3C,UAAM,OAAO,OAAO,QAAQ,CAAC;AAC7B,SAAK,IAAI,IAAI;AACb,WAAO,OAAO;AACd,WAAO,kBAAkB;AACzB,UAAM,QAAQ,QAAQ,IAAI;AAC1B,eAAW,aAAa,OAAO,OAAO,MAAM,OAAO,EAAG,iBAAgB,SAAS;AAC/E,UAAM,sBAAsB,WAAW,KAAK;AAC5C,WAAO;AAAA,EACT,CAAC;AACH;AAyBO,SAAS,iBAAiB,MAAsB;AACrD,SAAO,WAAW,QAAQ,EAAE,OAAO,MAAM,MAAM,EAAE,OAAO,KAAK;AAC/D;AAEA,SAAS,UAAU,KAAa,UAA0B;AACxD,SAAO,IAAI,KAAK,eAAe,SAAS;AAAA,IACtC,UAAU;AAAA,IACV,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC,EAAE,OAAO,IAAI,KAAK,GAAG,CAAC;AACzB;AAEA,SAAS,eAAe,IAAoB;AAC1C,QAAM,eAAe,KAAK,MAAM,KAAK,GAAM;AAC3C,QAAM,QAAQ,KAAK,MAAM,eAAe,EAAE;AAC1C,QAAM,UAAU,eAAe;AAC/B,MAAI,SAAS,EAAG,QAAO,GAAG,OAAO;AACjC,SAAO,GAAG,KAAK,KAAK,OAAO,OAAO,EAAE,SAAS,GAAG,GAAG,CAAC;AACtD;AAGA,SAAS,UAAU,OAAuB;AACxC,SAAO,MAAM,QAAQ,QAAQ,GAAG,EAAE,QAAQ,UAAU,EAAE,EAAE,KAAK;AAC/D;AAEA,SAAS,iBAAiB,SAAkC;AAC1D,QAAM,QAAQ,UAAU,QAAQ,MAAM,KAAK;AAC3C,SAAO,QAAQ,MAAM,SAAS,SAAY,QAAQ,GAAG,KAAK,KAAK,QAAQ,MAAM,IAAI;AACnF;AAEA,SAAS,kBAAkB,SAAkC;AAC3D,MAAI,QAAQ,MAAM,aAAa,UAAa,QAAQ,MAAM,cAAc,OAAW,QAAO;AAC1F,SAAO,MAAM,QAAQ,MAAM,SAAS,QAAQ,CAAC,CAAC,IAAI,QAAQ,MAAM,UAAU,QAAQ,CAAC,CAAC;AACtF;AAEO,SAAS,uBACd,MACA,UACA,SACQ;AACR,QAAM,QAAkB,CAAC,yBAAoB,IAAI,KAAK,QAAQ,KAAK,EAAE;AACrE,QAAM,cAAiC,CAAC;AACxC,MAAI,mBAAmB;AACvB,aAAW,SAAS,OAAO,OAAO,OAAO,GAAG;AAC1C,gBAAY,KAAK,GAAG,MAAM,QAAQ;AAClC,wBAAoB,MAAM;AAAA,EAC5B;AAEA,QAAM,KAAK,cAAc,EAAE;AAC3B,MAAI,qBAAqB,GAAG;AAC1B,UAAM,KAAK,sCAAsC,EAAE;AAAA,EACrD,OAAO;AACL,UAAM,YAAY,eAAe,WAAW,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;AAClF,UAAM;AAAA,MACJ,qBAAqB,UAAU,MAAM;AAAA,MACrC,GAAG,UAAU;AAAA,QACX,CAAC,aAAa,KAAK,UAAU,SAAS,MAAM,KAAK,CAAC,KAAK,eAAe,SAAS,OAAO,CAAC;AAAA,MACzF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,OAAO,KAAK,OAAO,EAAE,KAAK,CAAC,GAAG,MAAO,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAE;AAClF,aAAW,YAAY,WAAW;AAChC,UAAM,QAAQ,QAAQ,QAAQ;AAC9B,UAAM,KAAK,sBAAiB,UAAU,MAAM,uBAAuB,QAAQ,CAAC,IAAI,EAAE;AAClF,QAAI,MAAM,SAAS,WAAW,GAAG;AAC/B,YAAM,KAAK,oBAAoB,EAAE;AACjC;AAAA,IACF;AACA,eAAW,WAAW,MAAM,UAAU;AACpC,YAAM;AAAA,QACJ,KAAK,UAAU,QAAQ,UAAU,QAAQ,CAAC,SAAI,UAAU,QAAQ,QAAQ,QAAQ,CAAC,WAAM,iBAAiB,OAAO,CAAC,GAAG,kBAAkB,OAAO,CAAC;AAAA,MAC/I;AAAA,IACF;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AACA,SAAO,GAAG,MAAM,KAAK,IAAI,EAAE,QAAQ,CAAC;AAAA;AACtC;AAEO,SAAS,uBACd,MACA,UACA,SACA,MACiB;AACjB,MAAI,mBAAmB;AACvB,aAAW,SAAS,OAAO,OAAO,OAAO,EAAG,qBAAoB,MAAM;AACtE,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,SAAS,OAAO,KAAK,OAAO,EAAE,KAAK,CAAC,GAAG,MAAO,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAE;AAAA,IACzE;AAAA,IACA,aAAa,iBAAiB,IAAI;AAAA,EACpC;AACF;AAEA,SAAS,kBAAkB,KAAa,OAAgC;AACtE,SAAO,GAAG,GAAG,KAAK,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK,CAAC;AAC7E;AAEA,SAAS,gBAAgB,KAAa,QAAqC;AACzE,MAAI,OAAO,WAAW,EAAG,QAAO,CAAC,GAAG,GAAG,MAAM;AAC7C,QAAM,QAAQ,CAAC,GAAG,GAAG,GAAG;AACxB,aAAW,SAAS,OAAQ,OAAM,KAAK,OAAO,KAAK,UAAU,KAAK,CAAC,EAAE;AACrE,SAAO;AACT;AAEO,SAAS,qBAAqB,MAAuB,MAAsB;AAChF,QAAM,QAAkB,CAAC,KAAK;AAC9B,QAAM,KAAK,kBAAkB,QAAQ,KAAK,IAAI,CAAC;AAC/C,QAAM,KAAK,kBAAkB,QAAQ,KAAK,IAAI,CAAC;AAC/C,QAAM,KAAK,kBAAkB,YAAY,KAAK,QAAQ,CAAC;AACvD,QAAM,KAAK,kBAAkB,iBAAiB,KAAK,aAAa,CAAC;AACjE,QAAM,KAAK,GAAG,gBAAgB,WAAW,KAAK,OAAO,CAAC;AACtD,QAAM,KAAK,kBAAkB,oBAAoB,KAAK,gBAAgB,CAAC;AACvE,QAAM,KAAK,kBAAkB,eAAe,KAAK,WAAW,CAAC;AAC7D,QAAM,KAAK,OAAO,IAAI,IAAI;AAC1B,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,YAAY,KAAqB;AACxC,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,WAAO,OAAO,WAAW,WAAW,SAAS;AAAA,EAC/C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAgBO,SAAS,wBAAwB,KAAwC;AAC9E,MAAI,CAAC,IAAI,WAAW,OAAO,EAAG,QAAO;AACrC,QAAM,aAAa,IAAI,QAAQ,WAAW,CAAC;AAC3C,MAAI,eAAe,GAAI,QAAO;AAC9B,QAAM,UAAkC,CAAC;AACzC,QAAM,QAAkC,CAAC;AACzC,MAAI,cAA6B;AACjC,aAAW,QAAQ,IAAI,MAAM,GAAG,UAAU,EAAE,MAAM,IAAI,GAAG;AACvD,UAAM,WAAW,eAAe,KAAK,IAAI;AACzC,QAAI,aAAa,QAAQ,gBAAgB,MAAM;AAC7C,YAAM,WAAW,EAAG,KAAK,YAAY,SAAS,CAAC,CAAE,CAAC;AAClD;AAAA,IACF;AACA,kBAAc;AACd,UAAM,YAAY,KAAK,QAAQ,GAAG;AAClC,QAAI,cAAc,GAAI;AACtB,UAAM,MAAM,KAAK,MAAM,GAAG,SAAS;AACnC,UAAM,QAAQ,KAAK,MAAM,YAAY,CAAC,EAAE,KAAK;AAC7C,QAAI,UAAU,MAAM,UAAU,MAAM;AAClC,YAAM,GAAG,IAAI,CAAC;AACd,oBAAc;AACd;AAAA,IACF;AACA,QAAI,MAAM,WAAW,GAAG,GAAG;AACzB,YAAM,GAAG,IAAI,CAAC,YAAY,KAAK,CAAC;AAChC,oBAAc;AACd;AAAA,IACF;AACA,YAAQ,GAAG,IAAI;AAAA,EACjB;AACA,MAAI,QAAQ,SAAS,UAAa,YAAY,QAAQ,IAAI,MAAM,kBAAmB,QAAO;AAC1F,MAAI,QAAQ,SAAS,UAAa,QAAQ,gBAAgB,OAAW,QAAO;AAC5E,SAAO;AAAA,IACL,MAAM,YAAY,QAAQ,IAAI;AAAA,IAC9B,UAAU,QAAQ,aAAa,SAAY,QAAQ,YAAY,QAAQ,QAAQ;AAAA,IAC/E,SAAS,MAAM,WAAW,CAAC;AAAA,IAC3B,kBAAkB,QAAQ,qBAAqB,SAAY,IAAI,OAAO,QAAQ,gBAAgB,KAAK;AAAA,IACnG,aAAa,YAAY,QAAQ,WAAW;AAAA,EAC9C;AACF;AAIA,SAAS,YAAY,KAAc,MAAuB;AACxD,SAAO,eAAe,SAAU,IAA8B,SAAS;AACzE;AAEA,eAAe,iBAAiB,QAAgB,MAA+C;AAC7F,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,MAAM,MAAM;AAAA,EAC3B,SAAS,KAAK;AACZ,QAAI,YAAY,KAAK,QAAQ,EAAG;AAChC,UAAM;AAAA,EACR;AACA,MAAI,KAAK,eAAe,GAAG;AACzB,UAAM,IAAI;AAAA,MACR,aAAa,IAAI,KAAK,KAAK,SAAS,MAAM,CAAC;AAAA,IAC7C;AAAA,EACF;AACF;AAEA,eAAe,eAAe,UAAkB,WAAkC;AAChF,MAAI;AACJ,MAAI;AACF,oBAAgB,MAAM,SAAS,SAAS;AAAA,EAC1C,QAAQ;AACN;AAAA,EACF;AACA,MAAI,CAAC,aAAa,UAAU,aAAa,GAAG;AAC1C,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,uBAAuB,WAAmB,YAAmC;AAC1F,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,SAAS,SAAS;AAAA,EACrC,QAAQ;AACN,eAAW,KAAK,QAAQ,SAAS;AAAA,EACnC;AACA,QAAM,eAAe,KAAK,KAAK,WAAW,kBAAkB;AAC5D,QAAM,eAAe,UAAU,YAAY;AAC3C,QAAM,eAAe,UAAU,UAAU;AAGzC,QAAM,iBAAiB,cAAc,WAAW;AAChD,QAAM,iBAAiB,YAAY,UAAU;AAC/C;AAOA,eAAsB,iBACpB,WACA,MACA,YACkB;AAClB,QAAM,SAAS,oBAAoB,WAAW,IAAI;AAClD,QAAM,uBAAuB,WAAW,MAAM;AAC9C,MAAI;AACF,QAAK,MAAM,SAAS,QAAQ,OAAO,MAAO,WAAY,QAAO;AAAA,EAC/D,SAAS,KAAK;AACZ,QAAI,CAAC,YAAY,KAAK,QAAQ,EAAG,OAAM;AAAA,EACzC;AACA,QAAM,MAAM,KAAK,QAAQ,MAAM,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAClE,QAAM,oBAAoB,QAAQ,UAAU;AAC5C,SAAO;AACT;AAGA,eAAsB,gBAAgB,WAAmB,MAAsC;AAC7F,QAAM,SAAS,oBAAoB,WAAW,IAAI;AAClD,QAAM,uBAAuB,WAAW,MAAM;AAC9C,MAAI;AACF,WAAO,MAAM,SAAS,QAAQ,OAAO;AAAA,EACvC,SAAS,KAAK;AACZ,QAAI,YAAY,KAAK,QAAQ,EAAG,QAAO;AACvC,UAAM;AAAA,EACR;AACF;AAGA,eAAsB,qBAAqB,WAAsC;AAC/E,QAAM,eAAe,KAAK,KAAK,WAAW,kBAAkB;AAC5D,QAAM,uBAAuB,WAAW,YAAY;AACpD,MAAI;AACJ,MAAI;AACF,cAAU,MAAM,QAAQ,YAAY;AAAA,EACtC,SAAS,KAAK;AACZ,QAAI,YAAY,KAAK,QAAQ,EAAG,QAAO,CAAC;AACxC,UAAM;AAAA,EACR;AACA,QAAM,QAAQ,QACX,OAAO,CAAC,UAAU,sBAAsB,KAAK,KAAK,CAAC,EACnD,IAAI,CAAC,UAAU,MAAM,MAAM,GAAG,EAAE,CAAC;AACpC,QAAM,KAAK,CAAC,GAAG,MAAO,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAE;AACjD,SAAO;AACT;;;ACpbA,eAAsB,oBAAoB,WAA6C;AACrF,QAAM,QAAQ,MAAM,sBAAsB,SAAS;AACnD,QAAM,QAAyB,oBAAI,IAAI;AACvC,aAAW,CAAC,UAAU,MAAM,KAAK,OAAO,QAAQ,MAAM,OAAO,GAAG;AAC9D,eAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,OAAO,QAAQ,CAAC,CAAC,GAAG;AAC/D,YAAM,QAAgC,EAAE,UAAU,UAAU,QAAQ,YAAY,CAAC,EAAE;AACnF,YAAM,WAAW,MAAM,IAAI,IAAI;AAC/B,UAAI,aAAa,OAAW,OAAM,IAAI,MAAM,CAAC,KAAK,CAAC;AAAA,UAC9C,UAAS,KAAK,KAAK;AAAA,IAC1B;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,kBAAkB,QAA2C;AAC3E,SAAO;AAAA,IACL,uBAAuB,OAAO;AAAA,IAC9B,mBAAmB,OAAO;AAAA,IAC1B,mBAAmB,OAAO;AAAA,EAC5B;AACF;AAGO,SAAS,uBAAuB,QAAiC;AACtE,SAAO,OAAO,WAAW,OAAO,QAAQ;AAC1C;AAQA,eAAsB,qBACpB,SACA,WACA,QACe;AACf,MAAI,UAAU,WAAW,KAAK,CAAC,OAAO,YAAY,CAAC,uBAAuB,OAAO,QAAQ,EAAG;AAC5F,MAAI;AACF,UAAM,2BAA2B;AAAA,MAC/B;AAAA,MACA;AAAA,MACA,WAAW,OAAO;AAAA,MAClB,QAAQ,OAAO;AAAA,IACjB,CAAC;AAAA,EACH,SAAS,eAAe;AACtB,QAAI,KAAK,oDAAoD,aAAa;AAAA,EAC5E;AACF;AAEA,SAAS,gBAAgB,OAAwB,MAAmD;AAClG,QAAM,SAAS,oBAAI,IAAoC;AACvD,aAAW,OAAO,MAAM;AACtB,eAAW,SAAS,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG;AACxC,YAAM,WAAW,OAAO,IAAI,MAAM,QAAQ;AAC1C,UAAI,aAAa,QAAW;AAC1B,eAAO,IAAI,MAAM,UAAU,EAAE,UAAU,MAAM,UAAU,UAAU,CAAC,GAAG,MAAM,QAAQ,EAAE,CAAC;AACtF;AAAA,MACF;AACA,eAAS,SAAS,KAAK,GAAG,MAAM,QAAQ;AAAA,IAC1C;AAAA,EACF;AACA,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC;AAC5B;AAGA,SAAS,cACP,aACA,OACA,QACoB;AACpB,QAAM,SAAS,kBAAkB,MAAM;AACvC,QAAM,SAAS,qBAAqB,aAAa,CAAC,YAAY,YAAY,SAAS,OAAO,QAAQ,CAAC;AACnG,MAAI,OAAO,aAAa,gBAAiB,QAAO,EAAE,SAAS,gBAAgB;AAC3E,MAAI,OAAO,aAAa,aAAa,OAAO,WAAW,UAAa,OAAO,SAAS,QAAW;AAC7F,WAAO,EAAE,SAAS,UAAU;AAAA,EAC9B;AACA,QAAM,UAAU,gBAAgB,OAAO,OAAO,IAAI;AAClD,SAAO,mBAAmB,aAAa,mBAAmB,OAAO,QAAQ,SAAS,MAAM,GAAG,MAAM;AACnG;AAcO,SAAS,wBAAkD;AAChE,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,IACT,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,aAAa;AAAA,IACb,QAAQ;AAAA,EACV;AACF;AAEA,SAAS,aAAa,QAAkC,SAA8C;AACpG,MAAI,YAAY,SAAU,QAAO,UAAU;AAAA,WAClC,YAAY,UAAW,QAAO,WAAW;AAAA,WACzC,YAAY,UAAW,QAAO,WAAW;AAAA,WACzC,YAAY,YAAa,QAAO,aAAa;AAAA,WAC7C,YAAY,kBAAmB,QAAO,UAAU;AAAA,WAChD,YAAY,YAAa,QAAO,aAAa;AAAA,WAC7C,YAAY,UAAW,QAAO,WAAW;AAAA,WACzC,YAAY,gBAAiB,QAAO,eAAe;AAC9D;AAqBA,eAAsB,2BACpB,SACmC;AACnC,MAAI,CAAC,uBAAuB,QAAQ,MAAM,EAAG,QAAO,sBAAsB;AAC1E,QAAM,SAAS,sBAAsB;AACrC,QAAM,QAAQ,QAAQ,SAAU,MAAM,oBAAoB,QAAQ,SAAS;AAE3E,MAAI,WAAW,QAAQ;AACvB,MAAI,aAAa,UAAa,QAAQ,cAAc,QAAW;AAC7D,eAAW,CAAC;AACZ,eAAW,MAAM,QAAQ,WAAW;AAClC,YAAM,SAAS,MAAM,QAAQ,QAAQ,cAAc,EAAE;AACrD,UAAI,WAAW,KAAM,UAAS,KAAK,MAAM;AAAA,IAC3C;AAAA,EACF;AACA,MAAI,aAAa,OAAW,QAAO;AAEnC,aAAW,UAAU,UAAU;AAC7B,QAAI;AACF,YAAM,OAAO,cAAc,OAAO,aAAa,OAAO,QAAQ,MAAM;AAGpE,UAAI,KAAK,UAAU,UAAa,QAAQ,WAAW,MAAM;AACvD,qBAAa,QAAQ,KAAK,OAAO;AACjC;AAAA,MACF;AACA,YAAM,QAAQ,QAAQ,uBAAuB,QAAQ,KAAK,OAAO,EAAE,OAAO,mBAAmB,CAAC;AAC9F,mBAAa,QAAQ,KAAK,OAAO;AAAA,IACnC,QAAQ;AACN,aAAO,UAAU;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AACT;AAOA,eAAsB,kCACpB,eACA,MACe;AACf,MAAI,CAAC,uBAAuB,KAAK,MAAM,KAAK,cAAc,WAAW,EAAG;AACxE,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,oBAAoB,KAAK,SAAS;AAAA,EAClD,QAAQ;AACN;AAAA,EACF;AACA,QAAM,SAAS,kBAAkB,KAAK,MAAM;AAC5C,aAAW,gBAAgB,eAAe;AACxC,QAAI,aAAa,aAAa,UAAa,aAAa,SAAS,SAAS,EAAG;AAC7E,QAAI;AACF,YAAM,UAAU,KAAK,MAAM,aAAa,QAAQ;AAChD,YAAM,QAAQ,aAAa,WAAW,SAAY,KAAK,MAAM,aAAa,MAAM,IAAI,OAAO;AAC3F,YAAM,SACJ,OAAO,SAAS,OAAO,KAAK,OAAO,SAAS,KAAK,KAAK,QAAQ,UAC1D,EAAE,MAAM,YAAqB,UAAU,aAAa,UAAU,QAAQ,aAAa,OAAiB,IACpG,EAAE,MAAM,WAAoB,OAAO,aAAa,SAAS;AAC/D,YAAM,SAAS,OAAO,SAAS,aAAa,IAAI,KAAK,KAAK,MAAM,OAAO,MAAM,IAAI,CAAC,EAAE,YAAY,IAAI,OAAO;AAC3G,YAAM,OAAO,CAAC,GAAG,oBAAI,IAAI,CAAC,YAAY,QAAQ,KAAK,OAAO,QAAQ,GAAG,YAAY,aAAa,UAAU,KAAK,OAAO,QAAQ,CAAC,CAAC,CAAC;AAC/H,YAAM,UAAU,mBAAmB,QAAQ,gBAAgB,OAAO,IAAI,GAAG,MAAM;AAC/E,UAAI,QAAQ,WAAW,WAAW;AAChC,qBAAa,WAAW,QAAQ,MAAM,MAAM;AAAA,MAC9C;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAGA,eAAsB,yBACpB,WACA,MACA,QACwB;AACxB,MAAI,CAAC,uBAAuB,MAAM,EAAG,QAAO;AAC5C,QAAM,QAAQ,MAAM,sBAAsB,SAAS;AACnD,QAAM,WAAW,CAAC;AAClB,aAAW,UAAU,OAAO,OAAO,MAAM,OAAO,GAAG;AACjD,eAAW,WAAW,OAAO,OAAO,IAAI,GAAG,YAAY,CAAC,EAAG,UAAS,KAAK,OAAO;AAAA,EAClF;AACA,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,QAAM,YAAY,eAAe,QAAQ,EACtC,OAAO,CAAC,aAAa,CAAC,QAAQ,QAAQ,KAAK,EAAE,SAAS,SAAS,MAAM,QAAQ,KAAK,CAAC,EACnF,KAAK,CAAC,GAAG,MAAO,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,KAAK,EAAE,MAAM,KAAK,KAAK,CAAE;AACtG,MAAI,UAAU,WAAW,EAAG,QAAO;AACnC,QAAM,QAAQ,UAAU,IAAI,CAAC,aAAa;AACxC,UAAM,UAAU,KAAK,MAAM,SAAS,UAAU,GAAM;AACpD,UAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,UAAM,WAAW,SAAS,IAAI,GAAG,OAAO,MAAM,GAAG,KAAK,KAAK,OAAO,UAAU,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC;AAChG,WAAO,KAAK,SAAS,MAAM,MAAM,QAAQ,QAAQ,GAAG,EAAE,QAAQ,UAAU,EAAE,EAAE,KAAK,CAAC,KAAK,QAAQ;AAAA,EACjG,CAAC;AACD,SAAO;AAAA;AAAA,EAA0B,MAAM,KAAK,IAAI,CAAC;AACnD;","names":[]}
@@ -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/maintenance/graph-edge-decay.ts"],"sourcesContent":["/**\n * Graph-edge decay maintenance job (issue #681 PR 2/3).\n *\n * For each edge in the on-disk JSONL graph stores\n * (`<memoryDir>/state/graphs/{entity,time,causal}.jsonl`) call\n * {@link decayEdgeConfidence} from PR 1/3 and write the decayed edge\n * back to disk via the temp+rename atomic-replace pattern (CLAUDE.md\n * gotcha #54: never delete-before-write).\n *\n * Emits a structured telemetry record per run that the doctor surface\n * (`remnic doctor`) and a tail of the maintenance ledger can consume.\n *\n * Pure-helper-style API (the function takes a `memoryDir` + opts and\n * returns a record); callers wire the cron / MCP tool / CLI surfaces.\n */\n\nimport {\n mkdir,\n readdir,\n readFile,\n rename,\n writeFile,\n} from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport {\n decayEdgeConfidence,\n DEFAULT_DECAY_FLOOR,\n DEFAULT_DECAY_PER_WINDOW,\n DEFAULT_DECAY_WINDOW_MS,\n readEdgeConfidence,\n type DecayOptions,\n} from \"../graph-edge-reinforcement.js\";\nimport {\n graphFilePath,\n graphsDir,\n readEdgesStrict,\n withGraphWriteLock,\n type GraphEdge,\n type GraphType,\n} from \"../graph.js\";\nimport { isSafeRouteNamespace } from \"../routing/engine.js\";\n\n/** Default visibility threshold for the \"below visibility\" telemetry counter. */\nexport const DEFAULT_VISIBILITY_THRESHOLD = 0.2;\n\nconst GRAPH_TYPES: readonly GraphType[] = [\"entity\", \"time\", \"causal\"] as const;\n\n/** Per-edge-type breakdown emitted by {@link runGraphEdgeDecayMaintenance}. */\nexport interface GraphEdgeDecayPerTypeStats {\n type: GraphType;\n edgesTotal: number;\n edgesDecayed: number;\n edgesBelowVisibilityThreshold: number;\n}\n\n/** Top-decayed-entity entry (label + total confidence drop summed across edges). */\nexport interface GraphEdgeDecayTopEntity {\n label: string;\n totalDrop: number;\n edgeCount: number;\n}\n\n/**\n * Telemetry record emitted by every run of the decay job. Persisted to\n * `<memoryDir>/state/graph-edge-decay-status.json` for doctor consumption\n * and (optionally) appended to the maintenance ledger by callers.\n */\nexport interface GraphEdgeDecayTelemetry {\n ranAt: string;\n durationMs: number;\n edgesTotal: number;\n edgesDecayed: number;\n edgesBelowVisibilityThreshold: number;\n topDecayedEntities: GraphEdgeDecayTopEntity[];\n perType: GraphEdgeDecayPerTypeStats[];\n windowMs: number;\n perWindow: number;\n floor: number;\n visibilityThreshold: number;\n}\n\nexport interface GraphEdgeDecayOptions extends DecayOptions {\n /** Confidence threshold below which an edge counts as \"low visibility\". */\n visibilityThreshold?: number;\n /** Override \"now\" for deterministic testing. Defaults to `new Date().toISOString()`. */\n now?: string;\n /** When `true`, do not write decayed edges back — just compute telemetry. */\n dryRun?: boolean;\n}\n\n/** Path of the latest-run status file. */\nexport function graphEdgeDecayStatusPath(memoryDir: string): string {\n return path.join(memoryDir, \"state\", \"graph-edge-decay-status.json\");\n}\n\n/** Write a JSONL file atomically using temp+rename (CLAUDE.md gotcha #54). */\nasync function writeJsonlAtomic(filePath: string, edges: GraphEdge[]): Promise<void> {\n await mkdir(path.dirname(filePath), { recursive: true });\n const body = edges.length === 0 ? \"\" : edges.map((e) => JSON.stringify(e)).join(\"\\n\") + \"\\n\";\n // Codex P2 / gotcha #54: write to temp then rename. Never rmSync(target)\n // before the rename succeeds; rename is atomic on the same filesystem.\n // Include pid + monotonic-ish suffix so concurrent runs cannot collide.\n const tempPath = `${filePath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;\n await writeFile(tempPath, body, \"utf-8\");\n await rename(tempPath, filePath);\n}\n\n/**\n * Run a single decay pass over every edge type.\n *\n * Idempotency: PR 1/3's `decayEdgeConfidence` advances `lastReinforcedAt`\n * by exactly the windows it just charged for, so a second run with the\n * same `now` (or any `now` inside the new grace window) is a no-op.\n *\n * Returns the telemetry record. The record is also persisted to\n * {@link graphEdgeDecayStatusPath} so doctor / CLI can read the last run\n * without re-scanning the graphs.\n */\nexport async function runGraphEdgeDecayMaintenance(\n memoryDir: string,\n options: GraphEdgeDecayOptions = {},\n): Promise<GraphEdgeDecayTelemetry> {\n const startedAt = Date.now();\n const ranAt = options.now ?? new Date().toISOString();\n const windowMs = options.windowMs ?? DEFAULT_DECAY_WINDOW_MS;\n const perWindow = options.perWindow ?? DEFAULT_DECAY_PER_WINDOW;\n const floor = options.floor ?? DEFAULT_DECAY_FLOOR;\n const visibilityThreshold =\n typeof options.visibilityThreshold === \"number\" && Number.isFinite(options.visibilityThreshold)\n ? Math.max(0, Math.min(1, options.visibilityThreshold))\n : DEFAULT_VISIBILITY_THRESHOLD;\n const dryRun = options.dryRun === true;\n\n await mkdir(graphsDir(memoryDir), { recursive: true });\n\n const perType: GraphEdgeDecayPerTypeStats[] = [];\n // Aggregate per-label decay drops across ALL graph types so the\n // \"top decayed entities\" list reflects whichever label dominated\n // each edge (entity name, threadId, or causal phrase). Sorting by\n // total confidence drop highlights the edges decay actually moved\n // most in this pass.\n const dropByLabel = new Map<string, { totalDrop: number; edgeCount: number }>();\n\n let edgesTotal = 0;\n let edgesDecayed = 0;\n let edgesBelowVisibilityThreshold = 0;\n\n for (const type of GRAPH_TYPES) {\n const filePath = graphFilePath(memoryDir, type);\n\n // Hold the per-graph-file write lock across BOTH the read-snapshot\n // and the atomic rewrite so concurrent `appendEdge()` calls cannot\n // sneak in between (issue #729 / Codex P1, line 224). Without this\n // lock the snapshot rewrite would silently drop any edge appended\n // by extraction during the same window. Read failures other than\n // ENOENT are surfaced via `readEdgesStrict` so I/O outages cannot\n // be reported as \"no edges to decay\" (Codex P1, line 120).\n const {\n typeDecayed,\n typeBelow,\n typeTotal,\n } = await withGraphWriteLock(filePath, async () => {\n const edges = await readEdgesStrict(memoryDir, type);\n const updated: GraphEdge[] = new Array(edges.length);\n\n let localDecayed = 0;\n let localBelow = 0;\n let localChangedAny = false;\n\n for (let i = 0; i < edges.length; i += 1) {\n const edge = edges[i];\n const before = readEdgeConfidence(edge);\n const decayed = decayEdgeConfidence(edge, ranAt, { windowMs, perWindow, floor });\n const after = readEdgeConfidence(decayed);\n\n // Only count as \"decayed\" when the confidence actually dropped.\n // `decayEdgeConfidence` may return an unchanged copy (still inside\n // the grace window, or already at/below the floor) — those are\n // visited but not decayed.\n if (after < before) {\n localDecayed += 1;\n const drop = before - after;\n const label = typeof edge.label === \"string\" ? edge.label : \"\";\n // Skip empty labels in the top list — surfacing them produces\n // a meaningless \"\" entry that crowds the report.\n if (label.length > 0) {\n const prev = dropByLabel.get(label);\n if (prev) {\n prev.totalDrop += drop;\n prev.edgeCount += 1;\n } else {\n dropByLabel.set(label, { totalDrop: drop, edgeCount: 1 });\n }\n }\n }\n if (after < visibilityThreshold) {\n localBelow += 1;\n }\n updated[i] = decayed;\n // Detect any structural change (confidence OR lastReinforcedAt anchor advance)\n // so we only rewrite the JSONL when there's something to persist.\n if (\n decayed.confidence !== edge.confidence ||\n decayed.lastReinforcedAt !== edge.lastReinforcedAt\n ) {\n localChangedAny = true;\n }\n }\n\n if (!dryRun && localChangedAny && edges.length > 0) {\n await writeJsonlAtomic(filePath, updated);\n }\n\n return {\n typeDecayed: localDecayed,\n typeBelow: localBelow,\n typeTotal: edges.length,\n };\n });\n\n edgesDecayed += typeDecayed;\n edgesBelowVisibilityThreshold += typeBelow;\n edgesTotal += typeTotal;\n perType.push({\n type,\n edgesTotal: typeTotal,\n edgesDecayed: typeDecayed,\n edgesBelowVisibilityThreshold: typeBelow,\n });\n }\n\n // Stable secondary key on label keeps ordering deterministic when two\n // labels happen to have exactly the same totalDrop (gotcha #19).\n const topDecayedEntities: GraphEdgeDecayTopEntity[] = [...dropByLabel.entries()]\n .map(([label, agg]) => ({ label, totalDrop: agg.totalDrop, edgeCount: agg.edgeCount }))\n .sort((a, b) => {\n if (b.totalDrop !== a.totalDrop) return b.totalDrop - a.totalDrop;\n return a.label.localeCompare(b.label);\n })\n .slice(0, 5);\n\n const telemetry: GraphEdgeDecayTelemetry = {\n ranAt,\n durationMs: Date.now() - startedAt,\n edgesTotal,\n edgesDecayed,\n edgesBelowVisibilityThreshold,\n topDecayedEntities,\n perType,\n windowMs,\n perWindow,\n floor,\n visibilityThreshold,\n };\n\n if (!dryRun) {\n await persistTelemetry(memoryDir, telemetry);\n }\n\n return telemetry;\n}\n\nasync function persistTelemetry(\n memoryDir: string,\n telemetry: GraphEdgeDecayTelemetry,\n): Promise<void> {\n const statusPath = graphEdgeDecayStatusPath(memoryDir);\n await mkdir(path.dirname(statusPath), { recursive: true });\n const tempPath = `${statusPath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;\n // Wrap I/O in try/catch (gotcha #13) — failing to persist telemetry must\n // not blow up the maintenance run; the in-memory record is still returned.\n try {\n await writeFile(tempPath, JSON.stringify(telemetry, null, 2) + \"\\n\", \"utf-8\");\n await rename(tempPath, statusPath);\n } catch {\n // Best-effort: callers still receive the in-memory telemetry record.\n }\n}\n\n/** Read the last persisted decay-run telemetry, if any. */\nexport async function readGraphEdgeDecayStatus(\n memoryDir: string,\n): Promise<GraphEdgeDecayTelemetry | null> {\n try {\n const raw = await readFile(graphEdgeDecayStatusPath(memoryDir), \"utf-8\");\n const parsed = JSON.parse(raw);\n // Validate the parsed payload is a plain object (gotcha #18: JSON.parse('null') is valid).\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return null;\n }\n return parsed as GraphEdgeDecayTelemetry;\n } catch {\n return null;\n }\n}\n\n/**\n * Per-namespace telemetry record returned by\n * {@link runGraphEdgeDecayMaintenanceAcrossNamespaces}. Each entry\n * pairs the namespace name with its decay telemetry (or an error\n * string if that namespace's run failed). Allows operators to spot\n * I/O outages on a single namespace without masking the rest.\n */\nexport interface GraphEdgeDecayNamespaceResult {\n namespace: string;\n storageRoot: string;\n telemetry?: GraphEdgeDecayTelemetry;\n error?: string;\n}\n\n/**\n * Discover every namespace storage root that may contain graph files.\n *\n * Returns a list of `{ namespace, storageRoot }` entries:\n * - The default namespace at `memoryDir` (always present).\n * - Each subdirectory under `memoryDir/namespaces/` that passes\n * `isSafeRouteNamespace`.\n *\n * Per gotcha #42: read paths must enumerate the same namespace layer\n * as write paths so non-default namespaces don't get skipped during\n * maintenance. Issue #729 / Codex P2.\n */\nexport async function discoverGraphNamespaceRoots(\n memoryDir: string,\n options: { namespacesEnabled: boolean; defaultNamespace: string },\n): Promise<{ namespace: string; storageRoot: string }[]> {\n const seen = new Map<string, string>();\n // Default namespace always lives at memoryDir (NamespaceStorageRouter\n // falls back to memoryDir when memoryDir/namespaces/<default> does\n // not exist).\n seen.set(options.defaultNamespace, memoryDir);\n\n if (!options.namespacesEnabled) {\n return [...seen.entries()].map(([namespace, storageRoot]) => ({ namespace, storageRoot }));\n }\n\n const namespacesDir = path.join(memoryDir, \"namespaces\");\n let entries: import(\"node:fs\").Dirent[];\n try {\n entries = await readdir(namespacesDir, { withFileTypes: true });\n } catch {\n // No namespaces dir yet — only the default namespace exists.\n return [...seen.entries()].map(([namespace, storageRoot]) => ({ namespace, storageRoot }));\n }\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (!isSafeRouteNamespace(entry.name)) continue;\n const root = path.join(namespacesDir, entry.name);\n seen.set(entry.name, root);\n }\n\n return [...seen.entries()].map(([namespace, storageRoot]) => ({ namespace, storageRoot }));\n}\n\n/**\n * Run the decay maintenance pass against every namespace storage root.\n *\n * In namespaces-enabled deployments, non-default namespaces store\n * their graph JSONLs under `memoryDir/namespaces/<ns>/state/graphs/`,\n * so a single-root run only updates the default namespace and silently\n * skips the rest (issue #729 / Codex P2).\n *\n * Failures in one namespace do not block other namespaces; per-root\n * errors are surfaced in the `error` field of each result.\n */\nexport async function runGraphEdgeDecayMaintenanceAcrossNamespaces(\n memoryDir: string,\n options: GraphEdgeDecayOptions & {\n namespacesEnabled: boolean;\n defaultNamespace: string;\n },\n): Promise<GraphEdgeDecayNamespaceResult[]> {\n const { namespacesEnabled, defaultNamespace, ...decayOptions } = options;\n const roots = await discoverGraphNamespaceRoots(memoryDir, {\n namespacesEnabled,\n defaultNamespace,\n });\n\n const results: GraphEdgeDecayNamespaceResult[] = [];\n for (const { namespace, storageRoot } of roots) {\n try {\n const telemetry = await runGraphEdgeDecayMaintenance(storageRoot, decayOptions);\n results.push({ namespace, storageRoot, telemetry });\n } catch (err) {\n results.push({\n namespace,\n storageRoot,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n return results;\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":[]}