@remnic/core 9.7.15 → 9.9.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-DbZ1G3zV.d.ts} +29 -36
  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-L2B3EE7B.js → chunk-2QMKMVHH.js} +2 -2
  88. package/dist/{chunk-VJVNLNDQ.js → chunk-2UFO7X4Q.js} +7 -7
  89. package/dist/{chunk-2MR3MFQB.js → chunk-2VEOKUPP.js} +3 -3
  90. package/dist/chunk-2Z24E5W2.js +22 -0
  91. package/dist/chunk-2Z24E5W2.js.map +1 -0
  92. package/dist/{chunk-RHOZ5LLO.js → chunk-347WD2LE.js} +2 -2
  93. package/dist/{chunk-HDTQVNWD.js → chunk-3QAH2S33.js} +3 -3
  94. package/dist/{chunk-37CTGERM.js → chunk-3WCASNQZ.js} +12 -1
  95. package/dist/chunk-3WCASNQZ.js.map +1 -0
  96. package/dist/{chunk-LRNMRXJO.js → chunk-3Y224NYC.js} +3 -3
  97. package/dist/{chunk-3IY64MV6.js → chunk-44XZ75OQ.js} +44 -10
  98. package/dist/chunk-44XZ75OQ.js.map +1 -0
  99. package/dist/{chunk-VFSP73LP.js → chunk-45GF7Y3V.js} +2 -2
  100. package/dist/{chunk-K7LOWSLU.js → chunk-4BJQODZF.js} +2479 -1520
  101. package/dist/chunk-4BJQODZF.js.map +1 -0
  102. package/dist/{chunk-JREB6UFH.js → chunk-57OWKFUQ.js} +17 -6
  103. package/dist/chunk-57OWKFUQ.js.map +1 -0
  104. package/dist/{chunk-OEHCMALU.js → chunk-5I4M26Q7.js} +5 -5
  105. package/dist/{chunk-2AZXIZEN.js → chunk-5Q7EVV4X.js} +6 -6
  106. package/dist/{chunk-LC7OODWZ.js → chunk-5SB7SC2G.js} +80 -49
  107. package/dist/chunk-5SB7SC2G.js.map +1 -0
  108. package/dist/{chunk-PUBTHW5O.js → chunk-6DRPPQEJ.js} +2 -2
  109. package/dist/{chunk-NWTGD4AN.js → chunk-6KIQT7RG.js} +10 -9
  110. package/dist/chunk-6KIQT7RG.js.map +1 -0
  111. package/dist/{chunk-FDCTQWLW.js → chunk-6O22TZSB.js} +3 -3
  112. package/dist/{chunk-ZQ7UBUZ6.js → chunk-6QYST5XN.js} +6 -6
  113. package/dist/{chunk-W4PGTAS2.js → chunk-6WAFYNVT.js} +3 -3
  114. package/dist/chunk-6ZMAMSHS.js +20 -0
  115. package/dist/chunk-6ZMAMSHS.js.map +1 -0
  116. package/dist/{chunk-R5VAVVHP.js → chunk-72A4L5JJ.js} +2 -2
  117. package/dist/{chunk-X64YLC24.js → chunk-72VAXGEI.js} +5 -13
  118. package/dist/chunk-72VAXGEI.js.map +1 -0
  119. package/dist/{chunk-IKQTFQMI.js → chunk-755Q3DGF.js} +22 -3
  120. package/dist/chunk-755Q3DGF.js.map +1 -0
  121. package/dist/{chunk-D7FOKIY5.js → chunk-7AMFUATK.js} +12 -9
  122. package/dist/{chunk-D7FOKIY5.js.map → chunk-7AMFUATK.js.map} +1 -1
  123. package/dist/{chunk-BFVEEB7W.js → chunk-7ON2JW73.js} +57 -22
  124. package/dist/chunk-7ON2JW73.js.map +1 -0
  125. package/dist/chunk-7RNBVZZO.js +270 -0
  126. package/dist/chunk-7RNBVZZO.js.map +1 -0
  127. package/dist/{chunk-3FAMU5TX.js → chunk-A6USBZTO.js} +2 -2
  128. package/dist/{chunk-ZHIVCODT.js → chunk-A72SWTWW.js} +7 -7
  129. package/dist/{chunk-FC77VUX5.js → chunk-A7Q43EUZ.js} +2 -2
  130. package/dist/{chunk-UJBESW6X.js → chunk-AE7WMV4V.js} +7 -7
  131. package/dist/{chunk-J2HSAU72.js → chunk-AIK5W3IW.js} +29 -1
  132. package/dist/chunk-AIK5W3IW.js.map +1 -0
  133. package/dist/{chunk-A5UXZRRM.js → chunk-AJ7QCSIS.js} +2 -2
  134. package/dist/{chunk-FNMFJWBY.js → chunk-ANEUPF6O.js} +5 -5
  135. package/dist/chunk-AREGMX2J.js +50 -0
  136. package/dist/chunk-AREGMX2J.js.map +1 -0
  137. package/dist/chunk-AVPXXV6J.js +448 -0
  138. package/dist/chunk-AVPXXV6J.js.map +1 -0
  139. package/dist/{chunk-2A3OXAP2.js → chunk-B7RWBZXW.js} +2 -2
  140. package/dist/{chunk-QKQYXZVS.js → chunk-BI2OJF6J.js} +1819 -1481
  141. package/dist/chunk-BI2OJF6J.js.map +1 -0
  142. package/dist/{chunk-GWTFLF2P.js → chunk-BJMBJZ2Y.js} +59 -59
  143. package/dist/chunk-BJMBJZ2Y.js.map +1 -0
  144. package/dist/{chunk-74F5STS4.js → chunk-BLAKS3CP.js} +4 -4
  145. package/dist/{chunk-M7VGG3ID.js → chunk-BV5WMSIJ.js} +9 -9
  146. package/dist/{chunk-2BFLDH5F.js → chunk-BXLOS5AJ.js} +2 -2
  147. package/dist/{chunk-UXKMMNJD.js → chunk-C23BYTJV.js} +6 -6
  148. package/dist/{chunk-JZHHREBL.js → chunk-C3AKM55W.js} +2 -2
  149. package/dist/{chunk-RP7YXA67.js → chunk-C5JF6EZ7.js} +2 -2
  150. package/dist/{chunk-T7Y5KPLN.js → chunk-C6XBRYVD.js} +16 -15
  151. package/dist/chunk-C6XBRYVD.js.map +1 -0
  152. package/dist/{chunk-FTYDWKO6.js → chunk-CEN6DW6X.js} +12 -2
  153. package/dist/chunk-CEN6DW6X.js.map +1 -0
  154. package/dist/chunk-CGASUJVP.js +421 -0
  155. package/dist/chunk-CGASUJVP.js.map +1 -0
  156. package/dist/{chunk-EHCONI6E.js → chunk-CQMEM5CC.js} +2 -2
  157. package/dist/{chunk-PBNZVPFS.js → chunk-CXZQOVIE.js} +12 -12
  158. package/dist/chunk-D3V3UMET.js +44 -0
  159. package/dist/chunk-D3V3UMET.js.map +1 -0
  160. package/dist/{chunk-7N2RUBAP.js → chunk-DDA47TES.js} +2 -2
  161. package/dist/{chunk-64SE4X5G.js → chunk-DEBHXHJR.js} +3 -3
  162. package/dist/{chunk-EHK6KZHK.js → chunk-DNHVPZOD.js} +2 -2
  163. package/dist/{chunk-437S3G37.js → chunk-DQEMWVMT.js} +2 -2
  164. package/dist/{chunk-LZZNTPLR.js → chunk-DX3XRGLH.js} +2 -2
  165. package/dist/chunk-EA2H5LML.js +72 -0
  166. package/dist/chunk-EA2H5LML.js.map +1 -0
  167. package/dist/{chunk-INELTPRG.js → chunk-EEC7UJPX.js} +103 -106
  168. package/dist/chunk-EEC7UJPX.js.map +1 -0
  169. package/dist/{chunk-KSNVDPDF.js → chunk-EKBNDKDY.js} +21 -20
  170. package/dist/chunk-EKBNDKDY.js.map +1 -0
  171. package/dist/{chunk-YF6FMLBT.js → chunk-EQWEIIKQ.js} +64 -34
  172. package/dist/chunk-EQWEIIKQ.js.map +1 -0
  173. package/dist/{chunk-DZKHSDOM.js → chunk-ES36HTSC.js} +4 -4
  174. package/dist/{chunk-TN7THW5U.js → chunk-ET356KSB.js} +2 -2
  175. package/dist/{chunk-YNDLCWXS.js → chunk-EZ25VE3G.js} +4 -4
  176. package/dist/{chunk-DMSDUGDM.js → chunk-F7GAIWFA.js} +20 -20
  177. package/dist/{chunk-G6XXLKC5.js → chunk-FFPJINJE.js} +6 -6
  178. package/dist/chunk-FMLKOL2Z.js +636 -0
  179. package/dist/chunk-FMLKOL2Z.js.map +1 -0
  180. package/dist/chunk-FQC3DHH2.js +20 -0
  181. package/dist/chunk-FQC3DHH2.js.map +1 -0
  182. package/dist/{chunk-G4CN3ZXL.js → chunk-FUTF72MJ.js} +15 -15
  183. package/dist/chunk-GCASGYIO.js +71 -0
  184. package/dist/chunk-GCASGYIO.js.map +1 -0
  185. package/dist/{chunk-HF77M34J.js → chunk-GFPZS3F5.js} +8 -8
  186. package/dist/{chunk-BCDKBDSY.js → chunk-GNVZQ5JN.js} +99 -41
  187. package/dist/chunk-GNVZQ5JN.js.map +1 -0
  188. package/dist/{chunk-G6NKALRN.js → chunk-H4WG3UQZ.js} +2 -2
  189. package/dist/{chunk-UDQUSU27.js → chunk-HNZKVLAN.js} +2 -2
  190. package/dist/{chunk-5EZXHU36.js → chunk-HYQJQGD3.js} +2 -2
  191. package/dist/{chunk-PLQE6MJA.js → chunk-IFH6LWTO.js} +50 -8
  192. package/dist/chunk-IFH6LWTO.js.map +1 -0
  193. package/dist/{chunk-RULE4VG5.js → chunk-ILGC6JH6.js} +21 -6
  194. package/dist/chunk-ILGC6JH6.js.map +1 -0
  195. package/dist/chunk-IUM3VSHI.js +113 -0
  196. package/dist/chunk-IUM3VSHI.js.map +1 -0
  197. package/dist/{chunk-TRWPCR6P.js → chunk-JECBQBEX.js} +3 -3
  198. package/dist/{chunk-E6CBU7XP.js → chunk-JYIFGGEM.js} +2 -2
  199. package/dist/{chunk-VA4WSW54.js → chunk-JYIJNNN3.js} +3 -3
  200. package/dist/{chunk-L5HJQC36.js → chunk-K2TDK7GG.js} +3 -3
  201. package/dist/{chunk-KDXVOFYY.js → chunk-KAVBJSBQ.js} +4 -4
  202. package/dist/{chunk-BS4SGLWV.js → chunk-KF5EUVKQ.js} +16 -6
  203. package/dist/chunk-KF5EUVKQ.js.map +1 -0
  204. package/dist/chunk-KFZY2OFH.js +42 -0
  205. package/dist/chunk-KFZY2OFH.js.map +1 -0
  206. package/dist/{chunk-4OKLXWDZ.js → chunk-KNB7IBBU.js} +2 -2
  207. package/dist/{chunk-QLULYKWZ.js → chunk-KSXJOC4F.js} +2 -2
  208. package/dist/{chunk-2S6QHZGJ.js → chunk-L2DPF4DF.js} +1 -1
  209. package/dist/{chunk-JI5AVXYO.js → chunk-LEPOP46W.js} +6 -6
  210. package/dist/{chunk-O7BBFJLP.js → chunk-LTAVSOZW.js} +2 -2
  211. package/dist/{chunk-E3VODCC3.js → chunk-LUDXM7MD.js} +14 -2
  212. package/dist/{chunk-E3VODCC3.js.map → chunk-LUDXM7MD.js.map} +1 -1
  213. package/dist/{chunk-2IZAGAJR.js → chunk-LULR4IUW.js} +3 -3
  214. package/dist/{chunk-QQGPUKMT.js → chunk-MC5Q3J7S.js} +398 -7
  215. package/dist/chunk-MC5Q3J7S.js.map +1 -0
  216. package/dist/{chunk-WMWVO45V.js → chunk-MC6XO7T4.js} +2 -2
  217. package/dist/chunk-MKQBXQKU.js +107 -0
  218. package/dist/chunk-MKQBXQKU.js.map +1 -0
  219. package/dist/{chunk-7PND4PUC.js → chunk-MMGGVZ4Q.js} +29 -9
  220. package/dist/{chunk-7PND4PUC.js.map → chunk-MMGGVZ4Q.js.map} +1 -1
  221. package/dist/{chunk-D6RIFG4O.js → chunk-MNB5RMAY.js} +2 -2
  222. package/dist/{chunk-Q5WG43OP.js → chunk-MYFQ3ED4.js} +7 -7
  223. package/dist/{chunk-V3UE5I5F.js → chunk-MYVPLJOO.js} +2 -2
  224. package/dist/chunk-NINSR6LX.js +83 -0
  225. package/dist/chunk-NINSR6LX.js.map +1 -0
  226. package/dist/{chunk-MTWKDOVO.js → chunk-NLE6TSLG.js} +2 -2
  227. package/dist/{chunk-OAZVR2BV.js → chunk-OGCAYLNA.js} +8 -6
  228. package/dist/{chunk-OAZVR2BV.js.map → chunk-OGCAYLNA.js.map} +1 -1
  229. package/dist/{chunk-DBRYEIGY.js → chunk-OJP3N7UK.js} +2 -2
  230. package/dist/{chunk-VDW4VU7B.js → chunk-OQJIB32H.js} +28 -23
  231. package/dist/chunk-OQJIB32H.js.map +1 -0
  232. package/dist/{chunk-SMX5267P.js → chunk-OZKOPQCM.js} +2 -2
  233. package/dist/{chunk-JCK7V6SN.js → chunk-P65YJEEL.js} +2 -2
  234. package/dist/{chunk-MTR7BZQN.js → chunk-PBGWYM3H.js} +3 -3
  235. package/dist/chunk-PIG4WJFQ.js +87 -0
  236. package/dist/chunk-PIG4WJFQ.js.map +1 -0
  237. package/dist/chunk-PJSK6OJM.js +201 -0
  238. package/dist/chunk-PJSK6OJM.js.map +1 -0
  239. package/dist/{chunk-OVJ2HIPE.js → chunk-PMUD7ERF.js} +158 -125
  240. package/dist/chunk-PMUD7ERF.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-SK7AMF2J.js +168 -0
  263. package/dist/chunk-SK7AMF2J.js.map +1 -0
  264. package/dist/{chunk-KSBEEMQF.js → chunk-TG6IHVE2.js} +151 -6
  265. package/dist/chunk-TG6IHVE2.js.map +1 -0
  266. package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
  267. package/dist/{chunk-DPAENM7O.js → chunk-U3ZAVRP3.js} +2 -2
  268. package/dist/{chunk-ODPLEWB6.js → chunk-UFGFMWAD.js} +47 -17
  269. package/dist/chunk-UFGFMWAD.js.map +1 -0
  270. package/dist/{chunk-4KJLYTLS.js → chunk-V57NLO5P.js} +2 -2
  271. package/dist/{chunk-FLVL4L3L.js → chunk-VDX2J7OX.js} +2 -2
  272. package/dist/{chunk-AJLLIIML.js → chunk-W4FBGYGK.js} +1 -1
  273. package/dist/{chunk-TXLGHDHS.js → chunk-W4XJFLAL.js} +53 -32
  274. package/dist/chunk-W4XJFLAL.js.map +1 -0
  275. package/dist/{chunk-6SXVCD7W.js → chunk-W7IGLX4G.js} +2 -2
  276. package/dist/{chunk-KQDNAXOM.js → chunk-WG5HSQ4P.js} +19 -6
  277. package/dist/chunk-WG5HSQ4P.js.map +1 -0
  278. package/dist/{chunk-LTJAMRGI.js → chunk-WL5EBRDH.js} +17 -3
  279. package/dist/chunk-WL5EBRDH.js.map +1 -0
  280. package/dist/{chunk-KAWTOYAW.js → chunk-WLZYGLJ4.js} +2 -2
  281. package/dist/{chunk-RO4LQGT3.js → chunk-WON4APQY.js} +4 -4
  282. package/dist/{chunk-PQVK2S3J.js → chunk-WZFAPHIK.js} +6 -6
  283. package/dist/{chunk-KQPJLK3X.js → chunk-XL24QQ63.js} +2 -2
  284. package/dist/{chunk-LZOV7MX7.js → chunk-XQDRKZ7V.js} +6476 -5747
  285. package/dist/chunk-XQDRKZ7V.js.map +1 -0
  286. package/dist/{chunk-RVZRYUQH.js → chunk-YROFNEG5.js} +7 -7
  287. package/dist/{chunk-RAR2BSEM.js → chunk-YV32N67O.js} +1 -1
  288. package/dist/chunk-YV32N67O.js.map +1 -0
  289. package/dist/{chunk-PBSAPHHA.js → chunk-YVKF3HEW.js} +1 -1
  290. package/dist/chunk-YVKF3HEW.js.map +1 -0
  291. package/dist/{chunk-VRAD2FGO.js → chunk-Z54EM5YZ.js} +12 -12
  292. package/dist/{chunk-2VN4JAX7.js → chunk-ZOKZIR5K.js} +95 -33
  293. package/dist/chunk-ZOKZIR5K.js.map +1 -0
  294. package/dist/{chunk-DCFV7A7H.js → chunk-ZVAYK7GU.js} +101 -91
  295. package/dist/chunk-ZVAYK7GU.js.map +1 -0
  296. package/dist/{cli-Cd5fMmhq.d.ts → cli-5tNLVTvJ.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 +94 -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 +172 -0
  617. package/src/access-observe-write-surface.ts +137 -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 +186 -179
  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 +245 -0
  781. package/src/write-quarantine.ts +290 -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
@@ -0,0 +1,773 @@
1
+ /**
2
+ * Per-principal recall concurrency + single-flight coalescing (issue #1906).
3
+ *
4
+ * Extracted from access-service.ts (structural ratchet #1520/#1995): the
5
+ * machinery that replaced the former width-1 `withBudgetLock` recall
6
+ * serialization with a per-principal concurrency semaphore plus query-level
7
+ * single-flight coalescing and atomic cross-namespace budget admission.
8
+ *
9
+ * These are free functions taking a {@link RecallCoordinatorHost} (the
10
+ * EngramAccessService instance) rather than methods, so the per-instance
11
+ * semaphore/flight state and budget/idempotency/execute dependencies stay on
12
+ * the service while the ~600 lines of coalescing logic live in their own
13
+ * module. `raceAbort` and `attachFlightAbort` need no host (they operate on the
14
+ * caller signal / flight object alone).
15
+ */
16
+ import { abortError, throwIfAborted } from "./abort-error.js";
17
+ import { hashAccessIdempotencyPayload } from "./access-idempotency.js";
18
+ import {
19
+ EngramAccessInputError,
20
+ type EngramAccessRecallRequest,
21
+ type EngramAccessRecallResponse,
22
+ } from "./access-service.js";
23
+ import {
24
+ type BudgetDecision,
25
+ type BudgetReservation,
26
+ type CrossNamespaceBudget,
27
+ toBudgetWarning,
28
+ } from "./cross-namespace-budget.js";
29
+
30
+ /**
31
+ * Per-principal recall concurrency slot (issue #1906). `active` counts
32
+ * in-flight recalls holding a permit; `waiters` is the FIFO queue of callers
33
+ * blocked on a permit. Process-local (per AGENTS.md multi-instance reality);
34
+ * entries self-delete when idle so the map never grows unbounded.
35
+ */
36
+ interface PrincipalSemaphore {
37
+ active: number;
38
+ waiters: Array<{ take: () => void; drop: () => void }>;
39
+ }
40
+
41
+ /** Result of one coalesced recall pipeline (issue #1906). */
42
+ export type RecallExecResult = {
43
+ response: EngramAccessRecallResponse;
44
+ budgetRecordPrincipal: string | null;
45
+ /** The pipeline's own atomic budget reservation token, so a consumer that
46
+ * fails AFTER the pipeline (response clone, idempotency put) can release
47
+ * the exact entry (#1906 review round 3). */
48
+ reservation?: BudgetReservation;
49
+ };
50
+
51
+ /**
52
+ * A shared single-flight recall execution (issue #1906 review). Identical
53
+ * concurrent recalls for one principal coalesce onto one `promise`. The flight
54
+ * owns its OWN AbortController so a single caller disconnecting never cancels
55
+ * the shared pipeline; `live` refcounts attached callers and the controller is
56
+ * aborted only when EVERY attached caller has aborted.
57
+ */
58
+ interface RecallFlight {
59
+ promise: Promise<RecallExecResult>;
60
+ controller: AbortController;
61
+ live: number;
62
+ /** Set true the instant the shared pipeline acquires its concurrency slot and
63
+ * begins executing. Before this, a KEYED flight whose only caller aborts must
64
+ * cancel (nothing has committed); after it, a keyed flight must persist
65
+ * regardless of caller disconnects (round 5 #1). Unkeyed flights ignore it —
66
+ * they carry no `persisted` gate and cancel whenever every caller leaves
67
+ * (round 14 #3). */
68
+ committed: boolean;
69
+ /** Called when the flight goes idle (no attached callers remain). Used to
70
+ * unregister the flight from `recallInFlight` only AFTER its consumers have
71
+ * finished — never on raw pipeline settle — so an identical arrival while a
72
+ * consumer is still finishing (e.g. a slow put) still coalesces (round 6 #1). */
73
+ onIdle?: () => void;
74
+ /** For KEYED flights only: settles when the leader's idempotency persistence
75
+ * (idempotency.put) completes — resolves on success, rejects with the put
76
+ * error on failure. The leader's consumeFlight detaches BEFORE its put runs,
77
+ * so `onIdle` awaits this gate before unregistering the flight — keeping it
78
+ * discoverable through the persistence window so an identical arrival during a
79
+ * slow put still coalesces instead of starting a second pipeline (round 12 #2,
80
+ * originally the round-7 #1 follower gate). */
81
+ persisted?: {
82
+ promise: Promise<void>;
83
+ resolve: () => void;
84
+ reject: (reason: unknown) => void;
85
+ };
86
+ }
87
+
88
+ /**
89
+ * The EngramAccessService surface these coordinator functions read/mutate. The
90
+ * service passes `this` (via an unknown cast at the single call site) so the
91
+ * per-instance state and dependencies stay owned by the service.
92
+ */
93
+ export interface RecallCoordinatorHost {
94
+ readonly recallSemaphores: Map<string, PrincipalSemaphore>;
95
+ readonly recallInFlight: Map<string, RecallFlight>;
96
+ readonly budget: Pick<CrossNamespaceBudget, "record" | "release">;
97
+ readonly orchestrator: { readonly config: { readonly recallMaxConcurrentPerPrincipal: number } };
98
+ executeRecall(request: EngramAccessRecallRequest): Promise<RecallExecResult>;
99
+ handleIdempotentRead<T>(options: {
100
+ operation: string;
101
+ idempotencyKey?: string;
102
+ requestFingerprint: unknown;
103
+ execute: () => Promise<T>;
104
+ afterStore?: (response: T) => Promise<void> | void;
105
+ }): Promise<T>;
106
+ }
107
+
108
+ /**
109
+ * Acquire a recall slot for `key` (issue #1906). Resolves with a release
110
+ * fn; rejects with an AbortError if `signal` fires while queued. A `limit`
111
+ * of `0` (or any non-positive/non-finite value, which cannot occur after
112
+ * config parse) means "unlimited". Waiters are served FIFO; an aborted
113
+ * waiter leaves the queue immediately and never holds a permit. Empty
114
+ * entries self-delete so the map never grows unbounded (the 2026-07-10
115
+ * unbounded-state-file lesson: every structure has a delete path).
116
+ */
117
+ function acquireRecallSlot(
118
+ host: RecallCoordinatorHost,
119
+ key: string,
120
+ limit: number,
121
+ signal?: AbortSignal,
122
+ ): Promise<{ release: () => void; waitedMs: number }> {
123
+ const cap = Number.isFinite(limit) && limit > 0 ? limit : Infinity;
124
+ const sem = host.recallSemaphores.get(key) ?? { active: 0, waiters: [] };
125
+ host.recallSemaphores.set(key, sem);
126
+ const release = () => {
127
+ sem.active--;
128
+ const next = sem.waiters.shift();
129
+ if (next) {
130
+ sem.active++;
131
+ next.take();
132
+ }
133
+ if (sem.active === 0 && sem.waiters.length === 0) {
134
+ host.recallSemaphores.delete(key);
135
+ }
136
+ };
137
+ if (sem.active < cap) {
138
+ // Slot free — acquired immediately, NO queue wait. (Measuring wall-clock
139
+ // here would count event-loop scheduling jitter under load and wrongly
140
+ // report a positive queueWaitMs for an uncontended recall.)
141
+ sem.active++;
142
+ return Promise.resolve({ release, waitedMs: 0 });
143
+ }
144
+ // Contended — measure the real time spent blocked for a slot.
145
+ const startedWaiting = Date.now();
146
+ return new Promise<{ release: () => void; waitedMs: number }>((resolve, reject) => {
147
+ const waiter = {
148
+ take: () => {
149
+ signal?.removeEventListener("abort", waiter.drop);
150
+ resolve({ release, waitedMs: Date.now() - startedWaiting });
151
+ },
152
+ drop: () => {
153
+ const i = sem.waiters.indexOf(waiter);
154
+ if (i >= 0) sem.waiters.splice(i, 1);
155
+ if (sem.active === 0 && sem.waiters.length === 0) {
156
+ host.recallSemaphores.delete(key);
157
+ }
158
+ reject(abortError("operation aborted"));
159
+ },
160
+ };
161
+ if (signal?.aborted) {
162
+ waiter.drop();
163
+ return;
164
+ }
165
+ signal?.addEventListener("abort", waiter.drop, { once: true });
166
+ sem.waiters.push(waiter);
167
+ });
168
+ }
169
+
170
+ /**
171
+ * Runs `fn` under a per-principal recall slot, passing the measured queue
172
+ * wait (ms) — 0 for an uncontended acquire, the real blocked time when the
173
+ * cap was reached — so it can be folded additively into recall-timings.
174
+ * Replaces the former width-1 `withBudgetLock` FIFO serialization (issue
175
+ * #1906): budget accounting stays correct because peek/record are synchronous
176
+ * (see cross-namespace-budget.ts). Release always runs in `finally`.
177
+ */
178
+ export async function withRecallConcurrency<T>(
179
+ host: RecallCoordinatorHost,
180
+ principal: string,
181
+ signal: AbortSignal | undefined,
182
+ fn: (queueWaitMs: number) => Promise<T>,
183
+ ): Promise<T> {
184
+ const key = principal || "__anonymous__";
185
+ const limit = host.orchestrator.config.recallMaxConcurrentPerPrincipal;
186
+ throwIfAborted(signal);
187
+ const { release, waitedMs } = await acquireRecallSlot(host, key, limit, signal);
188
+ try {
189
+ // The signal may have fired while queued: `take()` already removed the
190
+ // abort listener when granting this slot, so re-check before entering `fn`.
191
+ // Without this, a caller (or flight controller) that aborted just after
192
+ // admission would still start the recall pipeline and reserve/run work
193
+ // until a later rollback; the `finally` below releases the slot instead
194
+ // (round 14 #2).
195
+ throwIfAborted(signal);
196
+ return await fn(waitedMs);
197
+ } finally {
198
+ release();
199
+ }
200
+ }
201
+
202
+ /**
203
+ * Race `p` against `signal` (issue #1906). A single-flight caller waits on
204
+ * the shared flight promise but must be able to leave on its own abort. The
205
+ * abort listener is removed as soon as the race settles (either `p` won or
206
+ * the abort fired) so a settled-first promise never leaks a listener on a
207
+ * long-lived signal.
208
+ *
209
+ * Pre-check the signal BEFORE building the race: an already-aborted signal
210
+ * must win even when `p` is already fulfilled. `Promise.race` settles from
211
+ * already-resolved members in array order, so a fulfilled `p` (index 0) would
212
+ * otherwise beat the synchronously-rejected abort racer (index 1) and let an
213
+ * aborted caller proceed into its own persistence + budget accounting before
214
+ * the next abort check runs (round 15 #1).
215
+ */
216
+ export function raceAbort<T>(p: Promise<T>, signal?: AbortSignal): Promise<T> {
217
+ if (!signal) return p;
218
+ if (signal.aborted) return Promise.reject(abortError("operation aborted"));
219
+ let onAbort: (() => void) | undefined;
220
+ const racer = new Promise<never>((_resolve, reject) => {
221
+ onAbort = () => reject(abortError("operation aborted"));
222
+ signal.addEventListener("abort", onAbort, { once: true });
223
+ });
224
+ return Promise.race([p, racer]).finally(() => {
225
+ if (onAbort) signal.removeEventListener("abort", onAbort);
226
+ });
227
+ }
228
+
229
+ /**
230
+ * Attach a caller to a single-flight recall (issue #1906 review). Increments
231
+ * the flight refcount and (when `cancelOnAbort`) wires the caller's abort so
232
+ * the SHARED pipeline is cancelled when every attached caller has aborted —
233
+ * EXCEPT a KEYED flight that has already committed to execution, which must
234
+ * persist regardless of caller disconnects (round 5 #1). A caller attached
235
+ * with `cancelOnAbort=false` still holds a refcount slot (keeping the flight
236
+ * alive) but never cancels it. Returns a `detach` to call when the caller
237
+ * settles.
238
+ */
239
+ function attachFlightAbort(
240
+ flight: RecallFlight,
241
+ signal: AbortSignal | undefined,
242
+ cancelOnAbort: boolean,
243
+ ): () => void {
244
+ flight.live += 1;
245
+ let settled = false;
246
+ const onAbort = () => {
247
+ if (settled) return;
248
+ settled = true;
249
+ flight.live -= 1;
250
+ if (flight.live === 0) {
251
+ // A KEYED flight that already began executing must persist even though
252
+ // its last caller left (round 5 #1); cancel only a flight that has not
253
+ // committed (still queued for a slot) or has nothing to persist —
254
+ // unkeyed, no `persisted` gate (round 14 #3).
255
+ if (!flight.persisted || !flight.committed) flight.controller.abort();
256
+ flight.onIdle?.();
257
+ }
258
+ };
259
+ if (cancelOnAbort && signal) {
260
+ if (signal.aborted) {
261
+ onAbort();
262
+ } else {
263
+ signal.addEventListener("abort", onAbort, { once: true });
264
+ }
265
+ }
266
+ return () => {
267
+ if (settled) return;
268
+ settled = true;
269
+ flight.live -= 1;
270
+ if (cancelOnAbort && signal) signal.removeEventListener("abort", onAbort);
271
+ // Unregister only once the LAST consumer finishes, so a joiner arriving
272
+ // while a consumer is still settling (slow put / hooked consume) still
273
+ // coalesces onto the shared result (round 6 #1).
274
+ if (flight.live === 0) flight.onIdle?.();
275
+ };
276
+ }
277
+
278
+ /** Consume a shared recall flight for one caller (issue #1906 review). When
279
+ * `race` is true the caller leaves early on its own abort; when false (a
280
+ * committed idempotency-keyed leader) it awaits the flight to completion so
281
+ * persistence survives its disconnect (round 5 #1). `cancelOnAbort` (default
282
+ * `race`) decides whether this caller's abort counts toward cancelling the
283
+ * shared pipeline: a keyed leader awaits the flight (race=false) yet still
284
+ * wires its abort so that, while the flight is only QUEUED and no other caller
285
+ * is attached, its disconnect cancels the not-yet-committed pipeline (round
286
+ * 14 #3). Records this caller's OWN cross-namespace budget event (coalesced
287
+ * callers), clones the response inside the rollback scope, and returns the
288
+ * reservation this caller owns so an outer failure can release the exact
289
+ * entry. If the caller leaves before observing the result, the pipeline
290
+ * reservation it owns is released once the flight resolves so a cancelled
291
+ * recall never leaks quota (round 5 #2). */
292
+ export async function consumeFlight(
293
+ host: RecallCoordinatorHost,
294
+ flight: RecallFlight,
295
+ request: EngramAccessRecallRequest,
296
+ recordBudget: boolean,
297
+ race: boolean,
298
+ cancelOnAbort: boolean = race,
299
+ ): Promise<{ response: EngramAccessRecallResponse; reservation: BudgetReservation | undefined }> {
300
+ const detach = attachFlightAbort(flight, request.abortSignal, cancelOnAbort);
301
+ try {
302
+ let result: RecallExecResult;
303
+ try {
304
+ result = race
305
+ ? await raceAbort(flight.promise, request.abortSignal)
306
+ : await flight.promise;
307
+ } catch (err) {
308
+ // This caller left before observing the result. If it OWNS the
309
+ // pipeline's reservation (recordBudget=false) and the flight still
310
+ // resolves with one, release it so a cancelled recall does not leak
311
+ // quota (round 5 #2). A rejected flight already rolled back inside
312
+ // executeRecall, so the resolve handler simply never fires.
313
+ if (!recordBudget) {
314
+ flight.promise.then(
315
+ (settled) => {
316
+ if (settled.reservation) host.budget.release(settled.reservation);
317
+ },
318
+ () => {},
319
+ );
320
+ }
321
+ throw err;
322
+ }
323
+ // A committed (race=false) caller applies its own abort later (after
324
+ // persistence); a racing caller re-checks here. If the abort landed in the
325
+ // gap AFTER the result resolved, release the pipeline reservation this
326
+ // caller owns (recordBudget=false) rather than leak it (round 6 #2).
327
+ if (race && request.abortSignal?.aborted) {
328
+ if (!recordBudget && result.reservation) {
329
+ host.budget.release(result.reservation);
330
+ }
331
+ throwIfAborted(request.abortSignal);
332
+ }
333
+ // A caller that ran the pipeline inherits its reservation token; a
334
+ // coalesced caller records its OWN cross-namespace event below.
335
+ let reservation = recordBudget ? undefined : result.reservation;
336
+ let ownDecision: BudgetDecision | undefined;
337
+ if (recordBudget && result.budgetRecordPrincipal) {
338
+ const decision = host.budget.record(result.budgetRecordPrincipal);
339
+ if (!decision.allowed) {
340
+ throw new EngramAccessInputError(
341
+ `recall denied: cross-namespace budget exceeded (${decision.count}/${decision.limit.hardLimit} in ${decision.limit.windowMs}ms window)`,
342
+ );
343
+ }
344
+ reservation = decision.reservation;
345
+ ownDecision = decision;
346
+ }
347
+ try {
348
+ const response = structuredClone(result.response);
349
+ if (ownDecision) {
350
+ // The clone carries the LEADER's budgetWarning; replace it with THIS
351
+ // coalesced caller's OWN soft-limit decision so the caller whose event
352
+ // actually crossed the soft limit sees its own warning (round 4 #2).
353
+ // `toBudgetWarning` strips the server-only `reservation` token so the
354
+ // principal id never reaches the response / cache (round 10 #2).
355
+ response.budgetWarning = toBudgetWarning(ownDecision);
356
+ }
357
+ return { response, reservation };
358
+ } catch (err) {
359
+ // Clone threw on a successful pipeline — release the admission entry
360
+ // rather than leak it (round 3 #1).
361
+ host.budget.release(reservation);
362
+ throw err;
363
+ }
364
+ } finally {
365
+ detach();
366
+ }
367
+ }
368
+
369
+ /** UNKEYED follower path (issue #1906 review): join an already-registered
370
+ * flight WITHOUT taking a concurrency slot. Only unkeyed callers reach here —
371
+ * keyed callers enter the idempotency guard first (round 12 #1) and coalesce
372
+ * via leadRecallFlight's existing-join instead. Mirrors the leaders' final
373
+ * post-consume abort guard: a caller that disconnected after its per-caller
374
+ * reservation was recorded but before delivery releases it rather than leaking
375
+ * quota (round 8 #1). */
376
+ async function followRecallFlight(
377
+ host: RecallCoordinatorHost,
378
+ flight: RecallFlight,
379
+ request: EngramAccessRecallRequest,
380
+ ): Promise<EngramAccessRecallResponse> {
381
+ const consumed = await consumeFlight(host, flight, request, true, true);
382
+ try {
383
+ throwIfAborted(request.abortSignal);
384
+ } catch (err) {
385
+ host.budget.release(consumed.reservation);
386
+ throw err;
387
+ }
388
+ return consumed.response;
389
+ }
390
+
391
+ /** Non-coalesced recall (single-flight disabled): per-request execution
392
+ * under a concurrency slot, the caller's own signal driving its pipeline. */
393
+ async function runRecallDirect(
394
+ host: RecallCoordinatorHost,
395
+ request: EngramAccessRecallRequest,
396
+ normalizedRequest: EngramAccessRecallRequest,
397
+ requestFingerprint: unknown,
398
+ queueWaitMs: number,
399
+ ): Promise<EngramAccessRecallResponse> {
400
+ let capturedReservation: BudgetReservation | undefined;
401
+ let response: EngramAccessRecallResponse;
402
+ try {
403
+ response = await host.handleIdempotentRead({
404
+ operation: "recall",
405
+ idempotencyKey: request.idempotencyKey,
406
+ requestFingerprint,
407
+ execute: async () => {
408
+ // Create + await the pipeline inside the closure so its rejection is
409
+ // observed immediately (no unhandled-rejection window across the
410
+ // idempotency-lock await). The caller's own signal drives this
411
+ // non-coalesced pipeline.
412
+ const exec = host.executeRecall({ ...normalizedRequest, queueWaitMs });
413
+ let result: RecallExecResult;
414
+ try {
415
+ result = await raceAbort(exec, request.abortSignal);
416
+ } catch (err) {
417
+ // Caller left (abort) before observing the result. If exec still
418
+ // resolves with a reservation, release it so the cancelled recall
419
+ // does not leak quota (round 5 #2). A rejected exec already rolled
420
+ // back inside executeRecall.
421
+ exec.then(
422
+ (settled) => {
423
+ if (settled.reservation) host.budget.release(settled.reservation);
424
+ },
425
+ () => {},
426
+ );
427
+ throw err;
428
+ }
429
+ let cloned: EngramAccessRecallResponse;
430
+ try {
431
+ cloned = structuredClone(result.response);
432
+ } catch (err) {
433
+ // Clone threw on a successful pipeline — release now (round 3 #1);
434
+ // leave capturedReservation unset so the outer catch is a no-op.
435
+ host.budget.release(result.reservation);
436
+ throw err;
437
+ }
438
+ // Clone succeeded — the outer catch owns rollback if a later step
439
+ // (idempotency put) fails (round 4 #1).
440
+ capturedReservation = result.reservation;
441
+ return cloned;
442
+ },
443
+ });
444
+ } catch (err) {
445
+ if (capturedReservation) host.budget.release(capturedReservation);
446
+ throw err;
447
+ }
448
+ try {
449
+ throwIfAborted(request.abortSignal);
450
+ } catch (err) {
451
+ // Abort landed after the result was produced but before delivery. For a
452
+ // NON-persisted (unkeyed) recall the completed result is discarded and
453
+ // will not be replayed, so release its reservation rather than leak quota
454
+ // (round 6 #2). A keyed recall persisted its result (a retry replays it),
455
+ // so its budget event legitimately stands (round 5 #1).
456
+ if (!request.idempotencyKey?.trim() && capturedReservation) {
457
+ host.budget.release(capturedReservation);
458
+ }
459
+ throw err;
460
+ }
461
+ return response;
462
+ }
463
+
464
+ /** Register a single-flight and start its ONE shared pipeline in the
465
+ * background (issue #1906 review). The pipeline runs under a concurrency
466
+ * slot tied to the FLIGHT'S own abort controller (#3) — so a caller
467
+ * disconnecting (even while the flight is still queued for a slot) never
468
+ * cancels it while other callers still want the result. The flight
469
+ * unregisters via `onIdle` when its LAST consumer finishes (round 6 #1) or
470
+ * when every caller has aborted (round 3 #2) — NOT on raw pipeline settle,
471
+ * so a joiner arriving while a consumer is still finishing still coalesces. */
472
+ export function createAndStartFlight(
473
+ host: RecallCoordinatorHost,
474
+ normalizedRequest: EngramAccessRecallRequest,
475
+ flightKey: string,
476
+ principalKey: string,
477
+ keyed: boolean,
478
+ ): RecallFlight {
479
+ const controller = new AbortController();
480
+ let settleExec!: (result: RecallExecResult) => void;
481
+ let failExec!: (reason: unknown) => void;
482
+ const flightPromise = new Promise<RecallExecResult>((resolve, reject) => {
483
+ settleExec = resolve;
484
+ failExec = reject;
485
+ });
486
+ // Consumers attach their own handlers; keep Node quiet if none do yet.
487
+ flightPromise.catch(() => {});
488
+ // KEYED flights carry a persistence gate that fast-path followers await so
489
+ // they never report success before the leader's idempotency.put settled
490
+ // (round 7 #1).
491
+ let persisted: RecallFlight["persisted"];
492
+ if (keyed) {
493
+ let resolvePersist!: () => void;
494
+ let rejectPersist!: (reason: unknown) => void;
495
+ const persistPromise = new Promise<void>((resolve, reject) => {
496
+ resolvePersist = resolve;
497
+ rejectPersist = reject;
498
+ });
499
+ persistPromise.catch(() => {});
500
+ persisted = { promise: persistPromise, resolve: resolvePersist, reject: rejectPersist };
501
+ }
502
+ const flight: RecallFlight = {
503
+ promise: flightPromise,
504
+ controller,
505
+ live: 0,
506
+ committed: false,
507
+ onIdle: () => {
508
+ const unregister = () => {
509
+ if (host.recallInFlight.get(flightKey) === flight) {
510
+ host.recallInFlight.delete(flightKey);
511
+ }
512
+ };
513
+ // A KEYED leader's consumeFlight detaches (live -> 0) BEFORE
514
+ // handleIdempotentRead runs idempotency.put, so unregistering on detach
515
+ // would drop the flight DURING the persistence window — an identical
516
+ // arrival then finds no flight and starts a second pipeline + reserve.
517
+ // Keep the flight discoverable until `persisted` settles so arrivals
518
+ // during a slow put still coalesce onto the one pipeline (round 12 #2).
519
+ // Unkeyed flights have no put: unregister immediately.
520
+ if (persisted) {
521
+ persisted.promise.then(unregister, unregister);
522
+ } else {
523
+ unregister();
524
+ }
525
+ },
526
+ ...(persisted ? { persisted } : {}),
527
+ };
528
+ host.recallInFlight.set(flightKey, flight);
529
+ withRecallConcurrency(host, principalKey, controller.signal, async (queueWaitMs) => {
530
+ // A slot was granted and the abort re-check in withRecallConcurrency passed
531
+ // — the pipeline is now committing to execution. Past this point a keyed
532
+ // flight persists even if its callers disconnect (round 5 #1); before it,
533
+ // attachFlightAbort cancels a keyed flight whose only caller aborts while
534
+ // still queued (round 14 #3).
535
+ flight.committed = true;
536
+ return host.executeRecall({
537
+ ...normalizedRequest,
538
+ abortSignal: controller.signal,
539
+ queueWaitMs,
540
+ });
541
+ }).then(settleExec, failExec);
542
+ return flight;
543
+ }
544
+
545
+ /** Leader path (issue #1906 review): consult the idempotency guard FIRST so an
546
+ * idempotent REPLAY returns the stored response WITHOUT starting a pipeline,
547
+ * flight, or budget reserve (#1/#2). On a miss, coalesce onto a LIVE
548
+ * race-registered flight if one exists, else start the one shared pipeline
549
+ * and consume it as the leader. A failure after the reserve (e.g. idempotency
550
+ * put) releases this caller's exact reservation (round 3 #3). */
551
+ export async function leadRecallFlight(
552
+ host: RecallCoordinatorHost,
553
+ request: EngramAccessRecallRequest,
554
+ normalizedRequest: EngramAccessRecallRequest,
555
+ requestFingerprint: unknown,
556
+ flightKey: string,
557
+ principalKey: string,
558
+ ): Promise<EngramAccessRecallResponse> {
559
+ const keyed = !!request.idempotencyKey?.trim();
560
+ let capturedReservation: BudgetReservation | undefined;
561
+ // The flight THIS call created (leader) and thus owns persistence for — used
562
+ // to settle its `persisted` gate so keyed fast-path followers learn the
563
+ // put outcome (round 7 #1).
564
+ let ownedFlight: RecallFlight | undefined;
565
+ let response: EngramAccessRecallResponse;
566
+ try {
567
+ response = await host.handleIdempotentRead({
568
+ operation: "recall",
569
+ idempotencyKey: request.idempotencyKey,
570
+ requestFingerprint,
571
+ execute: async () => {
572
+ // A keyed request commits (race=false): the leader awaits the flight
573
+ // to completion so idempotency.put persists even if the leader itself
574
+ // disconnects (round 5 #1). A non-keyed request races its own signal
575
+ // and may leave early (nothing to persist).
576
+ const race = !keyed;
577
+ const existing = host.recallInFlight.get(flightKey);
578
+ if (existing && !existing.controller.signal.aborted) {
579
+ // A LIVE identical flight registered between our fast-path miss and
580
+ // the idempotency guard — join it and record our own event. But a
581
+ // caller that already disconnected must NOT join: a keyed join is
582
+ // non-racing (race=false), so it would record its own cross-namespace
583
+ // budget event and run idempotency.put before the late abort check.
584
+ // Reject at admission instead; the existing flight continues for its
585
+ // other live consumers (round 10 #1).
586
+ throwIfAborted(request.abortSignal);
587
+ // `cancelOnAbort=true` (not the race=false default): a keyed
588
+ // existing-join follower is non-racing (it awaits the shared flight
589
+ // to completion), but its abort must still be COUNTED in the flight's
590
+ // live refcount while the flight is only QUEUED. Otherwise, at
591
+ // recallMaxConcurrentPerPrincipal=1, if the leader disconnects
592
+ // (live 2 -> 1) and this follower then disconnects, live would stay 1
593
+ // and the flight would execute + reserve + persist with no caller
594
+ // connected. Counting drops live to 0, and attachFlightAbort's
595
+ // committed guard (!persisted || !committed) cancels the queued flight
596
+ // while leaving a committed keyed flight to persist (round 15 #2).
597
+ const consumed = await consumeFlight(host, existing, request, true, race, true);
598
+ capturedReservation = consumed.reservation;
599
+ // A KEYED follower that coalesced onto the leader's flight must
600
+ // inherit the leader's persistence outcome before reporting success.
601
+ // The shared pipeline settling is NOT the leader's idempotency.put:
602
+ // the leader detaches (consumeFlight) BEFORE its put, so without this
603
+ // await a keyed follower could return success (and run its OWN
604
+ // idempotency.put), keeping its cross-namespace reservation, while the
605
+ // leader's put later FAILS — a phantom success that a same-key retry
606
+ // would then diverge from. Await the joined flight's `persisted` gate
607
+ // so a keyed join resolves only after the leader's put succeeds and
608
+ // REJECTS (releasing this caller's reservation via the outer catch,
609
+ // and skipping its own put) with the leader's exact error when the
610
+ // put fails — identical to the leader's put-failure behavior (round
611
+ // 13 #1). Race this persistence wait with the follower's OWN abort
612
+ // signal (round 14 #1/#4): a keyed follower whose HTTP/MCP client
613
+ // disconnects while the leader's put is still pending must receive
614
+ // its own AbortError PROMPTLY rather than block until the put settles
615
+ // (and, on put failure, get the store error instead of AbortError).
616
+ // The follower already detached from the flight inside consumeFlight
617
+ // (its non-racing await ran to the shared settle), so bailing here
618
+ // never decrements the leader's refcount or cancels its controller —
619
+ // the leader's persistence continues for the flight's other
620
+ // consumers. On abort the outer catch releases ONLY this follower's
621
+ // reservation. Unkeyed joins (race=true) keep existing behavior: they
622
+ // consumed the shared result and never depend on another caller's
623
+ // persistence, so they never block on `persisted`.
624
+ if (keyed) {
625
+ if (existing.persisted) {
626
+ await raceAbort(existing.persisted.promise, request.abortSignal);
627
+ } else {
628
+ // The joined flight was started by an UNKEYED leader, so it
629
+ // carries no `persisted` gate. The non-racing consume (race=false
630
+ // for a keyed caller) never observed this follower's abort, so a
631
+ // keyed follower that disconnected while the shared pipeline was
632
+ // still running would otherwise return success here and let
633
+ // handleIdempotentRead persist its key + keep its recorded
634
+ // cross-namespace budget event. Recheck the abort before
635
+ // returning so it rejects with AbortError instead: the outer
636
+ // catch releases this follower's reservation and execute()
637
+ // throwing skips its own idempotency.put — matching the
638
+ // keyed-follower-on-keyed-leader persistence path (round 16 #1).
639
+ throwIfAborted(request.abortSignal);
640
+ }
641
+ }
642
+ return consumed.response;
643
+ }
644
+ // No LIVE flight to join. If the caller already disconnected before we
645
+ // committed any work, reject at admission — creating the flight starts
646
+ // the pipeline (queue + execute + persist) and reserves a cross-namespace
647
+ // budget event. For a keyed leader `race` is false, so without this the
648
+ // caller would burn a full recall + budget event before the final
649
+ // post-consume abort check rejects, even though it left before admission
650
+ // and no follower is here to keep the flight alive. The old width-1
651
+ // budget lock rejected before starting work; preserve that (#1906 r9).
652
+ throwIfAborted(request.abortSignal);
653
+ const flight = createAndStartFlight(host, normalizedRequest, flightKey, principalKey, keyed);
654
+ ownedFlight = flight;
655
+ // The leader's own budget event is reserved inside the pipeline, so it
656
+ // must NOT record again here. `cancelOnAbort=true` even for a keyed
657
+ // leader (race=false): while the flight is only QUEUED for a slot and
658
+ // this is its sole caller, the leader's disconnect cancels the
659
+ // not-yet-committed pipeline (attachFlightAbort's committed guard keeps
660
+ // a post-commit keyed flight persisting, and any additional live caller
661
+ // keeps live > 0 so the shared flight survives) (round 14 #3).
662
+ const consumed = await consumeFlight(host, flight, request, false, race, true);
663
+ capturedReservation = consumed.reservation;
664
+ return consumed.response;
665
+ },
666
+ });
667
+ } catch (err) {
668
+ // A failure AFTER the caller reserved (idempotency put, or any post-
669
+ // execute step in handleIdempotentRead) releases the exact reservation.
670
+ // If execute() rejected before reserving — leader abort mid-pipeline, or
671
+ // a pipeline failure already rolled back inside executeRecall/consumeFlight
672
+ // — capturedReservation is undefined, so this is a no-op (round 3 #3).
673
+ if (capturedReservation) host.budget.release(capturedReservation);
674
+ // Tell keyed followers coalescing via the existing-join (they await this
675
+ // flight's `persisted` gate) that persistence failed so they behave
676
+ // identically to this leader (release + reject) — no phantom success
677
+ // (round 7 #1; keyed followers moved to the existing-join in round 12 #1).
678
+ ownedFlight?.persisted?.reject(err);
679
+ throw err;
680
+ }
681
+ // Leader persisted successfully — resolve the gate so keyed followers
682
+ // awaiting the put return success.
683
+ ownedFlight?.persisted?.resolve();
684
+ try {
685
+ throwIfAborted(request.abortSignal);
686
+ } catch (err) {
687
+ // Abort landed after consumption but before delivery. A NON-persisted
688
+ // (unkeyed) recall's completed result is discarded (no replay), so release
689
+ // its reservation rather than leak quota (round 6 #2); a keyed recall
690
+ // persisted its result, so its budget event legitimately stands (round 5 #1).
691
+ if (!keyed && capturedReservation) {
692
+ host.budget.release(capturedReservation);
693
+ }
694
+ throw err;
695
+ }
696
+ return response;
697
+ }
698
+
699
+ /**
700
+ * Top-level recall coordination (issue #1906): dispatch a validated recall to
701
+ * either the non-coalesced per-request path (single-flight disabled) or the
702
+ * single-flight leader/follower coalescing path. `singleFlight` is resolved by
703
+ * the caller through the shared access-setup capability projection so the
704
+ * config flag is read only in capabilities.ts (#1523 scattered-gate ratchet).
705
+ */
706
+ export function coordinateRecall(
707
+ host: RecallCoordinatorHost,
708
+ request: EngramAccessRecallRequest,
709
+ normalizedRequest: EngramAccessRecallRequest,
710
+ requestFingerprint: Omit<EngramAccessRecallRequest, "abortSignal">,
711
+ principalKey: string,
712
+ singleFlight: boolean,
713
+ ): Promise<EngramAccessRecallResponse> {
714
+ if (!singleFlight) {
715
+ // No coalescing: per-request execution under a concurrency slot.
716
+ return withRecallConcurrency(
717
+ host,
718
+ principalKey,
719
+ request.abortSignal,
720
+ (queueWaitMs) =>
721
+ runRecallDirect(host, request, normalizedRequest, requestFingerprint, queueWaitMs),
722
+ );
723
+ }
724
+
725
+ // The flight key represents the recall WORK — the query + options that shape
726
+ // the result — NOT the persistence key. `idempotencyKey` only selects an
727
+ // idempotency-store slot; it never changes the computed result. Excluding it
728
+ // lets identical recalls that arrive with DISTINCT per-request idempotency
729
+ // keys (a common transport-retry pattern) coalesce onto ONE pipeline + slot
730
+ // instead of each key spawning its own (round 11). Contract: EVERY keyed
731
+ // caller enters the idempotency guard first (round 12 #1) and persists the
732
+ // shared result under ITS OWN key, so a same-key retry always replays from
733
+ // the store; distinct keys on identical work still coalesce onto one pipeline.
734
+ const { idempotencyKey: _flightKeyOmitIdemKey, ...flightFingerprint } = requestFingerprint;
735
+ const flightKey = `${principalKey}\u0000${hashAccessIdempotencyPayload({
736
+ operation: "recall",
737
+ request: flightFingerprint,
738
+ })}`;
739
+ // UNKEYED follower fast-path (#1906 review #2): join an in-flight identical
740
+ // recall WITHOUT acquiring a concurrency slot. Because the leader registers
741
+ // its flight synchronously (below, before any await), every later identical
742
+ // arrival coalesces here — even when the concurrency cap is below the number
743
+ // of concurrent callers. Followers never wait for, or consume, a slot.
744
+ //
745
+ // KEYED callers must NOT take this fast-path: they enter the idempotency
746
+ // guard FIRST (leadRecallFlight -> handleIdempotentRead) so a stored response
747
+ // REPLAYS and a reused key with a different payload raises a CONFLICT, instead
748
+ // of silently joining the flight and skipping the store check (round 12 #1).
749
+ // On a store MISS a keyed caller still coalesces onto a live flight via
750
+ // leadRecallFlight's existing-join, then persists under its own key.
751
+ const keyed = !!request.idempotencyKey?.trim();
752
+ const existing = host.recallInFlight.get(flightKey);
753
+ // Skip a flight already cancelled (all its callers aborted) — it will
754
+ // reject with AbortError; lead a fresh flight instead (round 3 #2).
755
+ if (!keyed && existing && !existing.controller.signal.aborted) {
756
+ // A caller that already disconnected must NOT join a live flight: joining
757
+ // records its own cross-namespace budget event before the late abort check.
758
+ // Reject at admission; the existing flight continues for its other live
759
+ // consumers (round 10 #1).
760
+ throwIfAborted(request.abortSignal);
761
+ return followRecallFlight(host, existing, request);
762
+ }
763
+ // We are the leader: leadRecallFlight registers the flight synchronously in
764
+ // this same turn, then acquires a slot to run the one shared pipeline.
765
+ return leadRecallFlight(
766
+ host,
767
+ request,
768
+ normalizedRequest,
769
+ requestFingerprint,
770
+ flightKey,
771
+ principalKey,
772
+ );
773
+ }