@iowarp/clio-coder 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/CHANGELOG.md +407 -0
  2. package/CODE_OF_CONDUCT.md +21 -0
  3. package/CONTRIBUTING.md +224 -0
  4. package/LICENSE +202 -0
  5. package/NOTICE +9 -0
  6. package/README.md +798 -0
  7. package/SECURITY.md +72 -0
  8. package/assets/clio-coder-logo-128.webp +0 -0
  9. package/damage-control-rules.yaml +419 -0
  10. package/dist/acp-UMLFVA3F.js +92 -0
  11. package/dist/agents-Q4MYPMUW.js +91 -0
  12. package/dist/auth-O6HYIJ6J.js +521 -0
  13. package/dist/chunk-262G75JS.js +35 -0
  14. package/dist/chunk-26BZQOAD.js +1281 -0
  15. package/dist/chunk-2J63S4SF.js +508 -0
  16. package/dist/chunk-3DANZDGR.js +717 -0
  17. package/dist/chunk-4UQA7NCT.js +29 -0
  18. package/dist/chunk-527KG6XR.js +497 -0
  19. package/dist/chunk-5LDRNKX2.js +1063 -0
  20. package/dist/chunk-5N2FG33Q.js +25 -0
  21. package/dist/chunk-67MTHP2E.js +135 -0
  22. package/dist/chunk-6CWDTGUC.js +20 -0
  23. package/dist/chunk-7BHLZB3A.js +2115 -0
  24. package/dist/chunk-7RBKDI66.js +348 -0
  25. package/dist/chunk-AMFR5YA3.js +541 -0
  26. package/dist/chunk-BBUH4VAA.js +1224 -0
  27. package/dist/chunk-BYEU76JP.js +899 -0
  28. package/dist/chunk-CLJ5HLUD.js +458 -0
  29. package/dist/chunk-D5YD55AR.js +116 -0
  30. package/dist/chunk-DXQNI4PC.js +61 -0
  31. package/dist/chunk-E3NYWENM.js +1004 -0
  32. package/dist/chunk-GNGDQYDU.js +34688 -0
  33. package/dist/chunk-GOTUR54M.js +9 -0
  34. package/dist/chunk-HBU5MTAM.js +41 -0
  35. package/dist/chunk-HMYNFFY4.js +28 -0
  36. package/dist/chunk-JPOWPFCU.js +1010 -0
  37. package/dist/chunk-JWHCJDCI.js +1215 -0
  38. package/dist/chunk-KBR4MZZR.js +41 -0
  39. package/dist/chunk-KKKPTZLM.js +93 -0
  40. package/dist/chunk-ME6DNWIU.js +66 -0
  41. package/dist/chunk-NI4DEJMC.js +88 -0
  42. package/dist/chunk-O4EJEDHO.js +659 -0
  43. package/dist/chunk-PIDUD6M2.js +31 -0
  44. package/dist/chunk-PS4PFJQP.js +29459 -0
  45. package/dist/chunk-QV47YRF4.js +48 -0
  46. package/dist/chunk-RQDWMVRB.js +279 -0
  47. package/dist/chunk-TFSSEXL6.js +136 -0
  48. package/dist/chunk-TKHQ4DGZ.js +8290 -0
  49. package/dist/chunk-TPOCL34A.js +2876 -0
  50. package/dist/chunk-UGYAX5YI.js +565 -0
  51. package/dist/chunk-UHTSULZS.js +461 -0
  52. package/dist/chunk-UU3R62TT.js +128 -0
  53. package/dist/chunk-UWIJNAOB.js +3906 -0
  54. package/dist/chunk-VOO7NYPP.js +914 -0
  55. package/dist/chunk-VPAWTYLY.js +117 -0
  56. package/dist/chunk-WD6AJM35.js +1216 -0
  57. package/dist/chunk-X3BR7HWV.js +115 -0
  58. package/dist/chunk-X3NE4WVW.js +120 -0
  59. package/dist/chunk-XNISANGE.js +1395 -0
  60. package/dist/chunk-XV4ZJ6ZM.js +3177 -0
  61. package/dist/cli/index.js +236 -0
  62. package/dist/clio-KIQ5SNDS.js +53 -0
  63. package/dist/components-JVHMUBEB.js +653 -0
  64. package/dist/config-ZFCDBMDC.js +372 -0
  65. package/dist/configure-G4E3A2PG.js +27 -0
  66. package/dist/context-CDXTP2MP.js +293 -0
  67. package/dist/context-E3KIFVXI.js +185 -0
  68. package/dist/context-clear-3F4PLXOS.js +102 -0
  69. package/dist/context-index-Q7YSYTR3.js +106 -0
  70. package/dist/docs-YIETIWZI.js +280 -0
  71. package/dist/doctor-M5HJJZOL.js +61 -0
  72. package/dist/domains/agents/builtins/architect.md +33 -0
  73. package/dist/domains/agents/builtins/coder.md +31 -0
  74. package/dist/domains/agents/builtins/context-bootstrap.md +38 -0
  75. package/dist/domains/agents/builtins/debugger.md +30 -0
  76. package/dist/domains/agents/builtins/documenter.md +31 -0
  77. package/dist/domains/agents/builtins/git-master.md +30 -0
  78. package/dist/domains/agents/builtins/provenance.md +30 -0
  79. package/dist/domains/agents/builtins/researcher.md +71 -0
  80. package/dist/domains/agents/builtins/scout.md +42 -0
  81. package/dist/domains/agents/builtins/tester.md +31 -0
  82. package/dist/domains/agents/builtins/verifier.md +30 -0
  83. package/dist/domains/agents/builtins/wiki-writer.md +41 -0
  84. package/dist/eval-B3KZZESM.js +2674 -0
  85. package/dist/evidence-V67CHM35.js +233 -0
  86. package/dist/evolve-YDZSUQYA.js +518 -0
  87. package/dist/extensions-SRG7XCAH.js +207 -0
  88. package/dist/fleet-CA2CRTVG.js +760 -0
  89. package/dist/fleet-preflight-CLIAX7YR.js +21 -0
  90. package/dist/init-2OZDJE2D.js +227 -0
  91. package/dist/memory-3PIQQAKX.js +207 -0
  92. package/dist/models-DY35XI7Y.js +237 -0
  93. package/dist/paths-5OMXW7Z4.js +57 -0
  94. package/dist/preload-KZVHET2B.js +11 -0
  95. package/dist/reset-PIFYNOS3.js +216 -0
  96. package/dist/run-3VSPP24F.js +735 -0
  97. package/dist/share-D36RQCXM.js +241 -0
  98. package/dist/skills-F2MRLELY.js +445 -0
  99. package/dist/skills-eval-E2ZTW4PL.js +932 -0
  100. package/dist/targets-DZMEZAH4.js +977 -0
  101. package/dist/trace-7NYCUI2J.js +250 -0
  102. package/dist/uninstall-AD3JWHBB.js +322 -0
  103. package/dist/upgrade-WYYBKGDY.js +301 -0
  104. package/dist/usage-ULIDAGFF.js +755 -0
  105. package/dist/version-ROZ6CZKH.js +16 -0
  106. package/dist/wiki-generate-PKFIX6OB.js +377 -0
  107. package/dist/worker/entry.js +1739 -0
  108. package/docs/README.md +93 -0
  109. package/docs/acp.md +120 -0
  110. package/docs/alcf-provider.md +72 -0
  111. package/docs/architecture.md +172 -0
  112. package/docs/artifact-versions.md +54 -0
  113. package/docs/built-in-agents.md +265 -0
  114. package/docs/capacity-and-scheduling.md +97 -0
  115. package/docs/commands-and-modes.md +554 -0
  116. package/docs/config-knobs-audit.md +115 -0
  117. package/docs/configuration-and-targets.md +812 -0
  118. package/docs/context-engine.md +236 -0
  119. package/docs/dispatch-architecture-rationale.md +126 -0
  120. package/docs/documentation-coverage.md +46 -0
  121. package/docs/documentation-guide.md +166 -0
  122. package/docs/environment-variables.md +105 -0
  123. package/docs/eval-runner.md +205 -0
  124. package/docs/evals-internal.md +298 -0
  125. package/docs/evidence-and-memory.md +243 -0
  126. package/docs/evolution.md +143 -0
  127. package/docs/exit-codes-and-output.md +74 -0
  128. package/docs/extensions-and-sharing.md +306 -0
  129. package/docs/fleet-demo-runbook.md +179 -0
  130. package/docs/fleet-dispatch.md +591 -0
  131. package/docs/glossary.md +75 -0
  132. package/docs/html/agents_blueprint.html +936 -0
  133. package/docs/html/alcf_blueprint.html +324 -0
  134. package/docs/html/architecture_blueprint.html +850 -0
  135. package/docs/html/commands_blueprint.html +794 -0
  136. package/docs/html/config_knobs_audit_blueprint.html +178 -0
  137. package/docs/html/configuration_blueprint.html +1080 -0
  138. package/docs/html/context_blueprint.html +603 -0
  139. package/docs/html/documentation_blueprint.html +832 -0
  140. package/docs/html/environment_blueprint.html +404 -0
  141. package/docs/html/eval_blueprint.html +743 -0
  142. package/docs/html/evals_internal_blueprint.html +190 -0
  143. package/docs/html/evolution_blueprint.html +674 -0
  144. package/docs/html/extensions_blueprint.html +2065 -0
  145. package/docs/html/fleet_dispatch_blueprint.html +286 -0
  146. package/docs/html/index.html +919 -0
  147. package/docs/html/lifecycle_blueprint.html +723 -0
  148. package/docs/html/memory_blueprint.html +699 -0
  149. package/docs/html/middleware_blueprint.html +664 -0
  150. package/docs/html/models_blueprint.html +2366 -0
  151. package/docs/html/observability_blueprint.html +683 -0
  152. package/docs/html/provider_adapter_blueprint.html +245 -0
  153. package/docs/html/safety_blueprint.html +1386 -0
  154. package/docs/html/shared.css +571 -0
  155. package/docs/html/shared.js +143 -0
  156. package/docs/html/skills_blueprint.html +671 -0
  157. package/docs/html/soak_blueprint.html +182 -0
  158. package/docs/html/tool_usage_blueprint.html +350 -0
  159. package/docs/html/tools_blueprint.html +2249 -0
  160. package/docs/html/trace_blueprint.html +235 -0
  161. package/docs/html/tui_design_blueprint.html +314 -0
  162. package/docs/html/validation_blueprint.html +961 -0
  163. package/docs/html/worker_dispatch_blueprint.html +231 -0
  164. package/docs/installation-and-lifecycle.md +308 -0
  165. package/docs/middleware-and-components.md +148 -0
  166. package/docs/model-catalog.md +189 -0
  167. package/docs/observability.md +233 -0
  168. package/docs/proactive-memory.md +452 -0
  169. package/docs/prompt-envelope-and-tools.md +142 -0
  170. package/docs/provider-adapter-cookbook.md +148 -0
  171. package/docs/release-cut-checklist.md +138 -0
  172. package/docs/safety-model.md +357 -0
  173. package/docs/scientific-validation.md +105 -0
  174. package/docs/session-lifecycle.md +156 -0
  175. package/docs/skills-marketplace.md +46 -0
  176. package/docs/tool-usage.md +527 -0
  177. package/docs/trace-store.md +132 -0
  178. package/docs/troubleshooting.md +33 -0
  179. package/docs/tui-design.md +239 -0
  180. package/docs/worker-dispatch-mechanics.md +242 -0
  181. package/package.json +132 -0
  182. package/skills/README.md +408 -0
  183. package/skills/git/commit-crafting/SKILL.md +79 -0
  184. package/skills/git/commit-crafting/evals.md +92 -0
  185. package/skills/git/create-pr/SKILL.md +116 -0
  186. package/skills/git/create-pr/evals.md +114 -0
  187. package/skills/git/investigate-issue/SKILL.md +139 -0
  188. package/skills/git/investigate-issue/evals.md +94 -0
  189. package/skills/git/resolve-merge-conflicts/SKILL.md +96 -0
  190. package/skills/git/resolve-merge-conflicts/evals.md +58 -0
  191. package/skills/git/review-changes/SKILL.md +103 -0
  192. package/skills/git/review-changes/evals.md +85 -0
  193. package/skills/git/worktree-create/SKILL.md +92 -0
  194. package/skills/git/worktree-create/evals.md +97 -0
  195. package/skills/git/worktree-create/references/worktree-setup.md +66 -0
  196. package/skills/git/worktree-merge/SKILL.md +95 -0
  197. package/skills/git/worktree-merge/evals.md +114 -0
  198. package/skills/skill-marketplace.json +261 -0
  199. package/skills/workflow/cut-it/SKILL.md +86 -0
  200. package/skills/workflow/cut-it/evals.md +42 -0
  201. package/src/domains/agents/builtins/architect.md +33 -0
  202. package/src/domains/agents/builtins/coder.md +31 -0
  203. package/src/domains/agents/builtins/context-bootstrap.md +38 -0
  204. package/src/domains/agents/builtins/debugger.md +30 -0
  205. package/src/domains/agents/builtins/documenter.md +31 -0
  206. package/src/domains/agents/builtins/git-master.md +30 -0
  207. package/src/domains/agents/builtins/provenance.md +30 -0
  208. package/src/domains/agents/builtins/researcher.md +71 -0
  209. package/src/domains/agents/builtins/scout.md +42 -0
  210. package/src/domains/agents/builtins/tester.md +31 -0
  211. package/src/domains/agents/builtins/verifier.md +30 -0
  212. package/src/domains/agents/builtins/wiki-writer.md +41 -0
  213. package/src/domains/agents/fleets/build-review.md +34 -0
  214. package/src/domains/agents/fleets/build-test.md +35 -0
  215. package/src/domains/agents/fleets/sdlc.md +86 -0
  216. package/src/domains/prompts/fragments/identity/clio-worker.md +11 -0
  217. package/src/domains/prompts/fragments/identity/clio.md +26 -0
  218. package/src/domains/prompts/fragments/operating/contract.md +64 -0
  219. package/src/domains/prompts/fragments/safety/auto-edit.md +14 -0
  220. package/src/domains/prompts/fragments/safety/full-auto.md +14 -0
  221. package/src/domains/prompts/fragments/safety/read-only.md +13 -0
  222. package/src/domains/prompts/fragments/safety/suggest.md +13 -0
  223. package/src/domains/prompts/fragments/wiki/page.md +75 -0
  224. package/src/domains/prompts/fragments/wiki/plan.md +48 -0
  225. package/src/domains/providers/models/cloud-models/alcf.yaml +40 -0
  226. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +993 -0
