@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
@@ -15,6 +15,7 @@ import { basename, join } from "node:path";
15
15
  import { Type } from "typebox";
16
16
  import { Value } from "typebox/value";
17
17
  import { resolvePackageRoot } from "../../core/package-root.js";
18
+ import { clioConfigDir } from "../../core/xdg.js";
18
19
  import { type FleetCommandRegistry, loadFleetCommands } from "./fleet-commands.js";
19
20
  import { parseFrontmatter } from "./frontmatter.js";
20
21
  import { normalizeWriteBoundary, WRITE_BOUNDARY_MAX_ENTRIES } from "./write-boundary.js";
@@ -35,6 +36,7 @@ export type FleetOnFailure = "stop" | "continue";
35
36
  * allowlist stated out loud.
36
37
  */
37
38
  export const FLEET_WRITE_BOUNDARY_VERSION = 4;
39
+ export const FLEET_DYNAMIC_STEP_VERSION = 5;
38
40
 
39
41
  /**
40
42
  * Upper bound on any declared loop. A loop is bounded in the contract, and the
@@ -63,6 +65,34 @@ export interface FleetContractAgentStep {
63
65
  scope: FleetStepScope;
64
66
  dependencies: ReadonlyArray<string>;
65
67
  writes?: ReadonlyArray<string>;
68
+ target?: string;
69
+ profile?: string;
70
+ }
71
+
72
+ export interface FleetContractGateStep {
73
+ kind: "gate";
74
+ id: string;
75
+ agent: string;
76
+ path: string;
77
+ run: string;
78
+ scope: "workspace";
79
+ dependencies: ReadonlyArray<string>;
80
+ target?: string;
81
+ profile?: string;
82
+ }
83
+
84
+ export interface FleetContractPlanStep {
85
+ kind: "plan";
86
+ id: string;
87
+ agent: string;
88
+ roster: ReadonlyArray<string>;
89
+ maxTasks: number;
90
+ proposals: boolean;
91
+ scope: FleetStepScope;
92
+ dependencies: ReadonlyArray<string>;
93
+ writes?: ReadonlyArray<string>;
94
+ target?: string;
95
+ profile?: string;
66
96
  }
67
97
 
68
98
  /**
@@ -89,7 +119,15 @@ export interface FleetContractCodeStep {
89
119
  /** The verification half of a loop: the question that decides continuation. */
90
120
  export type FleetContractLoopCheck =
91
121
  | { kind: "code"; command: string; scope: FleetStepScope; writes?: ReadonlyArray<string> }
92
- | { kind: "agent"; agent: string; scope: FleetStepScope; writes?: ReadonlyArray<string> };
122
+ | {
123
+ kind: "agent";
124
+ agent: string;
125
+ scope: FleetStepScope;
126
+ writes?: ReadonlyArray<string>;
127
+ target?: string;
128
+ profile?: string;
129
+ }
130
+ | { kind: "gate"; gate: string };
93
131
 
94
132
  /** The repair half. Always an agent: a deterministic repair is just a check. */
