bullswarm 0.29.0 → 0.30.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,87 @@
1
1
  # bullswarm changelog
2
2
 
3
+ ## 0.30.0 — a run never waits: it finishes and hands back what is left
4
+
5
+ - workflow: a run no longer waits for anyone. Every point where a
6
+ caller-planned run used to hold now finishes it and hands the decision
7
+ back: a `--scout` run with no program, a launch program the kernel could not
8
+ accept, requirements still open with nothing left to run, and steering still
9
+ unread when the last step ended. In a study of 41 caller runs on a real
10
+ project (2026-09-14), one run sat 197 minutes waiting for a caller that had
11
+ moved on.
12
+ - result: a new optional `handback` field lists every unfinished step with its
13
+ failure kind, its reason, whether a plain resume runs it again, and
14
+ `retryAfter` when every pool that could run it was paused; every open
15
+ requirement with its latest reason; and steering nobody acted on.
16
+ `runs result --summary` adds `handback.options`, one command each to
17
+ continue (plan revise), retry (resume), take over, or restart. Results
18
+ written before 0.30.0 still validate, and their summaries derive the same
19
+ view.
20
+ - result: the reason line says what happened. "all program actions finished
21
+ successfully; consult evidence for verification" read as success on runs
22
+ whose check had failed the work. It now reads, for example, "all 4 steps
23
+ succeeded, but not verified: requirement-2 failed — requirement-2: …" or "2
24
+ of 5 steps did not succeed: build-api failed (stalled), …". A long finding
25
+ quoted there is cut between words and ends in `…`; the full text is in the
26
+ requirement's `why`.
27
+ - summary: an open requirement's `why` is no longer blanked to fit the 4 KB
28
+ budget. Concerns, per-step detail and output names shrink first, and a
29
+ passed requirement carries no `why`. The same study found `why` blank in 6
30
+ of 10 unverified runs.
31
+ - watch: a finished run prints `outcome: <status> · verified|not verified`,
32
+ `reason:`, one line per unfinished step and open requirement, unread
33
+ steering, and `your call:` with the command for each option. A `--jsonl`
34
+ `finished` object carries `verified`, `reason` and `handback`.
35
+ - resume: `workflow resume` on a finished run is a retry. It reopens the run
36
+ for pending and cancelled steps, failed steps whose kind a retry fixes
37
+ (`provider`, `quota`, `auth`, `process`, `unavailable`, `interrupted`,
38
+ `runtime`, `schema`, `stalled`) and the steps blocked behind them, moves the
39
+ result to `result-before-resume-<n>.json`, and relaunches. With nothing
40
+ retryable it prints `nothing to retry`, starts nothing, and exits 1.
41
+ - dispatch: with no pool able to run a step, the step fails at once and says
42
+ which case it is: every capable pool is paused until a time (recorded as
43
+ `retryAfter`), the pinned pool cannot run that lane and effort, or no enabled
44
+ pool has a model on that tier.
45
+ - workers: a worker that writes nothing for 60 minutes is stopped and fails as
46
+ `stalled`, a mechanical failure retried once. The clock restarts on every
47
+ byte, so a long step that keeps working is never cut off.
48
+ `BULLSWARM_WORKER_SILENCE_SEC` sets the limit.
49
+ - kernel: a kernel that throws marks its run `interrupted` with `kernel
50
+ stopped on an error: <message>` instead of leaving it claiming to run, and
51
+ `runs show` reports a run whose kernel died as `interrupted`, with the
52
+ reason and the resume command.
53
+ - validate: an `ownedFiles` entry naming a directory (`src/`, or an existing
54
+ `src`) or a glob is refused by `plan validate`, `workflow goal` and
55
+ `plan revise`; it used to pass and then stop the kernel right after launch.
56
+ A pinned worker pool that cannot run a step's lane and effort is refused
57
+ before launch. A new advisory, `requirement-unchecked`, names requirements
58
+ no step checks.
59
+ - legacy: runs an older version left waiting still accept `plan show` and
60
+ `plan submit`; `workflow resume` now finishes them with a handback instead
61
+ of pausing again.
62
+
63
+ ## 0.29.1 — a revised cancelled run runs its cancelled steps again
64
+
65
+ - workflow: revising a cancelled run reopened it but left every step the
66
+ cancellation had stopped as `cancelled`, so the kernel finalized `partial`
67
+ in the same second and nothing ran. Found on a real claude-code run
68
+ (`pxkr7s`, revision 7). Reopening now returns those steps to pending, lists
69
+ them as `reopened.requeued` in the revise output and the `workflow.reopened`
70
+ event, and never counts their earlier attempts as completion. Failed steps
71
+ still wait for an explicit `--rerun`.
72
+ - watch: a run waiting for its caller planner now also prints the
73
+ `plan export` / `plan revise` commands next to `plan show`.
74
+ - workflow: an attempt stopped by a plan revision or a pause now records
75
+ `failureKind: superseded` or `paused` on the attempt and in
76
+ `attempt.finished`, the same kind `action.finished` already carried. It was
77
+ recorded as a plain `cancelled`, which made deliberate steering look like
78
+ worker failures.
79
+ - strategy: `strategy rungs` no longer counts a stopped dispatch against a
80
+ pool's "% ok". On 2026-09-14 all 11 claude-code dispatches recorded as not
81
+ ok were workflow cancellations, plan revisions or pauses, none a worker
82
+ failure. Dispatch records now carry `failureKind`. The share was display
83
+ only; routing never read it.
84
+
3
85
  ## 0.29.0 — steer a running workflow, providers become directories, a declared reset date
