@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,30 +1,37 @@
1
1
  import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
2
2
  import {
3
- protectedArtifactFromSessionEntry,
4
- protectedArtifactStateFromSessionEntries,
5
- readAuditRows,
6
- readSessionEntriesForId,
7
- responseModelIdObservationFromRecord
8
- } from "./chunk-YS5VLNH5.js";
3
+ decideReviewGate,
4
+ materializePendingGateDecision,
5
+ readGateDecisionArtifacts,
6
+ readGateDecisionArtifactsForRunIds,
7
+ stagePendingGateDecision,
8
+ verifyGateDecisionArtifact
9
+ } from "./chunk-X75E3D2N.js";
9
10
  import {
10
11
  RUN_RECEIPT_INTEGRITY_ALGORITHM,
11
12
  RUN_RECEIPT_INTEGRITY_VERSION,
12
- adaptFinishContractCompletionStatus,
13
13
  adaptGateDecisionReviewStatus,
14
14
  adaptGroundedEvidenceValidationStatus,
15
15
  composeTrustStatus,
16
+ formatTrustAxes,
17
+ formatTrustSummary,
16
18
  inspectRunReceiptTrustStatus,
17
19
  isReceiptIntegrity,
18
20
  isTrustStatusIdentifier,
19
- loadEvalArtifact,
20
21
  normalizeTrustStatus,
21
- parseEvalArtifactV4,
22
- redactArtifactForStorage,
23
22
  retiredIntegrityVersionOf,
24
- sumEvalHarnessMetrics,
23
+ sha256,
24
+ trustVerdict,
25
25
  verifyReceiptIntegrity,
26
26
  withReceiptIntegrity
27
- } from "./chunk-K4XHGFR5.js";
27
+ } from "./chunk-B7OBL7PK.js";
28
+ import {
29
+ protectedArtifactFromSessionEntry,
30
+ protectedArtifactStateFromSessionEntries,
31
+ readAuditRows,
32
+ readSessionEntriesForId,
33
+ responseModelIdObservationFromRecord
34
+ } from "./chunk-QREDIESB.js";
28
35
  import {
29
36
  applyTaskWorktree,
30
37
  captureWorkspaceSnapshot,
@@ -32,19 +39,32 @@ import {
32
39
  createTaskWorktree,
33
40
  createWriteBoundaryEnforcer,
34
41
  gitCheckoutRoot
35
- } from "./chunk-MXKJU4JB.js";
42
+ } from "./chunk-U77AMWDL.js";
36
43
  import {
37
44
  executionPlanAncestors,
38
45
  spliceExecutionPlan
39
- } from "./chunk-J3YUBZWY.js";
46
+ } from "./chunk-QBJA7R7N.js";
40
47
  import {
41
48
  parseRigorOverride,
42
49
  resolveRigor
43
50
  } from "./chunk-RVG5JXAL.js";
44
51
  import {
45
- FLEET_COMMAND_BASE_ENV,
46
- normalizeWriteBoundary
47
- } from "./chunk-E77JEWSD.js";
52
+ loadEvalArtifact,
53
+ parseEvalArtifactV4,
54
+ redactArtifactForStorage,
55
+ sumEvalHarnessMetrics
56
+ } from "./chunk-NHLBIGRH.js";
57
+ import {
58
+ defaultRunEventJournal,
59
+ removeRunEventJournals
60
+ } from "./chunk-IQ7KR472.js";
61
+ import {
62
+ AdmissionCanceledError,
63
+ EVENT_TEE_LIMIT,
64
+ createWorkerOutputCapture,
65
+ durableAssistantTextFromEvent,
66
+ startDispatchEventPump
67
+ } from "./chunk-T56WDKA5.js";
48
68
  import {
49
69
  LOCAL_NODE_ID,
50
70
  computeSettingsFingerprint,
@@ -55,9 +75,14 @@ import {
55
75
  receiptAttestationFields,
56
76
  routeFactVerdict,
57
77
  spawnNativeWorker
58
- } from "./chunk-2HEJ2F35.js";
78
+ } from "./chunk-QLFS5GO2.js";
79
+ import {
80
+ FLEET_COMMAND_BASE_ENV,
81
+ normalizeWriteBoundary
82
+ } from "./chunk-CTJ4RNAA.js";
59
83
  import {
60
84
  AGENT_LEDGER_PROMPT_MAX_CHARS,
85
+ COUNCIL_MIN_MEMBERS,
61
86
  RETRYABLE_OUTCOMES,
62
87
  UnsupportedResponseSchemaError,
63
88
  WORKER_EXIT_PERMISSION_REQUIRED,
@@ -67,24 +92,23 @@ import {
67
92
  agentRoleReadinessReport,
68
93
  agentRouteCandidates,
69
94
  antigravitySubprocessConfigForAutonomy,
70
- applyToolProfile,
71
95
  approvedRouteCandidates,
72
96
  assertApprovedAssignmentRoute,
73
97
  assertApprovedRecoveryCapability,
74
- assertToolProfileEnforceable,
75
98
  claimConflicts,
76
99
  classifyAgentTask,
77
100
  claudeSubprocessPermissionConfigForAutonomy,
78
101
  competeStanceLiner,
79
102
  createRunEffectsRecorder,
103
+ declaredScopeIntent,
80
104
  declaredScopeReplacementDiagnostic,
81
105
  declaredScopeReplacementNotice,
82
- describeCallAction,
83
106
  isBoundedGateRolePrompt,
84
107
  isClaudeCanonicalTool,
85
108
  isResponseSchemaRejection,
86
109
  isRunOutcomeCode,
87
110
  networkToolsDisabled,
111
+ nodeResultContractFilesystem,
88
112
  projectExecutionHandoffs,
89
113
  renderAgentLedger,
90
114
  resolveDispatchPathScope,
@@ -95,7 +119,7 @@ import {
95
119
  serializeWorkerRuntimeDescriptor,
96
120
  toolPromptHintsForNames,
97
121
  validateJobSpec
98
- } from "./chunk-A3WNZD3P.js";
122
+ } from "./chunk-J4W7KFM7.js";
99
123
  import {
100
124
  decideRoute,
101
125
  defaultRoutingIntent,
@@ -113,7 +137,20 @@ import {
113
137
  routingIntentRejection,
114
138
  sameRouteIdentity,
115
139
  toRouteCandidate
116
- } from "./chunk-P43ETTHK.js";
140
+ } from "./chunk-SJ5ZKQ4S.js";
141
+ import {
142
+ assessFinishContract
143
+ } from "./chunk-GKF55TAZ.js";
144
+ import {
145
+ WRITE_ROOT_REFUSED_TOOLS
146
+ } from "./chunk-32KWKNSF.js";
147
+ import {
148
+ describeCallAction
149
+ } from "./chunk-TVHHYFHE.js";
150
+ import {
151
+ applyToolProfile,
152
+ assertToolProfileEnforceable
153
+ } from "./chunk-42FMPA75.js";
117
154
  import {
118
155
  appliesRecipeResultContract,
119
156
  gateRouteCorrelation,
@@ -122,94 +159,93 @@ import {
122
159
  routeCorrelationFactsForRun,
123
160
  withAttemptRole
124
161
  } from "./chunk-H7IXIC72.js";
125
- import {
126
- WRITE_ROOT_REFUSED_TOOLS,
127
- assessFinishContract
128
- } from "./chunk-5H3GB5BO.js";
129
162
  import {
130
163
  compareCodepoints
131
- } from "./chunk-A2NJGIB3.js";
132
- import {
133
- isSkillActivation
134
- } from "./chunk-GOXNB3AO.js";
164
+ } from "./chunk-5LXZXPKX.js";
135
165
  import {
136
166
  DEFAULT_AUTONOMY_LEVEL,
137
167
  autonomyDenyRejection,
168
+ isSkillActivation,
138
169
  mapAutonomy
139
- } from "./chunk-HWUFFB6L.js";
170
+ } from "./chunk-RAPCMZL4.js";
140
171
  import {
141
- parseJsonObjectPayload,
142
- parseVerifierResult,
143
- pathBoundaryCovers,
144
- resultContractAuthorship,
145
- validateRecipeResult
146
- } from "./chunk-TTHACPOM.js";
172
+ createRedactionTally,
173
+ redactSecretsDeep,
174
+ redactSecretsText
175
+ } from "./chunk-4BJ5BYCE.js";
176
+ import {
177
+ truncateUtf8
178
+ } from "./chunk-6XLNIQDB.js";
179
+ import {
180
+ canonicalJson,
181
+ endpointIdentityHash,
182
+ parseAgentLedgerBody
183
+ } from "./chunk-CMZWFGD2.js";
184
+ import {
185
+ pathBoundaryCovers
186
+ } from "./chunk-HHV2GANA.js";
147
187
  import {
148
188
  agentSpecFingerprint,
149
189
  assertAgentSpecPolicy,
150
190
  classify,
151
191
  isUserVisibleAgent,
152
192
  normalizeAgentSpec,
153
- resolveAgentToolCompatibility
154
- } from "./chunk-AOCYTWAV.js";
193
+ parseJsonObjectPayload,
194
+ resolveAgentToolCompatibility,
195
+ resultContractAuthorship,
196
+ validateRecipeResult
197
+ } from "./chunk-DYJP44XW.js";
155
198
  import {
156
199
  detectValidationCommand
157
- } from "./chunk-MV3K5QF2.js";
200
+ } from "./chunk-GCSMB2KY.js";
158
201
  import {
159
202
  isProjectVerifierCheckId,
160
203
  isVerificationScriptName
161
204
  } from "./chunk-UL3WSD3F.js";
162
- import {
163
- createRedactionTally,
164
- redactSecretsDeep,
165
- redactSecretsText
166
- } from "./chunk-4BJ5BYCE.js";
167
205
  import {
168
206
  canonicalizeExistingPath
169
207
  } from "./chunk-ECH6PKUQ.js";
170
- import {
171
- canonicalJson,
172
- endpointIdentityHash,
173
- parseAgentLedgerBody
174
- } from "./chunk-CMZWFGD2.js";
175
- import {
176
- truncateUtf8
177
- } from "./chunk-6XLNIQDB.js";
178
208
  import {
179
209
  ToolNames,
180
210
  isBuiltinToolName
181
- } from "./chunk-CGKSTWHD.js";
211
+ } from "./chunk-K6BSR66V.js";
182
212
  import {
183
213
  canonicalizeWireModelId,
214
+ endpointCapacityFor,
215
+ endpointCapacityForStatus,
216
+ endpointLabel,
184
217
  firstRuntimeResolutionError,
218
+ foregroundStreamUsage,
185
219
  isDispatchEligibleRuntime,
220
+ normalizeCostProvenance,
221
+ resolveEndpointCapacities,
186
222
  resolveModelCapabilities,
187
223
  resolveRuntimeTarget,
188
224
  runtimeResolutionWarnings,
189
225
  runtimeTargetSnapshot
190
- } from "./chunk-7RFXX52T.js";
226
+ } from "./chunk-DQITNCXG.js";
191
227
  import {
192
228
  ceilChars
193
- } from "./chunk-RWSI4YD7.js";
229
+ } from "./chunk-UM7N4G5A.js";
230
+ import {
231
+ BusChannels
232
+ } from "./chunk-HLW2MRKE.js";
233
+ import {
234
+ atomicWrite
235
+ } from "./chunk-76ONBSIA.js";
236
+ import {
237
+ assertSafeId
238
+ } from "./chunk-R346GLFC.js";
194
239
  import {
195
240
  attributeCommitMessage,
196
241
  gitCommitAttributionEnabled,
197
242
  reportCommitAttributionDiagnostic,
198
243
  withManagedGitCommitAttributionEnvironment
199
- } from "./chunk-B5CSFE7B.js";
244
+ } from "./chunk-BBVJUZHB.js";
200
245
  import {
201
246
  MAX_TIMER_DELAY_MS,
202
247
  rawDurationMs
203
248
  } from "./chunk-FQ4SKYE4.js";
204
- import {
205
- BusChannels
206
- } from "./chunk-TT36MB5S.js";
207
- import {
208
- atomicWrite
209
- } from "./chunk-3BINW3FP.js";
210
- import {
211
- assertSafeId
212
- } from "./chunk-R346GLFC.js";
213
249
  import {
214
250
  AI_AGENT_NAME
215
251
  } from "./chunk-6EJMN2Y3.js";
@@ -223,14 +259,14 @@ import {
223
259
  DEFAULT_DELEGATION_TURN_TIMEOUT_MS,
224
260
  DEFAULT_SETTINGS,
225
261
  THINKING_LEVELS
226
- } from "./chunk-4DGYLA73.js";
262
+ } from "./chunk-GXNLGKAB.js";
227
263
  import {
228
264
  GUARDRAIL_DEFAULTS,
229
265
  resolveGuardrail
230
266
  } from "./chunk-4ZG3XFUR.js";
231
267
  import {
232
268
  targetRequiresAuth
233
- } from "./chunk-EQ63NRB7.js";
269
+ } from "./chunk-BBVYXMFO.js";
234
270
  import {
235
271
  FILE_LOCK_ACQUIRE_TIMEOUT_MS,
236
272
  withStateFileLock,
@@ -245,10 +281,10 @@ import {
245
281
  clioDataDir,
246
282
  clioStateDir,
247
283
  stateRootRemoved
248
- } from "./chunk-BNAZZHFG.js";
284
+ } from "./chunk-BYP5D4HI.js";
249
285
  import {
250
286
  resolveEffectivePricing
251
- } from "./chunk-PT7HYKEM.js";
287
+ } from "./chunk-VO2LKSTM.js";
252
288
  import {
253
289
  init_esm_shims
254
290
  } from "./chunk-3R73A4XB.js";
