the-high-council 0.7.9 → 0.8.1
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/README.md +272 -31
- package/TROUBLESHOOTING.md +2 -2
- package/chains/advise-premium.json +145 -0
- package/chains/advise-single-astra.json +44 -0
- package/chains/advise-single-deepseek.json +44 -0
- package/chains/advise-single-gemini.json +44 -0
- package/chains/advise-single-opus.json +44 -0
- package/chains/advise-single.json +44 -0
- package/chains/advise-standard.json +86 -0
- package/chains/cheap-7-v2.json +65 -14
- package/chains/cheap-7.json +68 -13
- package/chains/cheap.json +22 -4
- package/chains/coder-gate-v1.json +23 -5
- package/chains/coder-gate-v2.json +20 -4
- package/chains/eu-only.json +22 -4
- package/chains/gp-judge-v1.json +29 -24
- package/chains/idea-open-c2.json +18 -13
- package/chains/local-ollama.json +1 -0
- package/chains/mock-advise-deep.json +52 -0
- package/chains/mock-advise-quick.json +37 -0
- package/chains/mock-advise-single.json +27 -0
- package/chains/mock-advise-standard.json +47 -0
- package/chains/plan-auto-mistral.json +48 -18
- package/chains/plan-auto.json +34 -29
- package/chains/plan-cheap.json +16 -13
- package/chains/plan-daily-7.json +125 -14
- package/chains/plan-debate-c2.json +18 -13
- package/chains/plan-debate-open-c2.json +18 -13
- package/chains/plan-debate-roles-c1.json +17 -12
- package/chains/plan-debate.json +31 -26
- package/chains/plan-fast.json +11 -11
- package/chains/plan-highest-7.json +152 -15
- package/chains/plan-open-7.json +39 -9
- package/chains/plan-premium-7.json +33 -2
- package/chains/plan-proposals-best-of-5.json +20 -17
- package/chains/plan-proposals.json +20 -17
- package/chains/plan-relay.json +16 -13
- package/chains/plan-thorough.json +16 -13
- package/chains/plan-two-strong.json +45 -9
- package/chains/plan-unanimous.json +16 -13
- package/chains/security-review-only.json +29 -0
- package/chains/seven-cheap.json +30 -9
- package/chains/seven.json +32 -6
- package/chains/single-vendor-anthropic.json +31 -5
- package/chains/single-vendor-openai.json +20 -5
- package/chains/smo-v2-cheap.json +27 -9
- package/chains/smo.json +27 -5
- package/chains/us-only.json +26 -5
- package/chains/verify.json +26 -5
- package/package.json +4 -2
- package/schemas/gate-ledger-v1.json +41 -0
- package/schemas/gate-v1.json +46 -0
- package/schemas/report-v1.json +205 -8
- package/src/advice-brief.js +128 -0
- package/src/advice-guards.js +266 -0
- package/src/advice-mask.js +89 -0
- package/src/advice-retention.json +207 -0
- package/src/advice-run.js +187 -0
- package/src/advice-stop.js +37 -0
- package/src/advice-tier.js +140 -0
- package/src/advise-rate.js +53 -0
- package/src/advise.js +446 -0
- package/src/api.js +4 -0
- package/src/audit.js +9 -2
- package/src/cache-integrity.js +9 -1
- package/src/chain-lint.js +134 -2
- package/src/chain.js +296 -163
- package/src/cli.js +587 -51
- package/src/cost.js +104 -26
- package/src/criteria-ledger.js +38 -0
- package/src/criteria-lints.js +51 -0
- package/src/criteria-lock.js +142 -0
- package/src/decision-records.js +54 -0
- package/src/denied-models.js +11 -1
- package/src/draft-disputes.js +83 -0
- package/src/dry-run.js +96 -0
- package/src/env-file.js +31 -0
- package/src/gate-cli.js +149 -0
- package/src/gate-ledger.js +189 -0
- package/src/gate.js +367 -0
- package/src/handoff-from-run.js +114 -0
- package/src/key-env.js +39 -0
- package/src/mcp/advice.js +322 -0
- package/src/mcp/server.js +147 -53
- package/src/mcp/untrusted.js +89 -0
- package/src/metrics.js +6 -1
- package/src/outbound-scan.js +3 -2
- package/src/outcome.js +5 -0
- package/src/pii-gate.js +6 -1
- package/src/pricing.json +36 -18
- package/src/providers.js +128 -12
- package/src/reasoning-table.json +646 -0
- package/src/reasoning.js +249 -0
- package/src/report-shape.js +50 -5
- package/src/resume-brief.js +2 -0
- package/src/return-path.js +115 -0
- package/src/roles.js +154 -0
- package/src/run-budget.js +31 -0
- package/src/run-lock.js +23 -9
- package/src/run-status.js +100 -2
- package/src/scope-freeze.js +52 -3
- package/src/secret-patterns.js +7 -5
- package/src/security-review.js +8 -5
- package/src/send-path-refusals.js +143 -0
- package/src/send-path.js +363 -0
- package/src/send-profiles.js +101 -0
- package/src/spend.js +37 -7
- package/src/stage-contract.js +6 -3
- package/src/stop-files.js +79 -0
- package/src/superseded.js +17 -0
- package/src/text-fence.js +9 -0
- package/src/ui/app.js +12 -3
- package/src/ui/guard.js +94 -0
- package/src/ui/server.js +22 -11
- package/src/ui/style.css +2 -0
- package/src/verdict-stats.js +5 -1
package/README.md
CHANGED
|
@@ -40,13 +40,14 @@ Three commands from nothing to a priced run of your own idea (no key needed unti
|
|
|
40
40
|
|
|
41
41
|
| Chain | Who does what | Needs | Worst case |
|
|
42
42
|
|---|---|---|---|
|
|
43
|
-
| `cheap-7-v2` | Claude Sonnet 5 writes the plan; low-cost models from seven other labs review it, and all seven must sign off. Up to 7 rounds. | one OpenRouter key | $
|
|
44
|
-
| `plan-premium-7` | A Claude Code session writes the plan; a seven-lab panel of larger models (GPT-6 Astra, Claude Fable 5.1, Gemini 3.8 Flash, Muse Spark 1.2, Qwen 3.8 Max, DeepSeek V4 Pro, GLM-5.3) proposes, debates and reviews. | OpenRouter key + a Claude Code session | $
|
|
45
|
-
| `plan-highest-7` | Seven low-cost models propose and debate; four top models write whole architectures and are the only reviewers; one deep-dive seat checks the first draft against the task. **Untested with real models.** | OpenRouter key + a Claude Code session | $
|
|
43
|
+
| `cheap-7-v2` | Claude Sonnet 5 writes the plan; low-cost models from seven other labs review it, and all seven must sign off. Up to 7 rounds. | one OpenRouter key | $11.22 |
|
|
44
|
+
| `plan-premium-7` | A Claude Code session writes the plan; a seven-lab panel of larger models (GPT-6 Astra, Claude Fable 5.1, Gemini 3.8 Flash, Muse Spark 1.2, Qwen 3.8 Max, DeepSeek V4 Pro, GLM-5.3) proposes, debates and reviews. | OpenRouter key + a Claude Code session | $36.75 |
|
|
45
|
+
| `plan-highest-7` | Seven low-cost models propose and debate; four top models write whole architectures and are the only reviewers; one deep-dive seat checks the first draft against the task. **Untested with real models.** | OpenRouter key + a Claude Code session | $17.34 |
|
|
46
46
|
| `local-ollama` | Every seat on your own machine, through Ollama. | Ollama and the models pulled | $0 |
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
All three cost more than the default cap at their worst case, so give them a `--max-usd` at or above
|
|
49
|
+
their dry-run price (since 0.8.1 a proposal may use a seat's whole output allowance and every shipped seat reasons at
|
|
50
|
+
high, which raised the worst cases; a run that signs off early costs far less). The writer seats of `plan-premium-7` and `plan-highest-7` are [external](#quick-start-mcp): the run pauses
|
|
50
51
|
and a Claude Code session (or you) writes that stage, at no API cost. Nothing about any chain's
|
|
51
52
|
output quality has been measured.
|
|
52
53
|
|
|
@@ -90,11 +91,12 @@ before anything is spent.
|
|
|
90
91
|
it without:
|
|
91
92
|
|
|
92
93
|
npx the-high-council --task tasks/my-first-task.md --chain cheap-7-v2 --dry-run
|
|
93
|
-
npx the-high-council --task tasks/my-first-task.md --chain cheap-7-v2
|
|
94
|
+
npx the-high-council --task tasks/my-first-task.md --chain cheap-7-v2 --max-usd 11.23
|
|
94
95
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
`cheap-7-v2`'s worst case ($11.22) is above the default cap, so the run command carries its own
|
|
97
|
+
cap, set just above that price. Every run stops before it would pass its spend cap ($7 unless
|
|
98
|
+
you set `--max-usd`). A run stopped by the cap keeps what it paid for but has no plan yet, so pick
|
|
99
|
+
a cap at or above the dry run's price. A panel that signs off early costs less than the worst case.
|
|
98
100
|
|
|
99
101
|
The plan lands in `runs/<time>/deliverable.md`; the argument behind it is in `BOARD.md`.
|
|
100
102
|
|
|
@@ -128,7 +130,7 @@ Everywhere below, `council` means `npx the-high-council` unless you installed it
|
|
|
128
130
|
- **Handoff** - `HANDOFF.md`, the build instructions a coding agent works from.
|
|
129
131
|
|
|
130
132
|
**A visual write-up of all of this, built around one real run, is at
|
|
131
|
-
[sower-industries.de/
|
|
133
|
+
[sower-industries.de/en/THC/](https://sower-industries.de/en/THC/).** What changed in each release:
|
|
132
134
|
[CHANGELOG.md](CHANGELOG.md).
|
|
133
135
|
|
|
134
136
|
## How it works
|
|
@@ -148,7 +150,11 @@ A run moves through fixed stages. Which stages fire depends on the chain you pic
|
|
|
148
150
|
7. **Panel review** - every critic independently grades the draft against the acceptance criteria,
|
|
149
151
|
blind. Not unanimous? It revises against the union of every objection and the panel reviews
|
|
150
152
|
again, up to the chain's round cap.
|
|
151
|
-
8. **Handoff** - a `HANDOFF.md` written for whoever executes the result.
|
|
153
|
+
8. **Handoff** - a `HANDOFF.md` written for whoever executes the result. It ends with a block the
|
|
154
|
+
harness writes, not a model: the acceptance criteria the run settled, how each checkable one is
|
|
155
|
+
checked, and a fingerprint for each of the two. `council check-lock HANDOFF.md` ($0) says whether a
|
|
156
|
+
copy still carries them; it catches an edit or
|
|
157
|
+
a slip, and is not a signature.
|
|
152
158
|
|
|
153
159
|
Some chains add optional stages to this: whole alternative architectures written blind before
|
|
154
160
|
the skeleton, a deep-dive check of the first draft, a dispute stage that records unresolved
|
|
@@ -157,6 +163,12 @@ objections at the top of the plan, and a final security review.
|
|
|
157
163
|
Every run writes a folder: the deliverable, `BOARD.md` (the full debate - every post, every
|
|
158
164
|
withdrawal), `HANDOFF.md`, a per-lab scoreboard, and the real token/cost accounting.
|
|
159
165
|
|
|
166
|
+
A run that stopped before it wrote its handoff (the spend cap, an abandoned pause, a crash) can get one from
|
|
167
|
+
its latest draft: `council handoff --from-run runs/<id>`. It is one call on the chain's handoff seat, under the
|
|
168
|
+
run's own spend cap (what the folder already cost counts toward it; `--max-usd N` is a total, as on `--resume`),
|
|
169
|
+
the same policy check and key scan as a run, and a run no panel signed off gets a note at the top, written by
|
|
170
|
+
the harness, saying so. It never overwrites an existing `HANDOFF.md`.
|
|
171
|
+
|
|
160
172
|
### Reading a run with a program
|
|
161
173
|
|
|
162
174
|
`BOARD.md` is for people. **`report.json` is the same board, structured** - if you are building
|
|
@@ -276,8 +288,8 @@ ones. Put only the keys your chosen chain needs in that `.env`, one `NAME=value`
|
|
|
276
288
|
`DEEPSEEK_API_KEY` · `GROQ_API_KEY` · `TOGETHER_API_KEY` · `COHERE_API_KEY` ·
|
|
277
289
|
`OPENROUTER_API_KEY` · `ZAI_API_KEY`
|
|
278
290
|
|
|
279
|
-
xAI/Grok is never seated, and neither is a router id (`openrouter/auto`, the Pareto Code router
|
|
280
|
-
that could route to it: chain-lint refuses such a chain and the run itself refuses such a seat,
|
|
291
|
+
xAI/Grok is never seated, and neither is a router id (`openrouter/auto`, the Pareto Code router,
|
|
292
|
+
any other `openrouter/<name>` id) that could route to it: chain-lint refuses such a chain and the run itself refuses such a seat,
|
|
281
293
|
with no override. There is no `xai` provider. Kimi/Moonshot models are not in any chain this
|
|
282
294
|
package ships, but you may seat one in a chain of your own.
|
|
283
295
|
|
|
@@ -288,7 +300,8 @@ A keyed seat sends its key only to its own provider's https API. A chain that po
|
|
|
288
300
|
seat's `baseUrl` anywhere else is refused before any call (see
|
|
289
301
|
[Local models](#local-models-ollama-lm-studio-)).
|
|
290
302
|
|
|
291
|
-
Other settings, all optional, read from the environment or `.env
|
|
303
|
+
Other settings, all optional, read from the environment or `.env` (except `COUNCIL_ADVICE_SENSITIVITY_FLOOR` and
|
|
304
|
+
`COUNCIL_ADVICE_CHAINS_DIR`, which only the server's own environment sets: a project's `.env` is something an agent can write):
|
|
292
305
|
|
|
293
306
|
| Variable | What it does |
|
|
294
307
|
|---|---|
|
|
@@ -423,13 +436,14 @@ Each outcome has its own code, so a script or CI job can branch on it:
|
|
|
423
436
|
| 11 | Something in the input must not be sent: a prompt matches one of the key formats listed in `src/secret-patterns.js` (checked by default; `--allow-secret-shaped` overrides), or, under `--pii-gate hard-stop`, a PII shape. |
|
|
424
437
|
| 12 | `policy.json` refused the chain. |
|
|
425
438
|
| 13 | Another process is already running this run folder. |
|
|
426
|
-
| 14 | The task file changed since the run started and `AMENDMENTS.md` does not cover it. |
|
|
439
|
+
| 14 | The task file, or (since 0.8.0) a `--context` document, changed since the run started and `AMENDMENTS.md` does not cover it. The message prints the hashes to write; a context hash is written `ctx-<hash>`. |
|
|
427
440
|
| 15 | `--resume` of a run that already finished (it has a `report.json`); nothing is run or spent. |
|
|
428
441
|
| 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. |
|
|
429
442
|
| 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`). |
|
|
443
|
+
| 18 | An advice call was stopped before finishing: by a person (`council stop runs/<id>`), by the MCP client that cancelled the call or went away, or by its own wall-clock ceiling (`advise.max_wall_ms`). Calls already in flight finish and are recorded (a wall-clock stop cuts a call still running at the deadline, recorded as not answering); nothing new starts. It writes `report-partial.json` (`stoppedBy`: `user`, `client_cancel` or `wall_clock`; the answers that were paid for under `advise`), `BOARD-partial.md` when anything was paid for, and `STOPPED-<stoppedBy>.json`. An advice call is not resumed: ask again. |
|
|
430
444
|
|
|
431
445
|
Codes 9-17 were split out or added on 2026-09-23. Before that, several of these outcomes shared a code (2, 5,
|
|
432
|
-
6 or 1).
|
|
446
|
+
6 or 1). Code 18 came with the advice tools.
|
|
433
447
|
|
|
434
448
|
### Telling the council what your build session can actually use
|
|
435
449
|
|
|
@@ -507,10 +521,12 @@ council --task tasks/your-idea.md --chain mock-budget --max-usd 1
|
|
|
507
521
|
```
|
|
508
522
|
|
|
509
523
|
If a chain pauses for your input, it writes `NEEDS-<stage>.md` into the run folder and tells you
|
|
510
|
-
how to resume
|
|
524
|
+
how to resume. The run resumes as soon as the answer file exists, so write it under a `.partial`
|
|
525
|
+
name and rename it when it is complete:
|
|
511
526
|
|
|
512
527
|
```bash
|
|
513
|
-
# write your answer to runs/<id>/answers.md, then:
|
|
528
|
+
# write your answer to runs/<id>/answers.md.partial, then:
|
|
529
|
+
mv runs/<id>/answers.md.partial runs/<id>/answers.md
|
|
514
530
|
council --resume runs/<id>
|
|
515
531
|
```
|
|
516
532
|
|
|
@@ -549,6 +565,12 @@ up in `claude mcp list` as `plugin:the-high-council:high-council`. Remove it wit
|
|
|
549
565
|
local clone instead (`claude plugin marketplace add /path/to/clone`), the server runs from the
|
|
550
566
|
clone itself, so run `npm install` in it first.
|
|
551
567
|
|
|
568
|
+
Your provider keys can go into the plugin's settings dialog (`/plugin`, then the plugin's settings): one
|
|
569
|
+
optional field per lab, marked sensitive, so Claude Code keeps it in the OS keychain. Leave a field empty and
|
|
570
|
+
the key from your environment or a `.env` file in your project is used instead; a key in the dialog is used
|
|
571
|
+
first. The plugin passes each dialog value under its own name (`COUNCIL_PLUGIN_<LAB>_API_KEY`), so an empty
|
|
572
|
+
field never replaces a key you exported yourself.
|
|
573
|
+
|
|
552
574
|
**Claude Desktop:** download `the-high-council-<version>.mcpb` from the
|
|
553
575
|
[GitHub Releases](https://github.com/muad-yasin/the-high-council-mcp/releases) page (its SHA-256
|
|
554
576
|
is next to it) and open it. Claude Desktop shows a settings form: a council folder for tasks and
|
|
@@ -565,9 +587,10 @@ Continue): [docs/mcp-clients.md](docs/mcp-clients.md) has the real config for ea
|
|
|
565
587
|
|
|
566
588
|
Whichever way you add it, the server reads and writes in **your** working directory, not inside
|
|
567
589
|
the package: `.env` for keys, `tasks/` for requests, `runs/` for output, and a `chains/` of your
|
|
568
|
-
own takes precedence over the bundled ones
|
|
590
|
+
own takes precedence over the bundled ones (not for advice chains: see
|
|
591
|
+
[Asking other labs for advice](#asking-other-labs-for-advice-council_quote-council_advise-experimental)). In a git project, add `.env` (and `runs/` if your
|
|
569
592
|
ideas are private) to `.gitignore` before an agent commits everything; `council doctor` warns
|
|
570
|
-
when `.env` is not ignored.
|
|
593
|
+
when `.env` is not ignored. An advice call also leaves `council-<id>.log` and a `.council-advice-lock/` folder in the working folder: ignore those too.
|
|
571
594
|
|
|
572
595
|
The server only works inside that directory. `dry_run` and `start_run` take a chain by name.
|
|
573
596
|
Every path `start_run` is given (`task`, `draft`, `context`, `from_run`, and each file inside a
|
|
@@ -601,6 +624,100 @@ Then drive it with these tools:
|
|
|
601
624
|
| `read_run_file` | Read any file from a run folder (`report-partial.json` for a run the cap stopped) |
|
|
602
625
|
| `list_runs` | Past runs |
|
|
603
626
|
| `plan_outline` | Section tree of a run's deliverable (or a `.md` file in the working directory) with word counts |
|
|
627
|
+
| `council_quote` | Experimental. Preview and price a request for advice from other labs: who would receive the text, its exact size and `sha256` after masking, the worst-case and expected price, a `quote_id`. Sends and spends nothing. See [Asking other labs for advice](#asking-other-labs-for-advice-council_quote-council_advise-experimental) |
|
|
628
|
+
| `council_advise` | Experimental. Spends. Asks other labs for advice on one decision, once you approve it: a leaning and every dissent in the models' own words. `start_run` and `resume_run` refuse advice chains, so this is the only way in over MCP |
|
|
629
|
+
|
|
630
|
+
**Text from a run comes back marked as model-written.** A deliverable, a board, a log line or an
|
|
631
|
+
advisor's answer was written by AI models, and a model can be fooled into writing instructions aimed
|
|
632
|
+
at the agent that reads it. So `read_run_file` (and `run_status` with `brief: true`) returns the text
|
|
633
|
+
between a notice written by the server and markers whose id changes on every call, with Unicode tag
|
|
634
|
+
characters, bidi controls and zero-width characters removed and counted; JSON answers that carry such text name those fields
|
|
635
|
+
in `untrusted_fields`. Which tool returns what is one table in `src/mcp/untrusted.js`, and a tool
|
|
636
|
+
missing from it is refused when the server starts. This is a label, not a filter: it does not make
|
|
637
|
+
hostile text harmless, and the file on disk is unchanged.
|
|
638
|
+
|
|
639
|
+
### Asking other labs for advice (`council_quote`, `council_advise`; experimental)
|
|
640
|
+
|
|
641
|
+
Two more tools let a coding agent, when you ask it to, put **one decision** to models from other
|
|
642
|
+
labs and read back a **leaning**, every dissent in the models' own words, and what each would need
|
|
643
|
+
to see to change its answer. It is advice from other models, never an instruction, and it comes
|
|
644
|
+
**in addition to** whatever model is already the caller: the default seat is not Anthropic's.
|
|
645
|
+
Nothing has been measured that shows it improves what an agent does; it is an instrument, and each
|
|
646
|
+
call leaves a small record (`advise-log.json`) you can rate later with
|
|
647
|
+
`council advise-rate runs/<id> useful|not-useful|unclear [note]` (the only supported way to write the
|
|
648
|
+
rating: a typo in a hand edit of that file makes every later advice call refuse).
|
|
649
|
+
|
|
650
|
+
- **`council_quote`** sends nothing and spends nothing. The agent writes a short structured
|
|
651
|
+
**brief** (at most 48,000 characters, about 12,000 tokens, all together; over the limit is refused, never cut; no
|
|
652
|
+
transcript, tool output, environment or file listing). The quote scans the whole text for key
|
|
653
|
+
shapes, masks emails, IBANs, cards, IPs, internal hostnames and home paths (reversibly: the
|
|
654
|
+
mapping stays in memory), and returns a **send preview**: who receives it (lab, model, the
|
|
655
|
+
endpoint's retention wording), the exact size and `sha256` of the text, the worst-case and
|
|
656
|
+
expected price, and a `quote_id` valid for ten minutes. The text itself goes to you, not back to the agent:
|
|
657
|
+
you read all of it in the approval step.
|
|
658
|
+
- **`council_advise`** spends, and only after **you** approved the exact text. It needs the quote id
|
|
659
|
+
and the hash. It writes the run folder first (`runs/<id>/advice-brief.md`, the masked text, and a
|
|
660
|
+
pending approval, a "gate"), then asks you: in your client, if it can show you a dialog (MCP
|
|
661
|
+
elicitation: the price, the hash, the seats and the whole text), or at a terminal with
|
|
662
|
+
`council gate answer runs/<id> g1`, which prints the same and asks y/N. Until you answer, the call
|
|
663
|
+
returns `awaiting_approval` with that command; the agent sends the same quote again once you have.
|
|
664
|
+
The run starts only on an approved gate, and one approval covers one send. Nothing else approves a
|
|
665
|
+
call an agent asked for: no setting, no flag, no tool argument (the 0.8.0 `COUNCIL_ADVISE_APPROVAL=host`
|
|
666
|
+
statement is gone, and a server that still has it set refuses to start). The run is held to the seats and
|
|
667
|
+
the ceiling the gate showed you, whatever else is in the folder. Running an advice chain yourself at your
|
|
668
|
+
own terminal (`council --chain advise-single --task brief.md`) is your own call and has no gate; its
|
|
669
|
+
record says so (`gate: null` in `advise-log.json`). The terminal check is friction, not proof
|
|
670
|
+
that a person answered: a program can open a pseudo-terminal. Advice calls therefore need a person
|
|
671
|
+
at the keyboard; scripted or unattended use is not supported. `mode: "single"` asks one seat (default GPT-6.1 Sol through OpenRouter; the
|
|
672
|
+
`advisor` argument picks another); `mode: "council"` asks three labs (OpenAI GPT-6.1 Sol, Z.ai GLM-5.3, Google Gemini 3.8 Flash)
|
|
673
|
+
blind, lets them read each other once, and a seat changes its answer only by quoting an argument.
|
|
674
|
+
The call holds for up to `wait_seconds` (default 25, at most 30, the same for every client), your approval included;
|
|
675
|
+
a run that outlives the hold returns its id, and `run_status(run, wait_seconds: 25, until: "settled")` (also at most
|
|
676
|
+
30) returns the answer. Use the default: a client that gives up on a call cancels it, and a cancel stops the run.
|
|
677
|
+
- **Limits, meant to be set by you in the server's environment and not by the agent** (a project `.env` can still set them: see Known limits):
|
|
678
|
+
`COUNCIL_ADVISE_MAX_USD_PER_CALL` ($1.50, compared with the call's ceiling, the most it can spend), `..._PER_SESSION` ($3), `..._PER_DAY` ($10),
|
|
679
|
+
`COUNCIL_ADVISE_CALLS_PER_SESSION` (3), `..._CALLS_PER_DAY` (8), `COUNCIL_ADVISE_COOLDOWN_MS`
|
|
680
|
+
(two minutes). A question asked again needs `new_evidence` in the brief; an answer with
|
|
681
|
+
dissent needs an accept, reject or defer, with a reason, for each dissent before the next call.
|
|
682
|
+
Every refusal says that nothing was spent and what to do next.
|
|
683
|
+
- **What may be sent** starts from the floor you set in the server's settings,
|
|
684
|
+
`COUNCIL_ADVICE_SENSITIVITY_FLOOR` (`public`, `internal`, `confidential`; default `internal`). A
|
|
685
|
+
project's `policy.json` may raise it with `advice_sensitivity_floor` and can never lower it, since
|
|
686
|
+
the project folder is something the agent can write. The brief's own label can only tighten it:
|
|
687
|
+
a missing or `unknown` label counts as `confidential`, `personal_data` and `secret_adjacent` are
|
|
688
|
+
never sent, a `confidential` brief goes to one seat and never to a council, and a model that has
|
|
689
|
+
no endpoint OpenRouter tags zero-data-retention is reachable only for `public` material. The label
|
|
690
|
+
is the agent's word, so the approval text tells you what the text is treated as and who set each
|
|
691
|
+
part (your floor, the project's policy, the agent's label): you are the check on it.
|
|
692
|
+
- **Your own chain, or a $0 trial.** `COUNCIL_ADVISE_CHAIN_SINGLE` and `COUNCIL_ADVISE_CHAIN_COUNCIL` point a
|
|
693
|
+
mode at an advise chain by name. An advice chain is read from the package's own `chains/` or from one
|
|
694
|
+
folder you name in `COUNCIL_ADVICE_CHAINS_DIR` (an absolute path outside the project; anything else stops
|
|
695
|
+
the server), and never from the project's `chains/`: a repository's chain file would otherwise choose who
|
|
696
|
+
receives the text. Your chain must pass the same checks: priced seats, not denied, zero-retention routing
|
|
697
|
+
where the model has it, a wall clock. `COUNCIL_ADVISE_MOCK=1` runs the mock chains, so the whole exchange
|
|
698
|
+
can be tried with no key and no money.
|
|
699
|
+
- **When an advisor asks for more.** An answer can list what was missing from the brief. That list is model
|
|
700
|
+
text, shown to the agent as untrusted, and the next call does not go out on the agent's say-so: its
|
|
701
|
+
approval text starts with "This call follows an advisor's request for more material", so you see that
|
|
702
|
+
the new text answers a model's request, and decide whether that material should leave your machine.
|
|
703
|
+
- **Stopping.** A client that cancels the call or goes away, `council stop runs/<id>` at your
|
|
704
|
+
terminal, or the chain's own wall-clock ceiling (`advise.max_wall_ms`) stops the run before its
|
|
705
|
+
next paid step: calls already in flight finish and are billed (the wall clock cuts a call still
|
|
706
|
+
running at its deadline, which may still be billed), the run exits 18, and the answers
|
|
707
|
+
that were paid for are kept in `report-partial.json`, which `run_status` hands back. A stopped call
|
|
708
|
+
is not resumed; ask again.
|
|
709
|
+
|
|
710
|
+
What this does **not** do, stated plainly: "ZDR" in the preview is OpenRouter's routing tag for an
|
|
711
|
+
endpoint, not a guarantee about what that host does with your text, and the retention table
|
|
712
|
+
(`src/advice-retention.json`) is a dated snapshot (read on 2026-09-30; the preview prints its date and
|
|
713
|
+
says when it is more than 30 days old). No scanner catches names, addresses, phone
|
|
714
|
+
numbers or passwords written as prose: read the text the server shows you. The limits above bind
|
|
715
|
+
these two tools and `start_run` / `resume_run` for advice chains, which refuse them; they do not
|
|
716
|
+
bind a shell that runs `council` itself, and the ledger they read is in your working folder.
|
|
717
|
+
Headless use is refused by design: with no dialog and no person at a terminal the call returns
|
|
718
|
+
`awaiting_approval` and nothing runs (Claude Code in `-p` or CI mode included). The
|
|
719
|
+
models see only the brief: nothing is run or checked. A call takes seconds (one seat) or minutes (a
|
|
720
|
+
council) and costs real money: see the price in the quote, in your own units.
|
|
604
721
|
|
|
605
722
|
**External vs. API-backed seats.** `{ "provider": "external" }` pauses a run at that seat so a
|
|
606
723
|
Claude Code session on a flat-rate subscription plays it - free at the point of use, since the
|
|
@@ -613,7 +730,7 @@ for anyone with a subscription, since the project's cost story depends on it.
|
|
|
613
730
|
|
|
614
731
|
## Chains
|
|
615
732
|
|
|
616
|
-
|
|
733
|
+
64 chain configs live in `chains/`. Each one is plain JSON - the seat roster, which models fill
|
|
617
734
|
which seat, the round cap, and whether proposals/debate/handoff stages run. They are meant to be
|
|
618
735
|
copied and edited.
|
|
619
736
|
|
|
@@ -628,7 +745,9 @@ in the table at the top. A few more worth knowing:
|
|
|
628
745
|
Claude Opus 5.5 on your Claude subscription (an external seat), GPT-6 Luna and DeepSeek V4 Pro
|
|
629
746
|
write the architectures and alone vote; seven low-cost labs propose and debate. Two Claude Code
|
|
630
747
|
sessions answer its external seats: Opus 5.5 every stage whose label contains `opus5.5-sub`
|
|
631
|
-
(including `-retry` and `-reask1`/`-reask2` forms), Sonnet 5 the writer stages. $
|
|
748
|
+
(including `-retry` and `-reask1`/`-reask2` forms), Sonnet 5 the writer stages. $5.70 worst case
|
|
749
|
+
(0.8.1 dry run at the prices of 2026-10-06; $5.08 at the earlier prices, $4.88 before every seat reasoned at high, $1.90 before proposals could use a
|
|
750
|
+
seat's whole output allowance).
|
|
632
751
|
**Run once with real models (2026-09-28); nothing about it has been measured.**
|
|
633
752
|
- **`cheap`** - small models throughout. For testing the harness itself, not for real work.
|
|
634
753
|
- **`plan-debate`** - five labs propose blind, debate each other's proposals anonymised, then a
|
|
@@ -640,6 +759,36 @@ in the table at the top. A few more worth knowing:
|
|
|
640
759
|
|
|
641
760
|
Read a chain's `description` field before running it; they say what they cost you in calls.
|
|
642
761
|
|
|
762
|
+
### Reasoning effort
|
|
763
|
+
|
|
764
|
+
Every seat in a shipped chain is set to `high` where its model has a setting for it, and no code
|
|
765
|
+
path lowers it. What "high" means depends on the model, so `src/reasoning-table.json` lists,
|
|
766
|
+
per model, the request field that sets it (Anthropic `output_config.effort`, OpenRouter
|
|
767
|
+
`reasoning.effort`, OpenAI and Google `reasoning_effort`, Z.ai `thinking`, Together's Qwen chat
|
|
768
|
+
template), the model's own default effort and its largest reply. Each row carries the document it was
|
|
769
|
+
read from and a date. `chain-lint` refuses a shipped chain whose seat is set below high (a reasoning
|
|
770
|
+
setting that is off, low, medium, minimal, a smaller token budget, or hidden). That rule binds the
|
|
771
|
+
chains in this package only: a chain of your own is not refused, and a setting you write in your own
|
|
772
|
+
chain is sent as written. In your own chain, a seat with no reasoning setting gets the high default
|
|
773
|
+
for any model the table has a field for.
|
|
774
|
+
|
|
775
|
+
- **Models that default above high.** GLM-5.3, GLM-5.3 Flash and Qwen3.8 Max run at `max` or `xhigh`
|
|
776
|
+
unless told otherwise, so sending "high" would be a lower effort. They are sent nothing and run at
|
|
777
|
+
their own default.
|
|
778
|
+
- **Claude Haiku 4.5** has no effort levels. Its "high" is thinking on with a token budget of half the
|
|
779
|
+
seat's output cap (at least 1,024), and the cap carries the budget on top of the room the answer had.
|
|
780
|
+
- **A reply that spent its whole cap thinking** is retried once with the same request and a bigger cap
|
|
781
|
+
(double, up to the model's own maximum and what its connection can return). At that limit it is not
|
|
782
|
+
retried; the seat is recorded as `no answer: thinking used the whole cap` (the `no_answer` field of
|
|
783
|
+
that seat's entry in `panelVerdicts`) and is unheard, never a pass. Until 0.8.0 the retry turned
|
|
784
|
+
thinking off.
|
|
785
|
+
- **Models the table has no field for** (for example Cohere, Groq, Mistral Large, the models on Together
|
|
786
|
+
other than Qwen3.5-9B and DeepSeek V4 Flash, local Ollama models) are sent nothing. DeepSeek V4 Flash on
|
|
787
|
+
Together is sent the chat-template switch vLLM documents for it; Together's own page for it was not found.
|
|
788
|
+
- **`gp-judge-v1`** now runs its Sonnet and Qwen seats with reasoning on (it ran with it off). Scores
|
|
789
|
+
from this version on come from the high-effort judge, so earlier and later GP scores are not
|
|
790
|
+
directly comparable.
|
|
791
|
+
|
|
643
792
|
### Optional chain-config fields
|
|
644
793
|
|
|
645
794
|
- **`schemaVersion`** - an integer, optional. `council doctor` warns (never fails) when a chain
|
|
@@ -683,9 +832,10 @@ The parts worth knowing, because they explain why the code looks the way it does
|
|
|
683
832
|
**Almost every defensive branch here is a headstone.** `parseJson` in `chain.js` repairs two
|
|
684
833
|
specific malformations — an unescaped `"` inside a markdown-quoted span, and raw newlines inside
|
|
685
834
|
string values — because three consecutive real runs died on the first one and silently logged a
|
|
686
|
-
pass that never happened. The comments name the run id and the date. The retry
|
|
687
|
-
thinking exists because an Anthropic seat burned its entire
|
|
688
|
-
|
|
835
|
+
pass that never happened. The comments name the run id and the date. The retry after a
|
|
836
|
+
reply that spent its whole budget thinking exists because an Anthropic seat burned its entire
|
|
837
|
+
`maxTokens` budget thinking and returned nothing; until 0.8.0 it switched thinking off, and since
|
|
838
|
+
0.8.1 it keeps the same effort and raises the cap. The `ROSTER SHRANK` warning exists because a lab can return nothing and vanish
|
|
689
839
|
from the scoreboard without saying so. None of these were designed in advance; each one is a day
|
|
690
840
|
that went wrong.
|
|
691
841
|
|
|
@@ -712,7 +862,10 @@ it - usable in any project, with or without the harness, and needing no API key:
|
|
|
712
862
|
`context-and-handoff`, `tool-and-action-discipline` - the work around the work, for any agent
|
|
713
863
|
task, including setups where several models propose, critique, and hand off to each other.
|
|
714
864
|
- **Building software:** `backend-developer`, `frontend-developer`, `ux-design`, `visual-craft`.
|
|
715
|
-
- **
|
|
865
|
+
- **Game development:** `proof-discipline`, `game-verification`, `open-world-streaming`,
|
|
866
|
+
`engine-editor-driving`, `dcc-agent-authoring` - verification, streaming, editor and Blender work
|
|
867
|
+
for games.
|
|
868
|
+
- **Writing:** `drafting`, `fact-checking`, `line-editing`, `final-read`, `good-news-writing`.
|
|
716
869
|
|
|
717
870
|
The full catalog, with when to use each and what it guards against, is
|
|
718
871
|
[`skills/README.md`](skills/README.md); a shareable presentation page is `docs/skills.html`. Both
|
|
@@ -724,9 +877,12 @@ what each rule guards against and why. Copy the folders you want into your proje
|
|
|
724
877
|
## Known limits, stated plainly
|
|
725
878
|
|
|
726
879
|
- The spend cap is enforced against a **worst case**, not a prediction: the whole prompt billed as
|
|
727
|
-
input plus the seat's entire `maxTokens` budget billed as output (
|
|
728
|
-
|
|
880
|
+
input plus the seat's entire `maxTokens` budget billed as output (for Anthropic seats, plus the
|
|
881
|
+
bigger cap of the one retry they may make). Real stages almost never cost that much, so a run can stop with headroom
|
|
729
882
|
left. That is the intended trade - resume it with a higher ceiling.
|
|
883
|
+
- The dry run (`--dry-run`, MCP `dry_run`) prices the task alone and does not read `--context`
|
|
884
|
+
documents, so for a run with context its estimate is too low. The spend cap is not affected: it
|
|
885
|
+
checks every real prompt, context included, before each call.
|
|
730
886
|
- A seat whose model has no entry in `src/pricing.json` is **unpriced, and therefore uncapped**.
|
|
731
887
|
It contributes $0 to the running total no matter what it really costs. Check `dry_run` output
|
|
732
888
|
for `unpriced` before trusting a ceiling. `ollama` seats are the one deliberate exception: they
|
|
@@ -735,18 +891,36 @@ what each rule guards against and why. Copy the folders you want into your proje
|
|
|
735
891
|
- A call that fails **after** it reached the provider - the connection drops while a 200 reply is
|
|
736
892
|
being read, a 200 carries a body that is not JSON, or the request times out waiting for headers -
|
|
737
893
|
is not retried, because the generation was probably already billed. Its real usage cannot be
|
|
738
|
-
read, so it is counted toward the per-run cap at its worst-case projection
|
|
739
|
-
|
|
894
|
+
read, so it is counted toward the per-run cap at its worst-case projection, and recorded as
|
|
895
|
+
`superseded/<label>.charge-<n>.usage.json`, which `council --spend` and a resume count.
|
|
740
896
|
- Some hosted reasoning models stop at a provider-side reasoning ceiling well below the seat's own
|
|
741
897
|
cap, before writing any answer (seen 2026-09-23: `deepseek/deepseek-v4.1-flash` via OpenRouter, 6 of
|
|
742
898
|
28 calls stopped at ~4.2k tokens, all reasoning, under a 36k cap). A bigger cap cannot fix that, so
|
|
743
899
|
such a reply is recorded as `REASONING_EXHAUSTED` and is not retried: the seat abstains, which
|
|
744
900
|
blocks unanimity and never counts as consent. Whether to change a chain's reasoning settings for it
|
|
745
901
|
is a roster decision, not something the harness does for you.
|
|
902
|
+
- **The Claude Code plugin installs from the repository root.** `claude plugin validate .` passes with one warning, and
|
|
903
|
+
`claude plugin validate --strict .` fails on it: "CLAUDE.md at the plugin root is not loaded as project context" (the
|
|
904
|
+
file is this project's own instructions and is not part of the plugin). A separate `plugin/` directory would not have it;
|
|
905
|
+
that layout was declined for 0.8.1 and comes back with the plugin directory listing. What Claude Code passes for an
|
|
906
|
+
unset optional dialog field was seen once, in a scratch plugin on Claude Code 2.1.289 (an empty string), not across
|
|
907
|
+
versions or on Claude Desktop's own client.
|
|
908
|
+
- **The reasoning fields were set from the providers' documents and OpenRouter's public model list,
|
|
909
|
+
not exercised in a live call** (src/reasoning-table.json, read 2026-10-05). A provider that rejects a
|
|
910
|
+
field fails that seat's call with the provider's own error; the first real run of a changed chain is
|
|
911
|
+
the live test. The table turns stale after 60 days and a release test fails then. Seats that now
|
|
912
|
+
reason at high use their output cap faster, and a cap sized for a short answer (a questions or criteria
|
|
913
|
+
stage) can be spent on thinking: such a seat is retried once at a bigger cap and, past the limit, is
|
|
914
|
+
recorded with no answer. A direct Anthropic call is not streamed, so its retry is bounded at 64,000
|
|
915
|
+
tokens; streaming is not built.
|
|
746
916
|
- Prices in `src/pricing.json` are hand-maintained list prices. Its `asOf` date (2026-09-06: the
|
|
747
917
|
oldest date every entry was last checked) is printed by `council doctor` and `--dry-run`, with a
|
|
748
918
|
warning once it is more than 60 days old. The spend cap and every estimate use these static
|
|
749
|
-
prices. They are estimates, not invoices. Your provider's bill is the real number.
|
|
919
|
+
prices. They are estimates, not invoices. Your provider's bill is the real number. A row whose
|
|
920
|
+
price is known to change carries an `expires` date (GPT-5.6 Sol's promotional price, at least
|
|
921
|
+
through 2026-11-21; Gemini 3.8 Flash, which doubles on 2027-01-01): past it, `council doctor` and
|
|
922
|
+
`--dry-run` warn, but the projection and the cap keep the old price, so they can project low
|
|
923
|
+
until the table is updated.
|
|
750
924
|
- `plan-highest-7` has not been run with real models, and `plan-daily-7` has run once
|
|
751
925
|
(2026-09-28). None of the tiered councils' mechanisms (tiers, the deep-dive seat, the majority
|
|
752
926
|
guard) has been measured. Their dry-run prices are projections.
|
|
@@ -765,10 +939,69 @@ what each rule guards against and why. Copy the folders you want into your proje
|
|
|
765
939
|
which is the default, it does not detect a full rewrite**: anyone who can edit the file can
|
|
766
940
|
recompute every hash. Set `AUDIT_HMAC_KEY_FILE` to a key kept outside the run folder if the log
|
|
767
941
|
has to stand up to that.
|
|
942
|
+
- The advice tools (`council_quote`, `council_advise`) are experimental, and a call takes **seconds
|
|
943
|
+
(one seat) to minutes (a council), not milliseconds**, and **costs real money every time**: the quote
|
|
944
|
+
shows the worst case and the expected price, and the call cannot pass its ceiling. The brief goes to
|
|
945
|
+
outside labs: the preview says who, and its "ZDR-tagged by OpenRouter" wording is OpenRouter's routing
|
|
946
|
+
tag for an endpoint, **not a guarantee** about what that host does with your text (the table behind it,
|
|
947
|
+
`src/advice-retention.json`, is a dated snapshot). Masking catches the shapes it knows (emails, IBANs, cards, IPv4 addresses, a fixed list of internal host-name endings, home paths under
|
|
948
|
+
`/home`, `/Users` and `/srv`) and misses others (IPv6 addresses, `/var/home`, a WSL `/mnt/c/Users/...` path, `.home.arpa`, `.fritz.box`), and never names, addresses or a password written in words. The run folder of any run holds the absolute path of your working folder (`run.json`, `run.log`, `RESUME.md`): committing a run folder publishes it. The approval step covers `council_advise` only: `write_task` and `start_run` with another chain send text to the labs with no preview, only the key scan and the spend cap. The call limits bind
|
|
949
|
+
the advice tools, not a shell that runs `council` itself, and their ledger sits in your working folder.
|
|
950
|
+
Nothing has been measured that shows advice from other labs improves what an agent does.
|
|
768
951
|
- The outbound key scan matches **key shapes only**, the formats in `src/secret-patterns.js`; a
|
|
769
952
|
password written in prose is not detectable. Generic shapes (a password inside a URL or an
|
|
770
953
|
assignment) are checked in your inputs before the run; text the models write is checked only for
|
|
771
954
|
distinctive key formats.
|
|
955
|
+
- **The council advisor (`council_quote`, `council_advise`) was checked only against mock providers; these were not verified against a live provider or client.**
|
|
956
|
+
None of them is a claim about quality; a live check is yours to run, with a cap.
|
|
957
|
+
- U1: `zdr`, `data_collection` and `max_price` together on a real OpenRouter request. A wrong combination fails before generation, at $0, so the risk is a
|
|
958
|
+
refused call, not an overspend.
|
|
959
|
+
- U2: whether the output cap bounds reasoning tokens on all three council routes. The quoted ceiling is a projection; the provider's own billing decides.
|
|
960
|
+
- U3: whether a billed timeout is retried and charged twice against one reservation.
|
|
961
|
+
- U4: what a real client shows for an approval prompt of a 48,000-character brief (the limit), and whether the approval wait counts toward a client's background
|
|
962
|
+
threshold. The terminal path (`council gate answer`) always exists.
|
|
963
|
+
- U5: what each provider bills for an aborted request, and a real client's cancel (the tests send `notifications/cancelled` by hand).
|
|
964
|
+
- U6: Sol's real output length and latency, and GLM-5.3's latency, as advisors.
|
|
965
|
+
- U7: cancellation semantics under the protocol revision the SDK negotiates (generic cancellation, not the newer stdio requirement).
|
|
966
|
+
- **The approval gate is friction, not enforcement.** Every advice call needs a person to answer a gate through a terminal or an elicitation, so scripted or
|
|
967
|
+
unattended use is not supported: a client that cannot ask a person (headless Claude Code, a script) gets `awaiting_approval`, and nothing is sent until someone answers at a terminal. The terminal answer can be typed by anything that runs as you. The gate's ledger is
|
|
968
|
+
tamper-evident, not tamper-proof: an edit before its last line is detected; the last line, the tail and a rewrite of both the ledger and its view are not.
|
|
969
|
+
- **Planning runs still cannot be stopped from outside** (`council stop` and the client's cancel stop an advice call only).
|
|
970
|
+
- **`advise-premium` sends your text to labs that have no zero-retention-tagged endpoint.** It is `public`-only (the operator sets that floor), and its
|
|
971
|
+
worst case is above the add-on's default per-call limit, so an operator raises the limits to use it. GPT-6 Astra is reachable only through OpenRouter: there
|
|
972
|
+
is no subscription route. The retention table behind the send preview is a dated snapshot (`src/advice-retention.json`); the preview's wording is OpenRouter's
|
|
973
|
+
routing tag, not a guarantee.
|
|
974
|
+
- **The advice brief is written into the run folder** (`runs/<id>/advice-brief.md`), so a commit of the run folder publishes it.
|
|
975
|
+
- **`advise-single`'s ceiling is $1.32 (the "at most" its tool description shows).** It covers the first call and one retry of a cut-off reply; the typical
|
|
976
|
+
cost of one call is far lower. A person's own terminal run of an advice chain is not gated (`gate: null`), and the add-on's money limits and its chain choice can
|
|
977
|
+
also be set from a project `.env` (as can the audit-log key `AUDIT_HMAC_KEY` and the quote lifetime `COUNCIL_ADVISE_QUOTE_TTL_MS`): whether those should be refused is open. The council's wall clock (900 seconds) is untuned, and the single-seat swaps
|
|
978
|
+
(Astra, Gemini) keep fixed output caps.
|
|
979
|
+
- **A review cut-off in the security-review seat:** `src/security-review.js` cuts reviewer fields at 2,000 characters with a visible marker and no record.
|
|
980
|
+
- **Untested on case-insensitive file systems (macOS, Windows).** The fix for `handoff.md` and `HANDOFF.md` being one file (FX-9: `handoff --from-run` now also writes with an exclusive create, so it cannot replace an existing file whatever the disk's case rules) and the working-folder path checks were tested on Linux only. No pass on a Mac or a Windows machine was run for 0.8.1.
|
|
981
|
+
- **The dry run does not price every cap.** A planning chain's dry run prices a critic at the chain's own estimate, not at its output cap, so the larger caps of
|
|
982
|
+
0.8.1 (360,000 tokens for DeepSeek V4.1 Flash and the panel review of GLM-5.3 Flash) appear only in the spend cap's per-stage projection, which can stop a run before
|
|
983
|
+
the dry-run total. A retry of 720,000 tokens (a 360,000-token seat at the model's maximum) cannot finish inside the 45-minute request deadline and would be a paid timeout.
|
|
984
|
+
- **A failed start after approval is counted at the full ceiling.** If an advisor run cannot start after a person approved it (for example an unreadable audit-key file named in a project `.env`), the approval is used up, nothing is sent, and the call is still counted in the limits at its full ceiling (`advise-single`: $1.32). Two of these and one real call pass the $3 session limit, which then refuses advice for six hours with nothing spent.
|
|
985
|
+
- **One approval can start two runs if the approved run folder is copied:** the approval is bound to the text, not to the run folder.
|
|
986
|
+
- **Six shipped chains seat Gemini 2.5** (`plan-two-strong`, `seven`, `cheap`, `smo`, `us-only`, `verify` through the direct Google provider). Google has closed Gemini 2.5 to new projects, so a run on those chains by a new user will probably fail at that seat; use a chain with another seat, or change the seat's model.
|
|
987
|
+
- **The retry of a direct Anthropic seat whose thinking used the whole cap may never fire.** It keys on a thinking-token count in the reply's `usage`
|
|
988
|
+
(`output_tokens_details.thinking_tokens`) that Anthropic's public Messages API reference does not list (thinking counts inside `output_tokens`); OpenRouter reports
|
|
989
|
+
`reasoning_tokens`, so it fires for an Anthropic seat sent through a single-vendor route (`"transport": "openrouter"`). Where the count is absent, a reply cut off at its cap is retried by the panel's ordinary cut-off rule (one bigger call),
|
|
990
|
+
not by this one. Not verified against the live API.
|
|
991
|
+
- **Some fields an agent reads about a run are not marked as untrusted text.** `list_runs`, `run_status` and `external_prompt` return a run's label, chain name, task path and an
|
|
992
|
+
external seat's claim as ordinary fields; text from a cloned repository's run folder or chain file could carry an instruction there. Only the model-written fields named in
|
|
993
|
+
`untrusted_fields` are marked. A stage bundle for a subagent now says its referenced files are data; the field marking is planned for 0.8.2.
|
|
994
|
+
- **The terminal command for approving a call was not run under the `.mcpb` route.** It names the server's own Node binary and `cli.js` with absolute paths (or the standalone binary alone). Under Claude Desktop's bundled Node, whether that binary can be run from a terminal was not checked; `council gate answer` from an installed `council` always works.
|
|
995
|
+
- **A process killed in the middle of a call records nothing** (there are no signal handlers): the provider bills the call, but it is missing from `council --spend` and from a resume's
|
|
996
|
+
cap. A brief of non-ASCII text (CJK, say) is projected low in a planning chain (four characters a token); the add-on prices such a brief from its bytes.
|
|
997
|
+
- **A run paused under 0.8.0 on a chain that 0.8.1 changed is not replayed when resumed:** the config fingerprint differs, so its stages are set aside and paid for again.
|
|
998
|
+
Finish such a run on 0.8.0, or start it again.
|
|
999
|
+
- **`npm test` turns red on dates, by design:** 2026-10-31 (the retention table, 30 days old), 2026-11-21 (the `gpt-5.6-sol` promotional price row, and the OpenRouter
|
|
1000
|
+
price rows of `src/pricing.json`, 45 days after `scripts/refresh-openrouter-prices.mjs` last compared them with OpenRouter's list) and 2026-12-05
|
|
1001
|
+
(`src/reasoning-table.json`, 60 days old). Re-read the pages, re-date the file, then the suite is green again. The price rows of the direct providers
|
|
1002
|
+
(Anthropic, OpenAI, Google, ...) carry their own dates in `_source` and are not covered by that test.
|
|
1003
|
+
- **DeepSeek V4 Flash on Together** is sent `chat_template_kwargs {thinking: true, reasoning_effort: "high"}` from vLLM's serving recipe; Together's own page for it was
|
|
1004
|
+
not found, so the on-value is unconfirmed on Together.
|
|
772
1005
|
|
|
773
1006
|
## Privacy
|
|
774
1007
|
|
|
@@ -785,6 +1018,14 @@ This tool collects nothing. Stated plainly, not as a claim about quality:
|
|
|
785
1018
|
folder on your own disk (`runs/<id>/`) and nowhere else. Deleting that folder deletes the
|
|
786
1019
|
record. See `src/spend.js`'s own documentation for why spend accounting is derived from those
|
|
787
1020
|
folders rather than kept in a separate log.
|
|
1021
|
+
- An advice call (`council_advise`) sends a brief an agent wrote, after masking, to the labs the preview named, through
|
|
1022
|
+
OpenRouter, only after you approved its exact text (in your client's dialog or with `council gate answer`); there is no
|
|
1023
|
+
allowance and no statement that skips that. Like every run, it writes the exact text to disk, in the run folder:
|
|
1024
|
+
`runs/<id>/advice-brief.md`, hashed in `report.json` (`task_sha256`) and in the gate; the folder is made before you
|
|
1025
|
+
answer, so a declined or unanswered request leaves one too (nothing in it was sent or spent). `advise-log.json` keeps no
|
|
1026
|
+
brief text (only hashed, salted words of the question, salt kept in your home folder); `audit.jsonl` (always written
|
|
1027
|
+
for advice calls) holds a hash and a size per call, never the text. If you commit a run folder, you publish its masked
|
|
1028
|
+
brief.
|
|
788
1029
|
- If you opt in to the audit export (`"audit": true`, and on automatically whenever a `policy.json`
|
|
789
1030
|
exists), each run also writes `audit.jsonl` into its own folder: signed, hash-chained lines (each carries the previous line's hash) that
|
|
790
1031
|
`verifyAuditLog` in `src/audit.js` checks offline. Seat, cost and timing only, never task or
|
package/TROUBLESHOOTING.md
CHANGED
|
@@ -98,8 +98,8 @@ local chains as runnable because they need no key, not because the server is up.
|
|
|
98
98
|
The next stage's worst case would have crossed the cap. Nothing past the cap was spent, and no
|
|
99
99
|
plan was written yet; what the run got through is in `report-partial.json` and `BOARD-partial.md`.
|
|
100
100
|
`council --resume runs/<id> --max-usd <higher>` continues from where it stopped. The run tells you
|
|
101
|
-
at the start when a chain's worst case is above your cap. `
|
|
102
|
-
are above the default $7 cap before they start: price them with `--dry-run` and pass a
|
|
101
|
+
at the start when a chain's worst case is above your cap. `cheap-7-v2` (the first-run chain, $11.22 at the
|
|
102
|
+
prices of 2026-10-06), `plan-premium-7` and `plan-highest-7` are above the default $7 cap before they start: price them with `--dry-run` and pass a
|
|
103
103
|
`--max-usd` at or above that.
|
|
104
104
|
|
|
105
105
|
### `BLOCKED: ... file(s) named but never fenced` (exit 9)
|