@iowarp/clio-coder 0.3.8 → 0.4.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 (552) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/NOTICE +33 -0
  3. package/README.md +12 -3
  4. package/dist/{acp-U67UHUK2.js → acp-G5WJBNCT.js} +13 -12
  5. package/dist/{agents-YU6SGALZ.js → agents-FMV2Q5G4.js} +41 -36
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-5ZPJOIVG.js → auth-3IDSJEIK.js} +18 -18
  8. package/dist/{builtins-C6JMZVV6.js → builtins-XCZWXSC7.js} +5 -5
  9. package/dist/{chunk-IFBNV6H6.js → chunk-2ANTL7MR.js} +3 -3
  10. package/dist/{chunk-5FR74PWO.js → chunk-2JDWVJND.js} +2 -2
  11. package/dist/{chunk-XWSF374K.js → chunk-2OQE55CK.js} +3 -3
  12. package/dist/{chunk-5H3GB5BO.js → chunk-32KWKNSF.js} +8 -384
  13. package/dist/{chunk-KTYTFRMB.js → chunk-36EJLSQQ.js} +34 -36
  14. package/dist/{chunk-FHJEP5SW.js → chunk-3BT2XMV4.js} +19 -13
  15. package/dist/chunk-3DPEIQKN.js +113 -0
  16. package/dist/{chunk-GU2UIAFZ.js → chunk-3URVFKWK.js} +7 -7
  17. package/dist/{chunk-WEH5XRJQ.js → chunk-3XML7CDN.js} +3 -3
  18. package/dist/chunk-42FMPA75.js +101 -0
  19. package/dist/{chunk-A2NJGIB3.js → chunk-5LXZXPKX.js} +2 -2
  20. package/dist/{chunk-VCBR6CU7.js → chunk-5PSMVOLM.js} +2 -2
  21. package/dist/{chunk-NMPKI6XL.js → chunk-6DB53AJS.js} +203 -25
  22. package/dist/{chunk-3BINW3FP.js → chunk-76ONBSIA.js} +2 -2
  23. package/dist/{chunk-26LEYJZH.js → chunk-7MCTRUCE.js} +2 -2
  24. package/dist/{chunk-TYPGUK6W.js → chunk-AB44T6BB.js} +111 -5
  25. package/dist/{chunk-K4XHGFR5.js → chunk-B7OBL7PK.js} +317 -721
  26. package/dist/{chunk-B5CSFE7B.js → chunk-BBVJUZHB.js} +2 -2
  27. package/dist/{chunk-EQ63NRB7.js → chunk-BBVYXMFO.js} +2 -2
  28. package/dist/{chunk-ZVJ5BLO2.js → chunk-BKFJHQCA.js} +154 -16
  29. package/dist/chunk-BKFM6EJV.js +462 -0
  30. package/dist/chunk-BMS5RKQY.js +27 -0
  31. package/dist/{chunk-ZNLWCMVZ.js → chunk-BPKCPIL7.js} +2 -2
  32. package/dist/{chunk-TLQJPP24.js → chunk-BUMFYQFY.js} +1394 -1349
  33. package/dist/{chunk-BNAZZHFG.js → chunk-BYP5D4HI.js} +1 -1
  34. package/dist/chunk-C2LTL2W6.js +2447 -0
  35. package/dist/{chunk-ME6CCNFO.js → chunk-CODPRO7Q.js} +8 -8
  36. package/dist/{chunk-E77JEWSD.js → chunk-CTJ4RNAA.js} +7 -37
  37. package/dist/{chunk-ODFEOB4F.js → chunk-CY6FY24N.js} +26 -8
  38. package/dist/{chunk-7RFXX52T.js → chunk-DQITNCXG.js} +642 -172
  39. package/dist/{chunk-TTHACPOM.js → chunk-DYJP44XW.js} +578 -117
  40. package/dist/{chunk-2HFZQUHL.js → chunk-F4CKPOEQ.js} +18 -8
  41. package/dist/{chunk-DGSYXYMX.js → chunk-FEFIFZTL.js} +3 -3
  42. package/dist/{chunk-GWS3VEIW.js → chunk-FWDFM5ZU.js} +24 -3
  43. package/dist/{chunk-MV3K5QF2.js → chunk-GCSMB2KY.js} +2 -2
  44. package/dist/chunk-GKF55TAZ.js +391 -0
  45. package/dist/{chunk-VWZOAB7K.js → chunk-GR5G2PVF.js} +9 -8
  46. package/dist/{chunk-4DGYLA73.js → chunk-GXNLGKAB.js} +80 -9
  47. package/dist/chunk-HHV2GANA.js +88 -0
  48. package/dist/{chunk-IIZWH4XA.js → chunk-HI63TFOG.js} +5 -4
  49. package/dist/{chunk-WLFILSD5.js → chunk-HJJTYUHX.js} +113 -83
  50. package/dist/{chunk-TT36MB5S.js → chunk-HLW2MRKE.js} +3 -1
  51. package/dist/{chunk-PMDBGQSJ.js → chunk-HWHKMHUA.js} +7 -7
  52. package/dist/chunk-HZHHCK24.js +1631 -0
  53. package/dist/{chunk-WSB3FPX7.js → chunk-I5VEOC6I.js} +39 -143
  54. package/dist/chunk-IBEBSCYA.js +564 -0
  55. package/dist/chunk-IQ7KR472.js +362 -0
  56. package/dist/{chunk-A3WNZD3P.js → chunk-J4W7KFM7.js} +949 -972
  57. package/dist/{chunk-TB5666IT.js → chunk-JDG2WCRO.js} +5 -5
  58. package/dist/{chunk-N22QMJKY.js → chunk-K5C3NCBD.js} +4 -4
  59. package/dist/{chunk-CGKSTWHD.js → chunk-K6BSR66V.js} +2 -1
  60. package/dist/{chunk-5C3AQNDW.js → chunk-KFZI4NIL.js} +216 -38
  61. package/dist/chunk-KMVISBZR.js +132 -0
  62. package/dist/{chunk-WXY7KU3G.js → chunk-LDQ2ZF2M.js} +2 -2
  63. package/dist/{chunk-XN3L4EYL.js → chunk-LQ3DZAMX.js} +3 -3
  64. package/dist/{chunk-U6MBIEMB.js → chunk-LY4S7GJC.js} +173 -144
  65. package/dist/{chunk-4SPRNWDE.js → chunk-MLKNTWH2.js} +19 -19
  66. package/dist/{chunk-MVVUPGPW.js → chunk-MXHC5QYU.js} +6 -6
  67. package/dist/chunk-NEKRRTYW.js +56 -0
  68. package/dist/{chunk-SPULKLCF.js → chunk-NHCZP4K7.js} +3 -3
  69. package/dist/chunk-NHLBIGRH.js +1506 -0
  70. package/dist/chunk-NQQH3YT7.js +302 -0
  71. package/dist/chunk-NYS75XW5.js +15 -0
  72. package/dist/{chunk-GN57SG4G.js → chunk-O4XIVISU.js} +10 -8
  73. package/dist/{chunk-EMYUUSFG.js → chunk-O6TL7WWY.js} +6 -6
  74. package/dist/chunk-OQBA45DZ.js +97 -0
  75. package/dist/{chunk-LU7P4LHA.js → chunk-P3FOHJT4.js} +2 -2
  76. package/dist/chunk-PMZCIOCJ.js +25 -0
  77. package/dist/{chunk-I4HZDVNP.js → chunk-PQEFIJ36.js} +2 -2
  78. package/dist/{chunk-J3YUBZWY.js → chunk-QBJA7R7N.js} +62 -6
  79. package/dist/chunk-QDC3K2U3.js +262 -0
  80. package/dist/{chunk-2HEJ2F35.js → chunk-QLFS5GO2.js} +22 -10
  81. package/dist/{chunk-7RGZWPB6.js → chunk-QLL7ILRG.js} +95 -32
  82. package/dist/{chunk-YS5VLNH5.js → chunk-QREDIESB.js} +6 -6
  83. package/dist/chunk-QSNYB6ZV.js +195 -0
  84. package/dist/{chunk-GOXNB3AO.js → chunk-RAPCMZL4.js} +75 -4
  85. package/dist/chunk-RKKLTLYB.js +45 -0
  86. package/dist/{chunk-P43ETTHK.js → chunk-SJ5ZKQ4S.js} +2 -2
  87. package/dist/{chunk-GPIEI3LY.js → chunk-SP2RXXYO.js} +6 -54
  88. package/dist/chunk-SUCTJL45.js +45 -0
  89. package/dist/{chunk-DYIM5TJT.js → chunk-SUW5DORT.js} +263 -7
  90. package/dist/chunk-T56WDKA5.js +183 -0
  91. package/dist/chunk-TVHHYFHE.js +255 -0
  92. package/dist/{chunk-FJ3H4MN5.js → chunk-TZ3SGWZZ.js} +3 -3
  93. package/dist/{chunk-MXKJU4JB.js → chunk-U77AMWDL.js} +91 -10
  94. package/dist/{chunk-5DHKRSMQ.js → chunk-ULC6OTWO.js} +11 -7
  95. package/dist/{chunk-RWSI4YD7.js → chunk-UM7N4G5A.js} +33 -12
  96. package/dist/{chunk-FCSXB6T2.js → chunk-UOSL25KY.js} +14 -2
  97. package/dist/{chunk-IGWKHNIQ.js → chunk-UXMFQ54G.js} +44 -37
  98. package/dist/{chunk-HFSBBKSQ.js → chunk-V5DHCITQ.js} +171 -3
  99. package/dist/{chunk-5WIGXA4T.js → chunk-VAZSBTKF.js} +111 -4
  100. package/dist/{chunk-VHN4MY6O.js → chunk-VEO4AP2K.js} +2 -2
  101. package/dist/{chunk-IJ7RPIYJ.js → chunk-VFA6GDY5.js} +65 -4
  102. package/dist/{chunk-PT7HYKEM.js → chunk-VO2LKSTM.js} +2 -2
  103. package/dist/chunk-VO67MWHC.js +75 -0
  104. package/dist/{chunk-XK56QHLX.js → chunk-VPKWYKEY.js} +19 -5
  105. package/dist/{chunk-TANS5ZJS.js → chunk-VYMXRQI6.js} +36 -22
  106. package/dist/{chunk-WWCZ5F23.js → chunk-W5VSYASO.js} +77 -16
  107. package/dist/{chunk-WNIJTQQK.js → chunk-WZR7K7ZX.js} +72 -116
  108. package/dist/{chunk-5Q2VVUKB.js → chunk-X3YGUTOB.js} +4 -4
  109. package/dist/chunk-X75E3D2N.js +686 -0
  110. package/dist/{chunk-VAWNZU7Z.js → chunk-YDFRH54B.js} +4 -4
  111. package/dist/chunk-YJX4SHTD.js +40 -0
  112. package/dist/{chunk-ZI647VB5.js → chunk-YPI3QQCF.js} +2 -2
  113. package/dist/chunk-Z2RR6MAK.js +127 -0
  114. package/dist/{chunk-FBVTI2TJ.js → chunk-Z4TXYIEG.js} +12 -131
  115. package/dist/cli/index.js +47 -36
  116. package/dist/{clio-QVTYJ57A.js → clio-2JXHBBY5.js} +7 -7
  117. package/dist/{code-nav-FGGFIE7L.js → code-nav-3YYRMYNF.js} +8 -8
  118. package/dist/{compile-cache-CVJMMODC.js → compile-cache-7FPE6PS3.js} +3 -3
  119. package/dist/{components-ZFA3SAER.js → components-RYZV4JGP.js} +5 -5
  120. package/dist/{config-LW5IJFQN.js → config-QZPCMYSO.js} +99 -63
  121. package/dist/{configure-7XIZCOU4.js → configure-TEGEBYCA.js} +23 -22
  122. package/dist/{context-Y6Y7QPR6.js → context-AV7OEZ4D.js} +12 -12
  123. package/dist/{context-L3WL3X7K.js → context-E6H5RNMC.js} +56 -47
  124. package/dist/{context-N52ZA626.js → context-GSXUE4CT.js} +29 -27
  125. package/dist/{context-clear-MBQRLSDQ.js → context-clear-SHIBYK6T.js} +55 -46
  126. package/dist/{context-index-HVMFQHK3.js → context-index-HNG3MOME.js} +2 -2
  127. package/dist/{context-working-set-GS6DSO7F.js → context-working-set-5ZGKPGZQ.js} +13 -13
  128. package/dist/{dispatch-runner-22ZCNOM3.js → dispatch-runner-EFMJT4LD.js} +93 -64
  129. package/dist/{docs-7LQ23DLM.js → docs-23KQS3XK.js} +5 -5
  130. package/dist/doctor-QOA5FNY5.js +313 -0
  131. package/dist/{eval-BEC2WHDA.js → eval-TFBYQH4H.js} +2032 -156
  132. package/dist/eval-inventory-SXH7PDKX.js +316 -0
  133. package/dist/{evidence-REJUMSKM.js → evidence-ERGESKGN.js} +203 -48
  134. package/dist/{evolve-PY5ZBA5K.js → evolve-VDXTSYCJ.js} +52 -43
  135. package/dist/{extensions-HVKU65YU.js → extensions-7BGBHN57.js} +13 -7
  136. package/dist/{fleet-7WZEWRFA.js → fleet-2RRVDF2V.js} +228 -108
  137. package/dist/{fleet-commands-UVHWM76J.js → fleet-commands-VJ726XIA.js} +11 -11
  138. package/dist/fleet-decisions-EPAPM3XJ.js +157 -0
  139. package/dist/{fleet-graph-6ULH7PES.js → fleet-graph-JF5QOATM.js} +18 -15
  140. package/dist/fleet-inspect-VLY4S7QM.js +442 -0
  141. package/dist/{fleet-preflight-J53T6CCE.js → fleet-preflight-AIZUEJOY.js} +5 -5
  142. package/dist/{fleet-validate-72PC4SLA.js → fleet-validate-AJRPDMDV.js} +22 -19
  143. package/dist/fleet-verify-JFEL2L3H.js +175 -0
  144. package/dist/fleet-view-ZCON35AG.js +102 -0
  145. package/dist/{init-OG3TPGQG.js → init-DN2WWLFE.js} +72 -62
  146. package/dist/install-XGLBQY5E.js +13 -0
  147. package/dist/interop-OZBKXAYL.js +114 -0
  148. package/dist/{library-CNTMPLRF.js → library-YWZG7IMW.js} +21 -18
  149. package/dist/{memory-6IS7F275.js → memory-I4C4HMLW.js} +54 -45
  150. package/dist/{models-ENRJDA5W.js → models-CEYXJBO6.js} +33 -30
  151. package/dist/{monitor-XLDVO7TN.js → monitor-NZ6GCI3P.js} +59 -52
  152. package/dist/{orchestrator-6KSPYRHA.js → orchestrator-GCGQ4N5I.js} +7827 -7328
  153. package/dist/panes-HMABYVO4.js +58 -0
  154. package/dist/panes-KY6W3V2E.js +103 -0
  155. package/dist/{paths-DBXMZMDU.js → paths-II4K7DNR.js} +5 -5
  156. package/dist/{reset-RZ4ER727.js → reset-DQ6FGCSH.js} +13 -11
  157. package/dist/resources-BB3MVJMD.js +111 -0
  158. package/dist/{run-Y2CNK5RU.js → run-H2GQDUER.js} +119 -87
  159. package/dist/{share-A55GYP6Z.js → share-GTJN6A5O.js} +20 -17
  160. package/dist/{skills-ALC5J6AT.js → skills-L55TEW6R.js} +33 -24
  161. package/dist/{skills-eval-JPBEBYQU.js → skills-eval-XVXPH2JI.js} +67 -56
  162. package/dist/skills-inventory-S4MXPJFV.js +126 -0
  163. package/dist/slash-commands-ZSGASKJC.js +77 -0
  164. package/dist/{steer-GGWFUJUD.js → steer-RZGSCY4R.js} +4 -4
  165. package/dist/{support-MIETYA5E.js → support-PKEUNNQL.js} +6 -6
  166. package/dist/{targets-VGNXIR3S.js → targets-NCPZ644J.js} +68 -40
  167. package/dist/{terminal-lease-WOBR64YA.js → terminal-lease-44SV3YCN.js} +6 -4
  168. package/dist/tools-DAF3DI3C.js +27 -0
  169. package/dist/{trace-PNCASAXC.js → trace-FYVW2MQA.js} +207 -10
  170. package/dist/tui-primitives-2AKXQNZK.js +13 -0
  171. package/dist/{uninstall-ZJF5H5ZN.js → uninstall-DW2PNOIC.js} +5 -5
  172. package/dist/{upgrade-FUSUAGHR.js → upgrade-3XPP6OQL.js} +27 -24
  173. package/dist/{usage-N4MKVHKD.js → usage-3NLHGTU2.js} +114 -62
  174. package/dist/{verifiers-YAWOJ3H2.js → verifiers-SSQONKRT.js} +172 -13
  175. package/dist/{verify-LTDHYBGY.js → verify-3U6J7FZI.js} +10 -10
  176. package/dist/{web-fetch-2YHJ3KTG.js → web-fetch-S7RR6GZ7.js} +3 -3
  177. package/dist/{wiki-generate-6M7GHTBJ.js → wiki-generate-CEHYGPGQ.js} +75 -65
  178. package/dist/with-panes-MKB46MPQ.js +782 -0
  179. package/dist/worker/entry.js +106 -75
  180. package/docs/README.md +3 -2
  181. package/docs/acp.md +24 -3
  182. package/docs/alcf-provider.md +1 -1
  183. package/docs/architecture.md +2 -2
  184. package/docs/artifact-versions.md +9 -1
  185. package/docs/built-in-agents.md +1 -1
  186. package/docs/capacity-and-scheduling.md +62 -3
  187. package/docs/commands-and-modes.md +31 -2
  188. package/docs/configuration-and-targets.md +69 -12
  189. package/docs/context-engine.md +63 -4
  190. package/docs/development-pipeline.md +19 -0
  191. package/docs/dispatch-typed-intent.md +385 -0
  192. package/docs/documentation-coverage.md +5 -5
  193. package/docs/documentation-guide.md +1 -1
  194. package/docs/environment-variables.md +3 -0
  195. package/docs/eval-runner.md +262 -11
  196. package/docs/evals-internal.md +72 -2
  197. package/docs/evidence-and-memory.md +12 -11
  198. package/docs/evolution.md +1 -1
  199. package/docs/exit-codes-and-output.md +1 -1
  200. package/docs/extensions-and-sharing.md +27 -1
  201. package/docs/fleet-dispatch.md +25 -4
  202. package/docs/installation-and-lifecycle.md +15 -2
  203. package/docs/middleware-and-components.md +1 -1
  204. package/docs/model-catalog.md +10 -1
  205. package/docs/observability.md +55 -4
  206. package/docs/proactive-memory.md +127 -14
  207. package/docs/prompt-envelope-and-tools.md +19 -1
  208. package/docs/provider-adapter-cookbook.md +1 -1
  209. package/docs/release-cut-checklist.md +19 -3
  210. package/docs/safety-model.md +2 -2
  211. package/docs/scientific-validation.md +3 -3
  212. package/docs/session-lifecycle.md +1 -1
  213. package/docs/skills-marketplace.md +1 -1
  214. package/docs/tool-usage.md +18 -8
  215. package/docs/trace-store.md +1 -1
  216. package/docs/troubleshooting.md +88 -1
  217. package/docs/tui-design.md +1 -1
  218. package/docs/worker-dispatch-mechanics.md +1 -1
  219. package/package.json +5 -2
  220. package/src/cli/acp.ts +6 -2
  221. package/src/cli/agents.ts +1 -1
  222. package/src/cli/argv.ts +25 -0
  223. package/src/cli/config-inspect.ts +33 -6
  224. package/src/cli/config.ts +1 -1
  225. package/src/cli/configure.ts +23 -21
  226. package/src/cli/doctor-panes.ts +124 -0
  227. package/src/cli/doctor-state-size.ts +82 -0
  228. package/src/cli/doctor-toolchain.ts +57 -0
  229. package/src/cli/doctor.ts +22 -1
  230. package/src/cli/eval-inventory.ts +436 -0
  231. package/src/cli/eval.ts +93 -16
  232. package/src/cli/evidence-detail.ts +88 -0
  233. package/src/cli/evidence-inventory.ts +183 -0
  234. package/src/cli/evidence.ts +30 -5
  235. package/src/cli/extensions.ts +5 -1
  236. package/src/cli/fleet-decisions.ts +69 -0
  237. package/src/cli/fleet-inspect.ts +334 -0
  238. package/src/cli/fleet-verify.ts +133 -0
  239. package/src/cli/fleet-view.ts +810 -0
  240. package/src/cli/fleet.ts +179 -39
  241. package/src/cli/index.ts +14 -2
  242. package/src/cli/interop-inspect.ts +128 -0
  243. package/src/cli/interop.ts +34 -0
  244. package/src/cli/panes.ts +35 -0
  245. package/src/cli/reset.ts +5 -2
  246. package/src/cli/run.ts +58 -0
  247. package/src/cli/skills-inventory.ts +185 -0
  248. package/src/cli/skills.ts +16 -13
  249. package/src/cli/targets.ts +44 -13
  250. package/src/cli/tools.ts +321 -0
  251. package/src/cli/trace-inspect.ts +252 -0
  252. package/src/cli/trace.ts +85 -5
  253. package/src/cli/usage.ts +63 -14
  254. package/src/cli/verifiers-inspect.ts +347 -0
  255. package/src/cli/verifiers.ts +9 -0
  256. package/src/core/bus-events.ts +33 -1
  257. package/src/core/cache-telemetry.ts +42 -0
  258. package/src/core/config.ts +67 -0
  259. package/src/core/defaults.ts +124 -8
  260. package/src/core/endpoint-key.ts +27 -0
  261. package/src/core/residency-target-key.ts +25 -0
  262. package/src/core/response-schema.ts +80 -6
  263. package/src/core/theme-token-hex.ts +43 -0
  264. package/src/core/tool-names.ts +2 -1
  265. package/src/core/xdg.ts +1 -1
  266. package/src/domains/agents/fleets/build-review.md +0 -3
  267. package/src/domains/agents/fleets/build-test.md +0 -3
  268. package/src/domains/agents/result-contract-filesystem.ts +32 -0
  269. package/src/domains/agents/result-contract.ts +164 -35
  270. package/src/domains/config/classify.ts +6 -0
  271. package/src/domains/context/codewiki/coordinator.ts +12 -4
  272. package/src/domains/dispatch/admission-error.ts +9 -0
  273. package/src/domains/dispatch/admission.ts +52 -14
  274. package/src/domains/dispatch/capacity-lease.ts +118 -9
  275. package/src/domains/dispatch/contract.ts +11 -0
  276. package/src/domains/dispatch/council-topology.ts +398 -0
  277. package/src/domains/dispatch/execution-plan.ts +44 -4
  278. package/src/domains/dispatch/extension.ts +378 -82
  279. package/src/domains/dispatch/fleet-node-prompt.ts +62 -0
  280. package/src/domains/dispatch/fleet-plan.ts +7 -2
  281. package/src/domains/dispatch/fleet-run.ts +87 -4
  282. package/src/domains/dispatch/gate-decisions.ts +11 -1
  283. package/src/domains/dispatch/gate-role-prompts.ts +9 -0
  284. package/src/domains/dispatch/gate-topology.ts +289 -0
  285. package/src/domains/dispatch/heartbeat.ts +32 -8
  286. package/src/domains/dispatch/index.ts +22 -0
  287. package/src/domains/dispatch/intent-compatibility.ts +330 -0
  288. package/src/domains/dispatch/intent.ts +85 -1
  289. package/src/domains/dispatch/orphan-recovery.ts +5 -0
  290. package/src/domains/dispatch/reservation-store.ts +139 -11
  291. package/src/domains/dispatch/run-event-journal-bridge.ts +149 -0
  292. package/src/domains/dispatch/run-event-journal.ts +598 -0
  293. package/src/domains/dispatch/state.ts +49 -1
  294. package/src/domains/dispatch/types.ts +13 -0
  295. package/src/domains/dispatch/validation.ts +33 -8
  296. package/src/domains/dispatch/worker-spawn.ts +25 -11
  297. package/src/domains/dispatch/write-boundary-enforcer.ts +20 -3
  298. package/src/domains/dispatch/write-boundary.ts +62 -1
  299. package/src/domains/eval/artifacts/store.ts +62 -0
  300. package/src/domains/eval/compare/behavioral.ts +224 -0
  301. package/src/domains/eval/compare/compare.ts +342 -2
  302. package/src/domains/eval/compare/envelope.ts +128 -0
  303. package/src/domains/eval/compare/gates.ts +24 -6
  304. package/src/domains/eval/compare/thresholds.ts +30 -3
  305. package/src/domains/eval/execution-provenance.ts +240 -0
  306. package/src/domains/eval/inventory.ts +113 -0
  307. package/src/domains/eval/metrics/aggregate.ts +136 -0
  308. package/src/domains/eval/metrics/call-ledger-stream.ts +112 -0
  309. package/src/domains/eval/metrics/tracked.ts +413 -0
  310. package/src/domains/eval/provenance.ts +117 -0
  311. package/src/domains/eval/reports/comparison.ts +128 -0
  312. package/src/domains/eval/reports/junit.ts +17 -3
  313. package/src/domains/eval/reports/markdown.ts +3 -3
  314. package/src/domains/eval/reports/text.ts +14 -0
  315. package/src/domains/eval/run-compare.ts +20 -0
  316. package/src/domains/eval/runners/clio-run.ts +127 -0
  317. package/src/domains/eval/runners/external-command.ts +28 -3
  318. package/src/domains/eval/schema/adapter.ts +111 -0
  319. package/src/domains/eval/schema/artifact.ts +20 -0
  320. package/src/domains/eval/schema/behavioral-metrics.ts +204 -0
  321. package/src/domains/eval/schema/behavioral.ts +520 -0
  322. package/src/domains/eval/schema/execution-envelope.ts +194 -0
  323. package/src/domains/eval/schema/serving.ts +105 -0
  324. package/src/domains/eval/schema/suite.ts +38 -8
  325. package/src/domains/eval/schema/validate.ts +58 -3
  326. package/src/domains/eval/schema/verdict.ts +237 -0
  327. package/src/domains/eval/suites/resolve.ts +2 -0
  328. package/src/domains/eval/suites/run.ts +264 -33
  329. package/src/domains/eval/verifiers/command.ts +2 -1
  330. package/src/domains/eval/workspaces/temp-copy.ts +145 -13
  331. package/src/domains/evidence/build.ts +2 -13
  332. package/src/domains/evidence/eval.ts +2 -12
  333. package/src/domains/evidence/findings-markdown.ts +33 -0
  334. package/src/domains/evidence/run-trust.ts +7 -113
  335. package/src/domains/evidence/store.ts +6 -0
  336. package/src/domains/evidence/trust-projection.ts +2 -2
  337. package/src/domains/extensions/compatibility.ts +285 -0
  338. package/src/domains/extensions/discovery.ts +38 -3
  339. package/src/domains/extensions/resources.ts +1 -1
  340. package/src/domains/extensions/state.ts +12 -3
  341. package/src/domains/extensions/types.ts +2 -0
  342. package/src/domains/lifecycle/doctor.ts +69 -1
  343. package/src/domains/memory/index.ts +14 -1
  344. package/src/domains/memory/task-bank-promotion.ts +64 -0
  345. package/src/domains/memory/task-memory-policy.ts +82 -17
  346. package/src/domains/memory/task-memory-spend.ts +131 -0
  347. package/src/domains/memory/task-memory-status.ts +7 -0
  348. package/src/domains/memory/task-memory-telemetry.ts +3 -0
  349. package/src/domains/middleware/index.ts +1 -0
  350. package/src/domains/middleware/memory-intervention.ts +97 -21
  351. package/src/domains/middleware/memory-step-endpoint.ts +71 -0
  352. package/src/domains/mux/contract.ts +434 -0
  353. package/src/domains/mux/detect.ts +158 -0
  354. package/src/domains/mux/extension.ts +47 -0
  355. package/src/domains/mux/index.ts +96 -0
  356. package/src/domains/mux/manifest.ts +6 -0
  357. package/src/domains/mux/operations.ts +164 -0
  358. package/src/domains/mux/pane-registry.ts +90 -0
  359. package/src/domains/mux/protocol.ts +49 -0
  360. package/src/domains/mux/socket-client.ts +816 -0
  361. package/src/domains/mux/types.ts +222 -0
  362. package/src/domains/mux/viewer-command.ts +59 -0
  363. package/src/domains/mux/yazi/assets/init.lua +2 -0
  364. package/src/domains/mux/yazi/assets/plugins/git.yazi/LICENSE +21 -0
  365. package/src/domains/mux/yazi/assets/plugins/git.yazi/README.md +78 -0
  366. package/src/domains/mux/yazi/assets/plugins/git.yazi/main.lua +255 -0
  367. package/src/domains/mux/yazi/assets/plugins/git.yazi/types.lua +12 -0
  368. package/src/domains/mux/yazi/assets/yazi.toml +17 -0
  369. package/src/domains/mux/yazi/event-stream.ts +180 -0
  370. package/src/domains/mux/yazi/profile.ts +299 -0
  371. package/src/domains/mux/yazi/session.ts +228 -0
  372. package/src/domains/mux/yazi/theme.ts +30 -0
  373. package/src/domains/observability/background-memory-usage.ts +140 -0
  374. package/src/domains/observability/cost.ts +22 -1
  375. package/src/domains/observability/index.ts +9 -0
  376. package/src/domains/observability/out-of-turn-usage.ts +51 -2
  377. package/src/domains/observability/trace-store.ts +234 -2
  378. package/src/domains/prompts/compiler.ts +100 -13
  379. package/src/domains/providers/endpoint-capacity.ts +228 -0
  380. package/src/domains/providers/endpoint-slots-store.ts +189 -0
  381. package/src/domains/providers/extension.ts +20 -3
  382. package/src/domains/providers/index.ts +32 -0
  383. package/src/domains/providers/model-runtime-capabilities.ts +32 -0
  384. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +243 -1
  385. package/src/domains/providers/runtime-resolution.ts +8 -1
  386. package/src/domains/providers/runtimes/boot-manifest.ts +1 -0
  387. package/src/domains/providers/runtimes/builtins.ts +2 -0
  388. package/src/domains/providers/runtimes/common/probe-helpers.ts +31 -9
  389. package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +1 -1
  390. package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +1 -1
  391. package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +1 -1
  392. package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +1 -1
  393. package/src/domains/providers/runtimes/local-native/llamacpp.ts +4 -1
  394. package/src/domains/providers/runtimes/local-native/lmstudio.ts +4 -1
  395. package/src/domains/providers/runtimes/local-native/ollama-native.ts +6 -1
  396. package/src/domains/providers/runtimes/protocol/litellm.ts +375 -0
  397. package/src/domains/providers/support.ts +1 -0
  398. package/src/domains/providers/target-model-cache.ts +124 -0
  399. package/src/domains/providers/types/capability-flags.ts +2 -0
  400. package/src/domains/providers/types/target-descriptor.ts +2 -0
  401. package/src/domains/resources/index.ts +3 -0
  402. package/src/domains/resources/prompts/loader.ts +95 -33
  403. package/src/domains/resources/skills/loader.ts +33 -0
  404. package/src/domains/safety/action-classifier.ts +6 -0
  405. package/src/domains/safety/call-target.ts +52 -0
  406. package/src/domains/safety/run-effects.ts +35 -4
  407. package/src/domains/session/context-accounting.ts +52 -1
  408. package/src/domains/session/context-ledger.ts +37 -13
  409. package/src/domains/session/index.ts +6 -0
  410. package/src/domains/session/prompt-cache.ts +140 -0
  411. package/src/domains/session/prompt-manifest.ts +42 -0
  412. package/src/domains/toolchain/archive.ts +175 -0
  413. package/src/domains/toolchain/contract.ts +28 -0
  414. package/src/domains/toolchain/extension.ts +47 -0
  415. package/src/domains/toolchain/index.ts +39 -0
  416. package/src/domains/toolchain/install.ts +327 -0
  417. package/src/domains/toolchain/manifest.ts +8 -0
  418. package/src/domains/toolchain/paths.ts +34 -0
  419. package/src/domains/toolchain/registry.ts +265 -0
  420. package/src/domains/toolchain/remove.ts +218 -0
  421. package/src/domains/toolchain/resolve.ts +182 -0
  422. package/src/domains/toolchain/types.ts +113 -0
  423. package/src/domains/toolchain/version.ts +88 -0
  424. package/src/engine/acp/adapter.ts +18 -3
  425. package/src/engine/acp/server.ts +413 -70
  426. package/src/engine/acp/types.ts +19 -1
  427. package/src/engine/ai.ts +35 -0
  428. package/src/engine/apis/llamacpp-residency.ts +55 -3
  429. package/src/engine/apis/lmstudio.ts +25 -5
  430. package/src/engine/apis/ollama-native.ts +2 -1
  431. package/src/engine/apis/openai-completions.ts +80 -17
  432. package/src/engine/apis/residency-lock.ts +3 -1
  433. package/src/engine/apis/residency.ts +34 -1
  434. package/src/engine/claude/sdk-module.ts +98 -0
  435. package/src/engine/claude/sdk-runtime.ts +19 -11
  436. package/src/engine/provider-payload.ts +29 -1
  437. package/src/engine/tui-primitives.ts +21 -0
  438. package/src/engine/tui.ts +1 -0
  439. package/src/engine/worker-runtime.ts +2 -13
  440. package/src/entry/boot-options.ts +2 -0
  441. package/src/entry/orchestrator.ts +279 -35
  442. package/src/entry/panes-activation.ts +31 -0
  443. package/src/entry/with-panes.ts +20 -0
  444. package/src/interactive/chat-loop-messages.ts +26 -7
  445. package/src/interactive/chat-loop.ts +318 -41
  446. package/src/interactive/chat-panel.ts +62 -8
  447. package/src/interactive/clio-editor.ts +45 -8
  448. package/src/interactive/context-activity.ts +5 -1
  449. package/src/interactive/context-meter.ts +1 -1
  450. package/src/interactive/context-overlay.ts +41 -10
  451. package/src/interactive/cost-overlay.ts +66 -6
  452. package/src/interactive/council-grid.ts +1 -3
  453. package/src/interactive/council.ts +11 -0
  454. package/src/interactive/dispatch-board.ts +102 -20
  455. package/src/interactive/fleet-run-preview.ts +41 -15
  456. package/src/interactive/handoff-round.ts +41 -2
  457. package/src/interactive/interactive-application.ts +177 -7
  458. package/src/interactive/interactive-input-runtime.ts +15 -0
  459. package/src/interactive/interactive-presentation.ts +4 -0
  460. package/src/interactive/interactive-shell.ts +20 -17
  461. package/src/interactive/interactive-slash-runtime.ts +63 -10
  462. package/src/interactive/memory-overlay.ts +9 -0
  463. package/src/interactive/modal-marker.ts +170 -0
  464. package/src/interactive/mutation-preview.ts +295 -0
  465. package/src/interactive/mux-bridge.ts +214 -0
  466. package/src/interactive/overlay-frame.ts +58 -2
  467. package/src/interactive/overlay-general-openers.ts +17 -0
  468. package/src/interactive/overlay-key-routing.ts +52 -3
  469. package/src/interactive/overlay-lifecycle.ts +56 -7
  470. package/src/interactive/overlay-model-selectors.ts +40 -3
  471. package/src/interactive/overlay-permission-lifecycle.ts +112 -24
  472. package/src/interactive/overlay-session-lifecycle.ts +73 -9
  473. package/src/interactive/overlay-transitions.ts +18 -4
  474. package/src/interactive/overlays/agents.ts +1 -0
  475. package/src/interactive/overlays/ask-user.ts +227 -49
  476. package/src/interactive/overlays/auth-dialog.ts +1 -0
  477. package/src/interactive/overlays/context-reset.ts +1 -0
  478. package/src/interactive/overlays/cwd-fallback.ts +1 -0
  479. package/src/interactive/overlays/decisions.ts +11 -11
  480. package/src/interactive/overlays/extensions.ts +1 -0
  481. package/src/interactive/overlays/fleet-run-approval.ts +1 -0
  482. package/src/interactive/overlays/handoff-review.ts +1 -0
  483. package/src/interactive/overlays/help-reference.ts +6 -0
  484. package/src/interactive/overlays/interop.ts +1 -0
  485. package/src/interactive/overlays/library-install-confirm.ts +1 -0
  486. package/src/interactive/overlays/library-tabs.ts +28 -0
  487. package/src/interactive/overlays/list-overlay.ts +10 -1
  488. package/src/interactive/overlays/message-picker.ts +1 -0
  489. package/src/interactive/overlays/model-scope.ts +86 -0
  490. package/src/interactive/overlays/model-selector.ts +1 -0
  491. package/src/interactive/overlays/prompts.ts +12 -1
  492. package/src/interactive/overlays/session-selector.ts +1 -0
  493. package/src/interactive/overlays/settings-sections.ts +30 -0
  494. package/src/interactive/overlays/settings.ts +614 -45
  495. package/src/interactive/overlays/side-question.ts +1 -0
  496. package/src/interactive/overlays/skills-hub.ts +3 -11
  497. package/src/interactive/overlays/tree-selector.ts +1 -0
  498. package/src/interactive/pane-policy.ts +46 -0
  499. package/src/interactive/panes-runtime.ts +292 -0
  500. package/src/interactive/permission-hint.ts +34 -2
  501. package/src/interactive/permission-overlay.ts +159 -9
  502. package/src/interactive/prewarm.ts +197 -0
  503. package/src/interactive/render-trace.ts +162 -15
  504. package/src/interactive/renderers/compaction-summary.ts +29 -0
  505. package/src/interactive/renderers/tool-execution.ts +4 -0
  506. package/src/interactive/renderers/worker-entry.ts +122 -14
  507. package/src/interactive/side-question.ts +58 -1
  508. package/src/interactive/slash-commands.ts +251 -15
  509. package/src/interactive/status/controller.ts +11 -0
  510. package/src/interactive/status/state-machine.ts +54 -2
  511. package/src/interactive/status/types.ts +7 -0
  512. package/src/interactive/tasks-overlay.ts +1 -0
  513. package/src/interactive/terminal-lease.ts +2 -0
  514. package/src/interactive/theme/tokens.ts +3 -14
  515. package/src/interactive/turn-context.ts +346 -33
  516. package/src/interactive/turn-persistence.ts +14 -4
  517. package/src/interactive/turn-prewarm.ts +364 -0
  518. package/src/interactive/turn-queues.ts +7 -4
  519. package/src/interactive/turn-runtime.ts +8 -1
  520. package/src/interactive/turn-state.ts +23 -0
  521. package/src/interactive/view/artifacts.ts +109 -1
  522. package/src/interactive/view/view-overlay.ts +29 -3
  523. package/src/interactive/watch-pane.ts +152 -0
  524. package/src/interactive/worker-progress.ts +7 -1
  525. package/src/interactive/worker-receipts.ts +19 -1
  526. package/src/interactive/worker-stream.ts +5 -0
  527. package/src/interactive/yazi-bridge.ts +444 -0
  528. package/src/tools/ask-user.ts +43 -2
  529. package/src/tools/bootstrap.ts +26 -2
  530. package/src/tools/builtin-tool-catalog.ts +15 -0
  531. package/src/tools/compete-worktrees.ts +83 -2
  532. package/src/tools/core-bootstrap.ts +2 -1
  533. package/src/tools/dispatch-admission.ts +14 -3
  534. package/src/tools/dispatch-arguments.ts +20 -20
  535. package/src/tools/dispatch-plan.ts +17 -9
  536. package/src/tools/dispatch-run-events.ts +134 -19
  537. package/src/tools/dispatch-runner.ts +29 -7
  538. package/src/tools/dispatch-scout.ts +1 -1
  539. package/src/tools/dispatch-types.ts +15 -3
  540. package/src/tools/dispatch.ts +1 -1
  541. package/src/tools/executables.ts +17 -14
  542. package/src/tools/observation.ts +54 -4
  543. package/src/tools/panes-surface.ts +38 -0
  544. package/src/tools/panes.ts +112 -0
  545. package/src/tools/policy.ts +10 -1
  546. package/src/tools/presentation.ts +1 -0
  547. package/src/tools/registry.ts +16 -0
  548. package/dist/chunk-AOCYTWAV.js +0 -449
  549. package/dist/chunk-HLE42MG7.js +0 -37
  550. package/dist/chunk-HWUFFB6L.js +0 -83
  551. package/dist/chunk-JOZYP4GM.js +0 -279
  552. package/dist/doctor-M7YEDGAE.js +0 -91
