@remnic/core 9.7.15 → 9.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (929) hide show
  1. package/dist/access-admin-ops-surface.d.ts +13 -6
  2. package/dist/access-admin-ops-surface.js +85 -71
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-boundary.d.ts +35 -17
  5. package/dist/access-boundary.js +86 -74
  6. package/dist/access-citation.d.ts +28 -0
  7. package/dist/access-citation.js +9 -0
  8. package/dist/access-cli.js +194 -178
  9. package/dist/access-cli.js.map +1 -1
  10. package/dist/access-errors.d.ts +16 -1
  11. package/dist/access-errors.js +7 -3
  12. package/dist/access-http.d.ts +25 -19
  13. package/dist/access-http.js +100 -87
  14. package/dist/access-identity-continuity-surface.d.ts +13 -8
  15. package/dist/access-identity-continuity-surface.js +85 -71
  16. package/dist/access-lcm-surface.d.ts +16 -9
  17. package/dist/access-lcm-surface.js +85 -71
  18. package/dist/access-mcp.d.ts +23 -16
  19. package/dist/access-mcp.js +96 -84
  20. package/dist/access-memory-search-fanout.d.ts +93 -0
  21. package/dist/access-memory-search-fanout.js +18 -0
  22. package/dist/access-observe-write-surface.d.ts +26 -8
  23. package/dist/access-observe-write-surface.js +85 -71
  24. package/dist/access-operations-batch.js +92 -80
  25. package/dist/access-operations.d.ts +29 -22
  26. package/dist/access-operations.js +94 -82
  27. package/dist/access-recall-concurrency.d.ts +250 -0
  28. package/dist/access-recall-concurrency.js +157 -0
  29. package/dist/access-recall-response.d.ts +130 -0
  30. package/dist/access-recall-response.js +147 -0
  31. package/dist/access-recall-surface.d.ts +15 -7
  32. package/dist/access-recall-surface.js +85 -71
  33. package/dist/access-schema.d.ts +98 -98
  34. package/dist/access-schema.js +8 -6
  35. package/dist/{access-service-DpcYZ9Nl.d.ts → access-service-DEL4qCrc.d.ts} +25 -32
  36. package/dist/access-service.d.ts +13 -6
  37. package/dist/access-service.js +89 -72
  38. package/dist/access-surface-catalog.d.ts +23 -16
  39. package/dist/access-surface-catalog.js +1 -0
  40. package/dist/access-surface-catalog.js.map +1 -1
  41. package/dist/access-token-capabilities.d.ts +2 -1
  42. package/dist/access-token-capabilities.js +4 -2
  43. package/dist/action-confidence.d.ts +3 -1
  44. package/dist/active-memory-bridge.d.ts +3 -1
  45. package/dist/active-memory-bridge.js +4 -4
  46. package/dist/active-recall.d.ts +4 -1
  47. package/dist/active-recall.js +23 -13
  48. package/dist/active-recall.js.map +1 -1
  49. package/dist/adapters/index.js +4 -4
  50. package/dist/adapters/registry.js +2 -2
  51. package/dist/{auto-sync-AAMTVZMK.js → auto-sync-UZG3XQZ5.js} +14 -8
  52. package/dist/{auto-sync-AAMTVZMK.js.map → auto-sync-UZG3XQZ5.js.map} +1 -1
  53. package/dist/behavior-learner.d.ts +3 -1
  54. package/dist/behavior-signals.d.ts +3 -1
  55. package/dist/bootstrap.d.ts +12 -7
  56. package/dist/bootstrap.js +2 -2
  57. package/dist/bounded-jsonl-state.d.ts +54 -0
  58. package/dist/bounded-jsonl-state.js +10 -0
  59. package/dist/boxes.js +2 -2
  60. package/dist/briefing.d.ts +5 -2
  61. package/dist/briefing.js +34 -24
  62. package/dist/buffer-surprise-report.d.ts +3 -1
  63. package/dist/buffer.d.ts +60 -2
  64. package/dist/buffer.js +3 -3
  65. package/dist/bulk-import/index.d.ts +5 -3
  66. package/dist/calibration.d.ts +3 -1
  67. package/dist/calibration.js +6 -6
  68. package/dist/capabilities.d.ts +7 -7
  69. package/dist/capabilities.js +1 -1
  70. package/dist/{capsule-crypto-CZJSLEFG.js → capsule-crypto-YO5QJ6L3.js} +3 -3
  71. package/dist/capsule-crypto-YO5QJ6L3.js.map +1 -0
  72. package/dist/{catalog-C9444P10.d.ts → catalog-BWqHb5HT.d.ts} +1 -1
  73. package/dist/causal-behavior.d.ts +3 -1
  74. package/dist/causal-behavior.js +6 -6
  75. package/dist/causal-chain.js +4 -4
  76. package/dist/causal-consolidation.d.ts +3 -1
  77. package/dist/causal-consolidation.js +43 -34
  78. package/dist/causal-consolidation.js.map +1 -1
  79. package/dist/causal-retrieval.js +6 -6
  80. package/dist/causal-trajectory-graph.d.ts +3 -1
  81. package/dist/causal-trajectory-graph.js +1 -1
  82. package/dist/causal-trajectory.js +1 -1
  83. package/dist/{chunk-A3GOMRJG.js → chunk-23L3IXFD.js} +2 -2
  84. package/dist/chunk-2CGLBUW3.js +15 -0
  85. package/dist/chunk-2CGLBUW3.js.map +1 -0
  86. package/dist/{chunk-MRHFJV44.js → chunk-2DQ2XREU.js} +2 -2
  87. package/dist/{chunk-QKQYXZVS.js → chunk-2EJOEICD.js} +1819 -1481
  88. package/dist/chunk-2EJOEICD.js.map +1 -0
  89. package/dist/{chunk-L2B3EE7B.js → chunk-2QMKMVHH.js} +2 -2
  90. package/dist/{chunk-VJVNLNDQ.js → chunk-2UFO7X4Q.js} +7 -7
  91. package/dist/{chunk-2MR3MFQB.js → chunk-2VEOKUPP.js} +3 -3
  92. package/dist/chunk-2Z24E5W2.js +22 -0
  93. package/dist/chunk-2Z24E5W2.js.map +1 -0
  94. package/dist/{chunk-RHOZ5LLO.js → chunk-347WD2LE.js} +2 -2
  95. package/dist/{chunk-HDTQVNWD.js → chunk-3QAH2S33.js} +3 -3
  96. package/dist/{chunk-37CTGERM.js → chunk-3WCASNQZ.js} +12 -1
  97. package/dist/chunk-3WCASNQZ.js.map +1 -0
  98. package/dist/{chunk-LRNMRXJO.js → chunk-3Y224NYC.js} +3 -3
  99. package/dist/{chunk-3IY64MV6.js → chunk-44XZ75OQ.js} +44 -10
  100. package/dist/chunk-44XZ75OQ.js.map +1 -0
  101. package/dist/{chunk-VFSP73LP.js → chunk-45GF7Y3V.js} +2 -2
  102. package/dist/{chunk-K7LOWSLU.js → chunk-4BJQODZF.js} +2479 -1520
  103. package/dist/chunk-4BJQODZF.js.map +1 -0
  104. package/dist/{chunk-JREB6UFH.js → chunk-57OWKFUQ.js} +17 -6
  105. package/dist/chunk-57OWKFUQ.js.map +1 -0
  106. package/dist/{chunk-OEHCMALU.js → chunk-5I4M26Q7.js} +5 -5
  107. package/dist/{chunk-2AZXIZEN.js → chunk-5Q7EVV4X.js} +6 -6
  108. package/dist/{chunk-LC7OODWZ.js → chunk-5SB7SC2G.js} +80 -49
  109. package/dist/chunk-5SB7SC2G.js.map +1 -0
  110. package/dist/{chunk-PUBTHW5O.js → chunk-6DRPPQEJ.js} +2 -2
  111. package/dist/{chunk-NWTGD4AN.js → chunk-6KIQT7RG.js} +10 -9
  112. package/dist/chunk-6KIQT7RG.js.map +1 -0
  113. package/dist/{chunk-FDCTQWLW.js → chunk-6O22TZSB.js} +3 -3
  114. package/dist/{chunk-ZQ7UBUZ6.js → chunk-6QYST5XN.js} +6 -6
  115. package/dist/{chunk-W4PGTAS2.js → chunk-6WAFYNVT.js} +3 -3
  116. package/dist/chunk-6ZMAMSHS.js +20 -0
  117. package/dist/chunk-6ZMAMSHS.js.map +1 -0
  118. package/dist/{chunk-R5VAVVHP.js → chunk-72A4L5JJ.js} +2 -2
  119. package/dist/{chunk-X64YLC24.js → chunk-72VAXGEI.js} +5 -13
  120. package/dist/chunk-72VAXGEI.js.map +1 -0
  121. package/dist/{chunk-IKQTFQMI.js → chunk-755Q3DGF.js} +22 -3
  122. package/dist/chunk-755Q3DGF.js.map +1 -0
  123. package/dist/{chunk-OVJ2HIPE.js → chunk-76GLCM57.js} +158 -125
  124. package/dist/chunk-76GLCM57.js.map +1 -0
  125. package/dist/{chunk-D7FOKIY5.js → chunk-7AMFUATK.js} +12 -9
  126. package/dist/{chunk-D7FOKIY5.js.map → chunk-7AMFUATK.js.map} +1 -1
  127. package/dist/{chunk-BFVEEB7W.js → chunk-7ON2JW73.js} +57 -22
  128. package/dist/chunk-7ON2JW73.js.map +1 -0
  129. package/dist/chunk-7RNBVZZO.js +270 -0
  130. package/dist/chunk-7RNBVZZO.js.map +1 -0
  131. package/dist/{chunk-3FAMU5TX.js → chunk-A6USBZTO.js} +2 -2
  132. package/dist/{chunk-ZHIVCODT.js → chunk-A72SWTWW.js} +7 -7
  133. package/dist/{chunk-FC77VUX5.js → chunk-A7Q43EUZ.js} +2 -2
  134. package/dist/{chunk-UJBESW6X.js → chunk-AE7WMV4V.js} +7 -7
  135. package/dist/{chunk-J2HSAU72.js → chunk-AIK5W3IW.js} +29 -1
  136. package/dist/chunk-AIK5W3IW.js.map +1 -0
  137. package/dist/{chunk-A5UXZRRM.js → chunk-AJ7QCSIS.js} +2 -2
  138. package/dist/{chunk-FNMFJWBY.js → chunk-ANEUPF6O.js} +5 -5
  139. package/dist/chunk-AREGMX2J.js +50 -0
  140. package/dist/chunk-AREGMX2J.js.map +1 -0
  141. package/dist/chunk-AVPXXV6J.js +448 -0
  142. package/dist/chunk-AVPXXV6J.js.map +1 -0
  143. package/dist/{chunk-2A3OXAP2.js → chunk-B7RWBZXW.js} +2 -2
  144. package/dist/{chunk-GWTFLF2P.js → chunk-BJMBJZ2Y.js} +59 -59
  145. package/dist/chunk-BJMBJZ2Y.js.map +1 -0
  146. package/dist/{chunk-74F5STS4.js → chunk-BLAKS3CP.js} +4 -4
  147. package/dist/{chunk-M7VGG3ID.js → chunk-BV5WMSIJ.js} +9 -9
  148. package/dist/{chunk-2BFLDH5F.js → chunk-BXLOS5AJ.js} +2 -2
  149. package/dist/{chunk-UXKMMNJD.js → chunk-C23BYTJV.js} +6 -6
  150. package/dist/{chunk-JZHHREBL.js → chunk-C3AKM55W.js} +2 -2
  151. package/dist/{chunk-RP7YXA67.js → chunk-C5JF6EZ7.js} +2 -2
  152. package/dist/{chunk-T7Y5KPLN.js → chunk-C6XBRYVD.js} +16 -15
  153. package/dist/chunk-C6XBRYVD.js.map +1 -0
  154. package/dist/{chunk-FTYDWKO6.js → chunk-CEN6DW6X.js} +12 -2
  155. package/dist/chunk-CEN6DW6X.js.map +1 -0
  156. package/dist/chunk-CGASUJVP.js +421 -0
  157. package/dist/chunk-CGASUJVP.js.map +1 -0
  158. package/dist/{chunk-EHCONI6E.js → chunk-CQMEM5CC.js} +2 -2
  159. package/dist/{chunk-PBNZVPFS.js → chunk-CXZQOVIE.js} +12 -12
  160. package/dist/chunk-D3V3UMET.js +44 -0
  161. package/dist/chunk-D3V3UMET.js.map +1 -0
  162. package/dist/{chunk-7N2RUBAP.js → chunk-DDA47TES.js} +2 -2
  163. package/dist/{chunk-64SE4X5G.js → chunk-DEBHXHJR.js} +3 -3
  164. package/dist/{chunk-EHK6KZHK.js → chunk-DNHVPZOD.js} +2 -2
  165. package/dist/{chunk-437S3G37.js → chunk-DQEMWVMT.js} +2 -2
  166. package/dist/{chunk-LZZNTPLR.js → chunk-DX3XRGLH.js} +2 -2
  167. package/dist/chunk-EA2H5LML.js +72 -0
  168. package/dist/chunk-EA2H5LML.js.map +1 -0
  169. package/dist/{chunk-INELTPRG.js → chunk-EEC7UJPX.js} +103 -106
  170. package/dist/chunk-EEC7UJPX.js.map +1 -0
  171. package/dist/{chunk-KSNVDPDF.js → chunk-EKBNDKDY.js} +21 -20
  172. package/dist/chunk-EKBNDKDY.js.map +1 -0
  173. package/dist/{chunk-YF6FMLBT.js → chunk-EQWEIIKQ.js} +64 -34
  174. package/dist/chunk-EQWEIIKQ.js.map +1 -0
  175. package/dist/{chunk-DZKHSDOM.js → chunk-ES36HTSC.js} +4 -4
  176. package/dist/{chunk-TN7THW5U.js → chunk-ET356KSB.js} +2 -2
  177. package/dist/{chunk-YNDLCWXS.js → chunk-EZ25VE3G.js} +4 -4
  178. package/dist/{chunk-DMSDUGDM.js → chunk-F7GAIWFA.js} +20 -20
  179. package/dist/{chunk-G6XXLKC5.js → chunk-FFPJINJE.js} +6 -6
  180. package/dist/chunk-FMLKOL2Z.js +636 -0
  181. package/dist/chunk-FMLKOL2Z.js.map +1 -0
  182. package/dist/chunk-FQC3DHH2.js +20 -0
  183. package/dist/chunk-FQC3DHH2.js.map +1 -0
  184. package/dist/{chunk-G4CN3ZXL.js → chunk-FUTF72MJ.js} +15 -15
  185. package/dist/chunk-GCASGYIO.js +71 -0
  186. package/dist/chunk-GCASGYIO.js.map +1 -0
  187. package/dist/{chunk-HF77M34J.js → chunk-GFPZS3F5.js} +8 -8
  188. package/dist/{chunk-BCDKBDSY.js → chunk-GNVZQ5JN.js} +99 -41
  189. package/dist/chunk-GNVZQ5JN.js.map +1 -0
  190. package/dist/{chunk-G6NKALRN.js → chunk-H4WG3UQZ.js} +2 -2
  191. package/dist/{chunk-UDQUSU27.js → chunk-HNZKVLAN.js} +2 -2
  192. package/dist/{chunk-5EZXHU36.js → chunk-HYQJQGD3.js} +2 -2
  193. package/dist/{chunk-OAZVR2BV.js → chunk-IDZFBSHN.js} +8 -6
  194. package/dist/{chunk-OAZVR2BV.js.map → chunk-IDZFBSHN.js.map} +1 -1
  195. package/dist/{chunk-PLQE6MJA.js → chunk-IFH6LWTO.js} +50 -8
  196. package/dist/chunk-IFH6LWTO.js.map +1 -0
  197. package/dist/{chunk-RULE4VG5.js → chunk-ILGC6JH6.js} +21 -6
  198. package/dist/chunk-ILGC6JH6.js.map +1 -0
  199. package/dist/chunk-IUM3VSHI.js +113 -0
  200. package/dist/chunk-IUM3VSHI.js.map +1 -0
  201. package/dist/{chunk-DCFV7A7H.js → chunk-IYNGIMVG.js} +101 -91
  202. package/dist/chunk-IYNGIMVG.js.map +1 -0
  203. package/dist/{chunk-TRWPCR6P.js → chunk-JECBQBEX.js} +3 -3
  204. package/dist/{chunk-E6CBU7XP.js → chunk-JYIFGGEM.js} +2 -2
  205. package/dist/{chunk-VA4WSW54.js → chunk-JYIJNNN3.js} +3 -3
  206. package/dist/{chunk-L5HJQC36.js → chunk-K2TDK7GG.js} +3 -3
  207. package/dist/{chunk-KDXVOFYY.js → chunk-KAVBJSBQ.js} +4 -4
  208. package/dist/{chunk-BS4SGLWV.js → chunk-KF5EUVKQ.js} +16 -6
  209. package/dist/chunk-KF5EUVKQ.js.map +1 -0
  210. package/dist/chunk-KFZY2OFH.js +42 -0
  211. package/dist/chunk-KFZY2OFH.js.map +1 -0
  212. package/dist/{chunk-4OKLXWDZ.js → chunk-KNB7IBBU.js} +2 -2
  213. package/dist/{chunk-QLULYKWZ.js → chunk-KSXJOC4F.js} +2 -2
  214. package/dist/{chunk-2S6QHZGJ.js → chunk-L2DPF4DF.js} +1 -1
  215. package/dist/{chunk-JI5AVXYO.js → chunk-LEPOP46W.js} +6 -6
  216. package/dist/{chunk-O7BBFJLP.js → chunk-LTAVSOZW.js} +2 -2
  217. package/dist/{chunk-E3VODCC3.js → chunk-LUDXM7MD.js} +14 -2
  218. package/dist/{chunk-E3VODCC3.js.map → chunk-LUDXM7MD.js.map} +1 -1
  219. package/dist/{chunk-2IZAGAJR.js → chunk-LULR4IUW.js} +3 -3
  220. package/dist/{chunk-QQGPUKMT.js → chunk-MC5Q3J7S.js} +398 -7
  221. package/dist/chunk-MC5Q3J7S.js.map +1 -0
  222. package/dist/{chunk-WMWVO45V.js → chunk-MC6XO7T4.js} +2 -2
  223. package/dist/chunk-MKQBXQKU.js +107 -0
  224. package/dist/chunk-MKQBXQKU.js.map +1 -0
  225. package/dist/{chunk-7PND4PUC.js → chunk-MMGGVZ4Q.js} +29 -9
  226. package/dist/{chunk-7PND4PUC.js.map → chunk-MMGGVZ4Q.js.map} +1 -1
  227. package/dist/{chunk-D6RIFG4O.js → chunk-MNB5RMAY.js} +2 -2
  228. package/dist/{chunk-Q5WG43OP.js → chunk-MYFQ3ED4.js} +7 -7
  229. package/dist/{chunk-V3UE5I5F.js → chunk-MYVPLJOO.js} +2 -2
  230. package/dist/chunk-NINSR6LX.js +83 -0
  231. package/dist/chunk-NINSR6LX.js.map +1 -0
  232. package/dist/{chunk-MTWKDOVO.js → chunk-NLE6TSLG.js} +2 -2
  233. package/dist/{chunk-DBRYEIGY.js → chunk-OJP3N7UK.js} +2 -2
  234. package/dist/{chunk-VDW4VU7B.js → chunk-OQJIB32H.js} +28 -23
  235. package/dist/chunk-OQJIB32H.js.map +1 -0
  236. package/dist/{chunk-SMX5267P.js → chunk-OZKOPQCM.js} +2 -2
  237. package/dist/{chunk-JCK7V6SN.js → chunk-P65YJEEL.js} +2 -2
  238. package/dist/{chunk-MTR7BZQN.js → chunk-PBGWYM3H.js} +3 -3
  239. package/dist/chunk-PIG4WJFQ.js +87 -0
  240. package/dist/chunk-PIG4WJFQ.js.map +1 -0
  241. package/dist/chunk-PQVCH2AE.js +76 -0
  242. package/dist/chunk-PQVCH2AE.js.map +1 -0
  243. package/dist/{chunk-AXTXN4T6.js → chunk-PWFCHOB3.js} +2 -2
  244. package/dist/{chunk-FDPZVY6D.js → chunk-QFN4U7AG.js} +2 -2
  245. package/dist/{chunk-K2ZLHESQ.js → chunk-QIEUU4UK.js} +2 -2
  246. package/dist/{chunk-DYP3YYJJ.js → chunk-QJAQNXWI.js} +39 -5
  247. package/dist/chunk-QJAQNXWI.js.map +1 -0
  248. package/dist/{chunk-3D6AFGQR.js → chunk-QVT3E4CE.js} +7 -7
  249. package/dist/{chunk-FIJUY7GG.js → chunk-R26ZMXR2.js} +23 -23
  250. package/dist/{chunk-FIJUY7GG.js.map → chunk-R26ZMXR2.js.map} +1 -1
  251. package/dist/chunk-R3DJVOSM.js +34 -0
  252. package/dist/chunk-R3DJVOSM.js.map +1 -0
  253. package/dist/{chunk-SFQ6QNL7.js → chunk-R6YJI3HE.js} +2 -1
  254. package/dist/{chunk-5CJVLG3H.js → chunk-RFDD3B7W.js} +5 -5
  255. package/dist/{chunk-JBPKEARU.js → chunk-RKNJBZ55.js} +4 -4
  256. package/dist/chunk-ROI7BK7H.js +88 -0
  257. package/dist/chunk-ROI7BK7H.js.map +1 -0
  258. package/dist/{chunk-FNZQGN76.js → chunk-S2BBISHU.js} +4 -4
  259. package/dist/{chunk-IALLX7EE.js → chunk-S2FSBU4H.js} +3 -3
  260. package/dist/{chunk-BFPETA3S.js → chunk-SCCO46KZ.js} +3 -2
  261. package/dist/chunk-SCCO46KZ.js.map +1 -0
  262. package/dist/chunk-SICXL4MK.js +165 -0
  263. package/dist/chunk-SICXL4MK.js.map +1 -0
  264. package/dist/chunk-SK7AMF2J.js +168 -0
  265. package/dist/chunk-SK7AMF2J.js.map +1 -0
  266. package/dist/{chunk-LZOV7MX7.js → chunk-TDTXKOAJ.js} +6474 -5747
  267. package/dist/chunk-TDTXKOAJ.js.map +1 -0
  268. package/dist/{chunk-KSBEEMQF.js → chunk-TG6IHVE2.js} +151 -6
  269. package/dist/chunk-TG6IHVE2.js.map +1 -0
  270. package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
  271. package/dist/{chunk-DPAENM7O.js → chunk-U3ZAVRP3.js} +2 -2
  272. package/dist/{chunk-ODPLEWB6.js → chunk-UFGFMWAD.js} +47 -17
  273. package/dist/chunk-UFGFMWAD.js.map +1 -0
  274. package/dist/{chunk-4KJLYTLS.js → chunk-V57NLO5P.js} +2 -2
  275. package/dist/{chunk-FLVL4L3L.js → chunk-VDX2J7OX.js} +2 -2
  276. package/dist/{chunk-AJLLIIML.js → chunk-W4FBGYGK.js} +1 -1
  277. package/dist/{chunk-TXLGHDHS.js → chunk-W4XJFLAL.js} +53 -32
  278. package/dist/chunk-W4XJFLAL.js.map +1 -0
  279. package/dist/{chunk-6SXVCD7W.js → chunk-W7IGLX4G.js} +2 -2
  280. package/dist/{chunk-KQDNAXOM.js → chunk-WG5HSQ4P.js} +19 -6
  281. package/dist/chunk-WG5HSQ4P.js.map +1 -0
  282. package/dist/{chunk-LTJAMRGI.js → chunk-WL5EBRDH.js} +17 -3
  283. package/dist/chunk-WL5EBRDH.js.map +1 -0
  284. package/dist/{chunk-KAWTOYAW.js → chunk-WLZYGLJ4.js} +2 -2
  285. package/dist/{chunk-RO4LQGT3.js → chunk-WON4APQY.js} +4 -4
  286. package/dist/{chunk-PQVK2S3J.js → chunk-WZFAPHIK.js} +6 -6
  287. package/dist/{chunk-KQPJLK3X.js → chunk-XL24QQ63.js} +2 -2
  288. package/dist/{chunk-RVZRYUQH.js → chunk-YROFNEG5.js} +7 -7
  289. package/dist/{chunk-RAR2BSEM.js → chunk-YV32N67O.js} +1 -1
  290. package/dist/chunk-YV32N67O.js.map +1 -0
  291. package/dist/{chunk-PBSAPHHA.js → chunk-YVKF3HEW.js} +1 -1
  292. package/dist/chunk-YVKF3HEW.js.map +1 -0
  293. package/dist/{chunk-VRAD2FGO.js → chunk-Z54EM5YZ.js} +12 -12
  294. package/dist/{chunk-2VN4JAX7.js → chunk-ZOKZIR5K.js} +95 -33
  295. package/dist/chunk-ZOKZIR5K.js.map +1 -0
  296. package/dist/{cli-Cd5fMmhq.d.ts → cli-C_pqqTCw.d.ts} +28 -12
  297. package/dist/cli.d.ts +16 -9
  298. package/dist/cli.js +142 -127
  299. package/dist/compounding/engine.d.ts +5 -2
  300. package/dist/compounding/engine.js +36 -26
  301. package/dist/compounding/preference-consolidator.d.ts +3 -1
  302. package/dist/compounding/preference-consolidator.js +1 -1
  303. package/dist/compression-optimizer.d.ts +3 -1
  304. package/dist/config-qmd.d.ts +8 -0
  305. package/dist/config-qmd.js +20 -0
  306. package/dist/config-qmd.js.map +1 -0
  307. package/dist/config.d.ts +3 -1
  308. package/dist/config.js +15 -10
  309. package/dist/connectors/codex-materialize-runner.d.ts +3 -1
  310. package/dist/connectors/codex-materialize-runner.js +36 -26
  311. package/dist/connectors/codex-materialize.d.ts +3 -1
  312. package/dist/connectors/codex-materialize.js +2 -2
  313. package/dist/connectors/index.d.ts +3 -1
  314. package/dist/connectors/index.js +41 -32
  315. package/dist/consolidation-provenance-check.d.ts +5 -2
  316. package/dist/consolidation-undo.d.ts +5 -2
  317. package/dist/contradiction/index.d.ts +5 -2
  318. package/dist/contradiction/index.js +10 -4
  319. package/dist/{contradiction-scan-J57T5QV7.js → contradiction-scan-RJBABNRH.js} +4 -4
  320. package/dist/contradiction-scan-RJBABNRH.js.map +1 -0
  321. package/dist/conversation-index/backend.d.ts +3 -1
  322. package/dist/conversation-index/backend.js +5 -5
  323. package/dist/conversation-index/chunker.d.ts +3 -1
  324. package/dist/conversation-index/cleanup.js +2 -2
  325. package/dist/conversation-index/faiss-adapter.d.ts +3 -1
  326. package/dist/conversation-index/faiss-adapter.js +2 -2
  327. package/dist/conversation-index/indexer.d.ts +3 -1
  328. package/dist/conversation-index/indexer.js +2 -2
  329. package/dist/conversation-index/search.d.ts +3 -1
  330. package/dist/conversation-index/search.js +2 -2
  331. package/dist/cross-namespace-budget.d.ts +45 -1
  332. package/dist/cross-namespace-budget.js +5 -3
  333. package/dist/dashboard-runtime.js +2 -2
  334. package/dist/day-summary.d.ts +3 -1
  335. package/dist/day-summary.js +3 -3
  336. package/dist/delinearize.d.ts +3 -1
  337. package/dist/direct-answer-wiring.d.ts +3 -1
  338. package/dist/direct-answer.d.ts +3 -1
  339. package/dist/{dreams-ledger-6UODQOX6.js → dreams-ledger-567VKVOU.js} +4 -2
  340. package/dist/dreams-ledger-567VKVOU.js.map +1 -0
  341. package/dist/embedding-fallback.d.ts +3 -1
  342. package/dist/embedding-fallback.js +3 -3
  343. package/dist/enrichment/index.d.ts +3 -1
  344. package/dist/entity-retrieval.d.ts +5 -2
  345. package/dist/entity-retrieval.js +35 -26
  346. package/dist/entity-schema.d.ts +3 -1
  347. package/dist/explicit-capture.d.ts +13 -8
  348. package/dist/explicit-capture.js +7 -3
  349. package/dist/extraction-faithfulness.d.ts +3 -1
  350. package/dist/extraction-faithfulness.js +5 -5
  351. package/dist/extraction-judge-telemetry.d.ts +3 -1
  352. package/dist/extraction-judge-telemetry.js +2 -2
  353. package/dist/extraction-judge-training.d.ts +3 -1
  354. package/dist/extraction-judge-training.js +2 -2
  355. package/dist/extraction-judge.d.ts +3 -1
  356. package/dist/extraction-judge.js +5 -5
  357. package/dist/extraction.d.ts +3 -1
  358. package/dist/extraction.js +13 -12
  359. package/dist/faithfulness-config.js +3 -2
  360. package/dist/fallback-llm.d.ts +3 -1
  361. package/dist/fallback-llm.js +4 -4
  362. package/dist/{first-start-migration-TI67YMLG.js → first-start-migration-CSRHCJIQ.js} +2 -2
  363. package/dist/{forget-CQCLB5LB.js → forget-HRPLVB3W.js} +5 -5
  364. package/dist/graph-dashboard-diff.d.ts +3 -1
  365. package/dist/graph-dashboard-key.d.ts +3 -1
  366. package/dist/graph-dashboard-parser.d.ts +3 -1
  367. package/dist/{graph-edge-decay-IOGBBAGC.js → graph-edge-decay-Z6ENALU2.js} +3 -3
  368. package/dist/graph-edge-decay-Z6ENALU2.js.map +1 -0
  369. package/dist/graph-edge-reinforcement.d.ts +3 -1
  370. package/dist/graph-snapshot.d.ts +3 -1
  371. package/dist/graph-snapshot.js +2 -2
  372. package/dist/graph.d.ts +3 -1
  373. package/dist/graph.js +1 -1
  374. package/dist/identity-continuity.d.ts +1 -2
  375. package/dist/importance.d.ts +3 -1
  376. package/dist/importers/index.d.ts +3 -1
  377. package/dist/in-flight-reads.d.ts +3 -1
  378. package/dist/index.d.ts +473 -464
  379. package/dist/index.js +287 -239
  380. package/dist/intent.d.ts +3 -1
  381. package/dist/lcm/archive.js +2 -2
  382. package/dist/lcm/engine.d.ts +3 -1
  383. package/dist/lcm/engine.js +6 -6
  384. package/dist/lcm/index.d.ts +3 -1
  385. package/dist/lcm/index.js +13 -13
  386. package/dist/lcm/schema.js +2 -2
  387. package/dist/lcm/summarizer.js +3 -3
  388. package/dist/lcm/tools.d.ts +3 -1
  389. package/dist/lifecycle.d.ts +3 -1
  390. package/dist/live-connectors-runner.d.ts +3 -1
  391. package/dist/local-llm.d.ts +5 -2
  392. package/dist/local-llm.js +3 -3
  393. package/dist/local-model-endpoint.d.ts +3 -1
  394. package/dist/logger.d.ts +3 -1
  395. package/dist/logger.js +7 -3
  396. package/dist/maintenance/archive-observations.js +2 -2
  397. package/dist/maintenance/memory-governance.d.ts +3 -1
  398. package/dist/maintenance/memory-governance.js +35 -25
  399. package/dist/maintenance/migrate-observations.js +3 -3
  400. package/dist/maintenance/observation-ledger-utils.js +2 -2
  401. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +102 -1
  402. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +37 -25
  403. package/dist/maintenance/rebuild-memory-projection.js +38 -28
  404. package/dist/maintenance/rebuild-observations.js +3 -3
  405. package/dist/mcp-memory-inspector-app.d.ts +22 -15
  406. package/dist/memory-action-policy.d.ts +3 -1
  407. package/dist/memory-cache.d.ts +3 -1
  408. package/dist/memory-lifecycle-ledger-utils.d.ts +25 -2
  409. package/dist/memory-lifecycle-ledger-utils.js +11 -1
  410. package/dist/memory-projection-store.d.ts +3 -1
  411. package/dist/memory-projection-store.js +2 -2
  412. package/dist/memory-provenance.d.ts +3 -1
  413. package/dist/memory-worth-outcomes.d.ts +5 -2
  414. package/dist/model-registry.js +2 -2
  415. package/dist/models-json.d.ts +3 -1
  416. package/dist/models-json.js +2 -2
  417. package/dist/namespaces/migrate.d.ts +6 -3
  418. package/dist/namespaces/migrate.js +51 -42
  419. package/dist/namespaces/principal.d.ts +27 -2
  420. package/dist/namespaces/principal.js +6 -2
  421. package/dist/namespaces/search.d.ts +16 -2
  422. package/dist/namespaces/search.js +24 -20
  423. package/dist/namespaces/storage.d.ts +24 -3
  424. package/dist/namespaces/storage.js +35 -27
  425. package/dist/native-knowledge.d.ts +3 -1
  426. package/dist/native-knowledge.js +2 -2
  427. package/dist/negative.js +2 -2
  428. package/dist/offline-sync-exclude-globs.d.ts +13 -0
  429. package/dist/offline-sync-exclude-globs.js +10 -0
  430. package/dist/offline-sync-exclude-globs.js.map +1 -0
  431. package/dist/offline-sync-impression-drain.d.ts +78 -0
  432. package/dist/offline-sync-impression-drain.js +37 -0
  433. package/dist/offline-sync-impression-drain.js.map +1 -0
  434. package/dist/offline-sync.js +4 -2
  435. package/dist/operator-toolkit.d.ts +5 -2
  436. package/dist/operator-toolkit.js +69 -54
  437. package/dist/orchestration/compression-guideline-coordinator.d.ts +5 -2
  438. package/dist/orchestration/compression-guideline-coordinator.js +3 -3
  439. package/dist/orchestration/maintenance.d.ts +121 -2
  440. package/dist/orchestration/maintenance.js +44 -31
  441. package/dist/{orchestrator-Bp_jeBHK.d.ts → orchestrator-CQJ8U7En.d.ts} +85 -79
  442. package/dist/orchestrator.d.ts +13 -8
  443. package/dist/orchestrator.js +194 -177
  444. package/dist/patterns-cli.d.ts +3 -1
  445. package/dist/{pipeline-BAj5bx7g.d.ts → pipeline-Cn-kvYeV.d.ts} +1 -1
  446. package/dist/policy-runtime.d.ts +3 -1
  447. package/dist/prioritized-embed.d.ts +19 -0
  448. package/dist/prioritized-embed.js +8 -0
  449. package/dist/prioritized-embed.js.map +1 -0
  450. package/dist/proactive-contention.d.ts +28 -0
  451. package/dist/proactive-contention.js +8 -0
  452. package/dist/proactive-contention.js.map +1 -0
  453. package/dist/profiling.js +2 -2
  454. package/dist/provenance.d.ts +3 -1
  455. package/dist/provenance.js +3 -2
  456. package/dist/{purge-NDWV6WYD.js → purge-IRF47ZTX.js} +3 -3
  457. package/dist/{qmd-_MDSlj1m.d.ts → qmd-oh9VXz1d.d.ts} +11 -1
  458. package/dist/qmd-preflight.d.ts +5 -2
  459. package/dist/qmd-recall-cache.d.ts +3 -1
  460. package/dist/qmd-status.d.ts +57 -0
  461. package/dist/qmd-status.js +18 -0
  462. package/dist/qmd-status.js.map +1 -0
  463. package/dist/qmd.d.ts +5 -2
  464. package/dist/qmd.js +7 -3
  465. package/dist/recall-concurrency-config.d.ts +16 -0
  466. package/dist/recall-concurrency-config.js +10 -0
  467. package/dist/recall-concurrency-config.js.map +1 -0
  468. package/dist/recall-disclosure-escalation.d.ts +3 -1
  469. package/dist/recall-explain-renderer.d.ts +4 -1
  470. package/dist/recall-explain-renderer.js +3 -3
  471. package/dist/recall-memory-map.d.ts +26 -0
  472. package/dist/recall-memory-map.js +18 -0
  473. package/dist/recall-memory-map.js.map +1 -0
  474. package/dist/recall-planner-llm.d.ts +3 -1
  475. package/dist/recall-planner-llm.js +4 -4
  476. package/dist/recall-qos.js +2 -2
  477. package/dist/recall-state.d.ts +163 -2
  478. package/dist/recall-state.js +6 -3
  479. package/dist/recall-tag-filter.d.ts +3 -1
  480. package/dist/recall-timings.d.ts +11 -2
  481. package/dist/recall-timings.js +3 -1
  482. package/dist/recall-xray-cli.d.ts +3 -1
  483. package/dist/recall-xray-cli.js +4 -4
  484. package/dist/recall-xray-renderer.d.ts +3 -1
  485. package/dist/recall-xray-renderer.js +3 -3
  486. package/dist/recall-xray.d.ts +3 -1
  487. package/dist/recall-xray.js +2 -2
  488. package/dist/relevance.js +3 -3
  489. package/dist/replay/normalizers/chatgpt.d.ts +3 -1
  490. package/dist/replay/normalizers/claude.d.ts +3 -1
  491. package/dist/replay/normalizers/openclaw.d.ts +3 -1
  492. package/dist/replay/normalizers/shared.d.ts +3 -1
  493. package/dist/replay/runner.d.ts +3 -1
  494. package/dist/replay/types.d.ts +3 -1
  495. package/dist/rerank.d.ts +8 -1
  496. package/dist/rerank.js +3 -1
  497. package/dist/resolution-3K27T4VO.js +18 -0
  498. package/dist/resolution-3K27T4VO.js.map +1 -0
  499. package/dist/resolve-auth-token.d.ts +3 -1
  500. package/dist/resolve-provider-secret.js +2 -2
  501. package/dist/resume-bundles.js +19 -14
  502. package/dist/retrieval-agents.d.ts +19 -16
  503. package/dist/retrieval-agents.js +3 -3
  504. package/dist/retrieval-tiers.d.ts +3 -1
  505. package/dist/routing/engine.d.ts +3 -1
  506. package/dist/routing/store.d.ts +3 -1
  507. package/dist/routing/store.js +2 -2
  508. package/dist/salvage-envelope.d.ts +18 -0
  509. package/dist/salvage-envelope.js +15 -0
  510. package/dist/salvage-envelope.js.map +1 -0
  511. package/dist/schemas.d.ts +98 -98
  512. package/dist/scope-profiles-EpJG7yKP.d.ts +30 -0
  513. package/dist/search/document-scanner.js +3 -2
  514. package/dist/search/embed-helper.d.ts +3 -1
  515. package/dist/search/embed-helper.js +3 -3
  516. package/dist/search/factory.d.ts +3 -1
  517. package/dist/search/factory.js +18 -16
  518. package/dist/search/index.d.ts +3 -1
  519. package/dist/search/index.js +22 -20
  520. package/dist/search/lancedb-backend.d.ts +3 -1
  521. package/dist/search/lancedb-backend.js +6 -5
  522. package/dist/search/meilisearch-backend.d.ts +3 -1
  523. package/dist/search/meilisearch-backend.js +6 -5
  524. package/dist/search/noop-backend.d.ts +3 -1
  525. package/dist/search/orama-backend.d.ts +3 -1
  526. package/dist/search/orama-backend.js +6 -5
  527. package/dist/search/port.d.ts +16 -2
  528. package/dist/search/port.js +1 -1
  529. package/dist/search/remote-backend.d.ts +3 -1
  530. package/dist/search/remote-backend.js +3 -3
  531. package/dist/secure-store/index.d.ts +12 -1
  532. package/dist/secure-store/index.js +6 -3
  533. package/dist/{semantic-consolidation-C2m5eHHE.d.ts → semantic-consolidation-DILZEQq3.d.ts} +1 -1
  534. package/dist/semantic-consolidation.d.ts +4 -2
  535. package/dist/semantic-consolidation.js +38 -29
  536. package/dist/semantic-rule-promotion.js +34 -24
  537. package/dist/semantic-rule-verifier.d.ts +3 -1
  538. package/dist/semantic-rule-verifier.js +35 -25
  539. package/dist/session-observer-bands.d.ts +3 -1
  540. package/dist/session-observer-state.d.ts +3 -1
  541. package/dist/session-observer-state.js +2 -2
  542. package/dist/session-transcript-migration.js +2 -2
  543. package/dist/shared-context/manager.d.ts +11 -9
  544. package/dist/shared-context/manager.js +3 -3
  545. package/dist/signal.d.ts +3 -1
  546. package/dist/{storage-hr_Y2z5R.d.ts → storage-NIyKYD8g.d.ts} +489 -110
  547. package/dist/storage-guards.js +2 -2
  548. package/dist/storage.d.ts +6 -3
  549. package/dist/storage.js +38 -26
  550. package/dist/structured-attributes.d.ts +23 -1
  551. package/dist/structured-attributes.js +7 -1
  552. package/dist/summarizer.d.ts +3 -1
  553. package/dist/summarizer.js +11 -11
  554. package/dist/summary-snapshot.d.ts +3 -1
  555. package/dist/summary-snapshot.js +2 -2
  556. package/dist/temporal-index-batch.d.ts +1 -0
  557. package/dist/temporal-index-batch.js +10 -0
  558. package/dist/temporal-index-batch.js.map +1 -0
  559. package/dist/temporal-index-compat.d.ts +279 -1
  560. package/dist/temporal-index-compat.js +1 -1
  561. package/dist/temporal-index.d.ts +1 -225
  562. package/dist/temporal-index.js +35 -3
  563. package/dist/temporal-supersession.d.ts +5 -2
  564. package/dist/temporal-supersession.js +2 -2
  565. package/dist/temporal-timeline-recall.d.ts +3 -1
  566. package/dist/temporal-validity.d.ts +3 -1
  567. package/dist/threading.d.ts +3 -1
  568. package/dist/threading.js +2 -2
  569. package/dist/tier-migration.d.ts +5 -2
  570. package/dist/tier-routing.d.ts +3 -1
  571. package/dist/{tier-stats-KV7IWCJR.js → tier-stats-QEJSPFV2.js} +2 -2
  572. package/dist/tokens.js +3 -3
  573. package/dist/topics.d.ts +3 -1
  574. package/dist/transcript.d.ts +3 -1
  575. package/dist/transcript.js +2 -2
  576. package/dist/transfer/backup.js +3 -3
  577. package/dist/transfer/capsule-export.js +3 -3
  578. package/dist/transfer/capsule-import.js +3 -3
  579. package/dist/transfer/types.d.ts +90 -90
  580. package/dist/trust-score-stage.d.ts +75 -38
  581. package/dist/trust-score-stage.js +11 -3
  582. package/dist/trust-score.d.ts +3 -1
  583. package/dist/{types-Cg8q7W7_.d.ts → types-D_fG2ix8.d.ts} +39 -63
  584. package/dist/types-continuity.d.ts +52 -0
  585. package/dist/types-continuity.js +1 -0
  586. package/dist/types-continuity.js.map +1 -0
  587. package/dist/types.d.ts +3 -1
  588. package/dist/types.js +1 -1
  589. package/dist/utility-runtime.d.ts +3 -1
  590. package/dist/utils/serialize-mutations.d.ts +31 -2
  591. package/dist/utils/serialize-mutations.js +1 -1
  592. package/dist/verified-recall.js +36 -26
  593. package/dist/write-envelope.d.ts +282 -0
  594. package/dist/write-envelope.js +35 -0
  595. package/dist/write-envelope.js.map +1 -0
  596. package/dist/write-quarantine.d.ts +79 -0
  597. package/dist/write-quarantine.js +11 -0
  598. package/dist/write-quarantine.js.map +1 -0
  599. package/dist/write-rate-limiter.d.ts +45 -0
  600. package/dist/write-rate-limiter.js +9 -0
  601. package/dist/write-rate-limiter.js.map +1 -0
  602. package/package.json +37 -2
  603. package/src/access-admin-ops-surface.ts +17 -7
  604. package/src/access-boundary.test.ts +28 -0
  605. package/src/access-boundary.ts +31 -2
  606. package/src/access-citation.test.ts +72 -0
  607. package/src/access-citation.ts +139 -0
  608. package/src/access-errors.ts +21 -0
  609. package/src/access-fingerprint-parity.test.ts +211 -0
  610. package/src/access-http-cancellation.test.ts +59 -21
  611. package/src/access-http.test.ts +90 -0
  612. package/src/access-http.ts +79 -79
  613. package/src/access-mcp-cancellation.test.ts +16 -7
  614. package/src/access-memory-search-fanout.test.ts +220 -0
  615. package/src/access-memory-search-fanout.ts +168 -0
  616. package/src/access-observe-quarantine.test.ts +120 -0
  617. package/src/access-observe-write-surface.ts +130 -11
  618. package/src/access-operations-batch.ts +2 -0
  619. package/src/access-recall-concurrency.ts +773 -0
  620. package/src/access-recall-response.ts +307 -0
  621. package/src/access-recall-surface.ts +100 -252
  622. package/src/access-service-coding-write.test.ts +22 -4
  623. package/src/access-service-health.test.ts +49 -0
  624. package/src/access-service-namespace.test.ts +486 -8
  625. package/src/access-service-observe-scope.test.ts +4 -0
  626. package/src/access-service-recall-concurrency.test.ts +1990 -0
  627. package/src/access-service.ts +182 -175
  628. package/src/access-surface-catalog.ts +1 -0
  629. package/src/access-token-capabilities.ts +16 -9
  630. package/src/active-recall.test.ts +35 -0
  631. package/src/active-recall.ts +7 -0
  632. package/src/bounded-jsonl-state.ts +93 -0
  633. package/src/buffer-session.test.ts +422 -5
  634. package/src/buffer-surprise-trigger.test.ts +41 -0
  635. package/src/buffer.ts +218 -3
  636. package/src/capabilities-cluster-b.test.ts +1 -0
  637. package/src/capabilities.ts +5 -6
  638. package/src/cli.ts +21 -22
  639. package/src/coding/architecture-surfaces.test.ts +6 -3
  640. package/src/coding/architecture-surfaces.ts +36 -25
  641. package/src/coding/decision-surfaces.ts +42 -34
  642. package/src/compounding/engine.test.ts +5 -1
  643. package/src/compounding/engine.ts +7 -7
  644. package/src/config-qmd.ts +89 -0
  645. package/src/config.test.ts +136 -0
  646. package/src/config.ts +113 -118
  647. package/src/connector-provenance-lifecycle.test.ts +4 -4
  648. package/src/connectors/coerce.test.ts +131 -0
  649. package/src/connectors/coerce.ts +80 -7
  650. package/src/contradiction/contradiction.test.ts +10 -6
  651. package/src/contradiction/resolution.ts +17 -4
  652. package/src/correction/correction-access-wiring.ts +62 -18
  653. package/src/cross-namespace-budget.test.ts +35 -0
  654. package/src/cross-namespace-budget.ts +86 -19
  655. package/src/explicit-capture.ts +54 -17
  656. package/src/extraction.ts +2 -3
  657. package/src/faithfulness-graph-guard.test.ts +16 -69
  658. package/src/graph-recall.test.ts +31 -0
  659. package/src/index.ts +22 -2
  660. package/src/local-llm.ts +4 -6
  661. package/src/logger.ts +16 -0
  662. package/src/maintenance/dreams-ledger.ts +100 -49
  663. package/src/maintenance/rebuild-memory-lifecycle-ledger-cli.ts +77 -0
  664. package/src/maintenance/rebuild-memory-lifecycle-ledger.ts +373 -9
  665. package/src/memory-lifecycle-ledger-utils.ts +51 -5
  666. package/src/namespaces/principal.test.ts +37 -1
  667. package/src/namespaces/principal.ts +48 -0
  668. package/src/namespaces/search.test.ts +79 -5
  669. package/src/namespaces/search.ts +59 -6
  670. package/src/namespaces/storage.ts +43 -1
  671. package/src/offline-sync-exclude-globs.ts +58 -0
  672. package/src/offline-sync-impression-drain.test.ts +316 -0
  673. package/src/offline-sync-impression-drain.ts +260 -0
  674. package/src/offline-sync.test.ts +32 -5
  675. package/src/offline-sync.ts +1 -14
  676. package/src/operator-toolkit.ts +1 -1
  677. package/src/orchestration/batch-deindex-flush.test.ts +146 -0
  678. package/src/orchestration/consolidation-run.ts +96 -85
  679. package/src/orchestration/extraction-envelope.ts +94 -0
  680. package/src/orchestration/extraction-persist-promotion.ts +134 -0
  681. package/src/orchestration/extraction-persist.ts +325 -260
  682. package/src/orchestration/extraction-run.test.ts +1 -1
  683. package/src/orchestration/extraction-run.ts +2 -2
  684. package/src/orchestration/graph-recall-coordinator.ts +18 -7
  685. package/src/orchestration/lifecycle-policy-coordinator.ts +63 -48
  686. package/src/orchestration/maintenance.test.ts +2103 -3
  687. package/src/orchestration/maintenance.ts +574 -2
  688. package/src/orchestration/namespace-read-fanout.ts +14 -8
  689. package/src/orchestration/orchestrator-helpers.ts +8 -1
  690. package/src/orchestration/orchestrator-init.ts +22 -6
  691. package/src/orchestration/orchestrator-namespace-scope.ts +71 -0
  692. package/src/orchestration/persistence-index.ts +64 -9
  693. package/src/orchestration/qmd-result-resolver.ts +27 -0
  694. package/src/orchestration/recall-entry.ts +34 -19
  695. package/src/orchestration/recall-internal.ts +207 -79
  696. package/src/orchestration/recall-rerank-coordinator.ts +229 -82
  697. package/src/orchestration/recall-result-formatter.ts +76 -20
  698. package/src/orchestration/recall-search-pipeline.test.ts +70 -0
  699. package/src/orchestration/recall-search-pipeline.ts +102 -129
  700. package/src/orchestration/recall-section-coordinator.ts +315 -85
  701. package/src/orchestration/semantic-consolidation-coordinator.ts +69 -37
  702. package/src/orchestration/session-context.ts +21 -0
  703. package/src/orchestration/workspace-ops.test.ts +348 -0
  704. package/src/orchestration/workspace-ops.ts +168 -34
  705. package/src/orchestrator-chunked-hash-durability.test.ts +126 -0
  706. package/src/orchestrator-connector-dedup.test.ts +1061 -40
  707. package/src/orchestrator-flush.test.ts +155 -39
  708. package/src/orchestrator-nonchunked-hash-durability.test.ts +121 -0
  709. package/src/orchestrator-source-attribution.test.ts +9 -9
  710. package/src/orchestrator.ts +160 -149
  711. package/src/prioritized-embed.ts +123 -0
  712. package/src/proactive-contention.test.ts +80 -0
  713. package/src/proactive-contention.ts +39 -0
  714. package/src/procedural/procedure-miner.test.ts +19 -14
  715. package/src/procedural/procedure-miner.ts +44 -13
  716. package/src/qmd-client.test.ts +111 -1
  717. package/src/qmd-status.ts +186 -0
  718. package/src/qmd.ts +47 -47
  719. package/src/recall-budget-config.test.ts +30 -0
  720. package/src/recall-cold-deadline.test.ts +149 -0
  721. package/src/recall-concurrency-config.ts +28 -0
  722. package/src/recall-memory-map.ts +74 -0
  723. package/src/recall-rerank-coordinator.test.ts +508 -0
  724. package/src/recall-state.test.ts +825 -1
  725. package/src/recall-state.ts +406 -7
  726. package/src/recall-timings-access.test.ts +41 -0
  727. package/src/recall-timings.ts +16 -0
  728. package/src/relay/mission-access.test.ts +5 -5
  729. package/src/rerank.ts +22 -0
  730. package/src/retrieval-agents.test.ts +79 -0
  731. package/src/retrieval-agents.ts +71 -19
  732. package/src/salvage-envelope.ts +28 -0
  733. package/src/scopes/scope-plan.test.ts +42 -0
  734. package/src/scopes/scope-plan.ts +45 -0
  735. package/src/search/port.ts +13 -0
  736. package/src/secure-store/index.ts +1 -0
  737. package/src/secure-store/secure-fs.ts +48 -0
  738. package/src/secure-store/secure-store.test.ts +40 -0
  739. package/src/semantic-rule-promotion.ts +13 -4
  740. package/src/storage/content-hash-index.ts +655 -0
  741. package/src/storage/entity-timeline.ts +473 -0
  742. package/src/storage/memory-lifecycle-ledger-access.ts +603 -0
  743. package/src/storage/secure-line-reader.test.ts +197 -0
  744. package/src/storage/secure-line-reader.ts +181 -3
  745. package/src/storage-append-header-sniff.test.ts +195 -0
  746. package/src/storage-behavior-signals-cache.test.ts +237 -0
  747. package/src/storage-contract/cache-coherence.test.ts +96 -1
  748. package/src/storage-contract/content-hash.test.ts +47 -2
  749. package/src/storage-fact-hash-index-defer.test.ts +1200 -0
  750. package/src/storage-memory-lifecycle-ledger.test.ts +1146 -3
  751. package/src/storage.ts +882 -890
  752. package/src/structured-attributes.ts +52 -0
  753. package/src/temporal-index-batch.ts +112 -0
  754. package/src/temporal-index.test.ts +193 -0
  755. package/src/temporal-index.ts +49 -53
  756. package/src/testing/lifecycle-matrix.test.ts +212 -0
  757. package/src/testing/lifecycle-matrix.ts +271 -0
  758. package/src/testing/orchestrator-lite.ts +236 -0
  759. package/src/testing/subjects/dreams-ledger.test.ts +67 -0
  760. package/src/testing/subjects/extraction-lifecycle.test.ts +442 -0
  761. package/src/testing/subjects/lifecycle-ledger.test.ts +93 -0
  762. package/src/testing/subjects/recall-budget.test.ts +461 -0
  763. package/src/testing/subjects/serialized-write-chain.test.ts +224 -0
  764. package/src/trust-score-stage.test.ts +154 -0
  765. package/src/trust-score-stage.ts +216 -53
  766. package/src/types-continuity.ts +57 -0
  767. package/src/types.ts +51 -77
  768. package/src/utils/path-containment.test.ts +75 -0
  769. package/src/utils/path-containment.ts +76 -0
  770. package/src/utils/serialize-mutations.test.ts +122 -0
  771. package/src/utils/serialize-mutations.ts +68 -3
  772. package/src/wearables/memory-gen.test.ts +31 -9
  773. package/src/wearables/memory-gen.ts +95 -55
  774. package/src/wearables/pipeline.test.ts +10 -7
  775. package/src/wearables/service.test.ts +6 -8
  776. package/src/wearables/service.ts +2 -2
  777. package/src/write-envelope.extension.test.ts +111 -0
  778. package/src/write-envelope.test.ts +683 -0
  779. package/src/write-envelope.ts +902 -0
  780. package/src/write-quarantine.test.ts +193 -0
  781. package/src/write-quarantine.ts +241 -0
  782. package/src/write-rate-limiter.test.ts +105 -0
  783. package/src/write-rate-limiter.ts +135 -0
  784. package/src/write-sealed-parity.test.ts +204 -0
  785. package/dist/chunk-2VN4JAX7.js.map +0 -1
  786. package/dist/chunk-37CTGERM.js.map +0 -1
  787. package/dist/chunk-3IY64MV6.js.map +0 -1
  788. package/dist/chunk-BCDKBDSY.js.map +0 -1
  789. package/dist/chunk-BFPETA3S.js.map +0 -1
  790. package/dist/chunk-BFVEEB7W.js.map +0 -1
  791. package/dist/chunk-BS4SGLWV.js.map +0 -1
  792. package/dist/chunk-DCFV7A7H.js.map +0 -1
  793. package/dist/chunk-DYP3YYJJ.js.map +0 -1
  794. package/dist/chunk-E5BK6CGV.js +0 -335
  795. package/dist/chunk-E5BK6CGV.js.map +0 -1
  796. package/dist/chunk-FTYDWKO6.js.map +0 -1
  797. package/dist/chunk-GWTFLF2P.js.map +0 -1
  798. package/dist/chunk-IKQTFQMI.js.map +0 -1
  799. package/dist/chunk-INELTPRG.js.map +0 -1
  800. package/dist/chunk-J2HSAU72.js.map +0 -1
  801. package/dist/chunk-JREB6UFH.js.map +0 -1
  802. package/dist/chunk-K7LOWSLU.js.map +0 -1
  803. package/dist/chunk-KQDNAXOM.js.map +0 -1
  804. package/dist/chunk-KSBEEMQF.js.map +0 -1
  805. package/dist/chunk-KSNVDPDF.js.map +0 -1
  806. package/dist/chunk-LC7OODWZ.js.map +0 -1
  807. package/dist/chunk-LTJAMRGI.js.map +0 -1
  808. package/dist/chunk-LZOV7MX7.js.map +0 -1
  809. package/dist/chunk-NWTGD4AN.js.map +0 -1
  810. package/dist/chunk-ODPLEWB6.js.map +0 -1
  811. package/dist/chunk-OVJ2HIPE.js.map +0 -1
  812. package/dist/chunk-PBSAPHHA.js.map +0 -1
  813. package/dist/chunk-PHK3HARR.js +0 -32
  814. package/dist/chunk-PHK3HARR.js.map +0 -1
  815. package/dist/chunk-PLQE6MJA.js.map +0 -1
  816. package/dist/chunk-QKQYXZVS.js.map +0 -1
  817. package/dist/chunk-QQGPUKMT.js.map +0 -1
  818. package/dist/chunk-RANHFI3P.js +0 -8
  819. package/dist/chunk-RANHFI3P.js.map +0 -1
  820. package/dist/chunk-RAR2BSEM.js.map +0 -1
  821. package/dist/chunk-RULE4VG5.js.map +0 -1
  822. package/dist/chunk-SVOZFLIQ.js +0 -16
  823. package/dist/chunk-SVOZFLIQ.js.map +0 -1
  824. package/dist/chunk-T7Y5KPLN.js.map +0 -1
  825. package/dist/chunk-TXLGHDHS.js.map +0 -1
  826. package/dist/chunk-VDW4VU7B.js.map +0 -1
  827. package/dist/chunk-VSMRDBFT.js +0 -17
  828. package/dist/chunk-VSMRDBFT.js.map +0 -1
  829. package/dist/chunk-X64YLC24.js.map +0 -1
  830. package/dist/chunk-XDSXEKYK.js +0 -118
  831. package/dist/chunk-XDSXEKYK.js.map +0 -1
  832. package/dist/chunk-YF6FMLBT.js.map +0 -1
  833. package/dist/resolution-VH4NGENZ.js +0 -12
  834. /package/dist/{capsule-crypto-CZJSLEFG.js.map → access-citation.js.map} +0 -0
  835. /package/dist/{contradiction-scan-J57T5QV7.js.map → access-memory-search-fanout.js.map} +0 -0
  836. /package/dist/{dreams-ledger-6UODQOX6.js.map → access-recall-concurrency.js.map} +0 -0
  837. /package/dist/{graph-edge-decay-IOGBBAGC.js.map → access-recall-response.js.map} +0 -0
  838. /package/dist/{resolution-VH4NGENZ.js.map → bounded-jsonl-state.js.map} +0 -0
  839. /package/dist/{chunk-A3GOMRJG.js.map → chunk-23L3IXFD.js.map} +0 -0
  840. /package/dist/{chunk-MRHFJV44.js.map → chunk-2DQ2XREU.js.map} +0 -0
  841. /package/dist/{chunk-L2B3EE7B.js.map → chunk-2QMKMVHH.js.map} +0 -0
  842. /package/dist/{chunk-VJVNLNDQ.js.map → chunk-2UFO7X4Q.js.map} +0 -0
  843. /package/dist/{chunk-2MR3MFQB.js.map → chunk-2VEOKUPP.js.map} +0 -0
  844. /package/dist/{chunk-RHOZ5LLO.js.map → chunk-347WD2LE.js.map} +0 -0
  845. /package/dist/{chunk-HDTQVNWD.js.map → chunk-3QAH2S33.js.map} +0 -0
  846. /package/dist/{chunk-LRNMRXJO.js.map → chunk-3Y224NYC.js.map} +0 -0
  847. /package/dist/{chunk-VFSP73LP.js.map → chunk-45GF7Y3V.js.map} +0 -0
  848. /package/dist/{chunk-OEHCMALU.js.map → chunk-5I4M26Q7.js.map} +0 -0
  849. /package/dist/{chunk-2AZXIZEN.js.map → chunk-5Q7EVV4X.js.map} +0 -0
  850. /package/dist/{chunk-PUBTHW5O.js.map → chunk-6DRPPQEJ.js.map} +0 -0
  851. /package/dist/{chunk-FDCTQWLW.js.map → chunk-6O22TZSB.js.map} +0 -0
  852. /package/dist/{chunk-ZQ7UBUZ6.js.map → chunk-6QYST5XN.js.map} +0 -0
  853. /package/dist/{chunk-W4PGTAS2.js.map → chunk-6WAFYNVT.js.map} +0 -0
  854. /package/dist/{chunk-R5VAVVHP.js.map → chunk-72A4L5JJ.js.map} +0 -0
  855. /package/dist/{chunk-3FAMU5TX.js.map → chunk-A6USBZTO.js.map} +0 -0
  856. /package/dist/{chunk-ZHIVCODT.js.map → chunk-A72SWTWW.js.map} +0 -0
  857. /package/dist/{chunk-FC77VUX5.js.map → chunk-A7Q43EUZ.js.map} +0 -0
  858. /package/dist/{chunk-UJBESW6X.js.map → chunk-AE7WMV4V.js.map} +0 -0
  859. /package/dist/{chunk-A5UXZRRM.js.map → chunk-AJ7QCSIS.js.map} +0 -0
  860. /package/dist/{chunk-FNMFJWBY.js.map → chunk-ANEUPF6O.js.map} +0 -0
  861. /package/dist/{chunk-2A3OXAP2.js.map → chunk-B7RWBZXW.js.map} +0 -0
  862. /package/dist/{chunk-74F5STS4.js.map → chunk-BLAKS3CP.js.map} +0 -0
  863. /package/dist/{chunk-M7VGG3ID.js.map → chunk-BV5WMSIJ.js.map} +0 -0
  864. /package/dist/{chunk-2BFLDH5F.js.map → chunk-BXLOS5AJ.js.map} +0 -0
  865. /package/dist/{chunk-UXKMMNJD.js.map → chunk-C23BYTJV.js.map} +0 -0
  866. /package/dist/{chunk-JZHHREBL.js.map → chunk-C3AKM55W.js.map} +0 -0
  867. /package/dist/{chunk-RP7YXA67.js.map → chunk-C5JF6EZ7.js.map} +0 -0
  868. /package/dist/{chunk-EHCONI6E.js.map → chunk-CQMEM5CC.js.map} +0 -0
  869. /package/dist/{chunk-PBNZVPFS.js.map → chunk-CXZQOVIE.js.map} +0 -0
  870. /package/dist/{chunk-7N2RUBAP.js.map → chunk-DDA47TES.js.map} +0 -0
  871. /package/dist/{chunk-64SE4X5G.js.map → chunk-DEBHXHJR.js.map} +0 -0
  872. /package/dist/{chunk-EHK6KZHK.js.map → chunk-DNHVPZOD.js.map} +0 -0
  873. /package/dist/{chunk-437S3G37.js.map → chunk-DQEMWVMT.js.map} +0 -0
  874. /package/dist/{chunk-LZZNTPLR.js.map → chunk-DX3XRGLH.js.map} +0 -0
  875. /package/dist/{chunk-DZKHSDOM.js.map → chunk-ES36HTSC.js.map} +0 -0
  876. /package/dist/{chunk-TN7THW5U.js.map → chunk-ET356KSB.js.map} +0 -0
  877. /package/dist/{chunk-YNDLCWXS.js.map → chunk-EZ25VE3G.js.map} +0 -0
  878. /package/dist/{chunk-DMSDUGDM.js.map → chunk-F7GAIWFA.js.map} +0 -0
  879. /package/dist/{chunk-G6XXLKC5.js.map → chunk-FFPJINJE.js.map} +0 -0
  880. /package/dist/{chunk-G4CN3ZXL.js.map → chunk-FUTF72MJ.js.map} +0 -0
  881. /package/dist/{chunk-HF77M34J.js.map → chunk-GFPZS3F5.js.map} +0 -0
  882. /package/dist/{chunk-G6NKALRN.js.map → chunk-H4WG3UQZ.js.map} +0 -0
  883. /package/dist/{chunk-UDQUSU27.js.map → chunk-HNZKVLAN.js.map} +0 -0
  884. /package/dist/{chunk-5EZXHU36.js.map → chunk-HYQJQGD3.js.map} +0 -0
  885. /package/dist/{chunk-TRWPCR6P.js.map → chunk-JECBQBEX.js.map} +0 -0
  886. /package/dist/{chunk-E6CBU7XP.js.map → chunk-JYIFGGEM.js.map} +0 -0
  887. /package/dist/{chunk-VA4WSW54.js.map → chunk-JYIJNNN3.js.map} +0 -0
  888. /package/dist/{chunk-L5HJQC36.js.map → chunk-K2TDK7GG.js.map} +0 -0
  889. /package/dist/{chunk-KDXVOFYY.js.map → chunk-KAVBJSBQ.js.map} +0 -0
  890. /package/dist/{chunk-4OKLXWDZ.js.map → chunk-KNB7IBBU.js.map} +0 -0
  891. /package/dist/{chunk-QLULYKWZ.js.map → chunk-KSXJOC4F.js.map} +0 -0
  892. /package/dist/{chunk-2S6QHZGJ.js.map → chunk-L2DPF4DF.js.map} +0 -0
  893. /package/dist/{chunk-JI5AVXYO.js.map → chunk-LEPOP46W.js.map} +0 -0
  894. /package/dist/{chunk-O7BBFJLP.js.map → chunk-LTAVSOZW.js.map} +0 -0
  895. /package/dist/{chunk-2IZAGAJR.js.map → chunk-LULR4IUW.js.map} +0 -0
  896. /package/dist/{chunk-WMWVO45V.js.map → chunk-MC6XO7T4.js.map} +0 -0
  897. /package/dist/{chunk-D6RIFG4O.js.map → chunk-MNB5RMAY.js.map} +0 -0
  898. /package/dist/{chunk-Q5WG43OP.js.map → chunk-MYFQ3ED4.js.map} +0 -0
  899. /package/dist/{chunk-V3UE5I5F.js.map → chunk-MYVPLJOO.js.map} +0 -0
  900. /package/dist/{chunk-MTWKDOVO.js.map → chunk-NLE6TSLG.js.map} +0 -0
  901. /package/dist/{chunk-DBRYEIGY.js.map → chunk-OJP3N7UK.js.map} +0 -0
  902. /package/dist/{chunk-SMX5267P.js.map → chunk-OZKOPQCM.js.map} +0 -0
  903. /package/dist/{chunk-JCK7V6SN.js.map → chunk-P65YJEEL.js.map} +0 -0
  904. /package/dist/{chunk-MTR7BZQN.js.map → chunk-PBGWYM3H.js.map} +0 -0
  905. /package/dist/{chunk-AXTXN4T6.js.map → chunk-PWFCHOB3.js.map} +0 -0
  906. /package/dist/{chunk-FDPZVY6D.js.map → chunk-QFN4U7AG.js.map} +0 -0
  907. /package/dist/{chunk-K2ZLHESQ.js.map → chunk-QIEUU4UK.js.map} +0 -0
  908. /package/dist/{chunk-3D6AFGQR.js.map → chunk-QVT3E4CE.js.map} +0 -0
  909. /package/dist/{chunk-SFQ6QNL7.js.map → chunk-R6YJI3HE.js.map} +0 -0
  910. /package/dist/{chunk-5CJVLG3H.js.map → chunk-RFDD3B7W.js.map} +0 -0
  911. /package/dist/{chunk-JBPKEARU.js.map → chunk-RKNJBZ55.js.map} +0 -0
  912. /package/dist/{chunk-FNZQGN76.js.map → chunk-S2BBISHU.js.map} +0 -0
  913. /package/dist/{chunk-IALLX7EE.js.map → chunk-S2FSBU4H.js.map} +0 -0
  914. /package/dist/{chunk-7K5Q6COX.js.map → chunk-TVVEYCNW.js.map} +0 -0
  915. /package/dist/{chunk-DPAENM7O.js.map → chunk-U3ZAVRP3.js.map} +0 -0
  916. /package/dist/{chunk-4KJLYTLS.js.map → chunk-V57NLO5P.js.map} +0 -0
  917. /package/dist/{chunk-FLVL4L3L.js.map → chunk-VDX2J7OX.js.map} +0 -0
  918. /package/dist/{chunk-AJLLIIML.js.map → chunk-W4FBGYGK.js.map} +0 -0
  919. /package/dist/{chunk-6SXVCD7W.js.map → chunk-W7IGLX4G.js.map} +0 -0
  920. /package/dist/{chunk-KAWTOYAW.js.map → chunk-WLZYGLJ4.js.map} +0 -0
  921. /package/dist/{chunk-RO4LQGT3.js.map → chunk-WON4APQY.js.map} +0 -0
  922. /package/dist/{chunk-PQVK2S3J.js.map → chunk-WZFAPHIK.js.map} +0 -0
  923. /package/dist/{chunk-KQPJLK3X.js.map → chunk-XL24QQ63.js.map} +0 -0
  924. /package/dist/{chunk-RVZRYUQH.js.map → chunk-YROFNEG5.js.map} +0 -0
  925. /package/dist/{chunk-VRAD2FGO.js.map → chunk-Z54EM5YZ.js.map} +0 -0
  926. /package/dist/{first-start-migration-TI67YMLG.js.map → first-start-migration-CSRHCJIQ.js.map} +0 -0
  927. /package/dist/{forget-CQCLB5LB.js.map → forget-HRPLVB3W.js.map} +0 -0
  928. /package/dist/{purge-NDWV6WYD.js.map → purge-IRF47ZTX.js.map} +0 -0
  929. /package/dist/{tier-stats-KV7IWCJR.js.map → tier-stats-QEJSPFV2.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  EngramAccessForbiddenError
3
- } from "./chunk-RANHFI3P.js";
3
+ } from "./chunk-2Z24E5W2.js";
4
4
 
