bullswarm 0.10.2 → 0.10.4

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/AGENTS.md CHANGED
@@ -37,7 +37,7 @@ content. Published as `bullswarm` on npm.
37
37
  ## Development
38
38
 
39
39
  ```bash
40
- npm test # 232 tests, no network needed (meters read from cache)
40
+ npm test # 256 tests, no network needed (meters read from cache)
41
41
  node bin/bullswarm.js doctor --json # readiness report
42
42
  node bin/bullswarm.js workflow list # discover workflows
43
43
  node bin/bullswarm.js workflow runs # ongoing workflow instances
package/CHANGELOG.md CHANGED
@@ -1,5 +1,64 @@
1
1
  # bullswarm changelog
2
2
 
3
+ ## 0.10.4 — durable interactive workflow viewer
4
+
5
+ - Added `workflow runs result <id> [--json]`, a stable
6
+ `bullswarm.workflow.result.v1` handoff for parent agents. It selects the final
7
+ successful delivery rather than the last orchestrator response, pairs it with
8
+ its dependent verification verdict, and reports progress, step logs, token
9
+ usage, and honest complete-or-partial tool-call counts.
10
+ - Goal launches now return and print a four-part operating handoff for agentic
11
+ inspection, low-noise watching, the human TUI, and terminal result retrieval.
12
+ - Plain `workflow goal` now launches independently, prints that handoff, and
13
+ returns. The new explicit `--watch` flag follows low-noise progress until the
14
+ terminal state; the human TUI is opened from the printed command.
15
+ - `--foreground` retains terminal-owned execution and `--detach` remains an
16
+ explicit backward-compatible spelling of the new default.
17
+ - Rebuilt interactive workflow inspection as a responsive Phase → Agent →
18
+ Agent-activity browser: desktop uses two contextual panes while mobile and
19
+ narrow SSH terminals use one full-width level. It includes arrow/Enter/Esc
20
+ navigation, numbered semantic actions, active-agent following, scrolling,
21
+ completed-agent outcomes, total semantic-action counts, terminal agent
22
+ progress, resize handling, safe detach, and confirmed stopping.
23
+ - Made the autonomous orchestrator a compact selectable control-plane panel
24
+ stacked above the phase tree. Arrow/Enter or `o` opens its
25
+ durable session, checkpoint decisions, semantic
26
+ activity, usage, prompt, outcomes, and artifacts without counting planner
27
+ turns as phase workers.
28
+ - Standardized workflow TUI state marks across orchestrator, phases, agents,
29
+ and semantic activity: `○` pending, animated Braille spinner active, `⧖`
30
+ waiting, `✓` complete, and `✗` failed or interrupted.
31
+ - Made `maxExpansionRounds` an advisory convergence target instead of a hard
32
+ failure boundary. Near the target the orchestrator is told to consolidate
33
+ existing evidence and avoid marginal expansion; essential bounded work may
34
+ exceed it and the overage is recorded.
35
+ - Added truthful qualified terminal outcomes: planner `stop` now yields
36
+ `completed_with_concerns` with a ready best-effort delivery when useful work
37
+ exists, or `blocked` when it does not. Result envelopes expose `verified`,
38
+ the stopping reason, and unresolved concerns without relabeling failed
39
+ verification as success.
40
+ - Made phase and agent status derive from semantic output verdicts, so a
41
+ verifier process that successfully returns `ok:false` is displayed as a
42
+ failed verification rather than a completed check.
43
+ - Added persisted `strategy exclude-model` / `include-model` policy. Excluded
44
+ models are removed from strategy recommendations and dispatch assignments;
45
+ connectors pin an allowed same-tier fallback or become ineligible when they
46
+ cannot guarantee the exclusion.
47
+ - Let the CLI process drain stdout before exiting, preventing large
48
+ `workflow tui --json` snapshots from being truncated around the platform
49
+ pipe-buffer boundary.
50
+ - Expanded `workflow --help` into an operational map for building, observing,
51
+ controlling, and auditing workflows.
52
+
53
+ ## 0.10.3 — contextual help everywhere
54
+
55
+ - Added side-effect-free `-h` / `--help` handling for the top-level CLI and
56
+ every command and nested subcommand, including workflow drafts, run history,
57
+ approvals, actions, integrations, and strategy policy controls.
58
+ - Added a centralized command help tree so contextual help is consistent and
59
+ intercepted before setup, provider discovery, state writes, or destructive
60
+ command execution.
61
+
3
62
  ## 0.10.2 — cross-agent skill integration
4
63
 
5
64
  - Added explicit `bullswarm integrate status|install|remove` support for Codex,
package/README.md CHANGED
@@ -5,6 +5,24 @@ orchestrator, build and expand the plan, route bounded worker actions by quota,
5
5
  verify the result, and finish without an initiating agent authoring a graph.
6
6
  Every delegate output is judged by content before it counts.
7
7
 
8
+ Every command and nested subcommand supports contextual `-h` / `--help`
9
+ without initializing state or executing the command:
10
+
11
+ ```bash
12
+ bullswarm --help
13
+ bullswarm workflow run --help
14
+ bullswarm workflow draft step add --help
15
+ ```
16
+
17
+ `workflow goal` launches a durable background runner, prints operating commands,
18
+ and returns by default. Add `--watch` to immediately follow low-noise progress
19
+ until terminal, or `--foreground` to keep execution owned by the initiating
20
+ terminal. Open the full-screen Phase → Agent → Activity viewer at any time with
21
+ `bullswarm workflow tui <shortId>`; use Up/Down, Enter, Esc, and `q` to detach.
22
+ Wide terminals use two
23
+ contextual panes (phases + agents, then agents + activity); narrow and mobile
24
+ terminals give each level the full screen automatically.
25
+
8
26
  ## The doctrine (non-negotiable)
9
27
 
10
28
  1. **Judge by CONTENT, not exit code.** Every delegate CLI can exit 0 while
@@ -79,6 +97,7 @@ bullswarm strategy auto status
79
97
  bullswarm strategy set-subscription command-code \
80
98
  --plan GOAT --monthly-usd 10 --included-usd 70 --quota-window monthly
81
99
  bullswarm strategy assign high --pool claude-code --model claude-opus-4-6
100
+ bullswarm strategy exclude-model claude-fable-5
82
101
  bullswarm run --effort high --lane analyze --task-file /tmp/task.md --json
83
102
  ```
