@remnic/core 10.0.69 → 10.0.71

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 (412) hide show
  1. package/dist/access-admin-ops-surface.js +82 -79
  2. package/dist/access-authorization-probe.js +83 -80
  3. package/dist/access-boundary.js +82 -79
  4. package/dist/access-cli.js +196 -193
  5. package/dist/access-cli.js.map +1 -1
  6. package/dist/access-extraction-force-flush.js +82 -79
  7. package/dist/access-http-briefing.js +83 -80
  8. package/dist/access-http-query.js +84 -81
  9. package/dist/access-http.js +106 -103
  10. package/dist/access-identity-continuity-surface.js +82 -79
  11. package/dist/access-lcm-surface.js +82 -79
  12. package/dist/access-mcp.js +95 -92
  13. package/dist/access-namespace-preflight.js +82 -79
  14. package/dist/access-observe-lcm-archive.d.ts +5 -0
  15. package/dist/access-observe-lcm-archive.d.ts.map +1 -0
  16. package/dist/access-observe-lcm-archive.js +9 -0
  17. package/dist/access-observe-objective-state.d.ts +8 -0
  18. package/dist/access-observe-objective-state.d.ts.map +1 -0
  19. package/dist/access-observe-objective-state.js +17 -0
  20. package/dist/access-observe-stage-timing.d.ts +11 -0
  21. package/dist/access-observe-stage-timing.d.ts.map +1 -0
  22. package/dist/access-observe-stage-timing.js +9 -0
  23. package/dist/access-observe-stage-timing.js.map +1 -0
  24. package/dist/access-observe-write-category.js +13 -13
  25. package/dist/access-observe-write-surface.d.ts.map +1 -1
  26. package/dist/access-observe-write-surface.js +82 -79
  27. package/dist/access-offline-manifest.js +8 -8
  28. package/dist/access-operations-batch.js +85 -82
  29. package/dist/access-operations.js +92 -89
  30. package/dist/access-recall-concurrency.js +82 -79
  31. package/dist/access-recall-response.js +82 -79
  32. package/dist/access-recall-surface.js +82 -79
  33. package/dist/access-schema.js +12 -12
  34. package/dist/access-service.d.ts +1 -0
  35. package/dist/access-service.d.ts.map +1 -1
  36. package/dist/access-service.js +82 -79
  37. package/dist/access-surface-catalog.js +84 -81
  38. package/dist/access-surface-catalog.js.map +1 -1
  39. package/dist/active-recall.js +26 -26
  40. package/dist/adapters/index.js +4 -4
  41. package/dist/adapters/registry.js +2 -2
  42. package/dist/briefing.js +17 -17
  43. package/dist/buffer-turn-helpers.d.ts +10 -1
  44. package/dist/buffer-turn-helpers.d.ts.map +1 -1
  45. package/dist/buffer-turn-helpers.js +3 -1
  46. package/dist/buffer.d.ts +4 -0
  47. package/dist/buffer.d.ts.map +1 -1
  48. package/dist/buffer.js +9 -9
  49. package/dist/calibration.js +4 -4
  50. package/dist/{capsule-crypto-GWVG7LGC.js → capsule-crypto-7FJQINUR.js} +2 -2
  51. package/dist/capsule-crypto-7FJQINUR.js.map +1 -0
  52. package/dist/causal-behavior.js +2 -2
  53. package/dist/causal-chain.js +2 -2
  54. package/dist/causal-consolidation.js +22 -22
  55. package/dist/causal-retrieval.js +2 -2
  56. package/dist/causal-trajectory-graph.js +3 -3
  57. package/dist/causal-trajectory.js +1 -1
  58. package/dist/{chunk-6WKWL53V.js → chunk-23BA3USG.js} +128 -122
  59. package/dist/chunk-23BA3USG.js.map +1 -0
  60. package/dist/{chunk-OWHERGF2.js → chunk-2NLLXCJG.js} +2 -2
  61. package/dist/{chunk-CI3MAAIY.js → chunk-2R44BBPK.js} +2 -2
  62. package/dist/{chunk-QDZWQBLU.js → chunk-2R7OCBRR.js} +2 -2
  63. package/dist/{chunk-B3MWELZ3.js → chunk-2WPWEVAH.js} +2 -2
  64. package/dist/{chunk-PLCYKAWH.js → chunk-3ICAWZUU.js} +4 -4
  65. package/dist/{chunk-R4ZHF4K2.js → chunk-43FLJLT2.js} +4 -4
  66. package/dist/{chunk-PMDOGXA2.js → chunk-4PMFSYH7.js} +2 -2
  67. package/dist/{chunk-HXFIILGF.js → chunk-4RASUAN3.js} +4 -4
  68. package/dist/{chunk-EI6M5NVK.js → chunk-5JBVPJCT.js} +2 -2
  69. package/dist/{chunk-4NV7O76Q.js → chunk-5ORJHH43.js} +2 -2
  70. package/dist/{chunk-74AY3S7U.js → chunk-5RW247F5.js} +10 -10
  71. package/dist/{chunk-4XINO77L.js → chunk-66JOLMWS.js} +2 -2
  72. package/dist/{chunk-AYJQ644F.js → chunk-6KBCUIZP.js} +2 -2
  73. package/dist/{chunk-GKL6QYZO.js → chunk-6L63IN3M.js} +1 -1
  74. package/dist/{chunk-OPFVXM2D.js → chunk-7P5VBRBS.js} +2 -2
  75. package/dist/{chunk-4SOWMA55.js → chunk-7WFY2L5J.js} +3 -3
  76. package/dist/{chunk-GJ4HU6LK.js → chunk-AGRMXXVA.js} +2 -2
  77. package/dist/{chunk-KOLJJN5G.js → chunk-AQNHEDXP.js} +11 -4
  78. package/dist/chunk-AQNHEDXP.js.map +1 -0
  79. package/dist/{chunk-IVUVQPTQ.js → chunk-AZNE2H6D.js} +2 -2
  80. package/dist/{chunk-HPB5TF55.js → chunk-BCBY5GYZ.js} +3 -3
  81. package/dist/{chunk-M4IEZGCK.js → chunk-BFBS7OFQ.js} +7 -7
  82. package/dist/{chunk-4PG5R6BJ.js → chunk-BNU5TQLR.js} +2 -2
  83. package/dist/{chunk-TVE7W67N.js → chunk-BTU77RB5.js} +2 -2
  84. package/dist/{chunk-H6VJSITJ.js → chunk-CIL4GHMD.js} +3 -3
  85. package/dist/{chunk-KZZ5EZ7O.js → chunk-DC3DWF2M.js} +2 -2
  86. package/dist/{chunk-R2BIVU2Z.js → chunk-DE4U5PTV.js} +50 -46
  87. package/dist/chunk-DE4U5PTV.js.map +1 -0
  88. package/dist/{chunk-DDBB55L2.js → chunk-DSSTOV5M.js} +534 -361
  89. package/dist/chunk-DSSTOV5M.js.map +1 -0
  90. package/dist/{chunk-4MPAKYZU.js → chunk-EGKDONTC.js} +12 -6
  91. package/dist/chunk-EGKDONTC.js.map +1 -0
  92. package/dist/{chunk-AUFPPBC3.js → chunk-ENPJX3BB.js} +3 -3
  93. package/dist/{chunk-CTH2CQCB.js → chunk-EQ6EMJRG.js} +2 -2
  94. package/dist/{chunk-63A2BU2B.js → chunk-F4ZHKDBW.js} +5 -5
  95. package/dist/{chunk-3LBDEGQA.js → chunk-FDUCIUQ5.js} +2 -2
  96. package/dist/{chunk-OCK4D5PC.js → chunk-FGGLVCHI.js} +2 -2
  97. package/dist/{chunk-XVZA6VXC.js → chunk-FZVROZKC.js} +4 -4
  98. package/dist/{chunk-3RHU5MD7.js → chunk-GXAZ4Q2S.js} +2 -2
  99. package/dist/{chunk-UVVFPCPX.js → chunk-H2X32F2K.js} +2 -2
  100. package/dist/{chunk-645WOU5I.js → chunk-H7BZBSP6.js} +4 -4
  101. package/dist/{chunk-W7K5BP3M.js → chunk-HQPFACXO.js} +2 -2
  102. package/dist/{chunk-TECK5IVY.js → chunk-HZNURRDS.js} +2 -2
  103. package/dist/{chunk-U2CAGMUD.js → chunk-ICBUTKLL.js} +2 -2
  104. package/dist/{chunk-B4DXREWC.js → chunk-IQXQ3KWR.js} +2 -2
  105. package/dist/{chunk-AL3TCNSJ.js → chunk-J6GZ2254.js} +4 -4
  106. package/dist/{chunk-5MGKGEL7.js → chunk-J72ZY7NU.js} +2 -2
  107. package/dist/{chunk-OH55F76C.js → chunk-JEX2JL3U.js} +2 -2
  108. package/dist/{chunk-Y3XPSGNF.js → chunk-JGLZ46JS.js} +2 -2
  109. package/dist/{chunk-EXQJMFRF.js → chunk-JY4LXMZR.js} +2 -2
  110. package/dist/{chunk-6P7U3HWG.js → chunk-K36RMINQ.js} +3 -3
  111. package/dist/{chunk-BUKK5SWA.js → chunk-KQAFEZQX.js} +2 -2
  112. package/dist/{chunk-LN4X2NDA.js → chunk-KY3KJUNN.js} +10 -10
  113. package/dist/chunk-L3E7MLMK.js +20 -0
  114. package/dist/chunk-L3E7MLMK.js.map +1 -0
  115. package/dist/{chunk-H5DIRCZP.js → chunk-LHMCZ6VW.js} +18 -18
  116. package/dist/{chunk-GGD2YDS6.js → chunk-LN7CWLAU.js} +2 -2
  117. package/dist/{chunk-GHHQLSSY.js → chunk-LYOCAUI6.js} +3 -3
  118. package/dist/{chunk-VA3GNAWQ.js → chunk-LZIOY7ZU.js} +4 -5
  119. package/dist/chunk-LZIOY7ZU.js.map +1 -0
  120. package/dist/{chunk-W26D2USW.js → chunk-MUH7RR6T.js} +6 -6
  121. package/dist/{chunk-IAGVM7EY.js → chunk-N2Y6COEM.js} +2 -2
  122. package/dist/{chunk-64JLBFCQ.js → chunk-N7NAGECH.js} +2 -2
  123. package/dist/{chunk-5Y6VA6X2.js → chunk-OGQGDOYK.js} +2 -2
  124. package/dist/{chunk-U7MIMS2Y.js → chunk-OUBEJWVI.js} +17 -1
  125. package/dist/chunk-OUBEJWVI.js.map +1 -0
  126. package/dist/{chunk-JLMOH5JA.js → chunk-OWZXDBV4.js} +2 -2
  127. package/dist/{chunk-ZORS5BG5.js → chunk-PJAMFIDE.js} +10 -10
  128. package/dist/chunk-QCFZDYYG.js +34 -0
  129. package/dist/chunk-QCFZDYYG.js.map +1 -0
  130. package/dist/{chunk-SXTVZ6JL.js → chunk-QIOQI7QZ.js} +2 -2
  131. package/dist/{chunk-MMCO4SRG.js → chunk-QNN4FYBD.js} +19 -11
  132. package/dist/chunk-QNN4FYBD.js.map +1 -0
  133. package/dist/{chunk-75DCOS6I.js → chunk-QUPTDKSX.js} +67 -67
  134. package/dist/{chunk-HH73M65H.js → chunk-QVZZE6VH.js} +3 -3
  135. package/dist/{chunk-XWE3EOWX.js → chunk-RZED7FAU.js} +2 -2
  136. package/dist/{chunk-IZBIDPMY.js → chunk-S37O4S6E.js} +2 -2
  137. package/dist/{chunk-NHWDTOBN.js → chunk-S73ZVU37.js} +21 -21
  138. package/dist/{chunk-YSATDEBY.js → chunk-SBRUTD5O.js} +5 -5
  139. package/dist/{chunk-WVP2I6C5.js → chunk-SDL22RRW.js} +50 -11
  140. package/dist/chunk-SDL22RRW.js.map +1 -0
  141. package/dist/{chunk-PRKNAIGZ.js → chunk-T6T2RMWW.js} +5 -5
  142. package/dist/{chunk-CIEEYVUB.js → chunk-TPX7XXY4.js} +2 -2
  143. package/dist/{chunk-L334PSLW.js → chunk-U2A56LLF.js} +8 -8
  144. package/dist/{chunk-P4TV3TQ2.js → chunk-U6IL4724.js} +5 -5
  145. package/dist/{chunk-5UM4H64E.js → chunk-UAOJVQXC.js} +2 -2
  146. package/dist/{chunk-MOIJWWNA.js → chunk-UE5JYPU6.js} +13 -13
  147. package/dist/{chunk-TGQW3AMK.js → chunk-UIFWZMO7.js} +23 -23
  148. package/dist/{chunk-UW6LBFYN.js → chunk-USX5YIKB.js} +6 -6
  149. package/dist/{chunk-QGFR73SN.js → chunk-VK5HKVQ7.js} +2 -2
  150. package/dist/{chunk-ZOBYTRBU.js → chunk-VNTQU6KB.js} +47 -2
  151. package/dist/chunk-VNTQU6KB.js.map +1 -0
  152. package/dist/{chunk-IHCXMYSE.js → chunk-VPEIWMUT.js} +2 -2
  153. package/dist/{chunk-O5ZINWW3.js → chunk-VSJ3ARFS.js} +2 -2
  154. package/dist/{chunk-RLVI2M5Q.js → chunk-W4V7P5HP.js} +2 -2
  155. package/dist/{chunk-ELHJK7LM.js → chunk-WBN66HPI.js} +6 -6
  156. package/dist/{chunk-BJLCV2P3.js → chunk-WGRAB3KB.js} +2 -2
  157. package/dist/{chunk-5KDDAQ6K.js → chunk-WN2DASTS.js} +10 -10
  158. package/dist/{chunk-IG3EZ3TF.js → chunk-WNQ3B3Q5.js} +2 -2
  159. package/dist/{chunk-V6SBA5O7.js → chunk-WYOHQJKC.js} +7 -7
  160. package/dist/chunk-WZU5AGO6.js +38 -0
  161. package/dist/chunk-WZU5AGO6.js.map +1 -0
  162. package/dist/{chunk-WHROVQ5Q.js → chunk-X4DHAXFO.js} +3 -3
  163. package/dist/{chunk-UVYI6VIX.js → chunk-X7Y7WX73.js} +1 -1
  164. package/dist/{chunk-JLGBJ4AX.js → chunk-XPZM7GP6.js} +10 -10
  165. package/dist/{chunk-64S6X4IU.js → chunk-XTN54NML.js} +4 -4
  166. package/dist/{chunk-UYUFDTIX.js → chunk-YIXWY4OZ.js} +2 -2
  167. package/dist/{chunk-NCZGGGWI.js → chunk-YPYSC3TX.js} +12 -12
  168. package/dist/{chunk-AVGDYYMA.js → chunk-ZBET3W26.js} +3 -3
  169. package/dist/{chunk-Y7427SL7.js → chunk-ZG4GNPRE.js} +216 -50
  170. package/dist/chunk-ZG4GNPRE.js.map +1 -0
  171. package/dist/chunk-ZODKV27J.js +443 -0
  172. package/dist/chunk-ZODKV27J.js.map +1 -0
  173. package/dist/cli.js +133 -130
  174. package/dist/coding/export-okf-codegraph.js +16 -16
  175. package/dist/coding/pre-action-gate.js +2 -2
  176. package/dist/compounding/engine.js +18 -18
  177. package/dist/config.js +26 -26
  178. package/dist/connectors/codex-materialize-runner.js +19 -19
  179. package/dist/connectors/codex-materialize.js +2 -2
  180. package/dist/connectors/index.js +20 -20
  181. package/dist/consolidation-provenance-check.js +2 -2
  182. package/dist/convergence-refresh.js +20 -20
  183. package/dist/corpus-watermark.js +20 -20
  184. package/dist/deep-recall-http-glue.js +13 -13
  185. package/dist/deep-recall.js +2 -2
  186. package/dist/embedding-fallback.js +2 -2
  187. package/dist/entity-retrieval.js +20 -20
  188. package/dist/event-order-recall.js +2 -2
  189. package/dist/external-wiki-access.js +83 -80
  190. package/dist/extraction-span-materialize.js +2 -2
  191. package/dist/extraction-window-drain.d.ts.map +1 -1
  192. package/dist/extraction-window-drain.js +1 -1
  193. package/dist/extraction.js +32 -32
  194. package/dist/{graph-edge-decay-OEX5OGMI.js → graph-edge-decay-CXTNJ7IQ.js} +6 -6
  195. package/dist/graph-edge-decay-CXTNJ7IQ.js.map +1 -0
  196. package/dist/graph-jsonl.js +4 -4
  197. package/dist/graph-snapshot.js +4 -4
  198. package/dist/graph.js +3 -3
  199. package/dist/harmonic-retrieval.js +17 -17
  200. package/dist/index.js +281 -278
  201. package/dist/lcm/archive.d.ts +12 -2
  202. package/dist/lcm/archive.d.ts.map +1 -1
  203. package/dist/lcm/archive.js +2 -2
  204. package/dist/lcm/engine.d.ts +59 -8
  205. package/dist/lcm/engine.d.ts.map +1 -1
  206. package/dist/lcm/engine.js +6 -6
  207. package/dist/lcm/index.js +16 -16
  208. package/dist/lcm/queue.d.ts +7 -3
  209. package/dist/lcm/queue.d.ts.map +1 -1
  210. package/dist/lcm/queue.js +1 -1
  211. package/dist/lcm/summarizer.d.ts +8 -1
  212. package/dist/lcm/summarizer.d.ts.map +1 -1
  213. package/dist/lcm/summarizer.js +3 -3
  214. package/dist/local-llm.js +4 -4
  215. package/dist/location/index.js +19 -19
  216. package/dist/maintenance/memory-governance.js +18 -18
  217. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +17 -17
  218. package/dist/maintenance/rebuild-memory-projection-runner.js +20 -20
  219. package/dist/maintenance/rebuild-memory-projection.js +19 -19
  220. package/dist/memory-browse-operations.js +83 -80
  221. package/dist/memory-browse.js +6 -6
  222. package/dist/namespaces/migrate.js +18 -18
  223. package/dist/namespaces/search.js +7 -7
  224. package/dist/namespaces/storage.js +17 -17
  225. package/dist/offline-sync-changeset-generations.js +5 -5
  226. package/dist/offline-sync-embedding-generation.js +4 -4
  227. package/dist/offline-sync-snapshot-stream.js +7 -7
  228. package/dist/offline-sync.js +9 -9
  229. package/dist/operator-doctor-corpus.js +21 -21
  230. package/dist/operator-toolkit.js +41 -41
  231. package/dist/orchestration/backlog-scheduler.d.ts +151 -0
  232. package/dist/orchestration/backlog-scheduler.d.ts.map +1 -0
  233. package/dist/orchestration/backlog-scheduler.js +891 -0
  234. package/dist/orchestration/backlog-scheduler.js.map +1 -0
  235. package/dist/orchestration/buffer-drain-runner.d.ts +31 -27
  236. package/dist/orchestration/buffer-drain-runner.d.ts.map +1 -1
  237. package/dist/orchestration/buffer-drain-runner.js +202 -404
  238. package/dist/orchestration/buffer-drain-runner.js.map +1 -1
  239. package/dist/orchestration/extraction-drain.d.ts +50 -17
  240. package/dist/orchestration/extraction-drain.d.ts.map +1 -1
  241. package/dist/orchestration/extraction-queue-coordinator.d.ts +19 -1
  242. package/dist/orchestration/extraction-queue-coordinator.d.ts.map +1 -1
  243. package/dist/orchestration/extraction-run.d.ts +8 -0
  244. package/dist/orchestration/extraction-run.d.ts.map +1 -1
  245. package/dist/orchestration/extraction-task-queueing.d.ts +44 -0
  246. package/dist/orchestration/extraction-task-queueing.d.ts.map +1 -0
  247. package/dist/orchestration/maintenance.js +33 -33
  248. package/dist/orchestration/turn-ingestion.d.ts +11 -5
  249. package/dist/orchestration/turn-ingestion.d.ts.map +1 -1
  250. package/dist/orchestrator.d.ts +13 -0
  251. package/dist/orchestrator.d.ts.map +1 -1
  252. package/dist/orchestrator.js +196 -193
  253. package/dist/qmd.js +4 -4
  254. package/dist/recall-navigation-operations.js +83 -80
  255. package/dist/recall-navigation.js +82 -79
  256. package/dist/recall-state-view-admission.js +6 -6
  257. package/dist/recall-why-service.js +6 -6
  258. package/dist/resume-bundles.js +29 -29
  259. package/dist/search/factory.js +6 -6
  260. package/dist/search/index.js +12 -12
  261. package/dist/semantic-consolidation.js +25 -25
  262. package/dist/semantic-rule-promotion.js +17 -17
  263. package/dist/semantic-rule-verifier.js +17 -17
  264. package/dist/source-agent-qualifier.js +24 -24
  265. package/dist/standup/build.js +17 -17
  266. package/dist/storage/buffer-drain-claims.d.ts +15 -0
  267. package/dist/storage/buffer-drain-claims.d.ts.map +1 -1
  268. package/dist/storage/buffer-drain-claims.js +2 -2
  269. package/dist/storage/buffer-session-files.js +2 -2
  270. package/dist/storage.js +16 -16
  271. package/dist/summarizer.js +6 -6
  272. package/dist/support-passport/index.js +85 -82
  273. package/dist/transfer/backup.js +2 -2
  274. package/dist/transfer/capsule-export.js +2 -2
  275. package/dist/transfer/capsule-import.js +2 -2
  276. package/dist/transfer/export-okf.js +17 -17
  277. package/dist/verified-recall.js +17 -17
  278. package/dist/who-knows-cli.js +18 -18
  279. package/dist/who-knows.js +17 -17
  280. package/package.json +12 -2
  281. package/src/access-observe-lcm-archive.ts +30 -0
  282. package/src/access-observe-lcm-fail-closed.test.ts +118 -0
  283. package/src/access-observe-objective-state.ts +40 -0
  284. package/src/access-observe-stage-timing.test.ts +246 -0
  285. package/src/access-observe-stage-timing.ts +58 -0
  286. package/src/access-observe-write-surface.ts +45 -45
  287. package/src/access-service.ts +1 -0
  288. package/src/backlog-scheduler.test.ts +806 -0
  289. package/src/buffer-drain-handover.test.ts +363 -18
  290. package/src/buffer-drain-inprocess.test.ts +355 -0
  291. package/src/buffer-drain-model-boundary.test.ts +1062 -0
  292. package/src/buffer-drop-extraction-chunk.test.ts +237 -22
  293. package/src/buffer-turn-helpers.ts +26 -1
  294. package/src/buffer.ts +8 -0
  295. package/src/extraction-window-drain.ts +7 -7
  296. package/src/lcm/archive.ts +59 -7
  297. package/src/lcm/engine.ts +256 -53
  298. package/src/lcm/queue.test.ts +32 -14
  299. package/src/lcm/queue.ts +24 -16
  300. package/src/lcm/summarizer.ts +15 -2
  301. package/src/lcm-durability.test.ts +856 -0
  302. package/src/lcm-engine.test.ts +12 -3
  303. package/src/orchestration/backlog-scheduler.ts +481 -0
  304. package/src/orchestration/buffer-drain-runner.ts +545 -180
  305. package/src/orchestration/extraction-drain.ts +287 -108
  306. package/src/orchestration/extraction-queue-coordinator.ts +51 -3
  307. package/src/orchestration/extraction-run.test.ts +41 -0
  308. package/src/orchestration/extraction-run.ts +24 -5
  309. package/src/orchestration/extraction-task-queueing.ts +87 -0
  310. package/src/orchestration/turn-ingestion.ts +46 -59
  311. package/src/orchestrator-extraction-queue.test.ts +46 -2
  312. package/src/orchestrator-flush.test.ts +4 -1
  313. package/src/orchestrator.ts +47 -21
  314. package/src/storage/buffer-drain-claims.ts +55 -0
  315. package/dist/chunk-4MPAKYZU.js.map +0 -1
  316. package/dist/chunk-6WKWL53V.js.map +0 -1
  317. package/dist/chunk-DDBB55L2.js.map +0 -1
  318. package/dist/chunk-KOLJJN5G.js.map +0 -1
  319. package/dist/chunk-MMCO4SRG.js.map +0 -1
  320. package/dist/chunk-R2BIVU2Z.js.map +0 -1
  321. package/dist/chunk-U7MIMS2Y.js.map +0 -1
  322. package/dist/chunk-VA3GNAWQ.js.map +0 -1
  323. package/dist/chunk-WVP2I6C5.js.map +0 -1
  324. package/dist/chunk-Y7427SL7.js.map +0 -1
  325. package/dist/chunk-ZOBYTRBU.js.map +0 -1
  326. /package/dist/{capsule-crypto-GWVG7LGC.js.map → access-observe-lcm-archive.js.map} +0 -0
  327. /package/dist/{graph-edge-decay-OEX5OGMI.js.map → access-observe-objective-state.js.map} +0 -0
  328. /package/dist/{chunk-OWHERGF2.js.map → chunk-2NLLXCJG.js.map} +0 -0
  329. /package/dist/{chunk-CI3MAAIY.js.map → chunk-2R44BBPK.js.map} +0 -0
  330. /package/dist/{chunk-QDZWQBLU.js.map → chunk-2R7OCBRR.js.map} +0 -0
  331. /package/dist/{chunk-B3MWELZ3.js.map → chunk-2WPWEVAH.js.map} +0 -0
  332. /package/dist/{chunk-PLCYKAWH.js.map → chunk-3ICAWZUU.js.map} +0 -0
  333. /package/dist/{chunk-R4ZHF4K2.js.map → chunk-43FLJLT2.js.map} +0 -0
  334. /package/dist/{chunk-PMDOGXA2.js.map → chunk-4PMFSYH7.js.map} +0 -0
  335. /package/dist/{chunk-HXFIILGF.js.map → chunk-4RASUAN3.js.map} +0 -0
  336. /package/dist/{chunk-EI6M5NVK.js.map → chunk-5JBVPJCT.js.map} +0 -0
  337. /package/dist/{chunk-4NV7O76Q.js.map → chunk-5ORJHH43.js.map} +0 -0
  338. /package/dist/{chunk-74AY3S7U.js.map → chunk-5RW247F5.js.map} +0 -0
  339. /package/dist/{chunk-4XINO77L.js.map → chunk-66JOLMWS.js.map} +0 -0
  340. /package/dist/{chunk-AYJQ644F.js.map → chunk-6KBCUIZP.js.map} +0 -0
  341. /package/dist/{chunk-GKL6QYZO.js.map → chunk-6L63IN3M.js.map} +0 -0
  342. /package/dist/{chunk-OPFVXM2D.js.map → chunk-7P5VBRBS.js.map} +0 -0
  343. /package/dist/{chunk-4SOWMA55.js.map → chunk-7WFY2L5J.js.map} +0 -0
  344. /package/dist/{chunk-GJ4HU6LK.js.map → chunk-AGRMXXVA.js.map} +0 -0
  345. /package/dist/{chunk-IVUVQPTQ.js.map → chunk-AZNE2H6D.js.map} +0 -0
  346. /package/dist/{chunk-HPB5TF55.js.map → chunk-BCBY5GYZ.js.map} +0 -0
  347. /package/dist/{chunk-M4IEZGCK.js.map → chunk-BFBS7OFQ.js.map} +0 -0
  348. /package/dist/{chunk-4PG5R6BJ.js.map → chunk-BNU5TQLR.js.map} +0 -0
  349. /package/dist/{chunk-TVE7W67N.js.map → chunk-BTU77RB5.js.map} +0 -0
  350. /package/dist/{chunk-H6VJSITJ.js.map → chunk-CIL4GHMD.js.map} +0 -0
  351. /package/dist/{chunk-KZZ5EZ7O.js.map → chunk-DC3DWF2M.js.map} +0 -0
  352. /package/dist/{chunk-AUFPPBC3.js.map → chunk-ENPJX3BB.js.map} +0 -0
  353. /package/dist/{chunk-CTH2CQCB.js.map → chunk-EQ6EMJRG.js.map} +0 -0
  354. /package/dist/{chunk-63A2BU2B.js.map → chunk-F4ZHKDBW.js.map} +0 -0
  355. /package/dist/{chunk-3LBDEGQA.js.map → chunk-FDUCIUQ5.js.map} +0 -0
  356. /package/dist/{chunk-OCK4D5PC.js.map → chunk-FGGLVCHI.js.map} +0 -0
  357. /package/dist/{chunk-XVZA6VXC.js.map → chunk-FZVROZKC.js.map} +0 -0
  358. /package/dist/{chunk-3RHU5MD7.js.map → chunk-GXAZ4Q2S.js.map} +0 -0
  359. /package/dist/{chunk-UVVFPCPX.js.map → chunk-H2X32F2K.js.map} +0 -0
  360. /package/dist/{chunk-645WOU5I.js.map → chunk-H7BZBSP6.js.map} +0 -0
  361. /package/dist/{chunk-W7K5BP3M.js.map → chunk-HQPFACXO.js.map} +0 -0
  362. /package/dist/{chunk-TECK5IVY.js.map → chunk-HZNURRDS.js.map} +0 -0
  363. /package/dist/{chunk-U2CAGMUD.js.map → chunk-ICBUTKLL.js.map} +0 -0
  364. /package/dist/{chunk-B4DXREWC.js.map → chunk-IQXQ3KWR.js.map} +0 -0
  365. /package/dist/{chunk-AL3TCNSJ.js.map → chunk-J6GZ2254.js.map} +0 -0
  366. /package/dist/{chunk-5MGKGEL7.js.map → chunk-J72ZY7NU.js.map} +0 -0
  367. /package/dist/{chunk-OH55F76C.js.map → chunk-JEX2JL3U.js.map} +0 -0
  368. /package/dist/{chunk-Y3XPSGNF.js.map → chunk-JGLZ46JS.js.map} +0 -0
  369. /package/dist/{chunk-EXQJMFRF.js.map → chunk-JY4LXMZR.js.map} +0 -0
  370. /package/dist/{chunk-6P7U3HWG.js.map → chunk-K36RMINQ.js.map} +0 -0
  371. /package/dist/{chunk-BUKK5SWA.js.map → chunk-KQAFEZQX.js.map} +0 -0
  372. /package/dist/{chunk-LN4X2NDA.js.map → chunk-KY3KJUNN.js.map} +0 -0
  373. /package/dist/{chunk-H5DIRCZP.js.map → chunk-LHMCZ6VW.js.map} +0 -0
  374. /package/dist/{chunk-GGD2YDS6.js.map → chunk-LN7CWLAU.js.map} +0 -0
  375. /package/dist/{chunk-GHHQLSSY.js.map → chunk-LYOCAUI6.js.map} +0 -0
  376. /package/dist/{chunk-W26D2USW.js.map → chunk-MUH7RR6T.js.map} +0 -0
  377. /package/dist/{chunk-IAGVM7EY.js.map → chunk-N2Y6COEM.js.map} +0 -0
  378. /package/dist/{chunk-64JLBFCQ.js.map → chunk-N7NAGECH.js.map} +0 -0
  379. /package/dist/{chunk-5Y6VA6X2.js.map → chunk-OGQGDOYK.js.map} +0 -0
  380. /package/dist/{chunk-JLMOH5JA.js.map → chunk-OWZXDBV4.js.map} +0 -0
  381. /package/dist/{chunk-ZORS5BG5.js.map → chunk-PJAMFIDE.js.map} +0 -0
  382. /package/dist/{chunk-SXTVZ6JL.js.map → chunk-QIOQI7QZ.js.map} +0 -0
  383. /package/dist/{chunk-75DCOS6I.js.map → chunk-QUPTDKSX.js.map} +0 -0
  384. /package/dist/{chunk-HH73M65H.js.map → chunk-QVZZE6VH.js.map} +0 -0
  385. /package/dist/{chunk-XWE3EOWX.js.map → chunk-RZED7FAU.js.map} +0 -0
  386. /package/dist/{chunk-IZBIDPMY.js.map → chunk-S37O4S6E.js.map} +0 -0
  387. /package/dist/{chunk-NHWDTOBN.js.map → chunk-S73ZVU37.js.map} +0 -0
  388. /package/dist/{chunk-YSATDEBY.js.map → chunk-SBRUTD5O.js.map} +0 -0
  389. /package/dist/{chunk-PRKNAIGZ.js.map → chunk-T6T2RMWW.js.map} +0 -0
  390. /package/dist/{chunk-CIEEYVUB.js.map → chunk-TPX7XXY4.js.map} +0 -0
  391. /package/dist/{chunk-L334PSLW.js.map → chunk-U2A56LLF.js.map} +0 -0
  392. /package/dist/{chunk-P4TV3TQ2.js.map → chunk-U6IL4724.js.map} +0 -0
  393. /package/dist/{chunk-5UM4H64E.js.map → chunk-UAOJVQXC.js.map} +0 -0
  394. /package/dist/{chunk-MOIJWWNA.js.map → chunk-UE5JYPU6.js.map} +0 -0
  395. /package/dist/{chunk-TGQW3AMK.js.map → chunk-UIFWZMO7.js.map} +0 -0
  396. /package/dist/{chunk-UW6LBFYN.js.map → chunk-USX5YIKB.js.map} +0 -0
  397. /package/dist/{chunk-QGFR73SN.js.map → chunk-VK5HKVQ7.js.map} +0 -0
  398. /package/dist/{chunk-IHCXMYSE.js.map → chunk-VPEIWMUT.js.map} +0 -0
  399. /package/dist/{chunk-O5ZINWW3.js.map → chunk-VSJ3ARFS.js.map} +0 -0
  400. /package/dist/{chunk-RLVI2M5Q.js.map → chunk-W4V7P5HP.js.map} +0 -0
  401. /package/dist/{chunk-ELHJK7LM.js.map → chunk-WBN66HPI.js.map} +0 -0
  402. /package/dist/{chunk-BJLCV2P3.js.map → chunk-WGRAB3KB.js.map} +0 -0
  403. /package/dist/{chunk-5KDDAQ6K.js.map → chunk-WN2DASTS.js.map} +0 -0
  404. /package/dist/{chunk-IG3EZ3TF.js.map → chunk-WNQ3B3Q5.js.map} +0 -0
  405. /package/dist/{chunk-V6SBA5O7.js.map → chunk-WYOHQJKC.js.map} +0 -0
  406. /package/dist/{chunk-WHROVQ5Q.js.map → chunk-X4DHAXFO.js.map} +0 -0
  407. /package/dist/{chunk-UVYI6VIX.js.map → chunk-X7Y7WX73.js.map} +0 -0
  408. /package/dist/{chunk-JLGBJ4AX.js.map → chunk-XPZM7GP6.js.map} +0 -0
  409. /package/dist/{chunk-64S6X4IU.js.map → chunk-XTN54NML.js.map} +0 -0
  410. /package/dist/{chunk-UYUFDTIX.js.map → chunk-YIXWY4OZ.js.map} +0 -0
  411. /package/dist/{chunk-NCZGGGWI.js.map → chunk-YPYSC3TX.js.map} +0 -0
  412. /package/dist/{chunk-AVGDYYMA.js.map → chunk-ZBET3W26.js.map} +0 -0
