bullswarm 0.25.3 → 0.25.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/CHANGELOG.md CHANGED
@@ -1,5 +1,58 @@
1
1
  # bullswarm changelog
2
2
 
3
+ ## 0.25.4 — reasoning levels
4
+
5
+ - A connector now declares how its own CLI expresses a thinking level, and
6
+ every dispatch resolves exactly one level per attempt. The block is
7
+ `reasoning: { flag | args, levels, defaults, skipModels? }` — `flag` for a
8
+ CLI that takes `--effort <level>`, `args` for one whose control is a config
9
+ override (`-c model_reasoning_effort={level}`). The packaged `claude-code`,
10
+ `codex`, `grok`, and `command-code` templates carry the block read from
11
+ their installed CLIs or an official source (Claude Code and Command Code from
12
+ `--help`, Codex from its config reference, Grok from the binary's own
13
+ validation message); Command Code's model-dependent set stays marked
14
+ UNVERIFIED rather than invented. One shared resolver applies the precedence
15
+ chain — the action's own `reasoning` field, the run-wide override, the
16
+ configured `strategy.reasoning` level for that pool and tier, the same for
17
+ the tier globally, then the connector's default for the effort tier — so
18
+ the first layer that sets a level wins, not the strongest. The level is
19
+ appended to the spawned command exactly as `--model` is appended today;
20
+ nothing is appended for a connector with no block, for the literal level
21
+ `default`, or for a model the connector marks under `skipModels`. A level
22
+ the connector does not accept is clamped to the nearest one it does, never
23
+ dropped and never invented. `{ requested, applied, source, clamped }` is
24
+ recorded on every attempt, in the decision log, in `bullswarm run --json`,
25
+ in the V2 result envelope, and in the new `bullswarm run --dry-run` command
26
+ preview — which builds its argv through the same builder that spawns, so
27
+ preview and dispatch cannot drift.
28
+
29
+ - `bullswarm setup` asks one reasoning level per effort tier (suggesting
30
+ high=xhigh, medium=high, low=medium, with `default` always offered to leave
31
+ a worker CLI's own setting untouched) and stores the answers under
32
+ `state.strategy.reasoning`. Agents configure the same thing without a
33
+ terminal: `bullswarm strategy set-reasoning --tier <high|medium|low> --level
34
+ <low|medium|high|xhigh|max|default> [--pool <name>] --yes`, `bullswarm
35
+ strategy reset-reasoning [--tier ..] [--pool ..] --yes`, and a `reasoning`
36
+ section in `strategy configure --file <json> --yes` whose invalidity rejects
37
+ the whole document. `bullswarm strategy inventory --json` reports the
38
+ configured levels and, through the resolver dispatch itself uses, the
39
+ effective level and its source for every pool and tier. Installed home
40
+ connectors receive the packaged `reasoning` block additively on upgrade, and
41
+ a block the user has customized is never overwritten.
42
+
43
+ - A V2 program action accepts an optional `reasoning` field
44
+ (`low|medium|high|xhigh|max|default`) that the calling agent or the
45
+ Workflow Planner can set and that outranks every configured level for that
46
+ one action; `workflow plan contract` documents the field and echoes the
47
+ run-wide levels a launch would apply. `workflow goal` takes
48
+ `--worker-reasoning <level>` for every non-planner dispatch and
49
+ `--planner-reasoning <level>` for a dispatched Workflow Planner, and
50
+ `bullswarm run` takes `--reasoning <level>`; a level off the scale is a
51
+ usage error that launches nothing. The applied level appears next to the
52
+ model in `workflow runs show` (text and `--json`), `workflow runs result
53
+ --json`, the TUI attempt rows and agent pane, so a run that thought more
54
+ cheaply than asked is visible rather than inferred.
55
+
3
56
  ## 0.25.3 — usage-limit recovery and headroom-aware routing
4
57
 
5
58
  - A provider that reports a usage limit is now its own mechanical failure kind,
package/README.md CHANGED
@@ -149,6 +149,9 @@ bullswarm strategy set-model opencode2 kaihk/gpt-5.6-luna \
149
149
  --tiers high,medium,low --yes
150
150
  bullswarm strategy configure --file strategy.json --yes # atomic agent-authored policy
151
151
  bullswarm strategy reset-tier low --yes # restore one tier to automatic
152
+ bullswarm strategy set-reasoning --tier high --level xhigh --yes
153
+ bullswarm strategy set-reasoning --tier high --level high --pool codex --yes
154
+ bullswarm strategy reset-reasoning --tier high --yes # back to connector defaults
152
155
  bullswarm strategy refresh
153
156
  bullswarm strategy show --json
154
157
  bullswarm strategy apply --yes --refresh-hours 24
@@ -302,6 +305,16 @@ adversarial acceptance judgment. Merely being an analysis/evidence action or
302
305
  part of a difficult goal never promotes an action to high. The selected effort
303
306
  then resolves through the High/Medium/Low routes configured by `bullswarm setup`.
304
307
 
308
+ Reasoning depth is a third, independent decision. An action may carry an
309
+ optional `reasoning` field — `low`, `medium`, `high`, `xhigh`, `max`, or
310
+ `default` — that sets how hard the picked model thinks on that one action and
311
+ outranks every configured level for it. `default` passes nothing and lets the
312
+ worker CLI's own setting decide. Omitting the field keeps the configured level.
313
+ It never changes the pool, model, or effort tier, so a `low`-effort mechanical
314
+ step can still be given `xhigh` thinking and a `high`-effort action can be told
315
+ to think cheaply. A connector that does not accept the requested level gets the
316
+ nearest level it supports.
317
+
305
318
  The planner does not author phases or declare success/failure. The kernel
306
319
  derives stable presentation stages for the TUI and computes the final V2
307
320
  result. Saved V2 runs retain their original execution and workspace policy on
@@ -352,6 +365,30 @@ The worker lock covers scout, work actions, and evidence actions. A pool that ca
352
365
  the requested model is ineligible rather than silently substituting another
353
366
  model.
354
367
 
368
+ Reasoning depth can be pinned for a whole run the same way, without touching
369
+ global strategy:
370
+
371
+ ```bash
372
+ bullswarm workflow goal "Implement and verify the change" --cwd . \
373
+ --program plan.json --worker-reasoning high --json
374
+ bullswarm run --lane build --reasoning xhigh --prompt '<task>' --json
375
+ ```
376
+
377
+ `--worker-reasoning` covers scout, work actions, and evidence actions;
378
+ `--planner-reasoning` covers a dispatched Workflow Planner and applies only
379
+ with `--orchestrator`. Exactly one level is resolved per attempt, and the
380
+ first layer that sets one wins — not the strongest: the action's own
381
+ `reasoning` field, then the run-wide flag (`--worker-reasoning`,
382
+ `--planner-reasoning`, `bullswarm run --reasoning`), then the configured
383
+ `strategy.reasoning` level for that pool and tier, then the same for the tier
384
+ globally, then the connector's own default for the effort tier, and otherwise
385
+ nothing is appended. So an action asking for `low` beats a run-wide `max`.
386
+ `default` at any layer stops there and passes nothing, letting the worker
387
+ CLI's own setting decide; a connector with no `reasoning` block, or a model it
388
+ marks as skipped, never receives a flag. The applied level is recorded on
389
+ every attempt with the layer that set it and displayed next to the model, so a
390
+ run that thought more cheaply than requested is visible rather than inferred.
391
+
355
392
  The `opencode2` connector itself does not require a KaiHK provider: its base
356
393
  spawn command carries no hardcoded model, so a plain OpenCode installation
357
394
  dispatches with OpenCode's own configured default. When
@@ -656,8 +693,9 @@ while working. Process exit, a fatal auth/quota signature, explicit operator
656
693
  cancellation, or an opt-in timeout remain the terminal signals.
657
694
 
658
695
  Each attempt records the phase/action, selected pool and model, effort tier,
659
- routing reason, all eligible candidates with quota surplus, timestamps,
660
- artifact paths, outcome, and reported-or-estimated token/cost/quota usage.
696
+ the applied reasoning level with the layer that set it, routing reason, all
697
+ eligible candidates with quota surplus, timestamps, artifact paths, outcome,
698
+ and reported-or-estimated token/cost/quota usage.
661
699
  `workflow tui <id>` renders this breakdown for completed runs as well as live
662
700
  ones; `workflow tui --json <id>` exposes the durable audit document.
663
701
  When a provider event stream reports the actual model, Bullswarm records that
@@ -74,6 +74,19 @@
74
74
  "free": false
75
75
  }],