84
103
 
@@ -94,6 +113,12 @@ prices, and benchmarks stay `null` rather than being guessed. An assignment is
94
113
  only a preference: quarantine, exhaustion, burst gates, and capability checks
95
114
  still win.
96
115
 
116
+ Model exclusions are hard routing policy. An excluded model is removed from
117
+ recommendations and assignments, and Bullswarm pins a same-tier allowed model
118
+ through the connector-owned model flag whenever the provider default could be
119
+ excluded. A pool that cannot guarantee the exclusion is ineligible for that
120
+ dispatch. Reverse the policy with `bullswarm strategy include-model <model>`.
121
+
97
122
  Every run and workflow attempt reports its selected agent/model and estimated
98
123
  usage. When a delegate does not expose counters, Bullswarm labels its UTF-8
99
124
  byte/4 token estimate. The breakdown separates standard read, cache read,
@@ -107,26 +132,33 @@ phase/step/attempt tree.
107
132
  For normal multi-step work, give Bullswarm the goal—not a JSON graph:
108
133
 
109
134
  ```bash
110
- # Foreground: streams progress and returns when terminal.
135
+ # Default: starts independently, prints observation/result commands, and returns.
111
136
  bullswarm workflow goal \
112
137
  "Fix the failing tests with the smallest correct change and verify them" \
113
138
  --cwd ~/some-repo
114
139
 
115
- # Detached: the initiating CLI exits; the workflow continues independently.
140
+ # Follow low-noise semantic progress immediately after launch.
116
141
  bullswarm workflow goal \
117
142
  "Audit and repair the parser, then run its acceptance tests" \
118
- --cwd ~/some-repo --detach --json
143
+ --cwd ~/some-repo --watch
119
144
  ```