95
133
  export interface FleetContractLoopRepair {
@@ -97,6 +135,8 @@ export interface FleetContractLoopRepair {
97
135
  agent: string;
98
136
  scope: FleetStepScope;
99
137
  writes?: ReadonlyArray<string>;
138
+ target?: string;
139
+ profile?: string;
100
140
  }
101
141
 
102
142
  /**
@@ -120,7 +160,12 @@ export interface FleetContractLoopStep {
120
160
  repair: FleetContractLoopRepair;
121
161
  }
122
162
 
123
- export type FleetContractStep = FleetContractAgentStep | FleetContractCodeStep | FleetContractLoopStep;
163
+ export type FleetContractStep =
164
+ | FleetContractAgentStep
165
+ | FleetContractCodeStep
166
+ | FleetContractLoopStep
167
+ | FleetContractGateStep
168
+ | FleetContractPlanStep;
124
169
 
125
170
  /**
126
171
  * Contract schema version.
@@ -137,7 +182,7 @@ export type FleetContractStep = FleetContractAgentStep | FleetContractCodeStep |
137
182
  * A version literal gives that reader a clear refusal instead of an obscure
138
183
  * unknown-property error deep in a step.
139
184
  */
140
- export type FleetContractVersion = 1 | 2 | 3 | 4;
185
+ export type FleetContractVersion = 1 | 2 | 3 | 4 | 5;
141
186
 
142
187
  export interface FleetContract {
143
188
  version: FleetContractVersion;
@@ -147,12 +192,13 @@ export interface FleetContract {
147
192
  maxWorkers: number;
148
193
  budgetUsd: number | null;
149
194
  onFailure: FleetOnFailure;
195
+ writers?: 1;
150
196
  /** Prompt template body with unresolved {{var}} placeholders. */
151
197
  body: string;
152
198
  path: string;
153
199
  }
154
200
 
155
- export type FleetContractSource = "builtin" | "project";
201
+ export type FleetContractSource = "builtin" | "user" | "project";
156
202
 
157
203
  export interface FleetContractListing {
158
204
  name: string;
@@ -183,6 +229,12 @@ function writesSchema(version: FleetContractVersion) {
183
229
  : {};
184
230
  }
185
231
 
232
+ function routeSchema(version: FleetContractVersion) {
233
+ return version >= FLEET_DYNAMIC_STEP_VERSION
234
+ ? { target: Type.Optional(Type.String({ minLength: 1 })), profile: Type.Optional(Type.String({ minLength: 1 })) }
235
+ : {};
236
+ }
237
+
186
238
  function agentStepSchema(version: FleetContractVersion) {
187
239
  return Type.Object(
188
240
  {
@@ -192,6 +244,41 @@ function agentStepSchema(version: FleetContractVersion) {
192
244
  scope: FleetScopeSchema,
193
245
  dependencies: Type.Array(Type.String({ minLength: 1 })),
194
246
  ...writesSchema(version),
247
+ ...routeSchema(version),
248
+ },
249
+ { additionalProperties: false },
250
+ );
251
+ }
252
+
253
+ function gateStepSchema() {
254
+ return Type.Object(
255
+ {
256
+ kind: Type.Literal("gate"),
257
+ id: Type.String({ minLength: 1 }),
258
+ agent: Type.String({ minLength: 1 }),
259
+ path: Type.String({ minLength: 1 }),
260
+ run: Type.String({ minLength: 1 }),
261
+ scope: Type.Optional(Type.Literal("workspace")),
262
+ dependencies: Type.Array(Type.String({ minLength: 1 })),
263
+ ...routeSchema(5),
264
+ },
265
+ { additionalProperties: false },
266
+ );
267
+ }
268
+
269
+ function planStepSchema() {
270
+ return Type.Object(
271
+ {
272
+ kind: Type.Literal("plan"),
273
+ id: Type.String({ minLength: 1 }),
274
+ agent: Type.Optional(Type.String({ minLength: 1 })),
275
+ roster: Type.Array(Type.String({ minLength: 1 }), { minItems: 1, maxItems: 16 }),
276
+ maxTasks: Type.Integer({ minimum: 1, maximum: 16 }),
277
+ proposals: Type.Optional(Type.Boolean()),
278
+ scope: FleetScopeSchema,
279
+ dependencies: Type.Array(Type.String({ minLength: 1 })),
280
+ ...writesSchema(5),
281
+ ...routeSchema(5),
195
282
  },
196
283
  { additionalProperties: false },
197
284
  );
@@ -230,12 +317,21 @@ function loopStepSchema(version: FleetContractVersion) {
230
317
  },
231
318
  { additionalProperties: false },
232
319
  ),
320
+ ...(version >= FLEET_DYNAMIC_STEP_VERSION
321
+ ? [
322
+ Type.Object(
323
+ { kind: Type.Literal("gate"), gate: Type.String({ minLength: 1 }) },
324
+ { additionalProperties: false },
325
+ ),
326
+ ]
327
+ : []),
233
328
  Type.Object(
234
329
  {
235
330
  kind: Type.Literal("agent"),
236
331
  agent: Type.String({ minLength: 1 }),
237
332
  scope: FleetScopeSchema,
238
333
  ...writesSchema(version),
334
+ ...routeSchema(version),
239
335
  },
240
336
  { additionalProperties: false },
241
337
  ),
@@ -246,6 +342,7 @@ function loopStepSchema(version: FleetContractVersion) {
246
342
  agent: Type.String({ minLength: 1 }),
247
343
  scope: FleetScopeSchema,
248
344
  ...writesSchema(version),
345
+ ...routeSchema(version),
249
346
  },
250
347
  { additionalProperties: false },
251
348
  ),
@@ -257,6 +354,15 @@ function loopStepSchema(version: FleetContractVersion) {
257
354
  function stepSchema(version: FleetContractVersion) {
258
355
  if (version === 1) return agentStepSchema(1);
259
356
  if (version === 2) return Type.Union([agentStepSchema(2), codeStepSchema(2)]);
357
+ if (version === 5) {
358
+ return Type.Union([
359
+ agentStepSchema(version),
360
+ codeStepSchema(version),
361
+ loopStepSchema(version),
362
+ gateStepSchema(),
363
+ planStepSchema(),
364
+ ]);
365
+ }
260
366
  return Type.Union([agentStepSchema(version), codeStepSchema(version), loopStepSchema(version)]);
261
367
  }
262
368
 
@@ -270,6 +376,7 @@ function frontmatterSchema(version: FleetContractVersion) {
270
376
  maxWorkers: Type.Integer({ minimum: 1 }),
271
377
  budgetUsd: Type.Optional(Type.Number()),
272
378
  onFailure: Type.Union([Type.Literal("stop"), Type.Literal("continue")]),
379
+ ...(version >= FLEET_DYNAMIC_STEP_VERSION ? { writers: Type.Optional(Type.Literal(1)) } : {}),
273
380
  },
274
381
  { additionalProperties: false },
275
382
  );
@@ -280,11 +387,12 @@ const SCHEMAS: Readonly<Record<FleetContractVersion, ReturnType<typeof frontmatt
280
387
  2: frontmatterSchema(2),
281
388
  3: frontmatterSchema(3),
282
389
  4: frontmatterSchema(4),
390
+ 5: frontmatterSchema(5),
283
391
  };
284
392
 
285
393
  function contractVersion(frontmatter: Record<string, unknown>): FleetContractVersion | null {
286
394
  const value = frontmatter.version;
287
- return value === 1 || value === 2 || value === 3 || value === 4 ? value : null;
395
+ return value === 1 || value === 2 || value === 3 || value === 4 || value === 5 ? value : null;
288
396
  }
289
397
 
290
398
  function firstSchemaError(frontmatter: Record<string, unknown>, version: FleetContractVersion): string | null {
@@ -299,15 +407,38 @@ function fleetsDir(cwd: string): string {
299
407
  }
300
408
 
301
409
  type RawStep = {
302
- kind?: "agent" | "code" | "loop";
410
+ kind?: "agent" | "code" | "loop" | "gate" | "plan";
303
411
  id: string;
304
412
  agent?: string;
305
413
  command?: string;
306
414
  commitFrom?: string[];
307
415
  writes?: string[];
308
416
  maxAttempts?: number;
309
- check?: { kind: "code" | "agent"; command?: string; agent?: string; scope: FleetStepScope; writes?: string[] };
310
- repair?: { kind?: "agent"; agent: string; scope: FleetStepScope; writes?: string[] };
417
+ check?: {
418
+ kind: "code" | "agent" | "gate";
419
+ command?: string;
420
+ agent?: string;
421
+ gate?: string;
422
+ scope: FleetStepScope;
423
+ writes?: string[];
424
+ target?: string;
425
+ profile?: string;
426
+ };
427
+ repair?: {
428
+ kind?: "agent";
429
+ agent: string;
430
+ scope: FleetStepScope;
431
+ writes?: string[];
432
+ target?: string;
433
+ profile?: string;
434
+ };
435
+ target?: string;
436
+ profile?: string;
437
+ path?: string;
438
+ run?: string;
439
+ roster?: string[];
440
+ maxTasks?: number;
441
+ proposals?: boolean;
311
442
  } & Pick<FleetContractAgentStep, "scope"> & { dependencies: string[] };
312
443
 
313
444
  /** Normalized declaration, or nothing when this version declares no boundary. */
@@ -316,6 +447,36 @@ function normalizedWrites(writes: string[] | undefined): { writes?: ReadonlyArra
316
447
  }
317
448
 
318
449
  function normalizeStep(step: RawStep): FleetContractStep {
450
+ const route = (value: { target?: string; profile?: string }): { target?: string; profile?: string } => ({
451
+ ...(value.target !== undefined ? { target: value.target } : {}),
452
+ ...(value.profile !== undefined ? { profile: value.profile } : {}),
453
+ });
454
+ if (step.kind === "gate") {
455
+ return {
456
+ kind: "gate",
457
+ id: step.id,
458
+ agent: step.agent ?? "",
459
+ path: step.path ?? "",
460
+ run: step.run ?? "",
461
+ scope: "workspace",
462
+ dependencies: [...step.dependencies],
463
+ ...route(step),
464
+ };
465
+ }
466
+ if (step.kind === "plan") {
467
+ return {
468
+ kind: "plan",
469
+ id: step.id,
470
+ agent: step.agent ?? "architect",
471
+ roster: [...(step.roster ?? [])],
472
+ maxTasks: step.maxTasks ?? 0,
473
+ proposals: step.proposals ?? false,
474
+ scope: step.scope,
475
+ dependencies: [...step.dependencies],
476
+ ...normalizedWrites(step.writes),
477
+ ...route(step),
478
+ };
479
+ }
319
480
  if (step.kind === "loop") {
320
481
  const check = step.check as NonNullable<RawStep["check"]>;
321
482
  const repair = step.repair as NonNullable<RawStep["repair"]>;
@@ -327,8 +488,22 @@ function normalizeStep(step: RawStep): FleetContractStep {
327
488
  check:
328
489
  check.kind === "code"
329
490
  ? { kind: "code", command: check.command ?? "", scope: check.scope, ...normalizedWrites(check.writes) }
330
- : { kind: "agent", agent: check.agent ?? "", scope: check.scope, ...normalizedWrites(check.writes) },
331
- repair: { kind: "agent", agent: repair.agent, scope: repair.scope, ...normalizedWrites(repair.writes) },
491
+ : check.kind === "gate"
492
+ ? { kind: "gate", gate: check.gate ?? "" }
493
+ : {
494
+ kind: "agent",
495
+ agent: check.agent ?? "",
496
+ scope: check.scope,
497
+ ...normalizedWrites(check.writes),
498
+ ...route(check),
499
+ },
500
+ repair: {
501
+ kind: "agent",
502
+ agent: repair.agent,
503
+ scope: repair.scope,
504
+ ...normalizedWrites(repair.writes),
505
+ ...route(repair),
506
+ },
332
507
  };
333
508
  }
334
509
  if (step.kind === "code") {
@@ -349,6 +524,7 @@ function normalizeStep(step: RawStep): FleetContractStep {
349
524
  scope: step.scope,
350
525
  dependencies: [...step.dependencies],
351
526
  ...normalizedWrites(step.writes),
527
+ ...route(step),
352
528
  };
353
529
  }
354
530
 
@@ -406,6 +582,13 @@ export function validateFleetGraph(contract: Pick<FleetContract, "steps" | "path
406
582
  }
407
583
  }
408
584
  for (const step of contract.steps) {
585
+ if (step.kind === "loop" && step.check.kind === "gate") {
586
+ const gateId = step.check.gate;
587
+ const gate = contract.steps.find((candidate) => candidate.id === gateId);
588
+ if (gate?.kind !== "gate") {
589
+ throw new Error(`fleet contract ${contract.path}: loop '${step.id}' names unknown gate '${gateId}'`);
590
+ }
591
+ }
409
592
  for (const dependency of step.dependencies) {
410
593
  if (dependency === step.id) throw new Error(`fleet contract ${contract.path}: step '${step.id}' depends on itself`);
411
594
  if (!declared.has(dependency)) {
@@ -484,10 +667,18 @@ export function fleetStepBoundaries(contract: Pick<FleetContract, "steps" | "ver
484
667
  };
485
668
  for (const step of contract.steps) {
486
669
  if (step.kind === "loop") {
487
- add(`${step.id}.check`, step.check.scope, step.check.writes);
670
+ if (step.check.kind === "gate") {
671
+ const gateId = step.check.gate;
672
+ const gate = contract.steps.find((candidate) => candidate.id === gateId);
673
+ if (gate?.kind === "gate") add(`${step.id}.check`, "workspace", [gate.path]);
674
+ } else add(`${step.id}.check`, step.check.scope, step.check.writes);
488
675
  add(`${step.id}.repair`, step.repair.scope, step.repair.writes);
489
676
  continue;
490
677
  }
678
+ if (step.kind === "gate") {
679
+ add(step.id, "workspace", [step.path]);
680
+ continue;
681
+ }
491
682
  add(step.id, step.scope, step.writes);
492
683
  }
493
684
  return boundaries;
@@ -515,10 +706,14 @@ function validateWriteBoundaries(contract: Pick<FleetContract, "steps" | "versio
515
706
  const declared: Array<{ id: string; scope: FleetStepScope; writes: ReadonlyArray<string> | undefined }> =
516
707
  step.kind === "loop"
517
708
  ? [
518
- { id: `${step.id}.check`, scope: step.check.scope, writes: step.check.writes },
709
+ ...(step.check.kind === "gate"
710
+ ? []
711
+ : [{ id: `${step.id}.check`, scope: step.check.scope, writes: step.check.writes }]),
519
712
  { id: `${step.id}.repair`, scope: step.repair.scope, writes: step.repair.writes },
520
713
  ]
521
- : [{ id: step.id, scope: step.scope, writes: step.writes }];
714
+ : step.kind === "gate"
715
+ ? []
716
+ : [{ id: step.id, scope: step.scope, writes: step.writes }];
522
717
  for (const position of declared) {
523
718
  if (position.scope === "readonly" && position.writes !== undefined) {
524
719
  throw new Error(
@@ -559,11 +754,10 @@ export function parseFleetContract(raw: string, sourcePath: string): FleetContra
559
754
  const { frontmatter, body } = parseFrontmatter(raw, sourcePath);
560
755
  const version = contractVersion(frontmatter);
561
756
  if (version === null) {
562
- throw new Error(
563
- `fleet contract ${sourcePath}: version must be 1 (agent steps), 2 (agent and code steps), 3 (adds bounded loops and commit steps), or 4 (adds enforced write boundaries)`,
564
- );
757
+ throw new Error(`fleet contract ${sourcePath}: version must be 1, 2, 3, 4, or 5`);
565
758
  }
566
759
  if (version < FLEET_WRITE_BOUNDARY_VERSION) assertNoWritesBefore(frontmatter, sourcePath, version);
760
+ if (version < FLEET_DYNAMIC_STEP_VERSION) assertNoV5FieldsBefore(frontmatter, sourcePath, version);
567
761
  const schemaError = firstSchemaError(frontmatter, version);
568
762
  if (schemaError !== null) {
569
763
  throw new Error(`fleet contract ${sourcePath}: ${schemaError}`);
@@ -576,6 +770,7 @@ export function parseFleetContract(raw: string, sourcePath: string): FleetContra
576
770
  maxWorkers: number;
577
771
  budgetUsd?: number;
578
772
  onFailure: FleetOnFailure;
773
+ writers?: 1;
579
774
  };
580
775
  if (fm.budgetUsd !== undefined && !(fm.budgetUsd > 0)) {
581
776
  throw new Error(`fleet contract ${sourcePath}: budgetUsd must be a positive number`);
@@ -592,14 +787,49 @@ export function parseFleetContract(raw: string, sourcePath: string): FleetContra
592
787
  maxWorkers: fm.maxWorkers,
593
788
  budgetUsd: fm.budgetUsd ?? null,
594
789
  onFailure: fm.onFailure,
790
+ ...(fm.writers === 1 ? { writers: 1 as const } : {}),
595
791
  body: trimmedBody,
596
792
  path: sourcePath,
597
793
  };
598
794
  validateFleetGraph(contract);
599
795
  validateWriteBoundaries(contract);
796
+ validateV5Declarations(contract);
600
797
  return contract;
601
798
  }
602
799
 
800
+ function validateV5Declarations(contract: FleetContract): void {
801
+ if (contract.version < FLEET_DYNAMIC_STEP_VERSION) return;
802
+ const route = (id: string, value: { target?: string; profile?: string }): void => {
803
+ if (value.target !== undefined && value.profile !== undefined) {
804
+ throw new Error(`fleet contract ${contract.path}: step '${id}' may declare target or profile, never both`);
805
+ }
806
+ };
807
+ for (const step of contract.steps) {
808
+ if (step.kind === "agent" || step.kind === "plan" || step.kind === "gate") route(step.id, step);
809
+ if (step.kind === "plan" && new Set(step.roster).size !== step.roster.length) {
810
+ throw new Error(`fleet contract ${contract.path}: plan step '${step.id}' roster contains duplicate agents`);
811
+ }
812
+ if (step.kind === "gate") {
813
+ let normalized: ReadonlyArray<string>;
814
+ try {
815
+ normalized = normalizeWriteBoundary([step.path]);
816
+ } catch (error) {
817
+ throw new Error(
818
+ `fleet contract ${contract.path}: gate '${step.id}' path is invalid: ${error instanceof Error ? error.message : String(error)}`,
819
+ );
820
+ }
821
+ if (normalized[0] !== step.path.replaceAll("\\", "/")) {
822
+ throw new Error(
823
+ `fleet contract ${contract.path}: gate '${step.id}' path must be normalized and repository-relative`,
824
+ );
825
+ }
826
+ }
827
+ if (step.kind !== "loop") continue;
828
+ if (step.check.kind === "agent") route(`${step.id}.check`, step.check);
829
+ route(`${step.id}.repair`, step.repair);
830
+ }
831
+ }
832
+
603
833
  /**
604
834
  * A `writes` key under an older version is refused by name rather than as an
605
835
  * unknown property, because the two readings are far apart: the author wrote a
@@ -619,6 +849,34 @@ function assertNoWritesBefore(frontmatter: Record<string, unknown>, sourcePath:
619
849
  }
620
850
  }
621
851
 
852
+ function assertNoV5FieldsBefore(frontmatter: Record<string, unknown>, sourcePath: string, version: number): void {
853
+ const forbidden = ["target", "profile"] as const;
854
+ if ("writers" in frontmatter) {
855
+ throw new Error(
856
+ `fleet contract ${sourcePath}: 'writers' requires contract version ${FLEET_DYNAMIC_STEP_VERSION}; this contract declares version ${version}`,
857
+ );
858
+ }
859
+ for (const value of Array.isArray(frontmatter.steps) ? frontmatter.steps : []) {
860
+ if (typeof value !== "object" || value === null) continue;
861
+ const step = value as Record<string, unknown>;
862
+ if (step.kind === "plan" || step.kind === "gate") {
863
+ throw new Error(
864
+ `fleet contract ${sourcePath}: kind '${String(step.kind)}' requires contract version ${FLEET_DYNAMIC_STEP_VERSION}; this contract declares version ${version}`,
865
+ );
866
+ }
867
+ for (const candidate of [step, step.check, step.repair]) {
868
+ if (typeof candidate !== "object" || candidate === null) continue;
869
+ for (const field of forbidden) {
870
+ if (field in candidate) {
871
+ throw new Error(
872
+ `fleet contract ${sourcePath}: '${field}' requires contract version ${FLEET_DYNAMIC_STEP_VERSION}; this contract declares version ${version}`,
873
+ );
874
+ }
875
+ }
876
+ }
877
+ }
878
+ }
879
+
622
880
  /** Every loop in the contract, in declaration order. */
623
881
  export function fleetLoopSteps(contract: FleetContract): FleetContractLoopStep[] {
624
882
  return contract.steps.filter((step): step is FleetContractLoopStep => step.kind === "loop");
@@ -634,6 +892,7 @@ export function fleetCodeSteps(contract: FleetContract): Array<{ id: string; com
634
892
  const steps: Array<{ id: string; command: string }> = [];
635
893
  for (const step of contract.steps) {
636
894
  if (step.kind === "code") steps.push({ id: step.id, command: step.command });
895
+ else if (step.kind === "gate") steps.push({ id: step.id, command: step.run });
637
896
  else if (step.kind === "loop" && step.check.kind === "code") {
638
897
  steps.push({ id: fleetLoopCheckStepId(step.id, 1), command: step.check.command });
639
898
  }
@@ -702,6 +961,8 @@ function builtinFleetsDir(): string {
702
961
  function fleetContractPath(cwd: string, name: string): { path: string; source: FleetContractSource } | null {
703
962
  const projectPath = join(fleetsDir(cwd), `${name}.md`);
704
963
  if (existsSync(projectPath)) return { path: projectPath, source: "project" };
964
+ const userPath = join(clioConfigDir(), "fleets", `${name}.md`);
965
+ if (existsSync(userPath)) return { path: userPath, source: "user" };
705
966
  const builtinPath = join(builtinFleetsDir(), `${name}.md`);
706
967
  if (existsSync(builtinPath)) return { path: builtinPath, source: "builtin" };
707
968
  return null;
@@ -745,6 +1006,7 @@ export function listFleetContracts(cwd: string): FleetContractListing[] {
745
1006
  const listings = new Map<string, FleetContractListing>();
746
1007
  const sources: ReadonlyArray<{ dir: string; source: FleetContractSource }> = [
747
1008
  { dir: builtinFleetsDir(), source: "builtin" },
1009
+ { dir: join(clioConfigDir(), "fleets"), source: "user" },
748
1010
  { dir: fleetsDir(cwd), source: "project" },
749
1011
  ];
750
1012
  for (const { dir, source } of sources) {
@@ -20,10 +20,12 @@ export type {
20
20
  FleetContract,
21
21
  FleetContractAgentStep,
22
22
  FleetContractCodeStep,
23
+ FleetContractGateStep,
23
24
  FleetContractListing,
24
25
  FleetContractLoopCheck,
25
26
  FleetContractLoopRepair,
26
27
  FleetContractLoopStep,
28
+ FleetContractPlanStep,
27
29
  FleetContractSource,
28
30
  FleetContractStep,
29
31
  FleetContractVersion,
@@ -34,6 +36,7 @@ export type {
34
36
  export {
35
37
  FLEET_COMMANDS_REMEDY,
36
38
  FLEET_COMMANDS_REPO_PATH,
39
+ FLEET_DYNAMIC_STEP_VERSION,
37
40
  FLEET_LOOP_MAX_ATTEMPTS,
38
41
  FLEET_WRITE_BOUNDARY_VERSION,
39
42
  FleetCommandRegistryMissingError,
@@ -63,15 +66,26 @@ export { parseAgentBudget } from "./recipe.js";
63
66
  export { parseAgentRecipeSchema, recipeSchemaFieldNames } from "./recipe-schema.js";
64
67
  export type { AgentRecipeDiagnostic } from "./registry.js";
65
68
  export type {
69
+ CouncilReport,
70
+ CouncilReportMember,
71
+ DelegationPlanResult,
72
+ DelegationPlanResultTask,
73
+ OracleResult,
66
74
  ResultAuthorship,
67
75
  ResultContract,
68
76
  ResultContractQuality,
69
77
  ResultContractValidation,
70
78
  ScoutResult,
79
+ VerifierCheck,
80
+ VerifierResult,
71
81
  } from "./result-contract.js";
72
82
  export {
83
+ parseCouncilReport,
84
+ parseDelegationPlanResult,
85
+ parseOracleResult,
73
86
  parseResultContract,
74
87
  parseScoutResult,
88
+ parseVerifierResult,
75
89
  resultContractAuthorship,
76
90
  resultContractDigest,
77
91
  validateRecipeResult,
@@ -9,33 +9,33 @@ import type {
9
9
  AgentProjectContextTier,
10
10
  } from "./spec.js";
11
11
 
12
- /** Authored worker-loop phase policy carried by an agent recipe. */
13
- export interface AgentBudget {
12
+ /** One bounded worker-loop phase policy. */
13
+ export interface AgentBudgetPhase {
14
14
  /** Admitted tool-call boundary before the final-response phase. */
15
15
  toolCalls: number;
16
16
  /** Tail of the admitted boundary reserved for canonical `read` calls. */
17
17
  readReserve: number;
18
+ }
19
+
20
+ /** Authored worker-loop phase policy carried by an agent recipe. */
21
+ export interface AgentBudget extends AgentBudgetPhase {
18
22
  /** Whether reaching the boundary transitions to text-only synthesis. */
19
23
  synthesis: boolean;
24
+ /** Optional upper bound for invocation-level requests. Absence pins the default exactly. */
25
+ maximum?: AgentBudgetPhase;
20
26
  }
21
27
 
22
- const AGENT_BUDGET_KEYS = ["toolCalls", "readReserve", "synthesis"] as const;
28
+ const AGENT_BUDGET_KEYS = ["toolCalls", "readReserve", "synthesis", "maximum"] as const;
23
29
 
24
- /** Strict parser shared by the one recipe schema and direct contract fixtures. */
25
- export function parseAgentBudget(value: unknown, sourcePath: string): AgentBudget | undefined {
26
- if (value === undefined) return undefined;
27
- const prefix = `agent budget: ${sourcePath}: budget`;
30
+ function parseAgentBudgetPhase(value: unknown, prefix: string, relationTarget: string): AgentBudgetPhase {
28
31
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
29
32
  throw new Error(`${prefix} must be a non-null YAML object`);
30
33
  }
31
-
32
34
  const record = value as Record<string, unknown>;
33
35
  for (const key of Object.keys(record)) {
34
- if (!(AGENT_BUDGET_KEYS as ReadonlyArray<string>).includes(key)) {
35
- throw new Error(`${prefix}.${key} is unknown`);
36
- }
36
+ if (key !== "toolCalls" && key !== "readReserve") throw new Error(`${prefix}.${key} is unknown`);
37
37
  }
38
- for (const key of AGENT_BUDGET_KEYS) {
38
+ for (const key of ["toolCalls", "readReserve"] as const) {
39
39
  if (!Object.hasOwn(record, key)) throw new Error(`${prefix}.${key} is required`);
40
40
  }
41
41
 
@@ -50,12 +50,52 @@ export function parseAgentBudget(value: unknown, sourcePath: string): AgentBudge
50
50
  throw new Error(`${prefix}.readReserve must be a finite safe integer`);
51
51
  }
52
52
  if (readReserve < 0) throw new Error(`${prefix}.readReserve must be greater than or equal to 0`);
53
- if (readReserve >= toolCalls) throw new Error(`${prefix}.readReserve must be less than budget.toolCalls`);
53
+ if (readReserve >= toolCalls) throw new Error(`${prefix}.readReserve must be less than ${relationTarget}`);
54
+
55
+ return { toolCalls, readReserve };
56
+ }
57
+
58
+ /** Strict parser shared by the one recipe schema and direct contract fixtures. */
59
+ export function parseAgentBudget(value: unknown, sourcePath: string): AgentBudget | undefined {
60
+ if (value === undefined) return undefined;
61
+ const prefix = `agent budget: ${sourcePath}: budget`;
62
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
63
+ throw new Error(`${prefix} must be a non-null YAML object`);
64
+ }
65
+
66
+ const record = value as Record<string, unknown>;
67
+ for (const key of Object.keys(record)) {
68
+ if (!(AGENT_BUDGET_KEYS as ReadonlyArray<string>).includes(key)) {
69
+ throw new Error(`${prefix}.${key} is unknown`);
70
+ }
71
+ }
72
+ for (const key of ["toolCalls", "readReserve", "synthesis"] as const) {
73
+ if (!Object.hasOwn(record, key)) throw new Error(`${prefix}.${key} is required`);
74
+ }
75
+
76
+ const phase = parseAgentBudgetPhase(
77
+ { toolCalls: record.toolCalls, readReserve: record.readReserve },
78
+ prefix,
79
+ "budget.toolCalls",
80
+ );
54
81
 
55
82
  const synthesis = record.synthesis;
56
83
  if (typeof synthesis !== "boolean") throw new Error(`${prefix}.synthesis must be a boolean`);
57
84
 
58
- return { toolCalls, readReserve, synthesis };
85
+ const maximum =
86
+ record.maximum === undefined
87
+ ? undefined
88
+ : parseAgentBudgetPhase(record.maximum, `${prefix}.maximum`, "budget.maximum.toolCalls");
89
+ if (maximum !== undefined) {
90
+ if (maximum.toolCalls < phase.toolCalls) {
91
+ throw new Error(`${prefix}.maximum.toolCalls must be greater than or equal to budget.toolCalls`);
92
+ }
93
+ if (maximum.readReserve < phase.readReserve) {
94
+ throw new Error(`${prefix}.maximum.readReserve must be greater than or equal to budget.readReserve`);
95
+ }
96
+ }
97
+
98
+ return { ...phase, synthesis, ...(maximum === undefined ? {} : { maximum }) };
59
99
  }
60
100
 
61
101
  export interface AgentToolAnyOfRequirement {