the-high-council 0.6.0 → 0.7.6
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/.env.example +2 -3
- package/README.md +191 -23
- package/TROUBLESHOOTING.md +13 -0
- package/chains/cheap-7-v2.json +98 -0
- package/chains/cheap-7.json +93 -0
- package/chains/coder-gate-v1.json +56 -0
- package/chains/coder-gate-v2.json +55 -0
- package/chains/eu-only.json +44 -0
- package/chains/gp-judge-v1.json +31 -7
- package/chains/idea-open-c2.json +2 -13
- package/chains/local-ollama.json +43 -0
- package/chains/mock-dispute.json +47 -0
- package/chains/mock-partitioned.json +62 -0
- package/chains/mock-patch-fallback.json +41 -0
- package/chains/mock-patch.json +41 -0
- package/chains/mock-proposals.json +4 -2
- package/chains/mock-security-review.json +45 -0
- package/chains/plan-auto-mistral.json +6 -6
- package/chains/plan-auto.json +2 -2
- package/chains/plan-debate-c2.json +1 -1
- package/chains/plan-debate-open-c2.json +2 -13
- package/chains/plan-debate-roles-c1.json +25 -67
- package/chains/plan-debate.json +1 -1
- package/chains/plan-open-7.json +93 -0
- package/chains/plan-premium-7.json +113 -0
- package/chains/plan-two-strong.json +74 -0
- package/chains/seven.json +1 -6
- package/chains/single-vendor-anthropic.json +43 -0
- package/chains/single-vendor-openai.json +43 -0
- package/chains/us-only.json +44 -0
- package/chains/verify.json +1 -1
- package/package.json +24 -4
- package/src/audit.js +194 -0
- package/src/board-export.js +40 -1
- package/src/budget.js +18 -6
- package/src/buys.js +8 -0
- package/src/cache-integrity.js +39 -16
- package/src/canary.js +126 -0
- package/src/chain-lint.js +660 -7
- package/src/chain.js +2191 -140
- package/src/claims.js +135 -0
- package/src/cli.js +1210 -155
- package/src/cost.js +87 -3
- package/src/council-replay.js +122 -0
- package/src/denied-models.js +139 -0
- package/src/disagreement-groups.js +54 -0
- package/src/dissent-digest.js +105 -0
- package/src/errors.js +14 -0
- package/src/fence.js +145 -0
- package/src/http-server.js +1 -1
- package/src/key-redaction.js +15 -45
- package/src/lints.js +135 -0
- package/src/mcp/server.js +248 -54
- package/src/metrics.js +420 -0
- package/src/name-lint.js +54 -9
- package/src/outcome.js +29 -0
- package/src/partial-deliverable.js +29 -4
- package/src/patch-revise.js +91 -0
- package/src/peer-claim.js +65 -13
- package/src/pii-gate.js +149 -0
- package/src/policy.js +265 -0
- package/src/preflight.js +119 -8
- package/src/pricing.json +126 -18
- package/src/progress-spans.js +72 -0
- package/src/providers.js +529 -40
- package/src/quote-check.js +134 -0
- package/src/rematch.js +70 -0
- package/src/report-shape.js +119 -0
- package/src/role-diagnostics.js +10 -3
- package/src/roles.js +651 -40
- package/src/run-lock.js +106 -0
- package/src/run-state.js +54 -0
- package/src/run-status.js +84 -0
- package/src/scope-freeze.js +19 -3
- package/src/seat-role.js +5 -1
- package/src/secret-patterns.js +113 -0
- package/src/security-review.js +201 -0
- package/src/shape-rounds.js +5 -1
- package/src/spans.js +84 -0
- package/src/spend.js +44 -8
- package/src/stage-contract.js +46 -10
- package/src/superseded.js +73 -0
- package/src/tools.js +455 -0
- package/src/verdict-diff.js +63 -0
- package/src/verdict-stats.js +81 -7
- package/src/version.js +18 -0
package/.env.example
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
ANTHROPIC_API_KEY=
|
|
4
4
|
OPENAI_API_KEY=
|
|
5
5
|
GOOGLE_API_KEY=
|
|
6
|
-
XAI_API_KEY=
|
|
7
6
|
MISTRAL_API_KEY=
|
|
8
7
|
DEEPSEEK_API_KEY=
|
|
9
8
|
GROQ_API_KEY=
|
|
@@ -14,6 +13,6 @@ ZAI_API_KEY=
|
|
|
14
13
|
|
|
15
14
|
# Default per-run spend ceiling in USD. Overridden per run by --max-usd.
|
|
16
15
|
# A run stops cleanly before any stage that could take it past this, and
|
|
17
|
-
# resumes with a higher ceiling. Unset means $
|
|
16
|
+
# resumes with a higher ceiling. Unset means $7. Use --max-usd none to run
|
|
18
17
|
# without a ceiling.
|
|
19
|
-
MAX_USD_PER_RUN=
|
|
18
|
+
MAX_USD_PER_RUN=7
|
package/README.md
CHANGED
|
@@ -1,24 +1,29 @@
|
|
|
1
1
|
# The High Council
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **Repository status (2026-09-22): going private until the open-source release.** Development
|
|
4
|
+
> continues in a private repository, and the public open-source release is planned for later this
|
|
5
|
+
> year. Until then, the published npm package `the-high-council` (0.7.6) stays installable as it
|
|
6
|
+
> is, and the `npx github:...` lines below only work for someone with access to this repository.
|
|
7
|
+
> The licence of everything already released stays MIT.
|
|
4
8
|
|
|
5
9
|
See it work right now - no keys, no setup, no cost:
|
|
6
10
|
|
|
7
|
-
npx
|
|
11
|
+
npx the-high-council council demo
|
|
8
12
|
|
|
9
13
|
Add it to Claude Code as an MCP server the same way:
|
|
10
14
|
|
|
11
|
-
claude mcp add council -- npx -y
|
|
15
|
+
claude mcp add council -- npx -y the-high-council council --mcp
|
|
12
16
|
|
|
13
|
-
*(
|
|
14
|
-
|
|
17
|
+
*(With access to this repository, `npx github:muad-yasin/the-high-council-mcp council demo` runs
|
|
18
|
+
the current source instead of the published package.)*
|
|
15
19
|
|
|
16
20
|
A planning harness that runs one idea past several AI models from different labs, makes them
|
|
17
21
|
argue about it on the record, and stops at a checkable result.
|
|
18
22
|
|
|
19
23
|
Runs as an **MCP server** (so an agent like Claude Code can drive it) or as a **CLI**. Bring your
|
|
20
|
-
own API keys. Nothing is resold, nothing is hosted for you, and
|
|
21
|
-
|
|
24
|
+
own API keys. Nothing is resold, nothing is hosted for you, and your keys go only to the
|
|
25
|
+
providers you choose, never to us.
|
|
26
|
+
Run `npx the-high-council council doctor` to see which of your own keys are
|
|
22
27
|
set, which shipped chains you can already run with them, and what each would cost - before
|
|
23
28
|
spending anything.
|
|
24
29
|
|
|
@@ -76,6 +81,15 @@ anything on top of a run, read that instead. Do not parse the markdown.
|
|
|
76
81
|
"replies": [ { "id": "DEEPSEEK-1", "action": "keep|amend|withdraw",
|
|
77
82
|
"text": "...", "replaced_by": "GLM-1" } ]
|
|
78
83
|
},
|
|
84
|
+
// Only on chains with `alternatives: { enabled: true }`: one whole architecture per lab, written
|
|
85
|
+
// blind before the skeleton, and the same post/reply board the proposals get.
|
|
86
|
+
"alternatives": {
|
|
87
|
+
"items": [ { "id": "GLM-ALT", "lab": "glm", "model": "...", "name": "...", "shape": "...",
|
|
88
|
+
"key_tradeoffs": "...", "bad_at": "...", "amended": true, "withdrawn": false } ],
|
|
89
|
+
"posts": [ { "by": "qwen", "on": "GLM-ALT", "stance": "object|support|merge", "text": "..." } ],
|
|
90
|
+
"replies": [ { "id": "GLM-ALT", "action": "keep|amend|withdraw", "text": "..." } ],
|
|
91
|
+
"dropouts": [ { "lab": "...", "model": "...", "stage": "alternatives", "reason": "..." } ]
|
|
92
|
+
},
|
|
79
93
|
"signoff": [ { "provider": "qwen", "model": "...", "signedOff": false,
|
|
80
94
|
"objections": [ { "criterion": "...", "problem": "...", "fix": "..." } ] } ],
|
|
81
95
|
"lastCritique": { "meets": false, "failures": [ { "criterion": "...", "lab": "qwen" } ] },
|
|
@@ -136,10 +150,63 @@ Fill in `.env` with only the keys your chosen chain needs. Supported providers:
|
|
|
136
150
|
|
|
137
151
|
`ANTHROPIC_API_KEY` · `OPENAI_API_KEY` · `GOOGLE_API_KEY` · `MISTRAL_API_KEY` ·
|
|
138
152
|
`DEEPSEEK_API_KEY` · `GROQ_API_KEY` · `TOGETHER_API_KEY` · `COHERE_API_KEY` ·
|
|
139
|
-
`OPENROUTER_API_KEY` · `ZAI_API_KEY`
|
|
153
|
+
`OPENROUTER_API_KEY` · `ZAI_API_KEY`
|
|
154
|
+
|
|
155
|
+
xAI/Grok and Kimi/Moonshot are never seated, and neither is a router id (`openrouter/auto`, the
|
|
156
|
+
Pareto Code router) that could route to them: chain-lint refuses such a chain and the run itself
|
|
157
|
+
refuses such a seat, with no override. There is no `xai` provider.
|
|
140
158
|
|
|
141
159
|
The CLI refuses to start if any seat in the chosen chain is missing its key, rather than failing
|
|
142
|
-
halfway through a paid run.
|
|
160
|
+
halfway through a paid run. `ollama` (below) is the one exception - it needs no key at all.
|
|
161
|
+
|
|
162
|
+
### Standalone binaries (build them yourself)
|
|
163
|
+
|
|
164
|
+
There are no published binary downloads yet. From a clone you can build a single-file `council`
|
|
165
|
+
that needs no Node install to run: a Linux binary, a Linux AppImage, and a Windows `.exe`, all
|
|
166
|
+
built on Linux.
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
npm run build:bin # dist/the-high-council-linux, dist/the-high-council-win.exe
|
|
170
|
+
npm run build:appimage # dist/the-high-council-x86_64.AppImage (downloads a pinned appimagetool)
|
|
171
|
+
npm run smoke:bin -- dist/the-high-council-linux # demo + an MCP session, offline, $0
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Stated plainly: the `.exe` is tested under Wine on Linux, not on a real Windows machine, and none
|
|
175
|
+
of the binaries are code-signed, so Windows SmartScreen will warn. Put `.env` in the directory you
|
|
176
|
+
run the binary from.
|
|
177
|
+
|
|
178
|
+
### Local models (Ollama, LM Studio, ...)
|
|
179
|
+
|
|
180
|
+
A seat can run on a model you're hosting yourself instead of a paid API. Set its provider to
|
|
181
|
+
`ollama`:
|
|
182
|
+
|
|
183
|
+
```json
|
|
184
|
+
{ "provider": "ollama", "model": "llama3.1" }
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
This talks to Ollama's own OpenAI-compatibility endpoint (`http://localhost:11434/v1` by
|
|
188
|
+
default) - no `OLLAMA_API_KEY` needed; Ollama's docs describe a key as "required, but unused."
|
|
189
|
+
If your local runner listens somewhere else (LM Studio, a different port, a remote box), add
|
|
190
|
+
`baseUrl` to that seat:
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{ "provider": "ollama", "model": "mistral", "baseUrl": "http://localhost:1234/v1" }
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
A local seat prices at $0 in every estimate and run report - `dry_run` shows it as priced, not
|
|
197
|
+
"unpriced," and it can never trip the spend cap. See `chains/local-ollama.json` for a full
|
|
198
|
+
example chain with every seat local. As with every other seat in this project: BYOK is really
|
|
199
|
+
BYO-compute here, and no efficacy claim is made about local models versus hosted ones - nothing
|
|
200
|
+
has been measured.
|
|
201
|
+
|
|
202
|
+
### Final security-review gate
|
|
203
|
+
|
|
204
|
+
`"security_review": { "enabled": true }` adds one read-only reviewer as the last stage of a chain,
|
|
205
|
+
after the build and everything else. It returns typed findings, and any critical or high finding
|
|
206
|
+
fails the run (exit 7). A reviewer with no usable verdict fails it too (exit 8); that never counts
|
|
207
|
+
as a pass. The default reviewer is `anthropic/claude-fable-5-1` (your key, priced, capped);
|
|
208
|
+
`seats.security_reviewer` can be any seat, including a local `ollama` one as an offline option.
|
|
209
|
+
Full details: [docs/security-review-gate.md](docs/security-review-gate.md).
|
|
143
210
|
|
|
144
211
|
## Quick start (CLI)
|
|
145
212
|
|
|
@@ -163,6 +230,34 @@ them stay on your machine - if you fork this repo, you will not accidentally pub
|
|
|
163
230
|
|
|
164
231
|
`verify` is the cheap default: two labs, a hard two-round cap. Start there.
|
|
165
232
|
|
|
233
|
+
### Exit codes
|
|
234
|
+
|
|
235
|
+
Each outcome has its own code, so a script or CI job can branch on it:
|
|
236
|
+
|
|
237
|
+
| Code | Meaning |
|
|
238
|
+
|---|---|
|
|
239
|
+
| 0 | Finished: a deliverable and `report.json` were written. |
|
|
240
|
+
| 1 | The chain failed lint, or an input is missing (no task file, a resume from the wrong directory). |
|
|
241
|
+
| 2 | Usage error: a flag is missing its value or has an invalid one. |
|
|
242
|
+
| 3 | Paused at an external seat: answer `NEEDS-<stage>.md`, then `--resume`. |
|
|
243
|
+
| 4 | Stopped at the per-run spend cap before the next stage was paid for; resume with a higher `--max-usd`. |
|
|
244
|
+
| 5 | A provider key the chain needs is missing (degradable: set it and run again). |
|
|
245
|
+
| 6 | Fatal: the chain file cannot be parsed, or the audit key cannot be loaded. |
|
|
246
|
+
| 7 | Finished, but the final security review blocked the deliverable. |
|
|
247
|
+
| 8 | Finished, but the final security review could not judge it (never a pass). |
|
|
248
|
+
| 9 | Artifact gate: the task names files whose content it never includes (`BLOCKED-ARTIFACTS.md`). |
|
|
249
|
+
| 10 | Preflight: a seat objected to the task description itself (`STOPPED-preflight.md`). |
|
|
250
|
+
| 11 | PII gate (`--pii-gate hard-stop`): the input matches a PII shape or one of the key formats listed in `src/secret-patterns.js`. |
|
|
251
|
+
| 12 | `policy.json` refused the chain. |
|
|
252
|
+
| 13 | Another process is already running this run folder. |
|
|
253
|
+
| 14 | The task file changed since the run started and `AMENDMENTS.md` does not cover it. |
|
|
254
|
+
| 15 | `--resume` of a run that already finished (it has a `report.json`); nothing is run or spent. |
|
|
255
|
+
| 16 | The run stopped at an unexpected error (a seat that could not be reached, a crash); `STOPPED-error.md` says what, and `--resume` continues from the completed stages. |
|
|
256
|
+
| 17 | A draft (build, revise, dispute, final edit or handoff) was cut off at its token cap, and its one larger-cap retry was cut off too; the fragment is never graded or shipped (`STOPPED-truncated.md`). |
|
|
257
|
+
|
|
258
|
+
Codes 9-17 were split out or added on 2026-09-23. Before that, several of these outcomes shared a code (2, 5,
|
|
259
|
+
6 or 1).
|
|
260
|
+
|
|
166
261
|
### Telling the council what your build session can actually use
|
|
167
262
|
|
|
168
263
|
One optional convention, worth the four lines it costs. If your task file ends with a section
|
|
@@ -187,7 +282,7 @@ before building it."*
|
|
|
187
282
|
|
|
188
283
|
### The spend cap
|
|
189
284
|
|
|
190
|
-
Every run has a per-run ceiling in USD. It defaults to **$
|
|
285
|
+
Every run has a per-run ceiling in USD. It defaults to **$7**, and is checked *before* each paid
|
|
191
286
|
stage - a stage that could take the run past the ceiling is never called, so the cap holds rather
|
|
192
287
|
than reporting the overspend afterwards.
|
|
193
288
|
|
|
@@ -206,6 +301,14 @@ with a higher ceiling - completed stages replay from disk and cost nothing the s
|
|
|
206
301
|
node src/cli.js --resume runs/<id> --max-usd 10
|
|
207
302
|
```
|
|
208
303
|
|
|
304
|
+
A stage replays only if it would be asked the same thing again: the task text, the chain config
|
|
305
|
+
and the stage's own prompt must all match what it answered. If one changed (you edited the chain,
|
|
306
|
+
or an earlier stage came out differently this time), the stage runs again and its old files move
|
|
307
|
+
into `superseded/` inside the run folder. What the old answer cost still counts toward the ceiling,
|
|
308
|
+
`--spend` and `report.json`'s `totals.usd` (shown separately as `totals.supersededUsd`), so a resume
|
|
309
|
+
cannot spend past the cap. An answer you wrote for an external stage is never re-used against a
|
|
310
|
+
changed prompt: it is set aside the same way and the run asks you again.
|
|
311
|
+
|
|
209
312
|
The cap governs one run. To see what you have spent across all of them:
|
|
210
313
|
|
|
211
314
|
```bash
|
|
@@ -238,12 +341,16 @@ node src/cli.js --resume runs/<id>
|
|
|
238
341
|
|
|
239
342
|
## Quick start (MCP)
|
|
240
343
|
|
|
241
|
-
Register the server with your MCP client. No clone needed -
|
|
344
|
+
Register the server with your MCP client. No clone needed - from the published npm package:
|
|
242
345
|
|
|
243
346
|
```bash
|
|
244
|
-
claude mcp add council -- npx -y
|
|
347
|
+
claude mcp add council -- npx -y the-high-council council --mcp
|
|
245
348
|
```
|
|
246
349
|
|
|
350
|
+
With access to this repository (private until the open-source release), the same line with
|
|
351
|
+
`npx -y github:muad-yasin/the-high-council-mcp` runs the current source instead. The clone and
|
|
352
|
+
plugin-marketplace routes below need that access too.
|
|
353
|
+
|
|
247
354
|
Or from a clone of this repo:
|
|
248
355
|
|
|
249
356
|
```bash
|
|
@@ -253,7 +360,25 @@ claude mcp add high-council -- node /absolute/path/to/the-high-council-mcp/src/m
|
|
|
253
360
|
**The path must be absolute.** The client starts the server from its own working directory, not
|
|
254
361
|
from this one, so a relative path resolves somewhere unexpected and the server never starts.
|
|
255
362
|
|
|
256
|
-
|
|
363
|
+
Or as a Claude Code plugin, which registers the same server and also installs the skills in
|
|
364
|
+
[`skills/`](skills/README.md):
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
claude plugin marketplace add muad-yasin/the-high-council-mcp
|
|
368
|
+
claude plugin install the-high-council@the-high-council
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
Claude Code copies the plugin into its plugin cache and runs `npm ci` there itself, so the first
|
|
372
|
+
install takes a little longer. Start a new session (or run `/reload-plugins`) and the server shows
|
|
373
|
+
up in `claude mcp list` as `plugin:the-high-council:high-council`. Remove it with
|
|
374
|
+
`claude plugin uninstall the-high-council@the-high-council`. If you add the marketplace from a
|
|
375
|
+
local clone instead (`claude plugin marketplace add /path/to/clone`), the server runs from the
|
|
376
|
+
clone itself, so run `npm install` in it first.
|
|
377
|
+
|
|
378
|
+
Registering with a client other than Claude Code (DeepSeek Harness, OpenHands, Cline, goose,
|
|
379
|
+
Continue): [docs/mcp-clients.md](docs/mcp-clients.md) has the real config for each.
|
|
380
|
+
|
|
381
|
+
An npm package is also live:
|
|
257
382
|
|
|
258
383
|
```bash
|
|
259
384
|
claude mcp add high-council -- npx -y the-high-council --mcp
|
|
@@ -280,6 +405,7 @@ Then drive it with these tools:
|
|
|
280
405
|
| `run_status` | Stage reached, panel verdicts, scoreboard, cost, budget remaining |
|
|
281
406
|
| `spend_report` | What every run has cost across a window of days, plus `session_cost_today` (calendar-day, per-model breakdown), derived from disk |
|
|
282
407
|
| `verdict_stats` | How the debate mechanism itself is doing, per chain and per lab: sign-off rate, rounds, objections, dropouts, cost/wall time, largest prompt files - derived from disk |
|
|
408
|
+
| `metrics_report` | Descriptive telemetry only (never an evaluation or baseline): amendment rate, withdrawal rate, objection-follow-through rate, tool-call usage, consensus-induced-regression count - derived from disk. See [`docs/paid-comparison-run.md`](docs/paid-comparison-run.md) for what a *real* comparison against a single model would need - not built, not this metric |
|
|
283
409
|
| `external_prompt` | The prompt a paused external stage is waiting on - **read it with this, not by opening the file**; the prompts are routinely tens of thousands of tokens and most clients silently truncate a file read |
|
|
284
410
|
| `prepare_stage_prompt` | Write a self-contained bundle for a paused stage, so a driving session doing other work at the same time can dispatch it to a fresh subagent instead of authoring it inline - see [`docs/dispatch-pattern.md`](docs/dispatch-pattern.md) |
|
|
285
411
|
| `submit_stage` | Answer a paused stage and resume. Optional `claimed_by` records who's answering; a second submission for an already-answered stage no longer errors - it's kept as `<stage>.late.md` with a warning instead of being rejected |
|
|
@@ -299,7 +425,7 @@ for anyone with a subscription, since the project's cost story depends on it.
|
|
|
299
425
|
|
|
300
426
|
## Chains
|
|
301
427
|
|
|
302
|
-
|
|
428
|
+
48 chain configs live in `chains/`. Each one is plain JSON - the seat roster, which models fill
|
|
303
429
|
which seat, the round cap, and whether proposals/debate/handoff stages run. They are meant to be
|
|
304
430
|
copied and edited.
|
|
305
431
|
|
|
@@ -309,7 +435,8 @@ A few worth knowing:
|
|
|
309
435
|
- **`cheap`** - small models throughout. For testing the harness itself, not for real work.
|
|
310
436
|
- **`plan-debate`** - five labs propose blind, debate each other's proposals anonymised, then a
|
|
311
437
|
blind panel grades the integrated draft.
|
|
312
|
-
- **`plan-auto`** - the full open-scope chain
|
|
438
|
+
- **`plan-auto`** - the full open-scope chain with every seat on a real API, so no stage waits for
|
|
439
|
+
an external session. It still pauses once for your answers to its questions.
|
|
313
440
|
- **`plan-unanimous`** - every critic must independently sign off on the *same* draft. Three rounds
|
|
314
441
|
here means up to fifteen critic calls, not five.
|
|
315
442
|
|
|
@@ -361,8 +488,9 @@ Read a chain's `description` field before running it; they say what they cost yo
|
|
|
361
488
|
review round can't run), or a seat naming a provider this codebase doesn't know. The same check
|
|
362
489
|
also runs automatically, fail-loud, the moment you try to actually run a broken chain - before
|
|
363
490
|
any paid call.
|
|
364
|
-
- **`council doctor --scan-artifacts`** - scans your `tasks/` and `chains/` for
|
|
365
|
-
|
|
491
|
+
- **`council doctor --scan-artifacts`** - scans your `tasks/` and `chains/` for the key formats
|
|
492
|
+
listed in `src/secret-patterns.js` before you commit or share them. A format not on that list is
|
|
493
|
+
not caught. Reports the file and line, never the matched text.
|
|
366
494
|
- **`council --forecast-cost --chain <name> [--days N]`** - a realistic-case USD range for a
|
|
367
495
|
chain, built from its own historical runs on your machine and repriced at today's rates -
|
|
368
496
|
distinct from `--dry-run`'s worst-case estimate from a chain's declared token assumptions.
|
|
@@ -370,7 +498,7 @@ Read a chain's `description` field before running it; they say what they cost yo
|
|
|
370
498
|
verdict as one self-contained HTML file. No external assets, no server, `<details>` sections.
|
|
371
499
|
- **`council replay --run <folder> [--json]`** - a numbered, step-by-step transcript of a run's
|
|
372
500
|
reasoning in your terminal, with a `--json` mode for scripting.
|
|
373
|
-
- **A structured error catalog** (`COUNCIL-E001`-`COUNCIL-
|
|
501
|
+
- **A structured error catalog** (`COUNCIL-E001`-`COUNCIL-E005`, see [TROUBLESHOOTING.md](TROUBLESHOOTING.md))
|
|
374
502
|
for the hard-fail paths this project actually has - a missing key, an unpriced model, a
|
|
375
503
|
malformed chain file, an unreadable stage reply - each with a plain-words cause, a concrete fix
|
|
376
504
|
naming the real file, and a doc pointer. Degradable conditions exit 5; fatal ones exit 6.
|
|
@@ -417,6 +545,24 @@ claiming 29 chains and 12 tools when there were 30 and 11.
|
|
|
417
545
|
|
|
418
546
|
No claim is made here that any of this produces better plans. It has not been measured.
|
|
419
547
|
|
|
548
|
+
## Skills
|
|
549
|
+
|
|
550
|
+
`skills/` carries a small set of Claude Code skills shipped alongside this harness, not part of
|
|
551
|
+
it - usable in any project, with or without the harness, and needing no API key:
|
|
552
|
+
|
|
553
|
+
- **Core agentic work:** `task-scoping`, `research-and-sourcing`, `verification-and-critique`,
|
|
554
|
+
`context-and-handoff`, `tool-and-action-discipline` - the work around the work, for any agent
|
|
555
|
+
task, including setups where several models propose, critique, and hand off to each other.
|
|
556
|
+
- **Building software:** `backend-developer`, `frontend-developer`, `ux-design`, `visual-craft`.
|
|
557
|
+
- **Writing:** `good-news-writing`.
|
|
558
|
+
|
|
559
|
+
The full catalog, with when to use each and what it guards against, is
|
|
560
|
+
[`skills/README.md`](skills/README.md); a shareable presentation page is `docs/skills.html`. Both
|
|
561
|
+
are checked by the test suite against the real `skills/` folder. Same MIT/BYOK ethos as the
|
|
562
|
+
harness: the skills don't claim to make results better - nothing has been measured - they describe
|
|
563
|
+
what each rule guards against and why. Copy the folders you want into your project's
|
|
564
|
+
`.claude/skills/`, or point Claude Code at this repo's `skills/` directory.
|
|
565
|
+
|
|
420
566
|
## Known limits, stated plainly
|
|
421
567
|
|
|
422
568
|
- The spend cap is enforced against a **worst case**, not a prediction: the whole prompt billed as
|
|
@@ -425,7 +571,20 @@ No claim is made here that any of this produces better plans. It has not been me
|
|
|
425
571
|
left. That is the intended trade - resume it with a higher ceiling.
|
|
426
572
|
- A seat whose model has no entry in `src/pricing.json` is **unpriced, and therefore uncapped**.
|
|
427
573
|
It contributes $0 to the running total no matter what it really costs. Check `dry_run` output
|
|
428
|
-
for `unpriced` before trusting a ceiling.
|
|
574
|
+
for `unpriced` before trusting a ceiling. `ollama` seats are the one deliberate exception: they
|
|
575
|
+
price at an explicit $0 for any model name (they are genuinely free to run), so they never show
|
|
576
|
+
up in that `unpriced` list and never need a pricing.json entry.
|
|
577
|
+
- A call that fails **after** it reached the provider - the connection drops while a 200 reply is
|
|
578
|
+
being read, a 200 carries a body that is not JSON, or the request times out waiting for headers -
|
|
579
|
+
is not retried, because the generation was probably already billed. Its real usage cannot be
|
|
580
|
+
read, so it is counted toward the per-run cap at its worst-case projection. It leaves no
|
|
581
|
+
`<label>.usage.json`, so `council --spend` does not see it.
|
|
582
|
+
- Some hosted reasoning models stop at a provider-side reasoning ceiling well below the seat's own
|
|
583
|
+
cap, before writing any answer (seen 2026-09-23: `deepseek/deepseek-v4.1-flash` via OpenRouter, 6 of
|
|
584
|
+
28 calls stopped at ~4.2k tokens, all reasoning, under a 36k cap). A bigger cap cannot fix that, so
|
|
585
|
+
such a reply is recorded as `REASONING_EXHAUSTED` and is not retried: the seat abstains, which
|
|
586
|
+
blocks unanimity and never counts as consent. Whether to change a chain's reasoning settings for it
|
|
587
|
+
is a roster decision, not something the harness does for you.
|
|
429
588
|
- Prices in `src/pricing.json` are hand-maintained list prices, last verified 2026-09-06. They are
|
|
430
589
|
estimates, not invoices. Your provider's bill is the real number.
|
|
431
590
|
- Chains with many labs and high round caps get expensive quickly. `plan-unanimous` at three rounds
|
|
@@ -436,6 +595,10 @@ No claim is made here that any of this produces better plans. It has not been me
|
|
|
436
595
|
produce sign-offs that mean nothing - the quality of the run depends heavily on the quality of
|
|
437
596
|
the criteria stage.
|
|
438
597
|
- Some chains pause for human input by design. They are not stuck.
|
|
598
|
+
- The audit log (`audit.jsonl`) detects an edited line or a cut-off end, but **with no HMAC key,
|
|
599
|
+
which is the default, it does not detect a full rewrite**: anyone who can edit the file can
|
|
600
|
+
recompute every hash. Set `AUDIT_HMAC_KEY_FILE` to a key kept outside the run folder if the log
|
|
601
|
+
has to stand up to that.
|
|
439
602
|
|
|
440
603
|
## Privacy
|
|
441
604
|
|
|
@@ -447,16 +610,21 @@ collect nothing. Stated plainly, not as a claim about quality:
|
|
|
447
610
|
your own keys (`ANTHROPIC_API_KEY`, `OPENROUTER_API_KEY`, and so on) - and only when you start
|
|
448
611
|
a real run with a non-mock, non-external seat. `council doctor` and `council demo` make zero
|
|
449
612
|
network calls; both are implemented to read only local files and environment variable names.
|
|
450
|
-
- The
|
|
613
|
+
- The landing page (`docs/`, moving from GitHub Pages to sower-industries.de while this
|
|
614
|
+
repository is private) ships no JavaScript and loads no third-party resource - see
|
|
451
615
|
`test/landing-page.test.js`, which fails the build if either ever changes.
|
|
452
616
|
- Everything a run produces - the task, the debate, the deliverable, the cost - is written to a
|
|
453
617
|
folder on your own disk (`runs/<id>/`) and nowhere else. Deleting that folder deletes the
|
|
454
618
|
record. See `src/spend.js`'s own documentation for why spend accounting is derived from those
|
|
455
619
|
folders rather than kept in a separate log.
|
|
620
|
+
- If you opt in to the audit export (`"audit": true`, and on automatically whenever a `policy.json`
|
|
621
|
+
exists), each run also writes `audit.jsonl` into its own folder: signed, hash-chained lines (each carries the previous line's hash) that
|
|
622
|
+
`verifyAuditLog` in `src/audit.js` checks offline. Seat, cost and timing only, never task or
|
|
623
|
+
prompt text. Format: `docs/audit-schema.md`.
|
|
456
624
|
|
|
457
625
|
## Accessibility
|
|
458
626
|
|
|
459
|
-
The
|
|
627
|
+
The landing page (`docs/`) uses only native HTML elements for interaction - `<a href>`
|
|
460
628
|
links and `<details>/<summary>` for the expandable demo sections - specifically because those
|
|
461
629
|
are keyboard-operable by the browser itself, with no custom JavaScript to get wrong. Tested by
|
|
462
630
|
hand, 2026-09-13, on the live site:
|
|
@@ -478,8 +646,8 @@ hand, 2026-09-13, on the live site:
|
|
|
478
646
|
|
|
479
647
|
## Reporting a bug
|
|
480
648
|
|
|
481
|
-
|
|
482
|
-
|
|
649
|
+
Write to [contact@sower-industries.de](mailto:contact@sower-industries.de). (GitHub issues open
|
|
650
|
+
again with the public release; while the repository is private, email is the only route.)
|
|
483
651
|
|
|
484
652
|
## If this makes you money
|
|
485
653
|
|
package/TROUBLESHOOTING.md
CHANGED
|
@@ -43,3 +43,16 @@ lab actually returned. The run log also says why it was unreadable: truncated
|
|
|
43
43
|
(hit its token cap), malformed JSON, or the provider itself returned an error
|
|
44
44
|
mid-generation - each needs a different fix (a higher `maxTokens`, a smaller
|
|
45
45
|
prompt, or just retrying).
|
|
46
|
+
|
|
47
|
+
## COUNCIL-E005 - Policy refusal (fatal)
|
|
48
|
+
|
|
49
|
+
Either `policy.json` itself isn't valid JSON, or the chain you're about to run
|
|
50
|
+
violates one of its limits (an unlisted provider or region, over the per-run or
|
|
51
|
+
per-month spend cap, a missing required tag, or an unpriced seat when
|
|
52
|
+
`refuse_unpriced_seats` is set). A policy file is a locked, operator-set set of
|
|
53
|
+
limits checked before any provider is called - a run that would violate it never
|
|
54
|
+
starts, so nothing was spent.
|
|
55
|
+
|
|
56
|
+
**Fix:** if the file itself won't parse, fix its JSON syntax. Otherwise, either
|
|
57
|
+
change the chain so it no longer violates the listed limit(s), or change
|
|
58
|
+
`policy.json` if the limit itself was wrong. See [docs/policy.md](docs/policy.md).
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cheap-7-v2",
|
|
3
|
+
"description": "Seven independent labs vote, none of them the author's, all on current-generation models through one OpenRouter key: OpenAI GPT-5.6 Luna, Google Gemini 3.8 Flash, DeepSeek v4.1 Flash, Z.ai GLM 5.3 Flash, Qwen 3.7 Plus, MiniMax M3, Mistral Medium 3.5. Blind proposals, debate, unanimous signoff, with a round cap of 7 and a stall rule: if the same objections from the same labs survive two rounds running, the revise loop stops rather than buying more rounds of the same argument, and the unresolved dissent is recorded at the top of the deliverable. A run that ends that way reports no consensus - the dispute stage records disagreement, it never resolves it. Anthropic Sonnet 5 writes the skeleton, the draft, every revision and the handoff and holds NO panel seat; Meta Llama 4 Maverick writes the criteria and also holds no panel seat, so neither the lab that drafts nor the lab that sets the bar votes on whether the bar was cleared. This is the revision of cheap-7 after its first real run, where one lab held the criteria, skeleton, builder, reviser and handoff seats AND a critic seat, voted on its own draft, and a claim it wrote survived to the deliverable. Anthropic is deliberately absent from the panel: plans from this chain are read by a Claude session before anything is built, so that review happens downstream rather than inside the vote. Kimi K3 is deliberately absent too - a seat that may route through another lab is not an independent seat. Every seat gets a 36000-token ceiling and reasoning is left on: a debate is not squeezed to a short answer, and a reply cut off at the ceiling is retried once, then the seat is re-asked alone - it is never counted as agreement. The cap is a ceiling, not a price; only generated tokens are billed. Prices are from src/pricing.json, refreshed against OpenRouter's live model list on 2026-09-20 - price a real task with `npm run dry` before running.",
|
|
4
|
+
"maxRounds": 7,
|
|
5
|
+
"signoff": "unanimous",
|
|
6
|
+
"dispute": {
|
|
7
|
+
"enabled": true,
|
|
8
|
+
"stall_rounds": 2
|
|
9
|
+
},
|
|
10
|
+
"proposals": {
|
|
11
|
+
"parts": 3,
|
|
12
|
+
"maxTokens": 4000
|
|
13
|
+
},
|
|
14
|
+
"debate": true,
|
|
15
|
+
"canary": { "enabled": true, "sampleRate": 0.1 },
|
|
16
|
+
"handoff": true,
|
|
17
|
+
"estimate": {
|
|
18
|
+
"promptTokens": 10000,
|
|
19
|
+
"draftTokens": 10000,
|
|
20
|
+
"critiqueTokens": 5000
|
|
21
|
+
},
|
|
22
|
+
"seats": {
|
|
23
|
+
"criteria": {
|
|
24
|
+
"provider": "openrouter",
|
|
25
|
+
"model": "meta-llama/llama-4-maverick",
|
|
26
|
+
"maxTokens": 36000,
|
|
27
|
+
"lab": "llama4-maverick"
|
|
28
|
+
},
|
|
29
|
+
"skeleton": {
|
|
30
|
+
"provider": "openrouter",
|
|
31
|
+
"model": "anthropic/claude-sonnet-5",
|
|
32
|
+
"maxTokens": 36000,
|
|
33
|
+
"lab": "sonnet5"
|
|
34
|
+
},
|
|
35
|
+
"builder": {
|
|
36
|
+
"provider": "openrouter",
|
|
37
|
+
"model": "anthropic/claude-sonnet-5",
|
|
38
|
+
"maxTokens": 36000,
|
|
39
|
+
"lab": "sonnet5"
|
|
40
|
+
},
|
|
41
|
+
"reviser": {
|
|
42
|
+
"provider": "openrouter",
|
|
43
|
+
"model": "anthropic/claude-sonnet-5",
|
|
44
|
+
"maxTokens": 36000,
|
|
45
|
+
"lab": "sonnet5"
|
|
46
|
+
},
|
|
47
|
+
"handoff": {
|
|
48
|
+
"provider": "openrouter",
|
|
49
|
+
"model": "anthropic/claude-sonnet-5",
|
|
50
|
+
"maxTokens": 36000,
|
|
51
|
+
"lab": "sonnet5"
|
|
52
|
+
},
|
|
53
|
+
"critics": [
|
|
54
|
+
{
|
|
55
|
+
"provider": "openrouter",
|
|
56
|
+
"model": "openai/gpt-5.6-luna",
|
|
57
|
+
"maxTokens": 36000,
|
|
58
|
+
"lab": "gpt5.6-luna"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"provider": "openrouter",
|
|
62
|
+
"model": "google/gemini-3.8-flash",
|
|
63
|
+
"maxTokens": 36000,
|
|
64
|
+
"lab": "gemini3.8-flash"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"provider": "openrouter",
|
|
68
|
+
"model": "deepseek/deepseek-v4.1-flash",
|
|
69
|
+
"maxTokens": 36000,
|
|
70
|
+
"lab": "deepseek-v4.1-flash"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"provider": "openrouter",
|
|
74
|
+
"model": "z-ai/glm-5.3-flash",
|
|
75
|
+
"maxTokens": 36000,
|
|
76
|
+
"lab": "glm5.3-flash"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"provider": "openrouter",
|
|
80
|
+
"model": "qwen/qwen3.7-plus",
|
|
81
|
+
"maxTokens": 36000,
|
|
82
|
+
"lab": "qwen3.7-plus"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"provider": "openrouter",
|
|
86
|
+
"model": "minimax/minimax-m3",
|
|
87
|
+
"maxTokens": 36000,
|
|
88
|
+
"lab": "minimax-m3"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"provider": "openrouter",
|
|
92
|
+
"model": "mistralai/mistral-medium-3-5",
|
|
93
|
+
"maxTokens": 36000,
|
|
94
|
+
"lab": "mistral-medium3.5"
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cheap-7",
|
|
3
|
+
"description": "SUPERSEDED by cheap-7-v2, and deliberately left failing chain-lint's self-review check, so it will not run - kept unmodified as the record of what the 2026-09-20 run actually used. Sonnet 5 holds the criteria, skeleton, builder, reviser and handoff seats AND a critic seat here, so it voted on its own draft under unanimous signoff; that is the defect cheap-7-v2 fixes. Do not add \"selfReview\": \"allowed\" to make this runnable again - use cheap-7-v2. Original description follows. Seven labs' small/cheap models, one seat each, all through one OpenRouter key: Anthropic Sonnet 5, OpenAI GPT-5 mini, Google Gemini 3.7 Flash, DeepSeek v3.2, Z.ai GLM 5.3 Flash, Qwen 3.5 Plus, MiniMax M3. Blind proposals, debate, unanimous signoff. Every seat gets a 36000-token ceiling and reasoning is left on: a debate is not squeezed to a short answer, and a reply cut off at the ceiling is retried once, then the seat is re-asked alone - it is never counted as agreement. The cap is a ceiling, not a price; only generated tokens are billed. Sonnet 5 builds and revises. For small questions where every model should still get a say; the frontier equivalent is reserved for questions worth its price. Prices are from src/pricing.json - price a real task with `npm run dry` before running.",
|
|
4
|
+
"maxRounds": 3,
|
|
5
|
+
"signoff": "unanimous",
|
|
6
|
+
"proposals": {
|
|
7
|
+
"parts": 3,
|
|
8
|
+
"maxTokens": 4000
|
|
9
|
+
},
|
|
10
|
+
"debate": true,
|
|
11
|
+
"handoff": true,
|
|
12
|
+
"estimate": {
|
|
13
|
+
"promptTokens": 10000,
|
|
14
|
+
"draftTokens": 10000,
|
|
15
|
+
"critiqueTokens": 5000
|
|
16
|
+
},
|
|
17
|
+
"seats": {
|
|
18
|
+
"criteria": {
|
|
19
|
+
"provider": "openrouter",
|
|
20
|
+
"model": "anthropic/claude-sonnet-5",
|
|
21
|
+
"maxTokens": 36000,
|
|
22
|
+
"lab": "sonnet5"
|
|
23
|
+
},
|
|
24
|
+
"skeleton": {
|
|
25
|
+
"provider": "openrouter",
|
|
26
|
+
"model": "anthropic/claude-sonnet-5",
|
|
27
|
+
"maxTokens": 36000,
|
|
28
|
+
"lab": "sonnet5"
|
|
29
|
+
},
|
|
30
|
+
"builder": {
|
|
31
|
+
"provider": "openrouter",
|
|
32
|
+
"model": "anthropic/claude-sonnet-5",
|
|
33
|
+
"maxTokens": 36000,
|
|
34
|
+
"lab": "sonnet5"
|
|
35
|
+
},
|
|
36
|
+
"reviser": {
|
|
37
|
+
"provider": "openrouter",
|
|
38
|
+
"model": "anthropic/claude-sonnet-5",
|
|
39
|
+
"maxTokens": 36000,
|
|
40
|
+
"lab": "sonnet5"
|
|
41
|
+
},
|
|
42
|
+
"handoff": {
|
|
43
|
+
"provider": "openrouter",
|
|
44
|
+
"model": "anthropic/claude-sonnet-5",
|
|
45
|
+
"maxTokens": 36000,
|
|
46
|
+
"lab": "sonnet5"
|
|
47
|
+
},
|
|
48
|
+
"critics": [
|
|
49
|
+
{
|
|
50
|
+
"provider": "openrouter",
|
|
51
|
+
"model": "anthropic/claude-sonnet-5",
|
|
52
|
+
"maxTokens": 36000,
|
|
53
|
+
"lab": "sonnet5"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"provider": "openrouter",
|
|
57
|
+
"model": "openai/gpt-5-mini",
|
|
58
|
+
"maxTokens": 36000,
|
|
59
|
+
"lab": "gpt5-mini"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"provider": "openrouter",
|
|
63
|
+
"model": "google/gemini-3.7-flash",
|
|
64
|
+
"maxTokens": 36000,
|
|
65
|
+
"lab": "gemini3.7-flash"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"provider": "openrouter",
|
|
69
|
+
"model": "deepseek/deepseek-v3.2",
|
|
70
|
+
"maxTokens": 36000,
|
|
71
|
+
"lab": "deepseek-v3.2"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"provider": "openrouter",
|
|
75
|
+
"model": "z-ai/glm-5.3-flash",
|
|
76
|
+
"maxTokens": 36000,
|
|
77
|
+
"lab": "glm5.3-flash"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"provider": "openrouter",
|
|
81
|
+
"model": "qwen/qwen3.5-plus-20260420",
|
|
82
|
+
"maxTokens": 36000,
|
|
83
|
+
"lab": "qwen3.5-plus"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"provider": "openrouter",
|
|
87
|
+
"model": "minimax/minimax-m3",
|
|
88
|
+
"maxTokens": 36000,
|
|
89
|
+
"lab": "minimax-m3"
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "coder-gate-v1",
|
|
3
|
+
"description": "MLLM Coder v1 (relay/runs/2026-09-14T16-14-10-757Z/deliverable.md). The governed unit is one diff against one pre-named file/hunk, not prose. The `propose` seat is external: THCMCP never writes code itself, it hands the change-request task file to an outside coding session and gets one fenced diff back (docs/coder-gate-diff-format.md). The `builder` seat is also external, held to the same session, and must return the proposal's diff verbatim as this chain's draft - there is no second, independent code-writing step; `builder` exists only because every chain needs one to reach a draft, not because a second author writes anything. `verify` (config.verify.enabled: true) wires the existing run_tests mechanism, but `verify.tools` ships empty here by design, not oversight: runVerification runs before any change-request/diff exists, and this repo has no `{{...}}` templating to inject a per-run target file/test command into a static chain config - a filled-in entry as specced would be inert. No test command runs automatically today (see test/coder-gate-verify.test.js's IN-3 fixture for how the mechanism works when a real, per-run `verify.tools` entry IS supplied downstream). No write-capable tool is used anywhere - applying the diff to a real working tree stays a human/external action. Built from existing stage types (proposal, critic, unanimous signoff); `debate: true` is set for forward compatibility but is currently unreachable - with one proposer and `proposals.parts: 1`, at most one proposal ever exists, and `runChain`'s debate stage only runs when `proposals.length > 1`, so v1 has no live debate today. No change to src/chain.js or src/tools.js.",
|
|
4
|
+
"maxRounds": 2,
|
|
5
|
+
"signoff": "unanimous",
|
|
6
|
+
"proposals": {
|
|
7
|
+
"parts": 1,
|
|
8
|
+
"maxTokens": 4000
|
|
9
|
+
},
|
|
10
|
+
"estimate": {
|
|
11
|
+
"promptTokens": 3000,
|
|
12
|
+
"draftTokens": 3000,
|
|
13
|
+
"critiqueTokens": 1000
|
|
14
|
+
},
|
|
15
|
+
"seats": {
|
|
16
|
+
"criteria": {
|
|
17
|
+
"provider": "anthropic",
|
|
18
|
+
"model": "claude-sonnet-5",
|
|
19
|
+
"maxTokens": 2000
|
|
20
|
+
},
|
|
21
|
+
"skeleton": {
|
|
22
|
+
"provider": "anthropic",
|
|
23
|
+
"model": "claude-sonnet-5",
|
|
24
|
+
"maxTokens": 1000
|
|
25
|
+
},
|
|
26
|
+
"proposers": [
|
|
27
|
+
{
|
|
28
|
+
"provider": "external",
|
|
29
|
+
"model": "claude-code-session",
|
|
30
|
+
"lab": "external-proposer"
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"builder": {
|
|
34
|
+
"provider": "external",
|
|
35
|
+
"model": "claude-code-session"
|
|
36
|
+
},
|
|
37
|
+
"critics": [
|
|
38
|
+
{
|
|
39
|
+
"provider": "anthropic",
|
|
40
|
+
"model": "claude-sonnet-5",
|
|
41
|
+
"maxTokens": 8000
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"provider": "openai",
|
|
45
|
+
"model": "gpt-5",
|
|
46
|
+
"maxTokens": 8000
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
"debate": true,
|
|
51
|
+
"handoff": false,
|
|
52
|
+
"verify": {
|
|
53
|
+
"enabled": true,
|
|
54
|
+
"tools": []
|
|
55
|
+
}
|
|
56
|
+
}
|