120
145
 
121
146
  Bullswarm first honors an approved high-tier provider/model assignment when it
122
147
  remains eligible, otherwise it selects an eligible `workflow-planning`
123
- orchestrator by live quota surplus. The orchestrator observes durable evidence, proposes bounded actions,
148
+ orchestrator by live quota surplus. The orchestrator is one durable control-plane
149
+ conversation: Grok and Claude resume the same provider session at later
150
+ checkpoints, while Bullswarm keeps each turn separately auditable for routing,
151
+ usage, and recovery. It observes durable evidence, proposes bounded actions,
124
152
  and decides when another expansion or verification is necessary. Bullswarm
125
153
  validates the proposal, owns agent/process selection, routes workers, and calls
126
154
  the orchestrator again until completion, cancellation, failure, approval, or a
127
155
  hard graph-growth safeguard. No initial phases, prompts, JSON schema, or agent choice are
128
156
  required from the user.
129
157
 
158
+ Planner actions carry forward-only kebab-case phase names. A finished phase is
159
+ sealed: later planner turns must create a new phase for repair or verification,
160
+ so the TUI cannot jump backward or append work beneath a completed phase.
161
+
130
162
  The detached response includes a short ID and exact observation commands:
131
163
 
132
164
  ```bash
@@ -146,8 +178,9 @@ bullswarm workflow goal --resume <shortId> --json
146
178
 
147
179
  `--orchestrator <pool>` exists for controlled testing; ordinary use should
148
180
  leave selection on `auto`. `--max-agents` and `--max-workflow-seconds` are
149
- advisory planning targets; hard graph-growth safeguards are adjusted with
150
- `--max-expansion-rounds`, `--max-actions`, and `--max-items-per-expansion`.
181
+ advisory planning targets; `--max-expansion-rounds` is also an advisory
182
+ convergence target. Hard structural safeguards are adjusted with
183
+ `--max-actions` and `--max-items-per-expansion`.
151
184
  Interactive setup also records a worktree-isolation
152
185
  preference (`agent-decides`, `off`, or `required`); Bullswarm communicates that
153
186
  policy to the orchestrator without imposing repository topology itself.
@@ -196,6 +229,7 @@ bullswarm workflow runs --historical --since yesterday --until today
196
229
  bullswarm workflow runs --all --from 2026-08-20 --to 2026-08-27
197
230
  bullswarm workflow runs --limit 20 # cap the result count
198
231
  bullswarm workflow runs show <shortId> # state + report + summary
232
+ bullswarm workflow runs result <shortId> --json # stable result for the calling agent
199
233
  bullswarm runs show <shortId> # top-level shorthand
200
234
  bullswarm workflow runs delete <shortId> --yes # remove the run dir
201
235
 
@@ -208,6 +242,19 @@ Run-history time filters always compare when the workflow was initiated
208
242
  exclusive; `--started-after`/`--from` and `--started-before`/`--to` are aliases.
209
243
  Values accept ISO timestamps, local `YYYY-MM-DD` dates, `today`, `yesterday`,
210
244
  `tomorrow`, `now`, or relative durations such as `30m`, `24h`, `7d`, and `2w`.
245
+
246
+ After a workflow reaches a terminal state, agents should consume
247
+ `workflow runs result <id> --json` instead of probing `state.json`, task files,
248
+ or provider-specific output. The versioned `bullswarm.workflow.result.v1`
249
+ envelope identifies the final delivery artifact and its matching verification
250
+ verdict, and includes progress, step logs, tokens, and an explicitly
251
+ complete-or-partial tool-call total. `runs show` remains the low-level debugging
252
+ surface.
253
+ Goal launch output includes an `instructions` handoff with four named paths:
254
+ `agentInspect` for a machine-readable snapshot, `watch` for low-noise progress,
255
+ `humanTui` for the interactive browser, and `result` for the terminal delivery.
256
+ Use `--watch` when the initiating terminal should immediately follow progress;
257
+ otherwise the command returns after printing this handoff.
211
258
  Time filters preserve the existing scope, so use `--all` or `--historical` when
212
259
  auditing completed runs.
213
260
 
@@ -225,9 +272,20 @@ bullswarm workflow watch <shortId> --jsonl # automation-friendly stream
225
272
  bullswarm workflow watch <shortId> --once # one current/terminal snapshot
226
273
  ```