76
76
  "modelSelection": {"flag": "--model", "mode": "replace-or-append"},
77
+ "reasoning": {
78
+ "$comment": "Optional. How THIS CLI expresses a thinking level. Omit the block entirely when the CLI has no such control: core then appends nothing and reports source 'unsupported'. Declare exactly one of flag/args.",
79
+ "flag": "--effort",
80
+ "args": ["-c", "model_reasoning_effort={level}"],
81
+ "$comment-form": "flag: appended as `<flag> <level>` with replace-or-append semantics, so a level already pinned in spawn.cmd is replaced rather than duplicated. args: appended verbatim with {level} substituted, for CLIs whose control is a config override rather than a flag.",
82
+ "levels": ["low", "medium", "high", "xhigh", "max"],
83
+ "$comment-levels": "the subset of the common scale (low, medium, high, xhigh, max — weakest to strongest, src/lib/reasoning.js) that this CLI accepts, weakest first. A requested level outside the subset is clamped to the strongest supported level not above it, or to the weakest supported level when the request is below all of them, and the clamp is recorded.",
84
+ "defaults": {"high": "xhigh", "medium": "high", "low": "medium"},
85
+ "$comment-defaults": "the level to use for each effort tier when nothing else asked. Last layer of the precedence chain: action override > run override > strategy per-pool > strategy per-tier > THESE > nothing appended. The literal 'default' at any layer means 'append nothing, let the CLI's own configuration decide'.",
86
+ "skipModels": ["^model-id-regex-that-rejects-the-flag"],
87
+ "$comment-skipModels": "Optional connector-owned regexes. A selected model matching one gets no level appended (source 'skipped-model'), for CLIs whose flag is only valid on some models."
88
+ },
89
+ "$comment-reasoning": "Optional prose companion. Say which command's output the block was read from, and mark anything the CLI does not actually print as UNVERIFIED — never invent an accepted value.",
77
90
  "subscription": {"plan": null, "monthlyPriceUsd": null, "includedValueUsd": null, "quotaWindow": "weekly"},