4
86
 
5
87
  - workflow: the plan of a caller-planned program run can be changed at any
@@ -142,8 +142,9 @@ durable instruction that is delivered only to the next not-yet-started
142
142
  `decide` checkpoint; the active worker continues unchanged. In a caller-planned
143
143
  program run it never halts work: watchers print `steering received`, and the
144
144
  caller acts on it with `workflow plan revise`, which can stop, amend, add,
145
- remove, or rerun steps while the run continues; only a run about to finish with
146
- the guidance still unread pauses for it. Steering remains
145
+ remove, or rerun steps while the run continues. A run that finishes before
146
+ anyone acts on the guidance lists it as `steering not acted on`, and revising
147
+ the finished run delivers it and reopens the run. Steering remains
147
148
  inside the original goal and authorization boundary and cannot bypass runtime
148
149
  validation or required verification. Static workflows and terminal runs reject
149
150
  steering because they have no future orchestration checkpoint.
@@ -161,7 +161,7 @@ Manage a run with first-class verbs:
161
161
  bullswarm workflow plan export <shortId> --out plan.json # the live plan, editable
162
162
  bullswarm workflow plan revise <shortId> --program plan.json # change the plan while it runs
163
163
  bullswarm workflow pause <shortId> [--now] # start nothing new; resume continues
164
- bullswarm workflow resume <shortId> --watch # lift a pause; verb form of goal --resume
164
+ bullswarm workflow resume <shortId> --watch # lift a pause, or retry a finished run's retryable steps
165
165
  bullswarm workflow steer <shortId> --message "<guidance>" # guidance for whoever plans the run
166
166
  bullswarm workflow cancel <shortId> --json # a run with no kernel is finalized here
167
167
  ```
@@ -198,6 +198,33 @@ lets running agents finish and starts nothing new (`--now` stops them and runs
198
198
  those steps again after resume); revisions apply while paused, and only
199
199
  `workflow resume` continues the run.
200
200
 
201
+ ### A run never waits: it finishes and hands back
202
+
203
+ No run waits for its caller. When nothing more can run on its own (every step
204
+ has finished, failed, or is blocked behind a failure; no pool can take a step;
205
+ a `--scout` run has no program yet; steering arrived after the last step), the
206
+ run finishes `completed` or `partial`, and its result carries a `handback`:
207
+ each unfinished step with its failure kind, reason, whether a plain resume runs
208
+ it again, and `retryAfter` when every pool that could run it was paused; each
209
+ open requirement with its reason; and steering nobody acted on.
210
+ `watch` prints the same as `step …`, `requirement …` and `steering not acted
211
+ on:` lines, then `your call:` with one command per option:
212
+
213
+ - **continue**: export, edit and revise the plan (a failed check needs a fix
214
+ step added to the check's `dependsOn`);
215
+ - **retry**: `workflow resume <shortId>` reruns steps that failed for a reason
216
+ a retry fixes (`provider`, `quota`, `auth`, `process`, `unavailable`,
217
+ `interrupted`, `runtime`, `schema`, `stalled`), plus pending and cancelled
218
+ steps and the steps blocked behind them; with none it prints `nothing to
219
+ retry` and exits 1;
220
+ - **take over**: do the rest yourself from `runs result <shortId> --json`;
221
+ - **restart**: start a new `workflow goal`.
222
+
223
+ A step no pool can take fails at once instead of waiting for a pool to come
224
+ back, and a worker that writes nothing for 60 minutes is stopped as `stalled`
225
+ (`BULLSWARM_WORKER_SILENCE_SEC` changes the limit). The only stop that holds a
226
+ run is `workflow pause`, which you choose.
227
+
201
228
 
202
229
  `--orchestrator <pool>` expresses a preference and immediately falls back to
203
230
  another eligible pool if that provider is quota-gated or unavailable; plain
@@ -279,33 +306,31 @@ bullswarm workflow plan validate "1. Fix the parser. 2. Update the docs." --cwd
279
306
  # → dry run against that contract; exit 0 valid, exit 2 with the issues; nothing launches
280
307
  bullswarm workflow goal "1. Fix the parser. 2. Update the docs." --cwd . --program plan.json --watch
281
308
  # → validated before launch; executes with zero planner/scout dispatches
282
- bullswarm workflow plan show <shortId> --json # initial scout or explicit steering pause
283
- bullswarm workflow plan submit <shortId> --program plan-2.json --watch
309
+ bullswarm workflow runs result <shortId> --json --summary # outcome, reason, handback
284
310
  ```