227
274
 
228
- `workflow tui` is the interactive, Claude-style `/workflows` view. It watches
229
- ongoing runs from disk and supports `j`/`k` or arrow-key selection, Enter for
230
- details, `c` to request a cooperative stop, `r` to refresh, and `q` to quit.
275
+ `workflow tui` is the interactive, Claude-style `/workflows` view. For an
276
+ autonomous goal its left navigation stacks a compact Orchestrator panel above
277
+ the Phases panel; internal planner turns never appear as workers or phases.
278
+ Select Orchestration and press Enter, or press `o`
279
+ anywhere, to inspect the logical orchestration conversation: provider session,
280
+ checkpoint turns and decisions, recent semantic actions, usage, prompt, and
281
+ artifacts. Status marks are consistent throughout the tree: `○` not started,
282
+ an animated Braille spinner for active work, `⧖` waiting, `✓` finished, and
283
+ `✗` failed or interrupted. The non-emoji `⧖` avoids the inconsistent cell
284
+ width of `⌛` across terminal fonts. It watches ongoing runs from disk and supports `j`/`k` or arrow-key selection, Enter for
285
+ details, Esc to go back, `c` to request a confirmed cooperative stop, `r` to
286
+ refresh, and `q` to detach. Its responsive drill-down fits both desktop and
287
+ mobile SSH terminals without squeezing phase, agent, and activity into three
288
+ narrow columns.
231
289
 
232
290
  ```bash
233
291
  bullswarm workflow tui
@@ -272,12 +330,18 @@ declaratively map provider events into a common semantic action record:
272
330
  {"id":"provider-action-id","at":"...","kind":"shell_command|read_file|edit|response","status":"running|completed|failed","summary":"safe scalar preview"}
273
331
  ```
274
332
 
275
- The live workflow pane retains the latest three logical actions per agent.
333
+ The live workflow pane retains and numbers the latest three logical actions per agent.
276
334
  Repeated updates for the same tool call replace its status, and streaming text
277
335
  chunks coalesce into one response action. Heartbeats, token/thought deltas,
278
336
  usage messages, hooks, and unparsed output remain liveness evidence but do not
279
- occupy the action pane. Connector-specific flags, paths, and mappings live in
337
+ occupy the action pane. The viewer tracks the total logical-action count so it
338
+ can display `last 3 of N`, and completed-agent detail includes a scrollable
339
+ Outcome read from the durable output artifact. Connector-specific flags, paths, and mappings live in
280
340
  `connectors/*.json` under `eventStream`; core contains no provider event names.
341
+ Raw structured stdout is treated as an agent transcript, not a provider error
342
+ channel, so reading source text such as an auth-signature matcher cannot falsely
343
+ quarantine Grok or Command Code. Error-shaped semantic results and stderr
344
+ diagnostics still trigger the auth/quota guard.
281
345
 
282
346
  After ten minutes without transport, parsed-event, or semantic-action evidence,
283
347
  an active child is labeled `suspected_stalled`. This is an inspection signal,
@@ -326,13 +390,22 @@ limits:
326
390
  }