@@ -106,6 +106,13 @@ export interface ExtractionRunCoordinatorDeps {
106
106
  fingerprint: string,
107
107
  preloadedMeta?: Awaited<ReturnType<StorageManager["loadMeta"]>>
108
108
  ) => Promise<void>;
109
+ /**
110
+ * Orchestrator-wide provider resilience state. Absent for a standalone
111
+ * coordinator (own breaker); the orchestrator passes ITS breaker so every
112
+ * isolated claim-backed drain accumulates failures toward the same
113
+ * threshold and honors a foreground-opened breaker (review round).
114
+ */
115
+ providerBreaker?: ProviderCircuitBreaker;
109
116
  }
110
117
 
111
118
  // Recall/extraction abort helpers live in orchestrator-helpers.ts since
@@ -151,9 +158,11 @@ export class ExtractionRunCoordinator {
151
158
  // backoff still throttles, so a restart can't resurrect the hot loop.
152
159
  private readonly extractionRetryState = new Map<string, Map<string, ExtractionRetryStateEntry>>();
153
160
  private readonly hydratedRetryNamespaces = new Set<string>();
154
- private readonly providerBreaker = new ProviderCircuitBreaker();
161
+ private readonly providerBreaker: ProviderCircuitBreaker;
155
162
 
156
- constructor(private readonly deps: ExtractionRunCoordinatorDeps) {}
163
+ constructor(private readonly deps: ExtractionRunCoordinatorDeps) {
164
+ this.providerBreaker = deps.providerBreaker ?? new ProviderCircuitBreaker();
165
+ }
157
166
 
158
167
  private get config(): PluginConfig {
159
168
  return this.deps.config;
@@ -661,10 +670,14 @@ export class ExtractionRunCoordinator {
661
670
  log.warn(
662
671
  `runExtraction: skipping scope profile ${scopeProfileWritePlan.profileId} because write layer ${scopeProfileWritePlan.writeLayer} is not writable inside the profile read stack`
663
672
  );
664
- await clearBuffer();
673
+ // Policy refusal (same family as namespace_write_revoked): the window
674
+ // stays in the buffer/claim pending a later attempt. Clearing here
675
+ // would destroy content policy never wrote — the claim drain would
676
+ // erase denied backlog and ack it as drained.
665
677
  return {
666
678
  status: "skipped",
667
679
  reason: "scope_profile_no_writable_layer",
680
+ retainedBuffer: true,
668
681
  persistedCount: 0,
669
682
  durableOutputCount: 0,
670
683
  };
@@ -854,10 +867,13 @@ export class ExtractionRunCoordinator {
854
867
  if (options.failOnExtractionFailure) {
855
868
  throw new Error("extraction failed: invalid_extraction_result");
856
869
  }
857
- await clearBuffer();
870
+ // Actual extraction failure: the window is retained for a retry (same
871
+ // no-drop contract as a recorded provider failure), never destroyed.
858
872
  return {
859
873
  status: "skipped",
860
874
  reason: "invalid_extraction_result",
875
+ retainedBuffer: true,
876
+ failureClass: "parse_empty",
861
877
  persistedCount: 0,
862
878
  durableOutputCount: 0,
863
879
  };
@@ -878,10 +894,13 @@ export class ExtractionRunCoordinator {
878
894
  if (options.failOnExtractionFailure) {
879
895
  throw new Error("extraction failed: invalid_extraction_result");
880
896
  }
881
- await clearBuffer();
897
+ // Actual extraction failure: the window is retained for a retry (same
898
+ // no-drop contract as a recorded provider failure), never destroyed.
882
899
  return {
883
900
  status: "skipped",
884
901
  reason: "invalid_extraction_result",
902
+ retainedBuffer: true,
903
+ failureClass: "parse_empty",
885
904
  persistedCount: 0,
886
905
  durableOutputCount: 0,
887
906
  };
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Extraction task queueing — the scope-group and execution-context pieces of
3
+ * the turn-ingestion coordinator, split out to keep that module inside the
4
+ * house source-size cap (issue #1995).
5
+ */
6
+
7
+ import type { SmartBuffer } from "../buffer.js";
8
+ import { groupTurnsByExtractionScope } from "../buffer-turn-helpers.js";
9
+ import { log } from "../logger.js";
10
+ import type { ResolvedScopeProfilePlan } from "../namespaces/scope-profiles.js";
11
+ import type { BufferTurn, CodingContext } from "../types.js";
12
+ import type { ExtractionDrain } from "./extraction-drain.js";
13
+ import type { TurnIngestionDeps } from "./turn-ingestion.js";
14
+
15
+ /**
16
+ * Isolated per-task execution context (claim-backed backlog drain).
17
+ * Bound at enqueue time and read ONLY inside the enqueued closure, so the
18
+ * task runs against its own buffer/extraction/drain no matter which async
19
+ * context the coordinator's processor executes it from. Absent for live
20
+ * work, which keeps the shared orchestrator state.
21
+ */
22
+ export interface ExtractionTaskExecutionContext {
23
+ /** The task's own buffer (a claim-backed SmartBuffer). */
24
+ buffer: SmartBuffer;
25
+ /**
26
+ * The task's own chunked drain; its deps carry the isolated runExtraction +
27
+ * buffer (claim tasks build one with `dropFailedChunks: false` — the
28
+ * no-drop backlog policy).
29
+ */
30
+ drain: ExtractionDrain;
31
+ }
32
+
33
+ /** Queue options the capture-scope grouping forwards to the coordinator. */
34
+ export interface CaptureScopeGroupQueueOptions {
35
+ deadlineMs?: number;
36
+ abortSignal?: AbortSignal;
37
+ writeNamespaceOverride?: string;
38
+ principalOverride?: string;
39
+ scopeProfileWritePlan?: ResolvedScopeProfilePlan | null;
40
+ codingContext?: CodingContext;
41
+ onExtractionQueued?: (extraction: Promise<void>) => void;
42
+ }
43
+
44
+ /**
45
+ * Buffer-approved captures skip threshold/dedupe rechecks, not provider
46
+ * retry cooldowns. Scope and staleness are enforced at the shared
47
+ * queueBufferedExtraction boundary.
48
+ */
49
+ export function queueBufferedCaptureScopeGroups(
50
+ queueBufferedExtraction: TurnIngestionDeps["queueBufferedExtraction"],
51
+ extractionTurns: BufferTurn[],
52
+ bufferKey: string,
53
+ options: CaptureScopeGroupQueueOptions,
54
+ ): void {
55
+ for (const group of groupTurnsByExtractionScope(extractionTurns)) {
56
+ const groupIsAccepted = group.turns.some((turn) => turn.acceptedCapture === true);
57
+ if (!groupIsAccepted) {
58
+ // Native groups keep their own routing; skipped accepted prefixes require identity clearing.
59
+ void queueBufferedExtraction(group.turns, "trigger_mode", {
60
+ bufferKey,
61
+ clearMatchingTurns: true,
62
+ preemptable: true,
63
+ }).catch((err) => log.error(`native trigger extraction failed: ${err}`));
64
+ continue;
65
+ }
66
+ // Accepted groups use ONLY their own pins — no fallback to the
67
+ // triggering observe's scope.
68
+ const { promise: extraction, resolve, reject } = Promise.withResolvers<void>();
69
+ void queueBufferedExtraction(group.turns, "trigger_mode", {
70
+ bufferKey,
71
+ clearBufferAfterExtraction: true,
72
+ clearMatchingTurns: true,
73
+ skipDedupeCheck: true,
74
+ skipCharThreshold: true,
75
+ skipUserTurnThreshold: true,
76
+ abortSignal: options.abortSignal,
77
+ extractionDeadlineMs: options.deadlineMs,
78
+ writeNamespaceOverride: group.writeNamespaceOverride,
79
+ principalOverride: group.principalOverride,
80
+ scopeProfileWritePlan: group.scopeProfileWritePlan ?? null,
81
+ preemptable: true,
82
+ onTaskSettled: (err) => (err ? reject(err) : resolve()),
83
+ }).catch(reject);
84
+ if (options.onExtractionQueued) options.onExtractionQueued(extraction);
85
+ else extraction.catch((err) => log.error(`buffered capture extraction failed: ${err}`));
86
+ }
87
+ }
@@ -44,6 +44,11 @@ import type { BufferTurn, PluginConfig, SourceConnectorProvenance } from "../typ
44
44
  import { groupTurnsByExtractionScope, bufferTurnsEqual } from "../buffer-turn-helpers.js";
45
45
  import { ExtractionDrain } from "./extraction-drain.js";
46
46
  import { skipClaimedSession } from "./buffer-drain-gate.js";
47
+ import {
48
+ queueBufferedCaptureScopeGroups,
49
+ type CaptureScopeGroupQueueOptions,
50
+ type ExtractionTaskExecutionContext,
51
+ } from "./extraction-task-queueing.js";
47
52
  import { resolveScopeProfilePlan, type ResolvedScopeProfilePlan, hasExplicitNamespacePolicy } from "../namespaces/scope-profiles.js";
48
53
  import { resolveCodingNamespaceOverlay, combineNamespaces } from "../coding/coding-namespace.js";
49
54
  import { canWriteNamespace, defaultNamespaceForPrincipal } from "../namespaces/principal.js";
@@ -224,7 +229,7 @@ export class TurnIngestionCoordinator {
224
229
  // #3251: native triggers must not run mixed accepted scopes under one
225
230
  // policy — each scope group drains through the shared execution
226
231
  // boundary with its own pins.
227
- this.queueBufferedCaptureScopeGroups(outcome.extractionTurns, bufferKey, {});
232
+ queueBufferedCaptureScopeGroups(this.deps.queueBufferedExtraction, outcome.extractionTurns, bufferKey, {});
228
233
  return;
229
234
  }
230
235
  await this.deps.queueBufferedExtraction(
@@ -463,7 +468,12 @@ export class TurnIngestionCoordinator {
463
468
  );
464
469
  }
465
470
  if (outcome.decision !== "keep_buffering" && outcome.extractionTurns) {
466
- this.queueBufferedCaptureScopeGroups(outcome.extractionTurns, bufferKey, options);
471
+ queueBufferedCaptureScopeGroups(
472
+ this.deps.queueBufferedExtraction,
473
+ outcome.extractionTurns,
474
+ bufferKey,
475
+ options,
476
+ );
467
477
  }
468
478
  }
469
479
  // Acceptance durability barrier (#1909 seam): surfaces storage failures
@@ -472,58 +482,6 @@ export class TurnIngestionCoordinator {
472
482
  }
473
483
  }
474
484
 
475
- /**
476
- * Buffer-approved captures skip threshold/dedupe rechecks, not provider retry cooldowns.
477
- * Scope and staleness are enforced at the shared queueBufferedExtraction boundary.
478
- */
479
- private queueBufferedCaptureScopeGroups(
480
- extractionTurns: BufferTurn[],
481
- bufferKey: string,
482
- options: {
483
- deadlineMs?: number;
484
- abortSignal?: AbortSignal;
485
- writeNamespaceOverride?: string;
486
- principalOverride?: string;
487
- scopeProfileWritePlan?: ResolvedScopeProfilePlan | null;
488
- codingContext?: import("../types.js").CodingContext;
489
- onExtractionQueued?: (extraction: Promise<void>) => void;
490
- },
491
- ): void {
492
- for (const group of groupTurnsByExtractionScope(extractionTurns)) {
493
- const groupIsAccepted = group.turns.some((turn) => turn.acceptedCapture === true);
494
- if (!groupIsAccepted) {
495
- // Native groups keep their own routing; skipped accepted prefixes require identity clearing.
496
- void this.deps.queueBufferedExtraction(group.turns, "trigger_mode", {
497
- bufferKey,
498
- clearMatchingTurns: true,
499
- preemptable: true,
500
- }).catch((err) => log.error(`native trigger extraction failed: ${err}`));
501
- continue;
502
- }
503
- // Accepted groups use ONLY their own pins — no fallback to the
504
- // triggering observe's scope.
505
- const extraction = new Promise<void>((resolve, reject) => {
506
- void this.deps.queueBufferedExtraction(group.turns, "trigger_mode", {
507
- bufferKey,
508
- clearBufferAfterExtraction: true,
509
- clearMatchingTurns: true,
510
- skipDedupeCheck: true,
511
- skipCharThreshold: true,
512
- skipUserTurnThreshold: true,
513
- abortSignal: options.abortSignal,
514
- extractionDeadlineMs: options.deadlineMs,
515
- writeNamespaceOverride: group.writeNamespaceOverride,
516
- principalOverride: group.principalOverride,
517
- scopeProfileWritePlan: group.scopeProfileWritePlan ?? null,
518
- preemptable: true,
519
- onTaskSettled: (err) => (err ? reject(err) : resolve()),
520
- }).catch(reject);
521
- });
522
- if (options.onExtractionQueued) options.onExtractionQueued(extraction);
523
- else extraction.catch((err) => log.error(`buffered capture extraction failed: ${err}`));
524
- }
525
- }
526
-
527
485
  /**
528
486
  * Ingest a batch of bulk-import turns (#460). Like ingestReplayBatch, this
529
487
  * normalizes user/assistant turns into the extraction buffer and awaits
@@ -802,7 +760,7 @@ export class TurnIngestionCoordinator {
802
760
  if (turns.some((turn) => turn.acceptedCapture === true)) {
803
761
  // #3251: heartbeat triggers must not run mixed accepted scopes
804
762
  // under one policy — per-scope groups via the shared boundary.
805
- this.queueBufferedCaptureScopeGroups(turns, bufferKey, {});
763
+ queueBufferedCaptureScopeGroups(this.deps.queueBufferedExtraction, turns, bufferKey, {});
806
764
  return;
807
765
  }
808
766
  await this.deps.queueBufferedExtraction(turns, "heartbeat_observer", {
@@ -842,6 +800,14 @@ export class TurnIngestionCoordinator {
842
800
  abortSignal?: AbortSignal;
843
801
  /** Automatic buffered work only. Replay and import must not set this. */
844
802
  preemptable?: boolean;
803
+ /**
804
+ * Invoked when the queued closure has FULLY exited (after settlement).
805
+ * Settlement can fire before the closure exits — e.g. an abort listener
806
+ * settles while persistence is still in flight — so callers that
807
+ * release resources on settlement (claim leases) can use this to wait
808
+ * for the actual task exit first.
809
+ */
810
+ onTaskExit?: () => void;
845
811
  /** Fail-closed force-flush only. Not implied by failOnExtractionFailure. */
846
812
  preemptRunning?: boolean;
847
813
  writeNamespaceOverride?: string;
@@ -852,10 +818,14 @@ export class TurnIngestionCoordinator {
852
818
  */
853
819
  principalOverride?: string;
854
820
  scopeProfileWritePlan?: ResolvedScopeProfilePlan | null;
821
+ /** Isolated per-task execution context (claim-backed backlog drain). */
822
+ execution?: ExtractionTaskExecutionContext;
855
823
  } = {},
856
824
  ): Promise<void> {
857
825
  const bufferKey = options.bufferKey ?? turnsToExtract[0]?.sessionKey ?? "default";
858
- if (skipClaimedSession(this.deps.buffer, bufferKey, (result) => options.onTaskSettled?.(undefined, result))) return;
826
+ // The execution context owns the gate's buffer view: a claim-backed task
827
+ // reads its own claim (never "claimed"), not the live buffer's gate.
828
+ if (skipClaimedSession(options.execution?.buffer ?? this.deps.buffer, bufferKey, (result) => options.onTaskSettled?.(undefined, result))) return;
859
829
  if (
860
830
  !options.skipDedupeCheck &&
861
831
  !this.deps.shouldQueueExtraction(turnsToExtract, { bufferKey })
@@ -933,7 +903,8 @@ export class TurnIngestionCoordinator {
933
903
  if (settled) return;
934
904
  const preemptable = options.preemptable === true && options.preemptRunning !== true;
935
905
  const accepted = this.deps.extractionQueueCoordinator.enqueue(async (preemptHandle) => {
936
- await this.deps.extractionQueueCoordinator.runPreemptable(preemptHandle, preemptable, options.abortSignal, async (abortSignal) => {
906
+ try {
907
+ await this.deps.extractionQueueCoordinator.runPreemptable(preemptHandle, preemptable, options.abortSignal, async (abortSignal) => {
937
908
  if (settled) return;
938
909
  if (
939
910
  typeof extractionDeadlineMs === "number" &&
@@ -943,6 +914,17 @@ export class TurnIngestionCoordinator {
943
914
  return;
944
915
  }
945
916
  clearQueueWaitTimer();
917
+ // Execution-time claim recheck (review round): the scheduler's
918
+ // async claim decision may complete while this LIVE task sits queued;
919
+ // its turns then belong to the claim runner, and extracting the stale
920
+ // snapshot here would persist duplicate outputs. The enqueue-time gate
921
+ // plus the key reservation only park the task until the decision
922
+ // settles. Isolated claim tasks (options.execution) read their own
923
+ // claim-backed buffer and bypass this gate by construction.
924
+ if (
925
+ options.execution === undefined &&
926
+ skipClaimedSession(this.deps.buffer, bufferKey, (result) => settleTask(undefined, result))
927
+ ) return;
946
928
  try {
947
929
  // #3251 shared execution boundary for accepted captures (trigger and
948
930
  // flush drains both converge here): re-read the live buffer so a
@@ -951,8 +933,9 @@ export class TurnIngestionCoordinator {
951
933
  // WITHOUT clearing, and the plan is never retargeted.
952
934
  let effectiveTurns = turnsToExtract;
953
935
  let effectiveScopePlan = options.scopeProfileWritePlan;
936
+ const executionBuffer = options.execution?.buffer;
954
937
  if (effectiveTurns.some((turn) => turn.acceptedCapture === true)) {
955
- const liveTurns = this.deps.buffer
938
+ const liveTurns = (executionBuffer ?? this.deps.buffer)
956
939
  .getTurns(bufferKey)
957
940
  .filter((live) => effectiveTurns.some((snapshotted) => bufferTurnsEqual(live, snapshotted)));
958
941
  if (liveTurns.length === 0) {
@@ -1073,7 +1056,7 @@ export class TurnIngestionCoordinator {
1073
1056
  effectiveScopePlan = fresh;
1074
1057
  }
1075
1058
  }
1076
- const result = await this.drain.run(effectiveTurns, {
1059
+ const result = await (options.execution?.drain ?? this.drain).run(effectiveTurns, {
1077
1060
  clearBufferAfterExtraction:
1078
1061
  options.clearBufferAfterExtraction ?? true,
1079
1062
  clearMatchingTurns: options.clearMatchingTurns === true,
@@ -1099,9 +1082,13 @@ export class TurnIngestionCoordinator {
1099
1082
  }
1100
1083
  }
1101
1084
  });
1085
+ } finally {
1086
+ options.onTaskExit?.();
1087
+ }
1102
1088
  }, { front: options.preemptRunning === true, key: bufferKey });
1103
1089
  if (!accepted) {
1104
1090
  settleTask(new Error("extraction queue is stopped"));
1091
+ options.onTaskExit?.();
1105
1092
  return;
1106
1093
  }
1107
1094
 
@@ -184,7 +184,6 @@ test("logExtractionQueueFailure names the right layer (task vs processor)", asyn
184
184
  );
185
185
  });
186
186
 
187
-
188
187
  test("pauseAndDrain waits for accepted work after its observation timeout", async () => {
189
188
  const coordinator = createCoordinator();
190
189
  const started = Promise.withResolvers<void>();
@@ -270,7 +269,6 @@ test("a front enqueue does not abort a task that did not register as preemptable
270
269
  assert.deepEqual(order, ["protected", "flush"]);
271
270
  });
272
271
 
273
-
274
272
  // ── Bounded-parallel queue (extractionQueueConcurrency) ─────────────────────
275
273
 
276
274
  function createParallelCoordinator(limit: number): ExtractionQueueCoordinator {
@@ -441,3 +439,49 @@ test("pauseAndDrain waits for concurrent accepted work and rejects new producers
441
439
  assert.equal(second.outcome, "finished");
442
440
  assert.equal(coordinator.isProcessing, false);
443
441
  });
442
+
443
+ // ── Key reservations (daemon backlog scheduler) ────────────────────────────
444
+
445
+ function delay(ms: number): Promise<void> {
446
+ return new Promise((resolve) => setTimeout(resolve, ms));
447
+ }
448
+
449
+ test("tryReserveKey defers a queued task's start until the reservation releases", async () => {
450
+ const queue = createCoordinator();
451
+ assert.equal(queue.tryReserveKey("s1"), true, "a free key reserves synchronously");
452
+
453
+ let ran = false;
454
+ queue.pushRaw(async () => {
455
+ ran = true;
456
+ }, { key: "s1" });
457
+ const processing = queue.processQueue();
458
+ await delay(20);
459
+ assert.equal(ran, false, "a reserved key's queued task must not start");
460
+ assert.equal(queue.tryReserveKey("s1"), false, "the pending reservation is exclusive");
461
+
462
+ queue.releaseKeyReservation("s1");
463
+ await processing;
464
+ assert.equal(ran, true, "the task runs once the claim decision settles");
465
+ });
466
+
467
+ test("tryReserveKey refuses active and queued keys, and releases idempotently", async () => {
468
+ const queue = createCoordinator();
469
+ let release: () => void = () => {};
470
+ const gate = new Promise<void>((resolve) => {
471
+ release = resolve;
472
+ });
473
+ queue.pushRaw(async () => {
474
+ await gate;
475
+ }, { key: "s1" });
476
+ const processing = queue.processQueue();
477
+ await delay(20);
478
+ assert.equal(queue.tryReserveKey("s1"), false, "an active key cannot be reserved");
479
+
480
+ queue.releaseKeyReservation("s1");
481
+ queue.releaseKeyReservation("s1"); // idempotent
482
+ release();
483
+ await processing;
484
+
485
+ assert.equal(queue.tryReserveKey("s1"), true, "a settled key reserves again");
486
+ queue.releaseKeyReservation("s1");
487
+ });
@@ -1492,7 +1492,10 @@ test("runExtraction skips active scope profile writes when no layer is writable"
1492
1492
 
1493
1493
  assert.equal(result.status, "skipped");
1494
1494
  assert.equal(result.reason, "scope_profile_no_writable_layer");
1495
- assert.equal(clearCalls, 1);
1495
+ // Policy refusal (review round): the window is RETAINED, never
1496
+ // cleared — clearing here would destroy content policy never wrote.
1497
+ assert.equal(clearCalls, 0);
1498
+ assert.equal(result.retainedBuffer, true);
1496
1499
  });
1497
1500
 
1498
1501
  test("runExtraction writes buffered turns to active scope profile write layer", async () => {
@@ -98,6 +98,7 @@ import {
98
98
  gatewayTaskChainOptions,
99
99
  } from "./fallback-llm.js";
100
100
  import { MaintenanceScheduler } from "./orchestration/maintenance.js";
101
+ import { ProviderCircuitBreaker } from "./orchestration/provider-breaker.js";
101
102
  import { TierMigrationCoordinator } from "./orchestration/tier-migration-coordinator.js";
102
103
  import { ExtractionQueueCoordinator } from "./orchestration/extraction-queue-coordinator.js";
103
104
  import { CompressionGuidelineCoordinator } from "./orchestration/compression-guideline-coordinator.js";
@@ -119,6 +120,7 @@ import {
119
120
  } from "./orchestration/contradiction-linking-coordinator.js";
120
121
  import {
121
122
  ExtractionRunCoordinator,
123
+ type ExtractionRunCoordinatorDeps,
122
124
  type ExtractionRunResult,
123
125
  type ExtractionResilienceStatus,
124
126
  } from "./orchestration/extraction-run.js";
@@ -756,33 +758,57 @@ export class Orchestrator {
756
758
 
757
759
  readonly extractionQueueCoordinator: ExtractionQueueCoordinator;
758
760
  private _extractionRunCoordinator: ExtractionRunCoordinator | undefined;
761
+ private _providerBreaker: ProviderCircuitBreaker | undefined;
762
+
763
+ /** One breaker per orchestrator: foreground and every isolated claim-backed
764
+ * drain accumulate toward the same threshold and honor each other's open
765
+ * state (review round — isolated coordinators must not reset
766
+ * provider resilience). */
767
+ private get providerBreaker(): ProviderCircuitBreaker {
768
+ if (!this._providerBreaker) this._providerBreaker = new ProviderCircuitBreaker();
769
+ return this._providerBreaker;
770
+ }
771
+
772
+ /** The run-coordinator deps bundle, parameterized by its buffer accessor so
773
+ * an isolated claim-backed drain can bind its own SmartBuffer (the daemon
774
+ * backlog scheduler) while live extraction keeps `this.buffer`. */
775
+ private extractionRunDeps(getBuffer: () => SmartBuffer): ExtractionRunCoordinatorDeps {
776
+ return {
777
+ config: this.config,
778
+ getBuffer,
779
+ providerBreaker: this.providerBreaker,
780
+ getExtraction: () => this.extraction,
781
+ getStorageRouter: () => this.storageRouter,
782
+ getThreading: () => this.threading,
783
+ persistExtraction: (result, storage, threadId, sourceContext, baseNamespace, scopeProfileWritePlan, sourceText, graphCaps, lifecycleCaps) =>
784
+ this.persistExtraction(result, storage, threadId, sourceContext, baseNamespace, scopeProfileWritePlan, sourceText, graphCaps, lifecycleCaps),
785
+ maybeCapturePassiveCorrections: (turns, opts) => this.maybeCapturePassiveCorrections(turns, opts),
786
+ resolveSelfNamespace: (sessionKey) => this.resolveSelfNamespace(sessionKey),
787
+ getCodingContextForSession: (sessionKey) => this.getCodingContextForSession(sessionKey),
788
+ applyCodingNamespaceOverlay: (sessionKey, namespace) => this.applyCodingNamespaceOverlay(sessionKey, namespace),
789
+ boxBuilderFor: (storage) => this.boxBuilderFor(storage),
790
+ appendPersistedThreadEpisodes: (threadId, ids, pendingReviewIds) =>
791
+ this.appendPersistedThreadEpisodes(threadId, ids, pendingReviewIds),
792
+ maybeScheduleConsolidation: (nonZero) => this.maybeScheduleConsolidation(nonZero),
793
+ requestQmdMaintenance: () => this.requestQmdMaintenance(),
794
+ runTierMigrationCycle: (storage, trigger, options) => this.runTierMigrationCycle(storage, trigger, options),
795
+ recordProcessedExtractionFingerprint: (storage, fingerprint, preloadedMeta) =>
796
+ this.recordProcessedExtractionFingerprint(storage, fingerprint, preloadedMeta),
797
+ };
798
+ }
759
799
 
760
800
  private get extractionRunCoordinator(): ExtractionRunCoordinator {
761
801
  if (!this._extractionRunCoordinator) {
762
- this._extractionRunCoordinator = new ExtractionRunCoordinator({
763
- config: this.config,
764
- getBuffer: () => this.buffer,
765
- getExtraction: () => this.extraction,
766
- getStorageRouter: () => this.storageRouter,
767
- getThreading: () => this.threading,
768
- persistExtraction: (result, storage, threadId, sourceContext, baseNamespace, scopeProfileWritePlan, sourceText, graphCaps, lifecycleCaps) =>
769
- this.persistExtraction(result, storage, threadId, sourceContext, baseNamespace, scopeProfileWritePlan, sourceText, graphCaps, lifecycleCaps),
770
- maybeCapturePassiveCorrections: (turns, opts) => this.maybeCapturePassiveCorrections(turns, opts),
771
- resolveSelfNamespace: (sessionKey) => this.resolveSelfNamespace(sessionKey),
772
- getCodingContextForSession: (sessionKey) => this.getCodingContextForSession(sessionKey),
773
- applyCodingNamespaceOverlay: (sessionKey, namespace) => this.applyCodingNamespaceOverlay(sessionKey, namespace),
774
- boxBuilderFor: (storage) => this.boxBuilderFor(storage),
775
- appendPersistedThreadEpisodes: (threadId, ids, pendingReviewIds) =>
776
- this.appendPersistedThreadEpisodes(threadId, ids, pendingReviewIds),
777
- maybeScheduleConsolidation: (nonZero) => this.maybeScheduleConsolidation(nonZero),
778
- requestQmdMaintenance: () => this.requestQmdMaintenance(),
779
- runTierMigrationCycle: (storage, trigger, options) => this.runTierMigrationCycle(storage, trigger, options),
780
- recordProcessedExtractionFingerprint: (storage, fingerprint, preloadedMeta) =>
781
- this.recordProcessedExtractionFingerprint(storage, fingerprint, preloadedMeta),
782
- });
802
+ this._extractionRunCoordinator = new ExtractionRunCoordinator(this.extractionRunDeps(() => this.buffer));
783
803
  }
784
804
  return this._extractionRunCoordinator;
785
805
  }
806
+
807
+ /** An extraction run coordinator bound to `buffer` — per drain task, so a
808
+ * claim-backed drain never shares the live buffer's mutable state. */
809
+ extractionRunCoordinatorForBuffer(buffer: SmartBuffer): ExtractionRunCoordinator {
810
+ return new ExtractionRunCoordinator(this.extractionRunDeps(() => buffer));
811
+ }
786
812
  private _consolidationRunCoordinator: ConsolidationRunCoordinator | undefined;
787
813
  private get consolidationRunCoordinator(): ConsolidationRunCoordinator {
788
814
  if (!this._consolidationRunCoordinator) {
@@ -239,6 +239,10 @@ function parseLease(raw: string): DrainLease | null {
239
239
  };
240
240
  }
241
241
 
242
+ /** Claim bodies `listPage` may read per requested entry: bounds one scan's
243
+ * I/O even when the directory is mostly empty tombstones. */
244
+ const LIST_PAGE_SCAN_FACTOR = 8;
245
+
242
246
  export class BufferDrainClaims {
243
247
  constructor(
244
248
  private readonly stateDir: string,
@@ -582,6 +586,57 @@ export class BufferDrainClaims {
582
586
  return out;
583
587
  }
584
588
 
589
+ /**
590
+ * Paged listing for bounded periodic scans: at most `limit` claims with
591
+ * pending turns, starting AFTER `afterName` (a raw entry name returned as
592
+ * `nextCursor` by a previous page — file-name order is stable, so a
593
+ * rotating cursor visits every claim fairly without ever materializing
594
+ * the whole directory's bodies). Empty tombstones never count toward the
595
+ * limit; the number of bodies read per call is bounded separately
596
+ * (`LIST_PAGE_SCAN_FACTOR` per requested entry), and the cursor advances
597
+ * past every scanned name so a long tombstone run is crossed over several
598
+ * pages instead of starving the pending claims behind it.
599
+ */
600
+ async listPage(afterName: string | undefined, limit: number): Promise<{ entries: DrainClaimListing[]; nextCursor?: string }> {
601
+ let names: string[];
602
+ try {
603
+ names = (await readdir(this.dir)).filter((name) => name.endsWith(".json") && !name.endsWith(".lease.json")).sort();
604
+ } catch (err) {
605
+ // SAFETY: readdir rejects with NodeJS system errors; only the ENOENT
606
+ // (no claims directory yet) case maps to an empty listing.
607
+ const errno = (err as NodeJS.ErrnoException | undefined)?.code;
608
+ if (errno === "ENOENT") return { entries: [] };
609
+ throw err;
610
+ }
611
+ const start = afterName === undefined ? 0 : names.findIndex((name) => name > afterName);
612
+ const out: DrainClaimListing[] = [];
613
+ // The cursor is the LAST CONSUMED entry name: the next page starts
614
+ // strictly after it, so the first unconsumed name is never skipped.
615
+ // Returning the first unconsumed name instead would make every page
616
+ // boundary permanently skip one claim.
617
+ let cursor: string | undefined;
618
+ const scanBudget = Math.max(limit, 1) * LIST_PAGE_SCAN_FACTOR;
619
+ let scanned = 0;
620
+ for (let index = start < 0 ? names.length : start; index < names.length; index += 1) {
621
+ if (out.length >= limit || scanned >= scanBudget) break;
622
+ const name = names[index]!;
623
+ scanned += 1;
624
+ cursor = name;
625
+ const claim = await this.readClaimBodyByKey(name);
626
+ if (!claim) continue;
627
+ const turnCount = claim.entry.turns.length + (claim.entry.retainedTurns?.length ?? 0);
628
+ if (turnCount <= 0) continue;
629
+ const lease = await this.readLease(claim.key);
630
+ out.push({
631
+ key: claim.key,
632
+ turnCount,
633
+ leased: lease !== null,
634
+ leaseExpired: lease !== null ? isLeaseExpired(lease) : true,
635
+ });
636
+ }
637
+ return { entries: out, nextCursor: cursor };
638
+ }
639
+
585
640
  private async readClaimBodyByKey(name: string): Promise<DrainClaimFile | null> {
586
641
  try {
587
642
  return parseBody(await this.io.read(path.join(this.dir, name)));