@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,591 @@
1
+ # Fleet Dispatch
2
+
3
+ > **Interactive Spec Available:** An interactive fleet node topology planner, scout router, receipt verifier, and failure taxonomy simulator is located at [docs/html/fleet_dispatch_blueprint.html](html/fleet_dispatch_blueprint.html) (Version: 0.3.0).
4
+
5
+ Clio Coder dispatches bounded worker agents. With a fleet configured, those
6
+ workers run on remote machines over SSH while the orchestrator keeps every
7
+ guarantee it makes locally: one admission path, one autonomy matrix, one
8
+ receipt chain. This page covers the architecture, node setup, the doctor
9
+ preflight, placement, topologies, failure semantics, and the residency
10
+ default. For the end-to-end demo see
11
+ [fleet-demo-runbook.md](fleet-demo-runbook.md).
12
+
13
+ Source of truth: `src/domains/dispatch/**`, `src/domains/scheduling/cluster.ts`,
14
+ `src/tools/dispatch.ts`, `src/tools/monitor.ts`, and the contract tests under
15
+ `tests/contracts/`.
16
+
17
+ ## Architecture
18
+
19
+ The worker protocol is transport-neutral: the orchestrator writes one
20
+ WorkerSpec JSON line to the worker's stdin and reads NDJSON events from its
21
+ stdout. A remote worker is exactly the same protocol tunneled through
22
+ `ssh -T`, so nothing about prompts, safety, receipts, or telemetry changes
23
+ with distance. Transport is a ladder: `local` and `ssh` exist today; a future
24
+ container or cloud tier implements the same `WorkerTransport` interface
25
+ (`src/domains/dispatch/transport.ts`) without touching the protocol.
26
+
27
+ Both local and SSH native workers must emit `worker_announce` as their first
28
+ protocol event over the structured stderr control lane. The transport consumes it,
29
+ checks the dispatched WorkerSpec version, and accepts ordinary events only after
30
+ that check. The worker then attests protocol version (WORKER_PROTOCOL_VERSION = 1),
31
+ spec version, process ID, process group ID (or null), host, settings fingerprint,
32
+ worker-computed spec digest, runtime ID, target ID, endpoint identity hash, wire
33
+ model ID, effective tool signature, and bounded node resource facts (labels, CPU count,
34
+ total memory, free memory, GPU count, VRAM, and resident models) before any model
35
+ call. Drift from the approved identity kills the whole process group. The announcement and
36
+ attestation are strict protocol evidence, not proof against a malicious child
37
+ that controls its own process; SSH also uses the attested remote process group
38
+ for bounded abort escalation.
39
+
40
+ Scout routing is advisory rather than forced: the worker operating contract
41
+ steers explicit broad repository exploration to the read-only `scout` recipe,
42
+ and middleware emits a continuation nudge after nine or more manual
43
+ read-only exploration calls without a successful Scout dispatch. Direct reads
44
+ remain allowed; Clio does not automatically rewrite a broad request into a
45
+ Scout run.
46
+
47
+ Design decisions that shape everything else:
48
+
49
+ - Per-node inference targets, no central proxy. Target URLs resolve on the
50
+ node the worker runs on, so `localhost` in a worker's target means that
51
+ node's own inference server. The orchestrator-resolved API key rides the
52
+ WorkerSpec.
53
+ - Shared filesystem. Remote nodes see the project at the same absolute path.
54
+ The doctor preflight verifies this parity per node; hosts with a disjoint
55
+ filesystem fail admission with a clear reason.
56
+ - Deterministic placement and measured routing. Exact pins remain exact.
57
+ Unpinned placement prefers lower durable lease usage and declaration order;
58
+ the cross-process lease state is the final capacity authority. Route quality
59
+ can be activated only for named roles/postures after exact-tuple readiness,
60
+ and hard constraints always eliminate before any score.
61
+ - Environment whitelist. The SSH command carries an explicit environment
62
+ (`CLIO_CODER_RESIDENCY=observe`, `CLIO_CODER_WORKER_PGID=$$`, and any configured
63
+ `CLIO_CODER_WORKER_LABELS`); the orchestrator's `process.env` never crosses the
64
+ wire. `CLIO_CODER_WORKER_PGID` names the remote process group so an abort escalates
65
+ against the whole group rather than one process.
66
+
67
+ ## Worker prompt and budget admission
68
+
69
+ Dispatch resolves the recipe, target, effective autonomy, and final canonical toolkit before compiling one stable Clio worker harness. The harness contains identity-lite, the shared operating contract, the exact native tool surface (or honest no-tools wording), safety for the enforced autonomy, and the recipe or bounded override persona. Project context, memory, bounded briefing, pipeline input, task text, and run posture remain dynamic messages and therefore do not churn stable hashes. Briefing is explicitly untrusted task data and does not transport conversation or session history.
70
+
71
+ One run has a first-class singular shape: `task` is the worker assignment and
72
+ `briefing` is separate bounded context/data. Briefing never replaces task,
73
+ never gets copied into the receipt task, and remains a separately delimited
74
+ dynamic prompt message. `tasks` is the batch form. A shared top-level briefing
75
+ applies to string tasks and task objects without an override; an object-level
76
+ briefing wins. Supplying both `task` and `tasks` fails instead of choosing one.
77
+ After approval, execution consumes only the registry-owned resolved plan, so
78
+ later mutation of raw arguments cannot change either field.
79
+
80
+ Recipes may declare `budget: {toolCalls, readReserve, synthesis}`. `toolCalls` is the admitted-call phase boundary; the final `readReserve` slots accept canonical `read` plus the agent's granted mutation tools, so a writer can still deliver inside its own reserve; `synthesis: true` forces a text-only final round, while `false` stops after the admitted phase. `guardrails.workerToolCallCap` is transported separately as the ceiling on executed calls and always wins when lower. Native workers and Claude SDK enforce this policy. Claude Code and Antigravity reject explicit-budget recipes because their black-box loops cannot provide equivalent per-call mediation. Before launch, every admitted WorkerSpec v3 contains one concrete effective budget and a settings fingerprint, including custom recipes whose source omitted a budget.
81
+
82
+ ## Node setup
83
+
84
+ Fleet nodes are declared under `fleet.nodes` in `settings.yaml`. The implicit
85
+ `local` node always exists and is never declared.
86
+
87
+ ```yaml
88
+ fleet:
89
+ nodes:
90
+ - id: node-a
91
+ host: node-a.example.net
92
+ user: me # optional; defaults to the SSH config
93
+ port: 22 # optional
94
+ identityFile: ~/.ssh/id_fleet # optional
95
+ labels: [cpu] # optional operator labels
96
+ maxWorkers: 2 # per-node cap; defaults to 2
97
+ residency: observe # observe (default) or manage
98
+ - id: node-b
99
+ host: node-b.example.net
100
+ maxWorkers: 1
101
+ ```
102
+
103
+ `clioEntry` may override the remote invocation (default `clio-coder worker`).
104
+ Node ids must be unique and `local` is reserved.
105
+
106
+ Worker profiles can pin work to a node: `workers.profiles.<name>.node` routes
107
+ every dispatch bound to that profile. The `/fleet` overlay's profiles tab
108
+ edits the pin (`o` key), and the dispatch tool accepts an explicit `node`
109
+ argument per task.
110
+
111
+ ## Doctor preflight
112
+
113
+ A remote node is dispatch-eligible only after one preflight pass proved, over
114
+ the node's real SSH channel:
115
+
116
+ 1. reachability (SSH connects in batch mode),
117
+ 2. a version-matched `clio-coder` on the remote invocation path,
118
+ 3. path parity for the project root (the shared-filesystem assumption),
119
+ 4. a writable remote state directory,
120
+ 5. node-scoped target reachability, runtime/model compatibility, endpoint
121
+ identity, and explicit resource facts where the target exposes them.
122
+
123
+ Run it with `clio-coder doctor`. Results persist under the state dir
124
+ (`fleet-preflight.json`) keyed by node and project root, so eligibility
125
+ survives across processes. A record is invalidated by a changed host, a
126
+ changed project root, or a local `clio-coder` upgrade; admission then fails closed
127
+ with a reason that names the fix (run `clio-coder doctor` again). Failing nodes are
128
+ doctor warnings, never fatal: the fleet degrades to the nodes that passed.
129
+
130
+ ## Placement and process-safe admission
131
+
132
+ Placement and admission are separate, deterministic authorities:
133
+
134
+ 1. An explicit request pin, profile pin, or approved route envelope restricts
135
+ the eligible node set. Unknown, offline, stale-preflight, or incompatible
136
+ pins fail closed; they never silently fall back.
137
+ 2. For unpinned eligible nodes, placement prefers lower durable lease usage
138
+ read through the fleet registry; declaration order breaks ties.
139
+ 3. The capacity lease store decides under one cross-process state lock (`dispatch-admission.json`).
140
+ A stale placement preference cannot over-admit a node.
141
+ 4. If a pinned or selected node is momentarily full, the bounded admission
142
+ queue preserves priority/FIFO order until its finite deadline instead of
143
+ silently selecting another node.
144
+
145
+ The durable capacity state file (`dispatch-admission.json`) uses schema version 2 and owns global and per-node leases, heartbeats, reservation transfer, retry rebinding, and the TTL-bounded operator drain (`DEFAULT_CAPACITY_DRAIN_TTL_MS` = 3,600,000 ms). A lease acts as durable expiring authority (`DEFAULT_CAPACITY_LEASE_TTL_MS` = 30,000 ms) and is reclaimed only with owner-liveness evidence when a process birth token cannot prove process death. A plan reserves its peak wave, and a retry rebinds the same assignment member to its actual node and cost bound so that an assignment retry belongs to its existing plan slot and cannot queue behind or outspend itself. Full leasing schema and locking protocols are specified in [capacity-and-scheduling.md](capacity-and-scheduling.md).
146
+
147
+ Use `clio-coder fleet drain [--json]` before maintenance to close that shared
148
+ admission authority. Existing workers continue, but new plans and every new
149
+ execution start—including a retry or a previously reserved member—fail closed.
150
+ The drain expires after one hour so an abandoned operator process cannot wedge
151
+ future dispatch; repeating the command renews the deadline. `clio-coder fleet
152
+ status [--json]` reports the active deadline, requesting PID, and request time.
153
+ Use `clio-coder fleet resume [--json]` to reopen admission early. Detailed drain mechanics are documented in [capacity-and-scheduling.md](capacity-and-scheduling.md).
154
+
155
+ With no fleet configured and nothing requested, placement resolves to the
156
+ implicit local path and optional fleet-node provenance may remain absent.
157
+ Every new receipt uses strict integrity v15; older receipt formats are not
158
+ accepted by the current reader.
159
+
160
+ ## Failure semantics
161
+
162
+ - Channel failures (a stalled heartbeat, a spawn failure, SSH exit 255) count
163
+ against the node; completing the protocol counts for it; operator cancels
164
+ are neutral.
165
+ - Two consecutive channel failures classify the node dead. Every other
166
+ in-flight run on that node is reaped through the stall path, finalizes as
167
+ `stalled` (retryable), and its bounded retry re-enters placement on a
168
+ surviving node.
169
+ - Every failover hop is recorded as a reroute (`fromNode`, `toNode`, reason)
170
+ on the ledger row and the receipt, so the placement lineage of a run is
171
+ reconstructable from evidence alone.
172
+ - An idle node is never auto-offlined by staleness; only consecutive channel
173
+ failures change the process-local registry health to `offline`. Doctor
174
+ preflight is a separate durable eligibility gate: a failed or stale record
175
+ blocks placement without pretending it changed channel health.
176
+
177
+ ## Topologies
178
+
179
+ All topologies go through the dispatch tool, the same admission chain, and
180
+ the autonomy matrix. Workers never exceed the orchestrator's authority; a
181
+ request-level `autonomy` can only narrow the level (reviewers and judges run
182
+ `read-only`).
183
+
184
+ | Topology | Invocation | Semantics |
185
+ | --- | --- | --- |
186
+ | Singular | `task: "..."` | One assignment, with optional separate `briefing`. |
187
+ | Parallel (default) | `tasks: [...]` | Fan out, wait for all, one summary. |
188
+ | Sequential | `mode: "sequential"` | One at a time, stop reporting on timeout/abort. |
189
+ | Pipeline | `mode: "pipeline"` | Each step receives the previous step's output as data. |
190
+ | Detached | `detach: true` | Return logical assignment ids and a batch id immediately; collect later. |
191
+ | Review gate | `review: {reviewer?, max_cycles?}` | Builder, read-only reviewer verdict, bounded revise loop. |
192
+ | Compete | `mode: "compete", candidates: 2..4` | N candidates in scratch worktrees, read-only judge, winner applied or preserved. |
193
+ | Agent automation | `agent: "auto"` | Baselines candidate agent from task shape via shared classifier (`coder`, `tester`, `documenter`, `verifier`, `researcher`, `scout`); advisory unless activated. |
194
+
195
+ ### Detached fan-out, backgrounding, and collect
196
+
197
+ `detach: true` validates, admits, and spawns every task, then returns. The
198
+ reported id is the logical assignment id (also the first attempt's run id).
199
+ For an in-flight attached dispatch, pressing `Alt+S` or `Ctrl+Alt+B` converts
200
+ the running attached dispatch into a detached batch. Backgrounding checks
201
+ against a refusal table: it refuses Scout dependency plans driving stages from
202
+ the turn, compete judge gates, review cycle gates, multi-step pipelines,
203
+ dispatches with explicit `timeout_ms`, or missing detached records.
204
+
205
+ Attempts keep streaming into the board and immutable run ledger. The batch and
206
+ assignment index are durable (`batches.json` and `assignments.json` under the
207
+ state dir), so collection survives session exit. Gather results with the
208
+ monitor tool: `mode="wait"` observes one assignment for a bounded time (it
209
+ never cancels it; `steer` with `action="cancel"` cancels its current attempt
210
+ and suppresses later attempts); `mode="collect"` is the barrier over a batch id
211
+ or assignment-id list. It returns a pending snapshot while assignments are in
212
+ flight, then each assignment's terminal attempt plus `attemptRunIds` history.
213
+ Collecting marks the batch so the turn-end nudge stops firing. `wait` observes
214
+ without collecting; `collect` is the authoritative terminal batch operation.
215
+ Collect every detached batch before final synthesis.
216
+
217
+ ### Review gate
218
+
219
+ The builder runs the task. A reviewer then inspects the workspace against the
220
+ task. The reviewer defaults to the builtin `verifier` recipe
221
+ (`DEFAULT_GATE_DECIDER_AGENT_ID`) and never falls back to the builder's own
222
+ agent; it is pinned to read-only autonomy and is routable to a different node,
223
+ model, or target.
224
+
225
+ The reviewer answers a typed `verifier-report` contract rather than trailing
226
+ prose:
227
+
228
+ ```json
229
+ {"verdict":"pass","checks":[{"name":"npm run typecheck","passed":true,"evidence":"exit 0"}]}
230
+ ```
231
+
232
+ `revise` is not a verdict a model authors. The reviewer answers `pass` or
233
+ `fail`, and `decideReviewGate` in
234
+ `src/domains/dispatch/gate-decisions.ts` owns the continuation policy: a
235
+ non-passing verdict below the terminal cycle becomes `revise` and re-runs the
236
+ builder with only the failed checks threaded as input data, bounded by
237
+ `max_cycles` (default 2, max 4). On the terminal cycle the verdict settles as
238
+ reported. A reviewer that produces no structured result settles as `exhausted`
239
+ and surfaces as an explicit operator decision, never a silent failure.
240
+
241
+ ### Compete
242
+
243
+ N candidate builders (2 to 4) run the same task, each in its own scratch git
244
+ worktree under `.clio-coder/worktrees/<group>/` on its own
245
+ `clio/compete/<group>/<n>` branch. Each candidate's work is committed on its
246
+ branch; a read-only judge ranks the branches and names a winner
247
+ (`WINNER: <n>`). At full-auto the winning branch is merged. At supervised
248
+ levels the winner's branch and worktree are preserved and the operator
249
+ confirms through `apply_winner`, whose approval prompt is the winner
250
+ confirmation. Losers are cleaned on every path, including abort.
251
+
252
+ The compete group is a durable transaction owner. Its manifest records the
253
+ coordinator identity and every admitted worker process before the dispatch
254
+ handle is returned. At orchestrator startup, Clio uses process birth tokens
255
+ to distinguish the leased process from PID reuse, terminates an abandoned
256
+ worker or ACP process group, and then removes the group's registered
257
+ worktrees and branches. If a judge output is waiting in the decision journal,
258
+ the workers are quiesced but the candidates remain until that output is bound
259
+ to an integrity-verified judge receipt; a recovered winner is preserved for
260
+ operator inspection rather than silently auto-applied after restart.
261
+
262
+ ### ExecutionPlan and plan approval
263
+
264
+ Every orchestration shape compiles to one strict ExecutionPlan v2 DAG with
265
+ stable task ids, explicit dependencies, requested and approved authority,
266
+ capacity-bounded waves, stop/continue semantics, and authenticated structured
267
+ handoffs. The scheduler performs whole-plan preflight and reservation before
268
+ the first worker spawns. A missing authority grant is an admission failure.
269
+
270
+ A plan-scale dispatch call (more than one task, review, compete, effective
271
+ remote placement, or `apply_winner`) maps to an approval ask at supervised
272
+ autonomy levels. Before asking, Clio resolves the effective agent, target,
273
+ model, node, bounded review cycles/candidates/judge, and scheduling cost
274
+ ceiling, then reserves the plan's capacity and budget as a unit. The parked
275
+ call shows that sanitized artifact, including the approved fallback candidates
276
+ in preference order, and one approval covers the whole plan. Declining the plan
277
+ rolls the whole reservation back.
278
+
279
+ A reservation holds three scarce things and nothing else: a global concurrency
280
+ slot, a per-node slot, and a budget upper bound. It never pins route identity.
281
+ Capacity and budget are checked for the plan as a unit at approval time, per
282
+ wave, so a three-step sequential plan holds one slot rather than three and N
283
+ parallel tasks whose individual estimates each fit but whose sum breaches the
284
+ ceiling are denied together with the aggregate figure. A member is consumed
285
+ once by its assignment and released once when that assignment settles; a retry
286
+ that lands on a different node or a differently priced route rebinds the member
287
+ atomically and fails closed if the new node has no free slot or the new
288
+ estimate breaches the ceiling. Reservations owned by a dead process are
289
+ reclaimed at startup, with a TTL as the backstop, and live sibling processes'
290
+ reservations are preserved. Execution consumes the
291
+ same pins, including each expanded builder/reviewer/candidate/judge role and
292
+ the SSH node's transport kind and host. A placement, host, capability, or
293
+ cost-ceiling change fails before launch rather than silently choosing an
294
+ unapproved alternative. Full-auto skips the stop and seals the
295
+ same plan hash into every run's receipt instead
296
+ (`plan.approval: "full-auto"`). Read-only autonomy denies dispatch outright,
297
+ as it denies every non-read action.
298
+
299
+ The registry boundary is resolved dispatch plan v3. `deadlineMs` is required:
300
+ a fleet plan carries a positive finite number and a non-fleet plan carries
301
+ explicit `null`. Older versions, missing fields, and compatibility shapes are
302
+ rejected.
303
+
304
+ ### Shipped fleets and contract versions
305
+
306
+ Clio ships three builtin fleet contracts under `src/domains/agents/fleets/`: `build-test`, `build-review`, and `sdlc`. Projects can declare custom fleet contracts or shadow builtin fleets by placing Markdown files under `.clio-coder/fleets/<name>.md`. A file named `.clio-coder/fleets/<name>.md` shadows a builtin fleet of the same name.
307
+
308
+ Fleet contracts support schema versions 1 through 4:
309
+ - Version 1: Supports agent steps only.
310
+ - Version 2: Introduces deterministic code steps.
311
+ - Version 3: Adds bounded check/repair loops and commit steps with `commitFrom` message sources.
312
+ - Version 4 (`FLEET_WRITE_BOUNDARY_VERSION = 4`): Introduces per-step declared write boundaries (`writes`) and orchestrator post-step enforcement.
313
+
314
+ ### Per-step write boundaries (Contract v4)
315
+
316
+ Contract v4 requires every step to declare its write boundary using the `writes` allowlist property. Steps with scope `readonly` declare an empty allowlist (`[]`).
317
+
318
+ The grammar for declared write boundary entries requires repository-relative POSIX paths:
319
+ - Trailing `/` indicates a directory subtree allowlist.
320
+ - Exact relative paths without a trailing `/` permit changes to that single file.
321
+ - Declarations must not contain glob characters (`*`, `?`, `[`, `]`, `{`, `}`), `..` or `.` segments, backslashes, or absolute paths.
322
+ - Each step declaration is capped at a maximum of 32 entries (`WRITE_BOUNDARY_MAX_ENTRIES = 32`).
323
+
324
+ Write boundary enforcement is detect-and-rollback, never OS or filesystem sandboxing. A step runs with whatever filesystem permissions its underlying execution environment possesses. Upon step completion, the orchestrator inspects the working tree to verify compliance:
325
+ 1. Snapshot baseline: Before a step executes, the orchestrator captures a snapshot (`captureWorkspaceSnapshot`) recording the baseline git HEAD commit and existing dirty path content tokens.
326
+ 2. Workspace diffing: After step completion, the orchestrator runs git status inspection (`diffWorkspace`) to identify changed paths relative to the snapshot baseline commit.
327
+ 3. Rollback execution: Unauthorized changes (modified paths not covered by the step's declared allowlist) are automatically rolled back (`rollbackPath`).
328
+ 4. Content source: Rollback restores content strictly from what git already has in the pinned baseline commit (`snapshot.head`). If a path was already dirty when the step snapshot was captured, its prior content is not stored in git, so in-place restoration cannot be guaranteed. The working tree is left as the step made it, and the status settles as `rollback-incomplete`.
329
+ 5. Violation handling: Any unauthorized change fails the step with the typed reason `writes_boundary_violation`.
330
+ 6. Window attribution: Enforcement evaluates scheduling windows (`wave-<n>` or `revalidate-<stepId>-<n>`). A wave window cannot combine steps with overlapping declared boundaries or multiple concurrent step writers, ensuring single-step attribution.
331
+ 7. Ignored paths and state subtraction: Enforcement evaluates paths reported by git status. Git-ignored paths remain outside enforcement. The Clio state directory (`.clio-coder/` or `clioStateDir()`) is subtracted from status checks so orchestrator receipts, code step log artifacts, and boundary verdicts do not trigger false violations.
332
+ 8. Durable records: Verdicts are serialized as JSON records at `write-boundaries/<rootId>/<window>.json` under the Clio state directory, carrying the baseline HEAD commit, checked paths, violations, rollback actions, status, and SHA-256 digest.
333
+
334
+ ### Bounded check/repair loops
335
+
336
+ Contract v3 and v4 support declared check/repair loops (`kind: loop`). A loop declares `id`, `maxAttempts` (an integer between 1 and `FLEET_LOOP_MAX_ATTEMPTS = 5`), `check` (a code command or agent reviewer), and `repair` (an agent coder).
337
+
338
+ At plan compilation, the orchestrator unrolls each loop statically into a deterministic hashed DAG containing `maxAttempts` verification check steps (`<loopId>.check.<n>`) and `maxAttempts - 1` repair steps (`<loopId>.repair.<n>`).
339
+ - Receipt per attempt: Every attempt in an unrolled loop executes as an independent plan node and produces its own receipt.
340
+ - Recovery role: Repair attempts following the first check are assigned the `recovery` execution role.
341
+ - Spent bounds: Reaching `maxAttempts` without a passing check settles the loop with the terminal reason `loop_bound_exhausted`.
342
+ - Four terminal reasons: A loop concludes with one of four reasons: `resolved` (verification passed), `loop_bound_exhausted` (attempt ceiling spent), `loop_step_failed` (underlying step errored or was denied), or `loop_not_reached` (prior plan dependencies failed).
343
+ - Node counting: Unneeded nodes (verifications or repairs remaining after a loop resolves) are counted separately from skipped nodes.
344
+ - Verification staleness: The scheduler enforces verification staleness by re-running a check step if a subsequent workspace-editing step executes after it.
345
+
346
+ ### Deterministic code steps
347
+
348
+ Deterministic code steps (`kind: code`) execute known commands directly as subprocesses rather than calling an agent model.
349
+ - Registry binding: The `command` property must reference a command ID declared in `.clio-coder/fleets/commands.yaml`. Invocation strings are never generated from model output.
350
+ - Execution environment: Code steps run unattended with arguments bound from the command registry, fixed working directory, closed environment allowlist (`FLEET_COMMAND_BASE_ENV` plus declared command env), bounded timeout (`timeoutMs`), byte-capped output capture (`CODE_STEP_CAPTURE_MAX_BYTES` = 1 MB log artifact, `CODE_STEP_EXCERPT_MAX_BYTES` = 8 KB excerpt), no stdin pipe, no permission prompt, and no shell interpreter.
351
+ - Missing registry diagnostic: If a contract declares code steps but `.clio-coder/fleets/commands.yaml` is missing in the repository, `clio-coder fleet list` reports the fleet status as `setup` and provides the remedy: `needs .clio-coder/fleets/commands.yaml declaring <id>; declare each id there under commands: with an argv list; clio-coder docs fleet_dispatch has the schema`.
352
+ - Commit message sources: A code step with `commitFrom` populates its `commitMessage` placeholder from the output of preceding agent steps.
353
+ - Route quality: Code steps do not consume model tokens or cost estimates; their quality reports `unmeasured` rather than zero.
354
+
355
+ #### Command Registry Schema (`.clio-coder/fleets/commands.yaml`)
356
+
357
+ The repository command registry binds command IDs to exact argument vectors:
358
+
359
+ ```yaml
360
+ version: 1
361
+ commands:
362
+ test:
363
+ argv: ["npm", "test"]
364
+ timeoutMs: 600000
365
+ description: "Run repository test suite"
366
+ lint:
367
+ argv: ["npm", "run", "lint"]
368
+ timeoutMs: 300000
369
+ build:
370
+ argv: ["npm", "run", "build"]
371
+ timeoutMs: 600000
372
+ commit:
373
+ argv: ["git", "commit", "-m"]
374
+ timeoutMs: 60000
375
+ ```
376
+
377
+ Each command entry supports:
378
+ - `argv` (required): Array of command arguments starting with the binary name (no shell strings).
379
+ - `cwd` (optional): Repository-relative working directory (defaults to repository root).
380
+ - `timeoutMs` (optional): Per-step execution timeout in milliseconds (defaults to 600,000 ms; bounds: 1,000 to 3,600,000 ms).
381
+ - `env` (optional): Array of extra environment variable names to pass through on top of `FLEET_COMMAND_BASE_ENV` (`PATH`, `HOME`, `LANG`, `LC_ALL`, `TZ`, `TMPDIR`).
382
+ - `description` (optional): Human-readable description.
383
+
384
+
385
+ ## Measured route selection and agent automation
386
+
387
+ The joint resolver treats agent, target, model, runtime, and node as one
388
+ bounded tuple. Manual pins, the approved plan envelope, authority, audience,
389
+ required tools and skills, result contract, response-schema support, locality,
390
+ authentication, network policy, endpoint reachability, context, resource fit,
391
+ capacity, budget, deadline, and cooldown are hard filters. Only survivors are
392
+ estimated and Pareto-ranked by conservative quality, reliability, completed
393
+ cost and latency, queue wait, and cache affinity. The complete bounded
394
+ candidate/rejection set is sealed; at most three fallbacks are projected.
395
+
396
+ Shadow is the default and never changes the explicit route. Active route
397
+ selection requires both the execution role and posture to be named:
398
+
399
+ ```yaml
400
+ routing:
401
+ activeRoles: [researcher, verifier, reviewer, judge]
402
+ activePostures: [quality, balanced]
403
+ agentAutomation:
404
+ activeAgentRoles: []
405
+ ```
406
+
407
+ For every exact tuple, `evaluateRouteReadiness` requires consistent hard-
408
+ constraint evaluation, no integrity failures, at least six role-specific
409
+ quality labels, conservative quality and reliability floors, known cost,
410
+ fresh node/endpoint/resource/capacity/settings facts, and decision p95 below
411
+ 10 ms. If no tuple is ready, active mode refuses the assignment. It never
412
+ falls back to the fixed route, and manual or `failover: none` intent never
413
+ drifts.
414
+
415
+ `agent: "auto"` first filters recipe audience, authority, tools, skills,
416
+ result contract, locality, and governance. Bounded task features affect cold
417
+ priors only; one truthful role-quality label retires the task prior. Agent
418
+ automation has its own readiness report per agent/spec/role and stays shadow
419
+ unless the operator names an exact agent/role pair. A read-only Scout can
420
+ settle reconnaissance directly or return at most four typed subtasks. The
421
+ coordinator validates ids, dependencies, expected result contracts, and
422
+ requested authority and rejects embedded agents, routes, deadlines, costs, or
423
+ other control fields. Escalation to workspace editing requires authenticated
424
+ plan approval or existing full-auto authority.
425
+
426
+ ## Assignments, attempts, and failover
427
+
428
+ A dispatch is a logical assignment containing one or more immutable run
429
+ attempts. The assignment id and terminal run ids are distinct identities;
430
+ there is no `runIds` compatibility alias. Public `finalPromise` handles resolve only when the assignment succeeds,
431
+ is canceled, or exhausts its retry policy; the returned receipt is the
432
+ terminal attempt's unchanged receipt. Earlier attempts stay independently
433
+ addressable and integrity-verifiable.
434
+
435
+ The assignment owns the event stream as well as the terminal receipt. The
436
+ stream returned by `dispatch()` yields attempt 1's frames, then a synthetic
437
+ `attempt_start` frame for each retry, then that attempt's frames, and ends when
438
+ the assignment settles. A consumer therefore observes the same run the receipt
439
+ describes, and the marker tells it to discard state accumulated from an attempt
440
+ that has been superseded. The stream is single-consumer and bounded
441
+ (drop-oldest), so a slow reader degrades live display and never stalls a worker.
442
+
443
+ Manual `target`, `model`, or `node` pins default to exact failover (`none`): a
444
+ retry may repeat the tuple but cannot silently move away from it. `approved`
445
+ failover requires an ordered `allowedCandidates` envelope of exact
446
+ agent/target/model/node tuples and can never leave that set. `automatic`
447
+ failover lets typed infrastructure failures exclude only the failed route
448
+ part—for example, an SSH channel failure can move the node while retaining the
449
+ agent, target, and model. Cancellation, policy rejection, and permission
450
+ refusal neither retry nor penalize infrastructure.
451
+
452
+ A plan-approved task is never `automatic`. An explicitly pinned task seals its
453
+ exact tuple with `failover: "none"`; any other planned task seals
454
+ `failover: "approved"` with a bounded candidate list enumerated by
455
+ `route-candidates.ts` and rendered into the plan text the operator approves.
456
+ Validation rejects `automatic` on a request carrying plan provenance, so an
457
+ approved dispatch can only reroute to a tuple the approval actually showed.
458
+
459
+ Retries are governed by `workers.maxRetries` and backoff, and by nothing else.
460
+ A target cooldown protects new work from a known-bad target; it does not gate
461
+ an assignment already in flight, because that assignment's own retry budget is
462
+ the correct and sufficient bound. A retry denied at admission settles the
463
+ assignment failed, reports the reason on stderr, and records it in the
464
+ assignment's `outcomeDetail`.
465
+
466
+ Assignment status, attempt ids, and terminal run id are stored separately in
467
+ `assignments.json` while each attempt keeps its own strict v15 receipt.
468
+ Pipelines and batches await assignment terminals, so downstream stages consume
469
+ the successful fallback output rather than an earlier failed attempt.
470
+
471
+ Editing assignments also own one baseline-pinned workspace transaction. Every
472
+ attempt gets a distinct worktree. Before any winning diff can reach the
473
+ destination checkout, a pure gate checks terminal outcome, receipt integrity,
474
+ result conformance, and quality-gate success; protected artifacts, baseline
475
+ ancestry, and destination cleanliness are then rechecked on disk. Refusal
476
+ preserves the winner and recovery instructions, and the transaction cannot be
477
+ closed while a winner remains unapplied.
478
+
479
+ ## Receipts
480
+
481
+ Receipts carry exactly one integrity version (`RUN_RECEIPT_INTEGRITY_VERSION = 15`), which authenticates the complete receipt and reconstructible ledger provenance surface. There is no historical verification path: any other version is invalid, and a receipt that fails verification is never read as evidence. The fleet provenance fields covered by the digest
482
+ include:
483
+
484
+ - `node`: the fleet node the worker ran on (`id`, `kind`, `host`).
485
+ - `reroutes`: dead-node failover hops, oldest first.
486
+ - `gate`: review/compete provenance (role, group, cycle, subject run ids with
487
+ their receipt digests, and the verdict that caused a revise builder).
488
+ - `plan`: plan-approval provenance (hash, topology, task count, cost ceiling,
489
+ approval kind, and the registry approval identity when supervised).
490
+ - `briefing`: byte count and SHA-256 of the exact canonical parent briefing;
491
+ the prose is not retained and is distinct from bounded project context.
492
+ - `steering`: ordered byte/hash/timestamp and acknowledgement provenance for
493
+ successfully written steers; steering prose is never stored.
494
+ - `outcomeCode`: the stable terminal classifier, including
495
+ `worker_final_output_missing` when an otherwise successful worker exits
496
+ without a nonempty receipt-sealed final answer.
497
+ - `routingIntent`, `routeDecision`, and `quality`: the normalized hard bounds,
498
+ complete current-policy decision, exact execution role, route estimate and
499
+ readiness evidence, and authenticated quality sources.
500
+ - `resultContract`: the admitted contract identity and `valid`, `invalid`, or
501
+ `not-reached` conformance state. Only a due correctness-bearing contract can
502
+ label route quality.
503
+ - `validationGrounding`: claimed versus grounded validations checked against canonical executed commands.
504
+ - `capabilityMismatch`: capability class versus task shape verdict (`refuse` vs `flag`).
505
+ - worker attestation identity: settings/WorkerSpec fingerprints, runtime,
506
+ target, endpoint, model, tool surface, node, and bounded resource facts.
507
+
508
+ Process exit zero is not a delegated deliverable. Native and ACP runs succeed
509
+ only when the drained event stream yields a nonempty receipt output with
510
+ `state: "final"`. A missing final answer fails with
511
+ `outcomeCode: "worker_final_output_missing"`; any captured unfinished text is
512
+ retained only as `state: "partial"` diagnostics and automatic retry is
513
+ suppressed. Dispatch, monitor, ledger, receipt, terminal bus event, and retry
514
+ policy all consume that same final classification.
515
+
516
+ Receipt integrity and evidence verification are separate axes. Integrity says
517
+ that the sealed receipt matches its ledger envelope; evidence verification
518
+ reports whether Clio observed an applicable validation tool (or marks the
519
+ basis unknown/not applicable). A read-only Scout can therefore report `receipt_integrity=verified/v15/sha256` alongside
520
+ `evidence_verification=not_applicable/read-only-agent`. Briefing provenance and
521
+ bounded `project_context` provenance are also rendered independently; neither
522
+ hash substitutes for the other.
523
+
524
+ Gate references point backward: a reviewer references the builder it
525
+ reviewed, a revise builder references the reviewer whose findings it
526
+ received, and a judge references every candidate. Because a worker receipt
527
+ seals before the coordinator parses its final verdict, terminal pass/fail,
528
+ exhaustion, winner, and confirmation outcomes are append-only integrity-
529
+ covered gate-decision artifacts under the state directory. Evidence builds
530
+ discover them from linked receipt ids and export `gate-decisions.json`.
531
+ Reviewer and judge terminal output first crosses an integrity-covered
532
+ write-ahead boundary under `state/gate-decisions/pending/`, before the caller
533
+ waits for the final receipt. Restart recovery verifies the receipt, applies
534
+ the same verdict/winner parser, materializes the final artifact idempotently,
535
+ and only then clears the pending record. Missing receipts, tampering, or a
536
+ conflicting artifact fail closed and leave the journal and any compete
537
+ worktrees available for inspection.
538
+
539
+ Protected-artifact hard blocks follow compete work into candidate worktrees:
540
+ Clio mirrors every applicable parent-checkout path into each admitted worker
541
+ spec and independently rejects a winner branch whose diff touches a protected
542
+ parent path. The merge/apply coordinator rechecks the live protection state,
543
+ so neither full-auto nor a later supervised winner approval can override that
544
+ hard block.
545
+
546
+ ## Operator visibility
547
+
548
+ - The dispatch board shows per-run cards with the node id (absent placement
549
+ renders `local`), gate badges (`gate reviewer c2`), reroute badges, live
550
+ tool activity (names only; arguments never cross the worker stdout seam),
551
+ and a per-worker context meter.
552
+ - The context meter renders the worker's last-message context occupancy
553
+ against the model's context window: healthy below 80 percent, warn from 80,
554
+ critical from 95.
555
+ - `/fleet` cycles status (running and retrying runs with a node column),
556
+ nodes (the registry view with state, capacity, and last-seen), profiles
557
+ (with the node pin), and bindings.
558
+ - The monitor tool reports the node and reroute lineage on `status`, `list`,
559
+ and `collect`.
560
+ - `clio-coder fleet status [--json]` shows the durable ledger view cross-process.
561
+
562
+ ## Speculation observer
563
+
564
+ A shadow-mode observer watches every dispatch, computes the plan a rule-based
565
+ pipeline would have chosen (synchronous keyword rules, no model calls), and
566
+ records plan-versus-actual accuracy into a bounded JSONL under
567
+ `<state>/speculation/observations.jsonl`. It never influences dispatch;
568
+ disabling it changes nothing else.
569
+
570
+ ## Residency
571
+
572
+ Remote workers default to residency observe: the SSH transport exports
573
+ `CLIO_CODER_RESIDENCY=observe`, so a worker on a node that serves resident models
574
+ (for example a GPU box running the operator's inference server) never evicts
575
+ them. A node opts into management explicitly with `residency: manage` in its
576
+ fleet entry.
577
+
578
+ ## Opt-in live regression
579
+
580
+ After `npm run build`, an operator with a configured model target can run the
581
+ single-turn, read-only fleet lifecycle check explicitly:
582
+
583
+ ```bash
584
+ CLIO_CODER_LIVE_EVAL=1 npm run test:live-eval:fleet-dispatch
585
+ ```
586
+
587
+ It is not part of deterministic CI. The script copies the repository into an
588
+ isolated committed workspace, sandboxes all Clio config/state/data/cache,
589
+ exercises Scout, bounded spot-checking, detached Debugger briefing, steering,
590
+ wait, and collect, and fails if any workspace content changes. Failures retain
591
+ their isolated artifacts for diagnosis.