Stage 01
Challenge
Claude Sonnet 5, as Challenger
Examines the proposed change against the constitution’s binding constraints and surfaces evidence of violations. Its job is to find fault, not to be fair.
In the matter of every change Claude Code proposes
Bench is a constitutional governance layer for Claude Code. Each proposed edit is challenged, defended, and ruled on against a declared constitution before it touches your files, and every verdict is hash-chained into an append-only ledger.
Governance of AI reasoning is a primitive, not a feature.
+ try: + load_constitution(path) + except Exception: + pass
The problem
AI coding tools ship code no one argued with. When Claude Code writes a function, nothing stops it from swallowing errors silently, leaking credentials, or creeping past the scope of the task. Self-verification is a step forward, but without adversarial challenge, binding authority, and cryptographic evidence, it is just an opinion.
Bench inserts binding governance into Claude Code’s file-writing tools. A change that violates the constitution is not flagged for review later. It is vetoed before it lands, with the reasoning on record.
Procedure
The order is the point: evidence is surfaced before it is argued, argued before it is ruled on, and ruled on before it is recorded.
Stage 01
Claude Sonnet 5, as Challenger
Examines the proposed change against the constitution’s binding constraints and surfaces evidence of violations. Its job is to find fault, not to be fair.
Stage 02
Claude Sonnet 5, as Defender
Argues for the soundness of the change, rebutting or conceding each finding. A concession is itself evidence the Oracle will weigh.
Stage 03
Claude Opus 4.8, as Oracle
Weighs both sides and issues a binding verdict: PASS or VETO. A veto blocks the change before it touches a file and provides remediation guidance.
Stage 04
SHA-256 hash chain
Every verdict is appended to a tamper-evident ledger, pass and veto alike. The evidence is permanent, traceable, and independently verifiable.
If the pipeline cannot adjudicate a change (an API timeout, a malformed response, an unreadable constitution), the change is denied, and a pipeline_error veto is recorded. Bench fails closed: governance is a wall when it cannot render a verdict, not a gate that swings open on failure.
The constitution
Bench enforces a written constitution, bench.json, and the Oracle enforces it as law. Each constraint carries a severity and a rationale. These are the eight in force today.
Every catch block must log, re-throw, or return a typed error. Empty catch blocks are violations. Silent failures compound into untraceable production bugs.
A change stays within one coherent scope. Bundling unrelated edits into a single change is a violation. Scope creep is the primary trust failure mode of AI-generated code.
Every new import or dependency must be explicitly declared. Undeclared dependencies are supply chain attack vectors and reproducibility failures.
Existing type annotations must not be removed or weakened. The operative test is whether available precision was discarded, not whether the token Any appears in the diff.
New functions or branches of logic need corresponding tests, or an explicit justification for deferring them. Governance without verification is theater.
No API keys, passwords, or tokens in source. All secrets load from environment variables or a secrets manager.
Changes to the pipeline itself (challenger, defender, oracle, ledger, constitution) must not weaken enforcement, bypass verification, or disable logging. A governance system that can silently weaken itself is not a governance system.
Entries may only be appended. Editing, reordering, or removing an entry is a violation under all circumstances, with no exception. Tampering with evidence is the highest governance violation.
A governed project can stack its own constitution layer on top of the core: new constraints in the reserved P- namespace, and severity_overrides that raise a core constraint’s severity. A layer can add and tighten, never weaken. A missing layer is safe (the floor applies in full), and a malformed or hostile layer fails closed.
Self-governance
Every change authored through Claude Code’s file tools while building Bench was challenged, defended, ruled on, and recorded by Bench itself. Including the changes it refused.
Ledger entry #64 · constraint C-007 · VETO
A change to pipeline/constitution.py left a literal placeholder token in the file. It would have been a SyntaxError breaking every pipeline import, disabling enforcement outright. The Oracle caught it, named it, and blocked it. The change was corrected and resubmitted.
Other vetoes under C-007 in the current chain: entries #22 to #25 against bench.json, #28 against ledger/chain.py, #54 and #56 against utils/api.py, and #77 against pipeline/runner.py. Read any of them yourself:
python -m cli ledger
The ledger
Every verdict is appended to a hash-chained ledger scoped to the governed project. Each entry records the full diff, the verdict, and the raw hash of every constitution file that ruled.
Illustrative entries. Every append names every current tip, so a chain forked by a git merge reconciles itself with the next governed edit.
The ledger is two segments: a frozen legacy array that nothing writes, and one file per entry, named by its own hash, forming a DAG. Frozen files cannot conflict; new entries name their parents. There is no merge command, because reconciliation is just the next hash-linked entry.
Walking the chain fails closed on every defect it can detect, each with a name:
C-008 permits one narrow escape from immutability: a whole chain may be retired, never edited, and only when it contains content that must not be published. On 2026-07-24, Bench’s own predecessor chain met that trigger. A globally registered hook had written diffs from unrelated projects into Bench’s ledger, so the chain held third-party source. It was archived whole, verified before anything moved: 2,471 entries, tip 2176516f. The current chain opens with an anchor entry recording where it went. Retirement cannot be run from inside a Claude Code session; it requires a human at a real terminal, typing a confirmation phrase.
Do not take the site’s word for it:
python -m cli verify python -m cli audit-retirement
Boundaries
A governance tool that hides its gaps is not one. Bench governs the Write, Edit, and MultiEdit tools it hooks, and nothing else. These boundaries are named in the README, with their rationale, rather than glossed over.
Read the boundary plainly: what Bench guarantees is that changes made through the governed file tools were adjudicated and recorded. Not that every change to the repository was.
Quick start
git clone https://github.com/Nuralyn/bench.git cd bench pip install -r requirements.txt
Bench reaches its models through one of three backends. The roles (Challenger, Defender, Oracle) are the same on all of them.
export ANTHROPIC_API_KEY=your-key-here
The default. Direct API calls, lowest latency.
export BENCH_PROVIDER=openrouter export OPENROUTER_API_KEY=your-key-here
Same model roles, routed through OpenRouter.
export BENCH_PROVIDER=claude_code
No API key. Each stage runs through your logged-in claude CLI in headless mode. Noticeably slower per edit, since every stage cold-starts an invocation.
cp .claude/settings.template.json \ /your-project/.claude/settings.json
Copy the template, not Bench’s own settings file, then edit the copy and replace the placeholder with the absolute path to your Bench checkout. A wrong path does not silently disable governance. Bench fails closed and blocks every governed edit until it is corrected.
echo '/.bench/' >> /your-project/.gitignore
The ledger records the full diff of every change it governs. Committing it to a public repository publishes them. The corollary is also true: an ignored ledger has no git backup, so decide deliberately which you want.
python -m cli verify python -m cli stats
The court
| Role | Model | Purpose |
|---|---|---|
| Challenger | Claude Sonnet 5 | Adversarial analysis |
| Defender | Claude Sonnet 5 | Soundness argument |
| Oracle | Claude Opus 4.8 | Binding verdict |
| Utility | Claude Haiku 4.5 | Reserved for future summarization |
Model IDs live in one place, utils/api.py, and this table is a snapshot, not the authority. Built with Python 3.11+, the Anthropic API, Claude Code PreToolUse hooks, and SHA-256 hash chaining.