@iowarp/clio-coder 0.3.6 → 0.3.8

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 (323) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +22 -6
  3. package/dist/{acp-2BEHC4DL.js → acp-U67UHUK2.js} +14 -14
  4. package/dist/{agents-LNNFTM53.js → agents-YU6SGALZ.js} +42 -35
  5. package/dist/assets/codewiki.json +1 -1
  6. package/dist/{auth-KXXFI2VS.js → auth-5ZPJOIVG.js} +32 -24
  7. package/dist/builtins-C6JMZVV6.js +17 -0
  8. package/dist/{chunk-E25LMLRW.js → chunk-26LEYJZH.js} +2 -2
  9. package/dist/{chunk-TSHXZTOQ.js → chunk-2HEJ2F35.js} +5 -5
  10. package/dist/{chunk-PBTHKCPN.js → chunk-2HFZQUHL.js} +7 -7
  11. package/dist/{chunk-FO5ZOVUY.js → chunk-3BINW3FP.js} +5 -5
  12. package/dist/{chunk-4OC57DA6.js → chunk-4DGYLA73.js} +53 -2
  13. package/dist/{chunk-CKXWIANG.js → chunk-4SPRNWDE.js} +18 -16
  14. package/dist/{chunk-E2ER4LJF.js → chunk-5C3AQNDW.js} +25 -1
  15. package/dist/{chunk-XF5N4U5A.js → chunk-5DHKRSMQ.js} +9 -8
  16. package/dist/{chunk-43AOLP7E.js → chunk-5FR74PWO.js} +2 -1
  17. package/dist/{chunk-EKY57CSP.js → chunk-5H3GB5BO.js} +68 -772
  18. package/dist/{chunk-6XXKFVSN.js → chunk-5Q2VVUKB.js} +4 -4
  19. package/dist/{chunk-DJVECN66.js → chunk-7RFXX52T.js} +295 -3705
  20. package/dist/{chunk-ZXF4XRKW.js → chunk-7RGZWPB6.js} +158 -8
  21. package/dist/{chunk-FYYLNIL5.js → chunk-A2NJGIB3.js} +2 -2
  22. package/dist/{chunk-XXQNGV4M.js → chunk-A3WNZD3P.js} +548 -72
  23. package/dist/{chunk-VEZEGCGW.js → chunk-B5CSFE7B.js} +23 -21
  24. package/dist/{chunk-2SFS6XQE.js → chunk-DGSYXYMX.js} +3 -2
  25. package/dist/chunk-DR52UMZW.js +21 -0
  26. package/dist/{chunk-ZWLZP4ZT.js → chunk-DYIM5TJT.js} +98 -12
  27. package/dist/{chunk-QKMUKYO7.js → chunk-E77JEWSD.js} +270 -125
  28. package/dist/{chunk-LYF7OHWH.js → chunk-EMYUUSFG.js} +12 -467
  29. package/dist/{chunk-4VP4KH3K.js → chunk-EQ63NRB7.js} +8 -8
  30. package/dist/chunk-FBVTI2TJ.js +518 -0
  31. package/dist/{chunk-R46L2BIR.js → chunk-FHJEP5SW.js} +19 -25
  32. package/dist/{chunk-WR67VIZY.js → chunk-GN57SG4G.js} +66 -8
  33. package/dist/{chunk-RD5U66HV.js → chunk-GPIEI3LY.js} +9 -9
  34. package/dist/{chunk-PCZJO5TI.js → chunk-GU2UIAFZ.js} +13 -178
  35. package/dist/chunk-GWS3VEIW.js +195 -0
  36. package/dist/chunk-H7IXIC72.js +103 -0
  37. package/dist/{chunk-3BPUFZDL.js → chunk-HLE42MG7.js} +3 -3
  38. package/dist/{chunk-24I7BN55.js → chunk-IFBNV6H6.js} +3 -3
  39. package/dist/{chunk-QNQHSOLF.js → chunk-IGWKHNIQ.js} +114 -55
  40. package/dist/chunk-IIZWH4XA.js +172 -0
  41. package/dist/{chunk-AD2SYQYC.js → chunk-IJ7RPIYJ.js} +124 -6
  42. package/dist/chunk-J3YUBZWY.js +382 -0
  43. package/dist/{chunk-5JGRAMKL.js → chunk-JOZYP4GM.js} +8 -6
  44. package/dist/{chunk-OH3TOQTB.js → chunk-K4XHGFR5.js} +751 -15
  45. package/dist/{chunk-EYPA3EGJ.js → chunk-KTYTFRMB.js} +178 -14
  46. package/dist/chunk-LU7P4LHA.js +33 -0
  47. package/dist/chunk-ME6CCNFO.js +108 -0
  48. package/dist/chunk-MXKJU4JB.js +1100 -0
  49. package/dist/{chunk-RY3LY4J5.js → chunk-N22QMJKY.js} +21 -18
  50. package/dist/chunk-NMPKI6XL.js +3006 -0
  51. package/dist/chunk-NUGM5KR6.js +165 -0
  52. package/dist/{chunk-22NAGB7X.js → chunk-P43ETTHK.js} +5 -94
  53. package/dist/{chunk-NILBFAPG.js → chunk-PMDBGQSJ.js} +2 -2
  54. package/dist/chunk-PT7HYKEM.js +165 -0
  55. package/dist/chunk-RVG5JXAL.js +41 -0
  56. package/dist/{chunk-GEYXPTRF.js → chunk-RWSI4YD7.js} +2 -2
  57. package/dist/{chunk-4BPJXDWC.js → chunk-TANS5ZJS.js} +35 -19
  58. package/dist/{verifiers-NCBTHHN2.js → chunk-TB5666IT.js} +67 -324
  59. package/dist/{chunk-QM3F2GKX.js → chunk-TLQJPP24.js} +7927 -8088
  60. package/dist/{chunk-G7MUEIGA.js → chunk-TT36MB5S.js} +2 -1
  61. package/dist/chunk-TTHACPOM.js +961 -0
  62. package/dist/{chunk-6US73PDB.js → chunk-TYPGUK6W.js} +7 -7
  63. package/dist/{chunk-MFFY33HR.js → chunk-U6MBIEMB.js} +554 -209
  64. package/dist/chunk-VAWNZU7Z.js +242 -0
  65. package/dist/{chunk-IR4CFBFN.js → chunk-VCBR6CU7.js} +12 -12
  66. package/dist/{chunk-WHJYKASB.js → chunk-VHN4MY6O.js} +2 -2
  67. package/dist/{chunk-XYDYPRZI.js → chunk-VWZOAB7K.js} +10 -10
  68. package/dist/{chunk-ZRGEBJ4T.js → chunk-WLFILSD5.js} +48 -48
  69. package/dist/{chunk-K7T3E2SR.js → chunk-WNIJTQQK.js} +12 -11
  70. package/dist/{chunk-CYQKWTG3.js → chunk-WSB3FPX7.js} +68 -20
  71. package/dist/{chunk-KHSFENX2.js → chunk-WWCZ5F23.js} +116 -14
  72. package/dist/{chunk-XE2VEJHX.js → chunk-WXY7KU3G.js} +2 -2
  73. package/dist/{chunk-PPAMZ32Z.js → chunk-XK56QHLX.js} +6 -1
  74. package/dist/{chunk-KOHPCX4K.js → chunk-XWSF374K.js} +5 -5
  75. package/dist/{chunk-CJUB2JJ2.js → chunk-YS5VLNH5.js} +10 -10
  76. package/dist/{chunk-ZZMN5OM4.js → chunk-ZNLWCMVZ.js} +2 -2
  77. package/dist/{chunk-WHGPSPT5.js → chunk-ZVJ5BLO2.js} +2 -2
  78. package/dist/cli/index.js +33 -31
  79. package/dist/{clio-M2KGYUFZ.js → clio-QVTYJ57A.js} +10 -10
  80. package/dist/{code-nav-GQNL7XA6.js → code-nav-FGGFIE7L.js} +5 -5
  81. package/dist/codewiki/build-worker.js +4 -4
  82. package/dist/{components-5TTYYX6G.js → components-ZFA3SAER.js} +9 -9
  83. package/dist/{config-XUUYQIWO.js → config-LW5IJFQN.js} +65 -55
  84. package/dist/{configure-IHJ7YOMV.js → configure-7XIZCOU4.js} +29 -24
  85. package/dist/{context-75MIWW3U.js → context-L3WL3X7K.js} +54 -43
  86. package/dist/{context-ZQ7SIFJV.js → context-N52ZA626.js} +30 -14
  87. package/dist/{context-74JLXAWD.js → context-Y6Y7QPR6.js} +12 -12
  88. package/dist/{context-clear-GYKWNUML.js → context-clear-MBQRLSDQ.js} +54 -43
  89. package/dist/{context-index-SSR5ECNE.js → context-index-HVMFQHK3.js} +5 -5
  90. package/dist/{context-working-set-UX5KEP4J.js → context-working-set-GS6DSO7F.js} +18 -18
  91. package/dist/{dispatch-runner-GIJBHNFL.js → dispatch-runner-22ZCNOM3.js} +367 -79
  92. package/dist/{docs-6FZSCG5B.js → docs-7LQ23DLM.js} +9 -9
  93. package/dist/{doctor-SVJ5BZCW.js → doctor-M7YEDGAE.js} +27 -23
  94. package/dist/{eval-CG6LLBLD.js → eval-BEC2WHDA.js} +73 -20
  95. package/dist/{evidence-ZYFIEN42.js → evidence-REJUMSKM.js} +70 -59
  96. package/dist/{evolve-QGEXEMDW.js → evolve-PY5ZBA5K.js} +50 -39
  97. package/dist/{extensions-ADGNCJJD.js → extensions-HVKU65YU.js} +7 -7
  98. package/dist/{fleet-S5R4ZOQY.js → fleet-7WZEWRFA.js} +236 -377
  99. package/dist/fleet-commands-UVHWM76J.js +70 -0
  100. package/dist/fleet-graph-6ULH7PES.js +125 -0
  101. package/dist/fleet-new-RDVJLHHH.js +48 -0
  102. package/dist/{fleet-preflight-BHSNPBMH.js → fleet-preflight-J53T6CCE.js} +5 -5
  103. package/dist/fleet-validate-72PC4SLA.js +79 -0
  104. package/dist/{init-5DRU55YR.js → init-OG3TPGQG.js} +69 -57
  105. package/dist/library-CNTMPLRF.js +217 -0
  106. package/dist/{memory-7YKKR6UC.js → memory-6IS7F275.js} +52 -41
  107. package/dist/{models-ZPOLRU2C.js → models-ENRJDA5W.js} +37 -31
  108. package/dist/{monitor-US5F5YGZ.js → monitor-XLDVO7TN.js} +79 -42
  109. package/dist/{orchestrator-E2AL4T5N.js → orchestrator-6KSPYRHA.js} +4126 -762
  110. package/dist/{paths-E7KYAQWE.js → paths-DBXMZMDU.js} +6 -6
  111. package/dist/registry-LG64LTF4.js +11 -0
  112. package/dist/{reset-KZ652EK6.js → reset-RZ4ER727.js} +12 -12
  113. package/dist/{run-SRNBKDWD.js → run-Y2CNK5RU.js} +89 -76
  114. package/dist/{share-CGZE33UP.js → share-A55GYP6Z.js} +37 -13
  115. package/dist/{skills-S2X4DLY5.js → skills-ALC5J6AT.js} +29 -13
  116. package/dist/{skills-eval-W2GGIC4R.js → skills-eval-JPBEBYQU.js} +60 -48
  117. package/dist/support-MIETYA5E.js +38 -0
  118. package/dist/{targets-54SWINWB.js → targets-VGNXIR3S.js} +46 -36
  119. package/dist/{terminal-lease-SAIF2OGY.js → terminal-lease-WOBR64YA.js} +4 -4
  120. package/dist/{uninstall-BVLWXKBT.js → uninstall-ZJF5H5ZN.js} +9 -9
  121. package/dist/{upgrade-JKAR27XC.js → upgrade-FUSUAGHR.js} +31 -28
  122. package/dist/{usage-MSAWCLX4.js → usage-N4MKVHKD.js} +140 -68
  123. package/dist/verifiers-YAWOJ3H2.js +336 -0
  124. package/dist/{verify-X5HDROLA.js → verify-LTDHYBGY.js} +10 -9
  125. package/dist/{wiki-generate-GUSOQ6ZP.js → wiki-generate-6M7GHTBJ.js} +75 -62
  126. package/dist/worker/entry.js +67 -57
  127. package/docs/README.md +3 -2
  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-versions.md +11 -6
  132. package/docs/built-in-agents.md +26 -2
  133. package/docs/capacity-and-scheduling.md +1 -1
  134. package/docs/commands-and-modes.md +83 -3
  135. package/docs/configuration-and-targets.md +86 -4
  136. package/docs/context-engine.md +1 -1
  137. package/docs/development-pipeline.md +1 -1
  138. package/docs/dispatch-architecture-rationale.md +1 -1
  139. package/docs/documentation-coverage.md +3 -3
  140. package/docs/documentation-guide.md +3 -3
  141. package/docs/eval-runner.md +1 -1
  142. package/docs/evals-internal.md +1 -1
  143. package/docs/evidence-and-memory.md +74 -10
  144. package/docs/evolution.md +1 -1
  145. package/docs/exit-codes-and-output.md +4 -1
  146. package/docs/extensions-and-sharing.md +6 -2
  147. package/docs/fleet-demo-runbook.md +2 -2
  148. package/docs/fleet-dispatch.md +228 -16
  149. package/docs/git-commit-provenance.md +2 -2
  150. package/docs/glossary.md +22 -2
  151. package/docs/installation-and-lifecycle.md +2 -2
  152. package/docs/middleware-and-components.md +2 -1
  153. package/docs/model-catalog.md +1 -1
  154. package/docs/observability.md +56 -9
  155. package/docs/proactive-memory.md +1 -1
  156. package/docs/prompt-envelope-and-tools.md +4 -2
  157. package/docs/provider-adapter-cookbook.md +1 -1
  158. package/docs/release-cut-checklist.md +83 -65
  159. package/docs/resource-library.md +59 -0
  160. package/docs/safety-model.md +2 -2
  161. package/docs/scientific-validation.md +3 -3
  162. package/docs/session-lifecycle.md +37 -1
  163. package/docs/skills-marketplace.md +16 -3
  164. package/docs/tool-usage.md +14 -7
  165. package/docs/trace-store.md +1 -1
  166. package/docs/troubleshooting.md +1 -1
  167. package/docs/tui-design.md +1 -1
  168. package/docs/worker-dispatch-mechanics.md +3 -3
  169. package/package.json +1 -2
  170. package/src/cli/argv.ts +5 -0
  171. package/src/cli/configure.ts +107 -23
  172. package/src/cli/doctor.ts +5 -1
  173. package/src/cli/evidence.ts +30 -25
  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 +111 -0
  178. package/src/cli/fleet-validate.ts +30 -0
  179. package/src/cli/fleet.ts +173 -335
  180. package/src/cli/index.ts +3 -1
  181. package/src/cli/library.ts +190 -0
  182. package/src/cli/share.ts +13 -1
  183. package/src/cli/shared.ts +1 -0
  184. package/src/cli/targets.ts +4 -1
  185. package/src/cli/usage.ts +111 -19
  186. package/src/cli/validate-model.ts +60 -5
  187. package/src/core/bus-events.ts +29 -0
  188. package/src/core/commit-attribution.ts +4 -4
  189. package/src/core/config.ts +130 -0
  190. package/src/core/defaults.ts +81 -0
  191. package/src/core/path-boundary.ts +100 -0
  192. package/src/domains/agents/builtins/architect.md +1 -0
  193. package/src/domains/agents/builtins/oracle.md +33 -0
  194. package/src/domains/agents/catalog.ts +13 -1
  195. package/src/domains/agents/extension.ts +2 -11
  196. package/src/domains/agents/fleet-contract.ts +304 -24
  197. package/src/domains/agents/index.ts +14 -0
  198. package/src/domains/agents/recipe.ts +7 -1
  199. package/src/domains/agents/registry.ts +73 -5
  200. package/src/domains/agents/result-contract.ts +360 -15
  201. package/src/domains/agents/write-boundary.ts +15 -50
  202. package/src/domains/config/classify.ts +4 -0
  203. package/src/domains/context/project-rules.ts +51 -1
  204. package/src/domains/dispatch/active-route-planner.ts +14 -0
  205. package/src/domains/dispatch/assignment-reconcile.ts +22 -5
  206. package/src/domains/dispatch/assignment-store.ts +151 -14
  207. package/src/domains/dispatch/backoff.ts +2 -1
  208. package/src/domains/dispatch/capability-match.ts +1 -0
  209. package/src/domains/dispatch/checkout-writer-lease.ts +175 -0
  210. package/src/domains/dispatch/contract.ts +48 -0
  211. package/src/domains/dispatch/delegation-plan.ts +164 -0
  212. package/src/domains/dispatch/execution-plan.ts +76 -5
  213. package/src/domains/dispatch/execution-role.ts +12 -2
  214. package/src/domains/dispatch/execution-scheduler.ts +183 -67
  215. package/src/domains/dispatch/extension.ts +412 -74
  216. package/src/domains/dispatch/fleet-gate.ts +14 -0
  217. package/src/domains/dispatch/fleet-plan.ts +63 -3
  218. package/src/domains/dispatch/fleet-run.ts +791 -0
  219. package/src/domains/dispatch/gate-role-prompts.ts +47 -0
  220. package/src/domains/dispatch/host-verification.ts +178 -0
  221. package/src/domains/dispatch/index.ts +41 -1
  222. package/src/domains/dispatch/intent-requirements.ts +40 -0
  223. package/src/domains/dispatch/intent.ts +235 -0
  224. package/src/domains/dispatch/path-scope.ts +370 -0
  225. package/src/domains/dispatch/receipt-integrity.ts +9 -4
  226. package/src/domains/dispatch/state.ts +36 -3
  227. package/src/domains/dispatch/types.ts +64 -12
  228. package/src/domains/dispatch/validation.ts +69 -6
  229. package/src/domains/dispatch/write-boundary-enforcer.ts +45 -0
  230. package/src/domains/dispatch/write-boundary.ts +201 -22
  231. package/src/domains/eval/metrics/evidence.ts +79 -2
  232. package/src/domains/eval/runners/clio-run.ts +12 -2
  233. package/src/domains/evidence/build.ts +69 -11
  234. package/src/domains/evidence/index.ts +21 -0
  235. package/src/domains/evidence/provenance.ts +46 -11
  236. package/src/domains/evidence/trust-projection.ts +274 -0
  237. package/src/domains/evidence/trust-status.ts +155 -18
  238. package/src/domains/evidence/types.ts +4 -0
  239. package/src/domains/extensions/discovery.ts +88 -1
  240. package/src/domains/extensions/resources.ts +20 -8
  241. package/src/domains/extensions/state.ts +6 -2
  242. package/src/domains/extensions/types.ts +4 -1
  243. package/src/domains/lifecycle/doctor.ts +140 -1
  244. package/src/domains/middleware/index.ts +15 -0
  245. package/src/domains/middleware/watchdog.ts +281 -0
  246. package/src/domains/observability/contract.ts +3 -1
  247. package/src/domains/observability/cost.ts +12 -1
  248. package/src/domains/observability/extension.ts +2 -2
  249. package/src/domains/observability/index.ts +10 -0
  250. package/src/domains/observability/out-of-turn-usage.ts +223 -0
  251. package/src/domains/prompts/contract.ts +3 -5
  252. package/src/domains/providers/extension.ts +30 -2
  253. package/src/domains/resources/common-loader.ts +3 -0
  254. package/src/domains/resources/index.ts +20 -0
  255. package/src/domains/resources/library.ts +326 -0
  256. package/src/domains/resources/prompts/loader.ts +119 -14
  257. package/src/domains/resources/skills/marketplace.ts +37 -12
  258. package/src/domains/safety/policy-engine.ts +5 -5
  259. package/src/domains/safety/run-effects.ts +64 -1
  260. package/src/domains/safety/scope.ts +7 -12
  261. package/src/domains/session/handoff.ts +629 -0
  262. package/src/domains/share/archive.ts +67 -2
  263. package/src/engine/acp/server.ts +4 -1
  264. package/src/engine/prompt-templates.ts +18 -1
  265. package/src/engine/worker-runtime.ts +6 -3
  266. package/src/entry/orchestrator.ts +37 -0
  267. package/src/interactive/bus-notices.ts +26 -0
  268. package/src/interactive/chat-loop.ts +235 -1
  269. package/src/interactive/chat-renderer.ts +22 -0
  270. package/src/interactive/cost-overlay.ts +31 -3
  271. package/src/interactive/council-dispatch.ts +30 -0
  272. package/src/interactive/council-grid.ts +213 -0
  273. package/src/interactive/council.ts +99 -0
  274. package/src/interactive/dispatch-board.ts +311 -17
  275. package/src/interactive/fleet-run-preview.ts +307 -0
  276. package/src/interactive/footer/notifications.ts +219 -0
  277. package/src/interactive/handoff-round.ts +56 -0
  278. package/src/interactive/interactive-application.ts +43 -1
  279. package/src/interactive/interactive-event-projection.ts +23 -1
  280. package/src/interactive/interactive-slash-runtime.ts +52 -2
  281. package/src/interactive/interactive-subscriptions.ts +14 -2
  282. package/src/interactive/oracle.ts +179 -0
  283. package/src/interactive/overlay-ask-user-lifecycle.ts +6 -0
  284. package/src/interactive/overlay-general-openers.ts +190 -1
  285. package/src/interactive/overlay-key-routing.ts +17 -1
  286. package/src/interactive/overlay-lifecycle.ts +41 -1
  287. package/src/interactive/overlay-permission-lifecycle.ts +10 -0
  288. package/src/interactive/overlay-resource-openers.ts +11 -3
  289. package/src/interactive/overlay-session-lifecycle.ts +234 -2
  290. package/src/interactive/overlays/fleet-run-approval.ts +208 -0
  291. package/src/interactive/overlays/handoff-review.ts +185 -0
  292. package/src/interactive/overlays/library-install-confirm.ts +151 -0
  293. package/src/interactive/overlays/list-overlay.ts +168 -2
  294. package/src/interactive/overlays/settings.ts +221 -30
  295. package/src/interactive/overlays/side-question.ts +139 -0
  296. package/src/interactive/overlays/skills-hub.ts +401 -15
  297. package/src/interactive/side-question.ts +171 -0
  298. package/src/interactive/slash-commands.ts +439 -7
  299. package/src/interactive/slash-spec.ts +19 -6
  300. package/src/interactive/theme/tokens.ts +30 -0
  301. package/src/interactive/turn-middleware.ts +15 -1
  302. package/src/interactive/view/artifacts.ts +42 -9
  303. package/src/interactive/view/view-overlay.ts +15 -3
  304. package/src/interactive/watchdog-run.ts +75 -0
  305. package/src/interactive/worker-receipts.ts +14 -2
  306. package/src/interactive/worker-share.ts +56 -1
  307. package/src/interactive/worker-stream.ts +15 -0
  308. package/src/tools/bootstrap.ts +3 -0
  309. package/src/tools/compete-worktrees.ts +13 -79
  310. package/src/tools/dispatch-admission.ts +251 -18
  311. package/src/tools/dispatch-arguments.ts +84 -1
  312. package/src/tools/dispatch-plan.ts +165 -6
  313. package/src/tools/dispatch-runner.ts +364 -23
  314. package/src/tools/dispatch-types.ts +20 -1
  315. package/src/tools/dispatch.ts +72 -2
  316. package/src/tools/monitor.ts +29 -0
  317. package/src/tools/profiles.ts +18 -4
  318. package/src/tools/task-worktree.ts +238 -0
  319. package/src/tools/verify/authoring.ts +61 -1
  320. package/src/tools/verify/scripts.ts +62 -0
  321. package/src/tools/worker-evidence.ts +21 -14
  322. package/src/worker/spec-contract.ts +3 -1
  323. package/dist/chunk-HC4CLZ2Y.js +0 -68
