@iowarp/clio-coder 0.3.4 → 0.3.7

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 (376) hide show
  1. package/CHANGELOG.md +65 -2
  2. package/CONTRIBUTING.md +6 -6
  3. package/README.md +16 -5
  4. package/dist/{acp-S5R4RR5B.js → acp-SK4MD6MM.js} +11 -11
  5. package/dist/{agents-P6DMMVZY.js → agents-2FN2K6ME.js} +33 -26
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-2XCZLPKS.js → auth-QIYZWM5I.js} +15 -15
  8. package/dist/{chunk-EKMEHE4H.js → chunk-33YXPOE3.js} +2 -3
  9. package/dist/{chunk-VAWWTKDP.js → chunk-3HAPLH5M.js} +11 -11
  10. package/dist/{chunk-YCWGATWI.js → chunk-465YSENW.js} +3 -3
  11. package/dist/{chunk-4OC57DA6.js → chunk-4DGYLA73.js} +53 -2
  12. package/dist/{chunk-UZHIZC5S.js → chunk-4DWFMQDR.js} +61 -76
  13. package/dist/{chunk-ZWMF7253.js → chunk-5C3AQNDW.js} +328 -9
  14. package/dist/{chunk-22NAGB7X.js → chunk-5C77SEEY.js} +5 -94
  15. package/dist/{chunk-WPQLXFOZ.js → chunk-5FR74PWO.js} +3 -2
  16. package/dist/{chunk-35MKKU5R.js → chunk-5UJ6ECTS.js} +18 -10
  17. package/dist/{chunk-BRXQQJFP.js → chunk-6M7VS3J3.js} +571 -50
  18. package/dist/{chunk-QQK64KLB.js → chunk-6TUKSZVF.js} +141 -23
  19. package/dist/{chunk-N4CZJQRK.js → chunk-AB4XIIVB.js} +8 -6
  20. package/dist/{chunk-KRPY7NTG.js → chunk-BMWK7ZIZ.js} +14 -20
  21. package/dist/{chunk-4BPJXDWC.js → chunk-C4JBQ5SR.js} +30 -14
  22. package/dist/{chunk-ZYKPLLNQ.js → chunk-CEYBNUGC.js} +821 -83
  23. package/dist/{chunk-VEZEGCGW.js → chunk-D4MDIG46.js} +20 -18
  24. package/dist/chunk-DJNLUABN.js +843 -0
  25. package/dist/{chunk-BP4OYD6A.js → chunk-DMD2AGVS.js} +21 -2
  26. package/dist/{chunk-KOHPCX4K.js → chunk-DOOEX22V.js} +2 -2
  27. package/dist/chunk-DQA7QLMD.js +123 -0
  28. package/dist/chunk-DR52UMZW.js +21 -0
  29. package/dist/{chunk-3HZ5RWN2.js → chunk-EBEFWSGL.js} +9 -7
  30. package/dist/{chunk-EDRHSCIE.js → chunk-EELBMBT6.js} +128 -13
  31. package/dist/{chunk-HV5X7OR2.js → chunk-EOOQZZDE.js} +16 -14
  32. package/dist/{chunk-WR67VIZY.js → chunk-FOT2FX5J.js} +63 -5
  33. package/dist/{chunk-BPGS2WCQ.js → chunk-GEYXPTRF.js} +2 -1
  34. package/dist/{chunk-FYYLNIL5.js → chunk-GH5622CP.js} +2 -2
  35. package/dist/{chunk-BEY543CS.js → chunk-GOXNB3AO.js} +5 -2
  36. package/dist/chunk-GWS3VEIW.js +195 -0
  37. package/dist/{chunk-G4BMMOKF.js → chunk-HVDIIIQW.js} +2 -2
  38. package/dist/chunk-HWUFFB6L.js +83 -0
  39. package/dist/{chunk-X6COSD2O.js → chunk-J7PIKKWC.js} +8 -436
  40. package/dist/{chunk-NILBFAPG.js → chunk-JNXPYBB4.js} +2 -2
  41. package/dist/{chunk-4VP4KH3K.js → chunk-JRIO5UD2.js} +4 -4
  42. package/dist/{chunk-K6WL7QZT.js → chunk-JTSEDYVQ.js} +7 -7
  43. package/dist/{chunk-QKMUKYO7.js → chunk-KCMKRQX4.js} +236 -84
  44. package/dist/chunk-KZ2H5X4G.js +1026 -0
  45. package/dist/{chunk-A2GZF7DC.js → chunk-LADCF22A.js} +13 -13
  46. package/dist/chunk-LCGCVYZ4.js +57 -0
  47. package/dist/chunk-M4AKACEO.js +382 -0
  48. package/dist/{chunk-POHLU5DW.js → chunk-M6L6IDJG.js} +3 -3
  49. package/dist/{chunk-4JUF2NNX.js → chunk-MXI6J5JF.js} +7 -7
  50. package/dist/{chunk-X4RCMKVQ.js → chunk-NDINPTJ4.js} +2 -2
  51. package/dist/{chunk-TTNYS3EA.js → chunk-OB5HIGJY.js} +1 -1
  52. package/dist/{chunk-7RXG6QRZ.js → chunk-OBMAI2DP.js} +61 -840
  53. package/dist/{chunk-5M54SPOL.js → chunk-ODFEOB4F.js} +161 -5
  54. package/dist/chunk-PD3MESLB.js +242 -0
  55. package/dist/{chunk-ED4KHGC3.js → chunk-PPAMZ32Z.js} +9 -2
  56. package/dist/{chunk-VMNQ6OZA.js → chunk-QCTRSGHQ.js} +963 -786
  57. package/dist/chunk-RVG5JXAL.js +41 -0
  58. package/dist/{chunk-RD5U66HV.js → chunk-SROCI7ZU.js} +7 -7
  59. package/dist/{chunk-MFFY33HR.js → chunk-THKY7CD7.js} +466 -205
  60. package/dist/{chunk-34475P3I.js → chunk-TSHXZTOQ.js} +5 -4
  61. package/dist/{chunk-PCZJO5TI.js → chunk-UFQ3F4FW.js} +13 -178
  62. package/dist/{chunk-AD2SYQYC.js → chunk-UHXRNZ2J.js} +121 -3
  63. package/dist/chunk-UND3GU2L.js +103 -0
  64. package/dist/{chunk-QQL5RT5M.js → chunk-UUANF5CR.js} +2323 -2114
  65. package/dist/{chunk-VJWL6YS5.js → chunk-UUVG37B4.js} +2 -2
  66. package/dist/chunk-UVDSQ6LW.js +472 -0
  67. package/dist/{chunk-QWU7ZBO7.js → chunk-VQNODYQ4.js} +215 -56
  68. package/dist/chunk-VREKEFLL.js +37 -0
  69. package/dist/{chunk-2TZWSW76.js → chunk-WHGPSPT5.js} +2 -2
  70. package/dist/{chunk-TW3WDMVS.js → chunk-WHJYKASB.js} +2 -2
  71. package/dist/{chunk-MEQ45TQ4.js → chunk-WJHBC77E.js} +21 -7
  72. package/dist/{chunk-HXG4IURW.js → chunk-X2KV5FXT.js} +2 -2
  73. package/dist/{chunk-YHZX5GEU.js → chunk-XAKHZX5N.js} +2 -2
  74. package/dist/{chunk-2LZI5CAG.js → chunk-XEGB6BCN.js} +228 -36
  75. package/dist/{chunk-E25LMLRW.js → chunk-YD734TPH.js} +2 -2
  76. package/dist/{verifiers-4UUM6TEE.js → chunk-YTYFXUI3.js} +121 -372
  77. package/dist/{chunk-3JLKSKD7.js → chunk-ZGH7FGS5.js} +17 -7
  78. package/dist/{chunk-VSNATDE6.js → chunk-ZZMN5OM4.js} +2 -2
  79. package/dist/cli/index.js +34 -32
  80. package/dist/{clio-J5JIOIDS.js → clio-WBVQEBKO.js} +7 -7
  81. package/dist/{code-nav-AXCXSBHX.js → code-nav-FGGFIE7L.js} +7 -7
  82. package/dist/codewiki/build-worker.js +4 -4
  83. package/dist/{components-KELWS457.js → components-F7OEATSO.js} +5 -5
  84. package/dist/{config-OEBMIN2U.js → config-TRBL3RCF.js} +48 -41
  85. package/dist/{configure-PUQOSIXQ.js → configure-OLCVPHNM.js} +17 -17
  86. package/dist/{context-URSXPBCK.js → context-MJIJ6GOX.js} +12 -12
  87. package/dist/{context-EKDCKUUZ.js → context-WFPKQSM6.js} +26 -9
  88. package/dist/{context-MGSE4Z2T.js → context-XEWE3MOJ.js} +44 -37
  89. package/dist/{context-clear-KDAJRNUK.js → context-clear-KNOS2JPB.js} +44 -37
  90. package/dist/{context-index-BZ4UYMTC.js → context-index-SSR5ECNE.js} +3 -3
  91. package/dist/{context-working-set-SBKMPPI2.js → context-working-set-EUXAZI6N.js} +14 -13
  92. package/dist/{dispatch-runner-MSWN72NK.js → dispatch-runner-B7MTOVKL.js} +321 -60
  93. package/dist/{docs-2C2LTVT2.js → docs-FLJTIDSE.js} +5 -5
  94. package/dist/{doctor-7BSE27PJ.js → doctor-RN4YKO2X.js} +15 -15
  95. package/dist/{eval-IZGDOO4H.js → eval-RUBJVSNQ.js} +52 -236
  96. package/dist/{evidence-SR7WXB5B.js → evidence-JZNBUOQZ.js} +39 -33
  97. package/dist/{evolve-K7VE2CBX.js → evolve-FJVC4KKI.js} +39 -33
  98. package/dist/{extensions-QVDOHDGJ.js → extensions-IQL36S7K.js} +5 -5
  99. package/dist/{fleet-7XMJNQNF.js → fleet-BDKYJFCP.js} +243 -370
  100. package/dist/fleet-commands-ZFIWZSB3.js +70 -0
  101. package/dist/fleet-graph-Y6HPXIVF.js +125 -0
  102. package/dist/fleet-new-RDVJLHHH.js +48 -0
  103. package/dist/{fleet-preflight-AQNAH644.js → fleet-preflight-BHSNPBMH.js} +2 -2
  104. package/dist/fleet-validate-BIYREGIK.js +79 -0
  105. package/dist/{init-JGNPAYXT.js → init-LQUB5COQ.js} +57 -48
  106. package/dist/library-NJAHIGG4.js +217 -0
  107. package/dist/memory-OG6HOYKM.js +472 -0
  108. package/dist/{models-ZMMLFJNN.js → models-5ZG5XY7J.js} +23 -22
  109. package/dist/{monitor-2F3T5KHP.js → monitor-TJ7AMTGB.js} +69 -35
  110. package/dist/{orchestrator-ORHT43JB.js → orchestrator-WZYB54DM.js} +4868 -1189
  111. package/dist/{paths-UXLN5YYZ.js → paths-XUC7GS6E.js} +5 -5
  112. package/dist/{reset-NXGTYNUO.js → reset-PXQT45IY.js} +8 -8
  113. package/dist/{run-RF4WJGMT.js → run-FQ74YF62.js} +82 -62
  114. package/dist/{share-UT3W6E4M.js → share-FW7SVCL3.js} +34 -10
  115. package/dist/{skills-PSACKC5Q.js → skills-7E7IRB3R.js} +25 -9
  116. package/dist/{skills-eval-WJSI55RZ.js → skills-eval-LI75W6OK.js} +43 -35
  117. package/dist/{targets-PIIRAOYS.js → targets-4CIFKCTW.js} +27 -24
  118. package/dist/{terminal-lease-ULWXWNVY.js → terminal-lease-WUZY7ZV5.js} +5 -4
  119. package/dist/{uninstall-FZCQCDKC.js → uninstall-7FV7IP4E.js} +5 -5
  120. package/dist/{upgrade-346TZ6AV.js → upgrade-K2HVIVMQ.js} +21 -20
  121. package/dist/{usage-6KKXR32N.js → usage-GTZELZQX.js} +159 -59
  122. package/dist/verifiers-RLAHT27O.js +336 -0
  123. package/dist/{verify-X5HDROLA.js → verify-BX3BRKH5.js} +7 -6
  124. package/dist/{wiki-generate-7STOCIFZ.js → wiki-generate-ASIFASCN.js} +58 -48
  125. package/dist/worker/entry.js +98 -84
  126. package/dist/{workspace-G4ZWUIPR.js → workspace-ZJ6BFM3Q.js} +4 -4
  127. package/docs/README.md +4 -3
  128. package/docs/acp.md +1 -1
  129. package/docs/alcf-provider.md +1 -1
  130. package/docs/architecture.md +2 -2
  131. package/docs/artifact-placement.md +1 -2
  132. package/docs/artifact-versions.md +10 -6
  133. package/docs/built-in-agents.md +26 -2
  134. package/docs/capacity-and-scheduling.md +1 -1
  135. package/docs/commands-and-modes.md +90 -8
  136. package/docs/configuration-and-targets.md +90 -2
  137. package/docs/context-engine.md +4 -2
  138. package/docs/context-working-set.md +4 -4
  139. package/docs/development-pipeline.md +1 -1
  140. package/docs/dispatch-architecture-rationale.md +1 -1
  141. package/docs/documentation-coverage.md +4 -4
  142. package/docs/documentation-guide.md +4 -4
  143. package/docs/eval-runner.md +1 -1
  144. package/docs/evals-internal.md +4 -45
  145. package/docs/evidence-and-memory.md +70 -10
  146. package/docs/evolution.md +1 -1
  147. package/docs/exit-codes-and-output.md +4 -1
  148. package/docs/extensions-and-sharing.md +6 -2
  149. package/docs/fleet-demo-runbook.md +2 -2
  150. package/docs/fleet-dispatch.md +224 -11
  151. package/docs/git-commit-provenance.md +2 -2
  152. package/docs/glossary.md +1 -1
  153. package/docs/installation-and-lifecycle.md +2 -2
  154. package/docs/middleware-and-components.md +20 -2
  155. package/docs/model-catalog.md +1 -1
  156. package/docs/observability.md +55 -8
  157. package/docs/proactive-memory.md +26 -16
  158. package/docs/prompt-envelope-and-tools.md +4 -2
  159. package/docs/provider-adapter-cookbook.md +1 -1
  160. package/docs/release-cut-checklist.md +83 -65
  161. package/docs/resource-library.md +59 -0
  162. package/docs/safety-model.md +29 -7
  163. package/docs/scientific-validation.md +3 -3
  164. package/docs/session-lifecycle.md +37 -1
  165. package/docs/skills-marketplace.md +16 -3
  166. package/docs/tool-usage.md +14 -7
  167. package/docs/trace-store.md +1 -1
  168. package/docs/troubleshooting.md +1 -1
  169. package/docs/tui-design.md +38 -4
  170. package/docs/worker-dispatch-mechanics.md +3 -3
  171. package/package.json +7 -4
  172. package/src/cli/agents.ts +2 -3
  173. package/src/cli/argv.ts +14 -1
  174. package/src/cli/fleet-commands.ts +37 -0
  175. package/src/cli/fleet-graph.ts +102 -0
  176. package/src/cli/fleet-new.ts +36 -0
  177. package/src/cli/fleet-preflight.ts +121 -0
  178. package/src/cli/fleet-validate.ts +30 -0
  179. package/src/cli/fleet.ts +188 -335
  180. package/src/cli/index.ts +4 -2
  181. package/src/cli/library.ts +190 -0
  182. package/src/cli/memory.ts +272 -10
  183. package/src/cli/modes/json-stream.ts +2 -2
  184. package/src/cli/modes/print.ts +12 -1
  185. package/src/cli/run.ts +22 -2
  186. package/src/cli/share.ts +13 -1
  187. package/src/cli/targets.ts +12 -3
  188. package/src/cli/usage.ts +160 -20
  189. package/src/core/bus-events.ts +7 -0
  190. package/src/core/commit-attribution.ts +4 -4
  191. package/src/core/config.ts +130 -0
  192. package/src/core/defaults.ts +81 -0
  193. package/src/core/response-model-id.ts +134 -0
  194. package/src/core/toml.ts +62 -0
  195. package/src/core/workspace-files.ts +0 -1
  196. package/src/domains/agents/builtins/architect.md +2 -1
  197. package/src/domains/agents/builtins/oracle.md +33 -0
  198. package/src/domains/agents/catalog.ts +18 -5
  199. package/src/domains/agents/fleet-contract.ts +278 -16
  200. package/src/domains/agents/index.ts +14 -0
  201. package/src/domains/agents/recipe.ts +54 -14
  202. package/src/domains/agents/result-contract.ts +242 -5
  203. package/src/domains/config/classify.ts +4 -0
  204. package/src/domains/context/bootstrap.ts +36 -27
  205. package/src/domains/context/project-metadata.ts +19 -63
  206. package/src/domains/context/prompt-context.ts +8 -0
  207. package/src/domains/context/working-set/policies/index.ts +3 -4
  208. package/src/domains/dispatch/active-route-planner.ts +14 -0
  209. package/src/domains/dispatch/backoff.ts +2 -1
  210. package/src/domains/dispatch/budget-envelope.ts +396 -0
  211. package/src/domains/dispatch/capability-match.ts +1 -0
  212. package/src/domains/dispatch/checkout-writer-lease.ts +175 -0
  213. package/src/domains/dispatch/contract.ts +36 -0
  214. package/src/domains/dispatch/delegation-plan.ts +167 -0
  215. package/src/domains/dispatch/execution-plan.ts +76 -5
  216. package/src/domains/dispatch/execution-role.ts +3 -1
  217. package/src/domains/dispatch/execution-scheduler.ts +183 -67
  218. package/src/domains/dispatch/extension.ts +339 -36
  219. package/src/domains/dispatch/fleet-gate.ts +14 -0
  220. package/src/domains/dispatch/fleet-plan.ts +63 -3
  221. package/src/domains/dispatch/fleet-run.ts +737 -0
  222. package/src/domains/dispatch/gate-role-prompts.ts +9 -0
  223. package/src/domains/dispatch/host-verification.ts +178 -0
  224. package/src/domains/dispatch/index.ts +38 -0
  225. package/src/domains/dispatch/intent.ts +159 -0
  226. package/src/domains/dispatch/orphan-recovery.ts +1 -0
  227. package/src/domains/dispatch/receipt-integrity.ts +12 -4
  228. package/src/domains/dispatch/state.ts +37 -3
  229. package/src/domains/dispatch/types.ts +61 -9
  230. package/src/domains/dispatch/validation.ts +80 -6
  231. package/src/domains/dispatch/worker-spawn.ts +14 -3
  232. package/src/domains/eval/metrics/evidence.ts +0 -116
  233. package/src/domains/eval/metrics/invariants.ts +1 -1
  234. package/src/domains/eval/runners/clio-run.ts +1 -10
  235. package/src/domains/eval/runners/external-command.ts +2 -29
  236. package/src/domains/eval/schema/suite.ts +0 -7
  237. package/src/domains/eval/suites/run.ts +1 -7
  238. package/src/domains/evidence/trust-status.ts +10 -1
  239. package/src/domains/memory/index.ts +22 -0
  240. package/src/domains/memory/operations.ts +58 -1
  241. package/src/domains/memory/promotion.ts +281 -0
  242. package/src/domains/memory/prompt-section.ts +25 -5
  243. package/src/domains/memory/proposal.ts +51 -7
  244. package/src/domains/memory/task-bank.ts +3 -2
  245. package/src/domains/memory/task-memory-handoff.ts +181 -24
  246. package/src/domains/memory/task-memory-policy.ts +3 -1
  247. package/src/domains/memory/types.ts +37 -0
  248. package/src/domains/memory/validate.ts +178 -0
  249. package/src/domains/middleware/index.ts +15 -0
  250. package/src/domains/middleware/memory-intervention.ts +35 -25
  251. package/src/domains/middleware/runtime.ts +6 -0
  252. package/src/domains/middleware/skills-reminder.ts +19 -4
  253. package/src/domains/middleware/stalled-turn.ts +43 -1
  254. package/src/domains/middleware/types.ts +10 -0
  255. package/src/domains/middleware/watchdog.ts +281 -0
  256. package/src/domains/observability/contract.ts +9 -2
  257. package/src/domains/observability/cost.ts +31 -4
  258. package/src/domains/observability/extension.ts +2 -2
  259. package/src/domains/observability/index.ts +10 -0
  260. package/src/domains/observability/out-of-turn-usage.ts +223 -0
  261. package/src/domains/providers/index.ts +3 -0
  262. package/src/domains/providers/model-discovery.ts +9 -0
  263. package/src/domains/providers/runtime-resolution.ts +38 -1
  264. package/src/domains/providers/runtimes/common/probe-helpers.ts +97 -16
  265. package/src/domains/providers/types/context-window-slots.ts +18 -0
  266. package/src/domains/providers/types/runtime-descriptor.ts +3 -1
  267. package/src/domains/resources/index.ts +20 -0
  268. package/src/domains/resources/library.ts +326 -0
  269. package/src/domains/resources/skills/marketplace.ts +37 -12
  270. package/src/domains/safety/call-target.ts +211 -14
  271. package/src/domains/safety/decision-presentation.ts +268 -0
  272. package/src/domains/safety/redaction.ts +73 -0
  273. package/src/domains/session/context-ledger.ts +10 -1
  274. package/src/domains/session/decision-board.ts +4 -0
  275. package/src/domains/session/entries.ts +3 -0
  276. package/src/domains/session/handoff.ts +629 -0
  277. package/src/domains/session/history.ts +68 -19
  278. package/src/domains/session/usage.ts +24 -7
  279. package/src/domains/share/archive.ts +67 -2
  280. package/src/engine/acp/event-mapper.ts +7 -0
  281. package/src/engine/acp/server.ts +29 -2
  282. package/src/engine/apis/lmstudio.ts +25 -4
  283. package/src/engine/apis/openai-completions.ts +147 -22
  284. package/src/engine/claude/sdk-runtime.ts +8 -2
  285. package/src/engine/claude/tool-safety.ts +13 -0
  286. package/src/engine/loop-guard.ts +27 -3
  287. package/src/engine/worker-events.ts +4 -3
  288. package/src/engine/worker-runtime.ts +59 -54
  289. package/src/entry/orchestrator.ts +55 -1
  290. package/src/interactive/bus-notices.ts +26 -0
  291. package/src/interactive/chat-loop-messages.ts +22 -0
  292. package/src/interactive/chat-loop.ts +248 -1
  293. package/src/interactive/chat-renderer.ts +41 -3
  294. package/src/interactive/clio-editor.ts +44 -7
  295. package/src/interactive/context-overlay.ts +43 -5
  296. package/src/interactive/cost-overlay.ts +70 -11
  297. package/src/interactive/council-dispatch.ts +30 -0
  298. package/src/interactive/council-grid.ts +213 -0
  299. package/src/interactive/council.ts +99 -0
  300. package/src/interactive/dispatch-board.ts +471 -50
  301. package/src/interactive/fleet-run-preview.ts +307 -0
  302. package/src/interactive/footer/notifications.ts +219 -0
  303. package/src/interactive/footer/widgets.ts +13 -0
  304. package/src/interactive/handoff-round.ts +56 -0
  305. package/src/interactive/interactive-application.ts +49 -2
  306. package/src/interactive/interactive-event-projection.ts +9 -1
  307. package/src/interactive/interactive-input-runtime.ts +11 -1
  308. package/src/interactive/interactive-presentation.ts +11 -1
  309. package/src/interactive/interactive-slash-runtime.ts +52 -2
  310. package/src/interactive/interactive-subscriptions.ts +14 -2
  311. package/src/interactive/memory-overlay.ts +89 -4
  312. package/src/interactive/oracle.ts +179 -0
  313. package/src/interactive/overlay-ask-user-lifecycle.ts +7 -1
  314. package/src/interactive/overlay-frame.ts +5 -2
  315. package/src/interactive/overlay-general-openers.ts +230 -2
  316. package/src/interactive/overlay-key-routing.ts +58 -2
  317. package/src/interactive/overlay-lifecycle.ts +52 -5
  318. package/src/interactive/overlay-permission-lifecycle.ts +33 -8
  319. package/src/interactive/overlay-resource-openers.ts +11 -3
  320. package/src/interactive/overlay-session-lifecycle.ts +234 -2
  321. package/src/interactive/overlay-transitions.ts +11 -0
  322. package/src/interactive/overlays/ask-user.ts +74 -30
  323. package/src/interactive/overlays/decisions.ts +3 -1
  324. package/src/interactive/overlays/fleet-run-approval.ts +208 -0
  325. package/src/interactive/overlays/handoff-review.ts +185 -0
  326. package/src/interactive/overlays/library-install-confirm.ts +151 -0
  327. package/src/interactive/overlays/list-overlay.ts +168 -2
  328. package/src/interactive/overlays/settings.ts +101 -4
  329. package/src/interactive/overlays/side-question.ts +139 -0
  330. package/src/interactive/overlays/skills-hub.ts +401 -15
  331. package/src/interactive/permission-hint.ts +35 -0
  332. package/src/interactive/permission-overlay.ts +95 -45
  333. package/src/interactive/renderers/tool-execution.ts +19 -49
  334. package/src/interactive/session-last-turn.ts +8 -1
  335. package/src/interactive/session-usage-reseed.ts +36 -10
  336. package/src/interactive/side-question.ts +171 -0
  337. package/src/interactive/slash-commands.ts +434 -7
  338. package/src/interactive/slash-spec.ts +19 -6
  339. package/src/interactive/status/summary.ts +5 -0
  340. package/src/interactive/status/types.ts +5 -0
  341. package/src/interactive/terminal-lease.ts +1 -0
  342. package/src/interactive/theme/tokens.ts +30 -0
  343. package/src/interactive/turn-context.ts +96 -23
  344. package/src/interactive/turn-middleware.ts +16 -1
  345. package/src/interactive/turn-runtime.ts +37 -8
  346. package/src/interactive/turn-state.ts +3 -0
  347. package/src/interactive/watchdog-run.ts +75 -0
  348. package/src/interactive/worker-progress.ts +440 -0
  349. package/src/interactive/worker-share.ts +56 -1
  350. package/src/interactive/worker-stream.ts +58 -110
  351. package/src/tools/agent-tools.ts +28 -3
  352. package/src/tools/ask-user.ts +21 -1
  353. package/src/tools/bootstrap.ts +3 -0
  354. package/src/tools/compete-worktrees.ts +13 -79
  355. package/src/tools/context/index.ts +2 -2
  356. package/src/tools/dispatch-admission.ts +242 -8
  357. package/src/tools/dispatch-arguments.ts +65 -1
  358. package/src/tools/dispatch-event-text.ts +19 -0
  359. package/src/tools/dispatch-plan.ts +136 -6
  360. package/src/tools/dispatch-runner.ts +319 -13
  361. package/src/tools/dispatch-types.ts +20 -1
  362. package/src/tools/dispatch.ts +96 -3
  363. package/src/tools/monitor.ts +31 -0
  364. package/src/tools/profiles.ts +18 -4
  365. package/src/tools/registry.ts +15 -5
  366. package/src/tools/result-disposition.ts +156 -0
  367. package/src/tools/result-shaping.ts +59 -1
  368. package/src/tools/task-worktree.ts +238 -0
  369. package/src/tools/verify/authoring.ts +116 -55
  370. package/src/tools/verify/scripts.ts +62 -0
  371. package/src/tools/worker-evidence.ts +21 -1
  372. package/src/worker/spec-contract.ts +44 -3
  373. package/dist/chunk-EFADSJET.js +0 -18
  374. package/dist/chunk-HC4CLZ2Y.js +0 -68
  375. package/dist/memory-4ALKDJ4Q.js +0 -246
  376. package/src/domains/eval/metrics/chaos-stream.ts +0 -93