285
311
 
286
- Exit codes are a contract: **0** done or paused durably for you (nothing is
287
- running), **1** the run ended without completing, **2** usage or validation
288
- error with nothing launched. Every refusal names the commands that come next.
312
+ Exit codes are a contract: **0** completed, or stopped by `workflow pause`
313
+ (nothing is running), **1** the run finished without completing, **2** usage or
314
+ validation error with nothing launched. Every refusal names the commands that
315
+ come next.
289
316
 
290
- For foreground execution, exit 0 means the graph ran successfully or paused
291
- durably; it does not imply independent verification. An independent launch
317
+ For foreground execution, exit 0 means the graph ran successfully or was
318
+ paused; it does not imply independent verification. An independent launch
292
319
  also returns 0 before the workers finish. Consume its eventual result.
293
320
 
294
321
  `--program` accepts the planner response envelope or a bare
295
322
  `bullswarm.workflow.program.v2` document. An invalid program exits 2 with the
296
- validator's issues and nothing is launched. When the kernel reaches a planning
297
- boundary (an initial plan, or a run about to finish with queued steering still
298
- unread), it writes `planner-request-turn-N.json`, sets the run to `waiting`,
299
- exits, and `watch` prints the `plan show` command. A submitted program contains
300
- only new actions and is validated against the exact durable state at that
301
- boundary. Steering queued while work is still running does not stop it: watch
302
- prints `steering received` and the caller answers with `plan revise` (see
303
- [Changing the plan of a live run](#changing-the-plan-of-a-live-run)). Older saved V2
304
- runs still support their original gap boundaries and `--exhausted` submissions.
305
- `--scout` without
306
- `--program` runs the kernel scout first and pauses at the initial boundary so
307
- the caller plans against a real survey; scout units are advisory for a caller
308
- planner.
323
+ validator's issues and nothing is launched. Validate also refuses an
324
+ `ownedFiles` entry that is a directory or a glob, and a pinned pool that cannot
325
+ run a step. Steering queued while work is still running does not stop it:
326
+ watch prints `steering received` and the caller answers with `plan revise` (see
327
+ [Changing the plan of a live run](#changing-the-plan-of-a-live-run)). A run
328
+ an older version left waiting for its caller (`planner-request-turn-N.json`,
329
+ status `waiting`) still accepts `plan show` and `plan submit`, including
330
+ `--exhausted` at a gaps boundary; `workflow resume` finishes it with a handback
331
+ instead. `--scout` without `--program` runs the kernel scout and finishes
332
+ partial with the report, which the caller plans from and adds with `plan
333
+ revise`; scout units are advisory for a caller planner.
309
334
 
310
335
  An action's result envelope is covered in [Operations](./operations.md#result-envelope);
311
336
  the JSON example program shape (writers, a digest, and one integrator) is in
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bullswarm",
3
- "version": "0.29.0",
3
+ "version": "0.30.0",
4
4
  "description": "Route work across coding-agent CLI subscriptions — paced by live quota meters, verified by content, never trusting exit codes.",
5
5
  "type": "module",
6
6
  "bin": {
package/skill/SKILL.md CHANGED
@@ -91,12 +91,17 @@ bullswarm workflow plan validate "$(cat goal.txt)" --cwd=<abs-dir> --program=<ab
91
91
  ```
92
92
 
93
93
  Exit 2 means the program is invalid: the JSON lists `issues`; fix them and
94
- validate again. Exit 0 always carries an `advisories` array. Each entry names
95
- an action whose effort is above what its work warrants (`all-writers-high`,
96
- `docs-at-high`): lower that action's kind and validate again, or write the
97
- reason it needs high into its `purpose`. An empty array means launch now, with
98
- the same goal, `--cwd` and absolute `--program` (validate's `next.launch` line
99
- is this command):
94
+ validate again. Validate also refuses what would only fail after launch: an
95
+ `ownedFiles` entry that is a directory or a glob (name exact files), and, with
96
+ a pinned pool, a step that pool cannot run. Exit 0 always carries an
97
+ `advisories` array. `all-writers-high` and `docs-at-high` name an action whose
98
+ effort is above what its work warrants: lower that action's kind, or write the
99
+ reason it needs high into its `purpose`. `requirement-unchecked` names a
100
+ requirement no step lists in `evidenceFor`: the run can finish but never
101
+ verify it, so add it to an `adversarial-acceptance` step, or launch knowing the
102
+ result will be unverified. An empty array means launch now, with the same
103
+ goal, `--cwd` and absolute `--program` (validate's `next.launch` line is this
104
+ command):
100
105
 
101
106
  ```bash
102
107
  bullswarm workflow goal "$(cat goal.txt)" --cwd=<abs-dir> --program=<abs-dir>/plan.json --json
@@ -106,28 +111,60 @@ The launch detaches and returns `shortId`; report it.
106
111
 
107
112
  ## 3. Observe and judge
108
113
 
114
+ A run never waits for you. It runs until nothing more can happen on its own,
115
+ then finishes, and its result hands back whatever is left with your options.
116
+ What happens next is your decision.
117
+
109
118
  ```bash
110
119
  bullswarm workflow watch <shortId> --next
111
120
  bullswarm workflow runs result <shortId> --json --summary
112
121
  ```
113
122
 
114
- Run `watch --next` in a background terminal. When it exits, act on the printed
115
- event and relaunch with the exact `next: bullswarm workflow watch <shortId>
116
- --next --after <sequence> --since <iso>` line it printed, until the outcome
117
- line reports a pause or a terminal status. A pause is not completion.
123
+ Run `watch --next` in a background terminal and wait for it to exit. Do not
124
+ poll in a loop and do not read files in the run directory. When it exits on an
125
+ event, act on it and relaunch with the exact `next: bullswarm workflow watch
126
+ <shortId> --next --after <sequence> --since <iso>` line it printed. When it
127
+ exits on an `outcome:` line, the run has finished, paused, or been
128
+ interrupted, and the output already holds what you need to decide.
118
129
 
119
- Each wake-up is a decision point: read the output of the step that just
130
+ Each event is a decision point: read the output of the step that just
120
131
  finished (`bullswarm workflow action show <shortId> <actionId>` names its
121
132
  `outputFile`) and decide whether the rest of the plan still fits. If it does,
122
133
  relaunch the watcher. If it does not, revise the plan (section 4) before
123
134
  relaunching.
124
135
 
136
+ ### When it finishes
137
+
138
+ `outcome:` gives `completed`, `partial` or `cancelled` and whether the run is
139
+ verified; `reason:` says why in one line. `completed` means every step
140
+ succeeded. `verified` means every mandatory requirement passed its check,
141
+ which can still miss bugs. Anything short of verified is followed by what is
142
+ left: `step <id>: <status> (<kind>) — <why>` for each unfinished step,
143
+ `requirement <id>: <status> — <why>` for each open requirement, and `steering
144
+ not acted on:` for guidance that arrived too late. Then `your call:` gives one
145
+ command per option:
146
+
147
+ | Option | When | What to do |
148
+ |---|---|---|
149
+ | continue | the plan needs a fix, a new step, or a step redone | export, edit, and revise the plan (section 4) |
150
+ | retry | a step stopped for a reason a retry fixes: no pool, a paused pool, a crashed or silent worker | `bullswarm workflow resume <shortId>` |
151
+ | take over | the rest is small, or needs something only you have (a logged-in browser, a credential, a decision for the user) | do it yourself; `runs result <shortId> --json` names every step's output |
152
+ | restart | the goal or the approach was wrong | start a new `workflow goal` run |
153
+
154
+ `retry` appears only when a step is retryable. `resume` on a finished run
155
+ reruns exactly those steps and the steps blocked behind them. When nothing is
156
+ retryable it prints `nothing to retry`, starts nothing, and exits 1. A step
157
+ whose pools were all paused shows `its pool is back at <time>`; resuming
158
+ before then fails it again at once.
159
+
160
+ A failed check is a plan problem, not a retry. When the check step reports a
161
+ requirement failed, keep the same run: export the plan, add a step that fixes
162
+ what the evidence names, and add that step's id to the check's `dependsOn`.
163
+ The changed check runs again after the fix, and the run finishes again.
164
+
125
165
  Then read the real outputs and artifacts and probe the important edge cases
126
- yourself. `completed` means the graph ran. `verified` means evidence passed,
127
- which can still miss bugs. `partial` exposes failed or skipped branches; revise
128
- the plan to repair them (a revision reopens a finished run). Shared files
129
- remain after failure or cancellation. Exit 0 can mean launched, paused, or
130
- completed, so always inspect the returned status.
166
+ yourself. Shared files remain after failure or cancellation. Exit 0 can mean
167
+ launched, paused, or completed, so always inspect the returned status.
131
168
 
132
169
  ## 4. Steer a running workflow
133
170
 
@@ -174,7 +211,9 @@ Rules that matter when you edit:
174
211
  must not remain, give a new or amended step the job of reverting or repairing
175
212
  them.
176
213
  - Revising a finished run (`completed`, `partial`, `cancelled`) reopens it: the
177
- new plan runs and the run finishes again with a new result.
214
+ new plan runs and the run finishes again with a new result. Steps a
215
+ cancellation stopped run again; failed steps run again only when named in
216
+ `rerun`.
178
217
  - To think without new work starting, pause first: `bullswarm workflow pause
179
218
  <shortId>` starts nothing new and lets running agents finish (`--now` stops
180
219
  them; they run again after resume). Export and revise while paused, then
@@ -183,7 +222,9 @@ Rules that matter when you edit:
183
222
  and `steering received`. Steering a person queued never halts work: decide
184
223
  what it means for the plan and revise. The exported file lists pending
185
224
  steering in `steeringIds`, and a revision from that file marks it delivered.
186
- A run about to finish with unread steering pauses for it instead.
225
+ A run that finishes before you act on steering lists it as `steering not
226
+ acted on`; revising the finished run from a fresh export delivers it and
227
+ reopens the run.
187
228
 
188
229
  [operations.md](references/operations.md) covers the revision details, pause
189
230
  and resume, cancellation, scouting, a dispatched planner, isolation, watch
@@ -17,7 +17,7 @@ unless it asks for a dispatched one. The three ways to start:
17
17
 
18
18
  ```bash
19
19
  bullswarm workflow goal '<goal>' --cwd=<abs-dir> --program plan.json --json # you plan (see below)
20
- bullswarm workflow goal '<goal>' --cwd=<abs-dir> --scout # kernel surveys, then pauses for your program
20
+ bullswarm workflow goal '<goal>' --cwd=<abs-dir> --scout # kernel surveys, then finishes and hands you the report
21
21
  bullswarm workflow goal '<goal>' --cwd=<abs-dir> --orchestrator auto \
22
22
  --suggested-plan='<conceptual plan>' --json # dispatch a planner agent
23
23
  ```
@@ -69,7 +69,11 @@ heartbeat) instead of event mode; it applies only to V2 runs. A legacy
69
69
  authored-graph run cannot be watched at all: the watcher prints the legacy
70
70
  line and exits 2 before polling. `--classic` cannot combine with `--next`.
71
71
  The result command is the stable delivery/verification envelope; do not scrape
72
- task files or assume the last provider response is the deliverable.
72
+ task files or assume the last provider response is the deliverable. A finished
73
+ run's watch output ends with `outcome: <status> · verified|not verified`,
74
+ `reason:`, the handback lines and `your call:` options (see "When a run
75
+ finishes" below); under `--jsonl` the `finished` object carries `verified`,
76
+ `reason` and `handback`.
73
77
 
74
78
  Manage a live run:
75
79
 
@@ -77,14 +81,14 @@ Manage a live run:
77
81
  bullswarm workflow plan export <shortId> --out plan.json # the live plan as an editable revision document
78
82
  bullswarm workflow plan revise <shortId> --program plan.json --json # replace the plan at any time (see below)
79
83
  bullswarm workflow pause <shortId> [--now] # start nothing new; --now also stops running agents
80
- bullswarm workflow resume <shortId> [--foreground|--watch] # lift a pause; verb form of goal --resume
84
+ bullswarm workflow resume <shortId> [--foreground|--watch] # lift a pause, continue an interrupted run, or retry a finished one
81
85
  bullswarm workflow steer <shortId> --message '<guidance>' # guidance for whoever plans the run
82
86
  bullswarm workflow cancel <shortId> --json # cooperative; a run with no kernel is finalized here
83
87
  ```
84
88
 
85
89
  Resume keeps the run's durable planner mode, routing pins, and settings;
86
90
  `--program`, `--orchestrator`, `--scout`, and `--suggested-plan` are rejected
87
- there (use `workflow plan submit` for a caller program). Autonomous resume is
91
+ there (change the plan with `plan revise`). Autonomous resume is
88
92
  V2-only. An old autonomous run ID fails before dispatch; there is no migration
89
93
  or fallback executor. `bullswarm workflow goal --resume <shortId>` and
90
94
  `bullswarm workflow tui --cancel <shortId>` remain as aliases.
@@ -147,10 +151,11 @@ digest gets the digest entry in its `Dependency artifacts` list plus a
147
151
  `digestOf` array naming each digested source, so it can still open the
148
152
  originals.
149
153
 
150
- Two advisories report effort smells and never reject anything.
151
- `all-writers-high` fires when three or more `build`/`chore` actions run and none
152
- is below high effort; `docs-at-high` fires when a `build`/`chore` action owns
153
- only `*.md` files at high effort. `plan validate --json` carries them under
154
+ Three advisories, none of which rejects anything. `all-writers-high` fires
155
+ when three or more `build`/`chore` actions run and none is below high effort;
156
+ `docs-at-high` fires when a `build`/`chore` action owns only `*.md` files at
157
+ high effort; `requirement-unchecked` fires when a requirement is in no action's
158
+ `evidenceFor`, so the run can finish but never verify it. `plan validate --json` carries them under
154
159
  `advisories` and its human output prints `advisory:` lines; `workflow goal`
155
160
  prints the same lines at launch. Exit codes are unchanged, and the kernel stores
156
161
  them on the run, so `workflow runs show` lists them afterwards. `runs result`,
@@ -159,8 +164,8 @@ them on the run, so `workflow runs show` lists them afterwards. `runs result`,
159
164
  ## Revising a live plan
160
165
 
161
166
  `plan revise` replaces the plan of a caller-planned program run at any moment:
162
- while agents run, while it is paused, while it waits at a planning boundary, or
163
- after it finished. Start from the export so kept actions compare equal:
167
+ while agents run, while it is paused, or after it finished. Start from the
168
+ export so kept actions compare equal:
164
169
 
165
170
  ```bash
166
171
  bullswarm workflow plan export <shortId> --out plan.json # or --json for status + document
@@ -209,8 +214,10 @@ being replaced is stopped before the new plan is committed
209
214
  CLI applies the revision itself under the kernel lease and relaunches the
210
215
  kernel detached, unless the run is paused. A finished run is reopened: its
211
216
  `result.json` moves to `result-before-revision-<n>.json`, a
212
- `workflow.reopened` event is written, and the new plan runs to a new result. A
213
- revision also clears a caller-planner wait, so it can replace `plan submit`.
217
+ `workflow.reopened` event is written, and the new plan runs to a new result.
218
+ Steps a cancellation stopped return to pending (`reopened.requeued`); failed
219
+ steps stay failed unless the revision names them in `rerun`. A revision also
220
+ answers a run an older version left waiting for its caller.
214
221
 
215
222
  Stopping a process does not undo its edits in the shared tree. When a stopped
216
223
  or removed step's partial changes must go, amend it or add a step whose prompt
@@ -239,57 +246,76 @@ refused.
239
246
  `steering received`; the caller decides what the message means and revises.
240
247
  `plan export` lists undelivered steering under `pendingSteering` (with `--json`)
241
248
  and puts its ids in the document's `steeringIds`, so a revision from the export
242
- marks it delivered (`steering.delivered`, `source: revision`). When the graph
243
- would otherwise finish with steering still unread, the run pauses at a
244
- `steering` boundary instead; answer it with a revision (an acknowledgement-only
245
- revision is enough when the guidance needs no plan change) or with `plan
246
- submit`.
247
-
248
- ## Submitting work at a planning pause
249
-
250
- Use these commands when `watch` reports a caller-planner pause:
251
-
252
- ```bash
253
- bullswarm workflow plan show <shortId> --json
254
- bullswarm workflow plan submit <shortId> --program plan-2.json --watch
255
- ```
256
-
257
- Read the current request and author only new actions; existing action IDs can
258
- be dependencies. `plan revise` is accepted at the same pause when the answer
259
- also changes, removes, or reruns existing actions. New shared programs pause
260
- for opt-in scouting or, in a run about to finish, unread steering, not negative
261
- evidence. A submission is validated before modifying the run. Resuming without
262
- a submission preserves the pause.
263
-
264
- Older saved runs can also pause for requirement gaps and accept
265
- `plan submit <shortId> --exhausted --reason '<why>'` there. Do not use
266
- `--exhausted` for a new program or a steering request.
267
-
268
- Pause hygiene, all kernel-enforced:
269
-
270
- - The pause is authoritative. A resume keeps the recorded boundary and turn
271
- even when steering was queued meanwhile; the request is refreshed to list the
272
- pending steering (`pendingSteering`, also merged into `context.steering`).
273
- `plan show` performs the same refresh (`requestRefreshed: true`) without
274
- changing run state. A submission marks exactly the listed steering
275
- delivered (`steering.delivered` events tagged `source: caller`); steering
276
- queued after the request was shown stays pending and opens a `steering`
277
- boundary after the resume. A steering boundary needs at least one new action
278
- (`--exhausted` is valid only at a `gaps` boundary and is only advertised
279
- there).
280
- - `workflow cancel <id>` on a paused run finalizes it inline: no kernel is
281
- alive to honor a cooperative request, so the cancelled result envelope is
282
- written and the pause record cleared in that one command. If cancellation was
283
- recorded some other way (`tui --cancel`), `plan submit` refuses every
284
- submission and `plan show`/`watch` print `bullswarm workflow cancel <id>
285
- --json`. Finalizing always clears `planner.awaiting`; a terminal state that
286
- still claims to be waiting is rejected by the state validator.
287
- - A `--program` supplied at launch is kept as `initial-planner-response.json`
288
- in the run directory until applied, so an interruption during an opt-in
289
- `--scout` does not lose it.
290
- - Bare value flags (`--program` with no file, `--orchestrator` with no pool)
291
- are usage errors (exit 2); nothing launches in a different mode. `plan submit`
292
- checks the goal directory before touching state.
249
+ marks it delivered (`steering.delivered`, `source: revision`). A run never
250
+ waits for steering: if the graph finishes first, the result lists it under
251
+ `handback.unreadSteering` and watch prints `steering not acted on`. Revise the
252
+ finished run from a fresh export to deliver it; that reopens the run.
253
+
254
+ ## When a run finishes: the handback
255
+
256
+ A run never waits: not for its caller, not for a paused pool, not for a silent
257
+ worker. It finishes as soon as nothing more can happen on its own. The result
258
+ carries a `handback` whenever it is not verified or has steering nobody acted
259
+ on:
260
+
261
+ - `handback.unfinished[]`: `{id, status, failureKind, why, retryAfter?,
262
+ retryable}` for every step that did not succeed. `retryable` says whether
263
+ `workflow resume` would run it again. `retryAfter` is set when every pool
264
+ able to run the step was paused: the earliest time one is back.
265
+ - `handback.unresolvedRequirements[]`: `{id, status, why}` with the latest
266
+ evidence line, or `no evidence recorded for the current work`.
267
+ - `handback.unreadSteering[]`: `{id, message, queuedAt}`.
268
+
269
+ `runs result --summary` adds `handback.options`, one command per choice
270
+ (`continue`, `retry` when a step is retryable, `takeOver`, `restart`). An open
271
+ requirement keeps its `why` for as long as the 4 KB budget allows; concerns and
272
+ per-step detail shrink first. The `workflow.finished` event carries
273
+ `unfinished` and `unreadSteering` counts. The reason line says what happened:
274
+ `all 4 steps succeeded, but no step checked the requirements, so the result is
275
+ not verified`, or `2 of 5 steps did not succeed: build-api failed (stalled), …`.
276
+
277
+ Where a run used to wait, it now finishes:
278
+
279
+ | Situation | What happens |
280
+ |---|---|
281
+ | `--scout` with no program | `partial`: `no program to run (the scout report is at …)`; add steps with `plan revise` |
282
+ | a launch program the kernel cannot accept | `partial`: the reason lists the issues; nothing ran |
283
+ | requirements open with nothing left to run (older verified-mode runs) | `partial` with gaps |
284
+ | steering unread when the last step ends | the run finishes; `unreadSteering` lists it |
285
+ | every pool able to run a step is paused | the step fails at once (`unavailable` or `quota`) with `retryAfter` |
286
+ | a worker writes nothing for 60 minutes | stopped as `stalled`, retried once mechanically, then handed back |
287
+ | the kernel throws | the run is marked `interrupted` with `kernel stopped on an error: …`; `resume` continues it |
288
+
289
+ Resume on a finished run is a retry. It reopens the run for pending and
290
+ cancelled steps, failed steps whose kind a retry fixes (`provider`, `quota`,
291
+ `auth`, `process`, `unavailable`, `interrupted`, `runtime`, `schema`,
292
+ `stalled`), and the steps blocked behind them; moves `result.json` to
293
+ `result-before-resume-<n>.json`; writes `workflow.reopened` with `source:
294
+ resume`; and relaunches the kernel. A step that failed for any other reason
295
+ (the worker reported failure, `ownership`) stays failed: change the plan with
296
+ `plan revise`. With nothing retryable, resume prints `nothing to retry`, lists
297
+ the steps that need you, starts nothing, and exits 1.
298
+
299
+ The silence cutoff is `BULLSWARM_WORKER_SILENCE_SEC` (default 3600). It
300
+ measures silence, not run time: every byte a worker writes restarts it.
301
+
302
+ A `--program` supplied at launch is kept as `initial-planner-response.json` in
303
+ the run directory until applied, so an interruption during an opt-in `--scout`
304
+ does not lose it. Bare value flags (`--program` with no file, `--orchestrator`
305
+ with no pool) are usage errors (exit 2); nothing launches in a different mode.
306
+
307
+ ### Runs an older version left waiting
308
+
309
+ Runs started before 0.30.0 may still sit at a planning boundary; `watch`
310
+ prints `waiting for the caller planner`. Either answer it (`plan show
311
+ <shortId> --json`, then `plan submit <shortId> --program plan-2.json`, or
312
+ `--exhausted --reason '<why>'` at a `gaps` boundary; a `plan revise` also
313
+ answers it), or run `workflow resume <shortId>`, which finishes it and hands
314
+ back what is left. `plan show` refreshes the request with steering queued
315
+ since, and a submission marks exactly the listed steering delivered.
316
+ `workflow cancel <id>` finalizes a waiting run inline; once cancellation is
317
+ recorded, `plan submit` refuses every submission. `plan submit` checks the goal
318
+ directory before touching state.
293
319
 
294
320
  ## Workspace and concurrency options
295
321
 
@@ -458,11 +484,17 @@ document and writes nothing.
458
484
  killed at once, the pool is quarantined until the reset the message named
459
485
  (else its cached 5-hour `resets_at`, else 30 minutes), and the action moves
460
486
  to a pool that still has quota. The quarantine holds across runs until it
461
- expires. Discussing usage limits in a report is not a usage limit.
487
+ expires. When no pool able to run the step is left, the step fails at once
488
+ with `retryAfter` and the run hands it back; nothing waits for the reset.
489
+ Discussing usage limits in a report is not a usage limit.
462
490
  - A quota-gated preferred orchestrator falls back unless it was strictly pinned
463
491
  for QA.
464
- - Silence is evidence to inspect, not automatic proof of a hang. Check the TUI
465
- or JSON activity and stall fields before cancellation.
492
+ - A worker silent for `BULLSWARM_WORKER_SILENCE_SEC` (default 60 minutes) is
493
+ stopped as `stalled`. Shorter silence is evidence to inspect, not proof of a
494
+ hang: check the TUI or JSON activity and stall fields before cancelling.
495
+ - `ownedFiles` naming a directory or a glob is refused at `plan validate` and
496
+ at launch, and so is a pinned pool that cannot run a step's lane and effort.
497
+ Both used to fail only after launch.
466
498
  - A malformed V2 planner program receives one compact deterministic correction
467
499
  request. Repeated invalidity ends planning before worker budget is spent.
468
500
  - Schema-invalid evidence receives a bounded correction in the same physical