327
391
  ```
328
392
 
329
- `maxAgents` and `maxWorkflowSeconds` are advisory inputs to the orchestrator.
330
- Crossing either target is recorded in durable state but never stops a worker,
331
- skips verification, or fails a run. `maxExpansionRounds`, `maxActions`, and
332
- `maxItemsPerExpansion` remain hard graph-growth safeguards. Delegates have no
393
+ `maxAgents`, `maxWorkflowSeconds`, and `maxExpansionRounds` are advisory inputs
394
+ to the orchestrator. Approaching them strongly biases the planner toward
395
+ consolidating existing artifacts and returning the best useful outcome;
396
+ crossing them is recorded but never stops a worker, skips verification, or
397
+ fails a run. `maxActions` and `maxItemsPerExpansion` remain hard structural
398
+ safeguards. Reaching one returns a qualified outcome when useful work exists,
399
+ rather than discarding the run as a blanket failure. Delegates have no
333
400
  implicit wall-clock timeout; set a step's `timeoutSec` (or direct-run
334
401
  `--timeout`) only when an operator explicitly wants a hard termination timer.
335
402
 
403
+ An autonomous `complete` remains strictly verified. A planner `stop` produces
404
+ `completed_with_concerns` when a useful delivery exists, including unresolved
405
+ verification concerns and the stopping reason; it produces `blocked` only
406
+ when no useful delivery exists. `workflow runs result` treats the qualified
407
+ delivery as ready while reporting `verified:false`.
408
+
336
409
  The planner returns versioned JSON. It may propose `needs_more_work` with
337
410
  bounded `run`, inline-`fanout`, or `verify` actions. The deterministic runtime
338
411
  validates IDs, dependencies, operation types, capabilities, and budgets before
package/bin/bullswarm.js CHANGED
@@ -4,9 +4,9 @@
4
4
  import { main } from '../src/cli.js';
5
5
 
6
6
  main(process.argv.slice(2)).then(
7
- (code) => process.exit(code),
7
+ (code) => { process.exitCode = code; },
8
8
  (err) => {
9
9
  console.error(err?.message ?? err);
10
- process.exit(1);
10
+ process.exitCode = 1;
11
11
  },
12
12
  );
@@ -53,6 +53,10 @@
53
53
  "capabilities": ["strong-analysis", "code-reading", "file-editing", "workflow-planning"],
54
54
  "knownModels": ["claude-fable-5", "claude-opus-5", "claude-sonnet-5", "claude-haiku-4-5"],
55
55
  "modelSelection": { "flag": "--model", "mode": "replace-or-append" },
56
+ "conversation": {
57
+ "newArgs": ["--session-id", "{sessionId}"],
58
+ "resumeArgs": ["--resume", "{sessionId}"]
59
+ },
56
60
  "modelProfiles": [
57
61
  { "match": "^claude-fable-5$", "tier": "high", "qualityRank": 6, "pricing": { "inputUsdPerMillion": 10, "cacheReadUsdPerMillion": 1, "outputUsdPerMillion": 50 }, "pricingSource": "https://platform.claude.com/docs/en/about-claude/pricing", "pricingUpdatedAt": "2026-08-27" },
58
62
  { "match": "^claude-opus-(5|4-[5-8])$", "tier": "high", "qualityRank": 5, "pricing": { "inputUsdPerMillion": 5, "cacheReadUsdPerMillion": 0.5, "outputUsdPerMillion": 25 }, "pricingSource": "https://platform.claude.com/docs/en/about-claude/pricing", "pricingUpdatedAt": "2026-08-27" },
@@ -48,6 +48,10 @@
48
48
  "knownModels": ["grok-4.6", "grok-4.5"],
49
49
  "model": "grok-4.6",
50
50
  "modelSelection": { "flag": "--model", "mode": "replace-or-append" },
51
+ "conversation": {
52
+ "newArgs": ["--session-id", "{sessionId}"],
53
+ "resumeArgs": ["--resume", "{sessionId}"]
54
+ },
51
55
  "modelProfiles": [
52
56
  { "match": "^grok-4\\.6$", "tier": "high", "qualityRank": 5, "pricing": { "inputUsdPerMillion": 2, "cacheReadUsdPerMillion": 0.5, "outputUsdPerMillion": 6 }, "pricingSource": "https://docs.x.ai/developers/models/grok-4.6", "pricingUpdatedAt": "2026-08-27" },
53
57
  { "match": "^grok-4\\.5$", "tier": "medium", "qualityRank": 4 }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bullswarm",
3
- "version": "0.10.2",
3
+ "version": "0.10.4",
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
@@ -10,6 +10,10 @@ CLI subscription has the most quota headroom. Every delegate output is
10
10
  judged by **content**, not exit code. A non-zero exit is never a success; a
11
11
  `verified` output is.
12
12
 
13
+ Every command and nested subcommand supports side-effect-free `-h` / `--help`.
14
+ When a flag or argument is uncertain, inspect the exact surface before acting,
15
+ for example `bullswarm workflow draft step add --help`.
16
+
13
17
  This skill is registered globally by:
14
18
 
15
19
  ```bash