@@ -1,5 +1,6 @@
1
1
  import { randomBytes } from "node:crypto";
2
2
  import { withStateFileLockSync } from "../../core/state-file-lock.js";
3
+ import { endpointLabel } from "../providers/endpoint-capacity.js";
3
4
  import {
4
5
  acquireCapacityLease,
5
6
  activeCapacityDrainUnsafe,
@@ -7,21 +8,38 @@ import {
7
8
  type CapacityLimits,
8
9
  type CapacityStateFile,
9
10
  capacityStateLockPath,
11
+ describeEndpointCapacityHolders,
12
+ endpointCapacityRemedy,
10
13
  readCapacityStateUnsafe,
11
14
  writeCapacityStateUnsafe,
12
15
  } from "./capacity-lease.js";
16
+ import { COUNCIL_MIN_MEMBERS } from "./gate-role-prompts.js";
13
17
 
14
18
  const MAX_RESERVATION_RECORDS = 500;
15
19
  export const DEFAULT_RESERVATION_TTL_MS = 15 * 60_000;
16
20
 
17
- export type ReservationTopology = "parallel" | "detached" | "sequential" | "pipeline" | "review" | "compete";
21
+ /**
22
+ * `council` is carried rather than flattened into `parallel` because it is the
23
+ * one topology with a floor on its own width. Every other plan can answer a
24
+ * capacity denial by dispatching fewer at once; a council of two cannot, and a
25
+ * denial that tells it to is advice it cannot take.
26
+ */
27
+ export type ReservationTopology =
28
+ | "parallel"
29
+ | "detached"
30
+ | "sequential"
31
+ | "pipeline"
32
+ | "review"
33
+ | "compete"
34
+ | "council";
18
35
  export type ReservationMemberStatus = "held" | "consumed" | "released";
19
36
  export type ReservationStatus = "active" | "released" | "rolled_back" | "expired";
20
37
 
21
38
  /**
22
- * A reservation holds three scarce things and nothing else: a global
23
- * concurrency slot, a per-node slot, and a budget upper bound. Node identity
24
- * matters only because slots are per-node. Agent, target, model, and runtime
39
+ * A reservation holds four scarce things and nothing else: a global
40
+ * concurrency slot, a per-node slot, an inference-endpoint slot, and a budget
41
+ * upper bound. Node and endpoint identity matter only because slots bind on
42
+ * those dimensions. Agent, target, model, and runtime
25
43
  * identity are route identity, which the failover envelope owns
26
44
  * (`assertRouteWithinApprovedEnvelope`); pinning them here made a
27
45
  * plan-approved dispatch unable to fail over at all.
@@ -30,6 +48,7 @@ export interface ReservationPlanTask {
30
48
  memberId: string;
31
49
  wave: number;
32
50
  nodeId: string;
51
+ endpointKey?: string;
33
52
  costUpperBoundUsd: number;
34
53
  }
35
54
 
@@ -54,17 +73,33 @@ export interface DispatchReservationRecord {
54
73
  export interface ReservationCapacitySnapshot {
55
74
  global: { active: number; limit: number };
56
75
  nodes: Readonly<Record<string, { active: number; limit: number }>>;
76
+ endpoints: Readonly<Record<string, { active: number; limit: number; leases?: number; foregroundStreams?: number }>>;
57
77
  budget: { currentUsd: number; ceilingUsd: number };
58
78
  }
59
79
 
60
80
  export interface ReservationAllocation {
61
81
  globalSlots: number;
62
82
  nodeSlots: Readonly<Record<string, number>>;
83
+ endpointSlots: Readonly<Record<string, number>>;
63
84
  budgetUsd: number;
64
85
  }
65
86
 
66
87
  export type ReservationPlanResult = { ok: true; allocation: ReservationAllocation } | { ok: false; reason: string };
67
88
 
89
+ function endpointCapacityDenial(input: {
90
+ endpointKey: string;
91
+ limit: number;
92
+ used: number;
93
+ requested: number;
94
+ leases: number;
95
+ reservations: number;
96
+ foregroundStreams: number;
97
+ topology?: ReservationTopology;
98
+ }): string {
99
+ const remedy = endpointCapacityRemedy(input.topology === "council" ? { rosterFloor: COUNCIL_MIN_MEMBERS } : undefined);
100
+ return `dispatch: admission denied: endpoint '${endpointLabel(input.endpointKey)}' capacity exceeded (${input.used + input.requested}/${input.limit} slots): ${describeEndpointCapacityHolders(input)}; ${remedy}`;
101
+ }
102
+
68
103
  function copyRecord(record: DispatchReservationRecord): DispatchReservationRecord {
69
104
  return { ...record, members: record.members.map((member) => ({ ...member })) };
70
105
  }
@@ -82,7 +117,8 @@ function validRecord(value: unknown): value is DispatchReservationRecord {
82
117
  record.topology === "sequential" ||
83
118
  record.topology === "pipeline" ||
84
119
  record.topology === "review" ||
85
- record.topology === "compete") &&
120
+ record.topology === "compete" ||
121
+ record.topology === "council") &&
86
122
  (record.status === "active" ||
87
123
  record.status === "released" ||
88
124
  record.status === "rolled_back" ||
@@ -96,6 +132,7 @@ function validRecord(value: unknown): value is DispatchReservationRecord {
96
132
  typeof member.memberId === "string" &&
97
133
  Number.isInteger(member.wave) &&
98
134
  typeof member.nodeId === "string" &&
135
+ (member.endpointKey === undefined || typeof member.endpointKey === "string") &&
99
136
  typeof member.costUpperBoundUsd === "number" &&
100
137
  Number.isFinite(member.costUpperBoundUsd) &&
101
138
  member.costUpperBoundUsd >= 0 &&
@@ -145,9 +182,13 @@ function reservationAllocation(tasks: ReadonlyArray<ReservationPlanTask>): Reser
145
182
  ),
146
183
  );
147
184
  const nodeSlots = peakBy(tasks.map((task) => ({ wave: task.wave, key: task.nodeId })));
185
+ const endpointSlots = peakBy(
186
+ tasks.flatMap((task) => (task.endpointKey === undefined ? [] : [{ wave: task.wave, key: task.endpointKey }])),
187
+ );
148
188
  return {
149
189
  globalSlots,
150
190
  nodeSlots,
191
+ endpointSlots,
151
192
  budgetUsd: tasks.reduce((sum, task) => sum + task.costUpperBoundUsd, 0),
152
193
  };
153
194
  }
@@ -168,6 +209,7 @@ function allocateReservation(
168
209
  tasks: ReadonlyArray<ReservationPlanTask>,
169
210
  existing: ReadonlyArray<DispatchReservationRecord>,
170
211
  capacity: ReservationCapacitySnapshot,
212
+ topology?: ReservationTopology,
171
213
  ): ReservationPlanResult {
172
214
  if (tasks.length === 0) return { ok: false, reason: "reservation requires at least one task" };
173
215
  const duplicate = tasks.find((task, index) => tasks.slice(0, index).some((entry) => entry.memberId === task.memberId));
@@ -191,6 +233,27 @@ function allocateReservation(
191
233
  return { ok: false, reason: `node '${nodeId}' capacity exceeded (${used + slots}/${node.limit})` };
192
234
  }
193
235
  }
236
+ for (const [endpointKey, slots] of Object.entries(requested.endpointSlots)) {
237
+ const endpoint = capacity.endpoints[endpointKey];
238
+ if (!endpoint || !Number.isFinite(endpoint.limit)) continue;
239
+ const heldSlots = held.reduce((sum, allocation) => sum + (allocation.endpointSlots[endpointKey] ?? 0), 0);
240
+ const used = endpoint.active + heldSlots;
241
+ if (used + slots > endpoint.limit) {
242
+ return {
243
+ ok: false,
244
+ reason: endpointCapacityDenial({
245
+ endpointKey,
246
+ limit: endpoint.limit,
247
+ used,
248
+ requested: slots,
249
+ leases: endpoint.leases ?? endpoint.active - (endpoint.foregroundStreams ?? 0),
250
+ reservations: heldSlots,
251
+ foregroundStreams: endpoint.foregroundStreams ?? 0,
252
+ ...(topology === undefined ? {} : { topology }),
253
+ }),
254
+ };
255
+ }
256
+ }
194
257
  const existingBudget = activeRecords.reduce((sum, record) => sum + outstandingBudget(record), 0);
195
258
  const projected = capacity.budget.currentUsd + existingBudget + requested.budgetUsd;
196
259
  if (projected >= capacity.budget.ceilingUsd) {
@@ -221,11 +284,13 @@ export function createDispatchReservation(input: {
221
284
  `dispatch: reservation denied: capacity is draining (requested by pid ${drain.requestedByPid} at ${drain.requestedAt})`,
222
285
  );
223
286
  }
224
- const planned = allocateReservation(input.tasks, records, input.capacity);
287
+ const planned = allocateReservation(input.tasks, records, input.capacity, input.topology);
225
288
  if (!planned.ok) {
226
289
  replaceReservations(state, records);
227
290
  writeCapacityStateUnsafe(state);
228
- throw new Error(`dispatch: reservation denied: ${planned.reason}`);
291
+ throw new Error(
292
+ planned.reason.startsWith("dispatch:") ? planned.reason : `dispatch: reservation denied: ${planned.reason}`,
293
+ );
229
294
  }
230
295
  const createdAt = new Date(nowMs).toISOString();
231
296
  const record: DispatchReservationRecord = {
@@ -250,6 +315,7 @@ export function transferDispatchReservationToLease(input: {
250
315
  memberId: string;
251
316
  assignmentId: string;
252
317
  nodeId: string;
318
+ endpointKey?: string;
253
319
  limits: CapacityLimits;
254
320
  nowMs?: number;
255
321
  ttlMs?: number;
@@ -258,6 +324,7 @@ export function transferDispatchReservationToLease(input: {
258
324
  return acquireCapacityLease({
259
325
  assignmentId: input.assignmentId,
260
326
  nodeId: input.nodeId,
327
+ ...(input.endpointKey !== undefined ? { endpointKey: input.endpointKey } : {}),
261
328
  limits: input.limits,
262
329
  nowMs,
263
330
  ...(input.ttlMs !== undefined ? { ttlMs: input.ttlMs } : {}),
@@ -290,6 +357,7 @@ export function rebindDispatchReservationMember(input: {
290
357
  ownerId: string;
291
358
  memberId: string;
292
359
  nodeId: string;
360
+ endpointKey?: string;
293
361
  costUpperBoundUsd: number;
294
362
  capacity: ReservationCapacitySnapshot;
295
363
  nowMs?: number;
@@ -304,11 +372,42 @@ export function rebindDispatchReservationMember(input: {
304
372
  if (member.status === "released") {
305
373
  throw new Error(`dispatch: reservation member '${input.memberId}' was already released`);
306
374
  }
307
- if (member.nodeId === input.nodeId && member.costUpperBoundUsd === input.costUpperBoundUsd) {
375
+ if (
376
+ member.nodeId === input.nodeId &&
377
+ member.endpointKey === input.endpointKey &&
378
+ member.costUpperBoundUsd === input.costUpperBoundUsd
379
+ ) {
308
380
  return copyRecord(record);
309
381
  }
310
-
311
382
  const others = records.filter((entry) => entry.status === "active" && entry.ownerId !== input.ownerId);
383
+ if (member.endpointKey !== input.endpointKey && input.endpointKey !== undefined) {
384
+ const endpointKey = input.endpointKey;
385
+ const endpoint = input.capacity.endpoints[endpointKey];
386
+ if (endpoint !== undefined && Number.isFinite(endpoint.limit)) {
387
+ const siblingSlots = record.members.filter(
388
+ (entry) => entry !== member && entry.status !== "released" && entry.endpointKey === endpointKey,
389
+ ).length;
390
+ const otherHeld = others.reduce(
391
+ (sum, entry) => sum + (reservationAllocation(outstandingTasks(entry)).endpointSlots[endpointKey] ?? 0),
392
+ 0,
393
+ );
394
+ const used = endpoint.active + otherHeld + siblingSlots;
395
+ if (used + 1 > endpoint.limit) {
396
+ throw new Error(
397
+ endpointCapacityDenial({
398
+ endpointKey,
399
+ limit: endpoint.limit,
400
+ used,
401
+ requested: 1,
402
+ leases: endpoint.leases ?? endpoint.active - (endpoint.foregroundStreams ?? 0),
403
+ reservations: otherHeld + siblingSlots,
404
+ foregroundStreams: endpoint.foregroundStreams ?? 0,
405
+ }),
406
+ );
407
+ }
408
+ }
409
+ }
410
+
312
411
  if (member.nodeId !== input.nodeId) {
313
412
  const node = input.capacity.nodes[input.nodeId];
314
413
  if (node !== undefined && Number.isFinite(node.limit)) {
@@ -342,6 +441,8 @@ export function rebindDispatchReservationMember(input: {
342
441
  }
343
442
 
344
443
  member.nodeId = input.nodeId;
444
+ if (input.endpointKey === undefined) delete member.endpointKey;
445
+ else member.endpointKey = input.endpointKey;
345
446
  member.costUpperBoundUsd = Math.max(0, input.costUpperBoundUsd);
346
447
  writeStore(records);
347
448
  return copyRecord(record);
@@ -370,6 +471,26 @@ export function releaseDispatchReservationMember(
370
471
  });
371
472
  }
372
473
 
474
+ /** Settle every member after the scheduler has finished the reserved plan. */
475
+ export function releaseDispatchReservation(ownerId: string, nowMs = Date.now()): DispatchReservationRecord | null {
476
+ return withStateFileLockSync(capacityStateLockPath(), () => {
477
+ const records = readStore();
478
+ const record = records.find((entry) => entry.ownerId === ownerId);
479
+ if (!record) return null;
480
+ if (record.status !== "active") return copyRecord(record);
481
+ const settledAt = new Date(nowMs).toISOString();
482
+ for (const member of record.members) {
483
+ if (member.status === "released") continue;
484
+ member.status = "released";
485
+ member.releasedAt = settledAt;
486
+ }
487
+ record.status = "released";
488
+ record.settledAt = settledAt;
489
+ writeStore(records);
490
+ return copyRecord(record);
491
+ });
492
+ }
493
+
373
494
  export function rollbackDispatchReservation(ownerId: string, nowMs = Date.now()): DispatchReservationRecord | null {
374
495
  return withStateFileLockSync(capacityStateLockPath(), () => {
375
496
  const records = readStore();
@@ -488,14 +609,21 @@ export function reservedBudgetUsd(): number {
488
609
  .reduce((sum, record) => sum + outstandingBudget(record), 0);
489
610
  }
490
611
 
491
- export function reservedCapacity(): { globalSlots: number; nodeSlots: Readonly<Record<string, number>> } {
612
+ export function reservedCapacity(): {
613
+ globalSlots: number;
614
+ nodeSlots: Readonly<Record<string, number>>;
615
+ endpointSlots: Readonly<Record<string, number>>;
616
+ } {
492
617
  let globalSlots = 0;
493
618
  const nodeSlots: Record<string, number> = {};
619
+ const endpointSlots: Record<string, number> = {};
494
620
  for (const record of readStore().filter((entry) => entry.status === "active")) {
495
621
  const allocation = reservationAllocation(outstandingTasks(record));
496
622
  globalSlots += allocation.globalSlots;
497
623
  for (const [nodeId, count] of Object.entries(allocation.nodeSlots))
498
624
  nodeSlots[nodeId] = (nodeSlots[nodeId] ?? 0) + count;
625
+ for (const [endpointKey, count] of Object.entries(allocation.endpointSlots))
626
+ endpointSlots[endpointKey] = (endpointSlots[endpointKey] ?? 0) + count;
499
627
  }
500
- return { globalSlots, nodeSlots };
628
+ return { globalSlots, nodeSlots, endpointSlots };
501
629
  }
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Domain-owned writer for the run event journal.
3
+ *
4
+ * The journal was originally teed from `createDispatchRunEventRegistry`
5
+ * (src/tools/dispatch-run-events.ts), the display-tail helper behind the
6
+ * model-facing `dispatch` tool. That helper is not on the operator paths:
7
+ * `clio-coder run --agent` (src/cli/run.ts), `clio-coder fleet run`
8
+ * (src/cli/fleet.ts), and the TUI `/run` slash command each take a handle
9
+ * straight off `DispatchContract.dispatch` and iterate `handle.events`
10
+ * themselves, so no registry is ever built and the sink never fired. The
11
+ * writer had to move to something every dispatch reaches.
12
+ *
13
+ * `BusChannels.DispatchProgress` is that thing. The dispatch domain publishes
14
+ * it from inside the event pump for every consumer-visible event of every run,
15
+ * "attached, detached, batched, and retry runs, exactly once" (see
16
+ * src/core/bus-events.ts), whether or not anyone iterates the handle. The
17
+ * terminal pair `DispatchCompleted`/`DispatchFailed` closes every run the same
18
+ * way. Subscribing here makes the journal a property of dispatching, not of
19
+ * which caller happened to build a registry.
20
+ *
21
+ * Ownership is explicit rather than ambient: the bridge attaches only when a
22
+ * composition root asks for it (`DispatchBundleOptions.journalRunEvents`), and
23
+ * `registerAllTools` hands its registry `journal: null` in that same process.
24
+ * One writer per file, decided at one place, so a tool-path run in the TUI is
25
+ * not transcribed twice.
26
+ *
27
+ * Every write is best-effort. The sink degrades itself on I/O failure and a
28
+ * listener that throws is contained by the safe bus, so nothing here can fail a
29
+ * dispatch.
30
+ */
31
+
32
+ import type {
33
+ DispatchCompletedPayload,
34
+ DispatchFailedPayload,
35
+ DispatchProgressPayload,
36
+ } from "../../core/bus-events.js";
37
+ import { BusChannels } from "../../core/bus-events.js";
38
+ import type { SafeEventBus } from "../../core/event-bus.js";
39
+ import { runTailEntryFromEvent } from "../../tools/dispatch-run-events.js";
40
+ import { defaultRunEventJournal, type RunEventJournalSink } from "./run-event-journal.js";
41
+
42
+ /**
43
+ * Runs whose `open` line this bridge has already written. Bounded so a
44
+ * long-lived orchestrator cannot grow it without limit; the journal writer
45
+ * keeps its own bound for the same reason. Evicting a run only forgets that it
46
+ * was opened, and a later event for it writes a second `open` line, which the
47
+ * reader and the writer both tolerate.
48
+ */
49
+ const OPENED_RUN_LIMIT = 512;
50
+
51
+ export interface RunEventJournalBridge {
52
+ /** Unsubscribe from the bus. Idempotent. */
53
+ stop(): void;
54
+ }
55
+
56
+ export interface AttachRunEventJournalBridgeOptions {
57
+ /** Sink override; defaults to the process-wide journal. */
58
+ journal?: RunEventJournalSink;
59
+ }
60
+
61
+ function isRecord(value: unknown): value is Record<string, unknown> {
62
+ return typeof value === "object" && value !== null && !Array.isArray(value);
63
+ }
64
+
65
+ function runIdentity(payload: unknown): { runId: string; agentId: string } | null {
66
+ if (!isRecord(payload)) return null;
67
+ if (typeof payload.runId !== "string" || payload.runId.length === 0) return null;
68
+ return { runId: payload.runId, agentId: typeof payload.agentId === "string" ? payload.agentId : "unknown" };
69
+ }
70
+
71
+ /**
72
+ * Subscribe the journal to a dispatch bus. Returns a handle whose `stop()` the
73
+ * owning bundle calls on shutdown so a second bundle in the same process (tests
74
+ * do this) never inherits the first one's listeners.
75
+ */
76
+ export function attachRunEventJournalBridge(
77
+ bus: SafeEventBus,
78
+ options: AttachRunEventJournalBridgeOptions = {},
79
+ ): RunEventJournalBridge {
80
+ const journal = options.journal ?? defaultRunEventJournal();
81
+ const opened = new Set<string>();
82
+
83
+ const ensureOpen = (runId: string, agentId: string): void => {
84
+ if (opened.has(runId)) return;
85
+ opened.add(runId);
86
+ while (opened.size > OPENED_RUN_LIMIT) {
87
+ const oldest = opened.values().next();
88
+ if (oldest.done === true) break;
89
+ opened.delete(oldest.value);
90
+ }
91
+ journal.open(runId, agentId);
92
+ };
93
+
94
+ /**
95
+ * Write the receipt facts and close the run. Read defensively for the same
96
+ * reason the registry's seal is: a terminal payload that is missing a field
97
+ * it is typed to have must degrade the transcript, never throw back into the
98
+ * finalizer that emitted it.
99
+ */
100
+ const seal = (outcome: string, detail: string | null | undefined, payload: unknown): void => {
101
+ const identity = runIdentity(payload);
102
+ if (identity === null) return;
103
+ ensureOpen(identity.runId, identity.agentId);
104
+ const exitCode = isRecord(payload) && typeof payload.exitCode === "number" ? payload.exitCode : null;
105
+ journal.receipt(identity.runId, { outcome, exitCode });
106
+ journal.terminal(identity.runId, outcome, detail ?? undefined);
107
+ opened.delete(identity.runId);
108
+ };
109
+
110
+ const unsubscribes = [
111
+ bus.on(BusChannels.DispatchProgress, (payload: DispatchProgressPayload) => {
112
+ const identity = runIdentity(payload);
113
+ if (identity === null) return;
114
+ // The display projection decides what a transcript line is; a
115
+ // heartbeat or a streaming delta is not one. Opening the run only
116
+ // once an event survives that filter keeps a heartbeat-only run from
117
+ // creating an empty journal directory.
118
+ const entry = runTailEntryFromEvent(payload.event);
119
+ if (entry === null) return;
120
+ ensureOpen(identity.runId, identity.agentId);
121
+ // Route resolution warnings use `message`, while worker transcript
122
+ // events generally project their text through `detail`. Preserve the
123
+ // warning at this dispatch-owned durability seam so fleet view does not
124
+ // render a content-free `route_warning` line.
125
+ const message =
126
+ isRecord(payload.event) && typeof payload.event.message === "string" ? payload.event.message : undefined;
127
+ journal.append(
128
+ identity.runId,
129
+ entry.detail === undefined && message !== undefined ? { ...entry, detail: message } : entry,
130
+ );
131
+ }),
132
+ bus.on(BusChannels.DispatchCompleted, (payload: DispatchCompletedPayload) => {
133
+ seal(payload.outcome, payload.outcomeDetail, payload);
134
+ }),
135
+ bus.on(BusChannels.DispatchFailed, (payload: DispatchFailedPayload) => {
136
+ seal(payload.outcome, payload.outcomeDetail, payload);
137
+ }),
138
+ ];
139
+
140
+ let stopped = false;
141
+ return {
142
+ stop(): void {
143
+ if (stopped) return;
144
+ stopped = true;
145
+ for (const unsubscribe of unsubscribes) unsubscribe();
146
+ opened.clear();
147
+ },
148
+ };
149
+ }