@@ -15,6 +15,8 @@ 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";
19
+ import { enabledExtensionResourceRoots } from "../extensions/index.js";
18
20
  import { type FleetCommandRegistry, loadFleetCommands } from "./fleet-commands.js";
19
21
  import { parseFrontmatter } from "./frontmatter.js";
20
22
  import { normalizeWriteBoundary, WRITE_BOUNDARY_MAX_ENTRIES } from "./write-boundary.js";
@@ -35,6 +37,7 @@ export type FleetOnFailure = "stop" | "continue";
35
37
  * allowlist stated out loud.
36
38
  */
37
39
  export const FLEET_WRITE_BOUNDARY_VERSION = 4;
40
+ export const FLEET_DYNAMIC_STEP_VERSION = 5;
38
41
 
39
42
  /**
40
43
  * Upper bound on any declared loop. A loop is bounded in the contract, and the
@@ -63,6 +66,34 @@ export interface FleetContractAgentStep {
63
66
  scope: FleetStepScope;
64
67
  dependencies: ReadonlyArray<string>;
65
68
  writes?: ReadonlyArray<string>;
69
+ target?: string;
70
+ profile?: string;
71
+ }
72
+
73
+ export interface FleetContractGateStep {
74
+ kind: "gate";
75
+ id: string;
76
+ agent: string;
77
+ path: string;
78
+ run: string;
79
+ scope: "workspace";
80
+ dependencies: ReadonlyArray<string>;
81
+ target?: string;
82
+ profile?: string;
83
+ }
84
+
85
+ export interface FleetContractPlanStep {
86
+ kind: "plan";
87
+ id: string;
88
+ agent: string;
89
+ roster: ReadonlyArray<string>;
90
+ maxTasks: number;
91
+ proposals: boolean;
92
+ scope: FleetStepScope;
93
+ dependencies: ReadonlyArray<string>;
94
+ writes?: ReadonlyArray<string>;
95
+ target?: string;
96
+ profile?: string;
66
97
  }
67
98
 
68
99
  /**
@@ -89,7 +120,15 @@ export interface FleetContractCodeStep {
89
120
  /** The verification half of a loop: the question that decides continuation. */