@@ -82,16 +86,26 @@ Prefer this for ordinary goal-driven work. The caller supplies intent only:
82
86
  ```bash
83
87
  bullswarm workflow goal \
84
88
  "Fix the failing parser tests with the smallest correct change and verify them" \
85
- --cwd=<abs/path/to/repo> --detach --json
89
+ --cwd=<abs/path/to/repo> --json
86
90
  ```
87
91
 
88
92
  The returned JSON contains `runId`, `shortId`, logs, and exact observation
89
- commands. Bullswarm chooses a capable orchestrator by quota surplus, supplies
93
+ commands. Its `instructions` object separates `agentInspect`, low-noise `watch`,
94
+ interactive `humanTui`, and terminal `result` retrieval. Bullswarm chooses a capable orchestrator by quota surplus, supplies
90
95
  the internal planning contract, validates every proposed graph expansion,
91
96
  routes workers independently, requires verification evidence, and replans until
92
97
  a truthful terminal state. The initiating agent does not create phases, action
93
98
  IDs, dependency JSON, planner prompts, or pool assignments.
94
99
 
100
+ The autonomous orchestrator is one durable control-plane conversation, separate
101
+ from execution phases. Connectors that declare conversation continuation (Grok
102
+ and Claude Code) resume the provider session at later evidence checkpoints;
103
+ individual turns remain visible in JSON audit state for spend and recovery, but
104
+ the human TUI displays one orchestrator thread rather than several agents.
105
+ Planner-created actions also have forward-only named phases. Once a phase has
106
+ executed, a later turn must use a new phase name; Bullswarm rejects attempts to
107
+ append new work beneath a completed phase.
108
+
95
109
  Observe from any other shell or agent:
96
110
 
97
111
  ```bash
@@ -102,6 +116,13 @@ bullswarm workflow events --json <shortId> --after 0
102
116
  bullswarm workflow action show --json <shortId> <actionId>
103
117
  ```
104
118
 
119
+ `workflow goal` starts the durable runner in the background, prints operating
120
+ instructions, and returns by default. Add `--watch` to immediately follow
121
+ low-noise progress until terminal. Open the full-screen Phase → Agent →
122
+ Agent-steps viewer with the printed `humanTui` command; Up/Down, Enter, Esc, and
123
+ `q` navigate or detach while work continues. `--foreground` explicitly restores
124
+ terminal-owned execution.
125
+
105
126
  The detached runner does not depend on the initiating CLI remaining alive.
106
127
  Resume a process-interrupted run from its persisted definition with
107
128
  `bullswarm workflow goal --resume <shortId> --json`. Leave orchestrator
@@ -179,6 +200,7 @@ bullswarm workflow runs --name <workflow> # filter by workflow name
179
200
  bullswarm workflow runs --all --since 7d # initiated in the last 7 days
180
201
  bullswarm workflow runs --historical --since yesterday --until today
181
202
  bullswarm workflow runs show <shortId> # state + report + summary
203
+ bullswarm workflow runs result <shortId> --json # stable delivery for the caller
182
204
  bullswarm workflow runs delete <shortId> --yes
