bullswarm 0.25.3 → 0.25.5

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,134 @@
1
1
  # bullswarm changelog
2
2
 
3
+ ## 0.25.5 — forecast-aware routing
4
+
5
+ - Bullswarm now knows what it is already running. Every dispatch registers the
6
+ work it starts in a small ledger on disk (`~/.bullswarm/assignments/`, one
7
+ atomically written file per assignment), and every process reads it: a
8
+ `bullswarm run` in one terminal, a V1 runtime and four concurrent V2 kernel
9
+ actions all see each other's agents instead of each assuming the pool is
10
+ idle. Records whose process is gone, or that are older than 12 hours, are
11
+ pruned on read, so a crash cannot leave phantom load behind. `bullswarm
12
+ assignments` lists what is in flight right now — pool, run, action, how long
13
+ it has been going and how much longer it is expected to take — and
14
+ `bullswarm pools` carries the same count as `inflight=<n>`.
15
+
16
+ - A spend model turns those records into percentage points. It measures how
17
+ fast a pool actually burns its 5-hour and weekly windows by pairing meter
18
+ readings with the worker-minutes dispatched between them, and how long an
19
+ assignment on a given lane and effort tier usually runs by taking the median
20
+ of real attempts from the decision log. Every number carries its basis —
21
+ `history` (measured), `bootstrap` (one window's usage so far), or the
22
+ documented `default` table — and the sample count behind it. A pool nobody
23
+ has measured reports `null`, never a plausible-looking guess.
24
+
25
+ - Routing now decides on the forecast instead of on the last reading. Each
26
+ pool's projection (reading + what its in-flight agents will still spend) gets
27
+ the expected consumption of the assignment being routed added on top, and the
28
+ existing thresholds apply to that number: a pool projected at or above 75% of
29
+ its 5-hour window drops to the near-limit tier while its reading is still
30
+ below the line, and one projected at or above 90% is dropped from selection
31
+ as forecast-gated. Nothing is gated on an unknown forecast, and if every
32
+ capable pool is gated, the least loaded of them is still picked — with the
33
+ reason saying exactly that — rather than the action being stranded.
34
+
35
+ - Parallel work now spreads instead of stacking. Within a tier, a pool's pace
36
+ surplus is reduced by the weekly quota its in-flight agents and this
37
+ assignment are expected to spend, and by at least a flat 3 surplus points
38
+ per in-flight agent (`DEFAULT_INFLIGHT_PENALTY_PCT`, `config.inflightPenaltyPct`
39
+ in state.json, `0` disables it). The floor matters: at measured weekly rates
40
+ a six-minute agent projects to under one point, which would leave a burst on
41
+ one pool. The charge is labeled `penalty` when the floor set it and by its
42
+ measured basis otherwise. Load also beats incumbency: an incumbent carrying
43
+ more in-flight agents than a challenger keeps neither its margin nor its cost
44
+ guard. Four actions launched within the same second land on
45
+ four different providers rather than all on the single most-behind one, and
46
+ the V2 kernel re-reads the ledger before every pick rather than only on its
47
+ throttled meter refresh, so actions launched seconds apart still see each
48
+ other.
49
+
50
+ - Everything that observes routing shows the new numbers. `bullswarm
51
+ assignments [--json]` is a new command listing the live ledger; `bullswarm
52
+ pools` gained an `inflight=<n>` column and prints its 5-hour cell as
53
+ `5h=<reading>%-><projected>%` when in-flight work is expected to move it,
54
+ with `spend`, `projectedFiveHourPct` and `projectedWeeklyPct` in `--json`;
55
+ `bullswarm run --dry-run` prints the forecast the pick was made on and, being
56
+ a preview, still registers nothing and writes no decision log; and the
57
+ strategy control center shows each provider's in-flight count next to its
58
+ usage. Live meter readings are now retained as a capped per-pool series at
59
+ `~/.bullswarm/meters/history/<pool>.jsonl`, because the snapshot cache keeps
60
+ only the newest reading and a rate needs two.
61
+
62
+ - A rate is only reported once the dispatch behind it is real: at least five
63
+ worker-minutes must be attributable to a window before its utilization
64
+ counts as percentage-points-per-minute. Without that floor a pool at 26% of
65
+ its 5-hour window with one six-second-old agent measures as 260% per minute
66
+ and forecasts every provider past the burst line, which is the failure this
67
+ model exists to prevent rather than cause.
68
+
69
+ - All of it is visible after the fact. The routing reason names the in-flight
70
+ counts and projections that moved the pick (`5h used 30% -> 41% projected, 2
71
+ in flight`, `skipped near 5h limit (projected): wati 76%`, `forecast-gated
72
+ at/above 90%: …`, `preferred over busier: …`), every candidate row carries
73
+ `pace`, `effectiveSurplus`, `inflight`, `projectedFiveHourPct`,
74
+ `forecastFiveHourPct`, `projectedWeeklyPct`, `ratePerMinute`,
75
+ `estimateSource` and `forecastGated`, and the decision log records the
76
+ forecast the pick was made on. Pools that carry no ledger or spend fields
77
+ route exactly as they did before.
78
+
79
+ ## 0.25.4 — reasoning levels
80
+
81
+ - A connector now declares how its own CLI expresses a thinking level, and
82
+ every dispatch resolves exactly one level per attempt. The block is
83
+ `reasoning: { flag | args, levels, defaults, skipModels? }` — `flag` for a
84
+ CLI that takes `--effort <level>`, `args` for one whose control is a config
85
+ override (`-c model_reasoning_effort={level}`). The packaged `claude-code`,
86
+ `codex`, `grok`, and `command-code` templates carry the block read from
87
+ their installed CLIs or an official source (Claude Code and Command Code from
88
+ `--help`, Codex from its config reference, Grok from the binary's own
89
+ validation message); Command Code's model-dependent set stays marked
90
+ UNVERIFIED rather than invented. One shared resolver applies the precedence
91
+ chain — the action's own `reasoning` field, the run-wide override, the
92
+ configured `strategy.reasoning` level for that pool and tier, the same for
93
+ the tier globally, then the connector's default for the effort tier — so
94
+ the first layer that sets a level wins, not the strongest. The level is
95
+ appended to the spawned command exactly as `--model` is appended today;
96
+ nothing is appended for a connector with no block, for the literal level
97
+ `default`, or for a model the connector marks under `skipModels`. A level
98
+ the connector does not accept is clamped to the nearest one it does, never
99
+ dropped and never invented. `{ requested, applied, source, clamped }` is
100
+ recorded on every attempt, in the decision log, in `bullswarm run --json`,
101
+ in the V2 result envelope, and in the new `bullswarm run --dry-run` command
102
+ preview — which builds its argv through the same builder that spawns, so
103
+ preview and dispatch cannot drift.
104
+
105
+ - `bullswarm setup` asks one reasoning level per effort tier (suggesting
106
+ high=xhigh, medium=high, low=medium, with `default` always offered to leave
107
+ a worker CLI's own setting untouched) and stores the answers under
108
+ `state.strategy.reasoning`. Agents configure the same thing without a
109
+ terminal: `bullswarm strategy set-reasoning --tier <high|medium|low> --level
110
+ <low|medium|high|xhigh|max|default> [--pool <name>] --yes`, `bullswarm
111
+ strategy reset-reasoning [--tier ..] [--pool ..] --yes`, and a `reasoning`
112
+ section in `strategy configure --file <json> --yes` whose invalidity rejects
113
+ the whole document. `bullswarm strategy inventory --json` reports the
114
+ configured levels and, through the resolver dispatch itself uses, the
115
+ effective level and its source for every pool and tier. Installed home
116
+ connectors receive the packaged `reasoning` block additively on upgrade, and
117
+ a block the user has customized is never overwritten.
118
+
119
+ - A V2 program action accepts an optional `reasoning` field
120
+ (`low|medium|high|xhigh|max|default`) that the calling agent or the
121
+ Workflow Planner can set and that outranks every configured level for that
122
+ one action; `workflow plan contract` documents the field and echoes the
123
+ run-wide levels a launch would apply. `workflow goal` takes
124
+ `--worker-reasoning <level>` for every non-planner dispatch and
125
+ `--planner-reasoning <level>` for a dispatched Workflow Planner, and
126
+ `bullswarm run` takes `--reasoning <level>`; a level off the scale is a
127
+ usage error that launches nothing. The applied level appears next to the
128
+ model in `workflow runs show` (text and `--json`), `workflow runs result
129
+ --json`, the TUI attempt rows and agent pane, so a run that thought more
130
+ cheaply than asked is visible rather than inferred.
131
+
3
132
  ## 0.25.3 — usage-limit recovery and headroom-aware routing
4
133
 
5
134
  - 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
@@ -224,6 +227,49 @@ name the utilization that decided the pick, and meters and quarantines are
224
227
  re-read before each dispatch — and again, live, right after a usage limit —
225
228
  so a long run never routes off the snapshot it launched with.
226
229
 
230
+ Those thresholds are applied to the FORECAST, not to the last reading. A meter
231
+ reading is already old when it arrives: agents dispatched seconds ago have
232
+ spent quota the provider has not reported yet, and the assignment being routed
233
+ will spend more. So each pool's projection — its reading plus the quota its
234
+ in-flight agents are still expected to burn — gets this candidate's own
235
+ expected consumption added, and the tiers apply to that number: a pool
236
+ projected at or above 75% drops to the near-limit tier even while its reading
237
+ is lower, and one projected at or above `BURST_BLOCK_PCT` (90) is left out of
238
+ selection entirely as forecast-gated. If every capable pool is forecast-gated,
239
+ routing still names the least loaded of them rather than stranding the action,
240
+ and says so in the reason. A pool with no measured rate forecasts nothing and
241
+ is never gated or deprioritized for a number nobody produced.
242
+
243
+ Within a tier, pools already carrying work yield to quieter pools of similar
244
+ pace: each pool's surplus is reduced by the weekly quota its in-flight agents
245
+ and this assignment are expected to spend, and by at least a flat 3 surplus
246
+ points per in-flight agent. That floor is what spreads work at real rates,
247
+ where a six-minute agent projects to well under one point; the charge is
248
+ labeled `penalty` when the floor set it and carries its measured basis
249
+ (`history`, `bootstrap`) when the projection was larger. Load also beats
250
+ incumbency: an incumbent carrying more in-flight agents than a challenger keeps
251
+ neither its 10-point margin nor its cost protection, so the quieter pool wins
252
+ as soon as its effective surplus is higher. A burst of parallel actions
253
+ therefore spreads across providers instead of stacking on the single
254
+ most-behind one.
255
+ `bullswarm pools` shows each pool's `inflight=<n>` count and its 5-hour column
256
+ as `5h=<reading>%-><projected>%` whenever in-flight work is expected to move
257
+ it, `bullswarm assignments` lists what those agents are, `bullswarm run
258
+ --dry-run` prints the forecast the pick was made on without registering
259
+ anything, and every candidate row carries `pace`, `effectiveSurplus`,
260
+ `inflight`, `projectedFiveHourPct`, `forecastFiveHourPct`, `ratePerMinute`,
261
+ `estimateSource` and `forecastGated`, so a surprising pick can be read back
262
+ number by number.
263
+
264
+ The rates come from real records: every live meter reading is retained as a
265
+ capped per-pool series (`~/.bullswarm/meters/history/<pool>.jsonl`) and paired
266
+ with the worker-minutes dispatched between readings. Until at least five
267
+ worker-minutes of dispatch are attributable to a window there is no rate at
268
+ all — `null`, not a ratio of percentage points to seconds — so a fresh machine
269
+ routes on pace and the flat penalty until it has measured something. The
270
+ penalty itself is `config.inflightPenaltyPct` in `~/.bullswarm/state.json`
271
+ (default 3; `0` turns the tie-breaker off).
272
+
227
273
  Model exclusions are hard routing policy. An excluded model is removed from
228
274
  recommendations and assignments, and Bullswarm pins a same-tier allowed model
229
275
  through the connector-owned model flag whenever the provider default could be
@@ -302,6 +348,16 @@ adversarial acceptance judgment. Merely being an analysis/evidence action or
302
348
  part of a difficult goal never promotes an action to high. The selected effort
303
349
  then resolves through the High/Medium/Low routes configured by `bullswarm setup`.
304
350
 
351
+ Reasoning depth is a third, independent decision. An action may carry an
352
+ optional `reasoning` field — `low`, `medium`, `high`, `xhigh`, `max`, or
353
+ `default` — that sets how hard the picked model thinks on that one action and
354
+ outranks every configured level for it. `default` passes nothing and lets the
355
+ worker CLI's own setting decide. Omitting the field keeps the configured level.
356
+ It never changes the pool, model, or effort tier, so a `low`-effort mechanical
357
+ step can still be given `xhigh` thinking and a `high`-effort action can be told
358
+ to think cheaply. A connector that does not accept the requested level gets the
359
+ nearest level it supports.
360
+
305
361
  The planner does not author phases or declare success/failure. The kernel
306
362
  derives stable presentation stages for the TUI and computes the final V2
307
363
  result. Saved V2 runs retain their original execution and workspace policy on
@@ -352,6 +408,30 @@ The worker lock covers scout, work actions, and evidence actions. A pool that ca
352
408
  the requested model is ineligible rather than silently substituting another
353
409
  model.
354
410
 
411
+ Reasoning depth can be pinned for a whole run the same way, without touching
412
+ global strategy:
413
+
414
+ ```bash
415
+ bullswarm workflow goal "Implement and verify the change" --cwd . \
416
+ --program plan.json --worker-reasoning high --json
417
+ bullswarm run --lane build --reasoning xhigh --prompt '<task>' --json
418
+ ```
419
+
420
+ `--worker-reasoning` covers scout, work actions, and evidence actions;
421
+ `--planner-reasoning` covers a dispatched Workflow Planner and applies only
422
+ with `--orchestrator`. Exactly one level is resolved per attempt, and the
423
+ first layer that sets one wins — not the strongest: the action's own
424
+ `reasoning` field, then the run-wide flag (`--worker-reasoning`,
425
+ `--planner-reasoning`, `bullswarm run --reasoning`), then the configured
426
+ `strategy.reasoning` level for that pool and tier, then the same for the tier
427
+ globally, then the connector's own default for the effort tier, and otherwise
428
+ nothing is appended. So an action asking for `low` beats a run-wide `max`.
429
+ `default` at any layer stops there and passes nothing, letting the worker
430
+ CLI's own setting decide; a connector with no `reasoning` block, or a model it
431
+ marks as skipped, never receives a flag. The applied level is recorded on
432
+ every attempt with the layer that set it and displayed next to the model, so a
433
+ run that thought more cheaply than requested is visible rather than inferred.
434
+
355
435
  The `opencode2` connector itself does not require a KaiHK provider: its base
356
436
  spawn command carries no hardcoded model, so a plain OpenCode installation
357
437
  dispatches with OpenCode's own configured default. When
@@ -656,8 +736,9 @@ while working. Process exit, a fatal auth/quota signature, explicit operator
656
736
  cancellation, or an opt-in timeout remain the terminal signals.
657
737
 
658
738
  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.
739
+ the applied reasoning level with the layer that set it, routing reason, all
740
+ eligible candidates with quota surplus, timestamps, artifact paths, outcome,
741
+ and reported-or-estimated token/cost/quota usage.
661
742
  `workflow tui <id>` renders this breakdown for completed runs as well as live
662
743
  ones; `workflow tui --json <id>` exposes the durable audit document.
663
744
  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" },