@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.
- package/CHANGELOG.md +59 -0
- package/README.md +22 -6
- package/dist/{acp-2BEHC4DL.js → acp-U67UHUK2.js} +14 -14
- package/dist/{agents-LNNFTM53.js → agents-YU6SGALZ.js} +42 -35
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-KXXFI2VS.js → auth-5ZPJOIVG.js} +32 -24
- package/dist/builtins-C6JMZVV6.js +17 -0
- package/dist/{chunk-E25LMLRW.js → chunk-26LEYJZH.js} +2 -2
- package/dist/{chunk-TSHXZTOQ.js → chunk-2HEJ2F35.js} +5 -5
- package/dist/{chunk-PBTHKCPN.js → chunk-2HFZQUHL.js} +7 -7
- package/dist/{chunk-FO5ZOVUY.js → chunk-3BINW3FP.js} +5 -5
- package/dist/{chunk-4OC57DA6.js → chunk-4DGYLA73.js} +53 -2
- package/dist/{chunk-CKXWIANG.js → chunk-4SPRNWDE.js} +18 -16
- package/dist/{chunk-E2ER4LJF.js → chunk-5C3AQNDW.js} +25 -1
- package/dist/{chunk-XF5N4U5A.js → chunk-5DHKRSMQ.js} +9 -8
- package/dist/{chunk-43AOLP7E.js → chunk-5FR74PWO.js} +2 -1
- package/dist/{chunk-EKY57CSP.js → chunk-5H3GB5BO.js} +68 -772
- package/dist/{chunk-6XXKFVSN.js → chunk-5Q2VVUKB.js} +4 -4
- package/dist/{chunk-DJVECN66.js → chunk-7RFXX52T.js} +295 -3705
- package/dist/{chunk-ZXF4XRKW.js → chunk-7RGZWPB6.js} +158 -8
- package/dist/{chunk-FYYLNIL5.js → chunk-A2NJGIB3.js} +2 -2
- package/dist/{chunk-XXQNGV4M.js → chunk-A3WNZD3P.js} +548 -72
- package/dist/{chunk-VEZEGCGW.js → chunk-B5CSFE7B.js} +23 -21
- package/dist/{chunk-2SFS6XQE.js → chunk-DGSYXYMX.js} +3 -2
- package/dist/chunk-DR52UMZW.js +21 -0
- package/dist/{chunk-ZWLZP4ZT.js → chunk-DYIM5TJT.js} +98 -12
- package/dist/{chunk-QKMUKYO7.js → chunk-E77JEWSD.js} +270 -125
- package/dist/{chunk-LYF7OHWH.js → chunk-EMYUUSFG.js} +12 -467
- package/dist/{chunk-4VP4KH3K.js → chunk-EQ63NRB7.js} +8 -8
- package/dist/chunk-FBVTI2TJ.js +518 -0
- package/dist/{chunk-R46L2BIR.js → chunk-FHJEP5SW.js} +19 -25
- package/dist/{chunk-WR67VIZY.js → chunk-GN57SG4G.js} +66 -8
- package/dist/{chunk-RD5U66HV.js → chunk-GPIEI3LY.js} +9 -9
- package/dist/{chunk-PCZJO5TI.js → chunk-GU2UIAFZ.js} +13 -178
- package/dist/chunk-GWS3VEIW.js +195 -0
- package/dist/chunk-H7IXIC72.js +103 -0
- package/dist/{chunk-3BPUFZDL.js → chunk-HLE42MG7.js} +3 -3
- package/dist/{chunk-24I7BN55.js → chunk-IFBNV6H6.js} +3 -3
- package/dist/{chunk-QNQHSOLF.js → chunk-IGWKHNIQ.js} +114 -55
- package/dist/chunk-IIZWH4XA.js +172 -0
- package/dist/{chunk-AD2SYQYC.js → chunk-IJ7RPIYJ.js} +124 -6
- package/dist/chunk-J3YUBZWY.js +382 -0
- package/dist/{chunk-5JGRAMKL.js → chunk-JOZYP4GM.js} +8 -6
- package/dist/{chunk-OH3TOQTB.js → chunk-K4XHGFR5.js} +751 -15
- package/dist/{chunk-EYPA3EGJ.js → chunk-KTYTFRMB.js} +178 -14
- package/dist/chunk-LU7P4LHA.js +33 -0
- package/dist/chunk-ME6CCNFO.js +108 -0
- package/dist/chunk-MXKJU4JB.js +1100 -0
- package/dist/{chunk-RY3LY4J5.js → chunk-N22QMJKY.js} +21 -18
- package/dist/chunk-NMPKI6XL.js +3006 -0
- package/dist/chunk-NUGM5KR6.js +165 -0
- package/dist/{chunk-22NAGB7X.js → chunk-P43ETTHK.js} +5 -94
- package/dist/{chunk-NILBFAPG.js → chunk-PMDBGQSJ.js} +2 -2
- package/dist/chunk-PT7HYKEM.js +165 -0
- package/dist/chunk-RVG5JXAL.js +41 -0
- package/dist/{chunk-GEYXPTRF.js → chunk-RWSI4YD7.js} +2 -2
- package/dist/{chunk-4BPJXDWC.js → chunk-TANS5ZJS.js} +35 -19
- package/dist/{verifiers-NCBTHHN2.js → chunk-TB5666IT.js} +67 -324
- package/dist/{chunk-QM3F2GKX.js → chunk-TLQJPP24.js} +7927 -8088
- package/dist/{chunk-G7MUEIGA.js → chunk-TT36MB5S.js} +2 -1
- package/dist/chunk-TTHACPOM.js +961 -0
- package/dist/{chunk-6US73PDB.js → chunk-TYPGUK6W.js} +7 -7
- package/dist/{chunk-MFFY33HR.js → chunk-U6MBIEMB.js} +554 -209
- package/dist/chunk-VAWNZU7Z.js +242 -0
- package/dist/{chunk-IR4CFBFN.js → chunk-VCBR6CU7.js} +12 -12
- package/dist/{chunk-WHJYKASB.js → chunk-VHN4MY6O.js} +2 -2
- package/dist/{chunk-XYDYPRZI.js → chunk-VWZOAB7K.js} +10 -10
- package/dist/{chunk-ZRGEBJ4T.js → chunk-WLFILSD5.js} +48 -48
- package/dist/{chunk-K7T3E2SR.js → chunk-WNIJTQQK.js} +12 -11
- package/dist/{chunk-CYQKWTG3.js → chunk-WSB3FPX7.js} +68 -20
- package/dist/{chunk-KHSFENX2.js → chunk-WWCZ5F23.js} +116 -14
- package/dist/{chunk-XE2VEJHX.js → chunk-WXY7KU3G.js} +2 -2
- package/dist/{chunk-PPAMZ32Z.js → chunk-XK56QHLX.js} +6 -1
- package/dist/{chunk-KOHPCX4K.js → chunk-XWSF374K.js} +5 -5
- package/dist/{chunk-CJUB2JJ2.js → chunk-YS5VLNH5.js} +10 -10
- package/dist/{chunk-ZZMN5OM4.js → chunk-ZNLWCMVZ.js} +2 -2
- package/dist/{chunk-WHGPSPT5.js → chunk-ZVJ5BLO2.js} +2 -2
- package/dist/cli/index.js +33 -31
- package/dist/{clio-M2KGYUFZ.js → clio-QVTYJ57A.js} +10 -10
- package/dist/{code-nav-GQNL7XA6.js → code-nav-FGGFIE7L.js} +5 -5
- package/dist/codewiki/build-worker.js +4 -4
- package/dist/{components-5TTYYX6G.js → components-ZFA3SAER.js} +9 -9
- package/dist/{config-XUUYQIWO.js → config-LW5IJFQN.js} +65 -55
- package/dist/{configure-IHJ7YOMV.js → configure-7XIZCOU4.js} +29 -24
- package/dist/{context-75MIWW3U.js → context-L3WL3X7K.js} +54 -43
- package/dist/{context-ZQ7SIFJV.js → context-N52ZA626.js} +30 -14
- package/dist/{context-74JLXAWD.js → context-Y6Y7QPR6.js} +12 -12
- package/dist/{context-clear-GYKWNUML.js → context-clear-MBQRLSDQ.js} +54 -43
- package/dist/{context-index-SSR5ECNE.js → context-index-HVMFQHK3.js} +5 -5
- package/dist/{context-working-set-UX5KEP4J.js → context-working-set-GS6DSO7F.js} +18 -18
- package/dist/{dispatch-runner-GIJBHNFL.js → dispatch-runner-22ZCNOM3.js} +367 -79
- package/dist/{docs-6FZSCG5B.js → docs-7LQ23DLM.js} +9 -9
- package/dist/{doctor-SVJ5BZCW.js → doctor-M7YEDGAE.js} +27 -23
- package/dist/{eval-CG6LLBLD.js → eval-BEC2WHDA.js} +73 -20
- package/dist/{evidence-ZYFIEN42.js → evidence-REJUMSKM.js} +70 -59
- package/dist/{evolve-QGEXEMDW.js → evolve-PY5ZBA5K.js} +50 -39
- package/dist/{extensions-ADGNCJJD.js → extensions-HVKU65YU.js} +7 -7
- package/dist/{fleet-S5R4ZOQY.js → fleet-7WZEWRFA.js} +236 -377
- package/dist/fleet-commands-UVHWM76J.js +70 -0
- package/dist/fleet-graph-6ULH7PES.js +125 -0
- package/dist/fleet-new-RDVJLHHH.js +48 -0
- package/dist/{fleet-preflight-BHSNPBMH.js → fleet-preflight-J53T6CCE.js} +5 -5
- package/dist/fleet-validate-72PC4SLA.js +79 -0
- package/dist/{init-5DRU55YR.js → init-OG3TPGQG.js} +69 -57
- package/dist/library-CNTMPLRF.js +217 -0
- package/dist/{memory-7YKKR6UC.js → memory-6IS7F275.js} +52 -41
- package/dist/{models-ZPOLRU2C.js → models-ENRJDA5W.js} +37 -31
- package/dist/{monitor-US5F5YGZ.js → monitor-XLDVO7TN.js} +79 -42
- package/dist/{orchestrator-E2AL4T5N.js → orchestrator-6KSPYRHA.js} +4126 -762
- package/dist/{paths-E7KYAQWE.js → paths-DBXMZMDU.js} +6 -6
- package/dist/registry-LG64LTF4.js +11 -0
- package/dist/{reset-KZ652EK6.js → reset-RZ4ER727.js} +12 -12
- package/dist/{run-SRNBKDWD.js → run-Y2CNK5RU.js} +89 -76
- package/dist/{share-CGZE33UP.js → share-A55GYP6Z.js} +37 -13
- package/dist/{skills-S2X4DLY5.js → skills-ALC5J6AT.js} +29 -13
- package/dist/{skills-eval-W2GGIC4R.js → skills-eval-JPBEBYQU.js} +60 -48
- package/dist/support-MIETYA5E.js +38 -0
- package/dist/{targets-54SWINWB.js → targets-VGNXIR3S.js} +46 -36
- package/dist/{terminal-lease-SAIF2OGY.js → terminal-lease-WOBR64YA.js} +4 -4
- package/dist/{uninstall-BVLWXKBT.js → uninstall-ZJF5H5ZN.js} +9 -9
- package/dist/{upgrade-JKAR27XC.js → upgrade-FUSUAGHR.js} +31 -28
- package/dist/{usage-MSAWCLX4.js → usage-N4MKVHKD.js} +140 -68
- package/dist/verifiers-YAWOJ3H2.js +336 -0
- package/dist/{verify-X5HDROLA.js → verify-LTDHYBGY.js} +10 -9
- package/dist/{wiki-generate-GUSOQ6ZP.js → wiki-generate-6M7GHTBJ.js} +75 -62
- package/dist/worker/entry.js +67 -57
- package/docs/README.md +3 -2
- package/docs/acp.md +1 -1
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +2 -2
- package/docs/artifact-versions.md +11 -6
- package/docs/built-in-agents.md +26 -2
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +83 -3
- package/docs/configuration-and-targets.md +86 -4
- package/docs/context-engine.md +1 -1
- package/docs/development-pipeline.md +1 -1
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +3 -3
- package/docs/documentation-guide.md +3 -3
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +1 -1
- package/docs/evidence-and-memory.md +74 -10
- package/docs/evolution.md +1 -1
- package/docs/exit-codes-and-output.md +4 -1
- package/docs/extensions-and-sharing.md +6 -2
- package/docs/fleet-demo-runbook.md +2 -2
- package/docs/fleet-dispatch.md +228 -16
- package/docs/git-commit-provenance.md +2 -2
- package/docs/glossary.md +22 -2
- package/docs/installation-and-lifecycle.md +2 -2
- package/docs/middleware-and-components.md +2 -1
- package/docs/model-catalog.md +1 -1
- package/docs/observability.md +56 -9
- package/docs/proactive-memory.md +1 -1
- package/docs/prompt-envelope-and-tools.md +4 -2
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +83 -65
- package/docs/resource-library.md +59 -0
- package/docs/safety-model.md +2 -2
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +37 -1
- package/docs/skills-marketplace.md +16 -3
- package/docs/tool-usage.md +14 -7
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +1 -1
- package/docs/tui-design.md +1 -1
- package/docs/worker-dispatch-mechanics.md +3 -3
- package/package.json +1 -2
- package/src/cli/argv.ts +5 -0
- package/src/cli/configure.ts +107 -23
- package/src/cli/doctor.ts +5 -1
- package/src/cli/evidence.ts +30 -25
- package/src/cli/fleet-commands.ts +37 -0
- package/src/cli/fleet-graph.ts +102 -0
- package/src/cli/fleet-new.ts +36 -0
- package/src/cli/fleet-preflight.ts +111 -0
- package/src/cli/fleet-validate.ts +30 -0
- package/src/cli/fleet.ts +173 -335
- package/src/cli/index.ts +3 -1
- package/src/cli/library.ts +190 -0
- package/src/cli/share.ts +13 -1
- package/src/cli/shared.ts +1 -0
- package/src/cli/targets.ts +4 -1
- package/src/cli/usage.ts +111 -19
- package/src/cli/validate-model.ts +60 -5
- package/src/core/bus-events.ts +29 -0
- package/src/core/commit-attribution.ts +4 -4
- package/src/core/config.ts +130 -0
- package/src/core/defaults.ts +81 -0
- package/src/core/path-boundary.ts +100 -0
- package/src/domains/agents/builtins/architect.md +1 -0
- package/src/domains/agents/builtins/oracle.md +33 -0
- package/src/domains/agents/catalog.ts +13 -1
- package/src/domains/agents/extension.ts +2 -11
- package/src/domains/agents/fleet-contract.ts +304 -24
- package/src/domains/agents/index.ts +14 -0
- package/src/domains/agents/recipe.ts +7 -1
- package/src/domains/agents/registry.ts +73 -5
- package/src/domains/agents/result-contract.ts +360 -15
- package/src/domains/agents/write-boundary.ts +15 -50
- package/src/domains/config/classify.ts +4 -0
- package/src/domains/context/project-rules.ts +51 -1
- package/src/domains/dispatch/active-route-planner.ts +14 -0
- package/src/domains/dispatch/assignment-reconcile.ts +22 -5
- package/src/domains/dispatch/assignment-store.ts +151 -14
- package/src/domains/dispatch/backoff.ts +2 -1
- package/src/domains/dispatch/capability-match.ts +1 -0
- package/src/domains/dispatch/checkout-writer-lease.ts +175 -0
- package/src/domains/dispatch/contract.ts +48 -0
- package/src/domains/dispatch/delegation-plan.ts +164 -0
- package/src/domains/dispatch/execution-plan.ts +76 -5
- package/src/domains/dispatch/execution-role.ts +12 -2
- package/src/domains/dispatch/execution-scheduler.ts +183 -67
- package/src/domains/dispatch/extension.ts +412 -74
- package/src/domains/dispatch/fleet-gate.ts +14 -0
- package/src/domains/dispatch/fleet-plan.ts +63 -3
- package/src/domains/dispatch/fleet-run.ts +791 -0
- package/src/domains/dispatch/gate-role-prompts.ts +47 -0
- package/src/domains/dispatch/host-verification.ts +178 -0
- package/src/domains/dispatch/index.ts +41 -1
- package/src/domains/dispatch/intent-requirements.ts +40 -0
- package/src/domains/dispatch/intent.ts +235 -0
- package/src/domains/dispatch/path-scope.ts +370 -0
- package/src/domains/dispatch/receipt-integrity.ts +9 -4
- package/src/domains/dispatch/state.ts +36 -3
- package/src/domains/dispatch/types.ts +64 -12
- package/src/domains/dispatch/validation.ts +69 -6
- package/src/domains/dispatch/write-boundary-enforcer.ts +45 -0
- package/src/domains/dispatch/write-boundary.ts +201 -22
- package/src/domains/eval/metrics/evidence.ts +79 -2
- package/src/domains/eval/runners/clio-run.ts +12 -2
- package/src/domains/evidence/build.ts +69 -11
- package/src/domains/evidence/index.ts +21 -0
- package/src/domains/evidence/provenance.ts +46 -11
- package/src/domains/evidence/trust-projection.ts +274 -0
- package/src/domains/evidence/trust-status.ts +155 -18
- package/src/domains/evidence/types.ts +4 -0
- package/src/domains/extensions/discovery.ts +88 -1
- package/src/domains/extensions/resources.ts +20 -8
- package/src/domains/extensions/state.ts +6 -2
- package/src/domains/extensions/types.ts +4 -1
- package/src/domains/lifecycle/doctor.ts +140 -1
- package/src/domains/middleware/index.ts +15 -0
- package/src/domains/middleware/watchdog.ts +281 -0
- package/src/domains/observability/contract.ts +3 -1
- package/src/domains/observability/cost.ts +12 -1
- package/src/domains/observability/extension.ts +2 -2
- package/src/domains/observability/index.ts +10 -0
- package/src/domains/observability/out-of-turn-usage.ts +223 -0
- package/src/domains/prompts/contract.ts +3 -5
- package/src/domains/providers/extension.ts +30 -2
- package/src/domains/resources/common-loader.ts +3 -0
- package/src/domains/resources/index.ts +20 -0
- package/src/domains/resources/library.ts +326 -0
- package/src/domains/resources/prompts/loader.ts +119 -14
- package/src/domains/resources/skills/marketplace.ts +37 -12
- package/src/domains/safety/policy-engine.ts +5 -5
- package/src/domains/safety/run-effects.ts +64 -1
- package/src/domains/safety/scope.ts +7 -12
- package/src/domains/session/handoff.ts +629 -0
- package/src/domains/share/archive.ts +67 -2
- package/src/engine/acp/server.ts +4 -1
- package/src/engine/prompt-templates.ts +18 -1
- package/src/engine/worker-runtime.ts +6 -3
- package/src/entry/orchestrator.ts +37 -0
- package/src/interactive/bus-notices.ts +26 -0
- package/src/interactive/chat-loop.ts +235 -1
- package/src/interactive/chat-renderer.ts +22 -0
- package/src/interactive/cost-overlay.ts +31 -3
- package/src/interactive/council-dispatch.ts +30 -0
- package/src/interactive/council-grid.ts +213 -0
- package/src/interactive/council.ts +99 -0
- package/src/interactive/dispatch-board.ts +311 -17
- package/src/interactive/fleet-run-preview.ts +307 -0
- package/src/interactive/footer/notifications.ts +219 -0
- package/src/interactive/handoff-round.ts +56 -0
- package/src/interactive/interactive-application.ts +43 -1
- package/src/interactive/interactive-event-projection.ts +23 -1
- package/src/interactive/interactive-slash-runtime.ts +52 -2
- package/src/interactive/interactive-subscriptions.ts +14 -2
- package/src/interactive/oracle.ts +179 -0
- package/src/interactive/overlay-ask-user-lifecycle.ts +6 -0
- package/src/interactive/overlay-general-openers.ts +190 -1
- package/src/interactive/overlay-key-routing.ts +17 -1
- package/src/interactive/overlay-lifecycle.ts +41 -1
- package/src/interactive/overlay-permission-lifecycle.ts +10 -0
- package/src/interactive/overlay-resource-openers.ts +11 -3
- package/src/interactive/overlay-session-lifecycle.ts +234 -2
- package/src/interactive/overlays/fleet-run-approval.ts +208 -0
- package/src/interactive/overlays/handoff-review.ts +185 -0
- package/src/interactive/overlays/library-install-confirm.ts +151 -0
- package/src/interactive/overlays/list-overlay.ts +168 -2
- package/src/interactive/overlays/settings.ts +221 -30
- package/src/interactive/overlays/side-question.ts +139 -0
- package/src/interactive/overlays/skills-hub.ts +401 -15
- package/src/interactive/side-question.ts +171 -0
- package/src/interactive/slash-commands.ts +439 -7
- package/src/interactive/slash-spec.ts +19 -6
- package/src/interactive/theme/tokens.ts +30 -0
- package/src/interactive/turn-middleware.ts +15 -1
- package/src/interactive/view/artifacts.ts +42 -9
- package/src/interactive/view/view-overlay.ts +15 -3
- package/src/interactive/watchdog-run.ts +75 -0
- package/src/interactive/worker-receipts.ts +14 -2
- package/src/interactive/worker-share.ts +56 -1
- package/src/interactive/worker-stream.ts +15 -0
- package/src/tools/bootstrap.ts +3 -0
- package/src/tools/compete-worktrees.ts +13 -79
- package/src/tools/dispatch-admission.ts +251 -18
- package/src/tools/dispatch-arguments.ts +84 -1
- package/src/tools/dispatch-plan.ts +165 -6
- package/src/tools/dispatch-runner.ts +364 -23
- package/src/tools/dispatch-types.ts +20 -1
- package/src/tools/dispatch.ts +72 -2
- package/src/tools/monitor.ts +29 -0
- package/src/tools/profiles.ts +18 -4
- package/src/tools/task-worktree.ts +238 -0
- package/src/tools/verify/authoring.ts +61 -1
- package/src/tools/verify/scripts.ts +62 -0
- package/src/tools/worker-evidence.ts +21 -14
- package/src/worker/spec-contract.ts +3 -1
- 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
|
-
| {
|
|
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 =
|
|
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?: {
|
|
310
|
-
|
|
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
|
-
:
|
|
331
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
:
|
|
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
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
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
|
|
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 {
|