183
205
  ```
184
206
 
@@ -189,6 +211,12 @@ ISO timestamps, local dates, today/yesterday/tomorrow/now, or durations such as
189
211
  `7d`. Add `--all` or `--historical`; time filters do not silently change the
190
212
  normal ongoing-only scope.
191
213
 
214
+ When the run is terminal, use `workflow runs result <id> --json` as the
215
+ handoff contract. Its versioned result envelope points to the selected delivery
216
+ artifact, the dependent verification verdict, progress, and usage. Do not guess
217
+ the output schema by scraping task files or assume the last provider response is
218
+ the deliverable; `runs show` is for low-level debugging.
219
+
192
220
  Before authoring or choosing a workflow, agents can inspect the live execution
193
221
  fabric and the workflow document itself:
194
222
 
@@ -215,6 +243,7 @@ bullswarm strategy show --json
215
243
  bullswarm strategy apply --yes --refresh-hours 24
216
244
  bullswarm strategy auto status
217
245
  bullswarm strategy assign high --pool <pool> --model <model>
246
+ bullswarm strategy exclude-model <model>
218
247
  ```
219
248
 
220
249
  Connector-declared discovery, dated benchmark/pricing evidence, live quota,
@@ -226,6 +255,19 @@ an assignment, but it never bypasses capability, quarantine, exhaustion, or
226
255
  burst-gate safety. Each attempt records the chosen agent/model and labeled
227
256
  token, cost, and normalized-quota estimates in the workflow tree.
228
257
 
258
+ `exclude-model` is a persisted hard policy, not a prompt hint. Excluded models
259
+ are removed from recommendations and ignored in assignments. When a connector
260
+ supports explicit model selection, Bullswarm pins an allowed model in the same
261
+ effort tier; otherwise that pool is excluded because its implicit default
262
+ cannot be guaranteed. Restore eligibility with `strategy include-model`.
263
+
264
+ In the human TUI, the autonomous orchestrator has a compact selectable panel
265
+ stacked above the phase tree. Select it and press Enter, or press
266
+ `o`, to inspect its durable provider session, checkpoint turns and decisions,
267
+ recent semantic actions, usage, prompt, and artifacts. Esc returns to phases.
268
+ The shared state marks are `○` not started, animated Braille spinner active,
269
+ `⧖` waiting, `✓` finished, and `✗` failed or interrupted.
270
+
229
271
  Run state also exposes the versioned plan, action ledger, aggregate usage, every attempt,
230
272
  planner decisions and reasons, budgets, `currentPhase`, `currentStep`, and
231
273
  `activeAgents` in `workflow tui --json <shortId>`. Each attempt includes its
@@ -261,11 +303,13 @@ blocks into the same action shape and retains the latest three. Ten minutes
261
303
  without any transport/event/action evidence becomes `suspected_stalled` with
262
304
  `autoTerminate:false`; it is deliberately not treated as proof of death.
263
305
 
264
- For adaptive work, declare a `decide` step plus `maxExpansionRounds` and the
265
- other graph-growth safeguards (`maxActions` and `maxItemsPerExpansion`).
266
- `maxAgents` and `maxWorkflowSeconds` are advisory planning targets: they expose
267
- remaining headroom and overage to the orchestrator but never stop a worker or
268
- skip required verification. The loop is durable:
306
+ For adaptive work, declare a `decide` step plus advisory
307
+ `maxExpansionRounds` and the hard structural safeguards (`maxActions` and
308
+ `maxItemsPerExpansion`). `maxAgents`, `maxWorkflowSeconds`, and
309
+ `maxExpansionRounds` expose remaining headroom and overage to the orchestrator
310
+ but never stop a worker or skip required verification. Near the targets the
311
+ planner is instructed to converge, consolidate existing artifacts, and avoid
312
+ optional work. The loop is durable:
269
313
 
