the-high-council 0.7.5 → 0.7.7
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 +280 -116
- package/TROUBLESHOOTING.md +48 -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/gp-judge-v1.json +31 -7
- package/chains/idea-open-c2.json +2 -13
- package/chains/mock-criteria-kinds.json +19 -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 +22 -7
- 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/seven.json +1 -6
- package/chains/us-only.json +2 -7
- package/chains/verify.json +1 -1
- package/package.json +38 -4
- package/schemas/report-v1.json +784 -0
- package/schemas/verdict-diff.json +41 -0
- package/src/api.js +190 -0
- package/src/argued.js +286 -0
- package/src/audit.js +11 -5
- 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 +47 -6
- package/src/chain-lint.js +440 -11
- package/src/chain.js +1782 -138
- package/src/cli.js +1272 -211
- package/src/cost.js +83 -3
- package/src/council-replay.js +131 -0
- package/src/criteria-kinds.js +169 -0
- package/src/denied-models.js +139 -0
- package/src/disagreement-groups.js +54 -0
- package/src/dissent-digest.js +105 -0
- package/src/fence.js +145 -0
- package/src/http-server.js +1 -1
- package/src/invocation.js +25 -0
- package/src/key-redaction.js +15 -45
- package/src/mcp/server.js +248 -57
- package/src/metrics.js +5 -1
- package/src/mock-demo.js +237 -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/policy.js +140 -3
- package/src/preflight.js +119 -8
- package/src/pricing.json +126 -18
- package/src/progress-spans.js +72 -0
- package/src/providers.js +420 -36
- package/src/quote-check.js +134 -0
- package/src/rematch.js +70 -0
- package/src/report-shape.js +198 -0
- package/src/role-diagnostics.js +10 -3
- package/src/roles.js +524 -47
- 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 +53 -10
- package/src/superseded.js +73 -0
- package/src/tools.js +288 -24
- package/src/verdict-diff.js +63 -0
- package/src/verdict-stats.js +63 -22
- package/src/version.js +25 -0
- package/types/index.d.ts +122 -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
|
+
A planning harness that runs one idea past several AI models from different labs, makes them
|
|
4
|
+
argue about software engineering, architecture, specific features, roadmaps and philosophy, and
|
|
5
|
+
stops at a checkable result at an estimated price, with a variable number of debate rounds, model
|
|
6
|
+
seats and labs (except xAI) and variable token limits per response and model.
|
|
4
7
|
|
|
5
8
|
See it work right now - no keys, no setup, no cost:
|
|
6
9
|
|
|
7
|
-
npx
|
|
8
|
-
|
|
9
|
-
Add it to Claude Code as an MCP server the same way:
|
|
10
|
+
npx the-high-council council demo
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
The demo takes one example request (a tool that renames holiday photos by date) through every
|
|
13
|
+
stage: blind proposals, an anonymised debate in which one proposal is withdrawn and two are
|
|
14
|
+
amended, a panel that splits in round 1 and signs off in round 2, and the handoff file. Every
|
|
15
|
+
model reply in it is written in advance; what is real is the code that runs the stages around
|
|
16
|
+
them.
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
GitHub repo, no npm account needed.)*
|
|
18
|
+
Add it to Claude Code as an MCP server:
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
argue about it on the record, and stops at a checkable result.
|
|
20
|
+
claude mcp add council -- npx -y the-high-council council --mcp
|
|
18
21
|
|
|
19
22
|
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
|
-
|
|
23
|
+
own API keys. Nothing is resold, nothing is hosted for you, and your keys go only to the
|
|
24
|
+
providers you choose, never to us.
|
|
25
|
+
|
|
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
|
|
|
@@ -28,10 +33,65 @@ spending anything.
|
|
|
28
33
|
> disagreement between models *visible and recorded* instead of averaged away - you can read who
|
|
29
34
|
> objected to what, who withdrew a proposal under argument, and who held their position.
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
## Your first ten minutes
|
|
37
|
+
|
|
38
|
+
New to API keys, or to this? This path costs nothing until step 4, and step 4 tells you the price
|
|
39
|
+
before anything is spent.
|
|
40
|
+
|
|
41
|
+
1. **Watch one.** `npx the-high-council demo` walks an example request through every stage with
|
|
42
|
+
scripted replies. No key, no network, $0.
|
|
43
|
+
2. **Make it yours.** `npx the-high-council init` writes `tasks/my-first-task.md` (edit it into
|
|
44
|
+
your own idea, in plain words) and `chains/my-first-chain.json`, and runs a $0 mock pass so
|
|
45
|
+
you can look inside a real run folder.
|
|
46
|
+
3. **Find the least setup.** `npx the-high-council doctor` lists what your keys can run. Its
|
|
47
|
+
"Start here" block names the chains that need **one key only**: a single `OPENROUTER_API_KEY`
|
|
48
|
+
(one account at [openrouter.ai](https://openrouter.ai) that reaches many labs' models) is
|
|
49
|
+
enough for a seven-lab panel. Put the key in a file called `.env` in the folder you run from,
|
|
50
|
+
as `OPENROUTER_API_KEY=...`, and add `.env` to your `.gitignore` so it is never committed.
|
|
51
|
+
4. **Price it, then run it.** Add `--dry-run` to see the worst-case price for your task, then run
|
|
52
|
+
it without:
|
|
53
|
+
|
|
54
|
+
npx the-high-council --task tasks/my-first-task.md --chain cheap-7-v2 --dry-run
|
|
55
|
+
npx the-high-council --task tasks/my-first-task.md --chain cheap-7-v2
|
|
56
|
+
|
|
57
|
+
Every run stops before it would pass its spend cap ($7 unless you set `--max-usd`). A run
|
|
58
|
+
stopped by the cap keeps what it paid for but has no plan yet, so pick a cap at or above the
|
|
59
|
+
dry run's price. A panel that signs off early costs less than the worst case.
|
|
60
|
+
|
|
61
|
+
The plan lands in `runs/<time>/deliverable.md`; the argument behind it is in `BOARD.md`.
|
|
62
|
+
|
|
63
|
+
No key and no budget? A chain can run on models on your own machine through
|
|
64
|
+
[Ollama](#local-models-ollama-lm-studio-) at $0, if your computer can run them.
|
|
65
|
+
Everywhere below, `council` means `npx the-high-council` unless you installed it globally.
|
|
66
|
+
|
|
67
|
+
## Words used here
|
|
68
|
+
|
|
69
|
+
- **Lab** - a company that makes AI models (Anthropic, OpenAI, Google, DeepSeek, ...). "Different
|
|
70
|
+
labs" means models trained by different companies.
|
|
71
|
+
- **Provider** - where a call goes and who bills it: a lab's own API, OpenRouter (many labs, one
|
|
72
|
+
key and one bill), or `ollama` (your own machine).
|
|
73
|
+
- **API key** - a secret string from a provider that lets a program use your account there. You
|
|
74
|
+
pay the provider for what the program uses; nobody else sees the key.
|
|
75
|
+
- **Seat** - one job in a run, filled by one model: the one that writes criteria, the builder, a
|
|
76
|
+
critic, and so on.
|
|
77
|
+
- **Chain** - a JSON file that says which model sits in which seat and which stages run. Pick one
|
|
78
|
+
with `--chain`; `council doctor` lists them all.
|
|
79
|
+
- **Task** - your request, a plain text file in `tasks/`. No format.
|
|
80
|
+
- **Criteria** - yes/no checks the plan has to pass, written from your task before anyone plans.
|
|
81
|
+
- **Proposal, debate** - each lab suggests parts of the plan without seeing the others, then
|
|
82
|
+
they read each other's (with names hidden) and object, support or merge.
|
|
83
|
+
- **Panel, round, sign-off** - the critics grade the draft against the criteria; each failed check
|
|
84
|
+
goes back for a revision, which is one round. Sign-off means a critic found nothing failing.
|
|
85
|
+
- **Dry run** - `--dry-run`: price a run, call nothing.
|
|
86
|
+
- **Spend cap** - the most one run may cost. It is checked before every paid call.
|
|
87
|
+
- **Mock** - a fake provider with scripted replies, for trying the machinery for free.
|
|
88
|
+
- **External** - a seat that waits for a person or another agent (such as your Claude Code session)
|
|
89
|
+
to answer it from a file.
|
|
90
|
+
- **Handoff** - `HANDOFF.md`, the build instructions a coding agent works from.
|
|
91
|
+
|
|
92
|
+
**A visual write-up of all of this, built around one real run, is at
|
|
93
|
+
[sower-industries.de/MCP](https://sower-industries.de/MCP).** What changed in each release:
|
|
94
|
+
[CHANGELOG.md](CHANGELOG.md).
|
|
35
95
|
|
|
36
96
|
## How it works
|
|
37
97
|
|
|
@@ -58,11 +118,13 @@ withdrawal), `HANDOFF.md`, a per-lab scoreboard, and the real token/cost account
|
|
|
58
118
|
### Reading a run with a program
|
|
59
119
|
|
|
60
120
|
`BOARD.md` is for people. **`report.json` is the same board, structured** - if you are building
|
|
61
|
-
anything on top of a run, read that instead. Do not parse the markdown.
|
|
121
|
+
anything on top of a run, read that instead. Do not parse the markdown. The format is versioned
|
|
122
|
+
(`schemaVersion`) and published as a JSON Schema, `schemas/report-v1.json`; which fields are stable,
|
|
123
|
+
which are experimental, and how versions change: [docs/report-format.md](docs/report-format.md).
|
|
62
124
|
|
|
63
125
|
```jsonc
|
|
64
126
|
{
|
|
65
|
-
"runId": "...", "chain": "...", "passed": false, "maxUsd": 5,
|
|
127
|
+
"schemaVersion": 1, "runId": "...", "chain": "...", "passed": false, "maxUsd": 5,
|
|
66
128
|
"criteria": [ "each acceptance criterion, as written before the debate" ],
|
|
67
129
|
"questions": [ { "question": "...", "why": "...", "default": "..." } ], // null if the chain skipped them
|
|
68
130
|
"proposals": [ { "id": "DEEPSEEK-1", "lab": "deepseek", "model": "...",
|
|
@@ -76,7 +138,26 @@ anything on top of a run, read that instead. Do not parse the markdown.
|
|
|
76
138
|
"replies": [ { "id": "DEEPSEEK-1", "action": "keep|amend|withdraw",
|
|
77
139
|
"text": "...", "replaced_by": "GLM-1" } ]
|
|
78
140
|
},
|
|
79
|
-
|
|
141
|
+
// Only on chains with `alternatives: { enabled: true }`: one whole architecture per lab, written
|
|
142
|
+
// blind before the skeleton, and the same post/reply board the proposals get.
|
|
143
|
+
"alternatives": {
|
|
144
|
+
"items": [ { "id": "GLM-ALT", "lab": "glm", "model": "...", "name": "...", "shape": "...",
|
|
145
|
+
"key_tradeoffs": "...", "bad_at": "...", "amended": true, "withdrawn": false } ],
|
|
146
|
+
"posts": [ { "by": "qwen", "on": "GLM-ALT", "stance": "object|support|merge", "text": "..." } ],
|
|
147
|
+
"replies": [ { "id": "GLM-ALT", "action": "keep|amend|withdraw", "text": "..." } ],
|
|
148
|
+
"dropouts": [ { "lab": "...", "model": "...", "stage": "alternatives", "reason": "..." } ]
|
|
149
|
+
},
|
|
150
|
+
// Only on chains with `argued: { enabled: true }` (off by default, on in no shipped chain): the
|
|
151
|
+
// "How this plan was argued" section, written to ARGUED.md next to deliverable.md (never inside it)
|
|
152
|
+
// by the handoff seat, from a fact pack of this run's own record. unknown_refs / unknown_labs are
|
|
153
|
+
// ids and labs it named that the run never had; each is also a line in WARNINGS.md.
|
|
154
|
+
"argued": {
|
|
155
|
+
"file": "ARGUED.md",
|
|
156
|
+
"facts_counts": { "labs": 7, "alternatives": 7, "proposals": 14, "objections": 9, "...": 0 },
|
|
157
|
+
"unknown_refs": [], "unknown_labs": [], "missing_labs": [], "missing_sections": [],
|
|
158
|
+
"refs_cited": 23, "ok": true
|
|
159
|
+
},
|
|
160
|
+
"signoff": [ { "lab": "qwen", "provider": "qwen", "model": "...", "signedOff": false,
|
|
80
161
|
"objections": [ { "criterion": "...", "problem": "...", "fix": "..." } ] } ],
|
|
81
162
|
"lastCritique": { "meets": false, "failures": [ { "criterion": "...", "lab": "qwen" } ] },
|
|
82
163
|
"scoreboard": {
|
|
@@ -108,6 +189,8 @@ those plus `text` and may carry more (an `amend` often brings a `how`). `replace
|
|
|
108
189
|
when the action is `withdraw`. `proposals[]` likewise carries `withdrawn` / `amended` /
|
|
109
190
|
`replaced_by` only when they apply. Read defensively: check for a field, do not assume it.
|
|
110
191
|
|
|
192
|
+
`signoff[].lab` is the seat's lab; `signoff[].provider` holds the same value under an older,
|
|
193
|
+
misleading name and is deprecated (kept until the report format's version 2).
|
|
111
194
|
`signoff[].objections` is why a seat declined, on the seat's own record. `signedOff: null` means
|
|
112
195
|
the seat gave no usable reply and abstained - neither a pass nor an objection, and `objections` is
|
|
113
196
|
`null` rather than empty so the two stay apart. A seat that agreed has an empty list.
|
|
@@ -115,7 +198,7 @@ The same objections also appear flattened in `lastCritique.failures[]`, tagged w
|
|
|
115
198
|
the reviser wants the union across the whole panel. Both are built in one pass; they cannot drift.
|
|
116
199
|
|
|
117
200
|
**Before you publish a run,** note that `report.json` records `task` as the path to your task file
|
|
118
|
-
|
|
201
|
+
(relative to where you started the run, never absolute). Nothing transmits it anywhere - but if you are rendering a board onto a public
|
|
119
202
|
page, drop that field. The debate itself is the part worth showing.
|
|
120
203
|
|
|
121
204
|
## Requirements
|
|
@@ -125,22 +208,59 @@ page, drop that field. The debate itself is the part worth showing.
|
|
|
125
208
|
|
|
126
209
|
## Setup
|
|
127
210
|
|
|
211
|
+
Nothing to install beyond Node: `npx the-high-council council <command>` fetches the published
|
|
212
|
+
package and runs it. To keep a `council` command on your PATH instead:
|
|
213
|
+
|
|
128
214
|
```bash
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
npm install
|
|
132
|
-
cp .env.example .env
|
|
215
|
+
npm install -g the-high-council
|
|
216
|
+
council doctor
|
|
133
217
|
```
|
|
134
218
|
|
|
135
|
-
|
|
219
|
+
`council` reads and writes in the directory you run it from: `.env` for keys, `tasks/` for
|
|
220
|
+
requests, `runs/` for output, and a `chains/` of your own there takes precedence over the bundled
|
|
221
|
+
ones. Put only the keys your chosen chain needs in that `.env`, one `NAME=value` per line
|
|
222
|
+
(`.env.example` in the package lists them all). Supported providers:
|
|
136
223
|
|
|
137
224
|
`ANTHROPIC_API_KEY` · `OPENAI_API_KEY` · `GOOGLE_API_KEY` · `MISTRAL_API_KEY` ·
|
|
138
225
|
`DEEPSEEK_API_KEY` · `GROQ_API_KEY` · `TOGETHER_API_KEY` · `COHERE_API_KEY` ·
|
|
139
|
-
`OPENROUTER_API_KEY` · `ZAI_API_KEY`
|
|
226
|
+
`OPENROUTER_API_KEY` · `ZAI_API_KEY`
|
|
227
|
+
|
|
228
|
+
xAI/Grok and Kimi/Moonshot are never seated, and neither is a router id (`openrouter/auto`, the
|
|
229
|
+
Pareto Code router) that could route to them: chain-lint refuses such a chain and the run itself
|
|
230
|
+
refuses such a seat, with no override. There is no `xai` provider.
|
|
140
231
|
|
|
141
232
|
The CLI refuses to start if any seat in the chosen chain is missing its key, rather than failing
|
|
142
233
|
halfway through a paid run. `ollama` (below) is the one exception - it needs no key at all.
|
|
143
234
|
|
|
235
|
+
### From source
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
git clone https://github.com/muad-yasin/the-high-council-mcp.git
|
|
239
|
+
cd the-high-council-mcp
|
|
240
|
+
npm install
|
|
241
|
+
cp .env.example .env
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
In a clone, `node src/cli.js` does what `council` does, on the current source rather than the
|
|
245
|
+
published package. `npx github:muad-yasin/the-high-council-mcp council demo` runs the current
|
|
246
|
+
source without cloning.
|
|
247
|
+
|
|
248
|
+
### Standalone binaries (build them yourself)
|
|
249
|
+
|
|
250
|
+
There are no published binary downloads yet. From a clone you can build a single-file `council`
|
|
251
|
+
that needs no Node install to run: a Linux binary, a Linux AppImage, and a Windows `.exe`, all
|
|
252
|
+
built on Linux.
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
npm run build:bin # dist/the-high-council-linux, dist/the-high-council-win.exe
|
|
256
|
+
npm run build:appimage # dist/the-high-council-x86_64.AppImage (downloads a pinned appimagetool)
|
|
257
|
+
npm run smoke:bin -- dist/the-high-council-linux # demo + an MCP session, offline, $0
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Stated plainly: the `.exe` is tested under Wine on Linux, not on a real Windows machine, and none
|
|
261
|
+
of the binaries are code-signed, so Windows SmartScreen will warn. Put `.env` in the directory you
|
|
262
|
+
run the binary from.
|
|
263
|
+
|
|
144
264
|
### Local models (Ollama, LM Studio, ...)
|
|
145
265
|
|
|
146
266
|
A seat can run on a model you're hosting yourself instead of a paid API. Set its provider to
|
|
@@ -165,6 +285,15 @@ example chain with every seat local. As with every other seat in this project: B
|
|
|
165
285
|
BYO-compute here, and no efficacy claim is made about local models versus hosted ones - nothing
|
|
166
286
|
has been measured.
|
|
167
287
|
|
|
288
|
+
### Final security-review gate
|
|
289
|
+
|
|
290
|
+
`"security_review": { "enabled": true }` adds one read-only reviewer as the last stage of a chain,
|
|
291
|
+
after the build and everything else. It returns typed findings, and any critical or high finding
|
|
292
|
+
fails the run (exit 7). A reviewer with no usable verdict fails it too (exit 8); that never counts
|
|
293
|
+
as a pass. The default reviewer is `anthropic/claude-fable-5-1` (your key, priced, capped);
|
|
294
|
+
`seats.security_reviewer` can be any seat, including a local `ollama` one as an offline option.
|
|
295
|
+
Full details: [docs/security-review-gate.md](docs/security-review-gate.md).
|
|
296
|
+
|
|
168
297
|
## Quick start (CLI)
|
|
169
298
|
|
|
170
299
|
A task file is the request the council plans against: plain prose, written by you. There is no
|
|
@@ -175,17 +304,48 @@ mkdir -p tasks
|
|
|
175
304
|
echo "Plan the data model for a bookmarking app. Single user, offline-first." > tasks/your-idea.md
|
|
176
305
|
|
|
177
306
|
# see what's available and what it would cost
|
|
178
|
-
|
|
179
|
-
|
|
307
|
+
council --help
|
|
308
|
+
council --task tasks/your-idea.md --chain verify --dry-run
|
|
180
309
|
|
|
181
310
|
# a real run
|
|
182
|
-
|
|
311
|
+
council --task tasks/your-idea.md --chain verify
|
|
183
312
|
```
|
|
184
313
|
|
|
185
|
-
|
|
186
|
-
|
|
314
|
+
Your requests and everything the council writes about them stay on your machine, in `tasks/` and
|
|
315
|
+
`runs/` under the directory you ran from. In a clone of this repo both are gitignored, so a fork
|
|
316
|
+
will not accidentally publish them.
|
|
317
|
+
|
|
318
|
+
`verify` is the default when you name no chain: a panel of two labs, a hard two-round cap. It
|
|
319
|
+
needs three keys (Anthropic, OpenAI and Google, one account each). With one OpenRouter key, start
|
|
320
|
+
with `cheap-7-v2` instead; `council doctor` lists every chain that runs on the keys you have.
|
|
187
321
|
|
|
188
|
-
|
|
322
|
+
### Exit codes
|
|
323
|
+
|
|
324
|
+
Each outcome has its own code, so a script or CI job can branch on it:
|
|
325
|
+
|
|
326
|
+
| Code | Meaning |
|
|
327
|
+
|---|---|
|
|
328
|
+
| 0 | Finished: a deliverable and `report.json` were written. |
|
|
329
|
+
| 1 | The chain failed lint, or an input is missing (no task file, a resume from the wrong directory). |
|
|
330
|
+
| 2 | Usage error: a flag is missing its value or has an invalid one. |
|
|
331
|
+
| 3 | Paused at an external seat: answer `NEEDS-<stage>.md`, then `--resume`. |
|
|
332
|
+
| 4 | Stopped at the per-run spend cap before the next stage was paid for; resume with a higher `--max-usd`. |
|
|
333
|
+
| 5 | A provider key the chain needs is missing (degradable: set it and run again). |
|
|
334
|
+
| 6 | Fatal: the chain file cannot be parsed, or the audit key cannot be loaded. |
|
|
335
|
+
| 7 | Finished, but the final security review blocked the deliverable. |
|
|
336
|
+
| 8 | Finished, but the final security review could not judge it (never a pass). |
|
|
337
|
+
| 9 | Artifact gate: the task names files whose content it never includes (`BLOCKED-ARTIFACTS.md`). |
|
|
338
|
+
| 10 | Preflight: a seat objected to the task description itself (`STOPPED-preflight.md`). |
|
|
339
|
+
| 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`. |
|
|
340
|
+
| 12 | `policy.json` refused the chain. |
|
|
341
|
+
| 13 | Another process is already running this run folder. |
|
|
342
|
+
| 14 | The task file changed since the run started and `AMENDMENTS.md` does not cover it. |
|
|
343
|
+
| 15 | `--resume` of a run that already finished (it has a `report.json`); nothing is run or spent. |
|
|
344
|
+
| 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. |
|
|
345
|
+
| 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`). |
|
|
346
|
+
|
|
347
|
+
Codes 9-17 were split out or added on 2026-09-23. Before that, several of these outcomes shared a code (2, 5,
|
|
348
|
+
6 or 1).
|
|
189
349
|
|
|
190
350
|
### Telling the council what your build session can actually use
|
|
191
351
|
|
|
@@ -211,13 +371,13 @@ before building it."*
|
|
|
211
371
|
|
|
212
372
|
### The spend cap
|
|
213
373
|
|
|
214
|
-
Every run has a per-run ceiling in USD. It defaults to **$
|
|
374
|
+
Every run has a per-run ceiling in USD. It defaults to **$7**, and is checked *before* each paid
|
|
215
375
|
stage - a stage that could take the run past the ceiling is never called, so the cap holds rather
|
|
216
376
|
than reporting the overspend afterwards.
|
|
217
377
|
|
|
218
378
|
```bash
|
|
219
|
-
|
|
220
|
-
|
|
379
|
+
council --task tasks/x.md --max-usd 2 # this run stops at $2
|
|
380
|
+
council --task tasks/x.md --max-usd none # no ceiling
|
|
221
381
|
export MAX_USD_PER_RUN=20 # change the default
|
|
222
382
|
```
|
|
223
383
|
|
|
@@ -227,17 +387,25 @@ stage it stopped at, and what that stage would have cost. Nothing is half-writte
|
|
|
227
387
|
with a higher ceiling - completed stages replay from disk and cost nothing the second time:
|
|
228
388
|
|
|
229
389
|
```bash
|
|
230
|
-
|
|
390
|
+
council --resume runs/<id> --max-usd 10
|
|
231
391
|
```
|
|
232
392
|
|
|
393
|
+
A stage replays only if it would be asked the same thing again: the task text, the chain config
|
|
394
|
+
and the stage's own prompt must all match what it answered. If one changed (you edited the chain,
|
|
395
|
+
or an earlier stage came out differently this time), the stage runs again and its old files move
|
|
396
|
+
into `superseded/` inside the run folder. What the old answer cost still counts toward the ceiling,
|
|
397
|
+
`--spend` and `report.json`'s `totals.usd` (shown separately as `totals.supersededUsd`), so a resume
|
|
398
|
+
cannot spend past the cap. An answer you wrote for an external stage is never re-used against a
|
|
399
|
+
changed prompt: it is set aside the same way and the run asks you again.
|
|
400
|
+
|
|
233
401
|
The cap governs one run. To see what you have spent across all of them:
|
|
234
402
|
|
|
235
403
|
```bash
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
404
|
+
council --spend # today
|
|
405
|
+
council --spend --days 7 # the last week
|
|
406
|
+
council --cost-today # today by calendar day, with a per-model breakdown
|
|
407
|
+
council --cost-today --date 2026-09-01
|
|
408
|
+
council --stats --days 30 # how the debate mechanism itself is doing
|
|
241
409
|
```
|
|
242
410
|
|
|
243
411
|
That is read back off the run folders on disk - there is no ledger file, nothing is recorded
|
|
@@ -249,7 +417,7 @@ To watch this work without spending anything, the `mock-budget` chain calls no A
|
|
|
249
417
|
fixture prices:
|
|
250
418
|
|
|
251
419
|
```bash
|
|
252
|
-
|
|
420
|
+
council --task tasks/your-idea.md --chain mock-budget --max-usd 1
|
|
253
421
|
```
|
|
254
422
|
|
|
255
423
|
If a chain pauses for your input, it writes `NEEDS-<stage>.md` into the run folder and tells you
|
|
@@ -257,17 +425,20 @@ how to resume:
|
|
|
257
425
|
|
|
258
426
|
```bash
|
|
259
427
|
# write your answer to runs/<id>/answers.md, then:
|
|
260
|
-
|
|
428
|
+
council --resume runs/<id>
|
|
261
429
|
```
|
|
262
430
|
|
|
263
431
|
## Quick start (MCP)
|
|
264
432
|
|
|
265
|
-
Register the server with your MCP client. No clone needed -
|
|
433
|
+
Register the server with your MCP client. No clone needed - from the published npm package:
|
|
266
434
|
|
|
267
435
|
```bash
|
|
268
|
-
claude mcp add council -- npx -y
|
|
436
|
+
claude mcp add council -- npx -y the-high-council council --mcp
|
|
269
437
|
```
|
|
270
438
|
|
|
439
|
+
The same line with `npx -y github:muad-yasin/the-high-council-mcp` runs the current source
|
|
440
|
+
instead.
|
|
441
|
+
|
|
271
442
|
Or from a clone of this repo:
|
|
272
443
|
|
|
273
444
|
```bash
|
|
@@ -277,20 +448,34 @@ claude mcp add high-council -- node /absolute/path/to/the-high-council-mcp/src/m
|
|
|
277
448
|
**The path must be absolute.** The client starts the server from its own working directory, not
|
|
278
449
|
from this one, so a relative path resolves somewhere unexpected and the server never starts.
|
|
279
450
|
|
|
280
|
-
|
|
451
|
+
Or as a Claude Code plugin, which registers the same server and also installs the skills in
|
|
452
|
+
[`skills/`](skills/README.md):
|
|
281
453
|
|
|
282
454
|
```bash
|
|
283
|
-
claude
|
|
455
|
+
claude plugin marketplace add muad-yasin/the-high-council-mcp
|
|
456
|
+
claude plugin install the-high-council@the-high-council
|
|
284
457
|
```
|
|
285
458
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
459
|
+
Claude Code copies the plugin into its plugin cache and runs `npm ci` there itself, so the first
|
|
460
|
+
install takes a little longer. Start a new session (or run `/reload-plugins`) and the server shows
|
|
461
|
+
up in `claude mcp list` as `plugin:the-high-council:high-council`. Remove it with
|
|
462
|
+
`claude plugin uninstall the-high-council@the-high-council`. If you add the marketplace from a
|
|
463
|
+
local clone instead (`claude plugin marketplace add /path/to/clone`), the server runs from the
|
|
464
|
+
clone itself, so run `npm install` in it first.
|
|
289
465
|
|
|
290
|
-
|
|
466
|
+
Registering with a client other than Claude Code (DeepSeek Harness, OpenHands, Cline, goose,
|
|
467
|
+
Continue): [docs/mcp-clients.md](docs/mcp-clients.md) has the real config for each.
|
|
468
|
+
|
|
469
|
+
Whichever way you add it, the server reads and writes in **your** working directory, not inside
|
|
470
|
+
the package: `.env` for keys, `tasks/` for requests, `runs/` for output, and a `chains/` of your
|
|
471
|
+
own takes precedence over the bundled ones. In a git project, add `.env` (and `runs/` if your
|
|
472
|
+
ideas are private) to `.gitignore` before an agent commits everything; `council doctor` warns
|
|
473
|
+
when `.env` is not ignored.
|
|
474
|
+
|
|
475
|
+
To run it by hand:
|
|
291
476
|
|
|
292
477
|
```bash
|
|
293
|
-
|
|
478
|
+
council --mcp # from a clone: npm run mcp
|
|
294
479
|
```
|
|
295
480
|
|
|
296
481
|
Then drive it with these tools:
|
|
@@ -324,7 +509,7 @@ for anyone with a subscription, since the project's cost story depends on it.
|
|
|
324
509
|
|
|
325
510
|
## Chains
|
|
326
511
|
|
|
327
|
-
|
|
512
|
+
49 chain configs live in `chains/`. Each one is plain JSON - the seat roster, which models fill
|
|
328
513
|
which seat, the round cap, and whether proposals/debate/handoff stages run. They are meant to be
|
|
329
514
|
copied and edited.
|
|
330
515
|
|
|
@@ -334,7 +519,8 @@ A few worth knowing:
|
|
|
334
519
|
- **`cheap`** - small models throughout. For testing the harness itself, not for real work.
|
|
335
520
|
- **`plan-debate`** - five labs propose blind, debate each other's proposals anonymised, then a
|
|
336
521
|
blind panel grades the integrated draft.
|
|
337
|
-
- **`plan-auto`** - the full open-scope chain
|
|
522
|
+
- **`plan-auto`** - the full open-scope chain with every seat on a real API, so no stage waits for
|
|
523
|
+
an external session. It still pauses once for your answers to its questions.
|
|
338
524
|
- **`plan-unanimous`** - every critic must independently sign off on the *same* draft. Three rounds
|
|
339
525
|
here means up to fifteen critic calls, not five.
|
|
340
526
|
|
|
@@ -359,56 +545,6 @@ Read a chain's `description` field before running it; they say what they cost yo
|
|
|
359
545
|
before. **No efficacy claim**: this ships the mechanism, not evidence that it helps - see
|
|
360
546
|
CHANGELOG.md's 0.6.0 entry.
|
|
361
547
|
|
|
362
|
-
## New in 0.6.0
|
|
363
|
-
|
|
364
|
-
- **Role-assigned debate seats** - see the `role` field above. Ships the mechanism only; whether
|
|
365
|
-
it changes anything about a real debate is untested by this release.
|
|
366
|
-
- **`report.json`'s `debate.diagnostics`** - four failure-mode signals computed from a run's own
|
|
367
|
-
real debate output (never from an offline probe): a seat quoting no evidence despite objecting
|
|
368
|
-
or merging, textual overlap between differently-lensed seats' posts on the same proposal, a
|
|
369
|
-
same-run gap between role-bearing and role-less seats' evidence quoting, and the share of a
|
|
370
|
-
seat's own words that fall inside quoted evidence versus voice. Present (with nulls/empty
|
|
371
|
-
flags where there's nothing to compute) on any run that had a debate stage; absent otherwise.
|
|
372
|
-
- **`debate.tie_break`** - a `report.json` field recording a weighted-tiebreak event, when one
|
|
373
|
-
fires. Not yet wired into a live vote-counting decision in this release.
|
|
374
|
-
- **`PERSONAS.md`** - the five default public persona names and their voice directives, and how
|
|
375
|
-
an operator replaces the whole set with their own via `COUNCIL_PERSONAS_FILE`.
|
|
376
|
-
|
|
377
|
-
## New in 0.5.0
|
|
378
|
-
|
|
379
|
-
- **`council init [--yes]`** - the first thing to run in a fresh clone with no keys yet. Prints a
|
|
380
|
-
key check, writes a starter chain and task file you own (`chains/my-first-chain.json`,
|
|
381
|
-
`tasks/my-first-task.md` - a rerun never overwrites an edit you made to either), prices the
|
|
382
|
-
starter chain with no network call, then runs a canned, all-mock, $0 task end to end so the
|
|
383
|
-
first thing you inspect is a real run folder, not just terminal output.
|
|
384
|
-
- **`council doctor --chain <file>`** - lints one chain config before you ever run it: a seat
|
|
385
|
-
under a misspelled key (never wired to any stage), a missing or empty `seats.critics` (the
|
|
386
|
-
review round can't run), or a seat naming a provider this codebase doesn't know. The same check
|
|
387
|
-
also runs automatically, fail-loud, the moment you try to actually run a broken chain - before
|
|
388
|
-
any paid call.
|
|
389
|
-
- **`council doctor --scan-artifacts`** - scans your `tasks/` and `chains/` for API-key-shaped
|
|
390
|
-
strings before you commit or share them. Reports the file and line, never the matched text.
|
|
391
|
-
- **`council --forecast-cost --chain <name> [--days N]`** - a realistic-case USD range for a
|
|
392
|
-
chain, built from its own historical runs on your machine and repriced at today's rates -
|
|
393
|
-
distinct from `--dry-run`'s worst-case estimate from a chain's declared token assumptions.
|
|
394
|
-
- **`council export-board --run <folder> --out <file>`** - a run's proposals, debate, replies and
|
|
395
|
-
verdict as one self-contained HTML file. No external assets, no server, `<details>` sections.
|
|
396
|
-
- **`council replay --run <folder> [--json]`** - a numbered, step-by-step transcript of a run's
|
|
397
|
-
reasoning in your terminal, with a `--json` mode for scripting.
|
|
398
|
-
- **A structured error catalog** (`COUNCIL-E001`-`COUNCIL-E004`, see [TROUBLESHOOTING.md](TROUBLESHOOTING.md))
|
|
399
|
-
for the hard-fail paths this project actually has - a missing key, an unpriced model, a
|
|
400
|
-
malformed chain file, an unreadable stage reply - each with a plain-words cause, a concrete fix
|
|
401
|
-
naming the real file, and a doc pointer. Degradable conditions exit 5; fatal ones exit 6.
|
|
402
|
-
- **Structured per-stage JSON logs** - every run now also writes `stage-log.jsonl` (one line per
|
|
403
|
-
stage: seat, lab, token counts, cost, timing - no prompt content) alongside the existing
|
|
404
|
-
markdown/`report.json` artifacts.
|
|
405
|
-
- **[CONTRIBUTING.md](CONTRIBUTING.md)** - the three smallest landable contribution shapes, for
|
|
406
|
-
anyone who wants to send a PR rather than only file an issue.
|
|
407
|
-
|
|
408
|
-
None of the above change any existing chain's behaviour. `schemaVersion` and
|
|
409
|
-
`max_proposals_per_seat` are both opt-in; a chain file that predates 0.5.0 runs exactly as it did
|
|
410
|
-
before.
|
|
411
|
-
|
|
412
548
|
## How this was built
|
|
413
549
|
|
|
414
550
|
Vibecoded, with **Claude Code** doing the writing, by one person at
|
|
@@ -444,13 +580,21 @@ No claim is made here that any of this produces better plans. It has not been me
|
|
|
444
580
|
|
|
445
581
|
## Skills
|
|
446
582
|
|
|
447
|
-
`skills/` carries
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
583
|
+
`skills/` carries a small set of Claude Code skills shipped alongside this harness, not part of
|
|
584
|
+
it - usable in any project, with or without the harness, and needing no API key:
|
|
585
|
+
|
|
586
|
+
- **Core agentic work:** `task-scoping`, `research-and-sourcing`, `verification-and-critique`,
|
|
587
|
+
`context-and-handoff`, `tool-and-action-discipline` - the work around the work, for any agent
|
|
588
|
+
task, including setups where several models propose, critique, and hand off to each other.
|
|
589
|
+
- **Building software:** `backend-developer`, `frontend-developer`, `ux-design`, `visual-craft`.
|
|
590
|
+
- **Writing:** `good-news-writing`.
|
|
591
|
+
|
|
592
|
+
The full catalog, with when to use each and what it guards against, is
|
|
593
|
+
[`skills/README.md`](skills/README.md); a shareable presentation page is `docs/skills.html`. Both
|
|
594
|
+
are checked by the test suite against the real `skills/` folder. Same MIT/BYOK ethos as the
|
|
595
|
+
harness: the skills don't claim to make results better - nothing has been measured - they describe
|
|
596
|
+
what each rule guards against and why. Copy the folders you want into your project's
|
|
597
|
+
`.claude/skills/`, or point Claude Code at this repo's `skills/` directory.
|
|
454
598
|
|
|
455
599
|
## Known limits, stated plainly
|
|
456
600
|
|
|
@@ -463,6 +607,17 @@ at this repo's `skills/` directory (or copy the two folders into your own projec
|
|
|
463
607
|
for `unpriced` before trusting a ceiling. `ollama` seats are the one deliberate exception: they
|
|
464
608
|
price at an explicit $0 for any model name (they are genuinely free to run), so they never show
|
|
465
609
|
up in that `unpriced` list and never need a pricing.json entry.
|
|
610
|
+
- A call that fails **after** it reached the provider - the connection drops while a 200 reply is
|
|
611
|
+
being read, a 200 carries a body that is not JSON, or the request times out waiting for headers -
|
|
612
|
+
is not retried, because the generation was probably already billed. Its real usage cannot be
|
|
613
|
+
read, so it is counted toward the per-run cap at its worst-case projection. It leaves no
|
|
614
|
+
`<label>.usage.json`, so `council --spend` does not see it.
|
|
615
|
+
- Some hosted reasoning models stop at a provider-side reasoning ceiling well below the seat's own
|
|
616
|
+
cap, before writing any answer (seen 2026-09-23: `deepseek/deepseek-v4.1-flash` via OpenRouter, 6 of
|
|
617
|
+
28 calls stopped at ~4.2k tokens, all reasoning, under a 36k cap). A bigger cap cannot fix that, so
|
|
618
|
+
such a reply is recorded as `REASONING_EXHAUSTED` and is not retried: the seat abstains, which
|
|
619
|
+
blocks unanimity and never counts as consent. Whether to change a chain's reasoning settings for it
|
|
620
|
+
is a roster decision, not something the harness does for you.
|
|
466
621
|
- Prices in `src/pricing.json` are hand-maintained list prices, last verified 2026-09-06. They are
|
|
467
622
|
estimates, not invoices. Your provider's bill is the real number.
|
|
468
623
|
- Chains with many labs and high round caps get expensive quickly. `plan-unanimous` at three rounds
|
|
@@ -473,27 +628,34 @@ at this repo's `skills/` directory (or copy the two folders into your own projec
|
|
|
473
628
|
produce sign-offs that mean nothing - the quality of the run depends heavily on the quality of
|
|
474
629
|
the criteria stage.
|
|
475
630
|
- Some chains pause for human input by design. They are not stuck.
|
|
631
|
+
- The audit log (`audit.jsonl`) detects an edited line or a cut-off end, but **with no HMAC key,
|
|
632
|
+
which is the default, it does not detect a full rewrite**: anyone who can edit the file can
|
|
633
|
+
recompute every hash. Set `AUDIT_HMAC_KEY_FILE` to a key kept outside the run folder if the log
|
|
634
|
+
has to stand up to that.
|
|
476
635
|
|
|
477
636
|
## Privacy
|
|
478
637
|
|
|
479
|
-
This tool
|
|
480
|
-
collect nothing. Stated plainly, not as a claim about quality:
|
|
638
|
+
This tool collects nothing. Stated plainly, not as a claim about quality:
|
|
481
639
|
|
|
482
640
|
- No telemetry, no analytics, no tracking of any kind, anywhere in this repo.
|
|
483
641
|
- The only network calls this tool ever makes are to the AI provider APIs you configure with
|
|
484
642
|
your own keys (`ANTHROPIC_API_KEY`, `OPENROUTER_API_KEY`, and so on) - and only when you start
|
|
485
643
|
a real run with a non-mock, non-external seat. `council doctor` and `council demo` make zero
|
|
486
644
|
network calls; both are implemented to read only local files and environment variable names.
|
|
487
|
-
- The
|
|
645
|
+
- The landing page in `docs/` ships no JavaScript and loads no third-party resource - see
|
|
488
646
|
`test/landing-page.test.js`, which fails the build if either ever changes.
|
|
489
647
|
- Everything a run produces - the task, the debate, the deliverable, the cost - is written to a
|
|
490
648
|
folder on your own disk (`runs/<id>/`) and nowhere else. Deleting that folder deletes the
|
|
491
649
|
record. See `src/spend.js`'s own documentation for why spend accounting is derived from those
|
|
492
650
|
folders rather than kept in a separate log.
|
|
651
|
+
- If you opt in to the audit export (`"audit": true`, and on automatically whenever a `policy.json`
|
|
652
|
+
exists), each run also writes `audit.jsonl` into its own folder: signed, hash-chained lines (each carries the previous line's hash) that
|
|
653
|
+
`verifyAuditLog` in `src/audit.js` checks offline. Seat, cost and timing only, never task or
|
|
654
|
+
prompt text. Format: `docs/audit-schema.md`.
|
|
493
655
|
|
|
494
656
|
## Accessibility
|
|
495
657
|
|
|
496
|
-
The
|
|
658
|
+
The landing page (`docs/`) uses only native HTML elements for interaction - `<a href>`
|
|
497
659
|
links and `<details>/<summary>` for the expandable demo sections - specifically because those
|
|
498
660
|
are keyboard-operable by the browser itself, with no custom JavaScript to get wrong. Tested by
|
|
499
661
|
hand, 2026-09-13, on the live site:
|
|
@@ -515,8 +677,10 @@ hand, 2026-09-13, on the live site:
|
|
|
515
677
|
|
|
516
678
|
## Reporting a bug
|
|
517
679
|
|
|
518
|
-
Open an issue
|
|
519
|
-
|
|
680
|
+
Open an issue at
|
|
681
|
+
[github.com/muad-yasin/the-high-council-mcp/issues](https://github.com/muad-yasin/the-high-council-mcp/issues).
|
|
682
|
+
For anything security-related, or that should not be public, write to
|
|
683
|
+
[contact@sower-industries.de](mailto:contact@sower-industries.de) instead.
|
|
520
684
|
|
|
521
685
|
## If this makes you money
|
|
522
686
|
|