90
121
  export type FleetContractLoopCheck =
91
122
  | { kind: "code"; command: string; scope: FleetStepScope; writes?: ReadonlyArray<string> }
92
- | { kind: "agent"; agent: string; scope: FleetStepScope; writes?: ReadonlyArray<string> };
123
+ | {
124
+ kind: "agent";
125
+ agent: string;
126
+ scope: FleetStepScope;
127
+ writes?: ReadonlyArray<string>;
128
+ target?: string;
129
+ profile?: string;
130
+ }
131
+ | { kind: "gate"; gate: string };
93
132
 
94
133
  /** The repair half. Always an agent: a deterministic repair is just a check. */
95
134
  export interface FleetContractLoopRepair {
@@ -97,6 +136,8 @@ export interface FleetContractLoopRepair {
97
136
  agent: string;
98
137
  scope: FleetStepScope;
99
138
  writes?: ReadonlyArray<string>;
139
+ target?: string;
140
+ profile?: string;
100
141
  }
101
142
 
102
143
  /**
@@ -120,7 +161,12 @@ export interface FleetContractLoopStep {
120
161
  repair: FleetContractLoopRepair;
121
162
  }
122
163
 
123
- export type FleetContractStep = FleetContractAgentStep | FleetContractCodeStep | FleetContractLoopStep;
164
+ export type FleetContractStep =
165
+ | FleetContractAgentStep
166
+ | FleetContractCodeStep
167
+ | FleetContractLoopStep
168
+ | FleetContractGateStep
169
+ | FleetContractPlanStep;
124
170
 
125
171
  /**
126
172
  * Contract schema version.
@@ -137,7 +183,7 @@ export type FleetContractStep = FleetContractAgentStep | FleetContractCodeStep |
137
183
  * A version literal gives that reader a clear refusal instead of an obscure
138
184
  * unknown-property error deep in a step.
139
185
  */
140
- export type FleetContractVersion = 1 | 2 | 3 | 4;
186
+ export type FleetContractVersion = 1 | 2 | 3 | 4 | 5;
141
187
 
142
188
  export interface FleetContract {
143
189
  version: FleetContractVersion;
@@ -147,12 +193,13 @@ export interface FleetContract {
147
193
  maxWorkers: number;
148
194
  budgetUsd: number | null;
149
195
  onFailure: FleetOnFailure;
196
+ writers?: 1;
150
197
  /** Prompt template body with unresolved {{var}} placeholders. */
151
198
  body: string;
152
199
  path: string;
153
200
  }
154
201
 
155
- export type FleetContractSource = "builtin" | "project";
202
+ export type FleetContractSource = "builtin" | "extension" | "user" | "project";
156
203
 
157
204
  export interface FleetContractListing {
158
205
  name: string;
@@ -183,6 +230,12 @@ function writesSchema(version: FleetContractVersion) {
183
230
  : {};
184
231
  }
185
232
 
233
+ function routeSchema(version: FleetContractVersion) {
234
+ return version >= FLEET_DYNAMIC_STEP_VERSION
235
+ ? { target: Type.Optional(Type.String({ minLength: 1 })), profile: Type.Optional(Type.String({ minLength: 1 })) }
236
+ : {};
237
+ }
238
+
186
239
  function agentStepSchema(version: FleetContractVersion) {
187
240
  return Type.Object(
188
241
  {
@@ -192,6 +245,41 @@ function agentStepSchema(version: FleetContractVersion) {
192
245
  scope: FleetScopeSchema,
193
246
  dependencies: Type.Array(Type.String({ minLength: 1 })),
194
247
  ...writesSchema(version),
248
+ ...routeSchema(version),
249
+ },
250
+ { additionalProperties: false },
251
+ );
252
+ }
253
+
254
+ function gateStepSchema() {
255
+ return Type.Object(
256
+ {
257
+ kind: Type.Literal("gate"),
258
+ id: Type.String({ minLength: 1 }),
259
+ agent: Type.String({ minLength: 1 }),
260
+ path: Type.String({ minLength: 1 }),
261
+ run: Type.String({ minLength: 1 }),
262
+ scope: Type.Optional(Type.Literal("workspace")),
263
+ dependencies: Type.Array(Type.String({ minLength: 1 })),
264
+ ...routeSchema(5),
265
+ },
266
+ { additionalProperties: false },
267
+ );
268
+ }
269
+
270
+ function planStepSchema() {
271
+ return Type.Object(
272
+ {
273
+ kind: Type.Literal("plan"),
274
+ id: Type.String({ minLength: 1 }),
275
+ agent: Type.Optional(Type.String({ minLength: 1 })),
276
+ roster: Type.Array(Type.String({ minLength: 1 }), { minItems: 1, maxItems: 16 }),
277
+ maxTasks: Type.Integer({ minimum: 1, maximum: 16 }),
278
+ proposals: Type.Optional(Type.Boolean()),
279
+ scope: FleetScopeSchema,
280
+ dependencies: Type.Array(Type.String({ minLength: 1 })),
281
+ ...writesSchema(5),
282
+ ...routeSchema(5),
195
283
  },
196
284
  { additionalProperties: false },
197
285
  );
@@ -230,12 +318,21 @@ function loopStepSchema(version: FleetContractVersion) {
230
318
  },
231
319
  { additionalProperties: false },
232
320
  ),
321
+ ...(version >= FLEET_DYNAMIC_STEP_VERSION
322
+ ? [
323
+ Type.Object(
324
+ { kind: Type.Literal("gate"), gate: Type.String({ minLength: 1 }) },
325
+ { additionalProperties: false },
326
+ ),
327
+ ]
328
+ : []),
233
329
  Type.Object(
234
330
  {
235
331
  kind: Type.Literal("agent"),
236
332
  agent: Type.String({ minLength: 1 }),
237
333
  scope: FleetScopeSchema,
238
334
  ...writesSchema(version),
335
+ ...routeSchema(version),
239
336
  },
240
337
  { additionalProperties: false },
241
338
  ),
@@ -246,6 +343,7 @@ function loopStepSchema(version: FleetContractVersion) {
246
343
  agent: Type.String({ minLength: 1 }),
247
344
  scope: FleetScopeSchema,
248
345
  ...writesSchema(version),
346
+ ...routeSchema(version),
249
347
  },
250
348
  { additionalProperties: false },
251
349
  ),
@@ -257,6 +355,15 @@ function loopStepSchema(version: FleetContractVersion) {
257
355
  function stepSchema(version: FleetContractVersion) {
258
356
  if (version === 1) return agentStepSchema(1);
259
357
  if (version === 2) return Type.Union([agentStepSchema(2), codeStepSchema(2)]);
358
+ if (version === 5) {
359
+ return Type.Union([
360
+ agentStepSchema(version),
361
+ codeStepSchema(version),
362
+ loopStepSchema(version),
363
+ gateStepSchema(),
364
+ planStepSchema(),
365
+ ]);
366
+ }
260
367
  return Type.Union([agentStepSchema(version), codeStepSchema(version), loopStepSchema(version)]);
261
368
  }
262
369
 
@@ -270,6 +377,7 @@ function frontmatterSchema(version: FleetContractVersion) {
270
377
  maxWorkers: Type.Integer({ minimum: 1 }),
271
378
  budgetUsd: Type.Optional(Type.Number()),
272
379
  onFailure: Type.Union([Type.Literal("stop"), Type.Literal("continue")]),
380
+ ...(version >= FLEET_DYNAMIC_STEP_VERSION ? { writers: Type.Optional(Type.Literal(1)) } : {}),
273
381
  },
274
382
  { additionalProperties: false },
275
383
  );
@@ -280,11 +388,12 @@ const SCHEMAS: Readonly<Record<FleetContractVersion, ReturnType<typeof frontmatt
280
388
  2: frontmatterSchema(2),
281
389
  3: frontmatterSchema(3),
282
390
  4: frontmatterSchema(4),
391
+ 5: frontmatterSchema(5),
283
392
  };
284
393
 
285
394
  function contractVersion(frontmatter: Record<string, unknown>): FleetContractVersion | null {
286
395
  const value = frontmatter.version;
287
- return value === 1 || value === 2 || value === 3 || value === 4 ? value : null;
396
+ return value === 1 || value === 2 || value === 3 || value === 4 || value === 5 ? value : null;
288
397
  }
289
398
 
290
399
  function firstSchemaError(frontmatter: Record<string, unknown>, version: FleetContractVersion): string | null {
@@ -299,15 +408,38 @@ function fleetsDir(cwd: string): string {
299
408
  }
300
409
 
301
410
  type RawStep = {
302
- kind?: "agent" | "code" | "loop";
411
+ kind?: "agent" | "code" | "loop" | "gate" | "plan";
303
412
  id: string;
304
413
  agent?: string;
305
414
  command?: string;
306
415
  commitFrom?: string[];
307
416
  writes?: string[];
308
417
  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[] };
418
+ check?: {
419
+ kind: "code" | "agent" | "gate";
420
+ command?: string;
421
+ agent?: string;
422
+ gate?: string;
423
+ scope: FleetStepScope;
424
+ writes?: string[];
425
+ target?: string;
426
+ profile?: string;
427
+ };
428
+ repair?: {
429
+ kind?: "agent";
430
+ agent: string;
431
+ scope: FleetStepScope;
432
+ writes?: string[];
433
+ target?: string;
434
+ profile?: string;
435
+ };
436
+ target?: string;
437
+ profile?: string;
438
+ path?: string;
439
+ run?: string;
440
+ roster?: string[];
441
+ maxTasks?: number;
442
+ proposals?: boolean;
311
443
  } & Pick<FleetContractAgentStep, "scope"> & { dependencies: string[] };
312
444
 
313
445
  /** Normalized declaration, or nothing when this version declares no boundary. */
@@ -316,6 +448,36 @@ function normalizedWrites(writes: string[] | undefined): { writes?: ReadonlyArra
316
448
  }
317
449
 
318
450
  function normalizeStep(step: RawStep): FleetContractStep {
451
+ const route = (value: { target?: string; profile?: string }): { target?: string; profile?: string } => ({
452
+ ...(value.target !== undefined ? { target: value.target } : {}),
453
+ ...(value.profile !== undefined ? { profile: value.profile } : {}),
454
+ });
455
+ if (step.kind === "gate") {
456
+ return {
457
+ kind: "gate",
458
+ id: step.id,
459
+ agent: step.agent ?? "",
460
+ path: step.path ?? "",
461
+ run: step.run ?? "",
462
+ scope: "workspace",
463
+ dependencies: [...step.dependencies],
464
+ ...route(step),
465
+ };
466
+ }
467
+ if (step.kind === "plan") {
468
+ return {
469
+ kind: "plan",
470
+ id: step.id,
471
+ agent: step.agent ?? "architect",
472
+ roster: [...(step.roster ?? [])],
473
+ maxTasks: step.maxTasks ?? 0,
474
+ proposals: step.proposals ?? false,
475
+ scope: step.scope,
476
+ dependencies: [...step.dependencies],
477
+ ...normalizedWrites(step.writes),
478
+ ...route(step),
479
+ };
480
+ }
319
481
  if (step.kind === "loop") {
320
482
  const check = step.check as NonNullable<RawStep["check"]>;
321
483
  const repair = step.repair as NonNullable<RawStep["repair"]>;
@@ -327,8 +489,22 @@ function normalizeStep(step: RawStep): FleetContractStep {
327
489
  check:
328
490
  check.kind === "code"
329
491
  ? { 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) },
492
+ : check.kind === "gate"
493
+ ? { kind: "gate", gate: check.gate ?? "" }
494
+ : {
495
+ kind: "agent",
496
+ agent: check.agent ?? "",
497
+ scope: check.scope,
498
+ ...normalizedWrites(check.writes),
499
+ ...route(check),
500
+ },
501
+ repair: {
502
+ kind: "agent",
503
+ agent: repair.agent,
504
+ scope: repair.scope,
505
+ ...normalizedWrites(repair.writes),
506
+ ...route(repair),
507
+ },
332
508
  };
333
509
  }
334
510
  if (step.kind === "code") {
@@ -349,6 +525,7 @@ function normalizeStep(step: RawStep): FleetContractStep {
349
525
  scope: step.scope,
350
526
  dependencies: [...step.dependencies],
351
527
  ...normalizedWrites(step.writes),
528
+ ...route(step),
352
529
  };
353
530
  }
354
531
 
@@ -406,6 +583,13 @@ export function validateFleetGraph(contract: Pick<FleetContract, "steps" | "path
406
583
  }
407
584
  }
408
585
  for (const step of contract.steps) {
586
+ if (step.kind === "loop" && step.check.kind === "gate") {
587
+ const gateId = step.check.gate;
588
+ const gate = contract.steps.find((candidate) => candidate.id === gateId);
589
+ if (gate?.kind !== "gate") {
590
+ throw new Error(`fleet contract ${contract.path}: loop '${step.id}' names unknown gate '${gateId}'`);
591
+ }
592
+ }
409
593
  for (const dependency of step.dependencies) {
410
594
  if (dependency === step.id) throw new Error(`fleet contract ${contract.path}: step '${step.id}' depends on itself`);
411
595
  if (!declared.has(dependency)) {
@@ -484,10 +668,18 @@ export function fleetStepBoundaries(contract: Pick<FleetContract, "steps" | "ver
484
668
  };
485
669
  for (const step of contract.steps) {
486
670
  if (step.kind === "loop") {
487
- add(`${step.id}.check`, step.check.scope, step.check.writes);
671
+ if (step.check.kind === "gate") {
672
+ const gateId = step.check.gate;
673
+ const gate = contract.steps.find((candidate) => candidate.id === gateId);
674
+ if (gate?.kind === "gate") add(`${step.id}.check`, "workspace", [gate.path]);
675
+ } else add(`${step.id}.check`, step.check.scope, step.check.writes);
488
676
  add(`${step.id}.repair`, step.repair.scope, step.repair.writes);
489
677
  continue;
490
678
  }
679
+ if (step.kind === "gate") {
680
+ add(step.id, "workspace", [step.path]);
681
+ continue;
682
+ }
491
683
  add(step.id, step.scope, step.writes);
492
684
  }
493
685
  return boundaries;
@@ -515,10 +707,14 @@ function validateWriteBoundaries(contract: Pick<FleetContract, "steps" | "versio
515
707
  const declared: Array<{ id: string; scope: FleetStepScope; writes: ReadonlyArray<string> | undefined }> =
516
708
  step.kind === "loop"
517
709
  ? [
518
- { id: `${step.id}.check`, scope: step.check.scope, writes: step.check.writes },
710
+ ...(step.check.kind === "gate"
711
+ ? []
712
+ : [{ id: `${step.id}.check`, scope: step.check.scope, writes: step.check.writes }]),
519
713
  { id: `${step.id}.repair`, scope: step.repair.scope, writes: step.repair.writes },
520
714
  ]
521
- : [{ id: step.id, scope: step.scope, writes: step.writes }];
715
+ : step.kind === "gate"
716
+ ? []
717
+ : [{ id: step.id, scope: step.scope, writes: step.writes }];
522
718
  for (const position of declared) {
523
719
  if (position.scope === "readonly" && position.writes !== undefined) {
524
720
  throw new Error(
@@ -559,11 +755,11 @@ export function parseFleetContract(raw: string, sourcePath: string): FleetContra
559
755
  const { frontmatter, body } = parseFrontmatter(raw, sourcePath);
560
756
  const version = contractVersion(frontmatter);
561
757
  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
- );
758
+ throw new Error(`fleet contract ${sourcePath}: version must be 1, 2, 3, 4, or 5`);
565
759
  }
566
760
  if (version < FLEET_WRITE_BOUNDARY_VERSION) assertNoWritesBefore(frontmatter, sourcePath, version);
761
+ if (version < FLEET_DYNAMIC_STEP_VERSION) assertNoV5FieldsBefore(frontmatter, sourcePath, version);
762
+ if (version >= FLEET_DYNAMIC_STEP_VERSION) assertNoGateWrites(frontmatter, sourcePath);
567
763
  const schemaError = firstSchemaError(frontmatter, version);
568
764
  if (schemaError !== null) {
569
765
  throw new Error(`fleet contract ${sourcePath}: ${schemaError}`);
@@ -576,6 +772,7 @@ export function parseFleetContract(raw: string, sourcePath: string): FleetContra
576
772
  maxWorkers: number;
577
773
  budgetUsd?: number;
578
774
  onFailure: FleetOnFailure;
775
+ writers?: 1;
579
776
  };
580
777
  if (fm.budgetUsd !== undefined && !(fm.budgetUsd > 0)) {
581
778
  throw new Error(`fleet contract ${sourcePath}: budgetUsd must be a positive number`);
@@ -592,14 +789,49 @@ export function parseFleetContract(raw: string, sourcePath: string): FleetContra
592
789
  maxWorkers: fm.maxWorkers,
593
790
  budgetUsd: fm.budgetUsd ?? null,
594
791
  onFailure: fm.onFailure,
792
+ ...(fm.writers === 1 ? { writers: 1 as const } : {}),
595
793
  body: trimmedBody,
596
794
  path: sourcePath,
597
795
  };
598
796
  validateFleetGraph(contract);
599
797
  validateWriteBoundaries(contract);
798
+ validateV5Declarations(contract);
600
799
  return contract;
601
800
  }
602
801
 
802
+ function validateV5Declarations(contract: FleetContract): void {
803
+ if (contract.version < FLEET_DYNAMIC_STEP_VERSION) return;
804
+ const route = (id: string, value: { target?: string; profile?: string }): void => {
805
+ if (value.target !== undefined && value.profile !== undefined) {
806
+ throw new Error(`fleet contract ${contract.path}: step '${id}' may declare target or profile, never both`);
807
+ }
808
+ };
809
+ for (const step of contract.steps) {
810
+ if (step.kind === "agent" || step.kind === "plan" || step.kind === "gate") route(step.id, step);
811
+ if (step.kind === "plan" && new Set(step.roster).size !== step.roster.length) {
812
+ throw new Error(`fleet contract ${contract.path}: plan step '${step.id}' roster contains duplicate agents`);
813
+ }
814
+ if (step.kind === "gate") {
815
+ let normalized: ReadonlyArray<string>;
816
+ try {
817
+ normalized = normalizeWriteBoundary([step.path]);
818
+ } catch (error) {
819
+ throw new Error(
820
+ `fleet contract ${contract.path}: gate '${step.id}' path is invalid: ${error instanceof Error ? error.message : String(error)}`,
821
+ );
822
+ }
823
+ if (normalized[0] !== step.path.replaceAll("\\", "/")) {
824
+ throw new Error(
825
+ `fleet contract ${contract.path}: gate '${step.id}' path must be normalized and repository-relative`,
826
+ );
827
+ }
828
+ }
829
+ if (step.kind !== "loop") continue;
830
+ if (step.check.kind === "agent") route(`${step.id}.check`, step.check);
831
+ route(`${step.id}.repair`, step.repair);
832
+ }
833
+ }
834
+
603
835
  /**
604
836
  * A `writes` key under an older version is refused by name rather than as an
605
837
  * unknown property, because the two readings are far apart: the author wrote a
@@ -619,6 +851,45 @@ function assertNoWritesBefore(frontmatter: Record<string, unknown>, sourcePath:
619
851
  }
620
852
  }
621
853
 
854
+ function assertNoGateWrites(frontmatter: Record<string, unknown>, sourcePath: string): void {
855
+ for (const value of Array.isArray(frontmatter.steps) ? frontmatter.steps : []) {
856
+ if (typeof value !== "object" || value === null) continue;
857
+ const step = value as Record<string, unknown>;
858
+ if (step.kind !== "gate" || typeof step.id !== "string" || step.id.length === 0 || !("writes" in step)) continue;
859
+ throw new Error(
860
+ `fleet contract ${sourcePath}: gate step '${step.id}' must not declare 'writes'; its write boundary is derived from 'path'`,
861
+ );
862
+ }
863
+ }
864
+
865
+ function assertNoV5FieldsBefore(frontmatter: Record<string, unknown>, sourcePath: string, version: number): void {
866
+ const forbidden = ["target", "profile"] as const;
867
+ if ("writers" in frontmatter) {
868
+ throw new Error(
869
+ `fleet contract ${sourcePath}: 'writers' requires contract version ${FLEET_DYNAMIC_STEP_VERSION}; this contract declares version ${version}`,
870
+ );
871
+ }
872
+ for (const value of Array.isArray(frontmatter.steps) ? frontmatter.steps : []) {
873
+ if (typeof value !== "object" || value === null) continue;
874
+ const step = value as Record<string, unknown>;
875
+ if (step.kind === "plan" || step.kind === "gate") {
876
+ throw new Error(
877
+ `fleet contract ${sourcePath}: kind '${String(step.kind)}' requires contract version ${FLEET_DYNAMIC_STEP_VERSION}; this contract declares version ${version}`,
878
+ );
879
+ }
880
+ for (const candidate of [step, step.check, step.repair]) {
881
+ if (typeof candidate !== "object" || candidate === null) continue;
882
+ for (const field of forbidden) {
883
+ if (field in candidate) {
884
+ throw new Error(
885
+ `fleet contract ${sourcePath}: '${field}' requires contract version ${FLEET_DYNAMIC_STEP_VERSION}; this contract declares version ${version}`,
886
+ );
887
+ }
888
+ }
889
+ }
890
+ }
891
+ }
892
+
622
893
  /** Every loop in the contract, in declaration order. */
623
894
  export function fleetLoopSteps(contract: FleetContract): FleetContractLoopStep[] {
624
895
  return contract.steps.filter((step): step is FleetContractLoopStep => step.kind === "loop");
@@ -634,6 +905,7 @@ export function fleetCodeSteps(contract: FleetContract): Array<{ id: string; com
634
905
  const steps: Array<{ id: string; command: string }> = [];
635
906
  for (const step of contract.steps) {
636
907
  if (step.kind === "code") steps.push({ id: step.id, command: step.command });
908
+ else if (step.kind === "gate") steps.push({ id: step.id, command: step.run });
637
909
  else if (step.kind === "loop" && step.check.kind === "code") {
638
910
  steps.push({ id: fleetLoopCheckStepId(step.id, 1), command: step.check.command });
639
911
  }
@@ -699,11 +971,22 @@ function builtinFleetsDir(): string {
699
971
  return join(resolvePackageRoot(), "src", "domains", "agents", "fleets");
700
972
  }
701
973
 
974
+ function fleetSources(cwd: string): ReadonlyArray<{ dir: string; source: FleetContractSource }> {
975
+ return [
976
+ { dir: builtinFleetsDir(), source: "builtin" },
977
+ ...enabledExtensionResourceRoots("fleets", cwd)
978
+ .sort((left, right) => left.source.localeCompare(right.source))
979
+ .map((root) => ({ dir: root.path, source: "extension" as const })),
980
+ { dir: join(clioConfigDir(), "fleets"), source: "user" },
981
+ { dir: fleetsDir(cwd), source: "project" },
982
+ ];
983
+ }
984
+
702
985
  function fleetContractPath(cwd: string, name: string): { path: string; source: FleetContractSource } | null {
703
- const projectPath = join(fleetsDir(cwd), `${name}.md`);
704
- if (existsSync(projectPath)) return { path: projectPath, source: "project" };
705
- const builtinPath = join(builtinFleetsDir(), `${name}.md`);
706
- if (existsSync(builtinPath)) return { path: builtinPath, source: "builtin" };
986
+ for (const source of [...fleetSources(cwd)].reverse()) {
987
+ const candidate = join(source.dir, `${name}.md`);
988
+ if (existsSync(candidate)) return { path: candidate, source: source.source };
989
+ }
707
990
  return null;
708
991
  }
709
992
 
@@ -743,10 +1026,7 @@ export function listFleetContracts(cwd: string): FleetContractListing[] {
743
1026
  registryError = err instanceof Error ? err.message : String(err);
744
1027
  }
745
1028
  const listings = new Map<string, FleetContractListing>();
746
- const sources: ReadonlyArray<{ dir: string; source: FleetContractSource }> = [
747
- { dir: builtinFleetsDir(), source: "builtin" },
748
- { dir: fleetsDir(cwd), source: "project" },
749
- ];
1029
+ const sources = fleetSources(cwd);
750
1030
  for (const { dir, source } of sources) {
751
1031
  for (const file of listDirectory(dir)) {
752
1032
  const path = join(dir, file);
@@ -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,
@@ -131,7 +131,7 @@ export interface AgentRecipe {
131
131
  resultContract: ResultContract;
132
132
  product?: AgentProduct;
133
133
  tags: ReadonlyArray<string>;
134
- source: "builtin" | "user" | "project";
134
+ source: "builtin" | "extension" | "user" | "project";
135
135
  filepath: string;
136
136
  /** Persona prompt body. */
137
137
  body: string;
@@ -140,6 +140,12 @@ export interface AgentRecipe {
140
140
  export interface RecipeSource {
141
141
  dir: string;
142
142
  source: AgentRecipe["source"];
143
+ /** Project root whose extension and skill resources are being discovered. */
144
+ cwd?: string;
145
+ /** Stable provenance used to correlate resources from one extension. */
146
+ origin?: string;
147
+ /** The declaring extension's skill root; extension agents may bind only here. */
148
+ skillRoot?: string;
143
149
  }
144
150
 
145
151
  export function recipeIdFromPath(absPath: string, rootDir: string): string {