@@ -0,0 +1,760 @@
1
+ import {
2
+ SchedulingDomainModule,
3
+ createPromptsDomainModule
4
+ } from "./chunk-3DANZDGR.js";
5
+ import {
6
+ AgentsDomainModule,
7
+ SafetyDomainModule
8
+ } from "./chunk-JPOWPFCU.js";
9
+ import {
10
+ LifecycleDomainModule
11
+ } from "./chunk-NI4DEJMC.js";
12
+ import {
13
+ ensureClioState
14
+ } from "./chunk-7RBKDI66.js";
15
+ import {
16
+ ConfigDomainModule,
17
+ loadDomains
18
+ } from "./chunk-527KG6XR.js";
19
+ import "./chunk-UU3R62TT.js";
20
+ import "./chunk-HMYNFFY4.js";
21
+ import {
22
+ ContextDomainModule
23
+ } from "./chunk-UWIJNAOB.js";
24
+ import "./chunk-X3BR7HWV.js";
25
+ import "./chunk-VOO7NYPP.js";
26
+ import {
27
+ DispatchDomainModule,
28
+ MiddlewareDomainModule,
29
+ ObservabilityDomainModule,
30
+ SessionDomainModule,
31
+ WRITE_BOUNDARY_VIOLATION_REASON,
32
+ capacityDrain,
33
+ codeStepDir,
34
+ compileFleetExecutionPlan,
35
+ createWriteBoundaryEnforcer,
36
+ decideReviewGate,
37
+ executePlan,
38
+ executionPlanAncestors,
39
+ materializePendingGateDecision,
40
+ openLedger,
41
+ preflightWriteBoundaries,
42
+ runCodeStep,
43
+ setCapacityDraining,
44
+ stagePendingGateDecision,
45
+ writeCodeStepRecord
46
+ } from "./chunk-GNGDQYDU.js";
47
+ import {
48
+ ResourcesDomainModule
49
+ } from "./chunk-2J63S4SF.js";
50
+ import "./chunk-RQDWMVRB.js";
51
+ import {
52
+ agentRoleFactsResolver,
53
+ gateRouteCorrelation,
54
+ requestExecutionRole,
55
+ verifyReceiptIntegrity,
56
+ withAttemptRole
57
+ } from "./chunk-7BHLZB3A.js";
58
+ import "./chunk-TPOCL34A.js";
59
+ import "./chunk-E3NYWENM.js";
60
+ import {
61
+ FLEET_COMMANDS_REMEDY,
62
+ FLEET_COMMANDS_REPO_PATH,
63
+ FleetCommandRegistryMissingError,
64
+ listFleetContracts,
65
+ loadFleetCommands,
66
+ loadFleetContract,
67
+ renderFleetPrompt,
68
+ resultContractAuthorship
69
+ } from "./chunk-XV4ZJ6ZM.js";
70
+ import "./chunk-26BZQOAD.js";
71
+ import "./chunk-WD6AJM35.js";
72
+ import "./chunk-QV47YRF4.js";
73
+ import "./chunk-CLJ5HLUD.js";
74
+ import "./chunk-BBUH4VAA.js";
75
+ import "./chunk-GOTUR54M.js";
76
+ import "./chunk-KBR4MZZR.js";
77
+ import "./chunk-262G75JS.js";
78
+ import "./chunk-TFSSEXL6.js";
79
+ import {
80
+ ProvidersDomainModule
81
+ } from "./chunk-TKHQ4DGZ.js";
82
+ import "./chunk-D5YD55AR.js";
83
+ import "./chunk-JWHCJDCI.js";
84
+ import "./chunk-UHTSULZS.js";
85
+ import "./chunk-5LDRNKX2.js";
86
+ import "./chunk-UGYAX5YI.js";
87
+ import "./chunk-5N2FG33Q.js";
88
+ import "./chunk-VPAWTYLY.js";
89
+ import {
90
+ clioStateDir
91
+ } from "./chunk-X3NE4WVW.js";
92
+ import "./chunk-DXQNI4PC.js";
93
+
94
+ // src/cli/fleet.ts
95
+ import { randomBytes } from "node:crypto";
96
+ import { readFileSync } from "node:fs";
97
+ import { join } from "node:path";
98
+ var HELP = `clio-coder fleet <subcommand>
99
+
100
+ Repo-owned fleet contracts and the dispatch status surface.
101
+
102
+ Subcommands:
103
+ list list .clio-coder/fleets/*.md contracts with validation status
104
+ run <name> [--var k=v ...] preflight and execute a fleet contract
105
+ [--json] emit step receipts as JSON
106
+ status [--json] show running, retrying, and total dispatch state
107
+ drain [--json] deny new execution starts for up to one hour
108
+ resume [--json] reopen dispatch admission immediately
109
+
110
+ Notes:
111
+ status reads the durable run ledger. Rows started by another process show
112
+ heartbeat liveness from the recorded worker pid; per-token live meters are
113
+ only available inside the process that owns the run.
114
+ drain preserves running work. Repeat it to renew the one-hour expiry; resume
115
+ clears it early. The expiry prevents an abandoned drain from wedging Clio.
116
+ `;
117
+ function fail(message) {
118
+ process.stderr.write(`clio-coder fleet: ${message}
119
+ `);
120
+ return 2;
121
+ }
122
+ function parseVars(args) {
123
+ const vars = {};
124
+ const rest = [];
125
+ for (let i = 0; i < args.length; i++) {
126
+ const arg = args[i];
127
+ if (arg !== "--var") {
128
+ if (arg !== void 0) rest.push(arg);
129
+ continue;
130
+ }
131
+ const pair = args[i + 1];
132
+ i += 1;
133
+ if (pair === void 0 || !pair.includes("=")) {
134
+ return { vars, rest, error: "--var requires key=value" };
135
+ }
136
+ const eq = pair.indexOf("=");
137
+ const key = pair.slice(0, eq).trim();
138
+ const value = pair.slice(eq + 1);
139
+ if (key.length === 0) return { vars, rest, error: "--var requires a non-empty key" };
140
+ vars[key] = value;
141
+ }
142
+ return { vars, rest };
143
+ }
144
+ function fleetGateCorrelation(subject, decider) {
145
+ const facts = (receipt) => ({
146
+ agentId: receipt.agentId,
147
+ targetId: receipt.targetId,
148
+ wireModelId: receipt.wireModelId,
149
+ runtimeId: receipt.runtimeId,
150
+ nodeId: receipt.node?.id ?? "local"
151
+ });
152
+ const { agent, target, modelFamily, runtime, node, independent } = gateRouteCorrelation(
153
+ facts(subject),
154
+ facts(decider)
155
+ );
156
+ return { agent, target, modelFamily, runtime, node, independent };
157
+ }
158
+ var NO_WORKER_RESERVATION = "fleet-no-worker-reservation";
159
+ function newFleetRootId() {
160
+ return `fleet-${randomBytes(6).toString("hex")}`;
161
+ }
162
+ function renderStep(step) {
163
+ if (step.kind === "code") return `code:${step.command}[${step.scope}]`;
164
+ if (step.kind === "agent") return `${step.agent}[${step.scope}]`;
165
+ const check = step.check.kind === "code" ? `code:${step.check.command}` : step.check.agent;
166
+ return `loop:${step.id}(${check} -> ${step.repair.agent} x${step.maxAttempts})`;
167
+ }
168
+ function listingLine(entry, state, detail) {
169
+ return `${entry.name} ${entry.source} ${state.padEnd(7)} ${detail}
170
+ `;
171
+ }
172
+ function runList() {
173
+ const listings = listFleetContracts(process.cwd());
174
+ if (listings.length === 0) {
175
+ process.stdout.write("no fleet contracts found (.clio-coder/fleets/*.md)\n");
176
+ return 0;
177
+ }
178
+ for (const entry of listings) {
179
+ if (entry.contract !== null) {
180
+ const steps = entry.contract.steps.map(renderStep).join(" -> ");
181
+ process.stdout.write(listingLine(entry, "valid", steps));
182
+ if (entry.contract.description.length > 0) {
183
+ process.stdout.write(` ${entry.contract.description}
184
+ `);
185
+ }
186
+ continue;
187
+ }
188
+ if (entry.needsCommands !== null) {
189
+ process.stdout.write(
190
+ listingLine(entry, "setup", `needs ${FLEET_COMMANDS_REPO_PATH} declaring ${entry.needsCommands.join(", ")}`)
191
+ );
192
+ process.stdout.write(` ${FLEET_COMMANDS_REMEDY}
193
+ `);
194
+ continue;
195
+ }
196
+ process.stdout.write(listingLine(entry, "invalid", entry.error ?? "unknown error"));
197
+ }
198
+ return 0;
199
+ }
200
+ function contractAgents(contract) {
201
+ const agents = [];
202
+ for (const step of contract.steps) {
203
+ if (step.kind === "agent") agents.push({ id: step.id, agent: step.agent, scope: step.scope });
204
+ else if (step.kind === "loop") {
205
+ if (step.check.kind === "agent") {
206
+ agents.push({ id: `${step.id}.check`, agent: step.check.agent, scope: step.check.scope });
207
+ }
208
+ agents.push({ id: `${step.id}.repair`, agent: step.repair.agent, scope: step.repair.scope });
209
+ }
210
+ }
211
+ return agents;
212
+ }
213
+ function preflightFleet(contract, deps) {
214
+ for (const step of contractAgents(contract)) {
215
+ if (!deps.agents.get(step.agent)) {
216
+ return `unknown agent '${step.agent}' (step '${step.id}' must name a recipe from 'clio-coder agents')`;
217
+ }
218
+ const requested = step.scope === "readonly" ? deps.safety.scopes.readonly : deps.safety.scopes.workspace;
219
+ if (!deps.safety.isSubset(requested, deps.safety.scopes.workspace)) {
220
+ return `step '${step.id}' scope '${step.scope}' exceeds the orchestrator scope`;
221
+ }
222
+ }
223
+ if (deps.scheduling) {
224
+ const budget = deps.scheduling.preflight();
225
+ if (budget.verdict === "over" || budget.verdict === "at") {
226
+ return `budget ceiling crossed: $${budget.currentUsd.toFixed(4)} / $${budget.ceilingUsd.toFixed(4)}`;
227
+ }
228
+ if (contract.budgetUsd !== null) {
229
+ const remaining = budget.ceilingUsd - budget.currentUsd;
230
+ if (contract.budgetUsd > remaining) {
231
+ return `fleet budget $${contract.budgetUsd.toFixed(2)} exceeds remaining session budget $${remaining.toFixed(2)}`;
232
+ }
233
+ }
234
+ }
235
+ return null;
236
+ }
237
+ async function runFleet(args) {
238
+ const { vars, rest, error } = parseVars(args);
239
+ if (error !== void 0) return fail(error);
240
+ const json = rest.includes("--json");
241
+ const name = rest.find((arg) => !arg.startsWith("-"));
242
+ if (!name) return fail("usage: clio-coder fleet run <name> [--var key=value ...] [--json]");
243
+ let contract;
244
+ let prompt;
245
+ let commands;
246
+ try {
247
+ contract = loadFleetContract(process.cwd(), name);
248
+ prompt = renderFleetPrompt(contract.body, vars);
249
+ commands = loadFleetCommands(process.cwd());
250
+ } catch (err) {
251
+ if (err instanceof FleetCommandRegistryMissingError) {
252
+ process.stderr.write(`clio-coder fleet: ${err.message}
253
+ ${FLEET_COMMANDS_REMEDY}
254
+ `);
255
+ return 2;
256
+ }
257
+ return fail(err instanceof Error ? err.message : String(err));
258
+ }
259
+ ensureClioState();
260
+ const loaded = await loadDomains([
261
+ ConfigDomainModule,
262
+ ResourcesDomainModule,
263
+ ContextDomainModule,
264
+ ProvidersDomainModule,
265
+ SafetyDomainModule,
266
+ createPromptsDomainModule({ noContextFiles: true }),
267
+ AgentsDomainModule,
268
+ MiddlewareDomainModule,
269
+ ObservabilityDomainModule,
270
+ SchedulingDomainModule,
271
+ DispatchDomainModule,
272
+ SessionDomainModule,
273
+ LifecycleDomainModule
274
+ ]);
275
+ const dispatch = loaded.getContract("dispatch");
276
+ const agents = loaded.getContract("agents");
277
+ const safety = loaded.getContract("safety");
278
+ const scheduling = loaded.getContract("scheduling");
279
+ if (!dispatch || !agents || !safety) {
280
+ await loaded.stop();
281
+ return fail("required domains unavailable (dispatch/agents/safety)");
282
+ }
283
+ const roleFacts = agentRoleFactsResolver((id) => agents.getSpec(id));
284
+ const preflightError = preflightFleet(contract, { agents, safety, scheduling });
285
+ if (preflightError !== null) {
286
+ await loaded.stop();
287
+ return fail(`preflight failed: ${preflightError}`);
288
+ }
289
+ const fleetRootId = newFleetRootId();
290
+ let planOutcome;
291
+ let plan;
292
+ try {
293
+ plan = compileFleetExecutionPlan({
294
+ contract,
295
+ task: prompt,
296
+ resolveAgent(context) {
297
+ const spec = agents.getSpec(context.agentId);
298
+ if (spec === null || spec.capabilityClass === "orchestration" || spec.capabilityClass === "internal") {
299
+ throw new Error(`fleet step '${context.stepId}' has no automatable agent authority`);
300
+ }
301
+ const requestRole = requestExecutionRole({
302
+ agentId: context.agentId,
303
+ resolveFacts: roleFacts,
304
+ ...context.gateRole !== void 0 ? { gateRole: context.gateRole } : {}
305
+ });
306
+ return {
307
+ requestedAuthority: spec.capabilityClass,
308
+ approvedAuthority: spec.capabilityClass,
309
+ // A gate decider answers the coordinator's question, so its
310
+ // postcondition is the gate result contract, not its recipe's.
311
+ expectedResultContract: context.gateRole === "reviewer" ? "verifier-report" : spec.resultContract.kind,
312
+ executionRole: withAttemptRole(requestRole, context.attempt)
313
+ };
314
+ }
315
+ });
316
+ } catch (err) {
317
+ await loaded.stop();
318
+ return fail(err instanceof Error ? err.message : String(err));
319
+ }
320
+ try {
321
+ preflightWriteBoundaries(plan, process.cwd());
322
+ } catch (err) {
323
+ await loaded.stop();
324
+ return fail(`preflight failed: ${err instanceof Error ? err.message : String(err)}`);
325
+ }
326
+ const boundaryByStep = new Map(plan.steps.map((step) => [step.id, step.writes]));
327
+ const boundaryEnforcer = createWriteBoundaryEnforcer({
328
+ root: process.cwd(),
329
+ rootId: fleetRootId,
330
+ boundaryFor: (stepId) => boundaryByStep.get(stepId),
331
+ onVerdict(verdict, path) {
332
+ if (verdict.reason === null) return;
333
+ process.stderr.write(`write boundary ${verdict.window}: ${verdict.detail ?? verdict.reason} record=${path}
334
+ `);
335
+ }
336
+ });
337
+ process.stderr.write(
338
+ `fleet ${contract.name}: root=${fleetRootId} plan=${plan.hash} steps=${plan.steps.length} loops=${plan.loops.length}
339
+ `
340
+ );
341
+ const receipts = [];
342
+ const receiptsByStep = /* @__PURE__ */ new Map();
343
+ const planStep = (stepId) => plan.steps.find((entry) => entry.id === stepId);
344
+ const commitMessageFor = (step, priorResults) => {
345
+ for (const candidate of step.commitFrom ?? []) {
346
+ const source = planStep(candidate);
347
+ const result = priorResults.get(candidate);
348
+ if (source === void 0 || source.kind !== "agent" || result === void 0) continue;
349
+ const resultContract = agents.getSpec(source.agentId)?.resultContract ?? null;
350
+ if (resultContract === null) continue;
351
+ const authored = resultContractAuthorship(resultContract, result.output);
352
+ if (authored.commitMessage !== null) return authored.commitMessage;
353
+ if (authored.summary !== null) return `clio(${fleetRootId}): ${authored.summary}`;
354
+ }
355
+ return `clio(${fleetRootId}): ${contract.name} ${step.id}`;
356
+ };
357
+ try {
358
+ planOutcome = await executePlan(plan, {
359
+ preflight(step) {
360
+ const request = {
361
+ agentId: step.agentId,
362
+ executionRole: step.executionRole,
363
+ task: step.task,
364
+ requestOrigin: "user",
365
+ lineage: { parentRunId: fleetRootId, rootRunId: fleetRootId, attempt: 0, depth: 1 },
366
+ ...step.scope === "readonly" ? { autonomy: "read-only" } : {}
367
+ };
368
+ const resolution = dispatch.preview?.(request);
369
+ if (!resolution) throw new Error(`fleet preflight cannot resolve step '${step.id}'`);
370
+ return { step, costUpperBoundUsd: resolution.costUpperBoundUsd, nodeId: resolution.node.id };
371
+ },
372
+ reserve(_plan, admissions) {
373
+ if (admissions.length === 0) return { ownerId: NO_WORKER_RESERVATION };
374
+ const reservation = dispatch.reservations?.prepare({
375
+ topology: "parallel",
376
+ tasks: admissions.map((admission) => ({
377
+ memberId: admission.step.id,
378
+ wave: plan.waves.findIndex((wave) => wave.includes(admission.step.id)),
379
+ resolution: dispatch.preview?.({
380
+ agentId: admission.step.agentId,
381
+ executionRole: admission.step.executionRole,
382
+ task: admission.step.task
383
+ })
384
+ }))
385
+ });
386
+ if (!reservation) throw new Error("fleet whole-plan reservation is unavailable");
387
+ return { ownerId: reservation.ownerId };
388
+ },
389
+ async run(step, handoffs, reservation, ledger) {
390
+ const attempt = step.loop?.role === "repair" ? step.loop.attempt : 0;
391
+ const request = {
392
+ agentId: step.agentId,
393
+ executionRole: step.executionRole,
394
+ task: step.task,
395
+ predecessorHandoffs: handoffs,
396
+ requestOrigin: "user",
397
+ lineage: { parentRunId: fleetRootId, rootRunId: fleetRootId, attempt, depth: 1 },
398
+ reservation,
399
+ ...ledger !== void 0 ? { ledger } : {},
400
+ ...step.loop?.role === "check" ? {
401
+ gate: {
402
+ role: "reviewer",
403
+ group: `${fleetRootId}:${step.loop.loopId}`,
404
+ cycle: step.loop.attempt,
405
+ subjects: handoffs.map((handoff) => ({
406
+ runId: handoff.terminalRunId,
407
+ digest: handoff.receiptDigest
408
+ }))
409
+ }
410
+ } : {},
411
+ ...step.scope === "readonly" ? { autonomy: "read-only" } : {}
412
+ };
413
+ const handle = await dispatch.dispatch(request);
414
+ void (async () => {
415
+ for await (const _event of handle.events) {
416
+ }
417
+ })().catch(() => {
418
+ });
419
+ return {
420
+ assignmentId: handle.runId,
421
+ result: handle.finalPromise.then((receipt) => {
422
+ receipts.push(receipt);
423
+ receiptsByStep.set(step.id, receipt);
424
+ const envelope = dispatch.getRun(receipt.runId);
425
+ const integrityValid = envelope !== null && verifyReceiptIntegrity(receipt, envelope).ok;
426
+ const succeeded = receipt.exitCode === 0 && (receipt.outcome === void 0 || receipt.outcome === "succeeded");
427
+ if (json) process.stdout.write(`${JSON.stringify(receipt)}
428
+ `);
429
+ else
430
+ process.stdout.write(
431
+ `step ${step.id} ${step.agentId}: ${succeeded ? "succeeded" : "failed"} assignment=${handle.runId} terminal-run=${receipt.runId} cost=$${receipt.costUsd.toFixed(4)}
432
+ `
433
+ );
434
+ return {
435
+ stepId: step.id,
436
+ assignmentId: handle.runId,
437
+ terminalRunId: receipt.runId,
438
+ receiptDigest: receipt.integrity.digest,
439
+ output: receipt.output?.state === "final" ? receipt.output.text : "",
440
+ succeeded,
441
+ integrityValid
442
+ };
443
+ })
444
+ };
445
+ },
446
+ async runCode(step, _handoffs, signal, priorResults) {
447
+ const command = commands?.commands.get(step.commandId);
448
+ if (command === void 0) throw new Error(`fleet code step '${step.id}' has no registered command`);
449
+ const isCommit = step.commitFrom !== void 0;
450
+ const outcome = await runCodeStep({
451
+ stepId: step.id,
452
+ command,
453
+ workspaceRoot: process.cwd(),
454
+ artifactDir: codeStepDir(fleetRootId),
455
+ signal,
456
+ ...isCommit ? {
457
+ substitutions: { commitMessage: commitMessageFor(step, priorResults) },
458
+ requireWorkspaceChanges: true
459
+ } : {}
460
+ });
461
+ const recordPath = await writeCodeStepRecord(fleetRootId, outcome.record);
462
+ if (json) process.stdout.write(`${JSON.stringify({ codeStep: outcome.record })}
463
+ `);
464
+ else
465
+ process.stdout.write(
466
+ `step ${step.id} code:${command.id}: ${outcome.report.passed ? "passed" : "failed"} exit=${outcome.report.exitCode} ${outcome.record.durationMs}ms record=${recordPath}
467
+ `
468
+ );
469
+ return {
470
+ stepId: step.id,
471
+ assignmentId: outcome.record.runId,
472
+ terminalRunId: outcome.record.runId,
473
+ receiptDigest: outcome.record.reportDigest,
474
+ output: outcome.output,
475
+ succeeded: outcome.report.passed,
476
+ // The runner authored this report itself, so its provenance is
477
+ // valid by construction; only the command's verdict can be red.
478
+ integrityValid: true
479
+ };
480
+ },
481
+ async decideLoop({ loop, step, attempt, terminalAttempt, result }) {
482
+ const decider = receiptsByStep.get(step.id);
483
+ const ancestors = executionPlanAncestors(plan, step.id);
484
+ let subject;
485
+ for (const [stepId, receipt] of receiptsByStep) {
486
+ if (ancestors.has(stepId)) subject = receipt;
487
+ }
488
+ if (decider === void 0 || subject === void 0) {
489
+ return {
490
+ resolved: false,
491
+ findings: null,
492
+ needsDecision: `loop '${loop.id}' cycle ${attempt} has no sealed reviewer or subject receipt`
493
+ };
494
+ }
495
+ const decided = decideReviewGate({
496
+ group: `${fleetRootId}:${loop.id}`,
497
+ cycle: attempt,
498
+ terminalCycle: terminalAttempt,
499
+ subjects: [{ runId: subject.runId, digest: subject.integrity.digest }],
500
+ decider: { runId: decider.runId, digest: decider.integrity.digest },
501
+ correlation: fleetGateCorrelation(subject, decider),
502
+ output: result.output
503
+ });
504
+ const staged = stagePendingGateDecision(decided.draft);
505
+ const { path: decisionPath } = materializePendingGateDecision(staged);
506
+ if (!json) {
507
+ process.stdout.write(
508
+ `loop ${loop.id} cycle ${attempt}: ${decided.draft.outcome}${decided.draft.detail === void 0 ? "" : ` (${decided.draft.detail})`} decision=${decisionPath}
509
+ `
510
+ );
511
+ }
512
+ return {
513
+ resolved: decided.verdict === "pass",
514
+ findings: decided.findings,
515
+ needsDecision: decided.needsDecision
516
+ };
517
+ },
518
+ beginWriteBoundary: (window, stepIds) => boundaryEnforcer.begin(window, stepIds),
519
+ verifyWriteBoundary: (window, stepIds) => boundaryEnforcer.verify(window, stepIds),
520
+ cancel: (assignmentId) => dispatch.abort(assignmentId),
521
+ release: (ownerId) => {
522
+ if (ownerId === NO_WORKER_RESERVATION) return;
523
+ dispatch.reservations?.rollbackUnconsumed(ownerId);
524
+ },
525
+ releaseUnconsumed: (ownerId) => {
526
+ if (ownerId === NO_WORKER_RESERVATION) return;
527
+ dispatch.reservations?.rollbackUnconsumed(ownerId);
528
+ }
529
+ });
530
+ } catch (err) {
531
+ await dispatch.drain();
532
+ await loaded.stop();
533
+ return fail(err instanceof Error ? err.message : String(err));
534
+ }
535
+ await dispatch.drain();
536
+ await loaded.stop();
537
+ const required = plan.steps.filter((step) => step.loop === void 0 && !planOutcome.unneeded.includes(step.id));
538
+ const failedLoops = planOutcome.loops.filter((loop) => !loop.resolved);
539
+ const succeededSteps = required.filter((step) => planOutcome.results.get(step.id)?.succeeded === true).length;
540
+ const resolvedLoops = planOutcome.loops.length - failedLoops.length;
541
+ if (json) {
542
+ process.stdout.write(
543
+ `${JSON.stringify({
544
+ fleet: contract.name,
545
+ rootId: fleetRootId,
546
+ planHash: plan.hash,
547
+ loops: planOutcome.loops,
548
+ revalidated: planOutcome.revalidated,
549
+ unneeded: planOutcome.unneeded,
550
+ skipped: planOutcome.skipped,
551
+ needsDecision: planOutcome.needsDecision,
552
+ writeBoundaries: planOutcome.writeBoundaries
553
+ })}
554
+ `
555
+ );
556
+ } else {
557
+ const spentUsd = receipts.reduce((sum, receipt) => sum + receipt.costUsd, 0);
558
+ process.stdout.write(
559
+ `fleet ${contract.name}: ${succeededSteps}/${required.length} steps succeeded, ${resolvedLoops}/${planOutcome.loops.length} loops resolved, total cost $${spentUsd.toFixed(4)}
560
+ `
561
+ );
562
+ for (const loop of planOutcome.loops) {
563
+ process.stdout.write(
564
+ ` loop ${loop.loopId}: ${loop.reason} after ${loop.attempts} verification(s) and ${loop.repairs} repair(s)
565
+ `
566
+ );
567
+ }
568
+ if (planOutcome.revalidated.length > 0) {
569
+ process.stdout.write(
570
+ ` staleness: re-ran ${planOutcome.revalidated.join(", ")} because a workspace step landed after the last green
571
+ `
572
+ );
573
+ }
574
+ for (const message of planOutcome.needsDecision) process.stdout.write(` needs operator decision: ${message}
575
+ `);
576
+ for (const boundary of planOutcome.writeBoundaries) {
577
+ if (!boundary.violated) continue;
578
+ process.stdout.write(` write boundary ${boundary.window}: ${boundary.detail ?? WRITE_BOUNDARY_VIOLATION_REASON}
579
+ `);
580
+ }
581
+ }
582
+ const cleanRun = failedLoops.length === 0 && planOutcome.skipped.length === 0 && required.every((step) => planOutcome.results.get(step.id)?.succeeded === true);
583
+ return cleanRun ? 0 : 1;
584
+ }
585
+ function isProcessAlive(pid) {
586
+ if (pid === null || !Number.isFinite(pid) || pid <= 0) return false;
587
+ try {
588
+ process.kill(pid, 0);
589
+ return true;
590
+ } catch (err) {
591
+ return err.code === "EPERM";
592
+ }
593
+ }
594
+ function rowHeartbeat(row) {
595
+ if (row.status === "stale") return "stale";
596
+ if (row.status === "dead") return "dead";
597
+ return isProcessAlive(row.pid) ? "alive" : "dead";
598
+ }
599
+ function finiteCount(value) {
600
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
601
+ }
602
+ function receiptTokenSplit(row) {
603
+ const path = row.receiptPath ?? join(clioStateDir(), "receipts", `${row.id}.json`);
604
+ try {
605
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
606
+ return { input: finiteCount(parsed.inputTokenCount), output: finiteCount(parsed.outputTokenCount) };
607
+ } catch {
608
+ return null;
609
+ }
610
+ }
611
+ function rowTokenSplit(row) {
612
+ if (row.inputTokenCount !== void 0 || row.outputTokenCount !== void 0) {
613
+ return { input: finiteCount(row.inputTokenCount), output: finiteCount(row.outputTokenCount) };
614
+ }
615
+ if (row.endedAt !== null) {
616
+ return receiptTokenSplit(row) ?? { input: 0, output: 0 };
617
+ }
618
+ return { input: 0, output: 0 };
619
+ }
620
+ function admissionStatus(drain) {
621
+ if (drain === null) return { state: "open" };
622
+ return { state: "draining", ...drain };
623
+ }
624
+ function statusSnapshot() {
625
+ const ledger = openLedger();
626
+ const nowMs = Date.now();
627
+ const rows = ledger.list();
628
+ const running = rows.filter((row) => row.endedAt === null && (row.status === "running" || row.status === "stale")).map((row) => {
629
+ const startedMs = Date.parse(row.startedAt);
630
+ return {
631
+ runId: row.id,
632
+ agentId: row.agentId,
633
+ runtimeKind: row.runtimeKind,
634
+ outcomePhase: row.status,
635
+ heartbeat: rowHeartbeat(row),
636
+ lineage: row.lineage ?? { parentRunId: null, rootRunId: row.id, attempt: 0, depth: 0 },
637
+ startedAt: row.startedAt,
638
+ elapsedMs: Number.isFinite(startedMs) ? Math.max(0, nowMs - startedMs) : 0,
639
+ tokens: { input: 0, output: 0, total: row.tokenCount },
640
+ costUsd: row.costUsd,
641
+ node: row.node?.id ?? "local"
642
+ };
643
+ });
644
+ const totals = { inputTokens: 0, outputTokens: 0, totalTokens: 0, costUsd: 0, runtimeSeconds: 0 };
645
+ for (const row of rows) {
646
+ const split = rowTokenSplit(row);
647
+ totals.inputTokens += split.input;
648
+ totals.outputTokens += split.output;
649
+ totals.totalTokens += row.tokenCount;
650
+ totals.costUsd += row.costUsd;
651
+ const startedMs = Date.parse(row.startedAt);
652
+ const endedMs = row.endedAt !== null ? Date.parse(row.endedAt) : nowMs;
653
+ if (Number.isFinite(startedMs) && Number.isFinite(endedMs)) {
654
+ totals.runtimeSeconds += Math.max(0, endedMs - startedMs) / 1e3;
655
+ }
656
+ }
657
+ return {
658
+ generatedAt: new Date(nowMs).toISOString(),
659
+ admission: admissionStatus(capacityDrain(nowMs)),
660
+ running,
661
+ retrying: [],
662
+ totals
663
+ };
664
+ }
665
+ function runStatus(args) {
666
+ const unknown = args.find((arg) => arg !== "--json");
667
+ if (unknown) return fail(`status: unknown flag: ${unknown}`);
668
+ const snapshot = statusSnapshot();
669
+ if (args.includes("--json")) {
670
+ process.stdout.write(`${JSON.stringify(snapshot, null, 2)}
671
+ `);
672
+ return 0;
673
+ }
674
+ process.stdout.write(`dispatch status @ ${snapshot.generatedAt} (ledger: ${clioStateDir()})
675
+ `);
676
+ process.stdout.write(
677
+ snapshot.admission.state === "draining" ? `admission: draining until ${snapshot.admission.expiresAt} (requested by pid ${snapshot.admission.requestedByPid} at ${snapshot.admission.requestedAt})
678
+ ` : "admission: open\n"
679
+ );
680
+ if (snapshot.running.length === 0) {
681
+ process.stdout.write("running: none\n");
682
+ } else {
683
+ process.stdout.write("running:\n");
684
+ for (const row of snapshot.running) {
685
+ const lineage = row.lineage;
686
+ process.stdout.write(
687
+ ` ${row.runId} ${row.agentId} node=${row.node} ${row.heartbeat} attempt=${lineage.attempt} depth=${lineage.depth} ${Math.round(row.elapsedMs / 1e3)}s $${row.costUsd.toFixed(4)}
688
+ `
689
+ );
690
+ }
691
+ }
692
+ if (snapshot.retrying.length === 0) {
693
+ process.stdout.write("retrying: none (retry queue is in-memory and only visible in the owning process)\n");
694
+ } else {
695
+ process.stdout.write("retrying:\n");
696
+ for (const row of snapshot.retrying) {
697
+ process.stdout.write(` ${row.runId} ${row.agentId} attempt=${row.attempt} due=${row.dueAt} ${row.reason}
698
+ `);
699
+ }
700
+ }
701
+ const t = snapshot.totals;
702
+ process.stdout.write(
703
+ `totals: tokens=${t.totalTokens} (in=${t.inputTokens} out=${t.outputTokens}) cost=$${t.costUsd.toFixed(4)} runtime=${Math.round(t.runtimeSeconds)}s
704
+ `
705
+ );
706
+ return 0;
707
+ }
708
+ function runAdmissionControl(command, args) {
709
+ const unknown = args.find((arg) => arg !== "--json");
710
+ if (unknown) return fail(`${command}: unknown flag: ${unknown}`);
711
+ ensureClioState();
712
+ const admission = admissionStatus(setCapacityDraining(command === "drain"));
713
+ if (args.includes("--json")) {
714
+ process.stdout.write(`${JSON.stringify({ admission }, null, 2)}
715
+ `);
716
+ return 0;
717
+ }
718
+ if (admission.state === "draining") {
719
+ process.stdout.write(
720
+ `dispatch admission is draining until ${admission.expiresAt}; running work continues (requested by pid ${admission.requestedByPid})
721
+ `
722
+ );
723
+ } else {
724
+ process.stdout.write("dispatch admission is open\n");
725
+ }
726
+ return 0;
727
+ }
728
+ async function runFleetCommand(args) {
729
+ const sub = args[0];
730
+ if (sub === "help" || args.includes("--help") || args.includes("-h")) {
731
+ process.stdout.write(HELP);
732
+ return 0;
733
+ }
734
+ if (sub === void 0) {
735
+ process.stderr.write(HELP);
736
+ return 2;
737
+ }
738
+ switch (sub) {
739
+ case "list":
740
+ return runList();
741
+ case "run":
742
+ return runFleet(args.slice(1));
743
+ case "status":
744
+ return runStatus(args.slice(1));
745
+ case "drain":
746
+ return runAdmissionControl("drain", args.slice(1));
747
+ case "resume":
748
+ return runAdmissionControl("resume", args.slice(1));
749
+ default:
750
+ process.stderr.write(`clio-coder fleet: unknown subcommand '${sub}'
751
+ `);
752
+ process.stderr.write(HELP);
753
+ return 2;
754
+ }
755
+ }
756
+ export {
757
+ runFleetCommand,
758
+ statusSnapshot
759
+ };
760
+ //# sourceMappingURL=fleet-CA2CRTVG.js.map