@@ -12,13 +12,14 @@
12
12
  import { createHash, randomBytes } from "node:crypto";
13
13
  import { type Dirent, existsSync, readdirSync, readFileSync } from "node:fs";
14
14
  import { isAbsolute, relative, resolve as resolvePath, sep } from "node:path";
15
- import { BusChannels, type DispatchCompletedPayload } from "../../core/bus-events.js";
15
+ import { BusChannels, type DispatchCompletedPayload, type DispatchRunIdentity } from "../../core/bus-events.js";
16
16
  import { DEFAULT_SETTINGS, type DelegationToolGovernance } from "../../core/defaults.js";
17
17
  import type { DomainBundle, DomainContext, DomainExtension } from "../../core/domain-loader.js";
18
18
  import { GUARDRAIL_DEFAULTS } from "../../core/guardrails.js";
19
19
  import { readClioVersion, readPiMonoVersion } from "../../core/package-root.js";
20
20
  import { canonicalizeExistingPath } from "../../core/path-canonical.js";
21
21
  import { protectedResidencyModels } from "../../core/residency-protection.js";
22
+ import { responseModelIdObservationFromRecord } from "../../core/response-model-id.js";
22
23
  import {
23
24
  responseSchemaConflictsWithTools,
24
25
  runtimeSpeaksResponseSchemaDialect,
@@ -39,6 +40,12 @@ import { WORKER_RUNTIME_MEDIATES_CLIO_DISPATCH } from "../../engine/worker-runti
39
40
  import { toolPromptHintsForNames } from "../../tools/builtin-tool-catalog.js";
40
41
  import { networkToolsDisabled } from "../../tools/network-policy.js";
41
42
  import { applyToolProfile, assertToolProfileEnforceable, type ToolProfileName } from "../../tools/profiles.js";
43
+ import {
44
+ applyTaskWorktree,
45
+ cleanupTaskWorktree,
46
+ createTaskWorktree,
47
+ gitCheckoutRoot,
48
+ } from "../../tools/task-worktree.js";
42
49
  import { truncateUtf8 } from "../../tools/truncate-utf8.js";
43
50
  import {
44
51
  serializeWorkerRuntimeDescriptor,
@@ -134,8 +141,10 @@ import {
134
141
  registerDetachedBatch,
135
142
  } from "./batch-store.js";
136
143
  import { type BatchState, createBatch, onRunComplete, snapshotBatch } from "./batch-tracker.js";
144
+ import { type RunToolBudgetEnvelope, resolveToolBudgetEnvelope } from "./budget-envelope.js";
137
145
  import { assessCapabilityMismatch, type CapabilityMismatch } from "./capability-match.js";
138
146
  import { capacityLeaseUsage, createNodeLeaseUsageReader } from "./capacity-lease.js";
147
+ import { acquireCheckoutWriterLease, type CheckoutWriterLease } from "./checkout-writer-lease.js";
139
148
  import type {
140
149
  DispatchAdmissionObserver,
141
150
  DispatchContract,
@@ -157,6 +166,7 @@ import {
157
166
  import { routeFactVerdict } from "./fleet-preflight.js";
158
167
  import { competeStanceLiner, isBoundedGateRolePrompt } from "./gate-role-prompts.js";
159
168
  import { classifyHeartbeat, DEFAULT_HEARTBEAT_SPEC, type HeartbeatSpec, type HeartbeatStatus } from "./heartbeat.js";
169
+ import { hostVerificationRejection, runHostVerification } from "./host-verification.js";
160
170
  import { adaptJointRouteInput } from "./joint-route-adapter.js";
161
171
  import {
162
172
  configuredJointNodes,
@@ -207,7 +217,7 @@ import { createRouteObserver, type RouteObservationHandle, type RouteObserver }
207
217
  import { reduceRouteQuality } from "./route-quality.js";
208
218
  import { defaultRoutingIntent } from "./routing-intent.js";
209
219
  import { detectRunIdentity } from "./run-identity.js";
210
- import { type Ledger, openLedger } from "./state.js";
220
+ import { type Ledger, newRunId, openLedger } from "./state.js";
211
221
  import {
212
222
  countToolCalls,
213
223
  hasPotentiallyMutatingAttempt,
@@ -307,6 +317,7 @@ interface ActiveRun {
307
317
  requestOrigin?: DispatchRequestOrigin;
308
318
  agentId: string;
309
319
  task: string;
320
+ budget?: RunToolBudgetEnvelope;
310
321
  cwd: string;
311
322
  /** Fleet node this run was placed on; null when no placement resolved it. */
312
323
  node: RunNodeIdentity | null;
@@ -1287,6 +1298,7 @@ interface DispatchLifecycleStage {
1287
1298
  capabilityMismatch: CapabilityMismatch | null;
1288
1299
  effectiveAutonomy: AutonomyLevel;
1289
1300
  budget: WorkerBudget;
1301
+ budgetEnvelope: RunToolBudgetEnvelope;
1290
1302
  settings?: Readonly<ReturnType<ConfigContract["get"]>>;
1291
1303
  }
1292
1304
 
@@ -1411,7 +1423,7 @@ function assertWriteRootsEnforceable(runtime: RuntimeDescriptor, writeRoots: Rea
1411
1423
  function assertWorkerBudgetEnforceable(runtime: RuntimeDescriptor, hasDeclaredBudget: boolean): void {
1412
1424
  if (!hasDeclaredBudget || runtime.kind !== "subprocess") return;
1413
1425
  throw new Error(
1414
- `dispatch: runtime '${runtime.id}' cannot enforce an explicit agent budget because subprocess workers do not expose per-tool mediation; choose a native or claude-sdk worker`,
1426
+ `dispatch: runtime '${runtime.id}' cannot enforce an explicit dispatch budget because subprocess workers do not expose per-tool mediation; choose a native or claude-sdk worker`,
1415
1427
  );
1416
1428
  }
1417
1429
 
@@ -1543,26 +1555,36 @@ function assertPostRuntimeToolCompatibility(
1543
1555
  );
1544
1556
  }
1545
1557
 
1558
+ function workerToolCallHardCap(settings: EffectiveSettings): number {
1559
+ const rawEnvCap = process.env.CLIO_CODER_WORKER_TOOL_CALL_CAP?.trim();
1560
+ const parsedEnvCap = rawEnvCap && /^[1-9]\d*$/.test(rawEnvCap) ? Number(rawEnvCap) : Number.NaN;
1561
+ return Number.isSafeInteger(parsedEnvCap)
1562
+ ? parsedEnvCap
1563
+ : (settings?.guardrails.workerToolCallCap ?? GUARDRAIL_DEFAULTS.workerToolCallCap);
1564
+ }
1565
+
1546
1566
  function resolveEffectiveWorkerBudget(input: {
1567
+ req: DispatchRequest;
1568
+ recipeId: string;
1547
1569
  declared: ReturnType<typeof normalizeAgentSpec>["budget"];
1548
1570
  allowedTools: ReadonlyArray<ToolName>;
1549
1571
  settings: EffectiveSettings;
1550
- }): WorkerBudget {
1551
- const rawEnvCap = process.env.CLIO_CODER_WORKER_TOOL_CALL_CAP?.trim();
1552
- const parsedEnvCap = rawEnvCap && /^[1-9]\d*$/.test(rawEnvCap) ? Number(rawEnvCap) : Number.NaN;
1553
- const hardCap = Number.isSafeInteger(parsedEnvCap)
1554
- ? parsedEnvCap
1555
- : (input.settings?.guardrails.workerToolCallCap ?? GUARDRAIL_DEFAULTS.workerToolCallCap);
1572
+ }): RunToolBudgetEnvelope {
1573
+ const hardCap = workerToolCallHardCap(input.settings);
1556
1574
  const declared = input.declared ?? {
1557
1575
  toolCalls: hardCap,
1558
1576
  readReserve: Math.min(5, Math.max(0, hardCap - 1)),
1559
1577
  synthesis: true,
1560
1578
  };
1561
- const toolCalls = Math.min(declared.toolCalls, hardCap);
1562
- const readReserve = input.allowedTools.includes(ToolNames.Read)
1563
- ? Math.min(declared.readReserve, Math.max(0, toolCalls - 1))
1564
- : 0;
1565
- return { toolCalls, readReserve, synthesis: declared.synthesis, hardCap };
1579
+ return resolveToolBudgetEnvelope({
1580
+ recipeId: input.recipeId,
1581
+ policy: declared,
1582
+ ...(input.req.budget === undefined ? {} : { request: input.req.budget }),
1583
+ hardCap,
1584
+ hasReadTool: input.allowedTools.includes(ToolNames.Read),
1585
+ retry: (input.req.lineage?.attempt ?? 0) > 0,
1586
+ revision: input.req.gate?.role === "builder" && input.req.gate.cycle > 1 && input.req.gate.verdict === "revise",
1587
+ });
1566
1588
  }
1567
1589
 
1568
1590
  function frozenProtectedArtifactState(state: ProtectedArtifactState | undefined): ProtectedArtifactState {
@@ -1812,7 +1834,7 @@ function buildDispatchWorkerSpec(input: DispatchWorkerSpecInput, config?: Config
1812
1834
  // A gate role that overrides the recipe contract gets no worker-side repair,
1813
1835
  // for the same reason it gets no recipe validation.
1814
1836
  if (appliesRecipeResultContract(input.req.gate?.role) && input.recipe?.resultContract) {
1815
- spec.resultContract = input.recipe.resultContract;
1837
+ spec.resultContract = input.req.resultContractOverride ?? input.recipe.resultContract;
1816
1838
  }
1817
1839
  const product = input.req.product ?? input.recipe?.product;
1818
1840
  if (product) spec.product = product;
@@ -3193,7 +3215,7 @@ export function createDispatchBundle(
3193
3215
  );
3194
3216
  enforceCapabilityGate(target.target.id, target.modelCapabilities, req.requiredCapabilities);
3195
3217
  assertRuntimeCanHonorWorkerPermissionMode(target.runtime, settings?.workers.onPermission ?? "deny");
3196
- assertWorkerBudgetEnforceable(target.runtime, spec.budget !== null);
3218
+ assertWorkerBudgetEnforceable(target.runtime, spec.budget !== null || req.budget !== undefined);
3197
3219
 
3198
3220
  const cwd = req.cwd ?? process.cwd();
3199
3221
  const sessionAutonomy = settings?.autonomy ?? "auto-edit";
@@ -3231,7 +3253,13 @@ export function createDispatchBundle(
3231
3253
  workingContextPaths: workerWorkingContextPaths(req),
3232
3254
  });
3233
3255
  const systemPrompt = compiledWorkerPrompt.systemPrompt;
3234
- const budget = resolveEffectiveWorkerBudget({ declared: spec.budget, allowedTools: effectiveTools, settings });
3256
+ const budgetEnvelope = resolveEffectiveWorkerBudget({
3257
+ req,
3258
+ recipeId: recipe.id,
3259
+ declared: spec.budget,
3260
+ allowedTools: effectiveTools,
3261
+ settings,
3262
+ });
3235
3263
  // Fetch structured project context only for tiers that receive it, so
3236
3264
  // read-only scouts never pay the CLIO-CODER.md read. The tier is spec policy
3237
3265
  // (capability-class default, recipe frontmatter override).
@@ -3291,7 +3319,8 @@ export function createDispatchBundle(
3291
3319
  operatorProfileApplied: compiledWorkerPrompt.operatorProfileApplied ?? false,
3292
3320
  capabilityMismatch,
3293
3321
  effectiveAutonomy,
3294
- budget,
3322
+ budget: budgetEnvelope.effective,
3323
+ budgetEnvelope,
3295
3324
  ...(settings ? { settings } : {}),
3296
3325
  };
3297
3326
  }
@@ -3473,6 +3502,7 @@ export function createDispatchBundle(
3473
3502
  role?: string;
3474
3503
  usage?: unknown;
3475
3504
  model?: unknown;
3505
+ responseModelIdObservation?: unknown;
3476
3506
  responseModel?: unknown;
3477
3507
  responseId?: unknown;
3478
3508
  stopReason?: unknown;
@@ -3522,12 +3552,16 @@ export function createDispatchBundle(
3522
3552
  tokenMeter.cacheReadTokens += typeof u.cacheRead === "number" ? u.cacheRead : 0;
3523
3553
  tokenMeter.cacheWriteTokens += typeof u.cacheWrite === "number" ? u.cacheWrite : 0;
3524
3554
  tokenMeter.reasoningTokens += extractReasoningTokenCount(u);
3525
- const model = readStringOrNull(event.message.model);
3526
- const responseModel = readStringOrNull(event.message.responseModel);
3527
- const responseId = readStringOrNull(event.message.responseId);
3528
- if (model !== null || responseModel !== null || responseId !== null) {
3529
- upstreamResponses.push({ model, responseModel, responseId });
3530
- }
3555
+ const requestedModelId = readStringOrNull(event.message.model);
3556
+ const responseModelIdObservation = responseModelIdObservationFromRecord(event.message, "not-observed");
3557
+ const differingResponseModelId = readStringOrNull(event.message.responseModel);
3558
+ const providerResponseId = readStringOrNull(event.message.responseId);
3559
+ upstreamResponses.push({
3560
+ requestedModelId,
3561
+ responseModelIdObservation,
3562
+ differingResponseModelId,
3563
+ providerResponseId,
3564
+ });
3531
3565
  if (event.message.stopReason === "error") {
3532
3566
  const message = readStringOrNull(event.message.errorMessage);
3533
3567
  if (message !== null) failureMessage = message;
@@ -3584,10 +3618,12 @@ export function createDispatchBundle(
3584
3618
  let identity!: ReturnType<typeof detectRunIdentity>;
3585
3619
  try {
3586
3620
  envelope = ledgerRef.create({
3621
+ ...(req.runIdHint !== undefined ? { id: req.runIdHint } : {}),
3587
3622
  agentId: req.agentId,
3588
3623
  executionRole: withAttemptRole(req.executionRole, req.lineage?.attempt ?? 0),
3589
3624
  requestOrigin: lifecycle.requestOrigin,
3590
3625
  task: req.task,
3626
+ ...(req.intent !== undefined ? { intent: structuredClone(req.intent) } : {}),
3591
3627
  targetId,
3592
3628
  wireModelId,
3593
3629
  runtimeId,
@@ -3619,6 +3655,7 @@ export function createDispatchBundle(
3619
3655
  ...(lifecycle.pipeline ? { pipeline: lifecycle.pipeline } : {}),
3620
3656
  ...(lifecycle.briefing ? { briefing: lifecycle.briefing } : {}),
3621
3657
  ...(req.gate !== undefined ? { gate: req.gate } : {}),
3658
+ ...(req.council !== undefined ? { council: req.council } : {}),
3622
3659
  ...(req.plan !== undefined ? { plan: req.plan } : {}),
3623
3660
  ...(lifecycle.personaOverride ? { personaOverride: lifecycle.personaOverride } : {}),
3624
3661
  });
@@ -3761,6 +3798,7 @@ export function createDispatchBundle(
3761
3798
  executionRole: envelope.executionRole,
3762
3799
  requestOrigin: lifecycle.requestOrigin,
3763
3800
  task: req.task,
3801
+ ...(req.intent !== undefined ? { intent: structuredClone(req.intent) } : {}),
3764
3802
  targetId,
3765
3803
  wireModelId,
3766
3804
  runtimeId,
@@ -3775,6 +3813,7 @@ export function createDispatchBundle(
3775
3813
  ...(lifecycle.pipeline ? { pipeline: lifecycle.pipeline } : {}),
3776
3814
  ...(lifecycle.briefing ? { briefing: lifecycle.briefing } : {}),
3777
3815
  ...(req.gate !== undefined ? { gate: req.gate } : {}),
3816
+ ...(req.council !== undefined ? { council: req.council } : {}),
3778
3817
  ...(req.plan !== undefined ? { plan: req.plan } : {}),
3779
3818
  ...(lifecycle.personaOverride ? { personaOverride: lifecycle.personaOverride } : {}),
3780
3819
  projectContext: lifecycle.projectContext,
@@ -3887,6 +3926,7 @@ export function createDispatchBundle(
3887
3926
  durationMs,
3888
3927
  exitCode: receipt.exitCode,
3889
3928
  toolActivity: receipt.toolActivity ?? null,
3929
+ ...(receipt.hostVerification !== undefined ? { hostVerification: receipt.hostVerification.status } : {}),
3890
3930
  ...(receipt.skillActivations && receipt.skillActivations.length > 0
3891
3931
  ? { skillActivations: [...receipt.skillActivations] }
3892
3932
  : {}),
@@ -4142,6 +4182,11 @@ export function createDispatchBundle(
4142
4182
  return handle;
4143
4183
  };
4144
4184
  if (req.delegationAgentId) {
4185
+ if (req.budget !== undefined) {
4186
+ throw new Error(
4187
+ "dispatch: budget envelopes cannot be enforced on an ACP delegation target; dispatch to a native or claude-sdk worker",
4188
+ );
4189
+ }
4145
4190
  assertPlannedNodeIdentity(req, { id: "local", kind: "local" });
4146
4191
  assertProtectedArtifactsEnforceable("acp-delegation", false, protectedArtifactState);
4147
4192
  if (req.responseSchema !== undefined) {
@@ -4372,6 +4417,7 @@ export function createDispatchBundle(
4372
4417
  role?: string;
4373
4418
  usage?: unknown;
4374
4419
  model?: unknown;
4420
+ responseModelIdObservation?: unknown;
4375
4421
  responseModel?: unknown;
4376
4422
  responseId?: unknown;
4377
4423
  stopReason?: unknown;
@@ -4412,7 +4458,8 @@ export function createDispatchBundle(
4412
4458
  if (
4413
4459
  event.type === "clio_run_outcome" &&
4414
4460
  isRunOutcomeCode(event.payload?.outcomeCode) &&
4415
- event.payload.outcomeCode !== "worker_final_output_missing"
4461
+ event.payload.outcomeCode !== "worker_final_output_missing" &&
4462
+ event.payload.outcomeCode !== "host_verification_rejected"
4416
4463
  ) {
4417
4464
  if (acceptsOutcomeCodeEvents) {
4418
4465
  trustedOutcomeCodes.add(event.payload.outcomeCode);
@@ -4477,12 +4524,16 @@ export function createDispatchBundle(
4477
4524
  tokenMeter.cacheReadTokens += typeof u.cacheRead === "number" ? u.cacheRead : 0;
4478
4525
  tokenMeter.cacheWriteTokens += typeof u.cacheWrite === "number" ? u.cacheWrite : 0;
4479
4526
  tokenMeter.reasoningTokens += extractReasoningTokenCount(u);
4480
- const model = readStringOrNull(event.message.model);
4481
- const responseModel = readStringOrNull(event.message.responseModel);
4482
- const responseId = readStringOrNull(event.message.responseId);
4483
- if (model !== null || responseModel !== null || responseId !== null) {
4484
- upstreamResponses.push({ model, responseModel, responseId });
4485
- }
4527
+ const requestedModelId = readStringOrNull(event.message.model);
4528
+ const responseModelIdObservation = responseModelIdObservationFromRecord(event.message, "not-observed");
4529
+ const differingResponseModelId = readStringOrNull(event.message.responseModel);
4530
+ const providerResponseId = readStringOrNull(event.message.responseId);
4531
+ upstreamResponses.push({
4532
+ requestedModelId,
4533
+ responseModelIdObservation,
4534
+ differingResponseModelId,
4535
+ providerResponseId,
4536
+ });
4486
4537
  if (event.message.stopReason === "error") {
4487
4538
  const message = readStringOrNull(event.message.errorMessage);
4488
4539
  if (message !== null) failureMessage = message;
@@ -4568,11 +4619,14 @@ export function createDispatchBundle(
4568
4619
  let identity!: ReturnType<typeof detectRunIdentity>;
4569
4620
  try {
4570
4621
  envelope = ledgerRef.create({
4622
+ ...(req.runIdHint !== undefined ? { id: req.runIdHint } : {}),
4571
4623
  agentId: req.agentId,
4572
4624
  executionRole: withAttemptRole(req.executionRole, req.lineage?.attempt ?? 0),
4573
4625
  agentAudience: lifecycle.agentAudience,
4574
4626
  requestOrigin: lifecycle.requestOrigin,
4575
4627
  task: req.task,
4628
+ ...(req.intent !== undefined ? { intent: structuredClone(req.intent) } : {}),
4629
+ budget: lifecycle.budgetEnvelope,
4576
4630
  targetId: lifecycle.target.target.id,
4577
4631
  wireModelId: lifecycle.target.wireModelId,
4578
4632
  runtimeId: lifecycle.target.runtime.id,
@@ -4621,6 +4675,7 @@ export function createDispatchBundle(
4621
4675
  ...(lifecycle.pipeline ? { pipeline: lifecycle.pipeline } : {}),
4622
4676
  ...(lifecycle.briefing ? { briefing: lifecycle.briefing } : {}),
4623
4677
  ...(req.gate !== undefined ? { gate: req.gate } : {}),
4678
+ ...(req.council !== undefined ? { council: req.council } : {}),
4624
4679
  ...(req.plan !== undefined ? { plan: req.plan } : {}),
4625
4680
  ...(lifecycle.personaOverride ? { personaOverride: lifecycle.personaOverride } : {}),
4626
4681
  ...(heartbeatAt ? { heartbeatAt: heartbeatIso(heartbeatAt.current) } : {}),
@@ -4638,8 +4693,10 @@ export function createDispatchBundle(
4638
4693
  // reroute lineage depth, and the model context window for the
4639
4694
  // per-worker meter. All optional so consumers degrade to local/plain.
4640
4695
  const fleetIdentity = {
4696
+ budget: lifecycle.budgetEnvelope,
4641
4697
  ...(placement !== undefined && placement !== null ? { node: placement.node.id } : {}),
4642
4698
  ...(req.gate !== undefined ? { gate: { role: req.gate.role, cycle: req.gate.cycle } } : {}),
4699
+ ...(req.council !== undefined ? { council: req.council } : {}),
4643
4700
  ...(req.reroutes !== undefined && req.reroutes.length > 0 ? { rerouteCount: req.reroutes.length } : {}),
4644
4701
  ...(lifecycle.target.modelCapabilities !== undefined &&
4645
4702
  lifecycle.target.modelCapabilities !== null &&
@@ -4743,6 +4800,7 @@ export function createDispatchBundle(
4743
4800
  requestOrigin: lifecycle.requestOrigin,
4744
4801
  agentId: req.agentId,
4745
4802
  task: req.task,
4803
+ budget: lifecycle.budgetEnvelope,
4746
4804
  cwd: lifecycle.cwd,
4747
4805
  node: placement?.node ?? null,
4748
4806
  aborted: false,
@@ -4790,6 +4848,15 @@ export function createDispatchBundle(
4790
4848
  const tokenCount =
4791
4849
  tokenMeter.inputTokens + tokenMeter.outputTokens + tokenMeter.cacheReadTokens + tokenMeter.cacheWriteTokens;
4792
4850
  const protectedArtifacts = protectedArtifactReceiptSummary(spec.protectedArtifactState);
4851
+ const fleetGate = (() => {
4852
+ if (req.fleetGateReceipt === undefined) return null;
4853
+ try {
4854
+ const content = readFileSync(resolvePath(lifecycle.cwd, req.fleetGateReceipt.path));
4855
+ return { path: req.fleetGateReceipt.path, pathHash: createHash("sha256").update(content).digest("hex") };
4856
+ } catch {
4857
+ return { path: req.fleetGateReceipt.path, pathHash: createHash("sha256").update("").digest("hex") };
4858
+ }
4859
+ })();
4793
4860
  // Sealed from the stored board, never from anything the worker said
4794
4861
  // about itself. Absent when the run had no ledger.
4795
4862
  const ledgerContribution = (() => {
@@ -4817,6 +4884,7 @@ export function createDispatchBundle(
4817
4884
  agentAudience: lifecycle.agentAudience,
4818
4885
  requestOrigin: lifecycle.requestOrigin,
4819
4886
  task: req.task,
4887
+ budget: lifecycle.budgetEnvelope,
4820
4888
  targetId: lifecycle.target.target.id,
4821
4889
  wireModelId: lifecycle.target.wireModelId,
4822
4890
  runtimeId: lifecycle.target.runtime.id,
@@ -4824,6 +4892,7 @@ export function createDispatchBundle(
4824
4892
  outcome,
4825
4893
  outcomeCode,
4826
4894
  lineage,
4895
+ ...(req.intent !== undefined ? { intent: structuredClone(req.intent) } : {}),
4827
4896
  identity,
4828
4897
  node: placement?.node ?? LOCAL_RUN_NODE,
4829
4898
  ...receiptAttestationFields(worker.attestation?.() ?? null),
@@ -4834,7 +4903,9 @@ export function createDispatchBundle(
4834
4903
  ...(lifecycle.briefing ? { briefing: lifecycle.briefing } : {}),
4835
4904
  ...(steering.length > 0 ? { steering: steering.map((entry) => ({ ...entry })) } : {}),
4836
4905
  ...(req.gate !== undefined ? { gate: req.gate } : {}),
4906
+ ...(req.council !== undefined ? { council: req.council } : {}),
4837
4907
  ...(req.plan !== undefined ? { plan: req.plan } : {}),
4908
+ ...(fleetGate !== null ? { fleetGate } : {}),
4838
4909
  ...(lifecycle.personaOverride ? { personaOverride: lifecycle.personaOverride } : {}),
4839
4910
  projectContext: lifecycle.projectContext,
4840
4911
  rulesApplied: lifecycle.rulesApplied,
@@ -4964,6 +5035,7 @@ export function createDispatchBundle(
4964
5035
  durationMs,
4965
5036
  exitCode: receipt.exitCode,
4966
5037
  toolActivity: receipt.toolActivity ?? null,
5038
+ ...(receipt.hostVerification !== undefined ? { hostVerification: receipt.hostVerification.status } : {}),
4967
5039
  ...(receipt.skillActivations && receipt.skillActivations.length > 0
4968
5040
  ? { skillActivations: [...receipt.skillActivations] }
4969
5041
  : {}),
@@ -5062,7 +5134,7 @@ export function createDispatchBundle(
5062
5134
  const capturedOutput = outputCapture.snapshot();
5063
5135
  const observedRunEffects = runEffects.snapshot();
5064
5136
  const appliedResultContract = appliesRecipeResultContract(req.gate?.role)
5065
- ? (lifecycle.recipe?.resultContract ?? null)
5137
+ ? (req.resultContractOverride ?? lifecycle.recipe?.resultContract ?? null)
5066
5138
  : null;
5067
5139
  const resultContract = validateRecipeResult({
5068
5140
  contract: appliedResultContract,
@@ -5126,13 +5198,40 @@ export function createDispatchBundle(
5126
5198
  finalDetail = [finalDetail, describeUngroundedValidations(validationGrounding)].filter(Boolean).join("; ");
5127
5199
  }
5128
5200
  const hasTerminalArtifact =
5129
- lifecycle.recipe?.resultContract.kind === "architect-plan" && resultValidation?.conformance === "pass";
5201
+ (req.resultContractOverride ?? lifecycle.recipe?.resultContract)?.kind === "architect-plan" &&
5202
+ resultValidation?.conformance === "pass";
5130
5203
  if (finalOutcome === "succeeded" && !hasDurableFinalOutput(capturedOutput) && !hasTerminalArtifact) {
5131
5204
  finalOutcome = "failed";
5132
5205
  outcomeCode = "worker_final_output_missing";
5133
5206
  finalDetail = WORKER_FINAL_OUTPUT_MISSING_DETAIL;
5134
5207
  failureMessage = finalDetail;
5135
5208
  }
5209
+ const hostVerification = await runHostVerification({
5210
+ runId: envelope.id,
5211
+ request: req,
5212
+ workerSuccessful: finalOutcome === "succeeded",
5213
+ onDiagnostic: (error) => reportDispatchDiagnostic(`write host verification memo for ${envelope.id}`, error),
5214
+ });
5215
+ const hostRejection = hostVerificationRejection(hostVerification);
5216
+ if (hostRejection !== null && finalOutcome === "succeeded") {
5217
+ finalOutcome = "failed";
5218
+ outcomeCode = hostRejection.outcomeCode;
5219
+ finalDetail = hostRejection.detail;
5220
+ failureMessage = finalDetail;
5221
+ }
5222
+ let worktreeReceipt: RunReceiptDraft["worktree"];
5223
+ if (req.taskWorktree !== undefined && finalOutcome === "succeeded") {
5224
+ worktreeReceipt = applyTaskWorktree({
5225
+ worktree: req.taskWorktree,
5226
+ apply: req.apply ?? "merge",
5227
+ protectedPaths: getProtectedArtifactState().artifacts.map((artifact) => artifact.path),
5228
+ });
5229
+ if (worktreeReceipt.reason !== undefined) {
5230
+ finalOutcome = "failed";
5231
+ finalDetail = worktreeReceipt.reason;
5232
+ failureMessage = finalDetail;
5233
+ }
5234
+ }
5136
5235
  const status = runStatusForOutcome(finalOutcome);
5137
5236
  const failureClass = classifyFailure(evidence, result, finalOutcome, outcomeCode);
5138
5237
  const receiptDraft = buildReceiptDraft(
@@ -5146,6 +5245,8 @@ export function createDispatchBundle(
5146
5245
  sealedResultContractFact,
5147
5246
  validationGrounding === null ? null : { ...validationGrounding, ungrounded: [...validationGrounding.ungrounded] },
5148
5247
  );
5248
+ if (hostVerification !== undefined) receiptDraft.hostVerification = hostVerification;
5249
+ if (worktreeReceipt !== undefined) receiptDraft.worktree = worktreeReceipt;
5149
5250
  const ledgerPatch: Partial<RunEnvelope> = {
5150
5251
  status,
5151
5252
  outcome: finalOutcome,
@@ -5176,6 +5277,13 @@ export function createDispatchBundle(
5176
5277
  ledgerRef.update(envelope.id, ledgerPatch);
5177
5278
  const receipt = ledgerRef.recordReceipt(envelope.id, sealRouteDecision(receiptDraft, routeObservation.decision));
5178
5279
  await ledgerRef.persist();
5280
+ if (worktreeReceipt?.applied === true && req.taskWorktree !== undefined) {
5281
+ try {
5282
+ cleanupTaskWorktree(req.taskWorktree, true);
5283
+ } catch (cleanupError) {
5284
+ reportDispatchDiagnostic(`clean applied task worktree ${req.taskWorktree.runId}`, cleanupError);
5285
+ }
5286
+ }
5179
5287
  active.delete(envelope.id);
5180
5288
  recordTargetOutcome(
5181
5289
  lifecycle.target.target.id,
@@ -5263,10 +5371,58 @@ export function createDispatchBundle(
5263
5371
  events: AsyncIterableIterator<unknown>;
5264
5372
  finalPromise: Promise<RunReceipt>;
5265
5373
  }> {
5374
+ let prepared = req;
5375
+ let createdWorktree: DispatchRequest["taskWorktree"];
5376
+ let writerLease: CheckoutWriterLease | undefined;
5377
+ const writerRecipe = agents.get(req.agentId);
5378
+ if (writerRecipe !== null && normalizeAgentSpec(writerRecipe).capabilityClass === "workspace-edit") {
5379
+ const checkout = req.taskWorktree?.root ?? gitCheckoutRoot(req.cwd ?? process.cwd());
5380
+ if (checkout !== null) writerLease = acquireCheckoutWriterLease({ checkout });
5381
+ }
5382
+ if (req.worktree === true && req.taskWorktree === undefined) {
5383
+ const requestedCwd = resolvePath(req.cwd ?? process.cwd());
5384
+ const root = gitCheckoutRoot(requestedCwd);
5385
+ if (root === null) throw new Error("worktree_non_git_checkout");
5386
+ if (req.taskWorktreeDestination !== undefined && root !== req.taskWorktreeDestination) {
5387
+ writerLease?.release();
5388
+ throw new Error("dispatch: worktree merge destination differs from the approved execution snapshot");
5389
+ }
5390
+ const runId = newRunId();
5391
+ let taskWorktree: NonNullable<DispatchRequest["taskWorktree"]>;
5392
+ try {
5393
+ taskWorktree = createTaskWorktree(root, runId);
5394
+ } catch (error) {
5395
+ writerLease?.release();
5396
+ throw error;
5397
+ }
5398
+ createdWorktree = taskWorktree;
5399
+ const cwdRelative = relative(root, requestedCwd);
5400
+ const workerCwd = resolvePath(taskWorktree.path, cwdRelative);
5401
+ const writeRoots = req.writeRoots?.map((entry) => {
5402
+ const rel = relative(root, entry);
5403
+ return rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel) ? entry : resolvePath(taskWorktree.path, rel);
5404
+ });
5405
+ prepared = {
5406
+ ...req,
5407
+ runIdHint: runId,
5408
+ taskWorktree,
5409
+ cwd: workerCwd,
5410
+ protectedArtifactRemap: { sourceRoot: root, workerRoot: taskWorktree.path },
5411
+ ...(writeRoots === undefined ? {} : { writeRoots }),
5412
+ };
5413
+ }
5266
5414
  let handle: Awaited<ReturnType<typeof dispatchAttempt>>;
5267
5415
  try {
5268
- handle = await dispatchAttempt(req, observer);
5416
+ handle = await dispatchAttempt(prepared, observer);
5269
5417
  } catch (error) {
5418
+ writerLease?.release();
5419
+ if (createdWorktree !== undefined) {
5420
+ try {
5421
+ cleanupTaskWorktree(createdWorktree, true);
5422
+ } catch (cleanupError) {
5423
+ reportDispatchDiagnostic(`clean task worktree ${createdWorktree.runId} after admission failure`, cleanupError);
5424
+ }
5425
+ }
5270
5426
  if (req.reservation !== undefined && req.lineage === undefined) {
5271
5427
  rollbackDispatchReservation(req.reservation.ownerId, now());
5272
5428
  }
@@ -5274,7 +5430,7 @@ export function createDispatchBundle(
5274
5430
  }
5275
5431
  // Requests carrying lineage are internal attempts (retry or nested
5276
5432
  // orchestration) and retain the per-attempt handle contract.
5277
- if (req.lineage) return handle;
5433
+ if (req.lineage) return { ...handle, finalPromise: handle.finalPromise.finally(() => writerLease?.release()) };
5278
5434
 
5279
5435
  const assignment = assignments.open(handle.runId, assignmentPolicyFor(handle.effectiveRequest));
5280
5436
  persistAssignment(registerAssignment(assignment.id), `${assignment.id}:open`);
@@ -5287,9 +5443,10 @@ export function createDispatchBundle(
5287
5443
  const reservation = req.reservation;
5288
5444
  const terminal =
5289
5445
  reservation === undefined
5290
- ? assignment.terminal
5446
+ ? assignment.terminal.finally(() => writerLease?.release())
5291
5447
  : assignment.terminal.finally(() => {
5292
5448
  releaseDispatchReservationMember(reservation.ownerId, reservation.memberId, now());
5449
+ writerLease?.release();
5293
5450
  });
5294
5451
  return { runId: handle.runId, events: assignment.events, finalPromise: terminal };
5295
5452
  }
@@ -5306,6 +5463,11 @@ export function createDispatchBundle(
5306
5463
  req = validation.restore(validated.spec);
5307
5464
 
5308
5465
  if (req.delegationAgentId) {
5466
+ if (req.budget !== undefined) {
5467
+ throw new Error(
5468
+ "dispatch: budget envelopes cannot be enforced on an ACP delegation target; dispatch to a native or claude-sdk worker",
5469
+ );
5470
+ }
5309
5471
  const protectedArtifactState = getProtectedArtifactState();
5310
5472
  assertProtectedArtifactsEnforceable("acp-delegation", false, protectedArtifactState);
5311
5473
  if (req.responseSchema !== undefined) {
@@ -5369,6 +5531,7 @@ export function createDispatchBundle(
5369
5531
  );
5370
5532
  assertPostRuntimeToolCompatibility(req.agentId, agentSpec, effectiveTools, target);
5371
5533
  assertRuntimeCanHonorWorkerPermissionMode(target.runtime, settings?.workers.onPermission ?? "deny");
5534
+ assertWorkerBudgetEnforceable(target.runtime, agentSpec.budget !== null || req.budget !== undefined);
5372
5535
  assertResponseSchemaEnforceable(target.runtime, target.modelCapabilities, req.responseSchema, effectiveTools.length);
5373
5536
  assertWriteRootsEnforceable(target.runtime, req.writeRoots);
5374
5537
  assertProtectedArtifactsEnforceable(
@@ -5376,6 +5539,13 @@ export function createDispatchBundle(
5376
5539
  target.runtime.kind !== "subprocess",
5377
5540
  getProtectedArtifactState(),
5378
5541
  );
5542
+ resolveEffectiveWorkerBudget({
5543
+ req,
5544
+ recipeId: recipe.id,
5545
+ declared: agentSpec.budget,
5546
+ allowedTools: effectiveTools,
5547
+ settings,
5548
+ });
5379
5549
  return {
5380
5550
  agentId: req.agentId,
5381
5551
  specFingerprint: agentSpecFingerprint(agentSpec),
@@ -5660,6 +5830,137 @@ export function createDispatchBundle(
5660
5830
  };
5661
5831
  }
5662
5832
 
5833
+ async function sealCouncilSynthesis(input: {
5834
+ group: string;
5835
+ round: number;
5836
+ kind: "none" | "vote";
5837
+ text: string;
5838
+ subjects: ReadonlyArray<{ runId: string; digest: string | null }>;
5839
+ template: RunReceipt;
5840
+ }): Promise<RunReceipt> {
5841
+ const l = requireLedger();
5842
+ const runId = newRunId();
5843
+ const task = `Council ${input.kind} synthesis`;
5844
+ // The synthesis is the council's own verdict, filed under the origin the
5845
+ // council was asked from: an internal origin would keep it out of the
5846
+ // transcript worker fold, and with it out of /share.
5847
+ const origin = input.template.requestOrigin ?? "agent";
5848
+ const gate = { role: "synthesis" as const, group: input.group, cycle: input.round, subjects: [...input.subjects] };
5849
+ const council = { group: input.group, label: "synthesis", round: input.round };
5850
+ const created = l.create({
5851
+ id: runId,
5852
+ agentId: "council-synthesis",
5853
+ executionRole: "judge",
5854
+ requestOrigin: origin,
5855
+ task,
5856
+ targetId: input.template.targetId,
5857
+ wireModelId: input.template.wireModelId,
5858
+ runtimeId: input.template.runtimeId,
5859
+ runtimeKind: input.template.runtimeKind,
5860
+ sessionId: input.template.sessionId,
5861
+ cwd: input.template.reproducibility?.cwd ?? process.cwd(),
5862
+ });
5863
+ const endedAt = new Date().toISOString();
5864
+ l.update(runId, {
5865
+ status: "completed",
5866
+ outcome: "succeeded",
5867
+ endedAt,
5868
+ exitCode: 0,
5869
+ gate,
5870
+ council,
5871
+ ...(input.template.plan !== undefined ? { plan: input.template.plan } : {}),
5872
+ });
5873
+ const receipt = l.recordReceipt(runId, {
5874
+ runId,
5875
+ agentId: "council-synthesis",
5876
+ executionRole: "judge",
5877
+ requestOrigin: origin,
5878
+ task,
5879
+ targetId: input.template.targetId,
5880
+ wireModelId: input.template.wireModelId,
5881
+ runtimeId: input.template.runtimeId,
5882
+ runtimeKind: input.template.runtimeKind,
5883
+ startedAt: created.startedAt,
5884
+ endedAt,
5885
+ outcome: "succeeded",
5886
+ outcomeDetail: null,
5887
+ exitCode: 0,
5888
+ tokenCount: 0,
5889
+ inputTokenCount: 0,
5890
+ outputTokenCount: 0,
5891
+ reasoningTokenCount: 0,
5892
+ cacheReadTokenCount: 0,
5893
+ cacheWriteTokenCount: 0,
5894
+ output: { state: "final", text: input.text, bytes: Buffer.byteLength(input.text, "utf8"), truncated: false },
5895
+ costUsd: 0,
5896
+ costProvenance: "unknown",
5897
+ compiledPromptHash: null,
5898
+ staticCompositionHash: null,
5899
+ clioVersion: readClioVersion(),
5900
+ piMonoVersion: readPiMonoVersion(),
5901
+ platform: process.platform,
5902
+ nodeVersion: process.version,
5903
+ toolCalls: 0,
5904
+ toolStats: [],
5905
+ verification: { state: "unverified", basis: "no-validation-tool" },
5906
+ routingIntent: defaultRoutingIntent({}),
5907
+ quality: createRunReceiptQuality({ runtimeEnforceable: false, enforcementPassed: null, resultContract: null }),
5908
+ reproducibility: collectReproducibility(input.template.reproducibility?.cwd ?? process.cwd(), null),
5909
+ sessionId: input.template.sessionId,
5910
+ gate,
5911
+ council,
5912
+ ...(input.template.plan !== undefined ? { plan: input.template.plan } : {}),
5913
+ });
5914
+ await l.persist();
5915
+ // The synthesis never ran as a worker, so nothing else publishes its
5916
+ // lifecycle. The Fleet Runs board and /share are built from these
5917
+ // events, and a council whose synthesis they cannot see is a council
5918
+ // whose verdict the operator cannot read or share.
5919
+ const identity: DispatchRunIdentity = {
5920
+ runId,
5921
+ agentId: "council-synthesis",
5922
+ task,
5923
+ requestOrigin: origin,
5924
+ targetId: receipt.targetId,
5925
+ wireModelId: receipt.wireModelId,
5926
+ runtimeId: receipt.runtimeId,
5927
+ runtimeKind: receipt.runtimeKind,
5928
+ gate: { role: gate.role, cycle: gate.cycle },
5929
+ council,
5930
+ };
5931
+ context.bus.emit(BusChannels.DispatchEnqueued, { ...identity, requestOrigin: origin });
5932
+ context.bus.emit(BusChannels.DispatchStarted, {
5933
+ ...identity,
5934
+ requestOrigin: origin,
5935
+ pid: null,
5936
+ assignmentId: runId,
5937
+ attempt: 0,
5938
+ });
5939
+ context.bus.emit(BusChannels.DispatchCompleted, {
5940
+ ...identity,
5941
+ requestOrigin: origin,
5942
+ outcome: "succeeded",
5943
+ outcomeCode: null,
5944
+ outcomeDetail: null,
5945
+ lineage: input.template.lineage ?? { parentRunId: null, rootRunId: runId, attempt: 0, depth: 0 },
5946
+ tokenCount: 0,
5947
+ inputTokenCount: 0,
5948
+ outputTokenCount: 0,
5949
+ cacheReadTokenCount: 0,
5950
+ cacheWriteTokenCount: 0,
5951
+ reasoningTokenCount: 0,
5952
+ staticShellHash: null,
5953
+ sessionShellHash: null,
5954
+ dynamicHash: null,
5955
+ costUsd: 0,
5956
+ costProvenance: "unknown",
5957
+ durationMs: 0,
5958
+ exitCode: 0,
5959
+ toolActivity: null,
5960
+ });
5961
+ return receipt;
5962
+ }
5963
+
5663
5964
  const extension: DomainExtension = {
5664
5965
  async start() {
5665
5966
  // No in-memory executor survives a process restart, so every active
@@ -5773,6 +6074,7 @@ export function createDispatchBundle(
5773
6074
  runId: run.runId,
5774
6075
  agentId: run.agentId,
5775
6076
  task: run.task,
6077
+ ...(run.budget !== undefined ? { budget: run.budget } : {}),
5776
6078
  runtimeKind: run.runtimeKind,
5777
6079
  outcomePhase: run.stallKilled ? "terminating" : run.aborted ? "aborting" : "running",
5778
6080
  heartbeat,
@@ -5893,6 +6195,7 @@ export function createDispatchBundle(
5893
6195
  protectedArtifactState: () => getProtectedArtifactState(),
5894
6196
  dispatch,
5895
6197
  dispatchBatch,
6198
+ sealCouncilSynthesis,
5896
6199
  listRuns(status) {
5897
6200
  const l = requireLedger();
5898
6201
  return status ? l.list({ status }) : l.list();