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.
Files changed (86) hide show
  1. package/.env.example +2 -3
  2. package/README.md +280 -116
  3. package/TROUBLESHOOTING.md +48 -0
  4. package/chains/cheap-7-v2.json +98 -0
  5. package/chains/cheap-7.json +93 -0
  6. package/chains/coder-gate-v1.json +56 -0
  7. package/chains/coder-gate-v2.json +55 -0
  8. package/chains/gp-judge-v1.json +31 -7
  9. package/chains/idea-open-c2.json +2 -13
  10. package/chains/mock-criteria-kinds.json +19 -0
  11. package/chains/mock-dispute.json +47 -0
  12. package/chains/mock-partitioned.json +62 -0
  13. package/chains/mock-patch-fallback.json +41 -0
  14. package/chains/mock-patch.json +41 -0
  15. package/chains/mock-proposals.json +4 -2
  16. package/chains/mock-security-review.json +45 -0
  17. package/chains/plan-auto-mistral.json +6 -6
  18. package/chains/plan-auto.json +2 -2
  19. package/chains/plan-debate-c2.json +1 -1
  20. package/chains/plan-debate-open-c2.json +2 -13
  21. package/chains/plan-debate-roles-c1.json +22 -7
  22. package/chains/plan-debate.json +1 -1
  23. package/chains/plan-open-7.json +93 -0
  24. package/chains/plan-premium-7.json +113 -0
  25. package/chains/seven.json +1 -6
  26. package/chains/us-only.json +2 -7
  27. package/chains/verify.json +1 -1
  28. package/package.json +38 -4
  29. package/schemas/report-v1.json +784 -0
  30. package/schemas/verdict-diff.json +41 -0
  31. package/src/api.js +190 -0
  32. package/src/argued.js +286 -0
  33. package/src/audit.js +11 -5
  34. package/src/board-export.js +40 -1
  35. package/src/budget.js +18 -6
  36. package/src/buys.js +8 -0
  37. package/src/cache-integrity.js +39 -16
  38. package/src/canary.js +47 -6
  39. package/src/chain-lint.js +440 -11
  40. package/src/chain.js +1782 -138
  41. package/src/cli.js +1272 -211
  42. package/src/cost.js +83 -3
  43. package/src/council-replay.js +131 -0
  44. package/src/criteria-kinds.js +169 -0
  45. package/src/denied-models.js +139 -0
  46. package/src/disagreement-groups.js +54 -0
  47. package/src/dissent-digest.js +105 -0
  48. package/src/fence.js +145 -0
  49. package/src/http-server.js +1 -1
  50. package/src/invocation.js +25 -0
  51. package/src/key-redaction.js +15 -45
  52. package/src/mcp/server.js +248 -57
  53. package/src/metrics.js +5 -1
  54. package/src/mock-demo.js +237 -0
  55. package/src/name-lint.js +54 -9
  56. package/src/outcome.js +29 -0
  57. package/src/partial-deliverable.js +29 -4
  58. package/src/patch-revise.js +91 -0
  59. package/src/peer-claim.js +65 -13
  60. package/src/policy.js +140 -3
  61. package/src/preflight.js +119 -8
  62. package/src/pricing.json +126 -18
  63. package/src/progress-spans.js +72 -0
  64. package/src/providers.js +420 -36
  65. package/src/quote-check.js +134 -0
  66. package/src/rematch.js +70 -0
  67. package/src/report-shape.js +198 -0
  68. package/src/role-diagnostics.js +10 -3
  69. package/src/roles.js +524 -47
  70. package/src/run-lock.js +106 -0
  71. package/src/run-state.js +54 -0
  72. package/src/run-status.js +84 -0
  73. package/src/scope-freeze.js +19 -3
  74. package/src/seat-role.js +5 -1
  75. package/src/secret-patterns.js +113 -0
  76. package/src/security-review.js +201 -0
  77. package/src/shape-rounds.js +5 -1
  78. package/src/spans.js +84 -0
  79. package/src/spend.js +44 -8
  80. package/src/stage-contract.js +53 -10
  81. package/src/superseded.js +73 -0
  82. package/src/tools.js +288 -24
  83. package/src/verdict-diff.js +63 -0
  84. package/src/verdict-stats.js +63 -22
  85. package/src/version.js +25 -0
  86. 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 $5. Use --max-usd none to run
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=5
18
+ MAX_USD_PER_RUN=7
package/README.md CHANGED
@@ -1,24 +1,29 @@
1
1
  # The High Council
2
2
 