@@ -406,8 +442,8 @@ var StdioJsonRpcTransport = class {
406
442
  constructor(command, args, options = {}) {
407
443
  this.terminationGraceMs = boundedMilliseconds(options.terminationGraceMs, 500);
408
444
  this.terminationWaitMs = boundedMilliseconds(options.terminationWaitMs, 2e3);
409
- this.childClosePromise = new Promise((resolve5) => {
410
- this.resolveChildClose = resolve5;
445
+ this.childClosePromise = new Promise((resolve4) => {
446
+ this.resolveChildClose = resolve4;
411
447
  });
412
448
  const childEnvironment = options.env ? { ...process.env, ...options.env } : process.env;
413
449
  const attribution = withManagedGitCommitAttributionEnvironment(childEnvironment, {
@@ -464,10 +500,10 @@ var StdioJsonRpcTransport = class {
464
500
  const requestTimeoutMs = validateRequestTimeout(method, timeoutMs);
465
501
  const id = this.nextId++;
466
502
  const message = { jsonrpc: "2.0", id, method, params };
467
- const promise = new Promise((resolve5, reject) => {
503
+ const promise = new Promise((resolve4, reject) => {
468
504
  const pending = {
469
505
  method,
470
- resolve: (value) => resolve5(value),
506
+ resolve: (value) => resolve4(value),
471
507
  reject
472
508
  };
473
509
  if (requestTimeoutMs !== void 0) {
@@ -654,9 +690,9 @@ var StdioJsonRpcTransport = class {
654
690
  if (remaining <= 0) return this.terminationObserved();
655
691
  const interval = Math.min(10, remaining);
656
692
  if (this.childHandlesClosed) {
657
- await new Promise((resolve5) => setTimeout(resolve5, interval));
693
+ await new Promise((resolve4) => setTimeout(resolve4, interval));
658
694
  } else {
659
- await Promise.race([this.childClosePromise, new Promise((resolve5) => setTimeout(resolve5, interval))]);
695
+ await Promise.race([this.childClosePromise, new Promise((resolve4) => setTimeout(resolve4, interval))]);
660
696
  }
661
697
  }
662
698
  return true;
@@ -721,10 +757,10 @@ var StreamJsonRpcPeerTransport = class {
721
757
  const requestTimeoutMs = validateRequestTimeout(method, timeoutMs);
722
758
  const id = this.nextId++;
723
759
  const message = { jsonrpc: "2.0", id, method, params };
724
- const promise = new Promise((resolve5, reject) => {
760
+ const promise = new Promise((resolve4, reject) => {
725
761
  const pending = {
726
762
  method,
727
- resolve: (value) => resolve5(value),
763
+ resolve: (value) => resolve4(value),
728
764
  reject
729
765
  };
730
766
  if (requestTimeoutMs !== void 0) {
@@ -888,162 +924,6 @@ function createStdioServerTransport(options = {}) {
888
924
  return new StreamJsonRpcPeerTransport(options);
889
925
  }
890
926
 
891
- // src/domains/dispatch/event-pump.ts
892
- init_esm_shims();
893
- var EVENT_TEE_LIMIT = 1024;
894
- function startDispatchEventPump(source, fold, options = {}) {
895
- const limit = options.limit ?? EVENT_TEE_LIMIT;
896
- const pending = [...options.prelude ?? []];
897
- const waiters = [];
898
- let finished = false;
899
- let abandoned = false;
900
- let dropped = 0;
901
- const push = (value) => {
902
- if (abandoned) return;
903
- const waiter = waiters.shift();
904
- if (waiter) {
905
- waiter({ value, done: false });
906
- return;
907
- }
908
- pending.push(value);
909
- while (pending.length > limit) {
910
- pending.shift();
911
- dropped += 1;
912
- }
913
- };
914
- const end = () => {
915
- finished = true;
916
- while (waiters.length > 0) {
917
- waiters.shift()?.({ value: void 0, done: true });
918
- }
919
- };
920
- const notify = (event) => {
921
- try {
922
- options.onEvent?.(event);
923
- } catch (error) {
924
- options.onError?.(error);
925
- }
926
- };
927
- const done = (async () => {
928
- try {
929
- for (const event of options.prelude ?? []) notify(event);
930
- for await (const event of source) {
931
- try {
932
- fold(event);
933
- } catch (error) {
934
- options.onError?.(error);
935
- }
936
- notify(event);
937
- push(event);
938
- }
939
- } catch (error) {
940
- options.onError?.(error);
941
- } finally {
942
- end();
943
- }
944
- })();
945
- const events = {
946
- next() {
947
- if (pending.length > 0) {
948
- return Promise.resolve({ value: pending.shift(), done: false });
949
- }
950
- if (finished || abandoned) return Promise.resolve({ value: void 0, done: true });
951
- return new Promise((resolve5) => {
952
- waiters.push(resolve5);
953
- });
954
- },
955
- return() {
956
- abandoned = true;
957
- pending.length = 0;
958
- while (waiters.length > 0) {
959
- waiters.shift()?.({ value: void 0, done: true });
960
- }
961
- return Promise.resolve({ value: void 0, done: true });
962
- },
963
- [Symbol.asyncIterator]() {
964
- return this;
965
- }
966
- };
967
- return { events, done, droppedEvents: () => dropped };
968
- }
969
- var WORKER_OUTPUT_MAX_BYTES = 8192;
970
- var WORKER_OUTPUT_TRUNCATION_MARKER = "\n[worker output truncated]";
971
- function isRecord2(value) {
972
- return typeof value === "object" && value !== null && !Array.isArray(value);
973
- }
974
- function assistantTextFromContent(content) {
975
- if (typeof content === "string") return content;
976
- if (!Array.isArray(content)) return "";
977
- return content.map((block) => {
978
- if (typeof block === "string") return block;
979
- if (!isRecord2(block)) return "";
980
- return typeof block.text === "string" ? block.text : "";
981
- }).join("");
982
- }
983
- function isDurableAssistantMessage(message) {
984
- const stopReason = message.stopReason;
985
- if (stopReason === "toolUse" || stopReason === "error" || stopReason === "aborted" || stopReason === "cancelled") {
986
- return false;
987
- }
988
- if (!Array.isArray(message.content)) return true;
989
- return !message.content.some((block) => isRecord2(block) && block.type === "toolCall");
990
- }
991
- function durableAssistantTextFromEvent(event) {
992
- if (!isRecord2(event) || event.type !== "message_end" || !isRecord2(event.message)) return "";
993
- if (event.message.role !== "assistant" || !isDurableAssistantMessage(event.message)) return "";
994
- return assistantTextFromContent(event.message.content);
995
- }
996
- function boundedOutput(state, text) {
997
- const bytes = Buffer.byteLength(text, "utf8");
998
- const bounded = truncateUtf8(text, WORKER_OUTPUT_MAX_BYTES, WORKER_OUTPUT_TRUNCATION_MARKER);
999
- return { state, text: bounded, bytes, truncated: bounded !== text };
1000
- }
1001
- function createWorkerOutputCapture() {
1002
- let finalText = null;
1003
- let partialText = "";
1004
- let partialBytes = 0;
1005
- let partialStored = 0;
1006
- return {
1007
- observe(event) {
1008
- if (!isRecord2(event)) return;
1009
- if (event.type === "message_end") {
1010
- const message = isRecord2(event.message) ? event.message : null;
1011
- partialText = "";
1012
- partialBytes = 0;
1013
- partialStored = 0;
1014
- if (message === null || message.role !== "assistant") return;
1015
- if (!isDurableAssistantMessage(message)) return;
1016
- const text = assistantTextFromContent(message.content).trim();
1017
- if (text.length > 0) finalText = text;
1018
- return;
1019
- }
1020
- if (event.type !== "message_update") return;
1021
- const assistantEvent = isRecord2(event.assistantMessageEvent) ? event.assistantMessageEvent : null;
1022
- if (assistantEvent === null || assistantEvent.type !== "text_delta") return;
1023
- const delta = assistantEvent.delta;
1024
- if (typeof delta !== "string" || delta.length === 0) return;
1025
- partialBytes += Buffer.byteLength(delta, "utf8");
1026
- if (partialStored < WORKER_OUTPUT_MAX_BYTES) {
1027
- partialText += delta;
1028
- partialStored += Buffer.byteLength(delta, "utf8");
1029
- }
1030
- },
1031
- snapshot() {
1032
- if (partialBytes > 0 && partialText.trim().length > 0) {
1033
- const bounded = truncateUtf8(partialText.trim(), WORKER_OUTPUT_MAX_BYTES, WORKER_OUTPUT_TRUNCATION_MARKER);
1034
- return {
1035
- state: "partial",
1036
- text: bounded,
1037
- bytes: partialBytes,
1038
- truncated: bounded !== partialText.trim() || partialBytes > partialStored
1039
- };
1040
- }
1041
- if (finalText !== null) return boundedOutput("final", finalText);
1042
- return void 0;
1043
- }
1044
- };
1045
- }
1046
-
1047
927
  // src/domains/dispatch/capacity-lease.ts
1048
928
  init_esm_shims();
1049
929
  import { randomBytes } from "node:crypto";
@@ -1069,7 +949,7 @@ function clone(lease) {
1069
949
  function valid(value) {
1070
950
  if (typeof value !== "object" || value === null) return false;
1071
951
  const lease = value;
1072
- return typeof lease.leaseId === "string" && typeof lease.assignmentId === "string" && typeof lease.nodeId === "string" && (lease.host === void 0 || typeof lease.host === "string") && Number.isInteger(lease.ownerPid) && typeof lease.processBirthToken === "string" && typeof lease.acquiredAt === "string" && typeof lease.expiresAt === "string" && typeof lease.heartbeatAt === "string" && (lease.reservationOwnerId === null || typeof lease.reservationOwnerId === "string") && (lease.reservationMemberId === null || typeof lease.reservationMemberId === "string");
952
+ return typeof lease.leaseId === "string" && typeof lease.assignmentId === "string" && typeof lease.nodeId === "string" && (lease.endpointKey === void 0 || typeof lease.endpointKey === "string") && (lease.host === void 0 || typeof lease.host === "string") && Number.isInteger(lease.ownerPid) && typeof lease.processBirthToken === "string" && typeof lease.acquiredAt === "string" && typeof lease.expiresAt === "string" && typeof lease.heartbeatAt === "string" && (lease.reservationOwnerId === null || typeof lease.reservationOwnerId === "string") && (lease.reservationMemberId === null || typeof lease.reservationMemberId === "string");
1073
953
  }
1074
954
  function validTimestamp(value) {
1075
955
  if (typeof value !== "string") return false;
@@ -1133,6 +1013,7 @@ var MEMBER_STATUSES = /* @__PURE__ */ new Set(["held", "consumed", "released"]);
1133
1013
  function heldReservationUsage(values) {
1134
1014
  let global = 0;
1135
1015
  const nodes = {};
1016
+ const endpoints = {};
1136
1017
  for (const value of values) {
1137
1018
  if (typeof value !== "object" || value === null)
1138
1019
  throw new Error("dispatch capacity store has invalid reservation records");
@@ -1142,6 +1023,7 @@ function heldReservationUsage(values) {
1142
1023
  if (record.status !== "active") continue;
1143
1024
  const byWave = /* @__PURE__ */ new Map();
1144
1025
  const byNodeWave = /* @__PURE__ */ new Map();
1026
+ const byEndpointWave = /* @__PURE__ */ new Map();
1145
1027
  for (const raw of record.members) {
1146
1028
  if (typeof raw !== "object" || raw === null)
1147
1029
  throw new Error("dispatch capacity store has invalid reservation records");
@@ -1154,13 +1036,39 @@ function heldReservationUsage(values) {
1154
1036
  const nodeWaves = byNodeWave.get(member.nodeId) ?? /* @__PURE__ */ new Map();
1155
1037
  nodeWaves.set(wave, (nodeWaves.get(wave) ?? 0) + 1);
1156
1038
  byNodeWave.set(member.nodeId, nodeWaves);
1039
+ if (member.endpointKey !== void 0 && typeof member.endpointKey !== "string")
1040
+ throw new Error("dispatch capacity store has invalid reservation records");
1041
+ if (typeof member.endpointKey === "string") {
1042
+ const endpointWaves = byEndpointWave.get(member.endpointKey) ?? /* @__PURE__ */ new Map();
1043
+ endpointWaves.set(wave, (endpointWaves.get(wave) ?? 0) + 1);
1044
+ byEndpointWave.set(member.endpointKey, endpointWaves);
1045
+ }
1157
1046
  }
1158
1047
  global += Math.max(0, ...byWave.values());
1159
1048
  for (const [id, waves] of byNodeWave) nodes[id] = (nodes[id] ?? 0) + Math.max(0, ...waves.values());
1049
+ for (const [key, waves] of byEndpointWave) endpoints[key] = (endpoints[key] ?? 0) + Math.max(0, ...waves.values());
1160
1050
  }
1161
- return { global, nodes };
1051
+ return { global, nodes, endpoints };
1162
1052
  }
1163
- function assertCapacity(file, nodeId, limits) {
1053
+ function describeEndpointCapacityHolders(holders) {
1054
+ const parts = [];
1055
+ const add = (count, singular, plural) => {
1056
+ if (count > 0) parts.push(`${count} ${count === 1 ? singular : plural}`);
1057
+ };
1058
+ add(holders.leases, "active lease", "active leases");
1059
+ add(holders.reservations, "held reservation", "held reservations");
1060
+ add(holders.foregroundStreams, "foreground stream", "foreground streams");
1061
+ if (parts.length === 0) return "no active lease, held reservation, or foreground stream currently holds a slot";
1062
+ const named = parts.length === 1 ? parts[0] : parts.length === 2 ? `${parts[0]} and ${parts[1]}` : `${parts.slice(0, -1).join(", ")}, and ${parts.at(-1)}`;
1063
+ const total = holders.leases + holders.reservations + holders.foregroundStreams;
1064
+ return `${named} ${total === 1 ? "holds" : "hold"} ${total === 1 ? "the slot" : "the slots"}`;
1065
+ }
1066
+ function endpointCapacityRemedy(input) {
1067
+ const ways = "set this target's maxConcurrentRequests to the slot count the server was started with, collect in-flight runs, or point workers at a second server";
1068
+ if (input?.rosterFloor === void 0) return `reduce the same-wave worker count, ${ways}`;
1069
+ return `a council runs its whole roster in one wave and cannot go below ${input.rosterFloor} members, so ${ways}`;
1070
+ }
1071
+ function assertCapacity(file, nodeId, endpointKey, limits) {
1164
1072
  const held2 = heldReservationUsage(file.reservations);
1165
1073
  const globalUsed = file.leases.length + held2.global;
1166
1074
  if (globalUsed >= limits.global) {
@@ -1175,6 +1083,23 @@ function assertCapacity(file, nodeId, limits) {
1175
1083
  if (used >= nodeLimit)
1176
1084
  throw new Error(`dispatch: admission denied: node '${nodeId}' capacity reached (${used}/${nodeLimit})`);
1177
1085
  }
1086
+ if (endpointKey !== void 0) {
1087
+ const endpointLimit = limits.endpoints[endpointKey];
1088
+ if (endpointLimit !== void 0) {
1089
+ if (endpointLimit < 1)
1090
+ throw new Error(`dispatch: admission denied: endpoint '${endpointLabel(endpointKey)}' capacity unavailable`);
1091
+ const holders = {
1092
+ leases: file.leases.filter((lease) => lease.endpointKey === endpointKey).length,
1093
+ reservations: held2.endpoints[endpointKey] ?? 0,
1094
+ foregroundStreams: foregroundStreamUsage()[endpointKey] ?? 0
1095
+ };
1096
+ const used = holders.leases + holders.reservations + holders.foregroundStreams;
1097
+ if (used >= endpointLimit)
1098
+ throw new Error(
1099
+ `dispatch: admission denied: endpoint '${endpointLabel(endpointKey)}' capacity reached (${used}/${endpointLimit} slots): ${describeEndpointCapacityHolders(holders)}; ${endpointCapacityRemedy()}`
1100
+ );
1101
+ }
1102
+ }
1178
1103
  }
1179
1104
  function acquireCapacityLease(input) {
1180
1105
  return withStateFileLockSync(capacityStateLockPath(), () => {
@@ -1188,10 +1113,12 @@ function acquireCapacityLease(input) {
1188
1113
  );
1189
1114
  const existing = file.leases.find((lease2) => lease2.assignmentId === input.assignmentId);
1190
1115
  if (existing) {
1191
- if (existing.nodeId !== input.nodeId) {
1116
+ if (existing.nodeId !== input.nodeId || existing.endpointKey !== input.endpointKey) {
1192
1117
  const without = { ...file, leases: file.leases.filter((lease2) => lease2 !== existing) };
1193
- assertCapacity(without, input.nodeId, input.limits);
1118
+ assertCapacity(without, input.nodeId, input.endpointKey, input.limits);
1194
1119
  existing.nodeId = input.nodeId;
1120
+ if (input.endpointKey === void 0) delete existing.endpointKey;
1121
+ else existing.endpointKey = input.endpointKey;
1195
1122
  }
1196
1123
  existing.heartbeatAt = new Date(nowMs).toISOString();
1197
1124
  existing.expiresAt = new Date(nowMs + (input.ttlMs ?? DEFAULT_CAPACITY_LEASE_TTL_MS)).toISOString();
@@ -1199,7 +1126,7 @@ function acquireCapacityLease(input) {
1199
1126
  return clone(existing);
1200
1127
  }
1201
1128
  input.onAcquiredUnderLock?.(file);
1202
- assertCapacity(file, input.nodeId, input.limits);
1129
+ assertCapacity(file, input.nodeId, input.endpointKey, input.limits);
1203
1130
  const token = input.processBirthToken ?? processBirthToken(input.ownerPid ?? process.pid);
1204
1131
  if (!token) throw new Error("dispatch: cannot establish process birth token");
1205
1132
  const at = new Date(nowMs).toISOString();
@@ -1207,6 +1134,7 @@ function acquireCapacityLease(input) {
1207
1134
  leaseId: `lease-${nowMs.toString(36)}-${randomBytes(6).toString("hex")}`,
1208
1135
  assignmentId: input.assignmentId,
1209
1136
  nodeId: input.nodeId,
1137
+ ...input.endpointKey !== void 0 ? { endpointKey: input.endpointKey } : {},
1210
1138
  host: hostname(),
1211
1139
  ownerPid: input.ownerPid ?? process.pid,
1212
1140
  processBirthToken: token,
@@ -1278,8 +1206,23 @@ function capacityDrain(nowMs = Date.now()) {
1278
1206
  function capacityLeaseUsage(options) {
1279
1207
  const leases = listCapacityLeases(options);
1280
1208
  const nodes = {};
1281
- for (const lease of leases) nodes[lease.nodeId] = (nodes[lease.nodeId] ?? 0) + 1;
1282
- return { global: leases.length, nodes };
1209
+ const foreground = foregroundStreamUsage();
1210
+ const endpoints = { ...foreground };
1211
+ const endpointHolders = Object.fromEntries(
1212
+ Object.entries(foreground).map(([endpointKey, foregroundStreams]) => [
1213
+ endpointKey,
1214
+ { leases: 0, reservations: 0, foregroundStreams }
1215
+ ])
1216
+ );
1217
+ for (const lease of leases) {
1218
+ nodes[lease.nodeId] = (nodes[lease.nodeId] ?? 0) + 1;
1219
+ if (lease.endpointKey !== void 0) {
1220
+ endpoints[lease.endpointKey] = (endpoints[lease.endpointKey] ?? 0) + 1;
1221
+ const holders = endpointHolders[lease.endpointKey] ?? { leases: 0, reservations: 0, foregroundStreams: 0 };
1222
+ endpointHolders[lease.endpointKey] = { ...holders, leases: holders.leases + 1 };
1223
+ }
1224
+ }
1225
+ return { global: leases.length, nodes, endpoints, endpointHolders };
1283
1226
  }
1284
1227
  function createNodeLeaseUsageReader(options) {
1285
1228
  const cacheMs = options.cacheMs ?? 200;
@@ -1487,7 +1430,7 @@ function renderDispatchReviewerTask(originalTask, builderRunId, cycle, intent) {
1487
1430
 
1488
1431
  // src/domains/dispatch/receipt-findings.ts
1489
1432
  init_esm_shims();
1490
- import { createHash as createHash12 } from "node:crypto";
1433
+ import { createHash as createHash10 } from "node:crypto";
1491
1434
 
1492
1435
  // src/domains/evidence/index.ts
1493
1436
  init_esm_shims();
@@ -1495,37 +1438,39 @@ init_esm_shims();
1495
1438
  // src/domains/evidence/build.ts
1496
1439
  init_esm_shims();
1497
1440
  import { mkdir, readFile as readFile2, writeFile } from "node:fs/promises";
1498
- import { join as join17 } from "node:path";
1441
+ import { join as join16 } from "node:path";
1499
1442
 
1500
1443
  // src/domains/dispatch/index.ts
1501
1444
  init_esm_shims();
1502
1445
 
1503
1446
  // src/domains/dispatch/extension.ts
1504
1447
  init_esm_shims();
1505
- import { createHash as createHash9, randomBytes as randomBytes6 } from "node:crypto";
1506
- import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync12 } from "node:fs";
1448
+ import { createHash as createHash7, randomBytes as randomBytes5 } from "node:crypto";
1449
+ import { readdirSync as readdirSync4, readFileSync as readFileSync11 } from "node:fs";
1507
1450
  import { isAbsolute as isAbsolute2, relative, resolve as resolvePath, sep } from "node:path";
1451
+ import { performance as performance5 } from "node:perf_hooks";
1508
1452
 
1509
1453
  // src/engine/acp/adapter.ts
1510
1454
  init_esm_shims();
1455
+ import { performance as performance4 } from "node:perf_hooks";
1511
1456
 
1512
1457
  // src/engine/acp/event-mapper.ts
1513
1458
  init_esm_shims();
1514
1459
  import { performance as performance2 } from "node:perf_hooks";
1515
- function isRecord3(value) {
1460
+ function isRecord2(value) {
1516
1461
  return typeof value === "object" && value !== null && !Array.isArray(value);
1517
1462
  }
1518
1463
  function textFromContent(value) {
1519
1464
  if (typeof value === "string") return value;
1520
- if (!isRecord3(value)) return "";
1465
+ if (!isRecord2(value)) return "";
1521
1466
  if (value.type === "text" && typeof value.text === "string") return value.text;
1522
- if (isRecord3(value.content)) return textFromContent(value.content);
1467
+ if (isRecord2(value.content)) return textFromContent(value.content);
1523
1468
  return "";
1524
1469
  }
1525
1470
  function toolContentText(value) {
1526
1471
  if (typeof value === "string") return value;
1527
1472
  if (Array.isArray(value)) return value.map(toolContentText).filter(Boolean).join("\n");
1528
- if (!isRecord3(value)) return "";
1473
+ if (!isRecord2(value)) return "";
1529
1474
  const direct = textFromContent(value);
1530
1475
  if (direct.length > 0) return direct;
1531
1476
  return "";
@@ -1548,8 +1493,8 @@ var AcpEventMapper = class {
1548
1493
  /** Tool-call id to its `performance.now()` start mark; spans only, never an instant. */
1549
1494
  toolStarts = /* @__PURE__ */ new Map();
1550
1495
  mapUpdate(params) {
1551
- const record = isRecord3(params) ? params : {};
1552
- const update = isRecord3(record.update) ? record.update : {};
1496
+ const record = isRecord2(params) ? params : {};
1497
+ const update = isRecord2(record.update) ? record.update : {};
1553
1498
  const kind = typeof update.sessionUpdate === "string" ? update.sessionUpdate : "";
1554
1499
  if (kind === "agent_message_chunk" || kind === "user_message_chunk") {
1555
1500
  const text = textFromContent(update.content);
@@ -1716,7 +1661,7 @@ var MOVE_DESTINATION_PATH_KEYS = [
1716
1661
  "new_path",
1717
1662
  "target"
1718
1663
  ];
1719
- function isRecord4(value) {
1664
+ function isRecord3(value) {
1720
1665
  return typeof value === "object" && value !== null && !Array.isArray(value);
1721
1666
  }
1722
1667
  function stringField(record, ...keys) {
@@ -1850,7 +1795,7 @@ function extractLocationPaths(locations, cwd) {
1850
1795
  const paths = [];
1851
1796
  const errors = [];
1852
1797
  for (const value of locations) {
1853
- if (!isRecord4(value)) {
1798
+ if (!isRecord3(value)) {
1854
1799
  errors.push("locations contains a non-object entry");
1855
1800
  continue;
1856
1801
  }
@@ -1865,11 +1810,11 @@ function extractLocationPaths(locations, cwd) {
1865
1810
  return { paths, provided: true, errors };
1866
1811
  }
1867
1812
  function mutationTargets(toolCall, kind, cwd) {
1868
- const rawInput = isRecord4(toolCall?.rawInput) ? toolCall.rawInput : {};
1813
+ const rawInput = isRecord3(toolCall?.rawInput) ? toolCall.rawInput : {};
1869
1814
  const raw = extractRawMutationPaths(rawInput, kind, cwd);
1870
1815
  const locations = extractLocationPaths(toolCall?.locations, cwd);
1871
1816
  const errors = [...raw.errors, ...locations.errors];
1872
- if (toolCall?.rawInput !== void 0 && !isRecord4(toolCall.rawInput)) {
1817
+ if (toolCall?.rawInput !== void 0 && !isRecord3(toolCall.rawInput)) {
1873
1818
  errors.push("rawInput must be an object");
1874
1819
  }
1875
1820
  if (raw.provided && locations.provided && !samePathSet(raw.paths, locations.paths)) {
@@ -1939,11 +1884,11 @@ function mapMutationToolCall(toolCall, kind, displayTool, cwd, metadataError) {
1939
1884
  };
1940
1885
  }
1941
1886
  function mapPathBearingToolCall(toolCall, tool, displayTool, cwd, targetRequired) {
1942
- const rawInput = isRecord4(toolCall?.rawInput) ? toolCall.rawInput : {};
1887
+ const rawInput = isRecord3(toolCall?.rawInput) ? toolCall.rawInput : {};
1943
1888
  const raw = extractPathFields(rawInput, SINGLE_MUTATION_PATH_KEYS, MULTI_MUTATION_PATH_KEYS, cwd, "rawInput");
1944
1889
  const locations = extractLocationPaths(toolCall?.locations, cwd);
1945
1890
  const errors = [...raw.errors, ...locations.errors];
1946
- if (toolCall?.rawInput !== void 0 && !isRecord4(toolCall.rawInput)) errors.push("rawInput must be an object");
1891
+ if (toolCall?.rawInput !== void 0 && !isRecord3(toolCall.rawInput)) errors.push("rawInput must be an object");
1947
1892
  if (raw.provided && locations.provided && !samePathSet(raw.paths, locations.paths)) {
1948
1893
  errors.push("rawInput and locations contain conflicting path targets");
1949
1894
  }
@@ -1964,7 +1909,7 @@ function mapPathBearingToolCall(toolCall, tool, displayTool, cwd, targetRequired
1964
1909
  }
1965
1910
  function mapToolCall(toolCall, cwd) {
1966
1911
  const kind = typeof toolCall?.kind === "string" ? toolCall.kind.toLowerCase() : "";
1967
- const rawInput = isRecord4(toolCall?.rawInput) ? toolCall.rawInput : {};
1912
+ const rawInput = isRecord3(toolCall?.rawInput) ? toolCall.rawInput : {};
1968
1913
  const rawTool = stringField(rawInput, "tool", "toolName", "tool_name", "name");
1969
1914
  const title = typeof toolCall?.title === "string" ? toolCall.title : void 0;
1970
1915
  const displayTool = rawTool ?? kind ?? title ?? "unknown";
@@ -2068,9 +2013,9 @@ var AcpToolMediator = class {
2068
2013
  async handle(params) {
2069
2014
  const startedAt = performance3.now();
2070
2015
  this.requested += 1;
2071
- const parsed = isRecord4(params) ? params : {};
2016
+ const parsed = isRecord3(params) ? params : {};
2072
2017
  const options = Array.isArray(parsed.options) ? parsed.options : [];
2073
- const toolCall = isRecord4(parsed.toolCall) ? parsed.toolCall : void 0;
2018
+ const toolCall = isRecord3(parsed.toolCall) ? parsed.toolCall : void 0;
2074
2019
  const mapped = mapToolCall(toolCall, this.input.cwd);
2075
2020
  let decision = "denied";
2076
2021
  let reason;
@@ -2173,6 +2118,7 @@ var AcpToolMediator = class {
2173
2118
  init_esm_shims();
2174
2119
  var ACP_USAGE_META_KEY = "clio-coder/usage";
2175
2120
  var ACP_SESSION_META_KEY = "clio-coder/session";
2121
+ var ACP_AGENT_META_KEY = "clio-coder/agent";
2176
2122
  var ACP_MAX_STRING_BYTES = 4096;
2177
2123
  var ACP_MAX_RAW_RECORD_BYTES = 32768;
2178
2124
  var ACP_MAX_CHUNK_BYTES = 16384;
@@ -2191,7 +2137,7 @@ var AsyncEventQueue = class {
2191
2137
  const value = this.values.shift();
2192
2138
  if (value !== void 0) return Promise.resolve({ done: false, value });
2193
2139
  if (this.done) return Promise.resolve({ done: true, value: void 0 });
2194
- return new Promise((resolve5) => this.waiters.push(resolve5));
2140
+ return new Promise((resolve4) => this.waiters.push(resolve4));
2195
2141
  }
2196
2142
  push(value) {
2197
2143
  if (this.done) return;
@@ -2211,22 +2157,22 @@ var AsyncEventQueue = class {
2211
2157
  }
2212
2158
  }
2213
2159
  };
2214
- function isRecord5(value) {
2160
+ function isRecord4(value) {
2215
2161
  return typeof value === "object" && value !== null && !Array.isArray(value);
2216
2162
  }
2217
2163
  function sessionIdFrom(value) {
2218
2164
  if (typeof value === "string" && value.length > 0) return value;
2219
- if (!isRecord5(value)) return null;
2165
+ if (!isRecord4(value)) return null;
2220
2166
  const sessionId = value.sessionId ?? value.id;
2221
2167
  return typeof sessionId === "string" && sessionId.length > 0 ? sessionId : null;
2222
2168
  }
2223
2169
  function supportsSessionClose(init) {
2224
2170
  const caps = init?.agentCapabilities;
2225
- if (!isRecord5(caps)) return false;
2226
- const meta = isRecord5(caps._meta) ? caps._meta[ACP_SESSION_META_KEY] : void 0;
2227
- if (isRecord5(meta) && meta.close === true) return true;
2171
+ if (!isRecord4(caps)) return false;
2172
+ const meta = isRecord4(caps._meta) ? caps._meta[ACP_SESSION_META_KEY] : void 0;
2173
+ if (isRecord4(meta) && meta.close === true) return true;
2228
2174
  const sessionCaps = caps.sessionCapabilities;
2229
- return isRecord5(sessionCaps) && isRecord5(sessionCaps.close);
2175
+ return isRecord4(sessionCaps) && isRecord4(sessionCaps.close);
2230
2176
  }
2231
2177
  function flattenPrompt(input) {
2232
2178
  const parts = [
@@ -2250,7 +2196,7 @@ function finite(value) {
2250
2196
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
2251
2197
  }
2252
2198
  function mergeUsage(into, raw) {
2253
- if (!isRecord5(raw)) return;
2199
+ if (!isRecord4(raw)) return;
2254
2200
  into.inputTokens += finite(raw.input) + finite(raw.inputTokens) + finite(raw.input_tokens);
2255
2201
  into.outputTokens += finite(raw.output) + finite(raw.outputTokens) + finite(raw.output_tokens);
2256
2202
  into.cacheReadTokens += finite(raw.cacheRead) + finite(raw.cacheReadTokens) + finite(raw.cache_read_tokens);
@@ -2276,7 +2222,14 @@ function errorEvents(messageText2) {
2276
2222
  function startAcpDelegationRun(input) {
2277
2223
  const connectTimeoutMs = input.agent.connectTimeoutMs ?? DEFAULT_DELEGATION_CONNECT_TIMEOUT_MS;
2278
2224
  const turnTimeoutMs = input.agent.turnTimeoutMs ?? DEFAULT_DELEGATION_TURN_TIMEOUT_MS;
2279
- const heartbeatAt = { current: Date.now() };
2225
+ const now = input.now ?? Date.now;
2226
+ const monotonicNow = input.monotonicNow ?? (() => performance4.now());
2227
+ const heartbeatWallAnchor = now();
2228
+ const heartbeatMonotonicAnchor = monotonicNow();
2229
+ const heartbeatAt = {
2230
+ current: heartbeatWallAnchor,
2231
+ monotonic: heartbeatMonotonicAnchor
2232
+ };
2280
2233
  const queue = new AsyncEventQueue();
2281
2234
  const usage = emptyUsage();
2282
2235
  const mapper = new AcpEventMapper();
@@ -2303,7 +2256,9 @@ function startAcpDelegationRun(input) {
2303
2256
  cancelTimer = null;
2304
2257
  };
2305
2258
  const emit = (event) => {
2306
- heartbeatAt.current = Date.now();
2259
+ const stamp = monotonicNow();
2260
+ heartbeatAt.monotonic = stamp;
2261
+ heartbeatAt.current = heartbeatWallAnchor + (stamp - heartbeatMonotonicAnchor);
2307
2262
  queue.push(event);
2308
2263
  };
2309
2264
  const mediator = new AcpToolMediator({
@@ -2387,7 +2342,7 @@ function startAcpDelegationRun(input) {
2387
2342
  },
2388
2343
  turnTimeoutMs
2389
2344
  );
2390
- const metaUsage = isRecord5(promptResponse?._meta) ? promptResponse._meta[ACP_USAGE_META_KEY] : void 0;
2345
+ const metaUsage = isRecord4(promptResponse?._meta) ? promptResponse._meta[ACP_USAGE_META_KEY] : void 0;
2391
2346
  if (metaUsage !== void 0) {
2392
2347
  mergeUsage(usage, metaUsage);
2393
2348
  } else {
@@ -2478,62 +2433,6 @@ function startAcpDelegationRun(input) {
2478
2433
  // src/domains/prompts/compiler.ts
2479
2434
  init_esm_shims();
2480
2435
  import { join as join3 } from "node:path";
2481
-
2482
- // src/domains/prompts/hash.ts
2483
- init_esm_shims();
2484
- import { createHash as createHash2 } from "node:crypto";
2485
- function sha256(input) {
2486
- return createHash2("sha256").update(input, "utf8").digest("hex");
2487
- }
2488
- function canonicalJson2(value) {
2489
- return serialize(value);
2490
- }
2491
- function serialize(value) {
2492
- if (value === null) return "null";
2493
- if (typeof value === "number") {
2494
- if (!Number.isFinite(value)) {
2495
- throw new Error(`canonicalJson: non-finite number ${String(value)} is not representable`);
2496
- }
2497
- return JSON.stringify(value);
2498
- }
2499
- if (typeof value === "string" || typeof value === "boolean") {
2500
- return JSON.stringify(value);
2501
- }
2502
- if (typeof value === "bigint") {
2503
- throw new Error("canonicalJson: bigint is not representable");
2504
- }
2505
- if (typeof value === "symbol" || typeof value === "function") {
2506
- throw new Error(`canonicalJson: ${typeof value} is not representable`);
2507
- }
2508
- if (value === void 0) {
2509
- throw new Error("canonicalJson: undefined is not representable at root");
2510
- }
2511
- if (Array.isArray(value)) {
2512
- const parts = [];
2513
- for (let i = 0; i < value.length; i++) {
2514
- if (!(i in value) || value[i] === void 0) {
2515
- parts.push("null");
2516
- continue;
2517
- }
2518
- parts.push(serialize(value[i]));
2519
- }
2520
- return `[${parts.join(",")}]`;
2521
- }
2522
- if (typeof value === "object") {
2523
- const obj = value;
2524
- const keys = Object.keys(obj).sort();
2525
- const parts = [];
2526
- for (const key of keys) {
2527
- const child = obj[key];
2528
- if (child === void 0) continue;
2529
- parts.push(`${JSON.stringify(key)}:${serialize(child)}`);
2530
- }
2531
- return `{${parts.join(",")}}`;
2532
- }
2533
- throw new Error(`canonicalJson: unsupported value of type ${typeof value}`);
2534
- }
2535
-
2536
- // src/domains/prompts/compiler.ts
2537
2436
  var FLEET_ROUTING_GUIDANCE = 'Fleet routing: pin the `agent` id from the Fleet section; agent:"auto" baselines from the task text and is a fallback, not a router.';
2538
2437
  var WORKER_CLAIM_GUIDANCE = 'Never claim a completion, a validation, or a file change that no tool call in this run supports. If you did not run it or write it here, say "not verified" and report what you did do.';
2539
2438
  function lookupFragment(table, id, role) {
@@ -2745,15 +2644,45 @@ function renderProjectBlock(contextFiles) {
2745
2644
 
2746
2645
  ${trimmedFiles}`;
2747
2646
  }
2748
- function renderMemoryBlock(memorySection) {
2647
+ function renderMemoryBlock(memorySection, legacyDuplicateHeader = false) {
2749
2648
  const trimmed = memorySection?.trim() ?? "";
2750
- return trimmed.length === 0 ? "" : `# Memory
2649
+ if (trimmed.length === 0) return "";
2650
+ if (legacyDuplicateHeader) return `# Memory
2651
+
2652
+ ${trimmed}`;
2653
+ return /^#\s+Memory\s*$/.test(trimmed.split("\n", 1)[0] ?? "") ? trimmed : `# Memory
2751
2654
 
2752
2655
  ${trimmed}`;
2753
2656
  }
2754
2657
  function estimatePromptTokens(text) {
2755
2658
  return ceilChars(text.trim().length);
2756
2659
  }
2660
+ var SESSION_PROMPT_SECTION_ORDER = [
2661
+ "identity",
2662
+ "operating-contract",
2663
+ "delegation",
2664
+ "skills",
2665
+ "safety",
2666
+ "tool-contract",
2667
+ "fleet",
2668
+ "retrieval-hints",
2669
+ "project-context",
2670
+ "memory",
2671
+ "runtime"
2672
+ ];
2673
+ var LEGACY_SESSION_PROMPT_SECTION_ORDER = [
2674
+ "identity",
2675
+ "operating-contract",
2676
+ "delegation",
2677
+ "skills",
2678
+ "safety",
2679
+ "runtime",
2680
+ "tool-contract",
2681
+ "fleet",
2682
+ "retrieval-hints",
2683
+ "memory",
2684
+ "project-context"
2685
+ ];
2757
2686
  function compile(table, inputs) {
2758
2687
  const identity = lookupFragment(table, inputs.identity, "identity");
2759
2688
  const operatingContract = lookupFragment(table, inputs.operatingContract, "operating contract");
@@ -2773,24 +2702,29 @@ function compile(table, inputs) {
2773
2702
  const docsRouting = selfAwareness && sessionHasContext(session) ? table.byId.get("identity.docs-routing") : void 0;
2774
2703
  if (selfAwareness) {
2775
2704
  const packageRoot = resolvePackageRoot();
2776
- const rendered = selfAwareness.body.replace("{CLIO_DOCS_PATH}", join3(packageRoot, "docs")).replace("{CLIO_SRC_PATH}", join3(packageRoot, "src")).replace("{CLIO_CODEWIKI_PATH}", join3(packageRoot, "dist", "assets", "codewiki.json"));
2777
- identityBody = [identity.body.trim(), rendered.trim(), ...docsRouting ? [docsRouting.body.trim()] : []].join(
2705
+ const rendered2 = selfAwareness.body.replace("{CLIO_DOCS_PATH}", join3(packageRoot, "docs")).replace("{CLIO_SRC_PATH}", join3(packageRoot, "src")).replace("{CLIO_CODEWIKI_PATH}", join3(packageRoot, "dist", "assets", "codewiki.json"));
2706
+ identityBody = [identity.body.trim(), rendered2.trim(), ...docsRouting ? [docsRouting.body.trim()] : []].join(
2778
2707
  "\n\n"
2779
2708
  );
2780
2709
  }
2781
2710
  const delegation = sessionCanDispatch(session) ? table.byId.get("operating.delegation") : void 0;
2782
2711
  const skills = sessionHasContext(session) ? table.byId.get("operating.skills") : void 0;
2783
- push("identity", identityBody);
2784
- push("operating-contract", operatingContract.body);
2785
- if (delegation) push("delegation", delegation.body);
2786
- if (skills) push("skills", skills.body);
2787
- push("safety", renderSafetySection(safety, autonomyLevel));
2788
- push("runtime", renderRuntimeBlock(session));
2789
- push("tool-contract", renderToolContractBlock(session));
2790
- push("fleet", renderFleetBlock(session));
2791
- push("retrieval-hints", renderRetrievalHintsBlock(session));
2792
- push("memory", renderMemoryBlock(session.memorySection));
2793
- push("project-context", renderProjectBlock(session.contextFiles));
2712
+ const legacy = inputs.sectionOrder === "legacy-0.3.8";
2713
+ const rendered = /* @__PURE__ */ new Map([
2714
+ ["identity", identityBody],
2715
+ ["operating-contract", operatingContract.body],
2716
+ ["delegation", delegation?.body ?? ""],
2717
+ ["skills", skills?.body ?? ""],
2718
+ ["safety", renderSafetySection(safety, autonomyLevel)],
2719
+ ["runtime", renderRuntimeBlock(session)],
2720
+ ["tool-contract", renderToolContractBlock(session)],
2721
+ ["fleet", renderFleetBlock(session)],
2722
+ ["retrieval-hints", renderRetrievalHintsBlock(session)],
2723
+ ["memory", renderMemoryBlock(session.memorySection, legacy)],
2724
+ ["project-context", renderProjectBlock(session.contextFiles)]
2725
+ ]);
2726
+ const order = legacy ? LEGACY_SESSION_PROMPT_SECTION_ORDER : SESSION_PROMPT_SECTION_ORDER;
2727
+ for (const id of order) push(id, rendered.get(id) ?? "");
2794
2728
  for (const fragment of inputs.additionalFragments ?? []) {
2795
2729
  push(fragment.id, fragment.body);
2796
2730
  }
@@ -2926,8 +2860,8 @@ function createAssignmentEventStream(options = {}) {
2926
2860
  return Promise.resolve({ value: pending.shift(), done: false });
2927
2861
  }
2928
2862
  if (finished || abandoned) return Promise.resolve({ value: void 0, done: true });
2929
- return new Promise((resolve5) => {
2930
- waiters.push(resolve5);
2863
+ return new Promise((resolve4) => {
2864
+ waiters.push(resolve4);
2931
2865
  });
2932
2866
  },
2933
2867
  return() {
@@ -3031,10 +2965,10 @@ var AssignmentRegistry = class {
3031
2965
  const id = asAssignmentId(rootRunId);
3032
2966
  const existing = this.#assignments.get(id);
3033
2967
  if (existing) return this.#snapshot(existing);
3034
- let resolve5;
2968
+ let resolve4;
3035
2969
  let reject;
3036
2970
  const terminal = new Promise((resolvePromise, rejectPromise) => {
3037
- resolve5 = resolvePromise;
2971
+ resolve4 = resolvePromise;
3038
2972
  reject = rejectPromise;
3039
2973
  });
3040
2974
  const assignment = {
@@ -3049,7 +2983,7 @@ var AssignmentRegistry = class {
3049
2983
  outcomeDetail: null,
3050
2984
  terminal,
3051
2985
  stream: createAssignmentEventStream(this.#onStreamError !== void 0 ? { onError: this.#onStreamError } : {}),
3052
- resolve: resolve5,
2986
+ resolve: resolve4,
3053
2987
  reject
3054
2988
  };
3055
2989
  this.#assignments.set(id, assignment);
@@ -3289,10 +3223,10 @@ function createAdmissionQueue(options) {
3289
3223
  const effectiveDeadline = Math.min(request.deadlineAt, request.queuedAt + options.finiteCeilingMs);
3290
3224
  if (!Number.isFinite(effectiveDeadline))
3291
3225
  return Promise.reject(new Error("dispatch: queued request requires a finite deadline"));
3292
- return new Promise((resolve5, reject) => {
3226
+ return new Promise((resolve4, reject) => {
3293
3227
  const bounded = { ...request, deadlineAt: effectiveDeadline };
3294
3228
  const timer = setTimeout(() => remove(request.requestId, "timed_out"), Math.max(0, effectiveDeadline - now()));
3295
- entries.set(request.requestId, { request: bounded, resolve: resolve5, reject, timer });
3229
+ entries.set(request.requestId, { request: bounded, resolve: resolve4, reject, timer });
3296
3230
  });
3297
3231
  },
3298
3232
  cancel(requestId) {
@@ -3355,14 +3289,18 @@ init_esm_shims();
3355
3289
  import { randomBytes as randomBytes2 } from "node:crypto";
3356
3290
  var MAX_RESERVATION_RECORDS = 500;
3357
3291
  var DEFAULT_RESERVATION_TTL_MS = 15 * 6e4;
3292
+ function endpointCapacityDenial(input) {
3293
+ const remedy = endpointCapacityRemedy(input.topology === "council" ? { rosterFloor: COUNCIL_MIN_MEMBERS } : void 0);
3294
+ return `dispatch: admission denied: endpoint '${endpointLabel(input.endpointKey)}' capacity exceeded (${input.used + input.requested}/${input.limit} slots): ${describeEndpointCapacityHolders(input)}; ${remedy}`;
3295
+ }
3358
3296
  function copyRecord(record) {
3359
3297
  return { ...record, members: record.members.map((member) => ({ ...member })) };
3360
3298
  }
3361
3299
  function validRecord(value) {
3362
3300
  if (typeof value !== "object" || value === null) return false;
3363
3301
  const record = value;
3364
- return typeof record.ownerId === "string" && typeof record.ownerPid === "number" && Number.isInteger(record.ownerPid) && record.ownerPid > 0 && (record.topology === "parallel" || record.topology === "detached" || record.topology === "sequential" || record.topology === "pipeline" || record.topology === "review" || record.topology === "compete") && (record.status === "active" || record.status === "released" || record.status === "rolled_back" || record.status === "expired") && typeof record.createdAt === "string" && typeof record.expiresAt === "string" && (record.settledAt === null || typeof record.settledAt === "string") && Array.isArray(record.members) && record.members.every(
3365
- (member) => typeof member.memberId === "string" && Number.isInteger(member.wave) && typeof member.nodeId === "string" && typeof member.costUpperBoundUsd === "number" && Number.isFinite(member.costUpperBoundUsd) && member.costUpperBoundUsd >= 0 && (member.status === "held" || member.status === "consumed" || member.status === "released") && (member.consumedAt === null || typeof member.consumedAt === "string") && (member.releasedAt === null || typeof member.releasedAt === "string")
3302
+ return typeof record.ownerId === "string" && typeof record.ownerPid === "number" && Number.isInteger(record.ownerPid) && record.ownerPid > 0 && (record.topology === "parallel" || record.topology === "detached" || record.topology === "sequential" || record.topology === "pipeline" || record.topology === "review" || record.topology === "compete" || record.topology === "council") && (record.status === "active" || record.status === "released" || record.status === "rolled_back" || record.status === "expired") && typeof record.createdAt === "string" && typeof record.expiresAt === "string" && (record.settledAt === null || typeof record.settledAt === "string") && Array.isArray(record.members) && record.members.every(
3303
+ (member) => typeof member.memberId === "string" && Number.isInteger(member.wave) && typeof member.nodeId === "string" && (member.endpointKey === void 0 || typeof member.endpointKey === "string") && typeof member.costUpperBoundUsd === "number" && Number.isFinite(member.costUpperBoundUsd) && member.costUpperBoundUsd >= 0 && (member.status === "held" || member.status === "consumed" || member.status === "released") && (member.consumedAt === null || typeof member.consumedAt === "string") && (member.releasedAt === null || typeof member.releasedAt === "string")
3366
3304
  );
3367
3305
  }
3368
3306
  function parseReservations(values) {
@@ -3399,9 +3337,13 @@ function reservationAllocation(tasks) {
3399
3337
  )
3400
3338
  );
3401
3339
  const nodeSlots = peakBy(tasks.map((task) => ({ wave: task.wave, key: task.nodeId })));
3340
+ const endpointSlots = peakBy(
3341
+ tasks.flatMap((task) => task.endpointKey === void 0 ? [] : [{ wave: task.wave, key: task.endpointKey }])
3342
+ );
3402
3343
  return {
3403
3344
  globalSlots,
3404
3345
  nodeSlots,
3346
+ endpointSlots,
3405
3347
  budgetUsd: tasks.reduce((sum, task) => sum + task.costUpperBoundUsd, 0)
3406
3348
  };
3407
3349
  }
@@ -3411,7 +3353,7 @@ function outstandingTasks(record) {
3411
3353
  function outstandingBudget(record) {
3412
3354
  return record.members.filter((member) => member.status === "held" || member.status === "consumed").reduce((sum, member) => sum + member.costUpperBoundUsd, 0);
3413
3355
  }
3414
- function allocateReservation(tasks, existing, capacity) {
3356
+ function allocateReservation(tasks, existing, capacity, topology) {
3415
3357
  if (tasks.length === 0) return { ok: false, reason: "reservation requires at least one task" };
3416
3358
  const duplicate = tasks.find((task, index) => tasks.slice(0, index).some((entry) => entry.memberId === task.memberId));
3417
3359
  if (duplicate) return { ok: false, reason: `duplicate reservation member '${duplicate.memberId}'` };
@@ -3434,6 +3376,27 @@ function allocateReservation(tasks, existing, capacity) {
3434
3376
  return { ok: false, reason: `node '${nodeId}' capacity exceeded (${used + slots}/${node.limit})` };
3435
3377
  }
3436
3378
  }
3379
+ for (const [endpointKey, slots] of Object.entries(requested.endpointSlots)) {
3380
+ const endpoint = capacity.endpoints[endpointKey];
3381
+ if (!endpoint || !Number.isFinite(endpoint.limit)) continue;
3382
+ const heldSlots = held2.reduce((sum, allocation) => sum + (allocation.endpointSlots[endpointKey] ?? 0), 0);
3383
+ const used = endpoint.active + heldSlots;
3384
+ if (used + slots > endpoint.limit) {
3385
+ return {
3386
+ ok: false,
3387
+ reason: endpointCapacityDenial({
3388
+ endpointKey,
3389
+ limit: endpoint.limit,
3390
+ used,
3391
+ requested: slots,
3392
+ leases: endpoint.leases ?? endpoint.active - (endpoint.foregroundStreams ?? 0),
3393
+ reservations: heldSlots,
3394
+ foregroundStreams: endpoint.foregroundStreams ?? 0,
3395
+ ...topology === void 0 ? {} : { topology }
3396
+ })
3397
+ };
3398
+ }
3399
+ }
3437
3400
  const existingBudget = activeRecords.reduce((sum, record) => sum + outstandingBudget(record), 0);
3438
3401
  const projected = capacity.budget.currentUsd + existingBudget + requested.budgetUsd;
3439
3402
  if (projected >= capacity.budget.ceilingUsd) {
@@ -3457,11 +3420,13 @@ function createDispatchReservation(input) {
3457
3420
  `dispatch: reservation denied: capacity is draining (requested by pid ${drain.requestedByPid} at ${drain.requestedAt})`
3458
3421
  );
3459
3422
  }
3460
- const planned = allocateReservation(input.tasks, records, input.capacity);
3423
+ const planned = allocateReservation(input.tasks, records, input.capacity, input.topology);
3461
3424
  if (!planned.ok) {
3462
3425
  replaceReservations(state, records);
3463
3426
  writeCapacityStateUnsafe(state);
3464
- throw new Error(`dispatch: reservation denied: ${planned.reason}`);
3427
+ throw new Error(
3428
+ planned.reason.startsWith("dispatch:") ? planned.reason : `dispatch: reservation denied: ${planned.reason}`
3429
+ );
3465
3430
  }
3466
3431
  const createdAt = new Date(nowMs).toISOString();
3467
3432
  const record = {
@@ -3484,6 +3449,7 @@ function transferDispatchReservationToLease(input) {
3484
3449
  return acquireCapacityLease({
3485
3450
  assignmentId: input.assignmentId,
3486
3451
  nodeId: input.nodeId,
3452
+ ...input.endpointKey !== void 0 ? { endpointKey: input.endpointKey } : {},
3487
3453
  limits: input.limits,
3488
3454
  nowMs,
3489
3455
  ...input.ttlMs !== void 0 ? { ttlMs: input.ttlMs } : {},
@@ -3511,10 +3477,37 @@ function rebindDispatchReservationMember(input) {
3511
3477
  if (member.status === "released") {
3512
3478
  throw new Error(`dispatch: reservation member '${input.memberId}' was already released`);
3513
3479
  }
3514
- if (member.nodeId === input.nodeId && member.costUpperBoundUsd === input.costUpperBoundUsd) {
3480
+ if (member.nodeId === input.nodeId && member.endpointKey === input.endpointKey && member.costUpperBoundUsd === input.costUpperBoundUsd) {
3515
3481
  return copyRecord(record);
3516
3482
  }
3517
3483
  const others = records.filter((entry) => entry.status === "active" && entry.ownerId !== input.ownerId);
3484
+ if (member.endpointKey !== input.endpointKey && input.endpointKey !== void 0) {
3485
+ const endpointKey = input.endpointKey;
3486
+ const endpoint = input.capacity.endpoints[endpointKey];
3487
+ if (endpoint !== void 0 && Number.isFinite(endpoint.limit)) {
3488
+ const siblingSlots = record.members.filter(
3489
+ (entry) => entry !== member && entry.status !== "released" && entry.endpointKey === endpointKey
3490
+ ).length;
3491
+ const otherHeld = others.reduce(
3492
+ (sum, entry) => sum + (reservationAllocation(outstandingTasks(entry)).endpointSlots[endpointKey] ?? 0),
3493
+ 0
3494
+ );
3495
+ const used = endpoint.active + otherHeld + siblingSlots;
3496
+ if (used + 1 > endpoint.limit) {
3497
+ throw new Error(
3498
+ endpointCapacityDenial({
3499
+ endpointKey,
3500
+ limit: endpoint.limit,
3501
+ used,
3502
+ requested: 1,
3503
+ leases: endpoint.leases ?? endpoint.active - (endpoint.foregroundStreams ?? 0),
3504
+ reservations: otherHeld + siblingSlots,
3505
+ foregroundStreams: endpoint.foregroundStreams ?? 0
3506
+ })
3507
+ );
3508
+ }
3509
+ }
3510
+ }
3518
3511
  if (member.nodeId !== input.nodeId) {
3519
3512
  const node = input.capacity.nodes[input.nodeId];
3520
3513
  if (node !== void 0 && Number.isFinite(node.limit)) {
@@ -3542,6 +3535,8 @@ function rebindDispatchReservationMember(input) {
3542
3535
  );
3543
3536
  }
3544
3537
  member.nodeId = input.nodeId;
3538
+ if (input.endpointKey === void 0) delete member.endpointKey;
3539
+ else member.endpointKey = input.endpointKey;
3545
3540
  member.costUpperBoundUsd = Math.max(0, input.costUpperBoundUsd);
3546
3541
  writeStore2(records);
3547
3542
  return copyRecord(record);
@@ -3564,6 +3559,24 @@ function releaseDispatchReservationMember(ownerId, memberId, nowMs = Date.now())
3564
3559
  return copyRecord(record);
3565
3560
  });
3566
3561
  }
3562
+ function releaseDispatchReservation(ownerId, nowMs = Date.now()) {
3563
+ return withStateFileLockSync(capacityStateLockPath(), () => {
3564
+ const records = readStore2();
3565
+ const record = records.find((entry) => entry.ownerId === ownerId);
3566
+ if (!record) return null;
3567
+ if (record.status !== "active") return copyRecord(record);
3568
+ const settledAt = new Date(nowMs).toISOString();
3569
+ for (const member of record.members) {
3570
+ if (member.status === "released") continue;
3571
+ member.status = "released";
3572
+ member.releasedAt = settledAt;
3573
+ }
3574
+ record.status = "released";
3575
+ record.settledAt = settledAt;
3576
+ writeStore2(records);
3577
+ return copyRecord(record);
3578
+ });
3579
+ }
3567
3580
  function rollbackDispatchReservation(ownerId, nowMs = Date.now()) {
3568
3581
  return withStateFileLockSync(capacityStateLockPath(), () => {
3569
3582
  const records = readStore2();
@@ -3668,6 +3681,20 @@ var PUMP_MIN_MS = 10;
3668
3681
  var PUMP_MAX_MS = 500;
3669
3682
  function describeAdmissionFailure(input) {
3670
3683
  if (input.state === "canceled") return "dispatch: admission canceled before a capacity slot opened";
3684
+ if (input.endpointKey !== void 0) {
3685
+ const endpointLimit = input.limits.endpoints[input.endpointKey];
3686
+ const endpointActive = input.usage.endpoints[input.endpointKey] ?? 0;
3687
+ if (endpointLimit !== void 0 && endpointActive >= endpointLimit) {
3688
+ const holders = input.usage.endpointHolders?.[input.endpointKey];
3689
+ const occupancy = holders === void 0 ? "the supplied capacity snapshot does not attribute the occupied slots" : describeEndpointCapacityHolders(holders);
3690
+ const queued2 = input.queueDepth > 0 ? `, ${input.queueDepth} more queued` : "";
3691
+ return [
3692
+ `dispatch: admission timed out after ${Math.round(input.waitedMs)}ms waiting for an endpoint slot`,
3693
+ ` on '${endpointLabel(input.endpointKey)}' (${endpointActive}/${endpointLimit} slots${queued2}): ${occupancy}.`,
3694
+ " Wait for the running request to settle or dispatch this work again."
3695
+ ].join("");
3696
+ }
3697
+ }
3671
3698
  const nodeLimit = input.limits.nodes[input.nodeId];
3672
3699
  const nodeActive = input.usage.nodes[input.nodeId] ?? 0;
3673
3700
  const where = nodeLimit === void 0 ? `${input.usage.global}/${input.limits.global} worker slots in use` : `${nodeActive}/${nodeLimit} worker slots in use on '${input.nodeId}', ${input.usage.global}/${input.limits.global} globally`;
@@ -3759,11 +3786,13 @@ function createCapacityAdmissionController(options) {
3759
3786
  memberId: input.reservation.memberId,
3760
3787
  assignmentId: input.assignmentId,
3761
3788
  nodeId: input.nodeId,
3789
+ ...input.endpointKey !== void 0 ? { endpointKey: input.endpointKey } : {},
3762
3790
  limits: options.limits(),
3763
3791
  nowMs: now()
3764
3792
  }) : acquireCapacityLease({
3765
3793
  assignmentId: input.assignmentId,
3766
3794
  nodeId: input.nodeId,
3795
+ ...input.endpointKey !== void 0 ? { endpointKey: input.endpointKey } : {},
3767
3796
  limits: options.limits(),
3768
3797
  nowMs: now()
3769
3798
  })
@@ -3771,17 +3800,18 @@ function createCapacityAdmissionController(options) {
3771
3800
  pumpNow();
3772
3801
  const outcome = await outcomePromise;
3773
3802
  if (outcome.state !== "admitted") {
3774
- throw new Error(
3775
- describeAdmissionFailure({
3776
- state: outcome.state,
3777
- nodeId: input.nodeId,
3778
- waitedMs: now() - queuedAt,
3779
- overdueAtQueueMs: queuedAt - input.deadlineAt,
3780
- queueDepth: queue.size(),
3781
- limits: options.limits(),
3782
- usage: options.usage?.() ?? capacityLeaseUsage({ nowMs: now() })
3783
- })
3784
- );
3803
+ const detail = describeAdmissionFailure({
3804
+ state: outcome.state,
3805
+ nodeId: input.nodeId,
3806
+ ...input.endpointKey !== void 0 ? { endpointKey: input.endpointKey } : {},
3807
+ waitedMs: now() - queuedAt,
3808
+ overdueAtQueueMs: queuedAt - input.deadlineAt,
3809
+ queueDepth: queue.size(),
3810
+ limits: options.limits(),
3811
+ usage: options.usage?.() ?? capacityLeaseUsage({ nowMs: now() })
3812
+ });
3813
+ if (outcome.state === "canceled") throw new AdmissionCanceledError(detail);
3814
+ throw new Error(detail);
3785
3815
  }
3786
3816
  const lease = acquired.get(input.assignmentId);
3787
3817
  if (!lease) throw new Error("dispatch: admitted request has no capacity lease");
@@ -4344,7 +4374,7 @@ function assessCapabilityMismatch(input) {
4344
4374
 
4345
4375
  // src/domains/dispatch/checkout-writer-lease.ts
4346
4376
  init_esm_shims();
4347
- import { createHash as createHash3 } from "node:crypto";
4377
+ import { createHash as createHash2 } from "node:crypto";
4348
4378
  import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync5, realpathSync, unlinkSync } from "node:fs";
4349
4379
  import { dirname, join as join6 } from "node:path";
4350
4380
  var held = /* @__PURE__ */ new Map();
@@ -4354,7 +4384,7 @@ function canonicalCheckout(checkout) {
4354
4384
  }
4355
4385
  function checkoutWriterLeasePath(checkout) {
4356
4386
  const canonical = canonicalCheckout(checkout);
4357
- const key = createHash3("sha256").update(canonical, "utf8").digest("hex");
4387
+ const key = createHash2("sha256").update(canonical, "utf8").digest("hex");
4358
4388
  return join6(clioStateDir(), "checkout-writer-leases", `${key}.json`);
4359
4389
  }
4360
4390
  function validRecord3(value) {
@@ -4554,8 +4584,11 @@ function isInfrastructureFailure(failureClass) {
4554
4584
  // src/domains/dispatch/heartbeat.ts
4555
4585
  init_esm_shims();
4556
4586
  var DEFAULT_HEARTBEAT_SPEC = { windowMs: 5e3, graceMs: 1e4 };
4557
- function classifyHeartbeat(heartbeatAt, now, spec) {
4558
- const age = now - heartbeatAt;
4587
+ function heartbeatMonotonicAt(heartbeat) {
4588
+ return heartbeat.monotonic ?? heartbeat.current;
4589
+ }
4590
+ function classifyHeartbeat(heartbeatMonotonicAt2, monotonicNow, spec) {
4591
+ const age = monotonicNow - heartbeatMonotonicAt2;
4559
4592
  if (age <= spec.windowMs) return "alive";
4560
4593
  if (age <= spec.windowMs + spec.graceMs) return "stale";
4561
4594
  return "dead";
@@ -4564,14 +4597,14 @@ function classifyHeartbeat(heartbeatAt, now, spec) {
4564
4597
  // src/domains/dispatch/host-verification.ts
4565
4598
  init_esm_shims();
4566
4599
  import { execFileSync as execFileSync2 } from "node:child_process";
4567
- import { createHash as createHash5, randomUUID } from "node:crypto";
4600
+ import { createHash as createHash4, randomUUID } from "node:crypto";
4568
4601
  import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync6, renameSync, writeFileSync as writeFileSync2 } from "node:fs";
4569
4602
  import { dirname as dirname2, join as join8, resolve as resolve3 } from "node:path";
4570
4603
 
4571
4604
  // src/domains/dispatch/code-step.ts
4572
4605
  init_esm_shims();
4573
4606
  import { execFileSync, spawn as spawn2 } from "node:child_process";
4574
- import { createHash as createHash4 } from "node:crypto";
4607
+ import { createHash as createHash3 } from "node:crypto";
4575
4608
  import { mkdirSync as mkdirSync2, writeFileSync } from "node:fs";
4576
4609
  import { isAbsolute, join as join7, resolve as resolve2 } from "node:path";
4577
4610
  var CODE_STEP_CAPTURE_MAX_BYTES = 1048576;
@@ -4591,10 +4624,10 @@ function canonicalCodeReport(report) {
4591
4624
  });
4592
4625
  }
4593
4626
  function codeReportDigest(report) {
4594
- return createHash4("sha256").update(canonicalCodeReport(report), "utf8").digest("hex");
4627
+ return createHash3("sha256").update(canonicalCodeReport(report), "utf8").digest("hex");
4595
4628
  }
4596
4629
  function sha2562(value) {
4597
- return createHash4("sha256").update(value, "utf8").digest("hex");
4630
+ return createHash3("sha256").update(value, "utf8").digest("hex");
4598
4631
  }
4599
4632
  function tailUtf8(value, limit, marker) {
4600
4633
  if (value.length <= limit) return { text: value.toString("utf8"), truncated: false };
@@ -4644,7 +4677,7 @@ function workspaceHasChanges(root) {
4644
4677
  return status.trim().length > 0;
4645
4678
  }
4646
4679
  function newCodeRunId() {
4647
- return `code-${createHash4("sha256").update(`${process.pid}:${Date.now()}:${Math.random()}`).digest("hex").slice(0, 12)}`;
4680
+ return `code-${createHash3("sha256").update(`${process.pid}:${Date.now()}:${Math.random()}`).digest("hex").slice(0, 12)}`;
4648
4681
  }
4649
4682
  async function spawnCommand(input, cwd, argv) {
4650
4683
  const command = input.command;
@@ -4808,7 +4841,7 @@ ${spawned.spawnError}
4808
4841
  var OUTPUT_TAIL_BYTES = 2048;
4809
4842
  var MEMO_VERSION = 1;
4810
4843
  function sha2563(value) {
4811
- return createHash5("sha256").update(value, "utf8").digest("hex");
4844
+ return createHash4("sha256").update(value, "utf8").digest("hex");
4812
4845
  }
4813
4846
  function outputTail(value) {
4814
4847
  const bytes = Buffer.from(value, "utf8");
@@ -5577,7 +5610,7 @@ function selectApprovedRecoveryCandidates(input) {
5577
5610
  // src/domains/dispatch/reproducibility.ts
5578
5611
  init_esm_shims();
5579
5612
  import { spawnSync } from "node:child_process";
5580
- import { createHash as createHash6 } from "node:crypto";
5613
+ import { createHash as createHash5 } from "node:crypto";
5581
5614
  function collectReproducibilityMetadata(cwd, safety) {
5582
5615
  const branch = git(cwd, ["rev-parse", "--abbrev-ref", "HEAD"]);
5583
5616
  const commit = git(cwd, ["rev-parse", "HEAD"]);
@@ -5614,673 +5647,22 @@ function git(cwd, args) {
5614
5647
  return trimmed.length > 0 ? trimmed : null;
5615
5648
  }
5616
5649
  function sha2564(input) {
5617
- return createHash6("sha256").update(input, "utf8").digest("hex");
5650
+ return createHash5("sha256").update(input, "utf8").digest("hex");
5618
5651
  }
5619
5652
 
5620
5653
  // src/domains/dispatch/route-observer.ts
5621
5654
  init_esm_shims();
5622
- import { appendFileSync, existsSync as existsSync10, mkdirSync as mkdirSync5, readdirSync as readdirSync3, readFileSync as readFileSync10, renameSync as renameSync4, statSync } from "node:fs";
5623
- import { join as join12 } from "node:path";
5624
-
5625
- // src/domains/dispatch/gate-decisions.ts
5626
- init_esm_shims();
5627
- import { createHash as createHash7, randomBytes as randomBytes4 } from "node:crypto";
5628
- import { closeSync, existsSync as existsSync8, fsyncSync, mkdirSync as mkdirSync4, openSync, readdirSync as readdirSync2, readFileSync as readFileSync8, rmSync } from "node:fs";
5629
- import { dirname as dirname3, join as join10, resolve as resolve4 } from "node:path";
5630
- function parseReviewGateResult(output) {
5631
- const result = parseVerifierResult(output);
5632
- return result === null ? { ok: false, reason: "reviewer did not return a valid verifier report" } : { ok: true, result };
5633
- }
5634
- function decideReviewGate(input) {
5635
- const base = {
5636
- group: input.group,
5637
- topology: "review",
5638
- cycle: input.cycle,
5639
- subjects: input.subjects,
5640
- decider: input.decider,
5641
- correlation: input.correlation
5642
- };
5643
- const parsed = parseReviewGateResult(input.output);
5644
- if (!parsed.ok) {
5645
- return {
5646
- draft: { ...base, outcome: "exhausted", detail: parsed.reason },
5647
- verdict: null,
5648
- findings: null,
5649
- needsDecision: `review gate produced no structured verdict in cycle ${input.cycle}: ${parsed.reason}`
5650
- };
5651
- }
5652
- if (parsed.result.verdict === "pass" || input.terminalCycle) {
5653
- return {
5654
- draft: { ...base, outcome: parsed.result.verdict },
5655
- verdict: parsed.result.verdict,
5656
- findings: null,
5657
- needsDecision: null
5658
- };
5659
- }
5660
- const failed = parsed.result.checks.filter((check) => !check.passed);
5661
- return {
5662
- draft: { ...base, outcome: "revise", detail: `reviewer reported ${failed.length} failed check(s)` },
5663
- verdict: null,
5664
- findings: JSON.stringify({ verdict: "fail", checks: failed }),
5665
- needsDecision: null
5666
- };
5667
- }
5668
- function parseGateChecks(value) {
5669
- if (!Array.isArray(value) || value.length === 0) return null;
5670
- const checks = [];
5671
- for (const entry of value) {
5672
- if (!isRecord6(entry)) return null;
5673
- const keys = Object.keys(entry);
5674
- if (keys.some((key) => key !== "name" && key !== "passed" && key !== "evidence") || typeof entry.name !== "string" || entry.name.trim().length === 0 || typeof entry.passed !== "boolean" || typeof entry.evidence !== "string" || entry.evidence.trim().length === 0) {
5675
- return null;
5676
- }
5677
- checks.push({ name: entry.name, passed: entry.passed, evidence: entry.evidence });
5678
- }
5679
- return checks;
5680
- }
5681
- function parseCompeteGateResult(output, candidateCount) {
5682
- const parsed = parseJsonObjectPayload(output);
5683
- if (!parsed.ok) {
5684
- return {
5685
- ok: false,
5686
- reason: parsed.reason === "not-object" ? "judge result must be a JSON object" : "judge result must be valid JSON"
5687
- };
5688
- }
5689
- const value = parsed.value;
5690
- if (Object.keys(value).some((key) => key !== "winner" && key !== "checks")) {
5691
- return { ok: false, reason: "judge result has unknown fields" };
5692
- }
5693
- const winner = value.winner;
5694
- if (typeof winner !== "number" || !Number.isSafeInteger(winner) || winner < 1 || winner > candidateCount) {
5695
- return { ok: false, reason: `judge winner must be an integer 1..${candidateCount}` };
5696
- }
5697
- const checks = parseGateChecks(value.checks);
5698
- if (checks === null) return { ok: false, reason: "judge result must carry typed checks with evidence" };
5699
- return { ok: true, result: { winner, checks } };
5700
- }
5701
- function decisionsDirectory(stateDir = clioStateDir()) {
5702
- return join10(stateDir, "gate-decisions");
5703
- }
5704
- function pendingDecisionsDirectory(stateDir = clioStateDir()) {
5705
- return join10(decisionsDirectory(stateDir), "pending");
5706
- }
5707
- function isRecord6(value) {
5708
- return typeof value === "object" && value !== null && !Array.isArray(value);
5709
- }
5710
- function isSubjectRef(value) {
5711
- if (!isRecord6(value) || typeof value.runId !== "string" || value.runId.trim().length === 0) return false;
5712
- return typeof value.digest === "string" && /^[0-9a-f]{64}$/.test(value.digest);
5713
- }
5714
- function isSafeDecisionId(value) {
5715
- return typeof value === "string" && value.length > 0 && value.length <= 256 && /^[A-Za-z0-9._-]+$/.test(value);
5716
- }
5717
- function isCorrelation(value) {
5718
- if (!isRecord6(value)) return false;
5719
- const fields = ["agent", "target", "modelFamily", "runtime", "node", "independent"];
5720
- if (Object.keys(value).some((key) => !fields.includes(key))) return false;
5721
- if (!fields.every((field) => typeof value[field] === "boolean")) return false;
5722
- return value.independent === (!value.agent && !value.modelFamily);
5723
- }
5724
- function semanticError(value) {
5725
- if (!isRecord6(value)) return "gate decision is not an object";
5726
- if (value.version !== 2) return "unsupported gate decision version";
5727
- if (!isSafeDecisionId(value.id)) return "gate decision id invalid";
5728
- if (typeof value.group !== "string" || value.group.length === 0) return "gate decision group invalid";
5729
- if (value.topology !== "review" && value.topology !== "compete") return "gate decision topology invalid";
5730
- if (typeof value.cycle !== "number" || !Number.isInteger(value.cycle) || value.cycle < 1) {
5731
- return "gate decision cycle invalid";
5732
- }
5733
- const reviewOutcome = value.outcome === "pass" || value.outcome === "fail" || value.outcome === "revise" || value.outcome === "exhausted";
5734
- const competeOutcome = value.outcome === "winner" || value.outcome === "no-winner" || value.outcome === "operator-confirmed" || value.outcome === "full-auto-applied";
5735
- if (value.topology === "review" && !reviewOutcome || value.topology === "compete" && !competeOutcome) {
5736
- return "gate decision outcome is incompatible with topology";
5737
- }
5738
- if (!Array.isArray(value.subjects) || value.subjects.length === 0 || !value.subjects.every(isSubjectRef)) {
5739
- return "gate decision subjects invalid";
5740
- }
5741
- if (value.decider !== void 0 && !isSubjectRef(value.decider)) return "gate decision decider invalid";
5742
- if (value.decider === void 0) {
5743
- if (value.correlation !== void 0) return "gate decision correlation requires a decider";
5744
- } else if (!isCorrelation(value.correlation)) {
5745
- return "gate decision correlation invalid";
5746
- }
5747
- if (typeof value.createdAt !== "string" || !Number.isFinite(Date.parse(value.createdAt))) {
5748
- return "gate decision timestamp invalid";
5749
- }
5750
- const needsWinner = value.outcome === "winner" || value.outcome === "operator-confirmed" || value.outcome === "full-auto-applied";
5751
- if (needsWinner) {
5752
- if (!isRecord6(value.winner) || typeof value.winner.index !== "number" || !Number.isInteger(value.winner.index) || value.winner.index < 1 || !isSubjectRef(value.winner.subject) || typeof value.winner.branch !== "string" || value.winner.branch !== `clio/compete/${value.group}/${value.winner.index}`) {
5753
- return "gate decision winner invalid";
5754
- }
5755
- const winnerSubject = value.winner.subject;
5756
- if (!value.subjects.some((subject) => subject.runId === winnerSubject.runId)) {
5757
- return "gate decision winner is not a subject";
5758
- }
5759
- } else if (value.winner !== void 0) {
5760
- return "gate decision winner is not valid for this outcome";
5761
- }
5762
- const needsConfirmation = value.outcome === "operator-confirmed" || value.outcome === "full-auto-applied";
5763
- if (needsConfirmation) {
5764
- if (!isRecord6(value.confirmation) || typeof value.confirmation.id !== "string" || value.confirmation.id.length === 0 || typeof value.confirmation.digest !== "string" || !/^[0-9a-f]{64}$/.test(value.confirmation.digest)) {
5765
- return "gate decision confirmation invalid";
5766
- }
5767
- } else if (value.confirmation !== void 0) {
5768
- return "gate decision confirmation is not valid for this outcome";
5769
- }
5770
- if (value.detail !== void 0 && typeof value.detail !== "string") return "gate decision detail invalid";
5771
- if (!isRecord6(value.integrity) || value.integrity.algorithm !== "sha256" || typeof value.integrity.digest !== "string") {
5772
- return "gate decision integrity invalid";
5773
- }
5774
- return null;
5775
- }
5776
- function safeGroup(group) {
5777
- const safe = group.replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 128);
5778
- return safe.length > 0 ? safe : "gate";
5779
- }
5780
- function newDecisionId(group) {
5781
- return `${safeGroup(group)}-${Date.now().toString(36)}-${randomBytes4(6).toString("hex")}`;
5782
- }
5783
- function decisionArtifactPath(id, stateDir = clioStateDir()) {
5784
- return join10(decisionsDirectory(stateDir), `${id}.json`);
5785
- }
5786
- function pendingDecisionPath(id, stateDir = clioStateDir()) {
5787
- return join10(pendingDecisionsDirectory(stateDir), `${id}.json`);
5788
- }
5789
- function decisionPayload(decision) {
5790
- return {
5791
- contract: "clio.gateDecision.integrity",
5792
- version: decision.version,
5793
- id: decision.id,
5794
- group: decision.group,
5795
- topology: decision.topology,
5796
- cycle: decision.cycle,
5797
- outcome: decision.outcome,
5798
- subjects: decision.subjects.map((subject) => ({ runId: subject.runId, digest: subject.digest })),
5799
- ...decision.decider !== void 0 ? { decider: { runId: decision.decider.runId, digest: decision.decider.digest } } : {},
5800
- ...decision.correlation !== void 0 ? { correlation: { ...decision.correlation } } : {},
5801
- ...decision.winner !== void 0 ? {
5802
- winner: {
5803
- index: decision.winner.index,
5804
- subject: {
5805
- runId: decision.winner.subject.runId,
5806
- digest: decision.winner.subject.digest
5807
- },
5808
- branch: decision.winner.branch
5809
- }
5810
- } : {},
5811
- ...decision.confirmation !== void 0 ? { confirmation: { id: decision.confirmation.id, digest: decision.confirmation.digest } } : {},
5812
- ...decision.detail !== void 0 ? { detail: decision.detail } : {},
5813
- createdAt: decision.createdAt
5814
- };
5815
- }
5816
- function decisionDigest(decision) {
5817
- return createHash7("sha256").update(JSON.stringify(decisionPayload(decision)), "utf8").digest("hex");
5818
- }
5819
- function artifactWithoutIntegrity(artifact) {
5820
- const result = {
5821
- version: artifact.version,
5822
- id: artifact.id,
5823
- group: artifact.group,
5824
- topology: artifact.topology,
5825
- cycle: artifact.cycle,
5826
- outcome: artifact.outcome,
5827
- subjects: artifact.subjects.map((subject) => ({ ...subject })),
5828
- createdAt: artifact.createdAt
5829
- };
5830
- if (artifact.decider !== void 0) result.decider = { ...artifact.decider };
5831
- if (artifact.correlation !== void 0) result.correlation = { ...artifact.correlation };
5832
- if (artifact.winner !== void 0) {
5833
- result.winner = {
5834
- index: artifact.winner.index,
5835
- subject: { ...artifact.winner.subject },
5836
- branch: artifact.winner.branch
5837
- };
5838
- }
5839
- if (artifact.confirmation !== void 0) result.confirmation = { ...artifact.confirmation };
5840
- if (artifact.detail !== void 0) result.detail = artifact.detail;
5841
- return result;
5842
- }
5843
- function verifyGateDecisionArtifact(artifact) {
5844
- const invalid = semanticError(artifact);
5845
- if (invalid !== null) return { ok: false, reason: invalid };
5846
- if (!/^[0-9a-f]{64}$/.test(artifact.integrity.digest)) return { ok: false, reason: "gate decision integrity invalid" };
5847
- return decisionDigest(artifactWithoutIntegrity(artifact)) === artifact.integrity.digest ? { ok: true } : { ok: false, reason: "gate decision integrity mismatch" };
5848
- }
5849
- function buildGateDecisionArtifact(draft, id = newDecisionId(draft.group), createdAt = draft.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()) {
5850
- if (draft.group.trim().length === 0) throw new Error("gate decision group is required");
5851
- if (!Number.isInteger(draft.cycle) || draft.cycle < 1)
5852
- throw new Error("gate decision cycle must be a positive integer");
5853
- if (draft.subjects.length === 0) throw new Error("gate decision requires at least one subject receipt");
5854
- const withoutIntegrity = {
5855
- version: 2,
5856
- id,
5857
- group: draft.group,
5858
- topology: draft.topology,
5859
- cycle: draft.cycle,
5860
- outcome: draft.outcome,
5861
- subjects: draft.subjects.map((subject) => ({ ...subject })),
5862
- createdAt
5863
- };
5864
- if (draft.decider !== void 0) withoutIntegrity.decider = { ...draft.decider };
5865
- if (draft.correlation !== void 0) withoutIntegrity.correlation = { ...draft.correlation };
5866
- if (draft.winner !== void 0) {
5867
- withoutIntegrity.winner = {
5868
- index: draft.winner.index,
5869
- subject: { ...draft.winner.subject },
5870
- branch: draft.winner.branch
5871
- };
5872
- }
5873
- if (draft.confirmation !== void 0) withoutIntegrity.confirmation = { ...draft.confirmation };
5874
- if (draft.detail !== void 0) withoutIntegrity.detail = draft.detail;
5875
- const artifact = {
5876
- ...withoutIntegrity,
5877
- integrity: { algorithm: "sha256", digest: decisionDigest(withoutIntegrity) }
5878
- };
5879
- const verification = verifyGateDecisionArtifact(artifact);
5880
- if (!verification.ok) throw new Error(verification.reason);
5881
- return artifact;
5882
- }
5883
- function readVerifiedArtifact(path2) {
5884
- let value;
5885
- try {
5886
- value = JSON.parse(readFileSync8(path2, "utf8"));
5887
- } catch (error) {
5888
- throw new Error(
5889
- `gate decision artifact is unreadable at ${path2}: ${error instanceof Error ? error.message : String(error)}`
5890
- );
5891
- }
5892
- const artifact = value;
5893
- const verification = verifyGateDecisionArtifact(artifact);
5894
- if (!verification.ok) throw new Error(`gate decision artifact is invalid at ${path2}: ${verification.reason}`);
5895
- return artifact;
5896
- }
5897
- function persistGateDecisionArtifact(artifact, stateDir, allowIdenticalExisting) {
5898
- const verification = verifyGateDecisionArtifact(artifact);
5899
- if (!verification.ok) throw new Error(verification.reason);
5900
- const directory = decisionsDirectory(stateDir);
5901
- mkdirSync4(directory, { recursive: true });
5902
- const path2 = decisionArtifactPath(artifact.id, stateDir);
5903
- if (existsSync8(path2)) {
5904
- const existing = readVerifiedArtifact(path2);
5905
- if (allowIdenticalExisting && existing.id === artifact.id && existing.integrity.digest === artifact.integrity.digest) {
5906
- return { artifact: existing, path: path2 };
5907
- }
5908
- throw new Error(`gate decision artifact collision: ${artifact.id}`);
5909
- }
5910
- atomicWrite(path2, JSON.stringify(artifact, null, 2));
5911
- return { artifact, path: path2 };
5912
- }
5913
- function cloneGateDecisionArtifact(artifact) {
5914
- return {
5915
- ...artifactWithoutIntegrity(artifact),
5916
- integrity: { ...artifact.integrity }
5917
- };
5918
- }
5919
- function pendingRecordPayload(record) {
5920
- if (record.kind === "output") {
5921
- return {
5922
- contract: "clio.gateDecision.pending",
5923
- version: record.version,
5924
- kind: record.kind,
5925
- id: record.id,
5926
- group: record.group,
5927
- topology: record.topology,
5928
- cycle: record.cycle,
5929
- subjects: record.subjects.map((subject) => ({ runId: subject.runId, digest: subject.digest })),
5930
- deciderRunId: record.deciderRunId,
5931
- finalOutput: record.finalOutput,
5932
- ...record.terminalCycle !== void 0 ? { terminalCycle: record.terminalCycle } : {},
5933
- ...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
5934
- createdAt: record.createdAt
5935
- };
5936
- }
5937
- const decisionWithoutIntegrity = artifactWithoutIntegrity(record.decision);
5938
- return {
5939
- contract: "clio.gateDecision.pending",
5940
- version: record.version,
5941
- kind: record.kind,
5942
- id: record.id,
5943
- decision: {
5944
- ...decisionPayload(decisionWithoutIntegrity),
5945
- integrity: { ...record.decision.integrity }
5946
- },
5947
- ...record.finalOutput !== void 0 ? { finalOutput: record.finalOutput } : {},
5948
- ...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
5949
- createdAt: record.createdAt
5950
- };
5951
- }
5952
- function pendingRecordDigest(record) {
5953
- return createHash7("sha256").update(JSON.stringify(pendingRecordPayload(record)), "utf8").digest("hex");
5954
- }
5955
- function pendingRecordWithoutIntegrity(record) {
5956
- if (record.kind === "output") {
5957
- return {
5958
- version: record.version,
5959
- kind: record.kind,
5960
- id: record.id,
5961
- group: record.group,
5962
- topology: record.topology,
5963
- cycle: record.cycle,
5964
- subjects: record.subjects.map((subject) => ({ ...subject })),
5965
- deciderRunId: record.deciderRunId,
5966
- finalOutput: record.finalOutput,
5967
- ...record.terminalCycle !== void 0 ? { terminalCycle: record.terminalCycle } : {},
5968
- ...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
5969
- createdAt: record.createdAt
5970
- };
5971
- }
5972
- return {
5973
- version: record.version,
5974
- kind: record.kind,
5975
- id: record.id,
5976
- decision: cloneGateDecisionArtifact(record.decision),
5977
- ...record.finalOutput !== void 0 ? { finalOutput: record.finalOutput } : {},
5978
- ...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
5979
- createdAt: record.createdAt
5980
- };
5981
- }
5982
- function pendingSemanticError(value) {
5983
- if (!isRecord6(value)) return "pending gate decision is not an object";
5984
- if (value.version !== 1) return "unsupported pending gate decision version";
5985
- if (!isSafeDecisionId(value.id)) return "pending gate decision id invalid";
5986
- if (typeof value.createdAt !== "string" || !Number.isFinite(Date.parse(value.createdAt))) {
5987
- return "pending gate decision timestamp invalid";
5988
- }
5989
- if (!isRecord6(value.integrity) || value.integrity.algorithm !== "sha256" || typeof value.integrity.digest !== "string" || !/^[0-9a-f]{64}$/.test(value.integrity.digest)) {
5990
- return "pending gate decision integrity invalid";
5991
- }
5992
- if (value.kind === "output") {
5993
- if (typeof value.group !== "string" || value.group.trim().length === 0) {
5994
- return "pending gate output group invalid";
5995
- }
5996
- if (value.topology !== "review" && value.topology !== "compete") {
5997
- return "pending gate output topology invalid";
5998
- }
5999
- if (typeof value.cycle !== "number" || !Number.isInteger(value.cycle) || value.cycle < 1) {
6000
- return "pending gate output cycle invalid";
6001
- }
6002
- if (!Array.isArray(value.subjects) || value.subjects.length === 0 || !value.subjects.every(isSubjectRef)) {
6003
- return "pending gate output subjects invalid";
6004
- }
6005
- if (typeof value.deciderRunId !== "string" || value.deciderRunId.trim().length === 0) {
6006
- return "pending gate output decider run id invalid";
6007
- }
6008
- if (typeof value.finalOutput !== "string") return "pending gate output text invalid";
6009
- if (value.terminalCycle !== void 0 && typeof value.terminalCycle !== "boolean") {
6010
- return "pending gate output terminal-cycle marker invalid";
6011
- }
6012
- if (value.resourceRoot !== void 0 && (typeof value.resourceRoot !== "string" || value.resourceRoot.length === 0)) {
6013
- return "pending gate output resource root invalid";
6014
- }
6015
- return null;
6016
- }
6017
- if (value.kind !== "decision") return "pending gate decision kind invalid";
6018
- if (!isRecord6(value.decision)) return "pending gate decision artifact invalid";
6019
- const verification = verifyGateDecisionArtifact(value.decision);
6020
- if (!verification.ok) return `pending gate decision artifact invalid: ${verification.reason}`;
6021
- if (value.decision.id !== value.id) return "pending gate decision artifact id mismatch";
6022
- if (value.decision.createdAt !== value.createdAt) return "pending gate decision artifact timestamp mismatch";
6023
- if (value.finalOutput !== void 0 && typeof value.finalOutput !== "string") {
6024
- return "pending gate decision output invalid";
6025
- }
6026
- if (value.resourceRoot !== void 0 && (typeof value.resourceRoot !== "string" || value.resourceRoot.length === 0)) {
6027
- return "pending gate decision resource root invalid";
6028
- }
6029
- return null;
6030
- }
6031
- function verifyPendingGateDecisionRecord(record) {
6032
- const invalid = pendingSemanticError(record);
6033
- if (invalid !== null) return { ok: false, reason: invalid };
6034
- return pendingRecordDigest(pendingRecordWithoutIntegrity(record)) === record.integrity.digest ? { ok: true } : { ok: false, reason: "pending gate decision integrity mismatch" };
6035
- }
6036
- function clonePendingGateDecisionRecord(record) {
6037
- const without = pendingRecordWithoutIntegrity(record);
6038
- return {
6039
- ...without,
6040
- integrity: { ...record.integrity }
6041
- };
6042
- }
6043
- function parsePendingGateDecisionRecord(value) {
6044
- const invalid = pendingSemanticError(value);
6045
- if (invalid !== null) throw new Error(invalid);
6046
- const record = clonePendingGateDecisionRecord(value);
6047
- const verification = verifyPendingGateDecisionRecord(record);
6048
- if (!verification.ok) throw new Error(verification.reason);
6049
- return record;
6050
- }
6051
- function assertPendingHandlePath(handle) {
6052
- const expected = pendingDecisionPath(handle.record.id, handle.stateDir);
6053
- if (resolve4(handle.path) !== resolve4(expected)) {
6054
- throw new Error(`pending gate decision path does not match id ${handle.record.id}`);
6055
- }
6056
- }
6057
- function pendingHandle(record, stateDir) {
6058
- return {
6059
- record: clonePendingGateDecisionRecord(record),
6060
- path: pendingDecisionPath(record.id, stateDir),
6061
- stateDir
6062
- };
6063
- }
6064
- function persistPendingGateDecision(record, stateDir, allowReplace) {
6065
- const verification = verifyPendingGateDecisionRecord(record);
6066
- if (!verification.ok) throw new Error(verification.reason);
6067
- const path2 = pendingDecisionPath(record.id, stateDir);
6068
- mkdirSync4(dirname3(path2), { recursive: true });
6069
- if (!allowReplace && existsSync8(path2)) throw new Error(`pending gate decision collision: ${record.id}`);
6070
- atomicWrite(path2, JSON.stringify(record, null, 2));
6071
- return pendingHandle(record, stateDir);
6072
- }
6073
- function loadPendingGateDecision(handle) {
6074
- assertPendingHandlePath(handle);
6075
- if (!existsSync8(handle.path)) return null;
6076
- const record = parsePendingGateDecisionRecord(JSON.parse(readFileSync8(handle.path, "utf8")));
6077
- if (record.id !== handle.record.id) throw new Error("pending gate decision changed identity on disk");
6078
- return pendingHandle(record, handle.stateDir);
6079
- }
6080
- function fsyncDirectoryBestEffort(path2) {
6081
- let fd = null;
6082
- try {
6083
- fd = openSync(path2, "r");
6084
- fsyncSync(fd);
6085
- } catch {
6086
- } finally {
6087
- if (fd !== null) closeSync(fd);
6088
- }
6089
- }
6090
- function clearPendingGateDecision(handle) {
6091
- assertPendingHandlePath(handle);
6092
- rmSync(handle.path, { force: true });
6093
- fsyncDirectoryBestEffort(dirname3(handle.path));
6094
- }
6095
- function sameSubjectRefs(left, right) {
6096
- return left.length === right.length && left.every((subject, index) => {
6097
- const other = right[index];
6098
- return other !== void 0 && subject.runId === other.runId && subject.digest === other.digest;
6099
- });
6100
- }
6101
- function stagePendingGateOutput(draft, stateDir = clioStateDir()) {
6102
- const id = newDecisionId(draft.group);
6103
- const withoutIntegrity = {
6104
- version: 1,
6105
- kind: "output",
6106
- id,
6107
- group: draft.group,
6108
- topology: draft.topology,
6109
- cycle: draft.cycle,
6110
- subjects: draft.subjects.map((subject) => ({ ...subject })),
6111
- deciderRunId: draft.deciderRunId,
6112
- finalOutput: draft.finalOutput,
6113
- ...draft.terminalCycle !== void 0 ? { terminalCycle: draft.terminalCycle } : {},
6114
- ...draft.resourceRoot !== void 0 ? { resourceRoot: draft.resourceRoot } : {},
6115
- createdAt: draft.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
6116
- };
6117
- const record = {
6118
- ...withoutIntegrity,
6119
- integrity: { algorithm: "sha256", digest: pendingRecordDigest(withoutIntegrity) }
6120
- };
6121
- if (existsSync8(decisionArtifactPath(id, stateDir))) throw new Error(`gate decision artifact collision: ${id}`);
6122
- return persistPendingGateDecision(record, stateDir, false);
6123
- }
6124
- function stagePendingGateDecision(draft, options = {}) {
6125
- const stateDir = options.stateDir ?? clioStateDir();
6126
- const id = newDecisionId(draft.group);
6127
- const createdAt = draft.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
6128
- const decision = buildGateDecisionArtifact(draft, id, createdAt);
6129
- const withoutIntegrity = {
6130
- version: 1,
6131
- kind: "decision",
6132
- id,
6133
- decision,
6134
- ...options.finalOutput !== void 0 ? { finalOutput: options.finalOutput } : {},
6135
- ...options.resourceRoot !== void 0 ? { resourceRoot: options.resourceRoot } : {},
6136
- createdAt
6137
- };
6138
- const record = {
6139
- ...withoutIntegrity,
6140
- integrity: { algorithm: "sha256", digest: pendingRecordDigest(withoutIntegrity) }
6141
- };
6142
- if (existsSync8(decisionArtifactPath(id, stateDir))) throw new Error(`gate decision artifact collision: ${id}`);
6143
- return persistPendingGateDecision(record, stateDir, false);
6144
- }
6145
- function resolvePendingGateDecision(handle, draft) {
6146
- const loaded = loadPendingGateDecision(handle);
6147
- if (loaded === null) throw new Error(`pending gate decision is missing: ${handle.record.id}`);
6148
- if (loaded.record.kind === "decision") {
6149
- const expected = buildGateDecisionArtifact(draft, loaded.record.id, loaded.record.createdAt);
6150
- if (expected.integrity.digest !== loaded.record.decision.integrity.digest) {
6151
- throw new Error("pending gate decision was already resolved to a different artifact");
6152
- }
6153
- return loaded;
6154
- }
6155
- const pending = loaded.record;
6156
- if (draft.group !== pending.group || draft.topology !== pending.topology || draft.cycle !== pending.cycle || !sameSubjectRefs(draft.subjects, pending.subjects)) {
6157
- throw new Error("resolved gate decision does not match staged output context");
6158
- }
6159
- if (draft.decider === void 0 || draft.decider.runId !== pending.deciderRunId) {
6160
- throw new Error("resolved gate decision does not match staged decider run");
6161
- }
6162
- if (draft.createdAt !== void 0 && draft.createdAt !== pending.createdAt) {
6163
- throw new Error("resolved gate decision cannot change the staged timestamp");
6164
- }
6165
- const decision = buildGateDecisionArtifact(draft, pending.id, pending.createdAt);
6166
- const withoutIntegrity = {
6167
- version: 1,
6168
- kind: "decision",
6169
- id: pending.id,
6170
- decision,
6171
- finalOutput: pending.finalOutput,
6172
- ...pending.resourceRoot !== void 0 ? { resourceRoot: pending.resourceRoot } : {},
6173
- createdAt: pending.createdAt
6174
- };
6175
- const resolvedRecord = {
6176
- ...withoutIntegrity,
6177
- integrity: { algorithm: "sha256", digest: pendingRecordDigest(withoutIntegrity) }
6178
- };
6179
- return persistPendingGateDecision(resolvedRecord, loaded.stateDir, true);
6180
- }
6181
- function materializePendingGateDecision(handle) {
6182
- const loaded = loadPendingGateDecision(handle);
6183
- if (loaded === null) {
6184
- if (handle.record.kind !== "decision") {
6185
- throw new Error(`pending gate output is missing before resolution: ${handle.record.id}`);
6186
- }
6187
- const path2 = decisionArtifactPath(handle.record.decision.id, handle.stateDir);
6188
- if (!existsSync8(path2)) throw new Error(`pending gate decision and artifact are both missing: ${handle.record.id}`);
6189
- const artifact = readVerifiedArtifact(path2);
6190
- if (artifact.integrity.digest !== handle.record.decision.integrity.digest) {
6191
- throw new Error(`gate decision artifact conflicts with completed pending record: ${handle.record.id}`);
6192
- }
6193
- return { artifact, path: path2 };
6194
- }
6195
- if (loaded.record.kind !== "decision") {
6196
- throw new Error(`pending gate output requires receipt resolution: ${loaded.record.id}`);
6197
- }
6198
- const written = persistGateDecisionArtifact(loaded.record.decision, loaded.stateDir, true);
6199
- const persisted = readVerifiedArtifact(written.path);
6200
- if (persisted.integrity.digest !== loaded.record.decision.integrity.digest) {
6201
- throw new Error(`materialized gate decision does not match pending record: ${loaded.record.id}`);
6202
- }
6203
- clearPendingGateDecision(loaded);
6204
- return { artifact: persisted, path: written.path };
6205
- }
6206
- function finalizePendingGateDecision(handle, draft) {
6207
- return materializePendingGateDecision(resolvePendingGateDecision(handle, draft));
6208
- }
6209
- function readPendingGateDecisions(stateDir = clioStateDir()) {
6210
- const directory = pendingDecisionsDirectory(stateDir);
6211
- if (!existsSync8(directory)) return { records: [], errors: [] };
6212
- const records = [];
6213
- const errors = [];
6214
- for (const name of readdirSync2(directory).filter((entry) => entry.endsWith(".json")).sort()) {
6215
- const path2 = join10(directory, name);
6216
- try {
6217
- const record = parsePendingGateDecisionRecord(JSON.parse(readFileSync8(path2, "utf8")));
6218
- if (name !== `${record.id}.json`) throw new Error("pending gate decision filename does not match its id");
6219
- records.push({ record, path: path2, stateDir });
6220
- } catch (error) {
6221
- errors.push({ path: path2, message: error instanceof Error ? error.message : String(error) });
6222
- }
6223
- }
6224
- return { records, errors };
6225
- }
6226
- function preflightPendingGateDecisionMaterialization(handles) {
6227
- for (const handle of handles) {
6228
- if (handle.record.kind !== "decision") continue;
6229
- const path2 = decisionArtifactPath(handle.record.decision.id, handle.stateDir);
6230
- if (!existsSync8(path2)) continue;
6231
- const existing = readVerifiedArtifact(path2);
6232
- if (existing.integrity.digest !== handle.record.decision.integrity.digest) {
6233
- throw new Error(`gate decision artifact conflicts with pending record: ${handle.record.id}`);
6234
- }
6235
- }
6236
- }
6237
- function preparePendingGateDecisionRecovery(stateDir = clioStateDir()) {
6238
- const pending = readPendingGateDecisions(stateDir);
6239
- if (pending.errors.length > 0) {
6240
- throw new Error(
6241
- `pending gate decision journal is untrustworthy: ${pending.errors.map((entry) => `${entry.path}: ${entry.message}`).join("; ")}`
6242
- );
6243
- }
6244
- const ready = pending.records.filter((handle) => handle.record.kind === "decision");
6245
- preflightPendingGateDecisionMaterialization(ready);
6246
- return {
6247
- ready,
6248
- unresolved: pending.records.filter((handle) => handle.record.kind === "output")
6249
- };
6250
- }
6251
- function readGateDecisionArtifacts(group, stateDir = clioStateDir()) {
6252
- const directory = decisionsDirectory(stateDir);
6253
- if (!existsSync8(directory)) return [];
6254
- const out = [];
6255
- for (const name of readdirSync2(directory).filter((entry) => entry.endsWith(".json")).sort()) {
6256
- const path2 = join10(directory, name);
6257
- try {
6258
- const artifact = JSON.parse(readFileSync8(path2, "utf8"));
6259
- if (group !== void 0 && artifact.group !== group) continue;
6260
- if (!verifyGateDecisionArtifact(artifact).ok) continue;
6261
- out.push({ artifact, path: path2 });
6262
- } catch {
6263
- }
6264
- }
6265
- return out;
6266
- }
6267
- function readGateDecisionArtifactsForRunIds(runIds, stateDir = clioStateDir()) {
6268
- if (runIds.size === 0) return [];
6269
- return readGateDecisionArtifacts(void 0, stateDir).filter(({ artifact }) => {
6270
- if (artifact.subjects.some((subject) => runIds.has(subject.runId))) return true;
6271
- if (artifact.decider !== void 0 && runIds.has(artifact.decider.runId)) return true;
6272
- return artifact.winner !== void 0 && runIds.has(artifact.winner.subject.runId);
6273
- });
6274
- }
5655
+ import { appendFileSync, existsSync as existsSync9, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync9, renameSync as renameSync4, statSync } from "node:fs";
5656
+ import { join as join11 } from "node:path";
6275
5657
 
6276
5658
  // src/domains/dispatch/route-history.ts
6277
5659
  init_esm_shims();
6278
- import { existsSync as existsSync9, readFileSync as readFileSync9, renameSync as renameSync3 } from "node:fs";
6279
- import { join as join11 } from "node:path";
5660
+ import { existsSync as existsSync8, readFileSync as readFileSync8, renameSync as renameSync3 } from "node:fs";
5661
+ import { join as join10 } from "node:path";
6280
5662
  var ROUTE_HISTORY_VERSION = 3;
6281
5663
  var DEFAULT_MAX_RECORDS = 4096;
6282
5664
  function historyPath(stateDir) {
6283
- return join11(stateDir, "route-history.json");
5665
+ return join10(stateDir, "route-history.json");
6284
5666
  }
6285
5667
  function clone2(record) {
6286
5668
  return structuredClone(record);
@@ -6289,7 +5671,7 @@ function compareRecords(left, right) {
6289
5671
  return left.settledAt.localeCompare(right.settledAt) || left.receiptDigest.localeCompare(right.receiptDigest);
6290
5672
  }
6291
5673
  function validateRecord(value) {
6292
- if (!isRecord7(value) || value.version !== ROUTE_HISTORY_VERSION)
5674
+ if (!isRecord5(value) || value.version !== ROUTE_HISTORY_VERSION)
6293
5675
  throw new Error("route history record has unsupported version");
6294
5676
  if (!isDigest(value.receiptDigest)) throw new Error("route history receipt digest invalid");
6295
5677
  if (typeof value.assignmentId !== "string" || value.assignmentId.length === 0)
@@ -6333,8 +5715,8 @@ function validateRecord(value) {
6333
5715
  };
6334
5716
  }
6335
5717
  function readHistory(path2) {
6336
- if (!existsSync9(path2)) return [];
6337
- const raw = readFileSync9(path2, "utf8").trim();
5718
+ if (!existsSync8(path2)) return [];
5719
+ const raw = readFileSync8(path2, "utf8").trim();
6338
5720
  if (raw.length === 0) return [];
6339
5721
  let parsed;
6340
5722
  try {
@@ -6342,7 +5724,7 @@ function readHistory(path2) {
6342
5724
  } catch (error) {
6343
5725
  throw new Error(`route history unreadable: ${error instanceof Error ? error.message : String(error)}`);
6344
5726
  }
6345
- if (!isRecord7(parsed) || !Array.isArray(parsed.records)) throw new Error("route history has unsupported format");
5727
+ if (!isRecord5(parsed) || !Array.isArray(parsed.records)) throw new Error("route history has unsupported format");
6346
5728
  if (parsed.version !== ROUTE_HISTORY_VERSION) {
6347
5729
  retireHistory(path2, parsed.version);
6348
5730
  return [];
@@ -6402,14 +5784,14 @@ function createRouteHistoryStore(options = {}) {
6402
5784
  }
6403
5785
  };
6404
5786
  }
6405
- function isRecord7(value) {
5787
+ function isRecord5(value) {
6406
5788
  return typeof value === "object" && value !== null && !Array.isArray(value);
6407
5789
  }
6408
5790
  function isDigest(value) {
6409
5791
  return typeof value === "string" && /^[0-9a-f]{64}$/u.test(value);
6410
5792
  }
6411
5793
  function isRouteCandidate(value) {
6412
- if (!isRecord7(value)) return false;
5794
+ if (!isRecord5(value)) return false;
6413
5795
  if (!isExecutionRole(value.executionRole)) return false;
6414
5796
  return [
6415
5797
  value.agentId,
@@ -6425,7 +5807,7 @@ function isRouteCandidate(value) {
6425
5807
  ].every((field) => typeof field === "string");
6426
5808
  }
6427
5809
  function isPhaseTiming(value) {
6428
- if (!isRecord7(value)) return false;
5810
+ if (!isRecord5(value)) return false;
6429
5811
  return [
6430
5812
  "requestToDecisionMs",
6431
5813
  "decisionMs",
@@ -6441,7 +5823,7 @@ function isPhaseTiming(value) {
6441
5823
 
6442
5824
  // src/domains/dispatch/route-quality.ts
6443
5825
  init_esm_shims();
6444
- import { createHash as createHash8 } from "node:crypto";
5826
+ import { createHash as createHash6 } from "node:crypto";
6445
5827
  function compareStrings(left, right) {
6446
5828
  return left < right ? -1 : left > right ? 1 : 0;
6447
5829
  }
@@ -6556,19 +5938,19 @@ function reduceRouteQuality(input) {
6556
5938
  return { label, checks, correlatedGates, sourceDigests: [...sourceDigests].sort(compareStrings) };
6557
5939
  }
6558
5940
  function routeQualityEvalDigest(artifact) {
6559
- return createHash8("sha256").update(canonicalJson3(artifact), "utf8").digest("hex");
5941
+ return createHash6("sha256").update(canonicalJson2(artifact), "utf8").digest("hex");
6560
5942
  }
6561
- function canonicalJson3(value) {
5943
+ function canonicalJson2(value) {
6562
5944
  if (value === null) return "null";
6563
5945
  if (typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
6564
5946
  if (typeof value === "number") {
6565
5947
  if (!Number.isFinite(value)) throw new Error("route quality eval digest requires finite numbers");
6566
5948
  return JSON.stringify(value);
6567
5949
  }
6568
- if (Array.isArray(value)) return `[${value.map(canonicalJson3).join(",")}]`;
5950
+ if (Array.isArray(value)) return `[${value.map(canonicalJson2).join(",")}]`;
6569
5951
  if (typeof value === "object") {
6570
5952
  const record = value;
6571
- return `{${Object.keys(record).sort(compareStrings).map((key) => `${JSON.stringify(key)}:${canonicalJson3(record[key])}`).join(",")}}`;
5953
+ return `{${Object.keys(record).sort(compareStrings).map((key) => `${JSON.stringify(key)}:${canonicalJson2(record[key])}`).join(",")}}`;
6572
5954
  }
6573
5955
  throw new Error(`route quality eval digest cannot represent ${typeof value}`);
6574
5956
  }
@@ -6629,28 +6011,28 @@ function createRouteLearner(capacity = LEARNER_CAPACITY) {
6629
6011
  }
6630
6012
  var OBSERVATION_LOG_MAX_BYTES = 1024 * 1024;
6631
6013
  function durableQualitySources(stateDir) {
6632
- const runsPath2 = join12(stateDir, "runs.json");
6633
- if (!existsSync10(runsPath2)) return { receipts: [], gates: [], evals: [] };
6014
+ const runsPath2 = join11(stateDir, "runs.json");
6015
+ if (!existsSync9(runsPath2)) return { receipts: [], gates: [], evals: [] };
6634
6016
  try {
6635
- const parsed = JSON.parse(readFileSync10(runsPath2, "utf8"));
6017
+ const parsed = JSON.parse(readFileSync9(runsPath2, "utf8"));
6636
6018
  if (!Array.isArray(parsed)) return { receipts: [], gates: [], evals: [] };
6637
6019
  const receipts = [];
6638
6020
  for (const envelope of parsed) {
6639
6021
  if (typeof envelope !== "object" || envelope === null || Array.isArray(envelope)) continue;
6640
6022
  const run = envelope;
6641
- const path2 = run.receiptPath ?? join12(stateDir, "receipts", `${run.id}.json`);
6642
- if (!existsSync10(path2)) continue;
6643
- const receipt = JSON.parse(readFileSync10(path2, "utf8"));
6023
+ const path2 = run.receiptPath ?? join11(stateDir, "receipts", `${run.id}.json`);
6024
+ if (!existsSync9(path2)) continue;
6025
+ const receipt = JSON.parse(readFileSync9(path2, "utf8"));
6644
6026
  if (typeof receipt === "object" && receipt !== null && !Array.isArray(receipt)) {
6645
6027
  receipts.push({ receipt, envelope: run });
6646
6028
  }
6647
6029
  }
6648
6030
  const evals = [];
6649
- const evalDirectory = join12(clioDataDir(), "evals");
6650
- if (existsSync10(evalDirectory)) {
6651
- for (const name of readdirSync3(evalDirectory).filter((entry) => entry.endsWith(".json")).sort()) {
6031
+ const evalDirectory = join11(clioDataDir(), "evals");
6032
+ if (existsSync9(evalDirectory)) {
6033
+ for (const name of readdirSync2(evalDirectory).filter((entry) => entry.endsWith(".json")).sort()) {
6652
6034
  try {
6653
- const artifact = parseEvalArtifactV4(JSON.parse(readFileSync10(join12(evalDirectory, name), "utf8")), name);
6035
+ const artifact = parseEvalArtifactV4(JSON.parse(readFileSync9(join11(evalDirectory, name), "utf8")), name);
6654
6036
  evals.push({ artifact, digest: routeQualityEvalDigest(artifact) });
6655
6037
  } catch {
6656
6038
  }
@@ -6662,8 +6044,8 @@ function durableQualitySources(stateDir) {
6662
6044
  }
6663
6045
  }
6664
6046
  function appendObservationLine(dir, record) {
6665
- mkdirSync5(dir, { recursive: true });
6666
- const path2 = join12(dir, "observations.jsonl");
6047
+ mkdirSync4(dir, { recursive: true });
6048
+ const path2 = join11(dir, "observations.jsonl");
6667
6049
  try {
6668
6050
  if (statSync(path2).size > OBSERVATION_LOG_MAX_BYTES) {
6669
6051
  renameSync4(path2, `${path2}.1`);
@@ -6695,7 +6077,7 @@ function createRouteObserver(options) {
6695
6077
  const PENDING_LIMIT = 512;
6696
6078
  let totalObservations = 0;
6697
6079
  let sequence = 0;
6698
- const logDir = () => options.logDir ?? join12(clioStateDir(), "route-decisions");
6080
+ const logDir = () => options.logDir ?? join11(clioStateDir(), "route-decisions");
6699
6081
  const reconcileHistory = () => {
6700
6082
  const sources = durableQualitySources(options.stateDir ?? clioStateDir());
6701
6083
  if (sources.receipts.length === 0) return;
@@ -6860,8 +6242,328 @@ function createRouteObserver(options) {
6860
6242
  } catch {
6861
6243
  }
6862
6244
  },
6863
- summary() {
6864
- return learner.summary(totalObservations);
6245
+ summary() {
6246
+ return learner.summary(totalObservations);
6247
+ }
6248
+ };
6249
+ }
6250
+
6251
+ // src/domains/dispatch/run-event-journal-bridge.ts
6252
+ init_esm_shims();
6253
+
6254
+ // src/tools/dispatch-run-events.ts
6255
+ init_esm_shims();
6256
+
6257
+ // src/tools/dispatch-event-text.ts
6258
+ init_esm_shims();
6259
+ function assistantTextFromEvent(event) {
6260
+ return durableAssistantTextFromEvent(event).trim();
6261
+ }
6262
+ function receiptResponseModelIdObservationLabel(receipt) {
6263
+ const responses = receipt.upstreamResponses ?? [];
6264
+ if (responses.length === 0) return null;
6265
+ const labels = responses.map((response) => {
6266
+ const observation = responseModelIdObservationFromRecord(
6267
+ response,
6268
+ "legacy-difference-only"
6269
+ );
6270
+ if (observation.state === "reported") return `reported:${observation.reportedModelId}`;
6271
+ if (observation.state === "not-reported") return "not-reported";
6272
+ if (observation.state === "not-observed") return "not-observed";
6273
+ return `legacy-difference-only:${observation.differingModelId ?? "none"}`;
6274
+ });
6275
+ return `response_model_id_observation=${labels.join(",")}`;
6276
+ }
6277
+
6278
+ // src/tools/dispatch-run-events.ts
6279
+ var RUN_TAIL_ENTRY_LIMIT = 100;
6280
+ var RUN_TAIL_RUN_LIMIT = 64;
6281
+ var RUN_TAIL_TEXT_LIMIT = 600;
6282
+ function isRecord6(value) {
6283
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6284
+ }
6285
+ function eventDetail(event) {
6286
+ const text = assistantTextFromEvent(event);
6287
+ if (text.length > 0) return truncateUtf8(text, RUN_TAIL_TEXT_LIMIT, "...");
6288
+ if (!isRecord6(event)) return void 0;
6289
+ if (event.type === "clio_tool_finish" && isRecord6(event.payload)) {
6290
+ const tool = typeof event.payload.tool === "string" ? event.payload.tool : "tool";
6291
+ const outcome = typeof event.payload.outcome === "string" ? event.payload.outcome : "";
6292
+ return `${tool} ${outcome}`.trim();
6293
+ }
6294
+ if (event.type === "attempt_start") {
6295
+ const attempt = typeof event.attempt === "number" ? event.attempt : "?";
6296
+ const runId = typeof event.runId === "string" ? event.runId : "?";
6297
+ const reason = typeof event.reason === "string" ? event.reason : "retry";
6298
+ return truncateUtf8(`attempt ${attempt} -> ${runId}: ${reason}`, RUN_TAIL_TEXT_LIMIT, "...");
6299
+ }
6300
+ return void 0;
6301
+ }
6302
+ function runTailEntryFromEvent(event, at = (/* @__PURE__ */ new Date()).toISOString()) {
6303
+ const type = isRecord6(event) && typeof event.type === "string" ? event.type : "unknown";
6304
+ if (type === "heartbeat" || type === "message_update") return null;
6305
+ const entry = { at, type };
6306
+ const detail = eventDetail(event);
6307
+ if (detail !== void 0) entry.detail = detail;
6308
+ return entry;
6309
+ }
6310
+ var REGISTRY_FAILURE_OUTCOME = "failed";
6311
+ var REGISTRY_UNKNOWN_OUTCOME = "unknown";
6312
+ function errorText(error) {
6313
+ return error instanceof Error ? error.message : String(error);
6314
+ }
6315
+ function createDispatchRunEventRegistry(options = {}) {
6316
+ const runTails = /* @__PURE__ */ new Map();
6317
+ const activeRuns = /* @__PURE__ */ new Set();
6318
+ const activeBatches = /* @__PURE__ */ new Set();
6319
+ const journal = options.journal === void 0 ? defaultRunEventJournal() : options.journal;
6320
+ const journalSeal = (logicalRunId, receipt) => {
6321
+ if (journal === null || !isRecord6(receipt)) return;
6322
+ const digest = receipt.integrity?.digest;
6323
+ const outcome = typeof receipt.outcome === "string" ? receipt.outcome : REGISTRY_UNKNOWN_OUTCOME;
6324
+ journal.receipt(logicalRunId, {
6325
+ outcome,
6326
+ exitCode: typeof receipt.exitCode === "number" ? receipt.exitCode : null,
6327
+ ...typeof digest === "string" ? { digest } : {},
6328
+ ...receipt.runId !== logicalRunId ? { attemptRunId: receipt.runId } : {}
6329
+ });
6330
+ journal.terminal(logicalRunId, outcome, receipt.outcomeDetail ?? void 0);
6331
+ };
6332
+ const sealBatchJournals = (assignmentIds, receipts) => {
6333
+ if (journal === null || !Array.isArray(receipts)) return;
6334
+ if (assignmentIds.length === receipts.length) {
6335
+ for (const [index, runId] of assignmentIds.entries()) {
6336
+ const receipt = receipts[index];
6337
+ if (receipt !== void 0) journalSeal(runId, receipt);
6338
+ }
6339
+ return;
6340
+ }
6341
+ for (const receipt of receipts) {
6342
+ if (receipt != null && typeof receipt.runId === "string") journalSeal(receipt.runId, receipt);
6343
+ }
6344
+ };
6345
+ const pruneRunTails = () => {
6346
+ while (runTails.size > RUN_TAIL_RUN_LIMIT) {
6347
+ let oldestKey = null;
6348
+ let oldestSeen = Number.POSITIVE_INFINITY;
6349
+ for (const [key, state] of runTails) {
6350
+ if (activeRuns.has(key) || state.lastSeenAt >= oldestSeen) continue;
6351
+ oldestKey = key;
6352
+ oldestSeen = state.lastSeenAt;
6353
+ }
6354
+ if (oldestKey === null) break;
6355
+ runTails.delete(oldestKey);
6356
+ }
6357
+ };
6358
+ const recordRunEvent = (runId, agentId, event) => {
6359
+ const entry = runTailEntryFromEvent(event);
6360
+ if (entry === null) return;
6361
+ const state = runTails.get(runId) ?? { agentId, entries: [], lastSeenAt: Date.now() };
6362
+ state.lastSeenAt = Date.now();
6363
+ state.entries.push(entry);
6364
+ if (state.entries.length > RUN_TAIL_ENTRY_LIMIT) {
6365
+ state.entries.splice(0, state.entries.length - RUN_TAIL_ENTRY_LIMIT);
6366
+ }
6367
+ runTails.set(runId, state);
6368
+ pruneRunTails();
6369
+ journal?.append(runId, entry);
6370
+ };
6371
+ const drainSingle = async (runId, agentId, events, bus) => {
6372
+ const summary = {
6373
+ count: 0,
6374
+ types: [],
6375
+ lastAssistantText: "",
6376
+ terminalAttemptRunId: runId
6377
+ };
6378
+ for await (const event of events) {
6379
+ summary.count += 1;
6380
+ const type = isRecord6(event) && typeof event.type === "string" ? event.type : "unknown";
6381
+ summary.types.push(type);
6382
+ if (type === "attempt_start") summary.lastAssistantText = "";
6383
+ const text = durableAssistantTextFromEvent(event);
6384
+ if (text.trim().length > 0) summary.lastAssistantText = text;
6385
+ recordRunEvent(runId, agentId, event);
6386
+ if (type !== "heartbeat") bus?.emit(BusChannels.DispatchProgress, { runId, agentId, event });
6387
+ }
6388
+ return summary;
6389
+ };
6390
+ const drainBatch = async (batchId, events, bus) => {
6391
+ const summaries = /* @__PURE__ */ new Map();
6392
+ for await (const event of events) {
6393
+ if (!isRecord6(event) || event.type !== "batch_run_event") continue;
6394
+ const runId = typeof event.runId === "string" ? event.runId : batchId;
6395
+ const agentId = typeof event.agentId === "string" ? event.agentId : "batch";
6396
+ const inner = event.event;
6397
+ const summary = summaries.get(runId) ?? {
6398
+ count: 0,
6399
+ types: [],
6400
+ lastAssistantText: "",
6401
+ terminalAttemptRunId: runId
6402
+ };
6403
+ summary.count += 1;
6404
+ const type = isRecord6(inner) && typeof inner.type === "string" ? inner.type : "unknown";
6405
+ summary.types.push(type);
6406
+ const text = durableAssistantTextFromEvent(inner);
6407
+ if (text.trim().length > 0) summary.lastAssistantText = text;
6408
+ summaries.set(runId, summary);
6409
+ recordRunEvent(runId, agentId, inner);
6410
+ if (type !== "heartbeat") bus?.emit(BusChannels.DispatchProgress, { runId, agentId, event: inner });
6411
+ }
6412
+ return summaries;
6413
+ };
6414
+ return {
6415
+ registerSingle(handle, agentId, bus) {
6416
+ if (activeRuns.has(handle.runId)) {
6417
+ throw new Error(`dispatch event registry: run '${handle.runId}' is already registered`);
6418
+ }
6419
+ activeRuns.add(handle.runId);
6420
+ journal?.open(handle.runId, agentId);
6421
+ const summaryPromise = drainSingle(handle.runId, agentId, handle.events, bus);
6422
+ const completion = Promise.allSettled([summaryPromise, handle.finalPromise]).then(
6423
+ ([summaryResult, receiptResult]) => {
6424
+ if (summaryResult.status === "rejected") throw summaryResult.reason;
6425
+ if (receiptResult.status === "rejected") throw receiptResult.reason;
6426
+ return { receipt: receiptResult.value, summary: summaryResult.value };
6427
+ }
6428
+ );
6429
+ const releaseSingle = () => {
6430
+ activeRuns.delete(handle.runId);
6431
+ pruneRunTails();
6432
+ };
6433
+ void completion.then(
6434
+ ({ receipt }) => {
6435
+ journalSeal(handle.runId, receipt);
6436
+ releaseSingle();
6437
+ },
6438
+ (error) => {
6439
+ journal?.terminal(handle.runId, REGISTRY_FAILURE_OUTCOME, errorText(error));
6440
+ releaseSingle();
6441
+ }
6442
+ );
6443
+ return { runId: handle.runId, completion };
6444
+ },
6445
+ registerBatch(handle, agentIds, bus) {
6446
+ if (activeBatches.has(handle.batchId)) {
6447
+ throw new Error(`dispatch event registry: batch '${handle.batchId}' is already registered`);
6448
+ }
6449
+ const duplicateRunId = handle.assignmentIds.find(
6450
+ (runId, index) => handle.assignmentIds.slice(0, index).includes(runId)
6451
+ );
6452
+ if (duplicateRunId !== void 0) {
6453
+ throw new Error(`dispatch event registry: batch '${handle.batchId}' repeats run '${duplicateRunId}'`);
6454
+ }
6455
+ const activeRunId = handle.assignmentIds.find((runId) => activeRuns.has(runId));
6456
+ if (activeRunId !== void 0) {
6457
+ throw new Error(`dispatch event registry: run '${activeRunId}' is already registered`);
6458
+ }
6459
+ activeBatches.add(handle.batchId);
6460
+ for (const runId of handle.assignmentIds) activeRuns.add(runId);
6461
+ for (const [index, runId] of handle.assignmentIds.entries()) {
6462
+ journal?.open(runId, agentIds[index] ?? "unknown");
6463
+ }
6464
+ const completion = Promise.allSettled([drainBatch(handle.batchId, handle.events, bus), handle.finalPromise]).then(
6465
+ ([summariesResult, receiptsResult]) => {
6466
+ if (summariesResult.status === "rejected") throw summariesResult.reason;
6467
+ if (receiptsResult.status === "rejected") throw receiptsResult.reason;
6468
+ return { receipts: receiptsResult.value, summaries: summariesResult.value };
6469
+ }
6470
+ );
6471
+ const releaseBatch = () => {
6472
+ activeBatches.delete(handle.batchId);
6473
+ for (const runId of handle.assignmentIds) activeRuns.delete(runId);
6474
+ pruneRunTails();
6475
+ };
6476
+ void completion.then(
6477
+ ({ receipts }) => {
6478
+ sealBatchJournals(handle.assignmentIds, receipts);
6479
+ releaseBatch();
6480
+ },
6481
+ (error) => {
6482
+ const detail = errorText(error);
6483
+ for (const runId of handle.assignmentIds) {
6484
+ journal?.terminal(runId, REGISTRY_FAILURE_OUTCOME, detail);
6485
+ }
6486
+ releaseBatch();
6487
+ }
6488
+ );
6489
+ for (const [index, runId] of handle.assignmentIds.entries()) {
6490
+ if (!runTails.has(runId)) {
6491
+ runTails.set(runId, {
6492
+ agentId: agentIds[index] ?? "unknown",
6493
+ entries: [],
6494
+ lastSeenAt: Date.now()
6495
+ });
6496
+ }
6497
+ }
6498
+ return { batchId: handle.batchId, assignmentIds: handle.assignmentIds, completion };
6499
+ },
6500
+ recordEvent: recordRunEvent,
6501
+ eventTail(runId) {
6502
+ const state = runTails.get(runId);
6503
+ return state === void 0 ? null : { agentId: state.agentId, entries: [...state.entries] };
6504
+ }
6505
+ };
6506
+ }
6507
+
6508
+ // src/domains/dispatch/run-event-journal-bridge.ts
6509
+ var OPENED_RUN_LIMIT = 512;
6510
+ function isRecord7(value) {
6511
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6512
+ }
6513
+ function runIdentity(payload) {
6514
+ if (!isRecord7(payload)) return null;
6515
+ if (typeof payload.runId !== "string" || payload.runId.length === 0) return null;
6516
+ return { runId: payload.runId, agentId: typeof payload.agentId === "string" ? payload.agentId : "unknown" };
6517
+ }
6518
+ function attachRunEventJournalBridge(bus, options = {}) {
6519
+ const journal = options.journal ?? defaultRunEventJournal();
6520
+ const opened = /* @__PURE__ */ new Set();
6521
+ const ensureOpen = (runId, agentId) => {
6522
+ if (opened.has(runId)) return;
6523
+ opened.add(runId);
6524
+ while (opened.size > OPENED_RUN_LIMIT) {
6525
+ const oldest = opened.values().next();
6526
+ if (oldest.done === true) break;
6527
+ opened.delete(oldest.value);
6528
+ }
6529
+ journal.open(runId, agentId);
6530
+ };
6531
+ const seal = (outcome, detail, payload) => {
6532
+ const identity = runIdentity(payload);
6533
+ if (identity === null) return;
6534
+ ensureOpen(identity.runId, identity.agentId);
6535
+ const exitCode = isRecord7(payload) && typeof payload.exitCode === "number" ? payload.exitCode : null;
6536
+ journal.receipt(identity.runId, { outcome, exitCode });
6537
+ journal.terminal(identity.runId, outcome, detail ?? void 0);
6538
+ opened.delete(identity.runId);
6539
+ };
6540
+ const unsubscribes = [
6541
+ bus.on(BusChannels.DispatchProgress, (payload) => {
6542
+ const identity = runIdentity(payload);
6543
+ if (identity === null) return;
6544
+ const entry = runTailEntryFromEvent(payload.event);
6545
+ if (entry === null) return;
6546
+ ensureOpen(identity.runId, identity.agentId);
6547
+ const message = isRecord7(payload.event) && typeof payload.event.message === "string" ? payload.event.message : void 0;
6548
+ journal.append(
6549
+ identity.runId,
6550
+ entry.detail === void 0 && message !== void 0 ? { ...entry, detail: message } : entry
6551
+ );
6552
+ }),
6553
+ bus.on(BusChannels.DispatchCompleted, (payload) => {
6554
+ seal(payload.outcome, payload.outcomeDetail, payload);
6555
+ }),
6556
+ bus.on(BusChannels.DispatchFailed, (payload) => {
6557
+ seal(payload.outcome, payload.outcomeDetail, payload);
6558
+ })
6559
+ ];
6560
+ let stopped = false;
6561
+ return {
6562
+ stop() {
6563
+ if (stopped) return;
6564
+ stopped = true;
6565
+ for (const unsubscribe of unsubscribes) unsubscribe();
6566
+ opened.clear();
6865
6567
  }
6866
6568
  };
6867
6569
  }
@@ -6915,27 +6617,27 @@ function detectRunIdentity(env = process.env) {
6915
6617
 
6916
6618
  // src/domains/dispatch/state.ts
6917
6619
  init_esm_shims();
6918
- import { randomBytes as randomBytes5 } from "node:crypto";
6919
- import { existsSync as existsSync11, readFileSync as readFileSync11 } from "node:fs";
6920
- import { join as join13 } from "node:path";
6620
+ import { randomBytes as randomBytes4 } from "node:crypto";
6621
+ import { existsSync as existsSync10, readdirSync as readdirSync3, readFileSync as readFileSync10 } from "node:fs";
6622
+ import { join as join12 } from "node:path";
6921
6623
  function newRunId() {
6922
- const n = BigInt(`0x${randomBytes5(8).toString("hex")}`);
6624
+ const n = BigInt(`0x${randomBytes4(8).toString("hex")}`);
6923
6625
  const raw = n.toString(36);
6924
6626
  if (raw.length >= 12) return raw.slice(0, 12);
6925
6627
  return raw.padStart(12, "0");
6926
6628
  }
6927
6629
  function runsPath() {
6928
- return join13(clioStateDir(), "runs.json");
6630
+ return join12(clioStateDir(), "runs.json");
6929
6631
  }
6930
6632
  function receiptPathFor(runId) {
6931
- return join13(clioStateDir(), "receipts", `${runId}.json`);
6633
+ return join12(clioStateDir(), "receipts", `${runId}.json`);
6932
6634
  }
6933
6635
  function fleetRunPath(runId) {
6934
- return join13(clioStateDir(), "fleet-runs", `${runId}.json`);
6636
+ return join12(clioStateDir(), "fleet-runs", `${runId}.json`);
6935
6637
  }
6936
6638
  function readFleetRun(runId) {
6937
6639
  try {
6938
- const parsed = JSON.parse(readFileSync11(fleetRunPath(runId), "utf8"));
6640
+ const parsed = JSON.parse(readFileSync10(fleetRunPath(runId), "utf8"));
6939
6641
  return parsed.version === 1 && parsed.id === runId ? structuredClone(parsed) : null;
6940
6642
  } catch {
6941
6643
  return null;
@@ -6945,10 +6647,27 @@ async function writeFleetRun(record) {
6945
6647
  await atomicWrite(fleetRunPath(record.id), `${JSON.stringify(record, null, 2)}
6946
6648
  `);
6947
6649
  }
6650
+ var MAX_FLEET_RUN_SCAN = 64;
6651
+ function listFleetRuns(limit = MAX_FLEET_RUN_SCAN) {
6652
+ let entries;
6653
+ try {
6654
+ entries = readdirSync3(join12(clioStateDir(), "fleet-runs"));
6655
+ } catch {
6656
+ return [];
6657
+ }
6658
+ const records = [];
6659
+ for (const name of entries.slice(0, MAX_FLEET_RUN_SCAN)) {
6660
+ if (!name.endsWith(".json")) continue;
6661
+ const record = readFleetRun(name.slice(0, -".json".length));
6662
+ if (record !== null) records.push(record);
6663
+ }
6664
+ records.sort((a, b) => (Date.parse(b.startedAt) || 0) - (Date.parse(a.startedAt) || 0));
6665
+ return records.slice(0, Math.max(0, limit));
6666
+ }
6948
6667
  function readRuns() {
6949
6668
  const path2 = runsPath();
6950
- if (!existsSync11(path2)) return [];
6951
- const raw = readFileSync11(path2, "utf8").trim();
6669
+ if (!existsSync10(path2)) return [];
6670
+ const raw = readFileSync10(path2, "utf8").trim();
6952
6671
  if (raw.length === 0) return [];
6953
6672
  const parsed = JSON.parse(raw);
6954
6673
  if (!Array.isArray(parsed)) return [];
@@ -7106,6 +6825,10 @@ function openLedger(opts) {
7106
6825
  const capped = capRuns(merged, maxRuns);
7107
6826
  runs = capped;
7108
6827
  atomicWrite(target, JSON.stringify(capped, null, 2));
6828
+ if (merged.length > capped.length) {
6829
+ const kept = new Set(capped.map((run) => run.id));
6830
+ removeRunEventJournals(merged.filter((run) => !kept.has(run.id)).map((run) => run.id));
6831
+ }
7109
6832
  dirty.clear();
7110
6833
  });
7111
6834
  },
@@ -7274,7 +6997,7 @@ function requestOriginFor(req) {
7274
6997
  return req.requestOrigin ?? "agent";
7275
6998
  }
7276
6999
  function sha2565(input) {
7277
- return createHash9("sha256").update(input, "utf8").digest("hex");
7000
+ return createHash7("sha256").update(input, "utf8").digest("hex");
7278
7001
  }
7279
7002
  function promptHash(systemPrompt) {
7280
7003
  return systemPrompt.length > 0 ? sha2565(systemPrompt) : null;
@@ -7416,8 +7139,8 @@ var DISPATCH_DRAIN_GRACE_MS = 2e3;
7416
7139
  var RUN_WRITE_TARGET_HISTORY = 512;
7417
7140
  async function awaitEventDrain(drained, graceMs = DISPATCH_DRAIN_GRACE_MS) {
7418
7141
  let timer;
7419
- const grace = new Promise((resolve5) => {
7420
- timer = setTimeout(() => resolve5(false), graceMs);
7142
+ const grace = new Promise((resolve4) => {
7143
+ timer = setTimeout(() => resolve4(false), graceMs);
7421
7144
  });
7422
7145
  try {
7423
7146
  return await Promise.race([drained.then(() => true), grace]);
@@ -8496,19 +8219,21 @@ function createDispatchBundle(context, options) {
8496
8219
  return DEFAULT_RESILIENCE_COOLDOWN_MS;
8497
8220
  };
8498
8221
  const now = options?.now ?? (() => Date.now());
8222
+ const monotonicNow = options?.monotonicNow ?? (() => performance5.now());
8499
8223
  const routeObserver = options?.routeObserver ?? createRouteObserver({});
8500
8224
  let ledger = null;
8501
8225
  let heartbeatTimer = null;
8502
8226
  const active = /* @__PURE__ */ new Map();
8227
+ const pendingCapacity = /* @__PURE__ */ new Map();
8503
8228
  const targetCooldowns = /* @__PURE__ */ new Map();
8504
8229
  const ownedReservations = /* @__PURE__ */ new Set();
8505
- const runWriteTargets = /* @__PURE__ */ new Map();
8506
- const recordRunWriteTargets = (runId, paths) => {
8507
- runWriteTargets.set(runId, paths);
8508
- while (runWriteTargets.size > RUN_WRITE_TARGET_HISTORY) {
8509
- const oldest = runWriteTargets.keys().next();
8230
+ const runWriteAttributions = /* @__PURE__ */ new Map();
8231
+ const recordRunWriteAttribution = (runId, attribution) => {
8232
+ runWriteAttributions.set(runId, attribution);
8233
+ while (runWriteAttributions.size > RUN_WRITE_TARGET_HISTORY) {
8234
+ const oldest = runWriteAttributions.keys().next();
8510
8235
  if (oldest.done === true) break;
8511
- runWriteTargets.delete(oldest.value);
8236
+ runWriteAttributions.delete(oldest.value);
8512
8237
  }
8513
8238
  };
8514
8239
  const capacityAdmission = createCapacityAdmissionController({
@@ -8516,7 +8241,7 @@ function createDispatchBundle(context, options) {
8516
8241
  const settings = getEffectiveSettings();
8517
8242
  const nodes = { local: configuredGlobalCapacity(settings) };
8518
8243
  for (const node of settings?.fleet?.nodes ?? []) nodes[node.id] = node.maxWorkers;
8519
- return { global: configuredGlobalCapacity(settings), nodes };
8244
+ return { global: configuredGlobalCapacity(settings), nodes, endpoints: configuredEndpointLimits() };
8520
8245
  },
8521
8246
  now,
8522
8247
  reservedPlanPeak: (planId) => reservedPlanPeakSlots(planId, (error) => reportDispatchDiagnostic("read reserved plan peak", error))
@@ -8527,6 +8252,24 @@ function createDispatchBundle(context, options) {
8527
8252
  onError: (error) => reportDispatchDiagnostic("read capacity lease usage", error)
8528
8253
  })
8529
8254
  );
8255
+ function configuredEndpointCapacities() {
8256
+ return resolveEndpointCapacities({
8257
+ statuses: providers.list(),
8258
+ targets: getEffectiveSettings()?.targets ?? [],
8259
+ runtimeFor: (runtimeId) => providers.getRuntime(runtimeId)
8260
+ });
8261
+ }
8262
+ function configuredEndpointLimits() {
8263
+ return Object.fromEntries(Object.entries(configuredEndpointCapacities()).map(([key, value]) => [key, value.limit]));
8264
+ }
8265
+ function endpointCapacityForTarget(targetId) {
8266
+ const status = providers.list().find((entry) => entry.target.id === targetId);
8267
+ const target = status?.target ?? providers.getTarget(targetId);
8268
+ if (target === null || target === void 0) return null;
8269
+ const endpoint = status === void 0 ? endpointCapacityFor({ target, runtime: providers.getRuntime(target.runtime) }) : endpointCapacityForStatus(status);
8270
+ if (endpoint === null) return null;
8271
+ return configuredEndpointCapacities()[endpoint.key] ?? endpoint;
8272
+ }
8530
8273
  function reservationCapacitySnapshot(settings) {
8531
8274
  const preflight = scheduling.preflight();
8532
8275
  const usage = capacityLeaseUsage();
@@ -8535,9 +8278,21 @@ function createDispatchBundle(context, options) {
8535
8278
  };
8536
8279
  for (const node of settings?.fleet?.nodes ?? [])
8537
8280
  nodes[node.id] = { active: usage.nodes[node.id] ?? 0, limit: node.maxWorkers };
8281
+ const endpoints = Object.fromEntries(
8282
+ Object.entries(configuredEndpointLimits()).map(([key, limit]) => [
8283
+ key,
8284
+ {
8285
+ active: usage.endpoints[key] ?? 0,
8286
+ limit,
8287
+ leases: usage.endpointHolders[key]?.leases ?? 0,
8288
+ foregroundStreams: usage.endpointHolders[key]?.foregroundStreams ?? 0
8289
+ }
8290
+ ])
8291
+ );
8538
8292
  return {
8539
8293
  global: { active: usage.global, limit: configuredGlobalCapacity(settings) },
8540
8294
  nodes,
8295
+ endpoints,
8541
8296
  budget: { currentUsd: preflight.currentUsd, ceilingUsd: preflight.ceilingUsd }
8542
8297
  };
8543
8298
  }
@@ -8548,6 +8303,7 @@ function createDispatchBundle(context, options) {
8548
8303
  memberId: task.memberId,
8549
8304
  wave: task.wave,
8550
8305
  nodeId: task.resolution.node.id,
8306
+ ...task.resolution.endpoint !== void 0 ? { endpointKey: task.resolution.endpoint.key } : {},
8551
8307
  costUpperBoundUsd: task.resolution.routeApproval?.totalCostUpperBoundUsd ?? task.resolution.costUpperBoundUsd
8552
8308
  })),
8553
8309
  capacity: reservationCapacitySnapshot(getEffectiveSettings()),
@@ -8589,10 +8345,24 @@ function createDispatchBundle(context, options) {
8589
8345
  const configured = settings?.budget.concurrency;
8590
8346
  return scheduling.maxWorkers?.() ?? (configured === "auto" || configured === void 0 ? 4 : Math.max(1, configured));
8591
8347
  }
8592
- async function admitAssignmentCapacity(req, nodeId, timing) {
8348
+ function publishCapacityQueued(identity, timing, node) {
8349
+ pendingCapacity.set(identity.runId, { identity, timing, node });
8350
+ context.bus.emit(BusChannels.DispatchEnqueued, identity);
8351
+ }
8352
+ function publishCapacityAdmissionFailure(identity, error) {
8353
+ const detail = error instanceof Error ? error.message : String(error);
8354
+ const outcome = error instanceof AdmissionCanceledError ? "canceled" : /admission timed out/u.test(detail) ? "timed_out" : "denied_by_policy";
8355
+ context.bus.emit(BusChannels.DispatchFailed, {
8356
+ ...identity,
8357
+ outcome,
8358
+ outcomeDetail: detail,
8359
+ reason: outcome
8360
+ });
8361
+ }
8362
+ async function admitAssignmentCapacity(req, nodeId, timing, endpoint) {
8593
8363
  const queuedAt = now();
8594
8364
  timing.queuedAt = new Date(queuedAt).toISOString();
8595
- const assignmentId = req.lineage?.rootRunId ?? `pending-${queuedAt.toString(36)}-${randomBytes6(6).toString("hex")}`;
8365
+ const assignmentId = req.lineage?.rootRunId ?? req.runIdHint ?? `pending-${queuedAt.toString(36)}-${randomBytes5(6).toString("hex")}`;
8596
8366
  const requestedAt = Date.parse(timing.requestedAt ?? timing.queuedAt);
8597
8367
  const deadlineAt = req.assignmentDeadlineAt ?? requestedAt + (req.routingIntent?.deadlineMs ?? 6e4);
8598
8368
  if (req.lineage === void 0) await registerAssignment(assignmentId);
@@ -8605,9 +8375,14 @@ function createDispatchBundle(context, options) {
8605
8375
  const admitted = await capacityAdmission.admit({
8606
8376
  assignmentId,
8607
8377
  nodeId,
8378
+ ...endpoint !== null && endpoint !== void 0 ? { endpointKey: endpoint.key } : {},
8608
8379
  deadlineAt,
8609
8380
  ...plan,
8610
- ...req.reservation !== void 0 && req.lineage === void 0 ? { reservation: req.reservation } : {}
8381
+ // A fleet's first attempt carries lineage and still owns the held
8382
+ // reservation member that admission must transfer into its lease.
8383
+ // Retries carry the same reservation identity after that member was
8384
+ // consumed, so they reacquire/rebind the assignment lease normally.
8385
+ ...req.reservation !== void 0 && (req.lineage === void 0 || req.lineage.attempt === 0) ? { reservation: req.reservation } : {}
8611
8386
  });
8612
8387
  timing.admittedAt = new Date(admitted.admittedAt).toISOString();
8613
8388
  return admitted.lease;
@@ -8619,12 +8394,13 @@ function createDispatchBundle(context, options) {
8619
8394
  throw error;
8620
8395
  }
8621
8396
  }
8622
- function rebindReservationSlot(req, nodeId, costUsd, settings) {
8397
+ function rebindReservationSlot(req, nodeId, endpoint, costUsd, settings) {
8623
8398
  if (req.reservation === void 0 || req.lineage === void 0) return;
8624
8399
  const capacity = reservationCapacitySnapshot(settings);
8625
8400
  const rebind = {
8626
8401
  ...req.reservation,
8627
8402
  nodeId,
8403
+ ...endpoint !== null ? { endpointKey: endpoint.key } : {},
8628
8404
  costUpperBoundUsd: req.routeApproval?.totalCostUpperBoundUsd ?? costUsd,
8629
8405
  capacity,
8630
8406
  nowMs: now()
@@ -8691,10 +8467,23 @@ function createDispatchBundle(context, options) {
8691
8467
  persistAssignment(settleStoredAssignment(rootRunId, attemptRunId, "failed"), `${rootRunId}:finalize-error`);
8692
8468
  capacityAdmission.releaseAssignment(rootRunId);
8693
8469
  }
8470
+ function retryChainIsLive(run) {
8471
+ if (run.aborted) return false;
8472
+ const reservation = run.req.reservation;
8473
+ if (reservation === void 0) return assignments.get(run.lineage.rootRunId)?.status === "running";
8474
+ try {
8475
+ const record = getDispatchReservation(reservation.ownerId);
8476
+ const member = record?.members.find((entry) => entry.memberId === reservation.memberId);
8477
+ return record?.status === "active" && member !== void 0 && member.status !== "released";
8478
+ } catch (error) {
8479
+ reportDispatchDiagnostic(`read retry liveness for reservation member ${reservation.memberId}`, error);
8480
+ return false;
8481
+ }
8482
+ }
8694
8483
  function maybeScheduleRetry(run, outcome, detail, receipt, failureClass) {
8695
8484
  if (draining) return { scheduled: false };
8696
8485
  const rootRunId = run.lineage.rootRunId;
8697
- if (assignments.get(rootRunId)?.status !== "running") return { scheduled: false };
8486
+ if (!retryChainIsLive(run)) return { scheduled: false };
8698
8487
  if (!RETRYABLE_OUTCOMES.has(outcome)) {
8699
8488
  retryBackoff.delete(rootRunId);
8700
8489
  return { scheduled: false };
@@ -8803,7 +8592,7 @@ function createDispatchBundle(context, options) {
8803
8592
  });
8804
8593
  }
8805
8594
  async function executeRetry(run, attempt, reason = "retry", decision = decideRetry("internal", run.lineage.attempt, assignmentPolicyFor(run.req).maxRetries)) {
8806
- if (draining || assignments.get(run.lineage.rootRunId)?.status !== "running") return;
8595
+ if (draining || !retryChainIsLive(run)) return;
8807
8596
  const excludesNode = decision.excludedRouteParts.includes("node");
8808
8597
  const rerouteHops = excludesNode && run.node !== null ? [...run.req.reroutes ?? [], { attempt, fromNode: run.node.id, toNode: "", reason }] : run.req.reroutes;
8809
8598
  const retryReq = {
@@ -8817,6 +8606,7 @@ function createDispatchBundle(context, options) {
8817
8606
  depth: run.lineage.depth
8818
8607
  }
8819
8608
  };
8609
+ delete retryReq.runIdHint;
8820
8610
  const reasonKey = retryReasonKey(run.lineage.rootRunId, attempt);
8821
8611
  retryReasons.set(reasonKey, reason);
8822
8612
  try {
@@ -8959,8 +8749,8 @@ function createDispatchBundle(context, options) {
8959
8749
  fleetRegistry.recordChannelSuccess(run.node.id);
8960
8750
  }
8961
8751
  }
8962
- function heartbeatIso(heartbeatMs) {
8963
- return new Date(heartbeatMs).toISOString();
8752
+ function heartbeatIso(heartbeat) {
8753
+ return new Date(heartbeat.current).toISOString();
8964
8754
  }
8965
8755
  function heartbeatRunStatus(status) {
8966
8756
  return status === "alive" ? "running" : status;
@@ -8979,22 +8769,22 @@ function createDispatchBundle(context, options) {
8979
8769
  event: {
8980
8770
  type: "heartbeat_status",
8981
8771
  status,
8982
- heartbeatAt: run.heartbeatAt ? heartbeatIso(run.heartbeatAt.current) : null
8772
+ heartbeatAt: run.heartbeatAt ? heartbeatIso(run.heartbeatAt) : null
8983
8773
  }
8984
8774
  });
8985
8775
  }
8986
8776
  function checkActiveHeartbeats() {
8987
8777
  if (!ledger) return;
8988
- const tickNow = now();
8778
+ const tickMonotonic = monotonicNow();
8989
8779
  for (const run of active.values()) {
8990
8780
  if (run.aborted || run.stallKilled || !run.heartbeatAt) continue;
8991
- const heartbeatMs = run.heartbeatAt.current;
8992
- if (!Number.isFinite(heartbeatMs)) continue;
8781
+ const heartbeatMonotonic = heartbeatMonotonicAt(run.heartbeatAt);
8782
+ if (!Number.isFinite(heartbeatMonotonic) || !Number.isFinite(run.heartbeatAt.current)) continue;
8993
8783
  if (run.runtimeKind === "acp-delegation") {
8994
- ledger.update(run.runId, { heartbeatAt: heartbeatIso(heartbeatMs) });
8784
+ ledger.update(run.runId, { heartbeatAt: heartbeatIso(run.heartbeatAt) });
8995
8785
  const stallMs = run.stallTimeoutMs;
8996
8786
  if (stallMs === null || stallMs <= 0) continue;
8997
- if (tickNow - heartbeatMs <= stallMs) continue;
8787
+ if (tickMonotonic - heartbeatMonotonic <= stallMs) continue;
8998
8788
  run.stallKilled = true;
8999
8789
  run.heartbeatStatus = "dead";
9000
8790
  emitHeartbeatStatus(run, "dead");
@@ -9004,10 +8794,10 @@ function createDispatchBundle(context, options) {
9004
8794
  }
9005
8795
  continue;
9006
8796
  }
9007
- const status = classifyHeartbeat(heartbeatMs, tickNow, heartbeatSpec);
8797
+ const status = classifyHeartbeat(heartbeatMonotonic, tickMonotonic, heartbeatSpec);
9008
8798
  const patch = {
9009
8799
  status: heartbeatRunStatus(status),
9010
- heartbeatAt: heartbeatIso(heartbeatMs)
8800
+ heartbeatAt: heartbeatIso(run.heartbeatAt)
9011
8801
  };
9012
8802
  ledger.update(run.runId, patch);
9013
8803
  if (status === "alive" && run.node !== null && run.node.kind === "ssh") {
@@ -9343,7 +9133,26 @@ function createDispatchBundle(context, options) {
9343
9133
  const wireModelId = lifecycle.agentConfig.id;
9344
9134
  assertTargetNotCoolingDown(req, targetId, runtimeId, wireModelId);
9345
9135
  assertBudgetAdmitsRoute(req, { rates: null, provenance: "unknown" }, settings);
9346
- const capacityLease = await admitAssignmentCapacity(req, "local", timing);
9136
+ const queuedIdentity = req.lineage === void 0 && req.runIdHint !== void 0 ? {
9137
+ runId: req.runIdHint,
9138
+ agentId: req.agentId,
9139
+ task: req.task,
9140
+ requestOrigin: lifecycle.requestOrigin,
9141
+ targetId,
9142
+ wireModelId,
9143
+ runtimeId,
9144
+ runtimeKind: "acp-delegation"
9145
+ } : null;
9146
+ if (queuedIdentity !== null) publishCapacityQueued(queuedIdentity, timing, null);
9147
+ let capacityLease;
9148
+ try {
9149
+ capacityLease = await admitAssignmentCapacity(req, "local", timing, null);
9150
+ } catch (error) {
9151
+ if (queuedIdentity !== null) publishCapacityAdmissionFailure(queuedIdentity, error);
9152
+ throw error;
9153
+ } finally {
9154
+ if (queuedIdentity !== null) pendingCapacity.delete(queuedIdentity.runId);
9155
+ }
9347
9156
  const leaseSlot = createLeaseSlotGuard(capacityAdmission, capacityLease.leaseId, req.lineage !== void 0);
9348
9157
  const ledgerRef = (() => {
9349
9158
  try {
@@ -9365,7 +9174,9 @@ function createDispatchBundle(context, options) {
9365
9174
  cwd: lifecycle.cwd,
9366
9175
  safety,
9367
9176
  autonomy: lifecycle.autonomy,
9368
- clientVersion: readClioVersion()
9177
+ clientVersion: readClioVersion(),
9178
+ now,
9179
+ monotonicNow
9369
9180
  });
9370
9181
  } catch (error) {
9371
9182
  leaseSlot.release();
@@ -9510,15 +9321,17 @@ function createDispatchBundle(context, options) {
9510
9321
  runIdForPermissionAudit = envelope.id;
9511
9322
  lineage = lineageFor(req, envelope.id);
9512
9323
  if (req.lineage === void 0) {
9513
- capacityAdmission.rename(capacityLease.leaseId, lineage.rootRunId);
9514
- await renameStoredAssignment(capacityLease.assignmentId, lineage.rootRunId);
9324
+ if (capacityLease.assignmentId !== lineage.rootRunId) {
9325
+ capacityAdmission.rename(capacityLease.leaseId, lineage.rootRunId);
9326
+ await renameStoredAssignment(capacityLease.assignmentId, lineage.rootRunId);
9327
+ }
9515
9328
  leaseSlot.transferToAssignment();
9516
9329
  }
9517
9330
  identity = detectRunIdentity();
9518
9331
  ledgerRef.update(envelope.id, {
9519
9332
  status: "running",
9520
9333
  pid: acp.pid,
9521
- heartbeatAt: heartbeatIso(acp.heartbeatAt.current),
9334
+ heartbeatAt: heartbeatIso(acp.heartbeatAt),
9522
9335
  lineage,
9523
9336
  identity,
9524
9337
  node: LOCAL_RUN_NODE,
@@ -9535,16 +9348,18 @@ function createDispatchBundle(context, options) {
9535
9348
  runtimeKind: "acp-delegation"
9536
9349
  });
9537
9350
  await ledgerRef.persist();
9538
- context.bus.emit(BusChannels.DispatchEnqueued, {
9539
- runId: envelope.id,
9540
- agentId: req.agentId,
9541
- task: req.task,
9542
- requestOrigin: lifecycle.requestOrigin,
9543
- targetId,
9544
- wireModelId,
9545
- runtimeId,
9546
- runtimeKind: "acp-delegation"
9547
- });
9351
+ if (req.lineage !== void 0) {
9352
+ context.bus.emit(BusChannels.DispatchEnqueued, {
9353
+ runId: envelope.id,
9354
+ agentId: req.agentId,
9355
+ task: req.task,
9356
+ requestOrigin: lifecycle.requestOrigin,
9357
+ targetId,
9358
+ wireModelId,
9359
+ runtimeId,
9360
+ runtimeKind: "acp-delegation"
9361
+ });
9362
+ }
9548
9363
  context.bus.emit(BusChannels.DispatchStarted, {
9549
9364
  runId: envelope.id,
9550
9365
  agentId: req.agentId,
@@ -9878,7 +9693,7 @@ function createDispatchBundle(context, options) {
9878
9693
  cacheReadTokenCount: receiptDraft.cacheReadTokenCount ?? 0,
9879
9694
  cacheWriteTokenCount: receiptDraft.cacheWriteTokenCount ?? 0,
9880
9695
  reasoningTokenCount: receiptDraft.reasoningTokenCount ?? 0,
9881
- heartbeatAt: heartbeatIso(acp.heartbeatAt.current)
9696
+ heartbeatAt: heartbeatIso(acp.heartbeatAt)
9882
9697
  };
9883
9698
  ledgerRef.update(envelope.id, ledgerPatch);
9884
9699
  const receipt = ledgerRef.recordReceipt(envelope.id, sealRouteDecision(receiptDraft, routeDecision));
@@ -9951,6 +9766,7 @@ function createDispatchBundle(context, options) {
9951
9766
  throw new Error(`dispatch: invalid spec: ${validated.errors.join("; ")}`);
9952
9767
  }
9953
9768
  req = validation.restore(validated.spec);
9769
+ if (req.lineage === void 0 && req.runIdHint === void 0) req = { ...req, runIdHint: newRunId() };
9954
9770
  let activeRouteObservation = null;
9955
9771
  if (req.delegationAgentId === void 0) {
9956
9772
  const recipe = agents.get(req.agentId);
@@ -10015,7 +9831,7 @@ function createDispatchBundle(context, options) {
10015
9831
  "dispatch: writeRoots cannot be enforced on an ACP delegation target; the external agent runs its own tool surface. Dispatch to a native or claude-sdk worker."
10016
9832
  );
10017
9833
  }
10018
- rebindReservationSlot(req, "local", UNKNOWN_PRICING_ADMISSION_ESTIMATE_USD, settings);
9834
+ rebindReservationSlot(req, "local", null, UNKNOWN_PRICING_ADMISSION_ESTIMATE_USD, settings);
10019
9835
  routeObservation = observeShadowRoute(req, void 0, settings);
10020
9836
  return attachRouteObservation({
10021
9837
  ...await dispatchAcpDelegation(req, settings, timing, routeObservation.decision, observer),
@@ -10046,10 +9862,12 @@ function createDispatchBundle(context, options) {
10046
9862
  model: lifecycle.target.wireModelId,
10047
9863
  node: placement?.node?.id ?? "local"
10048
9864
  };
9865
+ const endpoint = endpointCapacityForTarget(lifecycle.target.target.id);
10049
9866
  assertRouteWithinApprovedEnvelope(req, effectiveRoute);
10050
9867
  rebindReservationSlot(
10051
9868
  req,
10052
9869
  effectiveRoute.node,
9870
+ endpoint,
10053
9871
  conservativeRouteAdmissionEstimateUsd(lifecycle.target.effectivePricing, admissionMaxOutputTokens(settings)),
10054
9872
  settings
10055
9873
  );
@@ -10067,7 +9885,34 @@ function createDispatchBundle(context, options) {
10067
9885
  },
10068
9886
  shadow: () => observeShadowRoute(req, placed, settings)
10069
9887
  });
10070
- const capacityLease = await admitAssignmentCapacity(req, placement?.node.id ?? "local", timing);
9888
+ const queuedIdentity = req.lineage === void 0 && req.runIdHint !== void 0 ? {
9889
+ runId: req.runIdHint,
9890
+ agentId: req.agentId,
9891
+ task: req.task,
9892
+ agentAudience: lifecycle.agentAudience,
9893
+ requestOrigin: lifecycle.requestOrigin,
9894
+ targetId: lifecycle.target.target.id,
9895
+ wireModelId: lifecycle.target.wireModelId,
9896
+ runtimeId: lifecycle.target.runtime.id,
9897
+ runtimeKind: lifecycle.runtimeKind,
9898
+ budget: lifecycle.budgetEnvelope,
9899
+ ...endpoint !== null ? { endpoint: { key: endpoint.key, label: endpoint.label, limit: endpoint.limit } } : {},
9900
+ ...placement !== null ? { node: placement.node.id } : {},
9901
+ ...req.gate !== void 0 ? { gate: { role: req.gate.role, cycle: req.gate.cycle } } : {},
9902
+ ...req.council !== void 0 ? { council: req.council } : {},
9903
+ ...req.reroutes !== void 0 && req.reroutes.length > 0 ? { rerouteCount: req.reroutes.length } : {},
9904
+ ...lifecycle.target.modelCapabilities !== void 0 && lifecycle.target.modelCapabilities !== null && lifecycle.target.modelCapabilities.contextWindow > 0 ? { contextWindow: lifecycle.target.modelCapabilities.contextWindow } : {}
9905
+ } : null;
9906
+ if (queuedIdentity !== null) publishCapacityQueued(queuedIdentity, timing, placement?.node ?? null);
9907
+ let capacityLease;
9908
+ try {
9909
+ capacityLease = await admitAssignmentCapacity(req, placement?.node.id ?? "local", timing, endpoint);
9910
+ } catch (error) {
9911
+ if (queuedIdentity !== null) publishCapacityAdmissionFailure(queuedIdentity, error);
9912
+ throw error;
9913
+ } finally {
9914
+ if (queuedIdentity !== null) pendingCapacity.delete(queuedIdentity.runId);
9915
+ }
10071
9916
  const leaseSlot = createLeaseSlotGuard(capacityAdmission, capacityLease.leaseId, req.lineage !== void 0);
10072
9917
  const ledgerRef = (() => {
10073
9918
  try {
@@ -10125,6 +9970,8 @@ function createDispatchBundle(context, options) {
10125
9970
  try {
10126
9971
  worker = (placement?.spawn ?? spawnWorker)(spec, {
10127
9972
  cwd: lifecycle.cwd,
9973
+ now,
9974
+ monotonicNow,
10128
9975
  ...agentLedgerId !== null ? { onLedgerPost } : {}
10129
9976
  });
10130
9977
  } catch (error) {
@@ -10174,7 +10021,18 @@ function createDispatchBundle(context, options) {
10174
10021
  const upstreamResponses = [];
10175
10022
  const skillActivations = [];
10176
10023
  const finishContractEntries = [];
10177
- const runEffects = createRunEffectsRecorder(lifecycle.cwd);
10024
+ let runIdForPermissionAudit = null;
10025
+ const runEffects = createRunEffectsRecorder(lifecycle.cwd, {
10026
+ onWriteRecordDowngraded(downgrade) {
10027
+ const runId = runIdForPermissionAudit;
10028
+ if (runId === null) return;
10029
+ context.bus.emit(BusChannels.DispatchProgress, {
10030
+ runId,
10031
+ agentId: req.agentId,
10032
+ event: { type: "clio_write_record_downgraded", payload: downgrade }
10033
+ });
10034
+ }
10035
+ });
10178
10036
  let finishContractAssistantText = "";
10179
10037
  let finishContractAssistantTurnId = null;
10180
10038
  let failureMessage;
@@ -10182,7 +10040,6 @@ function createDispatchBundle(context, options) {
10182
10040
  const trustedOutcomeCodes = /* @__PURE__ */ new Set();
10183
10041
  let reportedUntrustedOutcome = false;
10184
10042
  const acceptsOutcomeCodeEvents = lifecycle.runtimeKind === "http" || lifecycle.runtimeKind === "sdk" && lifecycle.target.runtime.id === "claude-sdk";
10185
- let runIdForPermissionAudit = null;
10186
10043
  let workerPolicyPermissionCounter = 0;
10187
10044
  const outputCapture = createWorkerOutputCapture();
10188
10045
  const markObservedPhase = (field) => {
@@ -10253,6 +10110,7 @@ function createDispatchBundle(context, options) {
10253
10110
  ...ruleId !== null ? { ruleId } : {},
10254
10111
  ...policySource !== null ? { policySource } : {},
10255
10112
  ...typeof event.payload.timeoutMs === "number" ? { timeoutMs: event.payload.timeoutMs } : {},
10113
+ fallback: spec.escalation?.fallback ?? "deny",
10256
10114
  escalation: true
10257
10115
  });
10258
10116
  }
@@ -10310,6 +10168,7 @@ function createDispatchBundle(context, options) {
10310
10168
  decidedBy,
10311
10169
  actionClass,
10312
10170
  reason,
10171
+ ...source === "timeout" ? { fallback: spec.escalation?.fallback ?? "deny" } : {},
10313
10172
  ...runIdForPermissionAudit !== null ? { requestedBy: runIdForPermissionAudit } : {}
10314
10173
  });
10315
10174
  }
@@ -10362,8 +10221,10 @@ function createDispatchBundle(context, options) {
10362
10221
  runIdForPermissionAudit = envelope.id;
10363
10222
  lineage = lineageFor(req, envelope.id);
10364
10223
  if (req.lineage === void 0) {
10365
- capacityAdmission.rename(capacityLease.leaseId, lineage.rootRunId);
10366
- await renameStoredAssignment(capacityLease.assignmentId, lineage.rootRunId);
10224
+ if (capacityLease.assignmentId !== lineage.rootRunId) {
10225
+ capacityAdmission.rename(capacityLease.leaseId, lineage.rootRunId);
10226
+ await renameStoredAssignment(capacityLease.assignmentId, lineage.rootRunId);
10227
+ }
10367
10228
  leaseSlot.transferToAssignment();
10368
10229
  }
10369
10230
  if (agentLedgerId !== null) {
@@ -10395,7 +10256,7 @@ function createDispatchBundle(context, options) {
10395
10256
  ...req.council !== void 0 ? { council: req.council } : {},
10396
10257
  ...req.plan !== void 0 ? { plan: req.plan } : {},
10397
10258
  ...lifecycle.personaOverride ? { personaOverride: lifecycle.personaOverride } : {},
10398
- ...heartbeatAt ? { heartbeatAt: heartbeatIso(heartbeatAt.current) } : {}
10259
+ ...heartbeatAt ? { heartbeatAt: heartbeatIso(heartbeatAt) } : {}
10399
10260
  });
10400
10261
  observer?.onAdmitted({
10401
10262
  runId: envelope.id,
@@ -10405,24 +10266,27 @@ function createDispatchBundle(context, options) {
10405
10266
  await ledgerRef.persist();
10406
10267
  const fleetIdentity = {
10407
10268
  budget: lifecycle.budgetEnvelope,
10269
+ ...endpoint !== null ? { endpoint: { key: endpoint.key, label: endpoint.label, limit: endpoint.limit } } : {},
10408
10270
  ...placement !== void 0 && placement !== null ? { node: placement.node.id } : {},
10409
10271
  ...req.gate !== void 0 ? { gate: { role: req.gate.role, cycle: req.gate.cycle } } : {},
10410
10272
  ...req.council !== void 0 ? { council: req.council } : {},
10411
10273
  ...req.reroutes !== void 0 && req.reroutes.length > 0 ? { rerouteCount: req.reroutes.length } : {},
10412
10274
  ...lifecycle.target.modelCapabilities !== void 0 && lifecycle.target.modelCapabilities !== null && lifecycle.target.modelCapabilities.contextWindow > 0 ? { contextWindow: lifecycle.target.modelCapabilities.contextWindow } : {}
10413
10275
  };
10414
- context.bus.emit(BusChannels.DispatchEnqueued, {
10415
- runId: envelope.id,
10416
- agentId: req.agentId,
10417
- task: req.task,
10418
- agentAudience: lifecycle.agentAudience,
10419
- requestOrigin: lifecycle.requestOrigin,
10420
- targetId: lifecycle.target.target.id,
10421
- wireModelId: lifecycle.target.wireModelId,
10422
- runtimeId: lifecycle.target.runtime.id,
10423
- runtimeKind: lifecycle.runtimeKind,
10424
- ...fleetIdentity
10425
- });
10276
+ if (req.lineage !== void 0) {
10277
+ context.bus.emit(BusChannels.DispatchEnqueued, {
10278
+ runId: envelope.id,
10279
+ agentId: req.agentId,
10280
+ task: req.task,
10281
+ agentAudience: lifecycle.agentAudience,
10282
+ requestOrigin: lifecycle.requestOrigin,
10283
+ targetId: lifecycle.target.target.id,
10284
+ wireModelId: lifecycle.target.wireModelId,
10285
+ runtimeId: lifecycle.target.runtime.id,
10286
+ runtimeKind: lifecycle.runtimeKind,
10287
+ ...fleetIdentity
10288
+ });
10289
+ }
10426
10290
  context.bus.emit(BusChannels.DispatchStarted, {
10427
10291
  runId: envelope.id,
10428
10292
  agentId: req.agentId,
@@ -10527,10 +10391,10 @@ function createDispatchBundle(context, options) {
10527
10391
  const fleetGate = (() => {
10528
10392
  if (req.fleetGateReceipt === void 0) return null;
10529
10393
  try {
10530
- const content = readFileSync12(resolvePath(lifecycle.cwd, req.fleetGateReceipt.path));
10531
- return { path: req.fleetGateReceipt.path, pathHash: createHash9("sha256").update(content).digest("hex") };
10394
+ const content = readFileSync11(resolvePath(lifecycle.cwd, req.fleetGateReceipt.path));
10395
+ return { path: req.fleetGateReceipt.path, pathHash: createHash7("sha256").update(content).digest("hex") };
10532
10396
  } catch {
10533
- return { path: req.fleetGateReceipt.path, pathHash: createHash9("sha256").update("").digest("hex") };
10397
+ return { path: req.fleetGateReceipt.path, pathHash: createHash7("sha256").update("").digest("hex") };
10534
10398
  }
10535
10399
  })();
10536
10400
  const ledgerContribution = (() => {
@@ -10785,18 +10649,7 @@ function createDispatchBundle(context, options) {
10785
10649
  cwd: lifecycle.cwd,
10786
10650
  networkAllowed: lifecycle.admission.allowedTools.includes(ToolNames.WebFetch),
10787
10651
  observedRunEffects,
10788
- filesystem: {
10789
- readFile(filePath) {
10790
- try {
10791
- return readFileSync12(filePath, "utf8");
10792
- } catch {
10793
- return null;
10794
- }
10795
- },
10796
- pathExists(filePath) {
10797
- return existsSync12(filePath);
10798
- }
10799
- }
10652
+ filesystem: nodeResultContractFilesystem()
10800
10653
  });
10801
10654
  const resultValidation = resultContract?.applicable === true ? resultContract.validation : null;
10802
10655
  if (finalOutcome === "succeeded" && resultValidation?.conformance === "fail") {
@@ -10887,15 +10740,35 @@ function createDispatchBundle(context, options) {
10887
10740
  dynamicHash: receiptDraft.dynamicHash ?? null,
10888
10741
  ...receiptDraft.cacheReadTokenCount !== void 0 ? { cacheReadTokenCount: receiptDraft.cacheReadTokenCount } : {},
10889
10742
  ...receiptDraft.cacheWriteTokenCount !== void 0 ? { cacheWriteTokenCount: receiptDraft.cacheWriteTokenCount } : {},
10890
- ...activeRun.heartbeatAt ? { heartbeatAt: heartbeatIso(activeRun.heartbeatAt.current) } : {}
10743
+ ...activeRun.heartbeatAt ? { heartbeatAt: heartbeatIso(activeRun.heartbeatAt) } : {}
10891
10744
  };
10892
10745
  if (receiptDraft.reasoningTokenCount !== void 0) {
10893
10746
  ledgerPatch.reasoningTokenCount = receiptDraft.reasoningTokenCount;
10894
10747
  }
10895
10748
  ledgerRef.update(envelope.id, ledgerPatch);
10896
10749
  const receipt = ledgerRef.recordReceipt(envelope.id, sealRouteDecision(receiptDraft, routeObservation.decision));
10897
- const writeRecordUsable = receipt.safety?.toolTelemetry?.coverage === "complete" && observedRunEffects.writeRecordComplete;
10898
- recordRunWriteTargets(envelope.id, writeRecordUsable ? [...observedRunEffects.mutatedPaths] : null);
10750
+ const toolTelemetryComplete = receipt.safety?.toolTelemetry?.coverage === "complete";
10751
+ const downgrades = observedRunEffects.writeRecordDowngrades.map((entry) => ({
10752
+ reason: entry.reason,
10753
+ tool: entry.tool,
10754
+ toolCallId: entry.toolCallId,
10755
+ runId: envelope.id,
10756
+ stepId: null
10757
+ }));
10758
+ if (!toolTelemetryComplete) {
10759
+ downgrades.push({
10760
+ reason: "incomplete_tool_telemetry",
10761
+ tool: null,
10762
+ toolCallId: null,
10763
+ runId: envelope.id,
10764
+ stepId: null
10765
+ });
10766
+ }
10767
+ recordRunWriteAttribution(envelope.id, {
10768
+ recorded: [...observedRunEffects.mutatedPaths],
10769
+ complete: toolTelemetryComplete && observedRunEffects.writeRecordComplete,
10770
+ downgrades
10771
+ });
10899
10772
  await ledgerRef.persist();
10900
10773
  if (worktreeReceipt?.applied === true && req.taskWorktree !== void 0) {
10901
10774
  try {
@@ -11136,12 +11009,14 @@ function createDispatchBundle(context, options) {
11136
11009
  allowedTools: effectiveTools,
11137
11010
  settings
11138
11011
  });
11012
+ const endpoint = endpointCapacityForTarget(target.target.id);
11139
11013
  return {
11140
11014
  agentId: req.agentId,
11141
11015
  specFingerprint: agentSpecFingerprint(agentSpec),
11142
11016
  targetId: target.target.id,
11143
11017
  wireModelId: target.wireModelId,
11144
11018
  runtimeId: target.runtime.id,
11019
+ ...endpoint !== null ? { endpoint: { key: endpoint.key, label: endpoint.label, limit: endpoint.limit } } : {},
11145
11020
  node: previewNode(req).node,
11146
11021
  thinkingLevel: target.thinkingLevel,
11147
11022
  toolSignature: toolSignature(effectiveTools),
@@ -11483,8 +11358,10 @@ function createDispatchBundle(context, options) {
11483
11358
  });
11484
11359
  return receipt;
11485
11360
  }
11361
+ let journalBridge = null;
11486
11362
  const extension = {
11487
11363
  async start() {
11364
+ if (options?.journalRunEvents === true) journalBridge = attachRunEventJournalBridge(context.bus);
11488
11365
  cleanupDispatchReservations({ startup: true, nowMs: now() });
11489
11366
  ledger = openLedger();
11490
11367
  try {
@@ -11536,6 +11413,8 @@ function createDispatchBundle(context, options) {
11536
11413
  for (const ownerId of ownedReservations) rollbackDispatchReservation(ownerId, now());
11537
11414
  ownedReservations.clear();
11538
11415
  await Promise.allSettled([...assignmentWrites]);
11416
+ journalBridge?.stop();
11417
+ journalBridge = null;
11539
11418
  }
11540
11419
  };
11541
11420
  function emitRunAborted(run, source) {
@@ -11552,19 +11431,41 @@ function createDispatchBundle(context, options) {
11552
11431
  }
11553
11432
  function snapshot() {
11554
11433
  const tickNow = now();
11434
+ const tickMonotonic = monotonicNow();
11555
11435
  const running = [];
11556
11436
  const totals = { ...finalizedTotals };
11557
11437
  const costAmounts = [...finalizedCosts];
11438
+ for (const pending of pendingCapacity.values()) {
11439
+ const startedAt = pending.timing.queuedAt ?? pending.timing.requestedAt ?? new Date(tickNow).toISOString();
11440
+ running.push({
11441
+ runId: pending.identity.runId,
11442
+ agentId: pending.identity.agentId,
11443
+ ...pending.identity.task !== void 0 ? { task: pending.identity.task } : {},
11444
+ ...pending.identity.budget !== void 0 ? { budget: pending.identity.budget } : {},
11445
+ runtimeKind: pending.identity.runtimeKind,
11446
+ outcomePhase: "queued",
11447
+ heartbeat: "n/a",
11448
+ lineage: { parentRunId: null, rootRunId: pending.identity.runId, attempt: 0, depth: 0 },
11449
+ startedAt,
11450
+ elapsedMs: 0,
11451
+ timing: deriveRunPhaseDurations(pending.timing, startedAt, new Date(tickNow).toISOString()),
11452
+ tokens: { input: 0, output: 0, total: 0 },
11453
+ costUsd: 0,
11454
+ costProvenance: "unknown",
11455
+ node: pending.node === null ? null : { ...pending.node }
11456
+ });
11457
+ }
11558
11458
  for (const run of active.values()) {
11559
11459
  let heartbeat = "n/a";
11560
- if (run.heartbeatAt && Number.isFinite(run.heartbeatAt.current)) {
11460
+ if (run.heartbeatAt && Number.isFinite(heartbeatMonotonicAt(run.heartbeatAt))) {
11461
+ const heartbeatMonotonic = heartbeatMonotonicAt(run.heartbeatAt);
11561
11462
  if (run.runtimeKind === "acp-delegation") {
11562
11463
  const stallMs = run.stallTimeoutMs;
11563
11464
  if (stallMs !== null && stallMs > 0) {
11564
- heartbeat = tickNow - run.heartbeatAt.current > stallMs ? "dead" : "alive";
11465
+ heartbeat = tickMonotonic - heartbeatMonotonic > stallMs ? "dead" : "alive";
11565
11466
  }
11566
11467
  } else {
11567
- heartbeat = classifyHeartbeat(run.heartbeatAt.current, tickNow, heartbeatSpec);
11468
+ heartbeat = classifyHeartbeat(heartbeatMonotonic, tickMonotonic, heartbeatSpec);
11568
11469
  }
11569
11470
  }
11570
11471
  const meter = run.meter;
@@ -11678,6 +11579,7 @@ function createDispatchBundle(context, options) {
11678
11579
  routeCandidates,
11679
11580
  reservations: {
11680
11581
  prepare: prepareReservation,
11582
+ release: (ownerId) => releaseDispatchReservation(ownerId, now()),
11681
11583
  rollback: (ownerId) => rollbackDispatchReservation(ownerId, now()),
11682
11584
  rollbackUnconsumed: (ownerId) => rollbackUnconsumedDispatchReservation(ownerId, now()),
11683
11585
  get: getDispatchReservation
@@ -11696,7 +11598,17 @@ function createDispatchBundle(context, options) {
11696
11598
  return ledger.get(runId);
11697
11599
  },
11698
11600
  observedRunWrites(runId) {
11699
- return runWriteTargets.get(runId) ?? null;
11601
+ const attribution = runWriteAttributions.get(runId);
11602
+ return attribution?.complete === true ? [...attribution.recorded] : null;
11603
+ },
11604
+ observedRunWriteAttribution(runId) {
11605
+ const attribution = runWriteAttributions.get(runId);
11606
+ if (attribution === void 0) return null;
11607
+ return {
11608
+ recorded: [...attribution.recorded],
11609
+ complete: attribution.complete,
11610
+ downgrades: attribution.downgrades?.map((entry) => ({ ...entry })) ?? []
11611
+ };
11700
11612
  },
11701
11613
  assignments: {
11702
11614
  get: (id) => assignments.get(id),
@@ -11707,6 +11619,17 @@ function createDispatchBundle(context, options) {
11707
11619
  },
11708
11620
  abort(runId, reason) {
11709
11621
  const rootRunId = assignmentRootFor(runId);
11622
+ const queued = pendingCapacity.get(rootRunId);
11623
+ if (queued !== void 0 && capacityAdmission.cancel(rootRunId)) {
11624
+ persistAssignment(cancelStoredAssignment(rootRunId), `${rootRunId}:cancel-queued`);
11625
+ context.bus.emit(BusChannels.RunAborted, {
11626
+ source: "dispatch_abort",
11627
+ runId: rootRunId,
11628
+ startedAt: null,
11629
+ elapsedMs: null,
11630
+ reason: reason?.detail ?? "operator abort while waiting for an endpoint slot"
11631
+ });
11632
+ }
11710
11633
  const assignment = assignments.get(rootRunId);
11711
11634
  if (assignment?.status === "running") {
11712
11635
  assignments.cancel(assignment.id);
@@ -11807,12 +11730,12 @@ var DispatchManifest = {
11807
11730
 
11808
11731
  // src/domains/dispatch/code-step-store.ts
11809
11732
  init_esm_shims();
11810
- import { join as join14 } from "node:path";
11733
+ import { join as join13 } from "node:path";
11811
11734
  function codeStepDir(rootId) {
11812
- return join14(clioStateDir(), "code-steps", rootId);
11735
+ return join13(clioStateDir(), "code-steps", rootId);
11813
11736
  }
11814
11737
  function codeStepRecordPath(rootId, runId) {
11815
- return join14(codeStepDir(rootId), `${runId}.json`);
11738
+ return join13(codeStepDir(rootId), `${runId}.json`);
11816
11739
  }
11817
11740
  async function writeCodeStepRecord(rootId, record) {
11818
11741
  const path2 = codeStepRecordPath(rootId, record.runId);
@@ -11823,7 +11746,7 @@ async function writeCodeStepRecord(rootId, record) {
11823
11746
 
11824
11747
  // src/domains/dispatch/delegation-plan.ts
11825
11748
  init_esm_shims();
11826
- import { createHash as createHash10 } from "node:crypto";
11749
+ import { createHash as createHash8 } from "node:crypto";
11827
11750
  var DELEGATION_PROPOSAL_BRIEFING_MAX_BYTES = 12e3;
11828
11751
  function buildDelegationProposalBriefing(proposals) {
11829
11752
  const value = proposals.map((proposal) => `PROPOSAL ${proposal.agent}
@@ -11931,7 +11854,7 @@ function validateDelegationPlan(input) {
11931
11854
  }
11932
11855
  }
11933
11856
  const plan = { tasks };
11934
- return { ok: true, plan, hash: createHash10("sha256").update(JSON.stringify(plan)).digest("hex") };
11857
+ return { ok: true, plan, hash: createHash8("sha256").update(JSON.stringify(plan)).digest("hex") };
11935
11858
  }
11936
11859
 
11937
11860
  // src/domains/dispatch/execution-scheduler.ts
@@ -12359,9 +12282,125 @@ function gateFailureLines(output) {
12359
12282
 
12360
12283
  // src/domains/dispatch/fleet-run.ts
12361
12284
  init_esm_shims();
12362
- import { createHash as createHash11 } from "node:crypto";
12363
- import { readFileSync as readFileSync13 } from "node:fs";
12364
- import { join as join15 } from "node:path";
12285
+ import { createHash as createHash9 } from "node:crypto";
12286
+ import { readFileSync as readFileSync12 } from "node:fs";
12287
+ import { join as join14 } from "node:path";
12288
+
12289
+ // src/domains/observability/cost.ts
12290
+ init_esm_shims();
12291
+ function emptyCostAggregate() {
12292
+ return { knownUsd: 0, hasEstimated: false, hasUnknown: false, allKnownFree: false, calls: 0 };
12293
+ }
12294
+ function costWasMeasured(cost) {
12295
+ return cost !== null && cost !== void 0 && cost.calls > 0;
12296
+ }
12297
+ function accumulateCostAmount(aggregate, amount, first) {
12298
+ return {
12299
+ knownUsd: aggregate.knownUsd + (amount.provenance === "unknown" ? 0 : amount.usd),
12300
+ hasEstimated: aggregate.hasEstimated || amount.provenance === "estimated",
12301
+ hasUnknown: aggregate.hasUnknown || amount.provenance === "unknown",
12302
+ allKnownFree: amount.provenance === "known_free" && (first || aggregate.allKnownFree),
12303
+ calls: aggregate.calls + 1
12304
+ };
12305
+ }
12306
+ function aggregateCostAmounts(amounts) {
12307
+ return amounts.reduce(
12308
+ (aggregate, amount, index) => accumulateCostAmount(aggregate, amount, index === 0),
12309
+ emptyCostAggregate()
12310
+ );
12311
+ }
12312
+ function formatUsdAmount(value) {
12313
+ if (!Number.isFinite(value) || value <= 0) return "$0.00";
12314
+ return value < 0.01 ? `$${value.toFixed(4)}` : `$${value.toFixed(2)}`;
12315
+ }
12316
+ function formatCostAggregate(cost) {
12317
+ if (!costWasMeasured(cost)) return null;
12318
+ if (cost.allKnownFree) return "$0.00 local";
12319
+ if (cost.hasUnknown) return cost.knownUsd > 0 ? `${formatUsdAmount(cost.knownUsd)} +?` : null;
12320
+ if (cost.hasEstimated) return `~${formatUsdAmount(cost.knownUsd)} est`;
12321
+ return formatUsdAmount(cost.knownUsd);
12322
+ }
12323
+ var COST_NOT_MEASURED = "not measured";
12324
+ function costAggregateForAmount(usd, provenance) {
12325
+ return aggregateCostAmounts([{ usd, provenance: normalizeCostProvenance(provenance) }]);
12326
+ }
12327
+ function renderCostAggregate(cost) {
12328
+ return formatCostAggregate(cost) ?? COST_NOT_MEASURED;
12329
+ }
12330
+ function renderCostAmount(usd, provenance) {
12331
+ return renderCostAggregate(costAggregateForAmount(usd, provenance));
12332
+ }
12333
+ function emptyBreakdown() {
12334
+ return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoningTokens: 0, totalTokens: 0 };
12335
+ }
12336
+ function createCostTracker() {
12337
+ const log = [];
12338
+ let total = 0;
12339
+ const totals = emptyBreakdown();
12340
+ return {
12341
+ accumulate(providerId, attributedModelId, tokens, usd, breakdown, costProvenance, modelIdFacts, label) {
12342
+ const resolvedUsd = usd ?? 0;
12343
+ const provenance = normalizeCostProvenance(costProvenance);
12344
+ const input = breakdown?.input ?? 0;
12345
+ const output = breakdown?.output ?? 0;
12346
+ const cacheRead = breakdown?.cacheRead ?? 0;
12347
+ const cacheWrite = breakdown?.cacheWrite ?? 0;
12348
+ const reasoningTokens = breakdown?.reasoningTokens ?? 0;
12349
+ const apiCalls = breakdown?.apiCalls;
12350
+ log.push({
12351
+ providerId,
12352
+ attributedModelId,
12353
+ requestedModelIds: [...modelIdFacts?.requestedModelIds ?? [attributedModelId]],
12354
+ responseModelIdObservationCounts: modelIdFacts ? { ...modelIdFacts.responseModelIdObservationCounts } : {
12355
+ reportedCalls: 0,
12356
+ notReportedCalls: 0,
12357
+ notObservedCalls: apiCalls ?? 1,
12358
+ legacyDifferenceOnlyCalls: 0
12359
+ },
12360
+ tokens,
12361
+ usd: resolvedUsd,
12362
+ provenance,
12363
+ input,
12364
+ output,
12365
+ cacheRead,
12366
+ cacheWrite,
12367
+ reasoningTokens,
12368
+ ...apiCalls !== void 0 ? { apiCalls } : {},
12369
+ ...label !== void 0 ? { label } : {}
12370
+ });
12371
+ total += resolvedUsd;
12372
+ totals.input += input;
12373
+ totals.output += output;
12374
+ totals.cacheRead += cacheRead;
12375
+ totals.cacheWrite += cacheWrite;
12376
+ totals.reasoningTokens += reasoningTokens;
12377
+ totals.totalTokens += tokens;
12378
+ return resolvedUsd;
12379
+ },
12380
+ sessionTotal() {
12381
+ return total;
12382
+ },
12383
+ sessionCost() {
12384
+ return aggregateCostAmounts(log.map((entry) => ({ usd: entry.usd, provenance: entry.provenance })));
12385
+ },
12386
+ sessionTokens() {
12387
+ return { ...totals };
12388
+ },
12389
+ entries() {
12390
+ return log;
12391
+ },
12392
+ reset() {
12393
+ log.length = 0;
12394
+ total = 0;
12395
+ totals.input = 0;
12396
+ totals.output = 0;
12397
+ totals.cacheRead = 0;
12398
+ totals.cacheWrite = 0;
12399
+ totals.reasoningTokens = 0;
12400
+ totals.totalTokens = 0;
12401
+ }
12402
+ };
12403
+ }
12365
12404
 
12366
12405
  // src/domains/dispatch/fleet-commit-attribution.ts
12367
12406
  init_esm_shims();
@@ -12453,6 +12492,11 @@ function fleetGateCorrelation(subject, decider) {
12453
12492
  );
12454
12493
  return { agent, target, modelFamily: modelFamily2, runtime, node, independent };
12455
12494
  }
12495
+ function fleetStepIntent(writes) {
12496
+ if (writes === void 0 || writes.length === 0) return null;
12497
+ const built = declaredScopeIntent({ relevantPaths: writes });
12498
+ return built.ok ? built.intent : null;
12499
+ }
12456
12500
  function fleetPlanWaveIndex(plan, stepId) {
12457
12501
  return plan.waves.findIndex((wave) => wave.includes(stepId));
12458
12502
  }
@@ -12490,10 +12534,29 @@ async function executeFleetRun(input) {
12490
12534
  boundaryFor: (stepId) => livePlan.steps.find((step) => step.id === stepId)?.writes,
12491
12535
  recordedWritesFor: (stepId) => {
12492
12536
  const step = livePlan.steps.find((entry) => entry.id === stepId);
12493
- if (step === void 0 || step.kind !== "agent") return null;
12537
+ if (step === void 0) return null;
12538
+ if (step.kind !== "agent") {
12539
+ return {
12540
+ recorded: [],
12541
+ complete: false,
12542
+ downgrades: [
12543
+ {
12544
+ reason: "code_step_untracked",
12545
+ tool: null,
12546
+ toolCallId: null,
12547
+ runId: null,
12548
+ stepId
12549
+ }
12550
+ ]
12551
+ };
12552
+ }
12494
12553
  const receipt = receiptsByStep.get(stepId);
12495
12554
  if (receipt === void 0) return null;
12496
- return dispatch.observedRunWrites?.(receipt.runId) ?? null;
12555
+ if (dispatch.observedRunWriteAttribution !== void 0) {
12556
+ return dispatch.observedRunWriteAttribution(receipt.runId);
12557
+ }
12558
+ const recorded = dispatch.observedRunWrites?.(receipt.runId) ?? null;
12559
+ return recorded === null ? null : { recorded, complete: true, downgrades: [] };
12497
12560
  },
12498
12561
  onVerdict(verdict, path2) {
12499
12562
  if (verdict.detail === null) return;
@@ -12505,7 +12568,7 @@ async function executeFleetRun(input) {
12505
12568
  for (const [stepId, replayedResult] of replayed) {
12506
12569
  try {
12507
12570
  const receipt = JSON.parse(
12508
- readFileSync13(join15(clioStateDir(), "receipts", `${replayedResult.terminalRunId}.json`), "utf8")
12571
+ readFileSync12(join14(clioStateDir(), "receipts", `${replayedResult.terminalRunId}.json`), "utf8")
12509
12572
  );
12510
12573
  receiptsByStep.set(stepId, receipt);
12511
12574
  } catch {
@@ -12526,6 +12589,9 @@ async function executeFleetRun(input) {
12526
12589
  succeeded: true,
12527
12590
  terminalRunId: replayedResult.terminalRunId,
12528
12591
  costUsd: receiptsByStep.get(stepId)?.costUsd ?? 0,
12592
+ // A replay whose receipt no longer exists on disk has no cost claim at
12593
+ // all, which is `unknown` rather than a zero the projection invented.
12594
+ costProvenance: receiptsByStep.get(stepId)?.costProvenance ?? "unknown",
12529
12595
  result: replayedResult
12530
12596
  });
12531
12597
  await fileStepAttempt(replayedResult.terminalRunId);
@@ -12595,11 +12661,13 @@ async function executeFleetRun(input) {
12595
12661
  if (step.planParentId !== void 0 && parentReceipt === void 0) {
12596
12662
  throw new Error(`fleet dynamic step '${step.id}' has no terminal plan-step receipt`);
12597
12663
  }
12664
+ const stepIntent = fleetStepIntent(step.writes);
12598
12665
  const request = {
12599
12666
  agentId: step.agentId,
12600
12667
  executionRole: step.executionRole,
12601
12668
  task: step.task,
12602
12669
  cwd: workspaceRoot,
12670
+ ...stepIntent === null ? {} : { intent: stepIntent },
12603
12671
  predecessorHandoffs: handoffs,
12604
12672
  requestOrigin: "user",
12605
12673
  lineage: {
@@ -12687,11 +12755,11 @@ async function executeFleetRun(input) {
12687
12755
  if (step.gate !== void 0 && succeeded) {
12688
12756
  let gateBytes = "";
12689
12757
  try {
12690
- gateBytes = readFileSync13(join15(workspaceRoot, step.gate.path), "utf8");
12758
+ gateBytes = readFileSync12(join14(workspaceRoot, step.gate.path), "utf8");
12691
12759
  } catch {
12692
12760
  gateBytes = "";
12693
12761
  }
12694
- gatePathHash = createHash11("sha256").update(gateBytes).digest("hex");
12762
+ gatePathHash = createHash9("sha256").update(gateBytes).digest("hex");
12695
12763
  const command = input.commands?.commands.get(step.gate.commandId);
12696
12764
  if (gateBytes.length === 0 || command === void 0) {
12697
12765
  stepSucceeded = false;
@@ -12743,11 +12811,12 @@ async function executeFleetRun(input) {
12743
12811
  succeeded: stepSucceeded,
12744
12812
  terminalRunId: receipt.runId,
12745
12813
  costUsd: receipt.costUsd,
12814
+ costProvenance: receipt.costProvenance,
12746
12815
  receipt,
12747
12816
  ...failureReason !== void 0 ? { failureReason } : {}
12748
12817
  });
12749
12818
  notice(
12750
- `step ${step.id} ${step.agentId}: ${stepSucceeded ? "succeeded" : "failed"}${failureReason !== void 0 ? ` reason=${failureReason}` : ""} assignment=${handle.runId} terminal-run=${receipt.runId} cost=$${receipt.costUsd.toFixed(4)}`
12819
+ `step ${step.id} ${step.agentId}: ${stepSucceeded ? "succeeded" : "failed"}${failureReason !== void 0 ? ` reason=${failureReason}` : ""} assignment=${handle.runId} terminal-run=${receipt.runId} cost=${renderCostAmount(receipt.costUsd, receipt.costProvenance)}`
12751
12820
  );
12752
12821
  return {
12753
12822
  stepId: step.id,
@@ -12806,6 +12875,8 @@ async function executeFleetRun(input) {
12806
12875
  succeeded: outcome.report.passed,
12807
12876
  terminalRunId: outcome.record.runId,
12808
12877
  costUsd: 0,
12878
+ // No model ran, so nothing needed pricing. This zero was observed.
12879
+ costProvenance: "known_free",
12809
12880
  codeStep: outcome.record,
12810
12881
  recordPath
12811
12882
  });
@@ -12864,7 +12935,7 @@ async function executeFleetRun(input) {
12864
12935
  cancel: (assignmentId) => dispatch.abort(assignmentId),
12865
12936
  release: (ownerId) => {
12866
12937
  if (ownerId === NO_WORKER_RESERVATION) return;
12867
- dispatch.reservations?.rollbackUnconsumed(ownerId);
12938
+ dispatch.reservations?.release(ownerId);
12868
12939
  },
12869
12940
  releaseUnconsumed: (ownerId) => {
12870
12941
  if (ownerId === NO_WORKER_RESERVATION) return;
@@ -12929,6 +13000,9 @@ async function executeFleetRun(input) {
12929
13000
  result,
12930
13001
  receipts,
12931
13002
  totalCostUsd: receipts.reduce((sum, receipt) => sum + receipt.costUsd, 0),
13003
+ totalCost: aggregateCostAmounts(
13004
+ receipts.map((receipt) => ({ usd: receipt.costUsd, provenance: receipt.costProvenance }))
13005
+ ),
12932
13006
  requiredStepCount: required.length,
12933
13007
  succeededStepCount,
12934
13008
  resolvedLoopCount: result.loops.length - failedLoops.length,
@@ -12977,6 +13051,36 @@ function attributeEvidenceFailure(facts) {
12977
13051
  return "unknown";
12978
13052
  }
12979
13053
 
13054
+ // src/domains/evidence/findings-markdown.ts
13055
+ init_esm_shims();
13056
+ function renderEvidenceFindingsMarkdown(findings, trustStatus) {
13057
+ const lines = ["# Findings", "", "## Canonical trust", ""];
13058
+ if (trustStatus.runs.length === 0) {
13059
+ lines.push("No linked run trust status.");
13060
+ } else {
13061
+ for (const run of trustStatus.runs) {
13062
+ lines.push(
13063
+ `- run=${run.runId}`,
13064
+ ` tier: ${trustVerdict(run.status)}`,
13065
+ ` summary: ${formatTrustSummary(run.status)}`,
13066
+ ` axes: ${formatTrustAxes(run.status)}`
13067
+ );
13068
+ }
13069
+ }
13070
+ lines.push("", "## Finding records", "");
13071
+ if (findings.length === 0) {
13072
+ lines.push("No findings.");
13073
+ } else {
13074
+ for (const item of findings) {
13075
+ const run = item.runId === null ? "" : ` run=${item.runId}`;
13076
+ lines.push(`- ${item.id} [${item.severity}] ${item.tag}${run}: ${item.message}`);
13077
+ }
13078
+ }
13079
+ lines.push("");
13080
+ return `${lines.join("\n")}
13081
+ `;
13082
+ }
13083
+
12980
13084
  // src/domains/evidence/provenance.ts
12981
13085
  init_esm_shims();
12982
13086
  var PERSONA_HASH_PREFIX_CHARS = 12;
@@ -13126,6 +13230,37 @@ init_esm_shims();
13126
13230
  // src/domains/evidence/types.ts
13127
13231
  init_esm_shims();
13128
13232
  var EVIDENCE_VERSION = 1;
13233
+ var EVIDENCE_TAGS = [
13234
+ "audit-linked",
13235
+ "audit-missing",
13236
+ "best-effort-link",
13237
+ "timeout",
13238
+ "context-overflow",
13239
+ "provider-transient",
13240
+ "missing-dependency",
13241
+ "wrong-runtime",
13242
+ "proxy-validation",
13243
+ "no-validation",
13244
+ "destructive-cleanup",
13245
+ "blocked-tool",
13246
+ "escalation",
13247
+ "external-bypass",
13248
+ "external-approximation",
13249
+ "independent-review",
13250
+ "context-provenance",
13251
+ "completion-evidence",
13252
+ "receipt-integrity",
13253
+ "receipt-retired",
13254
+ "protected-artifact",
13255
+ "tool-loop",
13256
+ "test-failure",
13257
+ "build-failure",
13258
+ "cwd-missing",
13259
+ "session-linked",
13260
+ "session-missing",
13261
+ "auth-failure",
13262
+ "unknown"
13263
+ ];
13129
13264
  var FAILURE_CAUSE_TAG_ORDER = [
13130
13265
  "timeout",
13131
13266
  "auth-failure",
@@ -13148,7 +13283,6 @@ function buildEvidenceTrustStatusFile(input) {
13148
13283
  evidenceId: input.evidenceId,
13149
13284
  source,
13150
13285
  gateDecisions: input.gateDecisions,
13151
- auditRows: input.auditRows,
13152
13286
  validationEvidence: input.validationEvidence?.get(source.envelope.id) ?? []
13153
13287
  })
13154
13288
  }))
@@ -13156,7 +13290,6 @@ function buildEvidenceTrustStatusFile(input) {
13156
13290
  }
13157
13291
  function composeEvidenceRunTrustStatus(input) {
13158
13292
  const inspection = inspectRunReceiptTrustStatus(input.source.receipt, input.source.envelope);
13159
- const receiptRejected = inspection.status.artifactIntegrity.state === "failed";
13160
13293
  let status = inspection.status;
13161
13294
  const grounded = input.validationEvidence.filter((artifact) => isTrustStatusIdentifier(artifact.id));
13162
13295
  if (grounded.length > 0 && (status.validationGrounding.state === "absent" || status.validationGrounding.state === "unknown")) {
@@ -13181,21 +13314,6 @@ function composeEvidenceRunTrustStatus(input) {
13181
13314
  independentReview: adaptGateDecisionReviewStatus(gate, input.source.envelope.id, verification)
13182
13315
  });
13183
13316
  }
13184
- const finish = latestFinishContractForRun(input.auditRows, input.source.envelope.id);
13185
- if (finish !== null) {
13186
- const completion = adaptFinishContractCompletionStatus(finish.assessment, {
13187
- sourceId: finish.sourceId,
13188
- artifacts: finish.artifacts
13189
- });
13190
- status = composeTrustStatus(status, {
13191
- completionEvidence: receiptRejected && completion.state === "evidenced" ? {
13192
- state: "unknown",
13193
- source: { kind: "finish_contract", id: finish.sourceId },
13194
- authority: { kind: "clio", id: "finish-contract" },
13195
- artifacts: finish.artifacts
13196
- } : completion
13197
- });
13198
- }
13199
13317
  return status;
13200
13318
  }
13201
13319
  function latestGateDecisionForRun(decisions, runId) {
@@ -13203,60 +13321,11 @@ function latestGateDecisionForRun(decisions, runId) {
13203
13321
  (left, right) => compareCodepoints(left.createdAt, right.createdAt) || left.cycle - right.cycle || compareCodepoints(left.id, right.id)
13204
13322
  ).at(-1) ?? null;
13205
13323
  }
13206
- function latestFinishContractForRun(rows, runId) {
13207
- const candidates = rows.filter((row) => row.auditKind === "completion_contract" && row.runId === runId && row.confidence === "exact").flatMap((row) => {
13208
- const assessment = finishContractAssessmentFromAudit(row.row);
13209
- if (assessment === null) return [];
13210
- const correlationId = readOptionalString(row.row.correlationId) ?? `${runId}:completion-contract`;
13211
- if (!isTrustStatusIdentifier(correlationId)) return [];
13212
- const turnId = readOptionalString(row.row.turnId);
13213
- const artifacts = [
13214
- { kind: "finish_contract_evidence", id: correlationId },
13215
- ...turnId === null || !isTrustStatusIdentifier(turnId) ? [] : [{ kind: "session_entry", id: turnId }]
13216
- ];
13217
- return [{ sourceId: correlationId, assessment, artifacts, timestamp: row.ts ?? "" }];
13218
- }).sort(
13219
- (left, right) => compareCodepoints(left.timestamp, right.timestamp) || compareCodepoints(left.sourceId, right.sourceId)
13220
- );
13221
- const latest2 = candidates.at(-1);
13222
- return latest2 === void 0 ? null : { sourceId: latest2.sourceId, assessment: latest2.assessment, artifacts: latest2.artifacts };
13223
- }
13224
- function finishContractAssessmentFromAudit(row) {
13225
- const reason = readOptionalString(row.reason);
13226
- const decision = readOptionalString(row.decision);
13227
- const mutatedPaths = Array.isArray(row.mutatedPaths) ? row.mutatedPaths.filter((entry) => typeof entry === "string") : [];
13228
- const turnId = readOptionalString(row.turnId);
13229
- const evidenceKinds = Array.isArray(row.evidenceKinds) ? row.evidenceKinds.filter(isFinishContractEvidenceKind) : [];
13230
- const evidence = evidenceKinds.map((kind) => ({
13231
- kind,
13232
- summary: "recorded by the finish contract",
13233
- ...turnId === null ? {} : { turnId }
13234
- }));
13235
- if (decision === "ok" && reason === "no_mutation") {
13236
- return { kind: "ok", reason, evidence: [], mutatedPaths };
13237
- }
13238
- if (decision === "ok" && reason === "validation_evidence") {
13239
- return { kind: "ok", reason, evidence, mutatedPaths };
13240
- }
13241
- if (decision === "ok" && reason === "explicit_limitation") {
13242
- return { kind: "ok", reason, evidence: [], mutatedPaths };
13243
- }
13244
- if (decision === "engage" && reason === "unvalidated_mutation") {
13245
- return { kind: "engage", reason, message: "finish contract engaged", evidence: [], mutatedPaths };
13246
- }
13247
- return null;
13248
- }
13249
- function isFinishContractEvidenceKind(value) {
13250
- return value === "validation_command" || value === "protected_artifact" || value === "dispatch_receipt";
13251
- }
13252
- function readOptionalString(value) {
13253
- return typeof value === "string" && value.trim().length > 0 ? value : null;
13254
- }
13255
13324
 
13256
13325
  // src/domains/evidence/store.ts
13257
13326
  init_esm_shims();
13258
13327
  import { readdir, readFile } from "node:fs/promises";
13259
- import { join as join16 } from "node:path";
13328
+ import { join as join15 } from "node:path";
13260
13329
  var EVIDENCE_FILES = [
13261
13330
  "overview.json",
13262
13331
  "transcript.md",
@@ -13272,11 +13341,11 @@ var EVIDENCE_FILES = [
13272
13341
  "findings.md"
13273
13342
  ];
13274
13343
  function evidenceRoot(dataDir) {
13275
- return join16(dataDir, "evidence");
13344
+ return join15(dataDir, "evidence");
13276
13345
  }
13277
13346
  function evidenceDirectory(dataDir, evidenceId) {
13278
13347
  assertSafeId(evidenceId, "evidence");
13279
- return join16(evidenceRoot(dataDir), evidenceId);
13348
+ return join15(evidenceRoot(dataDir), evidenceId);
13280
13349
  }
13281
13350
  var EvidenceNotFoundError = class extends Error {
13282
13351
  constructor(evidenceId) {
@@ -13292,7 +13361,7 @@ function isMissingFile(error) {
13292
13361
  async function loadEvidenceOverview(dataDir, evidenceId) {
13293
13362
  let raw;
13294
13363
  try {
13295
- raw = await readFile(join16(evidenceDirectory(dataDir, evidenceId), "overview.json"), "utf8");
13364
+ raw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "overview.json"), "utf8");
13296
13365
  } catch (error) {
13297
13366
  if (isMissingFile(error)) throw new EvidenceNotFoundError(evidenceId);
13298
13367
  throw error;
@@ -13304,7 +13373,7 @@ async function inspectEvidence(dataDir, evidenceId) {
13304
13373
  const overview = await loadEvidenceOverview(dataDir, evidenceId);
13305
13374
  let findingsRaw;
13306
13375
  try {
13307
- findingsRaw = await readFile(join16(evidenceDirectory(dataDir, evidenceId), "findings.json"), "utf8");
13376
+ findingsRaw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "findings.json"), "utf8");
13308
13377
  } catch (error) {
13309
13378
  if (isMissingFile(error)) throw new Error(`evidence artifact ${evidenceId} is missing findings.json`);
13310
13379
  throw error;
@@ -13316,7 +13385,7 @@ async function inspectEvidence(dataDir, evidenceId) {
13316
13385
  async function loadEvidenceTrustStatus(dataDir, evidenceId) {
13317
13386
  let raw;
13318
13387
  try {
13319
- raw = await readFile(join16(evidenceDirectory(dataDir, evidenceId), "trust-status.json"), "utf8");
13388
+ raw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "trust-status.json"), "utf8");
13320
13389
  } catch (error) {
13321
13390
  if (isMissingFile(error)) {
13322
13391
  return { version: 1, evidenceId, projection: "historical_format", runs: [] };
@@ -13349,7 +13418,7 @@ async function loadEvidenceTrustStatus(dataDir, evidenceId) {
13349
13418
  async function loadEvidenceRunProvenance(dataDir, evidenceId) {
13350
13419
  let raw;
13351
13420
  try {
13352
- raw = await readFile(join16(evidenceDirectory(dataDir, evidenceId), "receipt.json"), "utf8");
13421
+ raw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "receipt.json"), "utf8");
13353
13422
  } catch (error) {
13354
13423
  const err = error;
13355
13424
  if (err.code === "ENOENT") return [];
@@ -13403,6 +13472,7 @@ function parseOverview(value, source) {
13403
13472
  const totals = readTotals(value.totals, `${source}.totals`);
13404
13473
  const tags = readStringArray(value, source, "tags");
13405
13474
  const files = readStringArray(value, source, "files");
13475
+ const redactionCount = typeof value.redactionCount === "number" && Number.isFinite(value.redactionCount) ? value.redactionCount : void 0;
13406
13476
  return {
13407
13477
  version: 1,
13408
13478
  evidenceId,
@@ -13421,7 +13491,8 @@ function parseOverview(value, source) {
13421
13491
  modelIds,
13422
13492
  totals,
13423
13493
  tags,
13424
- files
13494
+ files,
13495
+ ...redactionCount === void 0 ? {} : { redactionCount }
13425
13496
  };
13426
13497
  }
13427
13498
  function parseFindingsFile(value, source) {
@@ -13564,7 +13635,6 @@ async function buildEvidence(options) {
13564
13635
  evidenceId,
13565
13636
  runSources,
13566
13637
  gateDecisions: gateDecisions.decisions,
13567
- auditRows: auditLinks.rows,
13568
13638
  validationEvidence
13569
13639
  });
13570
13640
  const findings = buildFindings(runSources, trustStatusRaw, sessionLinks, auditLinks, protectedArtifactsRaw);
@@ -13887,15 +13957,15 @@ function validationToolCallSummary(toolName, args) {
13887
13957
  const parsed = parseMaybeJson(args);
13888
13958
  const argRecord = isRecord11(parsed) ? parsed : null;
13889
13959
  if (toolName === "bash") {
13890
- const command = readOptionalString2(argRecord?.command);
13960
+ const command = readOptionalString(argRecord?.command);
13891
13961
  if (command === null) return null;
13892
13962
  const detected = detectValidationCommand(command);
13893
13963
  return detected.kind === "validation" ? detected.matched : null;
13894
13964
  }
13895
13965
  if (toolName === "verify") {
13896
- const check = readOptionalString2(argRecord?.check);
13966
+ const check = readOptionalString(argRecord?.check);
13897
13967
  if (check === "frontend") {
13898
- const target = readOptionalString2(argRecord?.path) ?? "artifact";
13968
+ const target = readOptionalString(argRecord?.path) ?? "artifact";
13899
13969
  return `verify frontend ${target}`;
13900
13970
  }
13901
13971
  if (check === null) return null;
@@ -13922,22 +13992,22 @@ function finding(index, severity, tag, runId, message) {
13922
13992
  }
13923
13993
  async function writeEvidenceFiles(directory, overview, runSources, findings, sessionLinks, auditLinks, toolEventRows, gateDecisions, trustStatus, protectedArtifacts, transcript) {
13924
13994
  await mkdir(directory, { recursive: true });
13925
- await writeJson(join17(directory, "overview.json"), overview);
13995
+ await writeJson(join16(directory, "overview.json"), overview);
13926
13996
  await writeFile(
13927
- join17(directory, "transcript.md"),
13997
+ join16(directory, "transcript.md"),
13928
13998
  transcript ?? renderTranscript(overview, runSources, sessionLinks, trustStatus),
13929
13999
  "utf8"
13930
14000
  );
13931
- await writeJsonl(join17(directory, "trace.raw.jsonl"), rawTraceRows(runSources));
13932
- await writeJsonl(join17(directory, "trace.cleaned.jsonl"), cleanedTraceRows(runSources, findings, toolEventRows));
13933
- await writeJsonl(join17(directory, "tool-events.jsonl"), toolEventRows);
13934
- await writeJsonl(join17(directory, "audit-linked.jsonl"), auditLinks.rows);
13935
- await writeJson(join17(directory, "receipt.json"), receiptsFile(runSources));
13936
- await writeJson(join17(directory, "gate-decisions.json"), gateDecisions);
13937
- await writeJson(join17(directory, "trust-status.json"), trustStatus);
13938
- await writeJson(join17(directory, "protected-artifacts.json"), protectedArtifacts);
13939
- await writeJson(join17(directory, "findings.json"), findingsFile(overview.evidenceId, [...findings]));
13940
- await writeFile(join17(directory, "findings.md"), renderFindings(findings), "utf8");
14001
+ await writeJsonl(join16(directory, "trace.raw.jsonl"), rawTraceRows(runSources));
14002
+ await writeJsonl(join16(directory, "trace.cleaned.jsonl"), cleanedTraceRows(runSources, findings, toolEventRows));
14003
+ await writeJsonl(join16(directory, "tool-events.jsonl"), toolEventRows);
14004
+ await writeJsonl(join16(directory, "audit-linked.jsonl"), auditLinks.rows);
14005
+ await writeJson(join16(directory, "receipt.json"), receiptsFile(runSources));
14006
+ await writeJson(join16(directory, "gate-decisions.json"), gateDecisions);
14007
+ await writeJson(join16(directory, "trust-status.json"), trustStatus);
14008
+ await writeJson(join16(directory, "protected-artifacts.json"), protectedArtifacts);
14009
+ await writeJson(join16(directory, "findings.json"), findingsFile(overview.evidenceId, [...findings]));
14010
+ await writeFile(join16(directory, "findings.md"), renderEvidenceFindingsMarkdown(findings, trustStatus), "utf8");
13941
14011
  }
13942
14012
  function rawTraceRows(runSources) {
13943
14013
  const rows = [];
@@ -14082,12 +14152,12 @@ function attributionWindows(ledger, runSources, sessionIds) {
14082
14152
  const linkedSessions = new Set(sessionIds);
14083
14153
  for (const row of ledger.rows) {
14084
14154
  if (!isRecord11(row)) continue;
14085
- const id = readOptionalString2(row.id);
14086
- const startedAt = readOptionalString2(row.startedAt);
14087
- const sessionId = readOptionalString2(row.sessionId);
14155
+ const id = readOptionalString(row.id);
14156
+ const startedAt = readOptionalString(row.startedAt);
14157
+ const sessionId = readOptionalString(row.sessionId);
14088
14158
  if (id === null || startedAt === null || sessionId === null) continue;
14089
14159
  if (windows.has(id) || !linkedSessions.has(sessionId)) continue;
14090
- windows.set(id, { runId: id, startedAt, endedAt: readOptionalString2(row.endedAt) });
14160
+ windows.set(id, { runId: id, startedAt, endedAt: readOptionalString(row.endedAt) });
14091
14161
  }
14092
14162
  return [...windows.values()].sort((left, right) => compareCodepoints(left.runId, right.runId));
14093
14163
  }
@@ -14202,16 +14272,16 @@ function extractSessionToolCall(entry, linked) {
14202
14272
  const payload = payloadObject(entry.payload);
14203
14273
  const block = firstContentBlock(entry.payload, "toolCall");
14204
14274
  const fn = payloadObject(payload?.function);
14205
- const id = readOptionalString2(payload?.id) ?? readOptionalString2(payload?.toolCallId) ?? readOptionalString2(payload?.tool_call_id) ?? readOptionalString2(block?.id) ?? entry.turnId;
14206
- const tool = readOptionalString2(payload?.name) ?? readOptionalString2(payload?.toolName) ?? readOptionalString2(payload?.tool) ?? readOptionalString2(fn?.name) ?? readOptionalString2(block?.name) ?? "tool";
14275
+ const id = readOptionalString(payload?.id) ?? readOptionalString(payload?.toolCallId) ?? readOptionalString(payload?.tool_call_id) ?? readOptionalString(block?.id) ?? entry.turnId;
14276
+ const tool = readOptionalString(payload?.name) ?? readOptionalString(payload?.toolName) ?? readOptionalString(payload?.tool) ?? readOptionalString(fn?.name) ?? readOptionalString(block?.name) ?? "tool";
14207
14277
  const args = payload?.arguments ?? payload?.args ?? payload?.input ?? parseMaybeJson(fn?.arguments) ?? block?.arguments ?? block?.args ?? void 0;
14208
14278
  return { id, tool, args, timestamp: entry.timestamp, link: linked.link, sessionId: linked.sessionId };
14209
14279
  }
14210
14280
  function extractSessionToolResult(entry, linked) {
14211
14281
  const payload = payloadObject(entry.payload);
14212
14282
  const contentText = extractTextFromPayload(entry.payload);
14213
- const id = readOptionalString2(payload?.toolCallId) ?? readOptionalString2(payload?.tool_call_id) ?? readOptionalString2(payload?.id) ?? null;
14214
- const tool = readOptionalString2(payload?.toolName) ?? readOptionalString2(payload?.name) ?? readOptionalString2(payload?.tool) ?? "tool";
14283
+ const id = readOptionalString(payload?.toolCallId) ?? readOptionalString(payload?.tool_call_id) ?? readOptionalString(payload?.id) ?? null;
14284
+ const tool = readOptionalString(payload?.toolName) ?? readOptionalString(payload?.name) ?? readOptionalString(payload?.tool) ?? "tool";
14215
14285
  const result = payload?.result ?? payload?.output ?? payload?.out ?? payload?.content ?? (contentText.length > 0 ? contentText : entry.payload);
14216
14286
  return {
14217
14287
  id,
@@ -14238,12 +14308,12 @@ async function linkAuditRows(stateDir, source, runSources, sessionLinks) {
14238
14308
  runSources.map((item) => [item.envelope.id, item.envelope.sessionId ?? item.receipt?.sessionId ?? null])
14239
14309
  );
14240
14310
  for (const audit of auditRows.rows) {
14241
- const directRunId = readOptionalString2(audit.row.runId);
14311
+ const directRunId = readOptionalString(audit.row.runId);
14242
14312
  if (directRunId !== null && runIds.has(directRunId)) {
14243
14313
  rows.push(
14244
14314
  auditLinkedRow(audit, {
14245
14315
  runId: directRunId,
14246
- sessionId: readOptionalString2(audit.row.sessionId) ?? runSessionIds.get(directRunId) ?? null,
14316
+ sessionId: readOptionalString(audit.row.sessionId) ?? runSessionIds.get(directRunId) ?? null,
14247
14317
  linkKind: "run-id",
14248
14318
  confidence: "exact",
14249
14319
  reasons: ["audit runId matched run ledger"]
@@ -14251,7 +14321,7 @@ async function linkAuditRows(stateDir, source, runSources, sessionLinks) {
14251
14321
  );
14252
14322
  continue;
14253
14323
  }
14254
- const directSessionId = readOptionalString2(audit.row.sessionId);
14324
+ const directSessionId = readOptionalString(audit.row.sessionId);
14255
14325
  if (directSessionId !== null && sessionIds.has(directSessionId)) {
14256
14326
  rows.push(
14257
14327
  auditLinkedRow(audit, {
@@ -14286,7 +14356,7 @@ function auditLinkedRow(audit, fields) {
14286
14356
  }
14287
14357
  function bestEffortAuditLink(audit, source, runSources, sessionIds) {
14288
14358
  if (audit.auditKind !== "tool_call") return null;
14289
- const tool = readOptionalString2(audit.row.tool);
14359
+ const tool = readOptionalString(audit.row.tool);
14290
14360
  if (tool === null || audit.ts === null) return null;
14291
14361
  const candidates = runSources.filter((item) => {
14292
14362
  if (!timestampInRunWindow(audit.ts ?? "", item.envelope)) return false;
@@ -14350,9 +14420,9 @@ function auditToolEvents(rows) {
14350
14420
  const events = [];
14351
14421
  for (const row of rows) {
14352
14422
  if (row.auditKind !== "tool_call") continue;
14353
- const tool = readOptionalString2(row.row.tool);
14423
+ const tool = readOptionalString(row.row.tool);
14354
14424
  if (tool === null) continue;
14355
- const decision = readOptionalString2(row.row.decision);
14425
+ const decision = readOptionalString(row.row.decision);
14356
14426
  if (decision === "classified") continue;
14357
14427
  const event = {
14358
14428
  source: "audit-row",
@@ -14369,7 +14439,7 @@ function auditToolEvents(rows) {
14369
14439
  };
14370
14440
  if (row.ts !== null) event.timestamp = row.ts;
14371
14441
  if (decision !== null) event.decision = decision;
14372
- const actionClass = readOptionalString2(row.row.actionClass);
14442
+ const actionClass = readOptionalString(row.row.actionClass);
14373
14443
  if (actionClass !== null) event.actionClass = actionClass;
14374
14444
  events.push(event);
14375
14445
  }
@@ -14380,8 +14450,8 @@ function compareAuditLinkedRows(a, b) {
14380
14450
  if (byTs !== 0) return byTs;
14381
14451
  const byKind = compareCodepoints(a.auditKind, b.auditKind);
14382
14452
  if (byKind !== 0) return byKind;
14383
- const aCorrelation = readOptionalString2(a.row.correlationId) ?? "";
14384
- const bCorrelation = readOptionalString2(b.row.correlationId) ?? "";
14453
+ const aCorrelation = readOptionalString(a.row.correlationId) ?? "";
14454
+ const bCorrelation = readOptionalString(b.row.correlationId) ?? "";
14385
14455
  if (aCorrelation !== bCorrelation) return compareCodepoints(aCorrelation, bCorrelation);
14386
14456
  return compareCodepoints(JSON.stringify(a.row), JSON.stringify(b.row));
14387
14457
  }
@@ -14614,19 +14684,8 @@ function axisFindings(offset, source, status) {
14614
14684
  }
14615
14685
  return out;
14616
14686
  }
14617
- function renderFindings(findings) {
14618
- if (findings.length === 0) return "# Findings\n\nNo findings.\n";
14619
- const lines = ["# Findings", ""];
14620
- for (const item of findings) {
14621
- const run = item.runId === null ? "" : ` run=${item.runId}`;
14622
- lines.push(`- ${item.id} [${item.severity}] ${item.tag}${run}: ${item.message}`);
14623
- }
14624
- lines.push("");
14625
- return `${lines.join("\n")}
14626
- `;
14627
- }
14628
14687
  async function readRunLedger(stateDir) {
14629
- const target = join17(stateDir, "runs.json");
14688
+ const target = join16(stateDir, "runs.json");
14630
14689
  let raw;
14631
14690
  try {
14632
14691
  raw = await readFile2(target, "utf8");
@@ -14647,7 +14706,7 @@ function selectRunEnvelopes(ledger, source) {
14647
14706
  });
14648
14707
  }
14649
14708
  async function readReceipt(stateDir, envelope) {
14650
- const receiptPath = envelope.receiptPath ?? join17(stateDir, "receipts", `${envelope.id}.json`);
14709
+ const receiptPath = envelope.receiptPath ?? join16(stateDir, "receipts", `${envelope.id}.json`);
14651
14710
  let raw;
14652
14711
  try {
14653
14712
  raw = await readFile2(receiptPath, "utf8");
@@ -14713,7 +14772,7 @@ function parseRunReceipt(value, source) {
14713
14772
  const integrity = value.integrity;
14714
14773
  if (!isRecord11(integrity)) throw new Error(`${source}.integrity: expected object`);
14715
14774
  const reasoningTokenCount = readOptionalNumber2(value, source, "reasoningTokenCount");
14716
- const failureMessage = readOptionalString2(value.failureMessage);
14775
+ const failureMessage = readOptionalString(value.failureMessage);
14717
14776
  return {
14718
14777
  ...value,
14719
14778
  runId: readString2(value, source, "runId"),
@@ -14805,7 +14864,7 @@ function readNullableNumber(record, source, field) {
14805
14864
  throw new Error(`${source}.${field}: expected number or null`);
14806
14865
  return value;
14807
14866
  }
14808
- function readOptionalString2(value) {
14867
+ function readOptionalString(value) {
14809
14868
  return typeof value === "string" && value.length > 0 ? value : null;
14810
14869
  }
14811
14870
  function parseJson2(raw, source) {
@@ -14936,7 +14995,7 @@ function sanitizeEvidenceId(value) {
14936
14995
  // src/domains/evidence/eval.ts
14937
14996
  init_esm_shims();
14938
14997
  import { mkdir as mkdir2, readdir as readdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
14939
- import { join as join18 } from "node:path";
14998
+ import { join as join17 } from "node:path";
14940
14999
 
14941
15000
  // src/domains/eval/index.ts
14942
15001
  init_esm_shims();
@@ -14947,9 +15006,6 @@ init_esm_shims();
14947
15006
  // src/domains/eval/report.ts
14948
15007
  init_esm_shims();
14949
15008
 
14950
- // src/domains/eval/run-compare.ts
14951
- init_esm_shims();
14952
-
14953
15009
  // src/domains/eval/runner.ts
14954
15010
  init_esm_shims();
14955
15011
  function summarizeEvalResults(records) {
@@ -15018,8 +15074,7 @@ async function buildEvalEvidence(options) {
15018
15074
  const trustStatus = buildEvidenceTrustStatusFile({
15019
15075
  evidenceId,
15020
15076
  runSources: linkedRuns.runSources,
15021
- gateDecisions: gateDecisions.decisions,
15022
- auditRows: linkedRuns.auditRows
15077
+ gateDecisions: gateDecisions.decisions
15023
15078
  });
15024
15079
  await writeEvalEvidenceFiles(
15025
15080
  directory,
@@ -15141,19 +15196,19 @@ async function writeEvalEvidenceFiles(directory, artifact, overview, findings, t
15141
15196
  };
15142
15197
  const redactedArtifact = redactArtifactForStorage(artifact);
15143
15198
  await mkdir2(directory, { recursive: true });
15144
- await writeJson2(join18(directory, "overview.json"), overview);
15145
- await writeFile2(join18(directory, "transcript.md"), renderEvalTranscript(redactedArtifact, overview), "utf8");
15146
- await writeJsonl2(join18(directory, "trace.raw.jsonl"), rawEvalTraceRows(redactedArtifact));
15147
- await writeJsonl2(join18(directory, "trace.cleaned.jsonl"), cleanedEvalTraceRows(redactedArtifact, findings));
15148
- await writeJsonl2(join18(directory, "tool-events.jsonl"), redactArtifactForStorage(toolEventRows));
15149
- await writeJsonl2(join18(directory, "audit-linked.jsonl"), linkedRuns.auditRows);
15150
- await writeJson2(join18(directory, "receipt.json"), receiptsFile2);
15151
- await writeJson2(join18(directory, "gate-decisions.json"), gateDecisions);
15152
- await writeJson2(join18(directory, "trust-status.json"), trustStatus);
15153
- await writeJson2(join18(directory, "protected-artifacts.json"), emptyProtected);
15154
- await writeJson2(join18(directory, "eval-result.json"), redactedArtifact);
15155
- await writeJson2(join18(directory, "findings.json"), findingsFile(overview.evidenceId, [...findings]));
15156
- await writeFile2(join18(directory, "findings.md"), renderFindings2(findings), "utf8");
15199
+ await writeJson2(join17(directory, "overview.json"), overview);
15200
+ await writeFile2(join17(directory, "transcript.md"), renderEvalTranscript(redactedArtifact, overview), "utf8");
15201
+ await writeJsonl2(join17(directory, "trace.raw.jsonl"), rawEvalTraceRows(redactedArtifact));
15202
+ await writeJsonl2(join17(directory, "trace.cleaned.jsonl"), cleanedEvalTraceRows(redactedArtifact, findings));
15203
+ await writeJsonl2(join17(directory, "tool-events.jsonl"), redactArtifactForStorage(toolEventRows));
15204
+ await writeJsonl2(join17(directory, "audit-linked.jsonl"), linkedRuns.auditRows);
15205
+ await writeJson2(join17(directory, "receipt.json"), receiptsFile2);
15206
+ await writeJson2(join17(directory, "gate-decisions.json"), gateDecisions);
15207
+ await writeJson2(join17(directory, "trust-status.json"), trustStatus);
15208
+ await writeJson2(join17(directory, "protected-artifacts.json"), emptyProtected);
15209
+ await writeJson2(join17(directory, "eval-result.json"), redactedArtifact);
15210
+ await writeJson2(join17(directory, "findings.json"), findingsFile(overview.evidenceId, [...findings]));
15211
+ await writeFile2(join17(directory, "findings.md"), renderEvidenceFindingsMarkdown(findings, trustStatus), "utf8");
15157
15212
  }
15158
15213
  function rawEvalTraceRows(artifact) {
15159
15214
  return artifact.results.map((result) => ({
@@ -15243,16 +15298,6 @@ function renderEvalTranscript(artifact, overview) {
15243
15298
  return `${lines.join("\n")}
15244
15299
  `;
15245
15300
  }
15246
- function renderFindings2(findings) {
15247
- if (findings.length === 0) return "No findings.\n";
15248
- const lines = ["# Findings", ""];
15249
- for (const finding2 of findings) {
15250
- lines.push(`- ${finding2.id} [${finding2.severity}] ${finding2.tag}: ${finding2.message}`);
15251
- }
15252
- lines.push("");
15253
- return `${lines.join("\n")}
15254
- `;
15255
- }
15256
15301
  async function writeJson2(path2, value) {
15257
15302
  await writeFile2(path2, `${JSON.stringify(value, null, 2)}
15258
15303
  `, "utf8");
@@ -15304,7 +15349,7 @@ async function linkEvalRuns(stateDir, artifact) {
15304
15349
  }
15305
15350
  async function readRunLedger2(stateDir) {
15306
15351
  try {
15307
- const raw = await readFile3(join18(stateDir, "runs.json"), "utf8");
15352
+ const raw = await readFile3(join17(stateDir, "runs.json"), "utf8");
15308
15353
  const parsed = JSON.parse(raw);
15309
15354
  return Array.isArray(parsed) ? parsed.filter(isRecord12) : [];
15310
15355
  } catch {
@@ -15315,7 +15360,7 @@ function evalRunMatches(artifact, envelope) {
15315
15360
  return artifact.results.some((result) => result.runId === envelope.id);
15316
15361
  }
15317
15362
  async function readReceiptForRun(stateDir, envelope) {
15318
- const path2 = envelope.receiptPath ?? join18(stateDir, "receipts", `${envelope.id}.json`);
15363
+ const path2 = envelope.receiptPath ?? join17(stateDir, "receipts", `${envelope.id}.json`);
15319
15364
  try {
15320
15365
  const parsed = JSON.parse(await readFile3(path2, "utf8"));
15321
15366
  return isRecord12(parsed) ? parsed : null;
@@ -15344,7 +15389,7 @@ async function countSessionEntries(stateDir, sessionIds) {
15344
15389
  return count;
15345
15390
  }
15346
15391
  async function findSessionLedgerPath(stateDir, sessionId) {
15347
- const root = join18(stateDir, "sessions");
15392
+ const root = join17(stateDir, "sessions");
15348
15393
  let cwdHashes;
15349
15394
  try {
15350
15395
  cwdHashes = await readdir2(root);
@@ -15352,7 +15397,7 @@ async function findSessionLedgerPath(stateDir, sessionId) {
15352
15397
  return null;
15353
15398
  }
15354
15399
  for (const cwdHash of cwdHashes) {
15355
- const path2 = join18(root, cwdHash, sessionId, "current.jsonl");
15400
+ const path2 = join17(root, cwdHash, sessionId, "current.jsonl");
15356
15401
  try {
15357
15402
  await readFile3(path2, "utf8");
15358
15403
  return path2;
@@ -15362,7 +15407,7 @@ async function findSessionLedgerPath(stateDir, sessionId) {
15362
15407
  return null;
15363
15408
  }
15364
15409
  async function linkedEvalAuditRows(stateDir, runIds, artifact) {
15365
- const root = join18(stateDir, "audit");
15410
+ const root = join17(stateDir, "audit");
15366
15411
  let files;
15367
15412
  try {
15368
15413
  files = await readdir2(root);
@@ -15371,7 +15416,7 @@ async function linkedEvalAuditRows(stateDir, runIds, artifact) {
15371
15416
  }
15372
15417
  const rows = [];
15373
15418
  for (const file of files.filter((name) => name.endsWith(".jsonl")).sort(compareCodepoints)) {
15374
- const raw = await readFile3(join18(root, file), "utf8").catch(() => "");
15419
+ const raw = await readFile3(join17(root, file), "utf8").catch(() => "");
15375
15420
  const lines = raw.split("\n");
15376
15421
  for (let index = 0; index < lines.length; index += 1) {
15377
15422
  const line = lines[index];
@@ -15464,30 +15509,30 @@ init_esm_shims();
15464
15509
  function lower(value) {
15465
15510
  return (value ?? "").toLowerCase();
15466
15511
  }
15467
- function canonicalJson4(value) {
15512
+ function canonicalJson3(value) {
15468
15513
  if (value === null) return "null";
15469
15514
  if (typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
15470
15515
  if (typeof value === "number") {
15471
15516
  if (!Number.isFinite(value)) throw new Error("response schema digest requires finite numbers");
15472
15517
  return JSON.stringify(value);
15473
15518
  }
15474
- if (Array.isArray(value)) return `[${value.map(canonicalJson4).join(",")}]`;
15519
+ if (Array.isArray(value)) return `[${value.map(canonicalJson3).join(",")}]`;
15475
15520
  if (typeof value === "object") {
15476
15521
  const record = value;
15477
15522
  return `{${Object.keys(record).sort().map((key) => {
15478
15523
  if (record[key] === void 0) throw new Error("response schema digest cannot contain undefined");
15479
- return `${JSON.stringify(key)}:${canonicalJson4(record[key])}`;
15524
+ return `${JSON.stringify(key)}:${canonicalJson3(record[key])}`;
15480
15525
  }).join(",")}}`;
15481
15526
  }
15482
15527
  throw new Error(`response schema digest cannot represent ${typeof value}`);
15483
15528
  }
15484
15529
  function canonicalResponseSchemaDigest(schema) {
15485
- return createHash12("sha256").update(canonicalJson4(schema), "utf8").digest("hex");
15530
+ return createHash10("sha256").update(canonicalJson3(schema), "utf8").digest("hex");
15486
15531
  }
15487
15532
  function typedValidationFactsFromToolStats(toolStats) {
15488
15533
  return toolStats.filter((stat) => stat.tool === "verify" && stat.count > 0).map((stat) => ({
15489
15534
  sourceId: "tool:verify",
15490
- validatorDigest: createHash12("sha256").update(canonicalJson4(stat), "utf8").digest("hex"),
15535
+ validatorDigest: createHash10("sha256").update(canonicalJson3(stat), "utf8").digest("hex"),
15491
15536
  passed: stat.ok === stat.count && stat.errors === 0 && stat.blocked === 0
15492
15537
  }));
15493
15538
  }
@@ -15610,38 +15655,36 @@ export {
15610
15655
  createStdioServerTransport,
15611
15656
  ACP_USAGE_META_KEY,
15612
15657
  ACP_SESSION_META_KEY,
15658
+ ACP_AGENT_META_KEY,
15613
15659
  ACP_MAX_STRING_BYTES,
15614
15660
  ACP_MAX_RAW_RECORD_BYTES,
15615
15661
  ACP_MAX_CHUNK_BYTES,
15616
15662
  ACP_MAX_TOOL_CALL_ID_BYTES,
15617
- sha256,
15618
- canonicalJson2 as canonicalJson,
15619
15663
  compile,
15620
15664
  compileWorker,
15621
- WORKER_OUTPUT_MAX_BYTES,
15622
- durableAssistantTextFromEvent,
15623
15665
  setCapacityDraining,
15624
15666
  capacityDrain,
15667
+ capacityLeaseUsage,
15625
15668
  openAgentLedger,
15626
15669
  renderAgentLedgerBoard,
15627
15670
  closeAgentLedger,
15628
15671
  renderDispatchReviewerTask,
15629
15672
  createRunReceiptQuality,
15630
15673
  UNVERIFIABLE_RECEIPT_VERIFICATION,
15631
- decideReviewGate,
15632
- parseCompeteGateResult,
15633
- stagePendingGateOutput,
15634
- stagePendingGateDecision,
15635
- resolvePendingGateDecision,
15636
- materializePendingGateDecision,
15637
- finalizePendingGateDecision,
15638
- readPendingGateDecisions,
15639
- preflightPendingGateDecisionMaterialization,
15640
- preparePendingGateDecisionRecovery,
15641
- readGateDecisionArtifacts,
15674
+ assistantTextFromEvent,
15675
+ receiptResponseModelIdObservationLabel,
15676
+ createDispatchRunEventRegistry,
15642
15677
  readFleetRun,
15678
+ listFleetRuns,
15643
15679
  openLedger,
15644
15680
  executePlan,
15681
+ aggregateCostAmounts,
15682
+ formatCostAggregate,
15683
+ COST_NOT_MEASURED,
15684
+ costAggregateForAmount,
15685
+ renderCostAggregate,
15686
+ renderCostAmount,
15687
+ createCostTracker,
15645
15688
  planFleetResume,
15646
15689
  executeFleetRun,
15647
15690
  DispatchDomainModule,
@@ -15649,14 +15692,16 @@ export {
15649
15692
  extractRunProvenance,
15650
15693
  provenanceTranscriptLines,
15651
15694
  provenanceCompactSuffix,
15695
+ EVIDENCE_TAGS,
15652
15696
  FAILURE_CAUSE_TAGS,
15653
15697
  evidenceDirectory,
15654
15698
  EvidenceNotFoundError,
15655
15699
  inspectEvidence,
15700
+ loadEvidenceTrustStatus,
15656
15701
  loadEvidenceRunProvenance,
15657
15702
  listEvidenceOverviews,
15658
15703
  buildEvidence,
15659
15704
  summarizeEvalResults,
15660
15705
  buildEvalEvidence
15661
15706
  };
15662
- //# sourceMappingURL=chunk-TLQJPP24.js.map
15707
+ //# sourceMappingURL=chunk-BUMFYQFY.js.map