the-high-council 0.6.0
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 +19 -0
- package/CONTRIBUTING.md +41 -0
- package/LICENSE +21 -0
- package/PERSONAS.md +51 -0
- package/README.md +499 -0
- package/TROUBLESHOOTING.md +45 -0
- package/chains/cheap.json +35 -0
- package/chains/gp-judge-v1.json +80 -0
- package/chains/idea-open-c2.json +106 -0
- package/chains/mock-budget.json +15 -0
- package/chains/mock-debate.json +59 -0
- package/chains/mock-external.json +59 -0
- package/chains/mock-open.json +60 -0
- package/chains/mock-proposals.json +57 -0
- package/chains/mock-questions-wait.json +63 -0
- package/chains/mock-questions.json +63 -0
- package/chains/mock-relay.json +42 -0
- package/chains/mock-unanimous.json +42 -0
- package/chains/mock.json +17 -0
- package/chains/plan-auto-mistral.json +101 -0
- package/chains/plan-auto.json +131 -0
- package/chains/plan-cheap.json +82 -0
- package/chains/plan-debate-c2.json +86 -0
- package/chains/plan-debate-open-c2.json +98 -0
- package/chains/plan-debate-roles-c1.json +149 -0
- package/chains/plan-debate.json +116 -0
- package/chains/plan-fast.json +66 -0
- package/chains/plan-proposals-best-of-5.json +98 -0
- package/chains/plan-proposals.json +96 -0
- package/chains/plan-relay.json +83 -0
- package/chains/plan-thorough.json +82 -0
- package/chains/plan-unanimous.json +82 -0
- package/chains/seven-cheap.json +67 -0
- package/chains/seven.json +60 -0
- package/chains/smo-v2-cheap.json +67 -0
- package/chains/smo.json +50 -0
- package/chains/verify.json +40 -0
- package/package.json +55 -0
- package/src/board-export.js +77 -0
- package/src/budget.js +126 -0
- package/src/buys.js +44 -0
- package/src/cache-integrity.js +38 -0
- package/src/chain-lint.js +107 -0
- package/src/chain.js +880 -0
- package/src/cli.js +1031 -0
- package/src/cost-forecast.js +70 -0
- package/src/cost.js +139 -0
- package/src/errors.js +82 -0
- package/src/http-server.js +349 -0
- package/src/integrity.js +48 -0
- package/src/key-redaction.js +97 -0
- package/src/mcp/server.js +319 -0
- package/src/name-lint.js +186 -0
- package/src/partial-deliverable.js +38 -0
- package/src/peer-claim.js +98 -0
- package/src/personas.js +54 -0
- package/src/preflight.js +84 -0
- package/src/pricing.json +120 -0
- package/src/providers.js +268 -0
- package/src/replay.js +40 -0
- package/src/resume-brief.js +114 -0
- package/src/role-diagnostics.js +181 -0
- package/src/roles.js +520 -0
- package/src/schema-version.js +39 -0
- package/src/scope-freeze.js +35 -0
- package/src/seat-role.js +96 -0
- package/src/shape-rounds.js +58 -0
- package/src/spend.js +193 -0
- package/src/stage-contract.js +223 -0
- package/src/stage-submission.js +53 -0
- package/src/tie-break.js +94 -0
- package/src/ui/app.js +139 -0
- package/src/ui/index.html +43 -0
- package/src/ui/parse.js +101 -0
- package/src/ui/server.js +117 -0
- package/src/ui/style.css +37 -0
- package/src/verdict-stats.js +267 -0
- package/src/withdrawal-ledger.js +47 -0
package/.env.example
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Copy to .env and fill in only the labs the chosen chain actually uses.
|
|
2
|
+
# The CLI refuses to start if any seat in the chosen chain is missing its key.
|
|
3
|
+
ANTHROPIC_API_KEY=
|
|
4
|
+
OPENAI_API_KEY=
|
|
5
|
+
GOOGLE_API_KEY=
|
|
6
|
+
XAI_API_KEY=
|
|
7
|
+
MISTRAL_API_KEY=
|
|
8
|
+
DEEPSEEK_API_KEY=
|
|
9
|
+
GROQ_API_KEY=
|
|
10
|
+
TOGETHER_API_KEY=
|
|
11
|
+
COHERE_API_KEY=
|
|
12
|
+
OPENROUTER_API_KEY=
|
|
13
|
+
ZAI_API_KEY=
|
|
14
|
+
|
|
15
|
+
# Default per-run spend ceiling in USD. Overridden per run by --max-usd.
|
|
16
|
+
# 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
|
|
18
|
+
# without a ceiling.
|
|
19
|
+
MAX_USD_PER_RUN=5
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
This project has one maintainer. The bottleneck is reviewing pull requests, not writing code -
|
|
4
|
+
an unscoped PR costs more of that time than it saves. The three shapes below are pre-scoped and
|
|
5
|
+
easy to land; a PR outside them is welcome but will take longer to review, since it needs a scope
|
|
6
|
+
discussion first.
|
|
7
|
+
|
|
8
|
+
## The three smallest landable contributions
|
|
9
|
+
|
|
10
|
+
1. **A new provider adapter** (`src/providers.js`). Every provider except `mock`/`external` speaks
|
|
11
|
+
either the Anthropic Messages API or the OpenAI chat-completions shape via `OPENAI_COMPAT`.
|
|
12
|
+
Adding a new OpenAI-compatible provider is usually one entry in `OPENAI_COMPAT` plus a pricing
|
|
13
|
+
row in `src/pricing.json`. Test it the way the existing providers are tested: no network calls
|
|
14
|
+
in `node --test`, real calls are opt-in and cost real money.
|
|
15
|
+
|
|
16
|
+
2. **A new chain config** (`chains/*.json`). A chain is data, not code - it names which seats run
|
|
17
|
+
which stages. `council doctor` validates any chain you add against every shipped-provider's key
|
|
18
|
+
presence and prices it worst-case with zero network calls; run that against your new file
|
|
19
|
+
before opening a PR. Look at `chains/plan-debate.json` or `chains/verify.json` as a starting
|
|
20
|
+
shape depending on whether you want a debate-and-panel chain or a single-critic chain.
|
|
21
|
+
|
|
22
|
+
3. **A new mock fixture** (`src/providers.js`'s `callMock`, exercised from `test/*.test.js`). If
|
|
23
|
+
you're adding test coverage for a new code path in the chain itself, the offline `mock`
|
|
24
|
+
provider needs a new scripted branch (keyed on a `mock-<something>` model name) rather than a
|
|
25
|
+
real API call. See the existing branches in `callMock` - `mock-unreadable`,
|
|
26
|
+
`mock-provider-error` - for the shape: a model name that triggers one deterministic scripted
|
|
27
|
+
reply, documented with which real-world failure it stands in for.
|
|
28
|
+
|
|
29
|
+
## Everything else
|
|
30
|
+
|
|
31
|
+
Bug fixes, docs fixes, and typo fixes are always welcome with no scoping step. Anything larger -
|
|
32
|
+
a new CLI command, a new stage, a change to what a chain's JSON schema can express - should start
|
|
33
|
+
as an issue describing what it's for, before the PR, so review time isn't spent re-deriving scope
|
|
34
|
+
from a diff.
|
|
35
|
+
|
|
36
|
+
## Running the tests
|
|
37
|
+
|
|
38
|
+
npm test
|
|
39
|
+
|
|
40
|
+
Offline, no API key, no network call, no cost. `node --test` matches the project's own test
|
|
41
|
+
runner - no additional test framework to install.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sower Industries
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/PERSONAS.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Personas
|
|
2
|
+
|
|
3
|
+
A seat's optional `role.persona` (see `src/seat-role.js`) is a name and voice directive layered
|
|
4
|
+
onto a debate-stage prompt - it changes how a seat *talks*, never what it's graded on (see
|
|
5
|
+
`src/personas.js`, `src/name-lint.js`). The default set, defined in `src/personas.js`:
|
|
6
|
+
|
|
7
|
+
- **Moses**
|
|
8
|
+
- **Noah**
|
|
9
|
+
- **Matthew**
|
|
10
|
+
- **Van Gogh**
|
|
11
|
+
- **Parzival**
|
|
12
|
+
|
|
13
|
+
These are historical and religious figures, chosen deliberately because none of them is anyone's
|
|
14
|
+
trademark. That said, using any recognizable name as a software judge's voice is itself an
|
|
15
|
+
editorial choice: a public audience may read it as reverence, satire, or an implied endorsement by
|
|
16
|
+
association, in either direction. That reading is not intended, but it's real, and this file says
|
|
17
|
+
so plainly rather than leaving it for someone to notice on their own.
|
|
18
|
+
|
|
19
|
+
One flag, recorded once, on a decision that already stands: "Parzival" is the medieval literary
|
|
20
|
+
figure (Wolfram von Eschenbach), unambiguously public domain - the name is not anyone's IP. It is
|
|
21
|
+
also the alias the protagonist chooses in Ernest Cline's *Ready Player One* (novel and Warner Bros.
|
|
22
|
+
film), a work still under active copyright. The character name "Parzival" in that context is drawn
|
|
23
|
+
from the same public-domain legend and is not itself claimed as anyone's trademark, so the exposure
|
|
24
|
+
here is a secondary association in a reader's mind, not a legal one - worth having on the record,
|
|
25
|
+
not worth revisiting a decision already made.
|
|
26
|
+
|
|
27
|
+
**You can replace the whole set.** `loadPersonas()` in `src/personas.js` reads an operator-supplied
|
|
28
|
+
JSON file (path via the `COUNCIL_PERSONAS_FILE` environment variable, or passed directly) and uses
|
|
29
|
+
it in place of the default five entirely - nothing in this repo needs editing to do that. A
|
|
30
|
+
persona file is a flat object keyed by the same short key your chain's `role.persona` field
|
|
31
|
+
references:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"your-key": { "name": "Public-facing name", "voice": "One or two sentences of voice directive." }
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## The naming lint
|
|
40
|
+
|
|
41
|
+
`src/name-lint.js` scans every text file in this repository for name patterns matched against a
|
|
42
|
+
forbidden-name hash list, and fails loudly (not a warning) if any shipped file, doc, chain config,
|
|
43
|
+
task fixture, or prompt template contains one. This repository ships **no** forbidden names of its
|
|
44
|
+
own - the default list is empty. An operator (this author included) can add their own forbidden
|
|
45
|
+
names - their own trademark risks to guard against, not only this project's - via a local file
|
|
46
|
+
(`COUNCIL_FORBIDDEN_NAMES_FILE`) that is hashed at load time and never committed; see
|
|
47
|
+
`src/name-lint.js`'s own comments for why a hash, not a plain list, is what a public repo can
|
|
48
|
+
safely carry. `.gitignore` covers a `.council/` directory as the suggested place to put this file
|
|
49
|
+
and your own `COUNCIL_PERSONAS_FILE` - that's a convention, not an enforced one: the environment
|
|
50
|
+
variable accepts any path, and only the `.council/` directory specifically is protected from an
|
|
51
|
+
accidental `git add`.
|
package/README.md
ADDED
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
# The High Council
|
|
2
|
+
|
|
3
|
+
[](https://github.com/muad-yasin/the-high-council-mcp/actions/workflows/test.yml)
|
|
4
|
+
|
|
5
|
+
See it work right now - no keys, no setup, no cost:
|
|
6
|
+
|
|
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
|
+
|
|
11
|
+
claude mcp add council -- npx -y github:muad-yasin/the-high-council-mcp council --mcp
|
|
12
|
+
|
|
13
|
+
*(An npm package is coming - not yet published. Both lines above work today, straight from this
|
|
14
|
+
GitHub repo, no npm account needed.)*
|
|
15
|
+
|
|
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.
|
|
18
|
+
|
|
19
|
+
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
|
|
22
|
+
set, which shipped chains you can already run with them, and what each would cost - before
|
|
23
|
+
spending anything.
|
|
24
|
+
|
|
25
|
+
> **On what this does and doesn't claim.** This repo publishes the mechanism: the chains, the seat
|
|
26
|
+
> rosters, the stage order. It does not claim to produce better plans than a single good model
|
|
27
|
+
> would. That is an open question and we have not measured it. What it does, concretely, is make
|
|
28
|
+
> disagreement between models *visible and recorded* instead of averaged away - you can read who
|
|
29
|
+
> objected to what, who withdrew a proposal under argument, and who held their position.
|
|
30
|
+
|
|
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/).
|
|
35
|
+
|
|
36
|
+
## How it works
|
|
37
|
+
|
|
38
|
+
A run moves through fixed stages. Which stages fire depends on the chain you pick.
|
|
39
|
+
|
|
40
|
+
1. **Questions** - a seat reads the request and asks only the questions whose answers would change
|
|
41
|
+
the output. You answer them (or take its stated defaults).
|
|
42
|
+
2. **Criteria** - the request becomes a short list of acceptance criteria, each one a yes/no check
|
|
43
|
+
rather than a matter of taste.
|
|
44
|
+
3. **Skeleton** - an outline the other models will propose against. Names the parts, decides
|
|
45
|
+
nothing.
|
|
46
|
+
4. **Proposals** - every lab proposes buildable parts, blind to each other.
|
|
47
|
+
5. **Debate** - the labs read each other's proposals, anonymised, and post support / object /
|
|
48
|
+
merge. Then each author replies: keep, amend, or withdraw.
|
|
49
|
+
6. **Build** - one seat integrates the surviving proposals into a single document.
|
|
50
|
+
7. **Panel review** - every critic independently grades the draft against the acceptance criteria,
|
|
51
|
+
blind. Not unanimous? It revises against the union of every objection and the panel reviews
|
|
52
|
+
again, up to the chain's round cap.
|
|
53
|
+
8. **Handoff** - a `HANDOFF.md` written for whoever executes the result.
|
|
54
|
+
|
|
55
|
+
Every run writes a folder: the deliverable, `BOARD.md` (the full debate - every post, every
|
|
56
|
+
withdrawal), `HANDOFF.md`, a per-lab scoreboard, and the real token/cost accounting.
|
|
57
|
+
|
|
58
|
+
### Reading a run with a program
|
|
59
|
+
|
|
60
|
+
`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.
|
|
62
|
+
|
|
63
|
+
```jsonc
|
|
64
|
+
{
|
|
65
|
+
"runId": "...", "chain": "...", "passed": false, "maxUsd": 5,
|
|
66
|
+
"criteria": [ "each acceptance criterion, as written before the debate" ],
|
|
67
|
+
"questions": [ { "question": "...", "why": "...", "default": "..." } ], // null if the chain skipped them
|
|
68
|
+
"proposals": [ { "id": "DEEPSEEK-1", "lab": "deepseek", "model": "...",
|
|
69
|
+
"title": "...", "serves": "...", "what": "...", "why": "...",
|
|
70
|
+
"how": "...", "acceptance_test": "...", "attempt": 1,
|
|
71
|
+
"withdrawn": true, "amended": true, "replaced_by": "GLM-1" } ],
|
|
72
|
+
"dropouts": [ { "lab": "...", "model": "...", "stage": "proposals", "reason": "..." } ],
|
|
73
|
+
"debate": {
|
|
74
|
+
"posts": [ { "by": "deepseek", "on": "QWEN-1", "stance": "object|support|merge",
|
|
75
|
+
"text": "...", "merge_with": "GLM-2" } ],
|
|
76
|
+
"replies": [ { "id": "DEEPSEEK-1", "action": "keep|amend|withdraw",
|
|
77
|
+
"text": "...", "replaced_by": "GLM-1" } ]
|
|
78
|
+
},
|
|
79
|
+
"signoff": [ { "provider": "qwen", "model": "...", "signedOff": false,
|
|
80
|
+
"objections": [ { "criterion": "...", "problem": "...", "fix": "..." } ] } ],
|
|
81
|
+
"lastCritique": { "meets": false, "failures": [ { "criterion": "...", "lab": "qwen" } ] },
|
|
82
|
+
"scoreboard": {
|
|
83
|
+
"rows": [ /* one per proposal, with its outcome */ ],
|
|
84
|
+
"labs": [ { "lab": "deepseek", "model": "...", "proposed": 3, "accepted": 0,
|
|
85
|
+
"cut": 0, "withdrawn": 3, "unaccounted": 0, "built": null } ]
|
|
86
|
+
},
|
|
87
|
+
"totals": { "input": 0, "output": 0, "total": 0, "usd": 0, "unpriced": [] }
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`proposals` plus `debate.posts` is a directed graph with verifiable edges: one node per proposal,
|
|
92
|
+
one edge per posture, and `replies[].action` says what each author did with their own proposal
|
|
93
|
+
once they had read the argument against it. That is the whole artifact, already machine-readable.
|
|
94
|
+
`scoreboard.labs` is the per-lab tally already aggregated for you — start there for a scoreboard
|
|
95
|
+
rather than counting `proposals` yourself.
|
|
96
|
+
|
|
97
|
+
**`dropouts` is the field you will regret ignoring.** A lab whose proposals came back unreadable
|
|
98
|
+
after a retry is dropped from the run: it is not in `proposals`, not in the debate, and not in the
|
|
99
|
+
scoreboard. It is only in `dropouts`. A consumer that counts labs from `proposals` and reports
|
|
100
|
+
"four labs debated this" will be wrong — the roster shrank, and the run log says so loudly at the
|
|
101
|
+
time. Report a seated lab that produced nothing as what it was, or you are publishing a panel that
|
|
102
|
+
was smaller than you claim. Treat `null` and `[]` alike here; runs written by older versions have
|
|
103
|
+
no such field at all.
|
|
104
|
+
|
|
105
|
+
**Two of these are not closed schemas.** `debate.replies[]` is built by spreading the model's own
|
|
106
|
+
reply object and normalising `id`, `action` and `replaced_by` over it, so an entry carries at least
|
|
107
|
+
those plus `text` and may carry more (an `amend` often brings a `how`). `replaced_by` is only set
|
|
108
|
+
when the action is `withdraw`. `proposals[]` likewise carries `withdrawn` / `amended` /
|
|
109
|
+
`replaced_by` only when they apply. Read defensively: check for a field, do not assume it.
|
|
110
|
+
|
|
111
|
+
`signoff[].objections` is why a seat declined, on the seat's own record. `signedOff: null` means
|
|
112
|
+
the seat gave no usable reply and abstained - neither a pass nor an objection, and `objections` is
|
|
113
|
+
`null` rather than empty so the two stay apart. A seat that agreed has an empty list.
|
|
114
|
+
The same objections also appear flattened in `lastCritique.failures[]`, tagged with `lab`, because
|
|
115
|
+
the reviser wants the union across the whole panel. Both are built in one pass; they cannot drift.
|
|
116
|
+
|
|
117
|
+
**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
|
|
119
|
+
page, drop that field. The debate itself is the part worth showing.
|
|
120
|
+
|
|
121
|
+
## Requirements
|
|
122
|
+
|
|
123
|
+
- Node 20+
|
|
124
|
+
- API keys for whichever labs the chain you choose actually uses
|
|
125
|
+
|
|
126
|
+
## Setup
|
|
127
|
+
|
|
128
|
+
```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
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Fill in `.env` with only the keys your chosen chain needs. Supported providers:
|
|
136
|
+
|
|
137
|
+
`ANTHROPIC_API_KEY` · `OPENAI_API_KEY` · `GOOGLE_API_KEY` · `MISTRAL_API_KEY` ·
|
|
138
|
+
`DEEPSEEK_API_KEY` · `GROQ_API_KEY` · `TOGETHER_API_KEY` · `COHERE_API_KEY` ·
|
|
139
|
+
`OPENROUTER_API_KEY` · `ZAI_API_KEY` · `XAI_API_KEY`
|
|
140
|
+
|
|
141
|
+
The CLI refuses to start if any seat in the chosen chain is missing its key, rather than failing
|
|
142
|
+
halfway through a paid run.
|
|
143
|
+
|
|
144
|
+
## Quick start (CLI)
|
|
145
|
+
|
|
146
|
+
A task file is the request the council plans against: plain prose, written by you. There is no
|
|
147
|
+
template and no format - write what you actually want, including the constraints that matter.
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
mkdir -p tasks
|
|
151
|
+
echo "Plan the data model for a bookmarking app. Single user, offline-first." > tasks/your-idea.md
|
|
152
|
+
|
|
153
|
+
# see what's available and what it would cost
|
|
154
|
+
node src/cli.js --help
|
|
155
|
+
npm run dry -- --task tasks/your-idea.md --chain verify
|
|
156
|
+
|
|
157
|
+
# a real run
|
|
158
|
+
node src/cli.js --task tasks/your-idea.md --chain verify
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
`tasks/` and `runs/` are both gitignored. Your requests and everything the council writes about
|
|
162
|
+
them stay on your machine - if you fork this repo, you will not accidentally publish them.
|
|
163
|
+
|
|
164
|
+
`verify` is the cheap default: two labs, a hard two-round cap. Start there.
|
|
165
|
+
|
|
166
|
+
### Telling the council what your build session can actually use
|
|
167
|
+
|
|
168
|
+
One optional convention, worth the four lines it costs. If your task file ends with a section
|
|
169
|
+
headed **`## Available tools`**, the handoff seat will name the right one in the acceptance test
|
|
170
|
+
for each item of work, instead of inventing a check from nothing:
|
|
171
|
+
|
|
172
|
+
```markdown
|
|
173
|
+
## Available tools
|
|
174
|
+
|
|
175
|
+
- `scope-gate` - decides GO / NEEDS-SPEC / KILL before anything is built
|
|
176
|
+
- `bug-audit` - reads code line by line, reports verified defects, edits nothing
|
|
177
|
+
- `npm test` - the project's own suite
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The council is told what exists, not how it is invoked, and is instructed never to name a tool
|
|
181
|
+
that is not on your list. Leave the section out and the handoff assumes nothing beyond your test
|
|
182
|
+
suite - which is what it did before this existed, and what it will keep doing.
|
|
183
|
+
|
|
184
|
+
This costs no tokens you were not already spending: the task file is already in the handoff seat's
|
|
185
|
+
prompt. It is the difference between *"write a test for this"* and *"run `scope-gate` on this
|
|
186
|
+
before building it."*
|
|
187
|
+
|
|
188
|
+
### The spend cap
|
|
189
|
+
|
|
190
|
+
Every run has a per-run ceiling in USD. It defaults to **$5**, and is checked *before* each paid
|
|
191
|
+
stage - a stage that could take the run past the ceiling is never called, so the cap holds rather
|
|
192
|
+
than reporting the overspend afterwards.
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
node src/cli.js --task tasks/x.md --max-usd 2 # this run stops at $2
|
|
196
|
+
node src/cli.js --task tasks/x.md --max-usd none # no ceiling
|
|
197
|
+
export MAX_USD_PER_RUN=20 # change the default
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
A run that hits the ceiling stops cleanly and writes `STOPPED-budget.md` saying what it spent, which
|
|
201
|
+
stage it stopped at, and what that stage would have cost. Nothing is half-written: it produces no
|
|
202
|
+
`deliverable.md` and no `report.json`, so a stopped run never reads as a finished one. Continue it
|
|
203
|
+
with a higher ceiling - completed stages replay from disk and cost nothing the second time:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
node src/cli.js --resume runs/<id> --max-usd 10
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
The cap governs one run. To see what you have spent across all of them:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
node src/cli.js --spend # today
|
|
213
|
+
node src/cli.js --spend --days 7 # the last week
|
|
214
|
+
node src/cli.js --cost-today # today by calendar day, with a per-model breakdown
|
|
215
|
+
node src/cli.js --cost-today --date 2026-09-01
|
|
216
|
+
node src/cli.js --stats --days 30 # how the debate mechanism itself is doing
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
That is read back off the run folders on disk - there is no ledger file, nothing is recorded
|
|
220
|
+
anywhere else, and nothing leaves your machine. Runs still going, or stopped by the cap, are
|
|
221
|
+
counted from the stages they already paid for. The same figures are available to an MCP client as
|
|
222
|
+
`spend_report`.
|
|
223
|
+
|
|
224
|
+
To watch this work without spending anything, the `mock-budget` chain calls no API but carries
|
|
225
|
+
fixture prices:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
node src/cli.js --task tasks/your-idea.md --chain mock-budget --max-usd 1
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
If a chain pauses for your input, it writes `NEEDS-<stage>.md` into the run folder and tells you
|
|
232
|
+
how to resume:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
# write your answer to runs/<id>/answers.md, then:
|
|
236
|
+
node src/cli.js --resume runs/<id>
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Quick start (MCP)
|
|
240
|
+
|
|
241
|
+
Register the server with your MCP client. No clone needed - straight from GitHub:
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
claude mcp add council -- npx -y github:muad-yasin/the-high-council-mcp council --mcp
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Or from a clone of this repo:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
claude mcp add high-council -- node /absolute/path/to/the-high-council-mcp/src/mcp/server.js
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**The path must be absolute.** The client starts the server from its own working directory, not
|
|
254
|
+
from this one, so a relative path resolves somewhere unexpected and the server never starts.
|
|
255
|
+
|
|
256
|
+
An npm package is coming - not yet published, no date. Once it lands:
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
claude mcp add high-council -- npx -y the-high-council --mcp
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Either way the server reads and writes in **your** working directory, not inside the package:
|
|
263
|
+
`.env` for keys, `tasks/` for requests, `runs/` for output, and a `chains/` of your own takes
|
|
264
|
+
precedence over the bundled ones.
|
|
265
|
+
|
|
266
|
+
To run it by hand, from a clone:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
npm run mcp # or: node src/cli.js --mcp
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Then drive it with these tools:
|
|
273
|
+
|
|
274
|
+
| Tool | What it does |
|
|
275
|
+
|---|---|
|
|
276
|
+
| `list_chains` | Available chains with descriptions and worst-case price |
|
|
277
|
+
| `write_task` | Write the request the harness plans against |
|
|
278
|
+
| `dry_run` | Price a run before spending anything |
|
|
279
|
+
| `start_run` | Start a run in the background (`max_usd` sets its ceiling) |
|
|
280
|
+
| `run_status` | Stage reached, panel verdicts, scoreboard, cost, budget remaining |
|
|
281
|
+
| `spend_report` | What every run has cost across a window of days, plus `session_cost_today` (calendar-day, per-model breakdown), derived from disk |
|
|
282
|
+
| `verdict_stats` | How the debate mechanism itself is doing, per chain and per lab: sign-off rate, rounds, objections, dropouts, cost/wall time, largest prompt files - derived from disk |
|
|
283
|
+
| `external_prompt` | The prompt a paused external stage is waiting on - **read it with this, not by opening the file**; the prompts are routinely tens of thousands of tokens and most clients silently truncate a file read |
|
|
284
|
+
| `prepare_stage_prompt` | Write a self-contained bundle for a paused stage, so a driving session doing other work at the same time can dispatch it to a fresh subagent instead of authoring it inline - see [`docs/dispatch-pattern.md`](docs/dispatch-pattern.md) |
|
|
285
|
+
| `submit_stage` | Answer a paused stage and resume. Optional `claimed_by` records who's answering; a second submission for an already-answered stage no longer errors - it's kept as `<stage>.late.md` with a warning instead of being rejected |
|
|
286
|
+
| `resume_run` | Resume a paused run, or raise `max_usd` on one the cap stopped |
|
|
287
|
+
| `read_run_file` | Read any file from a run folder |
|
|
288
|
+
| `list_runs` | Past runs |
|
|
289
|
+
| `plan_outline` | Outline pass |
|
|
290
|
+
|
|
291
|
+
**External vs. API-backed seats.** `{ "provider": "external" }` pauses a run at that seat so a
|
|
292
|
+
Claude Code session on a flat-rate subscription plays it - free at the point of use, since the
|
|
293
|
+
subagent runs on the same subscription. If you don't hold a flat-rate subscription and pay
|
|
294
|
+
metered rates for everything anyway, `{ "provider": "anthropic" }` (or another API provider) may
|
|
295
|
+
be simpler for those seats: no dispatch pattern to learn, at roughly 5x the metered cost of the
|
|
296
|
+
same debate on external, based on one measured comparison, not a guarantee. Not the default
|
|
297
|
+
anywhere in this repo's config, README ordering, or example chains - external stays recommended
|
|
298
|
+
for anyone with a subscription, since the project's cost story depends on it.
|
|
299
|
+
|
|
300
|
+
## Chains
|
|
301
|
+
|
|
302
|
+
31 chain configs live in `chains/`. Each one is plain JSON - the seat roster, which models fill
|
|
303
|
+
which seat, the round cap, and whether proposals/debate/handoff stages run. They are meant to be
|
|
304
|
+
copied and edited.
|
|
305
|
+
|
|
306
|
+
A few worth knowing:
|
|
307
|
+
|
|
308
|
+
- **`verify`** - two labs, two rounds. The recommended starting point.
|
|
309
|
+
- **`cheap`** - small models throughout. For testing the harness itself, not for real work.
|
|
310
|
+
- **`plan-debate`** - five labs propose blind, debate each other's proposals anonymised, then a
|
|
311
|
+
blind panel grades the integrated draft.
|
|
312
|
+
- **`plan-auto`** - the full open-scope chain, every seat on a real API, runs unattended end to end.
|
|
313
|
+
- **`plan-unanimous`** - every critic must independently sign off on the *same* draft. Three rounds
|
|
314
|
+
here means up to fifteen critic calls, not five.
|
|
315
|
+
|
|
316
|
+
Read a chain's `description` field before running it; they say what they cost you in calls.
|
|
317
|
+
|
|
318
|
+
### Optional chain-config fields
|
|
319
|
+
|
|
320
|
+
- **`schemaVersion`** - an integer, optional. `council doctor` warns (never fails) when a chain
|
|
321
|
+
omits it or names an older/newer one than this build knows about. A chain file without it keeps
|
|
322
|
+
working exactly as it always did - this is a warning, not a requirement.
|
|
323
|
+
- **`max_proposals_per_seat`** - an integer, **opt-in, no default**. Debate size stays unlimited
|
|
324
|
+
unless a chain file explicitly sets this. When it is set and one seat's own proposals still
|
|
325
|
+
exceed it, that seat gets one merge prompt to fold its own list down before the debate board
|
|
326
|
+
ever sees the extras.
|
|
327
|
+
- **`role`** - optional, on any `seats.proposers` entry only (set anywhere else and `council
|
|
328
|
+
doctor` rejects it fail-loud, since it would silently do nothing there): `{ lens?, persona? }`.
|
|
329
|
+
`lens` is one of `adversary | integrator | long-horizon | user-advocate | security-and-legal` -
|
|
330
|
+
a critique function. `persona` is a name - a voice, resolved against the default set in
|
|
331
|
+
`PERSONAS.md` when it matches, otherwise used as free text. Applies only to that seat's
|
|
332
|
+
debate-stage prompt; the panel/critique stage that sets `passed` never sees it, enforced by a
|
|
333
|
+
source-level guard, not just an intention. A chain with no `role` set is byte-identical to
|
|
334
|
+
before. **No efficacy claim**: this ships the mechanism, not evidence that it helps - see
|
|
335
|
+
CHANGELOG.md's 0.6.0 entry.
|
|
336
|
+
|
|
337
|
+
## New in 0.6.0
|
|
338
|
+
|
|
339
|
+
- **Role-assigned debate seats** - see the `role` field above. Ships the mechanism only; whether
|
|
340
|
+
it changes anything about a real debate is untested by this release.
|
|
341
|
+
- **`report.json`'s `debate.diagnostics`** - four failure-mode signals computed from a run's own
|
|
342
|
+
real debate output (never from an offline probe): a seat quoting no evidence despite objecting
|
|
343
|
+
or merging, textual overlap between differently-lensed seats' posts on the same proposal, a
|
|
344
|
+
same-run gap between role-bearing and role-less seats' evidence quoting, and the share of a
|
|
345
|
+
seat's own words that fall inside quoted evidence versus voice. Present (with nulls/empty
|
|
346
|
+
flags where there's nothing to compute) on any run that had a debate stage; absent otherwise.
|
|
347
|
+
- **`debate.tie_break`** - a `report.json` field recording a weighted-tiebreak event, when one
|
|
348
|
+
fires. Not yet wired into a live vote-counting decision in this release.
|
|
349
|
+
- **`PERSONAS.md`** - the five default public persona names and their voice directives, and how
|
|
350
|
+
an operator replaces the whole set with their own via `COUNCIL_PERSONAS_FILE`.
|
|
351
|
+
|
|
352
|
+
## New in 0.5.0
|
|
353
|
+
|
|
354
|
+
- **`council init [--yes]`** - the first thing to run in a fresh clone with no keys yet. Prints a
|
|
355
|
+
key check, writes a starter chain and task file you own (`chains/my-first-chain.json`,
|
|
356
|
+
`tasks/my-first-task.md` - a rerun never overwrites an edit you made to either), prices the
|
|
357
|
+
starter chain with no network call, then runs a canned, all-mock, $0 task end to end so the
|
|
358
|
+
first thing you inspect is a real run folder, not just terminal output.
|
|
359
|
+
- **`council doctor --chain <file>`** - lints one chain config before you ever run it: a seat
|
|
360
|
+
under a misspelled key (never wired to any stage), a missing or empty `seats.critics` (the
|
|
361
|
+
review round can't run), or a seat naming a provider this codebase doesn't know. The same check
|
|
362
|
+
also runs automatically, fail-loud, the moment you try to actually run a broken chain - before
|
|
363
|
+
any paid call.
|
|
364
|
+
- **`council doctor --scan-artifacts`** - scans your `tasks/` and `chains/` for API-key-shaped
|
|
365
|
+
strings before you commit or share them. Reports the file and line, never the matched text.
|
|
366
|
+
- **`council --forecast-cost --chain <name> [--days N]`** - a realistic-case USD range for a
|
|
367
|
+
chain, built from its own historical runs on your machine and repriced at today's rates -
|
|
368
|
+
distinct from `--dry-run`'s worst-case estimate from a chain's declared token assumptions.
|
|
369
|
+
- **`council export-board --run <folder> --out <file>`** - a run's proposals, debate, replies and
|
|
370
|
+
verdict as one self-contained HTML file. No external assets, no server, `<details>` sections.
|
|
371
|
+
- **`council replay --run <folder> [--json]`** - a numbered, step-by-step transcript of a run's
|
|
372
|
+
reasoning in your terminal, with a `--json` mode for scripting.
|
|
373
|
+
- **A structured error catalog** (`COUNCIL-E001`-`COUNCIL-E004`, see [TROUBLESHOOTING.md](TROUBLESHOOTING.md))
|
|
374
|
+
for the hard-fail paths this project actually has - a missing key, an unpriced model, a
|
|
375
|
+
malformed chain file, an unreadable stage reply - each with a plain-words cause, a concrete fix
|
|
376
|
+
naming the real file, and a doc pointer. Degradable conditions exit 5; fatal ones exit 6.
|
|
377
|
+
- **Structured per-stage JSON logs** - every run now also writes `stage-log.jsonl` (one line per
|
|
378
|
+
stage: seat, lab, token counts, cost, timing - no prompt content) alongside the existing
|
|
379
|
+
markdown/`report.json` artifacts.
|
|
380
|
+
- **[CONTRIBUTING.md](CONTRIBUTING.md)** - the three smallest landable contribution shapes, for
|
|
381
|
+
anyone who wants to send a PR rather than only file an issue.
|
|
382
|
+
|
|
383
|
+
None of the above change any existing chain's behaviour. `schemaVersion` and
|
|
384
|
+
`max_proposals_per_seat` are both opt-in; a chain file that predates 0.5.0 runs exactly as it did
|
|
385
|
+
before.
|
|
386
|
+
|
|
387
|
+
## How this was built
|
|
388
|
+
|
|
389
|
+
Vibecoded, with **Claude Code** doing the writing, by one person at
|
|
390
|
+
[Sower Industries](https://sower-industries.de). Parts of it were planned by the harness itself —
|
|
391
|
+
the build order for its own v2 went through a four-lab council, and the plan came back with one of
|
|
392
|
+
its findings built on evidence that turned out to be wrong, which is recorded rather than quietly
|
|
393
|
+
dropped.
|
|
394
|
+
|
|
395
|
+
The parts worth knowing, because they explain why the code looks the way it does:
|
|
396
|
+
|
|
397
|
+
**Almost every defensive branch here is a headstone.** `parseJson` in `chain.js` repairs two
|
|
398
|
+
specific malformations — an unescaped `"` inside a markdown-quoted span, and raw newlines inside
|
|
399
|
+
string values — because three consecutive real runs died on the first one and silently logged a
|
|
400
|
+
pass that never happened. The comments name the run id and the date. The retry that disables
|
|
401
|
+
thinking exists because an Anthropic seat burned its entire `maxTokens` budget thinking and
|
|
402
|
+
returned nothing. The `ROSTER SHRANK` warning exists because a lab can return nothing and vanish
|
|
403
|
+
from the scoreboard without saying so. None of these were designed in advance; each one is a day
|
|
404
|
+
that went wrong.
|
|
405
|
+
|
|
406
|
+
**The failure modes are testable offline.** The `mock` provider has named models
|
|
407
|
+
(`mock-unreadable`, `mock-provider-error`, `mock-proposer-empty`, `mock-critic-holdout`) that each
|
|
408
|
+
drive one of those branches for $0, so the regression tests run without keys and without spend.
|
|
409
|
+
|
|
410
|
+
**`docs/` ships no JavaScript on purpose.** The landing page arrived from a design tool depending
|
|
411
|
+
on an unlicensed runtime that also fetched React and Babel from a CDN at page load. Shipping it
|
|
412
|
+
would have relicensed someone else's build artifact as MIT and put a third-party request on a page
|
|
413
|
+
shared with a German site. Its loops were pre-rendered to static HTML and the fonts self-hosted
|
|
414
|
+
instead. `test/landing-page.test.js` fails if a script tag or a third-party URL ever comes back —
|
|
415
|
+
and if the page's typed-in numbers stop matching the repo, which has already caught the page
|
|
416
|
+
claiming 29 chains and 12 tools when there were 30 and 11.
|
|
417
|
+
|
|
418
|
+
No claim is made here that any of this produces better plans. It has not been measured.
|
|
419
|
+
|
|
420
|
+
## Known limits, stated plainly
|
|
421
|
+
|
|
422
|
+
- The spend cap is enforced against a **worst case**, not a prediction: the whole prompt billed as
|
|
423
|
+
input plus the seat's entire `maxTokens` budget billed as output (doubled for Anthropic seats,
|
|
424
|
+
which may retry once). Real stages almost never cost that much, so a run can stop with headroom
|
|
425
|
+
left. That is the intended trade - resume it with a higher ceiling.
|
|
426
|
+
- A seat whose model has no entry in `src/pricing.json` is **unpriced, and therefore uncapped**.
|
|
427
|
+
It contributes $0 to the running total no matter what it really costs. Check `dry_run` output
|
|
428
|
+
for `unpriced` before trusting a ceiling.
|
|
429
|
+
- Prices in `src/pricing.json` are hand-maintained list prices, last verified 2026-09-06. They are
|
|
430
|
+
estimates, not invoices. Your provider's bill is the real number.
|
|
431
|
+
- Chains with many labs and high round caps get expensive quickly. `plan-unanimous` at three rounds
|
|
432
|
+
is fifteen critic calls; `plan-auto` runs several frontier models over multiple rounds. Price
|
|
433
|
+
before you run.
|
|
434
|
+
- A panel that signs off is not a guarantee the output is correct. It means every critic seat
|
|
435
|
+
checked it against the stated acceptance criteria and found nothing. Criteria that are vague
|
|
436
|
+
produce sign-offs that mean nothing - the quality of the run depends heavily on the quality of
|
|
437
|
+
the criteria stage.
|
|
438
|
+
- Some chains pause for human input by design. They are not stuck.
|
|
439
|
+
|
|
440
|
+
## Privacy
|
|
441
|
+
|
|
442
|
+
This tool and the [demo page](https://muad-yasin.github.io/the-high-council-mcp/demo.html)
|
|
443
|
+
collect nothing. Stated plainly, not as a claim about quality:
|
|
444
|
+
|
|
445
|
+
- No telemetry, no analytics, no tracking of any kind, anywhere in this repo.
|
|
446
|
+
- The only network calls this tool ever makes are to the AI provider APIs you configure with
|
|
447
|
+
your own keys (`ANTHROPIC_API_KEY`, `OPENROUTER_API_KEY`, and so on) - and only when you start
|
|
448
|
+
a real run with a non-mock, non-external seat. `council doctor` and `council demo` make zero
|
|
449
|
+
network calls; both are implemented to read only local files and environment variable names.
|
|
450
|
+
- The GitHub Pages site (`docs/`) ships no JavaScript and loads no third-party resource - see
|
|
451
|
+
`test/landing-page.test.js`, which fails the build if either ever changes.
|
|
452
|
+
- Everything a run produces - the task, the debate, the deliverable, the cost - is written to a
|
|
453
|
+
folder on your own disk (`runs/<id>/`) and nowhere else. Deleting that folder deletes the
|
|
454
|
+
record. See `src/spend.js`'s own documentation for why spend accounting is derived from those
|
|
455
|
+
folders rather than kept in a separate log.
|
|
456
|
+
|
|
457
|
+
## Accessibility
|
|
458
|
+
|
|
459
|
+
The GitHub Pages site (`docs/`) uses only native HTML elements for interaction - `<a href>`
|
|
460
|
+
links and `<details>/<summary>` for the expandable demo sections - specifically because those
|
|
461
|
+
are keyboard-operable by the browser itself, with no custom JavaScript to get wrong. Tested by
|
|
462
|
+
hand, 2026-09-13, on the live site:
|
|
463
|
+
|
|
464
|
+
- **`index.html`**: tabbed from the page's first link; focus reached the "Clone the repo",
|
|
465
|
+
"How it works" and "Try it (demo)" buttons in order, each showing a visible focus ring;
|
|
466
|
+
pressing Enter on "Try it (demo)" navigated to `demo.html`, the same as a click.
|
|
467
|
+
- **`demo.html`**: tabbed to the first proposal's `<summary>` ("A-1 Synchronous invalidation...");
|
|
468
|
+
pressing Enter expanded it in place (the ▶ marker flipped to ▼ and the body text appeared),
|
|
469
|
+
identical to clicking it.
|
|
470
|
+
- No custom widget on any page (`index.html`, `board.html`, `demo.html`) uses a `<div>` or
|
|
471
|
+
`<span>` with a click handler in place of a real interactive element - checked directly in the
|
|
472
|
+
page source, not inferred.
|
|
473
|
+
- No image ships anywhere in `docs/` (checked directly - zero `<img>` tags across all three
|
|
474
|
+
pages), so there is no informative image that could be missing alt text.
|
|
475
|
+
- Primary body text (`#8d8a84`/`#b9b5ad`) against the page background (`#0a0a0b`) measures
|
|
476
|
+
roughly 5.7:1 contrast by the WCAG relative-luminance formula, above the 4.5:1 AA threshold
|
|
477
|
+
for normal text.
|
|
478
|
+
|
|
479
|
+
## Reporting a bug
|
|
480
|
+
|
|
481
|
+
Open an issue: [github.com/muad-yasin/the-high-council-mcp/issues](https://github.com/muad-yasin/the-high-council-mcp/issues).
|
|
482
|
+
Or write to [contact@sower-industries.de](mailto:contact@sower-industries.de).
|
|
483
|
+
|
|
484
|
+
## If this makes you money
|
|
485
|
+
|
|
486
|
+
The licence is MIT. You owe nothing, and that is the whole licence - nothing below changes it.
|
|
487
|
+
|
|
488
|
+
If The High Council ends up helping you build something that earns, I'd ask for **0.7%** of what it
|
|
489
|
+
earns. Not a fee, not a clause, not a subscription. A request between people who build things.
|
|
490
|
+
|
|
491
|
+
There is no reporting, no audit, no tracking, and nothing checks. **No is a complete answer** - use
|
|
492
|
+
it, fork it, sell what you build with it, and never think about this section again. That is a fine
|
|
493
|
+
outcome and it's why the licence says what it says.
|
|
494
|
+
|
|
495
|
+
If you'd rather say yes: [pay what you think it's worth](https://buy.stripe.com/cNi14neoycSF0sseYrfjG01).
|
|
496
|
+
|
|
497
|
+
## License
|
|
498
|
+
|
|
499
|
+
MIT. See [LICENSE](LICENSE). The section above is a request, not a term of it.
|