78
91
  "flags": {
79
92
  "stealth": false,
@@ -60,6 +60,13 @@
60
60
  "capabilities": ["strong-analysis", "code-reading", "file-editing", "workflow-planning"],
61
61
  "knownModels": ["claude-fable-5", "claude-opus-5", "claude-sonnet-5", "claude-haiku-4-5"],
62
62
  "modelSelection": { "flag": "--model", "mode": "replace-or-append" },
63
+ "$comment-reasoning": "verified from `claude --help` (Claude Code 2.1.263): `--effort <level> Effort level for the current session (low, medium, high, xhigh, max)`. skipModels: `--help` does not state per-model support, so Haiku is excluded conservatively — re-verify before removing the exclusion. With no `reasoning` override anywhere, workers inherit whatever effortLevel the home settings.json sets.",
64
+ "reasoning": {
65
+ "flag": "--effort",
66
+ "levels": ["low", "medium", "high", "xhigh", "max"],
67
+ "defaults": { "high": "xhigh", "medium": "high", "low": "medium" },
68
+ "skipModels": ["^claude-haiku-"]
69
+ },
63
70
  "conversation": {
64
71
  "newArgs": ["--session-id", "{sessionId}"],
65
72
  "resumeArgs": ["--resume", "{sessionId}"]
@@ -31,14 +31,61 @@
31
31
  },
32
32
  "eventStream": {
33
33
  "format": "jsonl",
34
- "args": ["--json"],
34
+ "args": [
35
+ "--json"
36
+ ],
35
37
  "silenceThresholdSec": 600,
36
38
  "rules": [
37
- { "rootMatch": { "path": "type", "equals": "item.started" }, "idPaths": ["item.id"], "kindPaths": ["item.type"], "kindMap": { "agent_message": "response" }, "summaryPaths": ["item.command", "item.text"], "status": "running" },
38
- { "rootMatch": { "path": "type", "equals": "item.completed" }, "idPaths": ["item.id"], "kindPaths": ["item.type"], "kindMap": { "agent_message": "response" }, "summaryPaths": ["item.command", "item.text"], "status": "completed" }
39
+ {
40
+ "rootMatch": {
41
+ "path": "type",
42
+ "equals": "item.started"
43
+ },
44
+ "idPaths": [
45
+ "item.id"
46
+ ],
47
+ "kindPaths": [
48
+ "item.type"
49
+ ],
50
+ "kindMap": {
51
+ "agent_message": "response"
52
+ },
53
+ "summaryPaths": [
54
+ "item.command",
55
+ "item.text"
56
+ ],
57
+ "status": "running"
58
+ },
59
+ {
60
+ "rootMatch": {
61
+ "path": "type",
62
+ "equals": "item.completed"
63
+ },
64
+ "idPaths": [
65
+ "item.id"
66
+ ],
67
+ "kindPaths": [
68
+ "item.type"
69
+ ],
70
+ "kindMap": {
71
+ "agent_message": "response"
72
+ },
73
+ "summaryPaths": [
74
+ "item.command",
75
+ "item.text"
76
+ ],
77
+ "status": "completed"
78
+ }
39
79
  ],
40
80
  "output": [
41
- { "match": { "path": "type", "equals": "item.completed" }, "path": "item.text", "mode": "last" }
81
+ {
82
+ "match": {
83
+ "path": "type",
84
+ "equals": "item.completed"
85
+ },
86
+ "path": "item.text",
87
+ "mode": "last"
88
+ }
42
89
  ]
43
90
  },
44
91
  "meter": {
@@ -51,18 +98,109 @@
51
98
  "build",
52
99
  "chore"
53
100
  ],
54
- "capabilities": ["strong-analysis", "code-reading", "file-editing", "workflow-planning"],
55
- "knownModels": ["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-5.5", "gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex"],
56
- "modelSelection": { "flag": "--model", "mode": "replace-or-append" },
101
+ "capabilities": [
102
+ "strong-analysis",
103
+ "code-reading",
104
+ "file-editing",
105
+ "workflow-planning"
106
+ ],
107
+ "knownModels": [
108
+ "gpt-5.6-sol",
109
+ "gpt-5.6-terra",
110
+ "gpt-5.6-luna",
111
+ "gpt-5.5",
112
+ "gpt-5.4",
113
+ "gpt-5.4-mini",
114
+ "gpt-5.3-codex"
115
+ ],
116
+ "modelSelection": {
117
+ "flag": "--model",
118
+ "mode": "replace-or-append"
119
+ },
120
+ "$comment-reasoning": "Codex has no reasoning flag; the control is the config key `model_reasoning_effort`, overridden per invocation with the escape hatch verified from `codex exec --help` (codex-cli 0.153.4): `-c, --config <key=value> Override a configuration value that would otherwise be loaded from ~/.codex/config.toml`. Accepted values verified from the official Codex config reference (https://learn.chatgpt.com/docs/config-file/config-reference, read 2026-09-09): `minimal | low | medium | high | xhigh` — \"Adjust reasoning effort for supported models (Responses API only; xhigh is model-dependent)\". `minimal` sits below bullswarm's common scale, so a request below `low` clamps up to `low`. Tier defaults stay at high/medium/low because `xhigh` is model-dependent; an explicit `xhigh` request passes through. Without this block Codex workers think at whatever config.toml sets (this machine: low).",
121
+ "reasoning": {
122
+ "args": [
123
+ "-c",
124
+ "model_reasoning_effort={level}"
125
+ ],
126
+ "levels": [
127
+ "low",
128
+ "medium",
129
+ "high",
130
+ "xhigh"
131
+ ],
132
+ "defaults": {
133
+ "high": "high",
134
+ "medium": "medium",
135
+ "low": "low"
136
+ }
137
+ },
57
138
  "modelProfiles": [
58
- { "match": "^gpt-5\\.6-sol$", "tier": "high", "qualityRank": 6, "pricing": { "inputUsdPerMillion": 4, "cacheReadUsdPerMillion": 0.4, "outputUsdPerMillion": 20 }, "pricingSource": "https://help.openai.com/en/articles/20001415-chatgpt-rate-card-enterprise-token-based-pricing", "pricingUpdatedAt": "2026-08-27" },
59
- { "match": "^gpt-5\\.(5|4)$", "tier": "high", "qualityRank": 5 },
60
- { "match": "^gpt-5\\.6-terra$", "tier": "medium", "qualityRank": 4, "pricing": { "inputUsdPerMillion": 2, "cacheReadUsdPerMillion": 0.2, "outputUsdPerMillion": 12 }, "pricingSource": "https://developers.openai.com/api/docs/models/gpt-5.6-terra", "pricingUpdatedAt": "2026-08-27" },
61
- { "match": "^gpt-5\\.3-codex$", "tier": "medium", "qualityRank": 4, "pricing": { "inputUsdPerMillion": 1.75, "cacheReadUsdPerMillion": 0.175, "outputUsdPerMillion": 14 }, "pricingSource": "https://help.openai.com/en/articles/20001415-chatgpt-rate-card-enterprise-token-based-pricing", "pricingUpdatedAt": "2026-08-27" },
62
- { "match": "^gpt-5\\.6-luna$", "tier": "low", "qualityRank": 3, "pricing": { "inputUsdPerMillion": 0.2, "cacheReadUsdPerMillion": 0.02, "outputUsdPerMillion": 1.2 }, "pricingSource": "https://developers.openai.com/api/docs/models", "pricingUpdatedAt": "2026-08-27" },
63
- { "match": "mini", "tier": "low", "qualityRank": 2 }
139
+ {
140
+ "match": "^gpt-5\\.6-sol$",
141
+ "tier": "high",
142
+ "qualityRank": 6,
143
+ "pricing": {
144
+ "inputUsdPerMillion": 4,
145
+ "cacheReadUsdPerMillion": 0.4,
146
+ "outputUsdPerMillion": 20
147
+ },
148
+ "pricingSource": "https://help.openai.com/en/articles/20001415-chatgpt-rate-card-enterprise-token-based-pricing",
149
+ "pricingUpdatedAt": "2026-08-27"
150
+ },
151
+ {
152
+ "match": "^gpt-5\\.(5|4)$",
153
+ "tier": "high",
154
+ "qualityRank": 5
155
+ },
156
+ {
157
+ "match": "^gpt-5\\.6-terra$",
158
+ "tier": "medium",
159
+ "qualityRank": 4,
160
+ "pricing": {
161
+ "inputUsdPerMillion": 2,
162
+ "cacheReadUsdPerMillion": 0.2,
163
+ "outputUsdPerMillion": 12
164
+ },
165
+ "pricingSource": "https://developers.openai.com/api/docs/models/gpt-5.6-terra",
166
+ "pricingUpdatedAt": "2026-08-27"
167
+ },
168
+ {
169
+ "match": "^gpt-5\\.3-codex$",
170
+ "tier": "medium",
171
+ "qualityRank": 4,
172
+ "pricing": {
173
+ "inputUsdPerMillion": 1.75,
174
+ "cacheReadUsdPerMillion": 0.175,
175
+ "outputUsdPerMillion": 14
176
+ },
177
+ "pricingSource": "https://help.openai.com/en/articles/20001415-chatgpt-rate-card-enterprise-token-based-pricing",
178
+ "pricingUpdatedAt": "2026-08-27"
179
+ },
180
+ {
181
+ "match": "^gpt-5\\.6-luna$",
182
+ "tier": "low",
183
+ "qualityRank": 3,
184
+ "pricing": {
185
+ "inputUsdPerMillion": 0.2,
186
+ "cacheReadUsdPerMillion": 0.02,
187
+ "outputUsdPerMillion": 1.2
188
+ },
189
+ "pricingSource": "https://developers.openai.com/api/docs/models",
190
+ "pricingUpdatedAt": "2026-08-27"
191
+ },
192
+ {
193
+ "match": "mini",
194
+ "tier": "low",
195
+ "qualityRank": 2
196
+ }
64
197
  ],
65
- "subscription": { "plan": null, "monthlyPriceUsd": null, "includedValueUsd": null, "quotaWindow": "weekly" },
198
+ "subscription": {
199
+ "plan": null,
200
+ "monthlyPriceUsd": null,
201
+ "includedValueUsd": null,
202
+ "quotaWindow": "weekly"
203
+ },
66
204
  "flags": {
67
205
  "stealth": false
68
206
  },
@@ -55,6 +55,12 @@
55
55
  "capabilities": ["code-reading", "file-editing", "strong-analysis", "workflow-planning"],
56
56
  "modelDiscovery": { "cmd": ["command-code", "--list-models"], "parse": "columns", "ignorePattern": "^(Available|Open Source$|Anthropic$|OpenAI$|Google$|Sakana$|Meta$|xAI$|Pass|cmd|Docs)", "timeoutMs": 20000, "maxModels": 150 },
57
57
  "modelSelection": { "flag": "--model", "mode": "replace-or-append" },
58
+ "$comment-reasoning": "verified from `command-code --help` (1.44.0): `--effort <level> Set reasoning effort for the session (e.g. low, medium, high) — depends on the model`. UNVERIFIED: the CLI says \"e.g.\" and \"depends on the model\", so the accepted set is neither closed nor uniform across this pool's many providers; low/medium/high is declared conservatively and a stronger request clamps down to high.",
59
+ "reasoning": {
60
+ "flag": "--effort",
61
+ "levels": ["low", "medium", "high"],
62
+ "defaults": { "high": "high", "medium": "medium", "low": "low" }
63
+ },
58
64
  "modelProfiles": [
59
65
  { "match": "^meta/muse-spark-1\\.3-contributor$", "tier": "high", "qualityRank": 5, "pricing": { "inputUsdPerMillion": 0.1, "cacheReadUsdPerMillion": 0.002, "outputUsdPerMillion": 0.2 }, "pricingSource": "https://commandcode.ai/docs/resources/pricing-limits", "pricingUpdatedAt": "2026-09-03" },
60
66
  { "match": "^meta/muse-spark-", "tier": "high", "qualityRank": 5, "pricing": { "inputUsdPerMillion": 1.25, "cacheReadUsdPerMillion": 0.15, "outputUsdPerMillion": 4.25 }, "pricingSource": "https://commandcode.ai/docs/resources/pricing-limits", "pricingUpdatedAt": "2026-09-03" },
@@ -24,15 +24,71 @@
24
24
  },
25
25
  "eventStream": {
26
26
  "format": "jsonl",
27
- "args": ["--output-format", "streaming-json"],
27
+ "args": [
28
+ "--output-format",
29
+ "streaming-json"
30
+ ],
28
31
  "silenceThresholdSec": 600,
29
32
  "rules": [
30
- { "rootMatch": { "path": "type", "equals": "tool_call" }, "idPaths": ["toolCallId"], "kindPaths": ["toolName", "title"], "summaryPaths": ["rawInput.command", "rawInput.file_path", "rawInput.path", "title"], "statusPath": "status" },
31
- { "rootMatch": { "path": "type", "equals": "tool_call_update" }, "idPaths": ["toolCallId"], "kindPaths": ["toolName"], "summaryPaths": ["rawOutput.command"], "statusPath": "status" },
32
- { "rootMatch": { "path": "type", "equals": "text" }, "kind": "response", "summaryPaths": ["data"], "status": "streaming", "aggregate": "consecutive", "summaryMode": "concat" }
33
+ {
34
+ "rootMatch": {
35
+ "path": "type",
36
+ "equals": "tool_call"
37
+ },
38
+ "idPaths": [
39
+ "toolCallId"
40
+ ],
41
+ "kindPaths": [
42
+ "toolName",
43
+ "title"
44
+ ],
45
+ "summaryPaths": [
46
+ "rawInput.command",
47
+ "rawInput.file_path",
48
+ "rawInput.path",
49
+ "title"
50
+ ],
51
+ "statusPath": "status"
52
+ },
53
+ {
54
+ "rootMatch": {
55
+ "path": "type",
56
+ "equals": "tool_call_update"
57
+ },
58
+ "idPaths": [
59
+ "toolCallId"
60
+ ],
61
+ "kindPaths": [
62
+ "toolName"
63
+ ],
64
+ "summaryPaths": [
65
+ "rawOutput.command"
66
+ ],
67
+ "statusPath": "status"
68
+ },
69
+ {
70
+ "rootMatch": {
71
+ "path": "type",
72
+ "equals": "text"
73
+ },
74
+ "kind": "response",
75
+ "summaryPaths": [
76
+ "data"
77
+ ],
78
+ "status": "streaming",
79
+ "aggregate": "consecutive",
80
+ "summaryMode": "concat"
81
+ }
33
82
  ],
34
83
  "output": [
35
- { "match": { "path": "type", "equals": "text" }, "path": "data", "mode": "concat" }
84
+ {
85
+ "match": {
86
+ "path": "type",
87
+ "equals": "text"
88
+ },
89
+ "path": "data",
90
+ "mode": "concat"
91
+ }
36
92
  ]
37
93
  },
38
94
  "meter": {
@@ -45,20 +101,81 @@
45
101
  "build",
46
102
  "chore"
47
103
  ],
48
- "capabilities": ["strong-analysis", "code-reading", "file-editing", "workflow-planning"],
49
- "modelDiscovery": { "cmd": ["grok", "models"], "parse": "bullets", "timeoutMs": 20000, "maxModels": 50 },
50
- "knownModels": ["grok-4.6", "grok-4.5"],
104
+ "capabilities": [
105
+ "strong-analysis",
106
+ "code-reading",
107
+ "file-editing",
108
+ "workflow-planning"
109
+ ],
110
+ "modelDiscovery": {
111
+ "cmd": [
112
+ "grok",
113
+ "models"
114
+ ],
115
+ "parse": "bullets",
116
+ "timeoutMs": 20000,
117
+ "maxModels": 50
118
+ },
119
+ "knownModels": [
120
+ "grok-4.6",
121
+ "grok-4.5"
122
+ ],
51
123
  "model": "grok-4.6",
52
- "modelSelection": { "flag": "--model", "mode": "replace-or-append" },
124
+ "modelSelection": {
125
+ "flag": "--model",
126
+ "mode": "replace-or-append"
127
+ },
128
+ "$comment-reasoning": "flag verified from `grok --help` (grok 1.0.13): `--reasoning-effort <EFFORT> Reasoning effort for reasoning models [aliases: --effort]`. Accepted values verified from the grok 1.0.13 binary's own validation message (`strings` on the executable): `invalid reasoning effort: (expected one of: none, minimal, low, medium, high, xhigh, max)`. `none` and `minimal` sit below bullswarm's common scale, so a request below `low` clamps up to `low`. Tier defaults mirror claude-code (high=xhigh, medium=high, low=medium).",
129
+ "reasoning": {
130
+ "flag": "--reasoning-effort",
131
+ "levels": [
132
+ "low",
133
+ "medium",
134
+ "high",
135
+ "xhigh",
136
+ "max"
137
+ ],
138
+ "defaults": {
139
+ "high": "xhigh",
140
+ "medium": "high",
141
+ "low": "medium"
142
+ }
143
+ },
53
144
  "conversation": {
54
- "newArgs": ["--session-id", "{sessionId}"],
55
- "resumeArgs": ["--resume", "{sessionId}"]
145
+ "newArgs": [
146
+ "--session-id",
147
+ "{sessionId}"
148
+ ],
149
+ "resumeArgs": [
150
+ "--resume",
151
+ "{sessionId}"
152
+ ]
56
153
  },
57
154
  "modelProfiles": [
58
- { "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" },
59
- { "match": "^grok-4\\.5$", "tier": "medium", "qualityRank": 4 }
155
+ {
156
+ "match": "^grok-4\\.6$",
157
+ "tier": "high",
158
+ "qualityRank": 5,
159
+ "pricing": {
160
+ "inputUsdPerMillion": 2,
161
+ "cacheReadUsdPerMillion": 0.5,
162
+ "outputUsdPerMillion": 6
163
+ },
164
+ "pricingSource": "https://docs.x.ai/developers/models/grok-4.6",
165
+ "pricingUpdatedAt": "2026-08-27"
166
+ },
167
+ {
168
+ "match": "^grok-4\\.5$",
169
+ "tier": "medium",
170
+ "qualityRank": 4
171
+ }
60
172
  ],
61
- "subscription": { "plan": null, "monthlyPriceUsd": null, "includedValueUsd": null, "quotaWindow": "weekly" },
173
+ "subscription": {
174
+ "plan": null,
175
+ "monthlyPriceUsd": null,
176
+ "includedValueUsd": null,
177
+ "quotaWindow": "weekly"
178
+ },
62
179
  "flags": {
63
180
  "stealth": false
64
181
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bullswarm",
3
- "version": "0.25.3",
3
+ "version": "0.25.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
@@ -95,6 +95,20 @@ Author the graph around these rules:
95
95
  `affects`/`ownedFiles`, and `evidenceFor` requirement IDs. Depend on every
96
96
  writer affecting those requirements. Describe the checks; the kernel adds
97
97
  the evidence JSON instructions. Evidence is optional for graph completion.
98
+ - **Optional reasoning depth:** `effort` picks the model tier; the optional
99
+ `reasoning` field picks how hard that model thinks. Values are
100
+ `low|medium|high|xhigh|max`, or `default` to pass nothing and let the worker
101
+ CLI's own setting decide. It applies to that one action and outranks every
102
+ configured level for it — so a `low`-effort integrator can still get `xhigh`
103
+ thinking. Omit it and the configured level applies; it never changes the
104
+ pool, model, or effort tier, and a connector that does not accept the exact
105
+ level gets the nearest level it supports. Set it only when an action needs
106
+ deeper thinking than its tier implies (a tricky shared-file integrator,
107
+ ambiguous acceptance judgment) or cheaper thinking for mechanical work.
108
+ For the whole run instead of one action, pass
109
+ `--worker-reasoning <level>` (and `--planner-reasoning <level>` with
110
+ `--orchestrator`) to `workflow goal`; the contract's `reasoning` block
111
+ echoes what a launch will apply.
98
112
 
99
113
  Validate, then launch:
100
114
 
@@ -167,6 +167,37 @@ and apply validated changes with `strategy set-provider`, `strategy set-model`,
167
167
  or one atomic `strategy configure --file <json> --yes`. Never weaken those
168
168
  controls in a prompt.
169
169
 
170
+ Reasoning depth is a separate axis from routing: the lane and effort tier
171
+ choose the pool and model, and the reasoning level chooses how hard that model
172
+ thinks. The first layer that sets a level wins — not the strongest — in this
173
+ order: an action's own `reasoning` field, then the run-wide
174
+ `--worker-reasoning` / `--planner-reasoning` (`bullswarm run --reasoning`),
175
+ then the configured `strategy.reasoning` level for that pool and tier, then
176
+ the same for the tier globally, then the connector default. An action asking
177
+ for `low` therefore beats a run-wide `max`. `default` at any layer means "pass
178
+ nothing and let the worker CLI's own setting decide", and a connector that does
179
+ not accept the requested level gets the nearest level it supports. The applied
180
+ level is recorded per attempt and shown next to the model in `workflow runs
181
+ show` (text and `--json`), `workflow runs result --json`, the TUI attempt rows,
182
+ and the agent pane, so an unexpectedly cheap or expensive turn is visible
183
+ rather than inferred.
184
+
185
+ Configure the standing levels the same way as the rest of strategy — no
186
+ interactive UI required:
187
+
188
+ ```bash
189
+ bullswarm strategy set-reasoning --tier high --level xhigh --yes
190
+ bullswarm strategy set-reasoning --tier high --level high --pool codex --yes
191
+ bullswarm strategy reset-reasoning --tier high --yes
192
+ bullswarm strategy inventory --json # reasoning.tiers, .pools, .effective
193
+ ```
194
+
195
+ `inventory --json` reports `reasoning.effective['<pool>'][tier]` as
196
+ `{ level, source }` through the same resolver dispatch uses, so what it shows
197
+ is what a run will send. `strategy configure --file <json> --yes` takes the
198
+ same values as a `reasoning` section; an invalid section rejects the whole
199
+ document and writes nothing.
200
+
170
201
  ## Recovery and stopping rules
171
202
 
172
203
  - Auth signatures quarantine the affected pool for a 10-minute re-probe