270
314
  ```text
271
315
  execute -> observe -> decide -> validate proposal -> append -> execute -> observe
@@ -274,6 +318,9 @@ execute -> observe -> decide -> validate proposal -> append -> execute -> observ
274
318
  Allowed planner decisions are `proceed`, `complete`, `needs_more_work`,
275
319
  `retry`, `escalate`, `wait_for_approval`, and `stop`. Expansion decisions must
276
320
  contain bounded actions; malformed or over-budget output executes nothing.
321
+ `complete` still requires successful delivery and verification. `stop` returns
322
+ `completed_with_concerns` with a ready best-effort artifact when useful work
323
+ exists, or `blocked` when it does not; neither hides failed verification.
277
324
  Use `workflows/adaptive-code-review.json` as the starting template.
278
325
  Planner proposals cannot choose `pool`, `addDir`, or `taskFile`. Those fields
279
326
  are runtime-owned. An initiator may constrain them with a decide step's
package/src/cli.js CHANGED
@@ -17,6 +17,8 @@ import { release } from './lib/release.js';
17
17
  import { cmdWorkflow } from './workflow/cli.js';
18
18
  import { cmdStrategy, maybeRefreshStrategy } from './strategy-cli.js';
19
19
  import { cmdIntegrate, installIntegration } from './integrate.js';
20
+ import { helpForArgs } from './help.js';
21
+ import { resolveDispatchModel } from './lib/strategy.js';
20
22
 
21
23
  export function getBullswarmDir() {
22
24
  const h = process.env.BULLSWARM_HOME?.trim();
@@ -117,7 +119,15 @@ async function cmdRun(opts) {
117
119
  // Burst gate (M3): a pool whose 5h window is >=90% used is excluded from
118
120
  // dispatch entirely this run — it paces nothing, it's just out of burst room.
119
121
  const gated = pools.filter((p) => p.burstGate);
120
- const eligiblePools = gated.length ? pools.filter((p) => !p.burstGate) : pools;
122
+ const ungatedPools = gated.length ? pools.filter((p) => !p.burstGate) : pools;
123
+ const assignment = state.strategy?.assignments?.[effortTier] ?? null;
124
+ const eligiblePools = ungatedPools.map((pool) => ({
125
+ ...pool,
126
+ modelPolicy: resolveDispatchModel(pool.connector ?? pool, effortTier, {
127
+ assignment,
128
+ excludedModels: state.strategy?.excludedModels ?? [],
129
+ }),
130
+ })).filter((pool) => pool.modelPolicy.eligible);
121
131
 
122
132
  const route = pickPool(lane, eligiblePools, {
123
133
  callerEligible: opts['no-caller'] !== true,
@@ -145,8 +155,8 @@ async function cmdRun(opts) {
145
155
  // connector spec lives one level down.
146
156
  const poolView = route.pick.connector ?? { name: route.pick.pool };
147
157
  const connector = poolView.connector ?? poolView;
148
- const assignment = state.strategy?.assignments?.[effortTier] ?? null;
149
- const selectedModel = assignment?.pool === connector.name ? assignment.model : null;
158
+ const selectedModel = poolView.modelPolicy?.model
159
+ ?? (assignment?.pool === connector.name ? assignment.model : null);
150
160
  const runtimeConnector = {
151
161
  ...connector,
152
162
  subscription: poolView.subscription ?? connector.subscription ?? null,
@@ -236,6 +246,8 @@ function emit(verdict, opts) {
236
246
 
237
247
  function cmdHealth(opts) {
238
248
  const state = loadState(getBullswarmDir());
249
+ const released = sweepQuarantines(state, Date.now());
250
+ if (released.length) saveState(getBullswarmDir(), state);
239
251
  const runsDir = join(getBullswarmDir(), 'runs');
240
252
  const findings = [];
241
253
 
@@ -394,6 +406,11 @@ async function cmdDoctor(opts) {
394
406
  // --- main ---------------------------------------------------------------------
395
407
 
396
408
  export async function main(argv) {
409
+ const help = helpForArgs(argv);
410
+ if (help) {
411
+ console.log(help);
412
+ return 0;
413
+ }
397
414
  const [verb, ...rest] = argv;
398
415
  const opts = parseArgs(rest);
399
416
  const { ensureSetup } = await import('./setup.js');