5
5
  // src/access-token-capabilities.ts
6
6
  import { AsyncLocalStorage } from "async_hooks";
@@ -137,14 +137,16 @@ function resolveEffectiveNamespace(namespace, defaultNamespace) {
137
137
  const normalized = namespace !== void 0 && namespace.length > 0 ? namespace : void 0;
138
138
  return normalized ?? defaultNamespace;
139
139
  }
140
- function enforceNamespaceAllowList(caps, namespace, defaultNamespace) {
141
- if (caps?.namespaces === void 0) return;
140
+ function isNamespaceAllowed(caps, namespace, defaultNamespace) {
141
+ if (caps?.namespaces === void 0) return true;
142
142
  const effective = resolveEffectiveNamespace(namespace, defaultNamespace);
143
- if (effective === void 0 || !caps.namespaces.includes(effective)) {
144
- throw new EngramAccessForbiddenError(
145
- namespace === void 0 ? "token is scoped to specific namespaces; the server default namespace is not permitted \u2014 supply an allowed namespace" : `token is not permitted to access namespace: ${namespace}`
146
- );
147
- }
143
+ return effective !== void 0 && caps.namespaces.includes(effective);
144
+ }
145
+ function enforceNamespaceAllowList(caps, namespace, defaultNamespace) {
146
+ if (isNamespaceAllowed(caps, namespace, defaultNamespace)) return;
147
+ throw new EngramAccessForbiddenError(
148
+ namespace === void 0 ? "token is scoped to specific namespaces; the server default namespace is not permitted \u2014 supply an allowed namespace" : `token is not permitted to access namespace: ${namespace}`
149
+ );
148
150
  }
149
151
  function assertFleetWideOperationAllowed(caps) {
150
152
  if (!capabilityAllowsNamespace(caps, void 0)) {
@@ -166,8 +168,9 @@ export {
166
168
  assertOperationAllowed,
167
169
  assertNamespaceAllowed,
168
170
  resolveEffectiveNamespace,
171
+ isNamespaceAllowed,
169
172
  enforceNamespaceAllowList,
170
173
  assertFleetWideOperationAllowed,
171
174
  tokenCapabilityStore
172
175
  };
173
- //# sourceMappingURL=chunk-D7FOKIY5.js.map
176
+ //# sourceMappingURL=chunk-7AMFUATK.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/access-token-capabilities.ts"],"sourcesContent":["/**\n * Per-token capabilities (issue #1837).\n *\n * A token entry MAY carry an explicit, versioned capabilities record. The\n * record's PRESENCE is mechanically detectable, which is load-bearing for\n * security:\n *\n * - ABSENT `capabilities` field ⇒ a PRE-FEATURE legacy entry (minted\n * before this feature). It is UNRESTRICTED — full access — purely for\n * backward compatibility. This is the ONLY path by which \"full access\"\n * is granted by omission.\n *\n * - PRESENT `capabilities` record (always carries a `version` marker) ⇒ a\n * token minted by the capability-aware path. Even a new token minted\n * without `--ops`/`--namespaces` records an EXPLICIT unrestricted record\n * (`{ version: 1 }`) — a deliberate, auditable choice, never an\n * accidentally-omitted field. Within the record, the two axes follow\n * absent-vs-present semantics:\n * * axis ABSENT (e.g. no `ops` key) ⇒ unrestricted on that axis.\n * * axis PRESENT and empty (`ops: []`) ⇒ deny all (fail-closed).\n * * axis PRESENT and non-empty ⇒ allow only the listed values.\n *\n * Malformed capability input at mint time (bad version, non-array axes,\n * non-string elements, unknown op names against the catalog, malformed\n * namespace values) is REJECTED — a token is never created from invalid\n * input (rule: invalid input rejected, not defaulted).\n *\n * This module owns the pure capability logic (shape validation, allow-list\n * checks) and the per-request AsyncLocalStorage carrying the presenting\n * token's resolved capabilities down to the access boundary. It imports\n * nothing else in the package except the forbidden-error class, so it can be\n * reused by the token store, the boundary, and the HTTP/MCP surfaces without\n * cycles.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { EngramAccessForbiddenError } from \"./access-errors.js\";\n\n/** Current capability-record schema version. */\nexport const TOKEN_CAPABILITIES_VERSION = 1 as const;\n\n/**\n * Versioned capabilities record stored on a token entry. Presence of this\n * record (vs. an absent field) is what distinguishes a capability-aware\n * token from a pre-feature legacy entry.\n */\nexport interface TokenCapabilities {\n readonly version: typeof TOKEN_CAPABILITIES_VERSION;\n /**\n * Operations allow-list. `undefined` (key absent) ⇒ unrestricted on this\n * axis. `[]` ⇒ deny all ops (fail-closed). Non-empty ⇒ allow only listed.\n */\n ops?: string[];\n /**\n * Namespaces allow-list. `undefined` ⇒ unrestricted. `[]` ⇒ deny all.\n * Non-empty ⇒ allow only listed.\n */\n namespaces?: string[];\n}\n\n/**\n * Namespace value validation. Namespace identifiers are flexible (default,\n * team, self, principal-prefixed, project-prefixed) but must never contain\n * whitespace, path separators, traversal segments, or control characters —\n * such values are malformed at mint time and rejected, never silently\n * coerced.\n */\nconst NAMESPACE_VALUE_MAX_LENGTH = 128;\n// Non-empty, no whitespace, no path separators, no control chars. `.` and\n// `..` are rejected separately so legitimate dotted names (e.g. a domain)\n// remain allowed while traversal is not.\nconst NAMESPACE_VALUE_PATTERN = /^[^\\s\\/\\\\\\x00-\\x1F]+$/;\n\n/** True when `value` is an acceptable namespace allow-list entry. */\nexport function isValidNamespaceValue(value: unknown): value is string {\n if (typeof value !== \"string\" || value.length === 0 || value.length > NAMESPACE_VALUE_MAX_LENGTH) {\n return false;\n }\n if (!NAMESPACE_VALUE_PATTERN.test(value)) return false;\n if (value === \".\" || value === \"..\") return false;\n return true;\n}\n\nfunction isStringArray(value: unknown): value is unknown[] {\n return Array.isArray(value) && value.every((v) => typeof v === \"string\");\n}\n\nfunction dedupeSort(values: string[]): string[] {\n return [...new Set(values)].sort();\n}\n\n/**\n * Parse one axis (ops or namespaces) for PERSISTENCE/LOAD. Returns the\n * cleaned array (deduped, sorted; possibly empty to preserve \"present ⇒\n * fail-closed\") or `undefined` when the key is absent. Throws on a malformed\n * shape (non-array, non-string elements, malformed namespace values). Op\n * validation against the catalog happens only at mint time.\n */\nfunction parseAxis(\n obj: Record<string, unknown>,\n key: \"ops\" | \"namespaces\",\n validateValue: (v: unknown) => boolean,\n valueLabel: string,\n): string[] | undefined {\n if (!Object.prototype.hasOwnProperty.call(obj, key)) return undefined;\n const value = obj[key];\n if (value === undefined || value === null) return undefined;\n if (!isStringArray(value)) {\n throw new Error(`capabilities ${key} must be an array of non-empty strings`);\n }\n const cleaned: string[] = [];\n for (const v of value) {\n if (typeof v !== \"string\" || v.length === 0) {\n throw new Error(`capabilities ${key} must be an array of non-empty strings`);\n }\n if (!validateValue(v)) {\n throw new Error(`capabilities ${key} contains a malformed ${valueLabel}: ${JSON.stringify(v)}`);\n }\n cleaned.push(v);\n }\n // Preserve presence: an explicitly empty array stays [] (fail-closed),\n // NOT coerced to undefined (which would mean unrestricted).\n return dedupeSort(cleaned);\n}\n\n/**\n * Normalize a capabilities record for PERSISTENCE/LOAD. Returns `undefined`\n * ONLY when the record is entirely absent (a pre-feature legacy entry ⇒\n * unrestricted). When present, an absent/`undefined` `version` is COERCED to\n * the current default (1) — mirroring {@link validateCapabilitiesForMint} — so\n * a record that mint-validated also load-normalizes without a schema throw.\n * An explicitly-present WRONG version (not 1) is still rejected. Throws on a\n * malformed record (non-object, explicitly-wrong version, malformed axes).\n */\nexport function normalizeCapabilities(raw: unknown): TokenCapabilities | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new Error(\"capabilities must be an object with a version marker\");\n }\n const obj = raw as Record<string, unknown>;\n // Coerce absent/undefined version → 1, mirroring validateCapabilitiesForMint\n // (version 1 is the only schema version; coercing keeps mint-validated\n // records reloadable). Only an explicitly-present WRONG version throws.\n if (obj.version !== undefined && obj.version !== TOKEN_CAPABILITIES_VERSION) {\n throw new Error(`capabilities.version must be ${TOKEN_CAPABILITIES_VERSION}`);\n }\n const ops = parseAxis(obj, \"ops\", () => true, \"operation\");\n const namespaces = parseAxis(obj, \"namespaces\", isValidNamespaceValue, \"namespace\");\n const result: TokenCapabilities = { version: TOKEN_CAPABILITIES_VERSION };\n if (ops !== undefined) result.ops = ops;\n if (namespaces !== undefined) result.namespaces = namespaces;\n return result;\n}\n\n/**\n * Validate a capabilities record at MINT time. ALWAYS returns a versioned\n * record (never `undefined`) so every newly-minted token carries an explicit\n * capability decision — a new token can never gain full access by OMITTING\n * the field. When `raw` is absent/null, the result is an explicit\n * unrestricted record (`{ version: 1 }`), a deliberate/auditable choice. A\n * present-but-`undefined` (or absent) `version` is coerced to the current\n * default (1); an explicitly-wrong version is rejected. This version rule is\n * identical to {@link normalizeCapabilities} (mint/load symmetry). Rejects\n * unknown op names against the catalog and malformed namespace values;\n * throws a plain Error — the caller must NOT create a token when this throws.\n */\nexport function validateCapabilitiesForMint(\n raw: unknown,\n validOps: readonly string[],\n): TokenCapabilities {\n const result: TokenCapabilities = { version: TOKEN_CAPABILITIES_VERSION };\n if (raw === undefined || raw === null) {\n return result;\n }\n if (typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new Error(\"capabilities must be an object with optional ops/namespaces arrays\");\n }\n const obj = raw as Record<string, unknown>;\n if (Object.prototype.hasOwnProperty.call(obj, \"version\") && obj.version !== undefined) {\n if (obj.version !== TOKEN_CAPABILITIES_VERSION) {\n throw new Error(`capabilities.version must be ${TOKEN_CAPABILITIES_VERSION}`);\n }\n }\n const validOpSet = new Set(validOps);\n\n if (Object.prototype.hasOwnProperty.call(obj, \"ops\") && obj.ops !== undefined && obj.ops !== null) {\n if (!isStringArray(obj.ops)) {\n throw new Error(\"capabilities ops must be an array of non-empty strings\");\n }\n const ops = obj.ops as unknown[];\n for (const v of ops) {\n if (typeof v !== \"string\" || v.length === 0) {\n throw new Error(\"capabilities ops must be an array of non-empty strings\");\n }\n }\n // Reject unknown op names against the catalog (unknown ⇒ reject, never drop).\n const unknown = ops.filter((op) => typeof op === \"string\" && !validOpSet.has(op));\n if (unknown.length > 0) {\n throw new Error(\n `capabilities ops contains unknown operation name(s): ${unknown.map((o) => JSON.stringify(o)).join(\", \")}`,\n );\n }\n // Preserve presence (empty stays [] ⇒ deny all ops).\n result.ops = dedupeSort(ops as string[]);\n }\n\n if (\n Object.prototype.hasOwnProperty.call(obj, \"namespaces\") &&\n obj.namespaces !== undefined &&\n obj.namespaces !== null\n ) {\n if (!isStringArray(obj.namespaces)) {\n throw new Error(\"capabilities namespaces must be an array of non-empty strings\");\n }\n const namespaces = obj.namespaces as unknown[];\n for (const v of namespaces) {\n if (typeof v !== \"string\" || v.length === 0) {\n throw new Error(\"capabilities namespaces must be an array of non-empty strings\");\n }\n if (!isValidNamespaceValue(v)) {\n throw new Error(`capabilities namespaces contains a malformed namespace: ${JSON.stringify(v)}`);\n }\n }\n result.namespaces = dedupeSort(namespaces as string[]);\n }\n\n return result;\n}\n\n/**\n * True when `caps` imposes any restriction (a present record with at least\n * one axis key). `undefined` (legacy / absent record) ⇒ unrestricted. A\n * present `{ version: 1 }` record with no axes ⇒ also unrestricted (but\n * auditable — it is a deliberate new-token decision, not omission).\n */\nexport function isCapabilityRestricted(caps: TokenCapabilities | undefined | null): boolean {\n if (!caps) return false;\n return caps.ops !== undefined || caps.namespaces !== undefined;\n}\n\n/**\n * True when `caps` permits `op`.\n * - record ABSENT (legacy) ⇒ unrestricted (true).\n * - ops axis ABSENT ⇒ unrestricted on this axis (true).\n * - ops axis PRESENT ⇒ `op` must be listed; `[]` ⇒ false (deny all).\n */\nexport function capabilityAllowsOp(caps: TokenCapabilities | undefined | null, op: string): boolean {\n if (caps?.ops === undefined) return true;\n return caps.ops.includes(op);\n}\n\n/**\n * True when `caps` permits `namespace`.\n * - record ABSENT / namespaces axis ABSENT ⇒ unrestricted (true).\n * - namespaces axis PRESENT ⇒ `namespace` must be listed; undefined\n * namespace ⇒ false; `[]` ⇒ false (deny all).\n */\nexport function capabilityAllowsNamespace(\n caps: TokenCapabilities | undefined | null,\n namespace: string | undefined,\n): boolean {\n if (caps?.namespaces === undefined) return true;\n if (namespace === undefined) return false;\n return caps.namespaces.includes(namespace);\n}\n\n/**\n * Throw {@link EngramAccessForbiddenError} when `caps` restricts ops and\n * `op` is not permitted. No-op for unrestricted tokens.\n */\nexport function assertOperationAllowed(\n caps: TokenCapabilities | undefined | null,\n op: string,\n): void {\n if (!capabilityAllowsOp(caps, op)) {\n throw new EngramAccessForbiddenError(\n `token is not permitted to call operation: ${op}`,\n );\n }\n}\n\n/**\n * Throw {@link EngramAccessForbiddenError} when `caps` restricts namespaces\n * and `namespace` is not permitted. No-op for unrestricted tokens.\n */\nexport function assertNamespaceAllowed(\n caps: TokenCapabilities | undefined | null,\n namespace: string | undefined,\n): void {\n if (!capabilityAllowsNamespace(caps, namespace)) {\n throw new EngramAccessForbiddenError(\n namespace === undefined\n ? \"token is scoped to specific namespaces and this operation requires an explicit namespace\"\n : `token is not permitted to access namespace: ${namespace}`,\n );\n }\n}\n\n/**\n * Resolve the EFFECTIVE namespace an operation runs against: a present,\n * non-empty request namespace wins, otherwise the server default — the same\n * resolution downstream storage applies\n * (`getWritableStorageForNamespace(undefined)` → `defaultNamespace`). Empty\n * strings are treated as absent. Centralized so every invocation surface\n * (HTTP query/body, MCP `tools/call`, id-loaded records, legacy pairs that\n * carry no namespace) applies ONE rule and none can dodge the check by\n * dropping the param. (issue #1850)\n */\nexport function resolveEffectiveNamespace(\n namespace: string | undefined,\n defaultNamespace: string | undefined,\n): string | undefined {\n const normalized = namespace !== undefined && namespace.length > 0 ? namespace : undefined;\n return normalized ?? defaultNamespace;\n}\n\n/**\n * The single effective-namespace allow-list chokepoint (issues #1837/#1850).\n * Throws {@link EngramAccessForbiddenError} when `caps` carries a namespaces\n * allow-list and the EFFECTIVE namespace (request value OR server default) is\n * not a member. FAIL CLOSED:\n * - a scoped token whose allow-list does not cover the effective namespace\n * (explicit OR defaulted) is rejected;\n * - an absent server default (unconfigured) is also rejected for scoped\n * tokens, so omitting `?namespace=` can never bypass the allow-list.\n * No-op for unrestricted tokens (no namespaces axis) so legacy/unrestricted\n * behavior is unchanged. Both the HTTP transport (`resolveNamespace`) and the\n * MCP dispatch route through this ONE function so no surface is missed.\n */\nexport function enforceNamespaceAllowList(\n caps: TokenCapabilities | undefined | null,\n namespace: string | undefined,\n defaultNamespace: string | undefined,\n): void {\n if (caps?.namespaces === undefined) return; // unrestricted token — unchanged\n const effective = resolveEffectiveNamespace(namespace, defaultNamespace);\n if (effective === undefined || !caps.namespaces.includes(effective)) {\n throw new EngramAccessForbiddenError(\n namespace === undefined\n ? \"token is scoped to specific namespaces; the server default namespace is not permitted — supply an allowed namespace\"\n : `token is not permitted to access namespace: ${namespace}`,\n );\n }\n}\n\n/**\n * Fleet-wide / global maintenance operation guard (issue #1850 round 10).\n *\n * A distinct escalation class from the id-addressed routes (round 9) and the\n * param-namespace ops (round 4): some boundary operations inherently run\n * ACROSS ALL namespaces — or against a single global layer (compression\n * guidelines, shared context, compounding) that is not namespace-partitioned\n * — and carry NO `namespace` argument, so the MCP `tools/call` effective-\n * namespace chokepoint ({@link enforceNamespaceAllowList}, which only fires\n * when `toolAcceptsNamespace`) never applies. Without this guard a bearer\n * scoped to ONE tenant could trigger maintenance that mutates state in EVERY\n * namespace (privilege escalation).\n *\n * Fail CLOSED exactly like the other shared guards: a namespace-SCOPED token\n * (namespaces axis present) is rejected; unrestricted / legacy tokens (absent\n * record or no namespaces axis — i.e. cron and internal callers that never\n * bind a capability record) are unaffected. Reuses the EXISTING capability\n * model via {@link capabilityAllowsNamespace} — no new \"all\"/\"*\" scope concept.\n * Must run BEFORE any side effect so a denial never leaks a partial mutation.\n */\nexport function assertFleetWideOperationAllowed(\n caps: TokenCapabilities | undefined | null,\n): void {\n // capabilityAllowsNamespace returns false for ANY scoped token when the\n // namespace is undefined (a fleet-wide op has no single namespace), and\n // true for unrestricted/legacy tokens — exactly the desired policy.\n if (!capabilityAllowsNamespace(caps, undefined)) {\n throw new EngramAccessForbiddenError(\n \"token is scoped to specific namespaces; this maintenance operation runs across all namespaces and is not permitted for a namespace-scoped token\",\n );\n }\n}\n\n/**\n * Per-request AsyncLocalStorage carrying the presenting token's resolved\n * capabilities. The HTTP surface binds the resolved capabilities with\n * `.run(caps, handler)` for the WHOLE authorized request dispatch (NOT\n * `.enterWith()`, which mutates the current async resource and does not\n * reliably isolate the store across the handler's awaits / concurrent\n * requests — risking a fail-open read of undefined mid-handler); the\n * access boundary reads `.getStore()` to enforce the ops allow-list for\n * every boundary operation without each dispatch site threading the value\n * explicitly. Unset (CLI, direct boundary callers, tests) ⇒ undefined ⇒\n * unrestricted (issue #1850 round 7).\n */\nexport const tokenCapabilityStore = new AsyncLocalStorage<TokenCapabilities | undefined>();\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/access-token-capabilities.ts"],"sourcesContent":["/**\n * Per-token capabilities (issue #1837).\n *\n * A token entry MAY carry an explicit, versioned capabilities record. The\n * record's PRESENCE is mechanically detectable, which is load-bearing for\n * security:\n *\n * - ABSENT `capabilities` field ⇒ a PRE-FEATURE legacy entry (minted\n * before this feature). It is UNRESTRICTED — full access — purely for\n * backward compatibility. This is the ONLY path by which \"full access\"\n * is granted by omission.\n *\n * - PRESENT `capabilities` record (always carries a `version` marker) ⇒ a\n * token minted by the capability-aware path. Even a new token minted\n * without `--ops`/`--namespaces` records an EXPLICIT unrestricted record\n * (`{ version: 1 }`) — a deliberate, auditable choice, never an\n * accidentally-omitted field. Within the record, the two axes follow\n * absent-vs-present semantics:\n * * axis ABSENT (e.g. no `ops` key) ⇒ unrestricted on that axis.\n * * axis PRESENT and empty (`ops: []`) ⇒ deny all (fail-closed).\n * * axis PRESENT and non-empty ⇒ allow only the listed values.\n *\n * Malformed capability input at mint time (bad version, non-array axes,\n * non-string elements, unknown op names against the catalog, malformed\n * namespace values) is REJECTED — a token is never created from invalid\n * input (rule: invalid input rejected, not defaulted).\n *\n * This module owns the pure capability logic (shape validation, allow-list\n * checks) and the per-request AsyncLocalStorage carrying the presenting\n * token's resolved capabilities down to the access boundary. It imports\n * nothing else in the package except the forbidden-error class, so it can be\n * reused by the token store, the boundary, and the HTTP/MCP surfaces without\n * cycles.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { EngramAccessForbiddenError } from \"./access-errors.js\";\n\n/** Current capability-record schema version. */\nexport const TOKEN_CAPABILITIES_VERSION = 1 as const;\n\n/**\n * Versioned capabilities record stored on a token entry. Presence of this\n * record (vs. an absent field) is what distinguishes a capability-aware\n * token from a pre-feature legacy entry.\n */\nexport interface TokenCapabilities {\n readonly version: typeof TOKEN_CAPABILITIES_VERSION;\n /**\n * Operations allow-list. `undefined` (key absent) ⇒ unrestricted on this\n * axis. `[]` ⇒ deny all ops (fail-closed). Non-empty ⇒ allow only listed.\n */\n ops?: string[];\n /**\n * Namespaces allow-list. `undefined` ⇒ unrestricted. `[]` ⇒ deny all.\n * Non-empty ⇒ allow only listed.\n */\n namespaces?: string[];\n}\n\n/**\n * Namespace value validation. Namespace identifiers are flexible (default,\n * team, self, principal-prefixed, project-prefixed) but must never contain\n * whitespace, path separators, traversal segments, or control characters —\n * such values are malformed at mint time and rejected, never silently\n * coerced.\n */\nconst NAMESPACE_VALUE_MAX_LENGTH = 128;\n// Non-empty, no whitespace, no path separators, no control chars. `.` and\n// `..` are rejected separately so legitimate dotted names (e.g. a domain)\n// remain allowed while traversal is not.\nconst NAMESPACE_VALUE_PATTERN = /^[^\\s\\/\\\\\\x00-\\x1F]+$/;\n\n/** True when `value` is an acceptable namespace allow-list entry. */\nexport function isValidNamespaceValue(value: unknown): value is string {\n if (typeof value !== \"string\" || value.length === 0 || value.length > NAMESPACE_VALUE_MAX_LENGTH) {\n return false;\n }\n if (!NAMESPACE_VALUE_PATTERN.test(value)) return false;\n if (value === \".\" || value === \"..\") return false;\n return true;\n}\n\nfunction isStringArray(value: unknown): value is unknown[] {\n return Array.isArray(value) && value.every((v) => typeof v === \"string\");\n}\n\nfunction dedupeSort(values: string[]): string[] {\n return [...new Set(values)].sort();\n}\n\n/**\n * Parse one axis (ops or namespaces) for PERSISTENCE/LOAD. Returns the\n * cleaned array (deduped, sorted; possibly empty to preserve \"present ⇒\n * fail-closed\") or `undefined` when the key is absent. Throws on a malformed\n * shape (non-array, non-string elements, malformed namespace values). Op\n * validation against the catalog happens only at mint time.\n */\nfunction parseAxis(\n obj: Record<string, unknown>,\n key: \"ops\" | \"namespaces\",\n validateValue: (v: unknown) => boolean,\n valueLabel: string,\n): string[] | undefined {\n if (!Object.prototype.hasOwnProperty.call(obj, key)) return undefined;\n const value = obj[key];\n if (value === undefined || value === null) return undefined;\n if (!isStringArray(value)) {\n throw new Error(`capabilities ${key} must be an array of non-empty strings`);\n }\n const cleaned: string[] = [];\n for (const v of value) {\n if (typeof v !== \"string\" || v.length === 0) {\n throw new Error(`capabilities ${key} must be an array of non-empty strings`);\n }\n if (!validateValue(v)) {\n throw new Error(`capabilities ${key} contains a malformed ${valueLabel}: ${JSON.stringify(v)}`);\n }\n cleaned.push(v);\n }\n // Preserve presence: an explicitly empty array stays [] (fail-closed),\n // NOT coerced to undefined (which would mean unrestricted).\n return dedupeSort(cleaned);\n}\n\n/**\n * Normalize a capabilities record for PERSISTENCE/LOAD. Returns `undefined`\n * ONLY when the record is entirely absent (a pre-feature legacy entry ⇒\n * unrestricted). When present, an absent/`undefined` `version` is COERCED to\n * the current default (1) — mirroring {@link validateCapabilitiesForMint} — so\n * a record that mint-validated also load-normalizes without a schema throw.\n * An explicitly-present WRONG version (not 1) is still rejected. Throws on a\n * malformed record (non-object, explicitly-wrong version, malformed axes).\n */\nexport function normalizeCapabilities(raw: unknown): TokenCapabilities | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new Error(\"capabilities must be an object with a version marker\");\n }\n const obj = raw as Record<string, unknown>;\n // Coerce absent/undefined version → 1, mirroring validateCapabilitiesForMint\n // (version 1 is the only schema version; coercing keeps mint-validated\n // records reloadable). Only an explicitly-present WRONG version throws.\n if (obj.version !== undefined && obj.version !== TOKEN_CAPABILITIES_VERSION) {\n throw new Error(`capabilities.version must be ${TOKEN_CAPABILITIES_VERSION}`);\n }\n const ops = parseAxis(obj, \"ops\", () => true, \"operation\");\n const namespaces = parseAxis(obj, \"namespaces\", isValidNamespaceValue, \"namespace\");\n const result: TokenCapabilities = { version: TOKEN_CAPABILITIES_VERSION };\n if (ops !== undefined) result.ops = ops;\n if (namespaces !== undefined) result.namespaces = namespaces;\n return result;\n}\n\n/**\n * Validate a capabilities record at MINT time. ALWAYS returns a versioned\n * record (never `undefined`) so every newly-minted token carries an explicit\n * capability decision — a new token can never gain full access by OMITTING\n * the field. When `raw` is absent/null, the result is an explicit\n * unrestricted record (`{ version: 1 }`), a deliberate/auditable choice. A\n * present-but-`undefined` (or absent) `version` is coerced to the current\n * default (1); an explicitly-wrong version is rejected. This version rule is\n * identical to {@link normalizeCapabilities} (mint/load symmetry). Rejects\n * unknown op names against the catalog and malformed namespace values;\n * throws a plain Error — the caller must NOT create a token when this throws.\n */\nexport function validateCapabilitiesForMint(\n raw: unknown,\n validOps: readonly string[],\n): TokenCapabilities {\n const result: TokenCapabilities = { version: TOKEN_CAPABILITIES_VERSION };\n if (raw === undefined || raw === null) {\n return result;\n }\n if (typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new Error(\"capabilities must be an object with optional ops/namespaces arrays\");\n }\n const obj = raw as Record<string, unknown>;\n if (Object.prototype.hasOwnProperty.call(obj, \"version\") && obj.version !== undefined) {\n if (obj.version !== TOKEN_CAPABILITIES_VERSION) {\n throw new Error(`capabilities.version must be ${TOKEN_CAPABILITIES_VERSION}`);\n }\n }\n const validOpSet = new Set(validOps);\n\n if (Object.prototype.hasOwnProperty.call(obj, \"ops\") && obj.ops !== undefined && obj.ops !== null) {\n if (!isStringArray(obj.ops)) {\n throw new Error(\"capabilities ops must be an array of non-empty strings\");\n }\n const ops = obj.ops as unknown[];\n for (const v of ops) {\n if (typeof v !== \"string\" || v.length === 0) {\n throw new Error(\"capabilities ops must be an array of non-empty strings\");\n }\n }\n // Reject unknown op names against the catalog (unknown ⇒ reject, never drop).\n const unknown = ops.filter((op) => typeof op === \"string\" && !validOpSet.has(op));\n if (unknown.length > 0) {\n throw new Error(\n `capabilities ops contains unknown operation name(s): ${unknown.map((o) => JSON.stringify(o)).join(\", \")}`,\n );\n }\n // Preserve presence (empty stays [] ⇒ deny all ops).\n result.ops = dedupeSort(ops as string[]);\n }\n\n if (\n Object.prototype.hasOwnProperty.call(obj, \"namespaces\") &&\n obj.namespaces !== undefined &&\n obj.namespaces !== null\n ) {\n if (!isStringArray(obj.namespaces)) {\n throw new Error(\"capabilities namespaces must be an array of non-empty strings\");\n }\n const namespaces = obj.namespaces as unknown[];\n for (const v of namespaces) {\n if (typeof v !== \"string\" || v.length === 0) {\n throw new Error(\"capabilities namespaces must be an array of non-empty strings\");\n }\n if (!isValidNamespaceValue(v)) {\n throw new Error(`capabilities namespaces contains a malformed namespace: ${JSON.stringify(v)}`);\n }\n }\n result.namespaces = dedupeSort(namespaces as string[]);\n }\n\n return result;\n}\n\n/**\n * True when `caps` imposes any restriction (a present record with at least\n * one axis key). `undefined` (legacy / absent record) ⇒ unrestricted. A\n * present `{ version: 1 }` record with no axes ⇒ also unrestricted (but\n * auditable — it is a deliberate new-token decision, not omission).\n */\nexport function isCapabilityRestricted(caps: TokenCapabilities | undefined | null): boolean {\n if (!caps) return false;\n return caps.ops !== undefined || caps.namespaces !== undefined;\n}\n\n/**\n * True when `caps` permits `op`.\n * - record ABSENT (legacy) ⇒ unrestricted (true).\n * - ops axis ABSENT ⇒ unrestricted on this axis (true).\n * - ops axis PRESENT ⇒ `op` must be listed; `[]` ⇒ false (deny all).\n */\nexport function capabilityAllowsOp(caps: TokenCapabilities | undefined | null, op: string): boolean {\n if (caps?.ops === undefined) return true;\n return caps.ops.includes(op);\n}\n\n/**\n * True when `caps` permits `namespace`.\n * - record ABSENT / namespaces axis ABSENT ⇒ unrestricted (true).\n * - namespaces axis PRESENT ⇒ `namespace` must be listed; undefined\n * namespace ⇒ false; `[]` ⇒ false (deny all).\n */\nexport function capabilityAllowsNamespace(\n caps: TokenCapabilities | undefined | null,\n namespace: string | undefined,\n): boolean {\n if (caps?.namespaces === undefined) return true;\n if (namespace === undefined) return false;\n return caps.namespaces.includes(namespace);\n}\n\n/**\n * Throw {@link EngramAccessForbiddenError} when `caps` restricts ops and\n * `op` is not permitted. No-op for unrestricted tokens.\n */\nexport function assertOperationAllowed(\n caps: TokenCapabilities | undefined | null,\n op: string,\n): void {\n if (!capabilityAllowsOp(caps, op)) {\n throw new EngramAccessForbiddenError(\n `token is not permitted to call operation: ${op}`,\n );\n }\n}\n\n/**\n * Throw {@link EngramAccessForbiddenError} when `caps` restricts namespaces\n * and `namespace` is not permitted. No-op for unrestricted tokens.\n */\nexport function assertNamespaceAllowed(\n caps: TokenCapabilities | undefined | null,\n namespace: string | undefined,\n): void {\n if (!capabilityAllowsNamespace(caps, namespace)) {\n throw new EngramAccessForbiddenError(\n namespace === undefined\n ? \"token is scoped to specific namespaces and this operation requires an explicit namespace\"\n : `token is not permitted to access namespace: ${namespace}`,\n );\n }\n}\n\n/**\n * Resolve the EFFECTIVE namespace an operation runs against: a present,\n * non-empty request namespace wins, otherwise the server default — the same\n * resolution downstream storage applies\n * (`getWritableStorageForNamespace(undefined)` → `defaultNamespace`). Empty\n * strings are treated as absent. Centralized so every invocation surface\n * (HTTP query/body, MCP `tools/call`, id-loaded records, legacy pairs that\n * carry no namespace) applies ONE rule and none can dodge the check by\n * dropping the param. (issue #1850)\n */\nexport function resolveEffectiveNamespace(\n namespace: string | undefined,\n defaultNamespace: string | undefined,\n): string | undefined {\n const normalized = namespace !== undefined && namespace.length > 0 ? namespace : undefined;\n return normalized ?? defaultNamespace;\n}\n\n/**\n * The single effective-namespace allow-list chokepoint (issues #1837/#1850).\n * Throws {@link EngramAccessForbiddenError} when `caps` carries a namespaces\n * allow-list and the EFFECTIVE namespace (request value OR server default) is\n * not a member. FAIL CLOSED:\n * - a scoped token whose allow-list does not cover the effective namespace\n * (explicit OR defaulted) is rejected;\n * - an absent server default (unconfigured) is also rejected for scoped\n * tokens, so omitting `?namespace=` can never bypass the allow-list.\n * No-op for unrestricted tokens (no namespaces axis) so legacy/unrestricted\n * behavior is unchanged. Both the HTTP transport (`resolveNamespace`) and the\n * MCP dispatch route through this ONE function so no surface is missed.\n */\nexport function isNamespaceAllowed(\n caps: TokenCapabilities | undefined | null,\n namespace: string | undefined,\n defaultNamespace: string | undefined,\n): boolean {\n if (caps?.namespaces === undefined) return true; // unrestricted token\n const effective = resolveEffectiveNamespace(namespace, defaultNamespace);\n return effective !== undefined && caps.namespaces.includes(effective);\n}\n\nexport function enforceNamespaceAllowList(\n caps: TokenCapabilities | undefined | null,\n namespace: string | undefined,\n defaultNamespace: string | undefined,\n): void {\n if (isNamespaceAllowed(caps, namespace, defaultNamespace)) return;\n throw new EngramAccessForbiddenError(\n namespace === undefined\n ? \"token is scoped to specific namespaces; the server default namespace is not permitted — supply an allowed namespace\"\n : `token is not permitted to access namespace: ${namespace}`,\n );\n}\n\n/**\n * Fleet-wide / global maintenance operation guard (issue #1850 round 10).\n *\n * A distinct escalation class from the id-addressed routes (round 9) and the\n * param-namespace ops (round 4): some boundary operations inherently run\n * ACROSS ALL namespaces — or against a single global layer (compression\n * guidelines, shared context, compounding) that is not namespace-partitioned\n * — and carry NO `namespace` argument, so the MCP `tools/call` effective-\n * namespace chokepoint ({@link enforceNamespaceAllowList}, which only fires\n * when `toolAcceptsNamespace`) never applies. Without this guard a bearer\n * scoped to ONE tenant could trigger maintenance that mutates state in EVERY\n * namespace (privilege escalation).\n *\n * Fail CLOSED exactly like the other shared guards: a namespace-SCOPED token\n * (namespaces axis present) is rejected; unrestricted / legacy tokens (absent\n * record or no namespaces axis — i.e. cron and internal callers that never\n * bind a capability record) are unaffected. Reuses the EXISTING capability\n * model via {@link capabilityAllowsNamespace} — no new \"all\"/\"*\" scope concept.\n * Must run BEFORE any side effect so a denial never leaks a partial mutation.\n */\nexport function assertFleetWideOperationAllowed(\n caps: TokenCapabilities | undefined | null,\n): void {\n // capabilityAllowsNamespace returns false for ANY scoped token when the\n // namespace is undefined (a fleet-wide op has no single namespace), and\n // true for unrestricted/legacy tokens — exactly the desired policy.\n if (!capabilityAllowsNamespace(caps, undefined)) {\n throw new EngramAccessForbiddenError(\n \"token is scoped to specific namespaces; this maintenance operation runs across all namespaces and is not permitted for a namespace-scoped token\",\n );\n }\n}\n\n/**\n * Per-request AsyncLocalStorage carrying the presenting token's resolved\n * capabilities. The HTTP surface binds the resolved capabilities with\n * `.run(caps, handler)` for the WHOLE authorized request dispatch (NOT\n * `.enterWith()`, which mutates the current async resource and does not\n * reliably isolate the store across the handler's awaits / concurrent\n * requests — risking a fail-open read of undefined mid-handler); the\n * access boundary reads `.getStore()` to enforce the ops allow-list for\n * every boundary operation without each dispatch site threading the value\n * explicitly. Unset (CLI, direct boundary callers, tests) ⇒ undefined ⇒\n * unrestricted (issue #1850 round 7).\n */\nexport const tokenCapabilityStore = new AsyncLocalStorage<TokenCapabilities | undefined>();\n"],"mappings":"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","names":[]}
@@ -1,12 +1,16 @@
1
+ import {
2
+ TAG_LIMITS,
3
+ composeMemoryEnvelope
4
+ } from "./chunk-CGASUJVP.js";
5
+ import {
6
+ sanitizeMemoryContent
7
+ } from "./chunk-5GKPFL3S.js";
1
8
  import {
2
9
  isSafeRouteNamespace
3
10
  } from "./chunk-U3PN77QT.js";
4
11
  import {
5
12
  resolveNamespaceCapabilities
6
- } from "./chunk-BFPETA3S.js";
7
- import {
8
- sanitizeMemoryContent
9
- } from "./chunk-5GKPFL3S.js";
13
+ } from "./chunk-SCCO46KZ.js";
10
14
 
11
15
  // src/explicit-capture.ts
12
16
  import { randomUUID } from "crypto";
@@ -274,15 +278,27 @@ function validateExplicitCaptureInput(input, mode = "strict_explicit") {
274
278
  throw new Error(`unsafe namespace: ${requestedNamespace}`);
275
279
  }
276
280
  const expiresAt = parseExplicitCaptureTtl(input.ttl);
281
+ const dedupedTags = Array.from(new Set((input.tags ?? []).map((tag) => tag.trim()).filter(Boolean)));
282
+ if (dedupedTags.length > TAG_LIMITS.maxTags) {
283
+ throw new Error(`too many tags: ${dedupedTags.length} exceeds the ${TAG_LIMITS.maxTags}-tag limit`);
284
+ }
285
+ for (const tag of dedupedTags) {
286
+ if (tag.length > TAG_LIMITS.maxTagLength) {
287
+ throw new Error(`tag exceeds ${TAG_LIMITS.maxTagLength} characters: ${JSON.stringify(tag.slice(0, 40))}\u2026`);
288
+ }
289
+ }
277
290
  return {
278
291
  content,
279
292
  category,
280
293
  confidence,
281
294
  namespace: asTrimmed(input.namespace),
282
- tags: Array.from(new Set((input.tags ?? []).map((tag) => tag.trim()).filter(Boolean))),
295
+ tags: dedupedTags,
283
296
  entityRef: asTrimmed(input.entityRef),
284
297
  sourceReason: asTrimmed(input.sourceReason),
285
- sourceConnector: input.sourceConnector,
298
+ // Trimmed like the other optional metadata (#2017 review round): a
299
+ // whitespace-only connector previously passed validation and then blew
300
+ // up at strict compose time - validated input must always compose.
301
+ sourceConnector: asTrimmed(input.sourceConnector),
286
302
  expiresAt
287
303
  };
288
304
  }
@@ -322,14 +338,20 @@ async function persistExplicitCapture(orchestrator, candidate, source) {
322
338
  return { id: duplicateOf, duplicateOf };
323
339
  }
324
340
  const storage = await orchestrator.getStorage(resolvedNamespace);
325
- const { id, tombstoneBlocked } = await storage.writeMemory(candidate.category, candidate.content, {
326
- confidence: candidate.confidence,
327
- tags: candidate.tags,
328
- entityRef: candidate.entityRef,
329
- expiresAt: candidate.expiresAt,
330
- source: source === "inline" ? "explicit-inline" : "explicit",
331
- ...candidate.sourceConnector ? { sourceConnector: candidate.sourceConnector } : {}
332
- });
341
+ const captureEnvelope = composeMemoryEnvelope(
342
+ {
343
+ content: candidate.content,
344
+ category: candidate.category,
345
+ confidence: candidate.confidence,
346
+ tags: candidate.tags,
347
+ ...candidate.entityRef ? { entityRef: candidate.entityRef } : {},
348
+ ...candidate.expiresAt ? { ttl: candidate.expiresAt } : {},
349
+ ...candidate.sourceConnector ? { sourceConnector: candidate.sourceConnector } : {},
350
+ ...candidate.sourceReason ? { sourceReason: candidate.sourceReason } : {}
351
+ },
352
+ { source: source === "inline" ? "explicit-inline" : "explicit" }
353
+ );
354
+ const { id, tombstoneBlocked } = await storage.writeSealedMemory(captureEnvelope);
333
355
  const created = (/* @__PURE__ */ new Date()).toISOString();
334
356
  const event = {
335
357
  eventId: `mle-${randomUUID()}`,
@@ -402,13 +424,26 @@ async function queueExplicitCaptureForReview(orchestrator, input, source, error)
402
424
  const reviewCategory = requestedCategory && INLINE_ALLOWED_CATEGORIES.has(requestedCategory) ? requestedCategory : "fact";
403
425
  const requestedTags = sanitizeReviewTags(input.tags);
404
426
  const storage = await orchestrator.getStorage(queueNamespace);
405
- const { id } = await storage.writeMemory(reviewCategory, content, {
406
- confidence: 0.2,
407
- tags: Array.from(/* @__PURE__ */ new Set([...EXPLICIT_CAPTURE_REVIEW_TAGS, ...requestedTags])),
408
- entityRef: sanitizeReviewMetadata(input.entityRef),
409
- source: source === "inline" ? "explicit-inline-review" : "explicit-review",
410
- ...input.sourceConnector ? { sourceConnector: input.sourceConnector } : {}
411
- });
427
+ const reviewEnvelope = composeMemoryEnvelope(
428
+ {
429
+ content,
430
+ category: reviewCategory,
431
+ confidence: 0.2,
432
+ tags: Array.from(/* @__PURE__ */ new Set([...EXPLICIT_CAPTURE_REVIEW_TAGS, ...requestedTags])),
433
+ ...sanitizeReviewMetadata(input.entityRef) ? { entityRef: sanitizeReviewMetadata(input.entityRef) } : {},
434
+ ...input.sourceConnector ? { sourceConnector: input.sourceConnector } : {}
435
+ },
436
+ { source: source === "inline" ? "explicit-inline-review" : "explicit-review" },
437
+ // The review queue is the FALLBACK for a capture that already failed
438
+ // primary validation — it must never be un-queueable. The tag list is
439
+ // machine-assembled (requested tags + the two fixed review tags), so 49+
440
+ // requested tags would push past the 50-tag limit and strict compose
441
+ // would throw, losing the capture (#2014 review round). Salvage clamps
442
+ // instead; the fixed review tags sort first in the assembly above, so
443
+ // they always survive the clamp.
444
+ { salvage: true }
445
+ );
446
+ const { id } = await storage.writeSealedMemory(reviewEnvelope);
412
447
  try {
413
448
  const created = await storage.getMemoryById(id);
414
449
  if (created) {
@@ -452,4 +487,4 @@ export {
452
487
  shouldSkipImplicitExtraction,
453
488
  shouldProcessInlineExplicitCapture
454
489
  };
455
- //# sourceMappingURL=chunk-BFVEEB7W.js.map
490
+ //# sourceMappingURL=chunk-7ON2JW73.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/explicit-capture.ts"],"sourcesContent":["import { composeMemoryEnvelope, TAG_LIMITS } from \"./write-envelope.js\";\nimport { resolveNamespaceCapabilities } from \"./capabilities.js\";\nimport { randomUUID } from \"node:crypto\";\nimport type { Orchestrator } from \"./orchestrator.js\";\nimport { isSafeRouteNamespace } from \"./routing/engine.js\";\nimport { sanitizeMemoryContent } from \"./sanitize.js\";\nimport { ContentHashIndex } from \"./storage.js\";\nimport type { CaptureMode, MemoryCategory, MemoryLifecycleEvent, PluginConfig } from \"./types.js\";\n\nexport type ExplicitCaptureInput = {\n content: string;\n category?: string;\n confidence?: number;\n namespace?: string;\n tags?: string[];\n entityRef?: string;\n sourceConnector?: string;\n ttl?: string;\n sourceReason?: string;\n};\n\nexport type ValidExplicitCapture = {\n content: string;\n category: MemoryCategory;\n confidence: number;\n namespace?: string;\n tags: string[];\n entityRef?: string;\n sourceConnector?: string;\n expiresAt?: string;\n sourceReason?: string;\n /**\n * When true, `namespace` was already resolved AND authorized by the caller\n * (the access service's `resolveCodingScopedWriteNamespace`, which auth-checks\n * the base and derives a session-owned `project-*` overlay). The persist /\n * queue layer then routes to it directly instead of re-validating against the\n * static policy allow-list — which would otherwise reject legitimately-derived\n * dynamic project namespaces (#1434). Callers that do NOT pre-authorize the\n * namespace must leave this unset so the allow-list guard still applies.\n */\n namespacePreResolved?: boolean;\n};\n\nexport type ExplicitCaptureSource = \"memory_store\" | \"memory_capture\" | \"suggestion_submit\" | \"inline\";\ntype ExplicitCaptureValidationMode = \"legacy_tool\" | \"strict_explicit\";\n\n// Bounded body {0,100000} instead of an unbounded lazy *? so scanning for the\n// closing tag cannot backtrack polynomially on unterminated <memory_note>\n// markup in hostile turn text (CodeQL js/polynomial-redos). 100 000 chars far\n// exceeds any real inline note, so matching is behavior-preserving; the outer\n// \\s* groups were also dropped (body absorbs whitespace; captures are trimmed).\nconst INLINE_NOTE_RE = /<memory_note>([\\s\\S]{0,100000}?)<\\/memory_note>/gi;\nconst INLINE_NOTE_MARKUP_RE = /<memory_note>[\\s\\S]{0,100000}?<\\/memory_note>/i;\nconst INLINE_ALLOWED_CATEGORIES = new Set<MemoryCategory>([\n \"fact\",\n \"preference\",\n \"correction\",\n \"entity\",\n \"decision\",\n \"relationship\",\n \"principle\",\n \"commitment\",\n \"moment\",\n \"skill\",\n \"rule\",\n \"procedure\",\n \"reasoning_trace\",\n]);\n\nconst SECRET_PATTERNS: RegExp[] = [\n /\\bsk-[A-Za-z0-9]{16,}\\b/,\n /\\bAKIA[0-9A-Z]{16}\\b/,\n /\\bBearer\\s+[A-Za-z0-9._-]{16,}\\b/i,\n /\\b(?:api[_-]?key|secret|token|password|passwd)\\s*[:=]\\s*[^\\s]{8,}\\b/i,\n /\\b(?:authorization)\\s*:\\s*[^\\s]{8,}\\b/i,\n];\nconst SECRET_REDACTION_PATTERNS: Array<{ pattern: RegExp; replacement: string }> = [\n { pattern: /\\bsk-[A-Za-z0-9]{16,}\\b/g, replacement: \"[redacted openai key]\" },\n { pattern: /\\bAKIA[0-9A-Z]{16}\\b/g, replacement: \"[redacted aws key]\" },\n { pattern: /\\bBearer\\s+[A-Za-z0-9._-]{16,}\\b/gi, replacement: \"Bearer [redacted token]\" },\n {\n pattern: /\\b(?:api[_-]?key|secret|token|password|passwd)\\s*[:=]\\s*[^\\s]{8,}\\b/gi,\n replacement: \"[redacted credential]\",\n },\n {\n pattern: /\\b(?:authorization)\\s*:\\s*[^\\s]{8,}\\b/gi,\n replacement: \"authorization: [redacted credential]\",\n },\n];\nconst EXPLICIT_CAPTURE_REVIEW_TAGS = [\"explicit-capture\", \"queued-review\"];\n\nfunction explicitCaptureActor(source: ExplicitCaptureSource): string {\n switch (source) {\n case \"inline\":\n return \"inline.memory_note\";\n case \"memory_store\":\n return \"tool.memory_store\";\n case \"suggestion_submit\":\n return \"tool.suggestion_submit\";\n default:\n return \"tool.memory_capture\";\n }\n}\n\nfunction asTrimmed(value: string | undefined): string | undefined {\n const trimmed = value?.trim();\n return trimmed && trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction normalizeCaptureContent(value: string): string {\n return value\n .toLowerCase()\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\nfunction redactSecrets(value: string): string {\n let redacted = value;\n for (const { pattern, replacement } of SECRET_REDACTION_PATTERNS) {\n redacted = redacted.replace(pattern, replacement);\n }\n return redacted;\n}\n\nfunction containsSecretLikeValue(value: string): boolean {\n return SECRET_PATTERNS.some((pattern) => pattern.test(value));\n}\n\nfunction assertNoSecretLikeMetadata(field: string, value: string | undefined): void {\n const trimmed = asTrimmed(value);\n if (trimmed && containsSecretLikeValue(trimmed)) {\n throw new Error(`${field} appears to contain a secret or credential`);\n }\n}\n\nfunction assertNoSecretLikeMetadataList(field: string, values: string[] | undefined): void {\n for (const value of values ?? []) {\n assertNoSecretLikeMetadata(field, value);\n }\n}\n\nfunction sanitizeReviewText(value: string | undefined, fallback: string): string {\n const redacted = redactSecrets(asTrimmed(value) ?? fallback);\n const sanitized = sanitizeMemoryContent(redacted);\n const safe = sanitized.text.trim();\n return safe.length > 0 ? safe : fallback;\n}\n\nfunction sanitizeReviewMetadata(value: string | undefined): string | undefined {\n const trimmed = asTrimmed(value);\n if (!trimmed) return undefined;\n return sanitizeReviewText(trimmed, \"[redacted]\");\n}\n\nfunction sanitizeReviewTags(tags: string[] | undefined): string[] {\n return Array.from(new Set((tags ?? [])\n .map((tag) => sanitizeReviewMetadata(tag))\n .filter((tag): tag is string => typeof tag === \"string\" && tag.length > 0)));\n}\n\nfunction normalizeExplicitCaptureError(error: unknown): string {\n if (error instanceof Error && error.message.trim().length > 0) return error.message.trim();\n const rendered = String(error).trim();\n return rendered.length > 0 ? rendered : \"explicit capture failed\";\n}\n\nfunction resolveExplicitCaptureReviewNamespace(\n orchestrator: Orchestrator,\n namespace: string | undefined,\n): string | undefined {\n const normalized = asTrimmed(namespace);\n if (!normalized) return undefined;\n return resolveExplicitCaptureNamespace(orchestrator, normalized);\n}\n\nfunction resolveExplicitCaptureNamespace(\n orchestrator: Orchestrator,\n namespace: string | undefined,\n): string | undefined {\n const normalized = asTrimmed(namespace);\n if (!normalized) return undefined;\n if (!resolveNamespaceCapabilities(orchestrator.config).namespaces) {\n if (normalized !== orchestrator.config.defaultNamespace) {\n throw new Error(`unsupported namespace: ${normalized}`);\n }\n return normalized;\n }\n const allowed = new Set([\n orchestrator.config.defaultNamespace,\n orchestrator.config.sharedNamespace,\n ...orchestrator.config.namespacePolicies.map((policy) => policy.name),\n ].map((value) => value.trim()).filter(Boolean));\n if (!allowed.has(normalized)) {\n throw new Error(`unsupported namespace: ${normalized}`);\n }\n return normalized;\n}\n\nfunction parseExplicitCaptureTtl(ttl: string | undefined): string | undefined {\n const raw = asTrimmed(ttl);\n if (!raw) return undefined;\n\n const absoluteMs = Date.parse(raw);\n if (Number.isFinite(absoluteMs)) {\n return new Date(absoluteMs).toISOString();\n }\n\n const relative = raw.match(/^(\\d+)\\s*([mhdw])$/i);\n if (!relative) {\n throw new Error(\"ttl must be an ISO-8601 timestamp or relative duration like 30m, 12h, 7d, or 2w\");\n }\n\n const amount = Number.parseInt(relative[1] ?? \"\", 10);\n const unit = (relative[2] ?? \"\").toLowerCase();\n if (!Number.isFinite(amount) || amount <= 0) {\n throw new Error(\"ttl duration must be a positive integer\");\n }\n\n const multiplier =\n unit === \"m\" ? 60_000\n : unit === \"h\" ? 60 * 60_000\n : unit === \"d\" ? 24 * 60 * 60_000\n : 7 * 24 * 60 * 60_000;\n return new Date(Date.now() + amount * multiplier).toISOString();\n}\n\nfunction parseInlineConfidence(value: string): number {\n const trimmed = value.trim();\n if (!/^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?$/i.test(trimmed)) {\n return Number.NaN;\n }\n const parsed = Number(trimmed);\n return Number.isFinite(parsed) ? parsed : Number.NaN;\n}\n\nfunction parseInlineNote(block: string): ExplicitCaptureInput | null {\n const lines = block.replace(/\\r/g, \"\").split(\"\\n\");\n const note: Partial<ExplicitCaptureInput> = {};\n let idx = 0;\n\n while (idx < lines.length) {\n const rawLine = lines[idx] ?? \"\";\n const line = rawLine.trim();\n idx += 1;\n if (line.length === 0) continue;\n const colonIdx = line.indexOf(\":\");\n if (colonIdx < 0) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n\n if (key === \"content\" && value === \"|\") {\n const contentLines: string[] = [];\n while (idx < lines.length) {\n const next = lines[idx] ?? \"\";\n if (next.startsWith(\" \") || next.startsWith(\"\\t\")) {\n contentLines.push(next.replace(/^( |\\t)/, \"\"));\n idx += 1;\n continue;\n }\n if (next.trim().length === 0) {\n contentLines.push(\"\");\n idx += 1;\n continue;\n }\n break;\n }\n note.content = contentLines.join(\"\\n\").trim();\n continue;\n }\n\n switch (key) {\n case \"content\":\n note.content = value;\n break;\n case \"category\":\n note.category = value;\n break;\n case \"confidence\":\n note.confidence = parseInlineConfidence(value);\n break;\n case \"namespace\":\n note.namespace = value;\n break;\n case \"tags\":\n note.tags = value\n .split(\",\")\n .map((entry) => entry.trim())\n .filter(Boolean);\n break;\n case \"entityRef\":\n note.entityRef = value;\n break;\n case \"ttl\":\n note.ttl = value;\n break;\n case \"sourceReason\":\n note.sourceReason = value;\n break;\n default:\n break;\n }\n }\n\n return asTrimmed(note.content) ? (note as ExplicitCaptureInput) : null;\n}\n\nexport function parseInlineExplicitCaptureNotes(text: string): ExplicitCaptureInput[] {\n const notes: ExplicitCaptureInput[] = [];\n for (const match of text.matchAll(INLINE_NOTE_RE)) {\n const parsed = parseInlineNote(match[1] ?? \"\");\n if (parsed) notes.push(parsed);\n }\n return notes;\n}\n\nexport function hasInlineExplicitCaptureMarkup(text: string): boolean {\n return INLINE_NOTE_MARKUP_RE.test(text);\n}\n\nexport function stripInlineExplicitCaptureNotes(text: string): string {\n return text.replace(INLINE_NOTE_RE, \"\").trim();\n}\n\nexport function validateExplicitCaptureInput(\n input: ExplicitCaptureInput,\n mode: ExplicitCaptureValidationMode = \"strict_explicit\",\n): ValidExplicitCapture {\n const content = asTrimmed(input.content);\n if (!content) throw new Error(\"content is required\");\n if (mode === \"strict_explicit\") {\n if (content.length < 10) throw new Error(\"content must be at least 10 characters\");\n if (content.length > 4000) throw new Error(\"content must be 4000 characters or fewer\");\n }\n if (/<memory_note>/i.test(content) || /<\\/memory_note>/i.test(content)) {\n throw new Error(\"nested memory_note blocks are not allowed\");\n }\n\n const category = (asTrimmed(input.category) ?? \"fact\") as MemoryCategory;\n if (!INLINE_ALLOWED_CATEGORIES.has(category)) {\n throw new Error(`unsupported category: ${input.category ?? category}`);\n }\n\n const sanitized = sanitizeMemoryContent(content);\n if (!sanitized.clean) {\n throw new Error(\"content failed memory sanitization\");\n }\n for (const pattern of SECRET_PATTERNS) {\n if (pattern.test(content)) {\n throw new Error(\"content appears to contain a secret or credential\");\n }\n }\n assertNoSecretLikeMetadata(\"sourceReason\", input.sourceReason);\n assertNoSecretLikeMetadata(\"entityRef\", input.entityRef);\n assertNoSecretLikeMetadata(\"ttl\", input.ttl);\n assertNoSecretLikeMetadataList(\"tags\", input.tags);\n\n if (input.confidence !== undefined && !Number.isFinite(input.confidence)) {\n throw new Error(\"confidence must be a finite number\");\n }\n const confidence = input.confidence === undefined ? 0.95 : Number(input.confidence);\n if (confidence < 0 || confidence > 1) {\n throw new Error(\"confidence must be between 0 and 1\");\n }\n const requestedNamespace = asTrimmed(input.namespace);\n if (requestedNamespace && !isSafeRouteNamespace(requestedNamespace)) {\n throw new Error(`unsafe namespace: ${requestedNamespace}`);\n }\n const expiresAt = parseExplicitCaptureTtl(input.ttl);\n\n // #2014 review round: enforce the composer's tag contract HERE so a capture\n // that passes validation can never fail later at strict compose time\n // (validated-then-thrown was a broken contract). Same limits as TAG_LIMITS.\n const dedupedTags = Array.from(new Set((input.tags ?? []).map((tag) => tag.trim()).filter(Boolean)));\n if (dedupedTags.length > TAG_LIMITS.maxTags) {\n throw new Error(`too many tags: ${dedupedTags.length} exceeds the ${TAG_LIMITS.maxTags}-tag limit`);\n }\n for (const tag of dedupedTags) {\n if (tag.length > TAG_LIMITS.maxTagLength) {\n throw new Error(`tag exceeds ${TAG_LIMITS.maxTagLength} characters: ${JSON.stringify(tag.slice(0, 40))}…`);\n }\n }\n\n return {\n content,\n category,\n confidence,\n namespace: asTrimmed(input.namespace),\n tags: dedupedTags,\n entityRef: asTrimmed(input.entityRef),\n sourceReason: asTrimmed(input.sourceReason),\n // Trimmed like the other optional metadata (#2017 review round): a\n // whitespace-only connector previously passed validation and then blew\n // up at strict compose time - validated input must always compose.\n sourceConnector: asTrimmed(input.sourceConnector),\n expiresAt,\n };\n}\n\nasync function findDuplicateExplicitCapture(\n orchestrator: Orchestrator,\n resolvedNamespace: string | undefined,\n candidate: ValidExplicitCapture,\n): Promise<string | null> {\n const storage = await orchestrator.getStorage(resolvedNamespace);\n if (\n candidate.category === \"fact\"\n && typeof (storage as { hasFactContentHash?: (content: string) => Promise<boolean> }).hasFactContentHash === \"function\"\n ) {\n try {\n const hasHash = await (storage as { hasFactContentHash: (content: string) => Promise<boolean> }).hasFactContentHash(\n candidate.content,\n );\n if (!hasHash) {\n const authoritative =\n typeof (storage as { isFactContentHashAuthoritative?: () => Promise<boolean> | boolean }).isFactContentHashAuthoritative\n === \"function\"\n ? await (storage as { isFactContentHashAuthoritative: () => Promise<boolean> | boolean })\n .isFactContentHashAuthoritative()\n : false;\n if (authoritative) return null;\n }\n } catch (err) {\n // Fail open: hash index is only an optimization, so fall back to the full corpus scan.\n void err;\n }\n }\n const existing = await storage.readAllMemories();\n const normalizedCandidate = normalizeCaptureContent(candidate.content);\n const match = existing.find((memory) => {\n const status = memory.frontmatter.status ?? \"active\";\n if (status !== \"active\") return false;\n if (memory.frontmatter.category !== candidate.category) return false;\n if (normalizeCaptureContent(memory.content) !== normalizedCandidate) return false;\n // Connector-aware dedup: same content from different connectors is NOT\n // a duplicate. Operator (undefined) and connector-tagged memories are\n // always distinct. Normalize empty strings to undefined.\n const existingConnector = memory.frontmatter.sourceConnector?.trim() || undefined;\n const newConnector = candidate.sourceConnector?.trim() || undefined;\n if (existingConnector !== newConnector) return false;\n return true;\n });\n return match?.frontmatter.id ?? null;\n}\n\nexport async function persistExplicitCapture(\n orchestrator: Orchestrator,\n candidate: ValidExplicitCapture,\n source: ExplicitCaptureSource,\n): Promise<{ id: string; duplicateOf?: string; tombstoneBlocked?: boolean }> {\n const resolvedNamespace = candidate.namespacePreResolved\n ? asTrimmed(candidate.namespace)\n : resolveExplicitCaptureNamespace(orchestrator, candidate.namespace);\n const duplicateOf = await findDuplicateExplicitCapture(orchestrator, resolvedNamespace, candidate);\n if (duplicateOf) {\n return { id: duplicateOf, duplicateOf };\n }\n\n const storage = await orchestrator.getStorage(resolvedNamespace);\n // #1645 (review thread yG-): surface the tombstone block so callers\n // (memory_store tool, access-service HTTP/MCP) can report the capture as\n // queued for review instead of a successfully stored active memory.\n // Sealed-envelope write (issue #1989 PR2).\n const captureEnvelope = composeMemoryEnvelope(\n {\n content: candidate.content,\n category: candidate.category,\n confidence: candidate.confidence,\n tags: candidate.tags,\n ...(candidate.entityRef ? { entityRef: candidate.entityRef } : {}),\n ...(candidate.expiresAt ? { ttl: candidate.expiresAt } : {}),\n ...(candidate.sourceConnector ? { sourceConnector: candidate.sourceConnector } : {}),\n ...(candidate.sourceReason ? { sourceReason: candidate.sourceReason } : {}),\n },\n { source: source === \"inline\" ? \"explicit-inline\" : \"explicit\" },\n );\n const { id, tombstoneBlocked } = await storage.writeSealedMemory(captureEnvelope);\n // #1522: catalog touch handled at the storage chokepoint — the StorageManager's\n // post-write hook records the namespace touch automatically.\n\n const created = new Date().toISOString();\n const event: MemoryLifecycleEvent = {\n eventId: `mle-${randomUUID()}`,\n memoryId: id,\n eventType: \"explicit_capture_accepted\",\n timestamp: created,\n actor: explicitCaptureActor(source),\n reasonCode: candidate.sourceReason,\n ruleVersion: \"explicit-capture.v1\",\n };\n await storage.appendMemoryLifecycleEvents([event]);\n\n return { id, tombstoneBlocked };\n}\n\nfunction buildExplicitCaptureReviewContent(input: ExplicitCaptureInput, reason: string): string {\n const requestedContent = asTrimmed(input.content);\n const safeContent = sanitizeReviewText(requestedContent, \"[empty explicit capture]\");\n const safeCategory = sanitizeReviewMetadata(input.category);\n const safeNamespace = sanitizeReviewMetadata(input.namespace);\n const safeEntityRef = sanitizeReviewMetadata(input.entityRef);\n const safeTtl = sanitizeReviewMetadata(input.ttl);\n const safeSourceReason = sanitizeReviewMetadata(input.sourceReason);\n const safeTags = sanitizeReviewTags(input.tags);\n const lines = [\n \"Explicit capture queued for review.\",\n \"\",\n `Reason: ${reason}`,\n \"\",\n \"Submitted content:\",\n safeContent,\n ];\n const metadata = [\n safeCategory ? `Requested category: ${safeCategory}` : undefined,\n safeNamespace ? `Requested namespace: ${safeNamespace}` : undefined,\n safeEntityRef ? `Requested entityRef: ${safeEntityRef}` : undefined,\n safeTtl ? `Requested ttl: ${safeTtl}` : undefined,\n safeSourceReason ? `Requested sourceReason: ${safeSourceReason}` : undefined,\n safeTags.length > 0 ? `Requested tags: ${safeTags.join(\", \")}` : undefined,\n ].filter((entry): entry is string => typeof entry === \"string\" && entry.length > 0);\n if (metadata.length > 0) {\n lines.push(\"\", ...metadata);\n }\n return lines.join(\"\\n\");\n}\n\nasync function findQueuedExplicitCaptureDuplicate(\n orchestrator: Orchestrator,\n namespace: string | undefined,\n content: string,\n sourceConnector?: string,\n): Promise<string | null> {\n const storage = await orchestrator.getStorage(namespace);\n const existing = await storage.readAllMemories();\n const normalized = normalizeCaptureContent(content);\n const match = existing.find((memory) => {\n const status = memory.frontmatter.status ?? \"active\";\n if (status !== \"pending_review\") return false;\n if (!(memory.frontmatter.tags ?? []).includes(\"queued-review\")) return false;\n if (normalizeCaptureContent(memory.content) !== normalized) return false;\n const existingConnector = memory.frontmatter.sourceConnector?.trim() || undefined;\n const newConnector = sourceConnector?.trim() || undefined;\n if (existingConnector !== newConnector) return false;\n return true;\n });\n return match?.frontmatter.id ?? null;\n}\n\nexport async function queueExplicitCaptureForReview(\n orchestrator: Orchestrator,\n input: ExplicitCaptureInput,\n source: ExplicitCaptureSource,\n error: unknown,\n): Promise<{ id: string; duplicateOf?: string }> {\n const reason = sanitizeReviewText(normalizeExplicitCaptureError(error), \"explicit capture failed\");\n const requestedNamespace = asTrimmed(input.namespace);\n // A caller-pre-authorized namespace (e.g. a session-owned project overlay\n // from the access service) routes directly; otherwise apply the static\n // policy allow-list guard (#1434).\n const queueNamespace = (input as { namespacePreResolved?: boolean }).namespacePreResolved\n ? requestedNamespace\n : resolveExplicitCaptureReviewNamespace(orchestrator, requestedNamespace);\n const content = buildExplicitCaptureReviewContent(input, reason);\n const duplicateOf = await findQueuedExplicitCaptureDuplicate(orchestrator, queueNamespace, content, input.sourceConnector);\n if (duplicateOf) {\n return { id: duplicateOf, duplicateOf };\n }\n\n const requestedCategory = asTrimmed(input.category);\n const reviewCategory = requestedCategory && INLINE_ALLOWED_CATEGORIES.has(requestedCategory as MemoryCategory)\n ? requestedCategory as MemoryCategory\n : \"fact\";\n const requestedTags = sanitizeReviewTags(input.tags);\n const storage = await orchestrator.getStorage(queueNamespace);\n const reviewEnvelope = composeMemoryEnvelope(\n {\n content,\n category: reviewCategory,\n confidence: 0.2,\n tags: Array.from(new Set([...EXPLICIT_CAPTURE_REVIEW_TAGS, ...requestedTags])),\n ...(sanitizeReviewMetadata(input.entityRef) ? { entityRef: sanitizeReviewMetadata(input.entityRef) } : {}),\n ...(input.sourceConnector ? { sourceConnector: input.sourceConnector } : {}),\n },\n { source: source === \"inline\" ? \"explicit-inline-review\" : \"explicit-review\" },\n // The review queue is the FALLBACK for a capture that already failed\n // primary validation — it must never be un-queueable. The tag list is\n // machine-assembled (requested tags + the two fixed review tags), so 49+\n // requested tags would push past the 50-tag limit and strict compose\n // would throw, losing the capture (#2014 review round). Salvage clamps\n // instead; the fixed review tags sort first in the assembly above, so\n // they always survive the clamp.\n { salvage: true },\n );\n const { id: id } = await storage.writeSealedMemory(reviewEnvelope);\n try {\n const created = await storage.getMemoryById(id);\n if (created) {\n await storage.writeMemoryFrontmatter(created, {\n status: \"pending_review\",\n updated: new Date().toISOString(),\n }, {\n actor: explicitCaptureActor(source),\n reasonCode: reason,\n ruleVersion: \"explicit-capture.v1\",\n });\n }\n } finally {\n // Record the catalog write touch (issue #1499, round 5/6 codex P2; NIhUg).\n // A queued review capture writes memory to the namespace's root (the DEFAULT\n // root when undefined), so its `lastWriteAt` must reflect the write once\n // `writeMemory` returns an id. If the later pending-review frontmatter update\n // fails, the memory file is still durable and must not disappear from\n // writtenSince/maintenance scheduling. Guarded optional hook (rule #33).\n // #1522: catalog touch handled at the storage chokepoint.\n }\n const event: MemoryLifecycleEvent = {\n eventId: `mle-${randomUUID()}`,\n memoryId: id,\n eventType: \"explicit_capture_queued\",\n timestamp: new Date().toISOString(),\n actor: explicitCaptureActor(source),\n reasonCode: reason,\n ruleVersion: \"explicit-capture.v1\",\n };\n await storage.appendMemoryLifecycleEvents([event]);\n return { id };\n}\n\nexport function shouldSkipImplicitExtraction(cfg: Pick<PluginConfig, \"captureMode\">): boolean {\n return cfg.captureMode === \"explicit\";\n}\n\nexport function shouldProcessInlineExplicitCapture(cfg: Pick<PluginConfig, \"captureMode\">): boolean {\n return cfg.captureMode !== \"implicit\";\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,270 @@
1
+ import {
2
+ toBackupStamp
3
+ } from "./chunk-KJTKLXTH.js";
4
+ import {
5
+ copyExistingFileToBackup,
6
+ writeFileAtomically
7
+ } from "./chunk-R6YJI3HE.js";
8
+ import {
9
+ StorageManager
10
+ } from "./chunk-4BJQODZF.js";
11
+ import {
12
+ withHeldFileLock
13
+ } from "./chunk-WL5EBRDH.js";
14
+ import {
15
+ displayErrorDetail
16
+ } from "./chunk-RL6NEVXT.js";
17
+ import {
18
+ MEMORY_LIFECYCLE_LEDGER_LOCK_STALE_MS,
19
+ buildLifecycleEventsForMemory,
20
+ compareMemoryLifecycleEvents,
21
+ memoryLifecycleLedgerLockPath,
22
+ sortMemoryLifecycleEvents
23
+ } from "./chunk-ILGC6JH6.js";
24
+ import {
25
+ probeEncryptedRegularFileHeader
26
+ } from "./chunk-AIK5W3IW.js";
27
+ import {
28
+ log
29
+ } from "./chunk-3WCASNQZ.js";
30
+
31
+ // src/maintenance/rebuild-memory-lifecycle-ledger.ts
32
+ import path from "path";
33
+ import { stat } from "fs/promises";
34
+ var FRONTMATTER_DERIVED_EVENT_TYPES = {
35
+ created: true,
36
+ updated: true,
37
+ superseded: true,
38
+ archived: true
39
+ };
40
+ function isNodeError(err) {
41
+ return typeof err === "object" && err !== null && "code" in err;
42
+ }
43
+ function lifecycleRowBytes(event) {
44
+ return Buffer.byteLength(`${JSON.stringify(event)}
45
+ `, "utf8");
46
+ }
47
+ function boundLifecycleEventsToByteCap(events, cap) {
48
+ if (!(cap > 0)) return { kept: events, dropped: 0 };
49
+ const sizes = /* @__PURE__ */ new Map();
50
+ let total = 0;
51
+ for (const event of events) {
52
+ const bytes = lifecycleRowBytes(event);
53
+ sizes.set(event, bytes);
54
+ total += bytes;
55
+ }
56
+ if (total <= cap) return { kept: events, dropped: 0 };
57
+ const byRecency = [...events].sort((a, b) => {
58
+ if (a.timestamp !== b.timestamp) return b.timestamp.localeCompare(a.timestamp);
59
+ return -compareMemoryLifecycleEvents(a, b);
60
+ });
61
+ const keep = /* @__PURE__ */ new Set();
62
+ let running = 0;
63
+ for (const event of byRecency) {
64
+ const bytes = sizes.get(event);
65
+ if (running + bytes > cap) continue;
66
+ running += bytes;
67
+ keep.add(event);
68
+ }
69
+ const kept = events.filter((event) => keep.has(event));
70
+ return { kept, dropped: events.length - kept.length };
71
+ }
72
+ async function backupExistingLedger(memoryDir, outputPath, now) {
73
+ try {
74
+ await stat(outputPath);
75
+ } catch (err) {
76
+ if (isNodeError(err) && err.code === "ENOENT") {
77
+ return void 0;
78
+ }
79
+ throw err;
80
+ }
81
+ const backupPath = path.join(
82
+ memoryDir,
83
+ "archive",
84
+ "memory-lifecycle-ledger",
85
+ toBackupStamp(now),
86
+ "state",
87
+ "memory-lifecycle-ledger.jsonl"
88
+ );
89
+ return backupPath;
90
+ }
91
+ async function rebuildMemoryLifecycleLedger(options) {
92
+ const dryRun = options.dryRun !== false;
93
+ const now = options.now ?? /* @__PURE__ */ new Date();
94
+ const outputPath = path.join(options.memoryDir, "state", "memory-lifecycle-ledger.jsonl");
95
+ const storage = options.storage ?? new StorageManager(options.memoryDir);
96
+ if (options.storage && path.resolve(storage.dir) !== path.resolve(options.memoryDir)) {
97
+ throw new Error(
98
+ `rebuildMemoryLifecycleLedger: storage.dir (${storage.dir}) must match memoryDir (${options.memoryDir})`
99
+ );
100
+ }
101
+ const secureRewrite = options.storage !== void 0;
102
+ const tiers = [
103
+ await storage.readAllMemories(),
104
+ await storage.readAllColdMemories(),
105
+ await storage.readArchivedMemories()
106
+ ];
107
+ const allMemories = tiers.flat();
108
+ const skippedBlankIdMemories = [];
109
+ const eventCandidates = [];
110
+ for (const tier of tiers) {
111
+ for (const memory of [...tier].sort((left, right) => left.path.localeCompare(right.path))) {
112
+ if (!memory.frontmatter.id.trim()) {
113
+ skippedBlankIdMemories.push({ path: memory.path });
114
+ log.warn(`lifecycle ledger rebuild skipped blank memory id: path=${memory.path}`);
115
+ continue;
116
+ }
117
+ for (const event of buildLifecycleEventsForMemory(memory)) {
118
+ eventCandidates.push({ event, path: memory.path });
119
+ }
120
+ }
121
+ }
122
+ const orderedEvents = sortMemoryLifecycleEvents(eventCandidates.map((candidate) => candidate.event));
123
+ const candidateByEvent = new Map(
124
+ eventCandidates.map((candidate) => [candidate.event, candidate])
125
+ );
126
+ const keptByEventId = /* @__PURE__ */ new Map();
127
+ const events = [];
128
+ const skippedDuplicateEvents = [];
129
+ for (const event of orderedEvents) {
130
+ const candidate = candidateByEvent.get(event);
131
+ const kept = keptByEventId.get(event.eventId);
132
+ if (kept) {
133
+ skippedDuplicateEvents.push({
134
+ eventId: event.eventId,
135
+ keptPath: kept.path,
136
+ skippedPath: candidate.path
137
+ });
138
+ log.warn(
139
+ `lifecycle ledger rebuild skipped duplicate event_id=${event.eventId}: kept=${kept.path} skipped=${candidate.path}`
140
+ );
141
+ continue;
142
+ }
143
+ keptByEventId.set(event.eventId, candidate);
144
+ events.push(event);
145
+ }
146
+ let finalEvents = events;
147
+ let preservedAppendOnlyRows;
148
+ let archivedOverflowRows;
149
+ let backupPath;
150
+ let rewritten = false;
151
+ const runLedgerCriticalSection = async (acquired, lock) => {
152
+ if (!dryRun && !acquired) {
153
+ throw new Error(
154
+ "lifecycle ledger rebuild aborted: could not acquire the ledger lock within the acquisition budget; refusing to read or rewrite unlocked so a concurrent append or compaction cannot be clobbered (issue #1910)."
155
+ );
156
+ }
157
+ if (options.preserveExistingEvents) {
158
+ let existing;
159
+ try {
160
+ existing = await storage.readAllMemoryLifecycleEventsForCompaction();
161
+ } catch (err) {
162
+ throw new Error(
163
+ `lifecycle ledger rebuild aborted: cannot read existing events to preserve (${displayErrorDetail(err) || "unknown error"})`
164
+ );
165
+ }
166
+ const contentKey = (event) => `${event.memoryId}\0${event.eventType}\0${event.timestamp}`;
167
+ const reconstructedKeys = new Set(events.map(contentKey));
168
+ const racedFrontmatterByKey = /* @__PURE__ */ new Map();
169
+ const appendOnly = [];
170
+ for (const event of existing) {
171
+ if (!FRONTMATTER_DERIVED_EVENT_TYPES[event.eventType]) {
172
+ appendOnly.push(event);
173
+ continue;
174
+ }
175
+ const key = contentKey(event);
176
+ if (reconstructedKeys.has(key)) continue;
177
+ if (!racedFrontmatterByKey.has(key)) racedFrontmatterByKey.set(key, event);
178
+ }
179
+ const mergedById = /* @__PURE__ */ new Map();
180
+ for (const event of sortMemoryLifecycleEvents([
181
+ ...events,
182
+ ...racedFrontmatterByKey.values(),
183
+ ...appendOnly
184
+ ])) {
185
+ if (!mergedById.has(event.eventId)) mergedById.set(event.eventId, event);
186
+ }
187
+ finalEvents = [...mergedById.values()];
188
+ preservedAppendOnlyRows = finalEvents.length - events.length;
189
+ if (options.maxLedgerBytes && options.maxLedgerBytes > 0) {
190
+ const bounded = boundLifecycleEventsToByteCap(finalEvents, options.maxLedgerBytes);
191
+ if (bounded.dropped > 0) {
192
+ finalEvents = bounded.kept;
193
+ archivedOverflowRows = bounded.dropped;
194
+ log.warn(
195
+ `lifecycle ledger rebuild bounded to ${options.maxLedgerBytes} bytes: dropped ${bounded.dropped} oldest row(s) from the active ledger (preserved in the backup) to stay under the read/decrypt cap.`
196
+ );
197
+ }
198
+ }
199
+ }
200
+ const abortIfLockLost = async () => {
201
+ if (lock && await lock.refresh()) return;
202
+ throw new Error(
203
+ "lifecycle ledger rebuild aborted: lost the ledger lock during the compaction rewrite (a peer stale-broke it while the event loop was blocked by CPU-bound merge/serialize); refusing to clobber a concurrent append (issue #1910/#2033)."
204
+ );
205
+ };
206
+ if (!dryRun) {
207
+ const payload = finalEvents.map((event) => JSON.stringify(event)).join("\n");
208
+ const content = payload.length > 0 ? `${payload}
209
+ ` : "";
210
+ let currentEncrypted = false;
211
+ let priorRawBuffer = null;
212
+ try {
213
+ currentEncrypted = await probeEncryptedRegularFileHeader(outputPath);
214
+ priorRawBuffer = await storage.readMemoryLifecycleLedgerRawBufferForCompaction();
215
+ } catch (err) {
216
+ if (!isNodeError(err) || err.code !== "ENOENT") throw err;
217
+ }
218
+ const forceEncrypt = secureRewrite && currentEncrypted && storage.isSecureStoreUnlocked();
219
+ const replacementEncrypted = secureRewrite && (storage.willEncryptStateWrites() || forceEncrypt);
220
+ if (priorRawBuffer !== null && currentEncrypted === replacementEncrypted && priorRawBuffer.equals(Buffer.from(content, "utf8"))) {
221
+ rewritten = false;
222
+ } else {
223
+ const desiredBackup = await backupExistingLedger(options.memoryDir, outputPath, now);
224
+ if (secureRewrite) {
225
+ if (desiredBackup && currentEncrypted) {
226
+ const rawForBackup = priorRawBuffer ?? await storage.readMemoryLifecycleLedgerRawBufferForCompaction();
227
+ await storage.writeMemoryLifecycleLedgerContent(rawForBackup, desiredBackup, forceEncrypt);
228
+ backupPath = desiredBackup;
229
+ } else {
230
+ backupPath = desiredBackup ? await copyExistingFileToBackup(outputPath, desiredBackup) : void 0;
231
+ }
232
+ await abortIfLockLost();
233
+ await storage.writeMemoryLifecycleLedgerContent(content, void 0, forceEncrypt);
234
+ } else {
235
+ await abortIfLockLost();
236
+ backupPath = await writeFileAtomically(outputPath, content, desiredBackup);
237
+ }
238
+ rewritten = true;
239
+ }
240
+ }
241
+ };
242
+ if (!dryRun) {
243
+ await withHeldFileLock(
244
+ memoryLifecycleLedgerLockPath(outputPath),
245
+ { staleMs: MEMORY_LIFECYCLE_LEDGER_LOCK_STALE_MS, ...options.lockOptions },
246
+ runLedgerCriticalSection
247
+ );
248
+ } else if (options.preserveExistingEvents) {
249
+ await runLedgerCriticalSection(true, null);
250
+ }
251
+ return {
252
+ dryRun,
253
+ scannedMemories: allMemories.length,
254
+ rebuiltRows: finalEvents.length,
255
+ outputPath,
256
+ backupPath,
257
+ skippedBlankIdMemories,
258
+ skippedDuplicateEvents,
259
+ preservedAppendOnlyRows,
260
+ archivedOverflowRows,
261
+ rewritten
262
+ };
263
+ }
264
+
265
+ export {
266
+ boundLifecycleEventsToByteCap,
267
+ backupExistingLedger,
268
+ rebuildMemoryLifecycleLedger
269
+ };
270
+ //# sourceMappingURL=chunk-7RNBVZZO.js.map