3
- [![Test](https://github.com/muad-yasin/the-high-council-mcp/actions/workflows/test.yml/badge.svg)](https://github.com/muad-yasin/the-high-council-mcp/actions/workflows/test.yml)
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 github:muad-yasin/the-high-council-mcp council demo
8
-
9
- Add it to Claude Code as an MCP server the same way:
10
+ npx the-high-council council demo
10
11
 
11
- claude mcp add council -- npx -y github:muad-yasin/the-high-council-mcp council --mcp
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
- *(An npm package is coming - not yet published. Both lines above work today, straight from this
14
- GitHub repo, no npm account needed.)*
18
+ Add it to Claude Code as an MCP server:
15
19
 
16
- A planning harness that runs one idea past several AI models from different labs, makes them
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 no key ever leaves your machine.
21
- Run `npx github:muad-yasin/the-high-council-mcp council doctor` to see which of your own keys are
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
- **A visual walkthrough of all of this - the stages, one real run's debate board, and what that run
32
- cost - is at [muad-yasin.github.io/the-high-council-mcp](https://muad-yasin.github.io/the-high-council-mcp/).**
33
- A different write-up, built around one run's actual debate board, is at
34
- [sower-industries.de/en/MCP/](https://sower-industries.de/en/MCP/).
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
- "signoff": [ { "provider": "qwen", "model": "...", "signedOff": false,
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
- on your own disk. Nothing transmits it anywhere - but if you are rendering a board onto a public
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
- git clone https://github.com/muad-yasin/the-high-council-mcp.git
130
- cd the-high-council-mcp
131
- npm install
132
- cp .env.example .env
215
+ npm install -g the-high-council
216
+ council doctor
133
217
  ```
134
218
 
135
- Fill in `.env` with only the keys your chosen chain needs. Supported providers:
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` · `XAI_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
- node src/cli.js --help
179
- npm run dry -- --task tasks/your-idea.md --chain verify
307
+ council --help
308
+ council --task tasks/your-idea.md --chain verify --dry-run
180
309
 
181
310
  # a real run
182
- node src/cli.js --task tasks/your-idea.md --chain verify
311
+ council --task tasks/your-idea.md --chain verify
183
312
  ```
184
313
 
185
- `tasks/` and `runs/` are both gitignored. Your requests and everything the council writes about
186
- them stay on your machine - if you fork this repo, you will not accidentally publish them.
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
- `verify` is the cheap default: two labs, a hard two-round cap. Start there.
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 **$5**, and is checked *before* each paid
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
- node src/cli.js --task tasks/x.md --max-usd 2 # this run stops at $2
220
- node src/cli.js --task tasks/x.md --max-usd none # no ceiling
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
- node src/cli.js --resume runs/<id> --max-usd 10
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
- node src/cli.js --spend # today
237
- node src/cli.js --spend --days 7 # the last week
238
- node src/cli.js --cost-today # today by calendar day, with a per-model breakdown
239
- node src/cli.js --cost-today --date 2026-09-01
240
- node src/cli.js --stats --days 30 # how the debate mechanism itself is doing
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
- node src/cli.js --task tasks/your-idea.md --chain mock-budget --max-usd 1
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
- node src/cli.js --resume runs/<id>
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 - straight from GitHub:
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 github:muad-yasin/the-high-council-mcp council --mcp
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
- An npm package is coming - not yet published, no date. Once it lands:
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 mcp add high-council -- npx -y the-high-council --mcp
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
- Either way the server reads and writes in **your** working directory, not inside the package:
287
- `.env` for keys, `tasks/` for requests, `runs/` for output, and a `chains/` of your own takes
288
- precedence over the bundled ones.
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
- To run it by hand, from a clone:
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
- npm run mcp # or: node src/cli.js --mcp
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
- 31 chain configs live in `chains/`. Each one is plain JSON - the seat roster, which models fill
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, every seat on a real API, runs unattended end to end.
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 two Claude Code skill files shipped alongside this harness, not part of it:
448
- `backend-developer` and `frontend-developer` - general backend and frontend engineering rules
449
- (contract-first design, save/persistence integrity, accessibility, verification discipline) that
450
- apply to any codebase, not just this one. Same MIT/BYOK ethos as the harness itself. They don't
451
- claim to make code better; they describe what each rule guards against and why. Point Claude Code
452
- at this repo's `skills/` directory (or copy the two folders into your own project's
453
- `.claude/skills/`) to use them.
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 and the [demo page](https://muad-yasin.github.io/the-high-council-mcp/demo.html)
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 GitHub Pages site (`docs/`) ships no JavaScript and loads no third-party resource - see
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 GitHub Pages site (`docs/`) uses only native HTML elements for interaction - `<a href>`
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: [github.com/muad-yasin/the-high-council-mcp/issues](https://github.com/muad-yasin/the-high-council-mcp/issues).
519
- Or write to [contact@sower-industries.de](mailto:contact@sower-industries.de).
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