In the matter of every change Claude Code proposes

Every change stands before the Bench.

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.

MIT licensed · Python 3.11+ · hooks into Claude Code’s PreToolUse

DOCKET No. 64 FILED
+ try:
+     load_constitution(path)
+ except Exception:
+     pass
  1. Challenger Sonnet 5  
  2. Defender Sonnet 5  
  3. Oracle Opus 4.8  
…9b41d2 

The problem

Unchallenged, unaudited, untraceable.

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

Four stages. One binding verdict.

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

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.

Stage 02

Defend

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

Rule

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

Record

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

Eight constraints. Declared, not implied.

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.

  1. C-001

    No Silent Error Swallowing

    veto

    Every catch block must log, re-throw, or return a typed error. Empty catch blocks are violations. Silent failures compound into untraceable production bugs.

  2. C-002

    Scope Boundary Enforcement

    veto

    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.

  3. C-003

    Dependency Declaration

    veto

    Every new import or dependency must be explicitly declared. Undeclared dependencies are supply chain attack vectors and reproducibility failures.

  4. C-004

    Type Safety Preservation

    veto

    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.

  5. C-005

    Test Coverage for New Logic

    warning

    New functions or branches of logic need corresponding tests, or an explicit justification for deferring them. Governance without verification is theater.

  6. C-006

    No Hardcoded Secrets or Credentials

    veto

    No API keys, passwords, or tokens in source. All secrets load from environment variables or a secrets manager.

  7. C-007

    Governance Pipeline Integrity

    veto

    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.

  8. C-008

    Ledger Immutability

    veto

    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 floor, not a default

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

Bench was built under its own law.

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

Evidence that outlives the conversation.

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.

#81PASSa3f91c #82VETO7c2ae4 #83PASSd94b07 #84PASS2f6c8d

Illustrative entries. Every append names every current tip, so a chain forked by a git merge reconciles itself with the next governed edit.

Append-only by construction

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.

Verification fails loudly

Walking the chain fails closed on every defect it can detect, each with a name:

  • MISSING_PARENT
  • ORPHAN_ENTRY
  • DUPLICATE_ENTRY
  • FILENAME_MISMATCH
  • MULTIPLE_GENESIS

The chain that was retired

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

What Bench does not govern.

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.

Shell commands
Any file written through Bash (shell redirection, tee, sed -i, a heredoc) never reaches the hook. No challenge, no verdict, no ledger entry. This is a complete bypass, available to any model or human with shell access, and adding Bash to the hook matcher does not close it. It breaks the tool instead.
MCP server tools
Tools exposed by MCP servers bypass the hook the same way, and less visibly: a tool named write_file reads as a governed primitive, where a shell command at least looks like a shell command. The available mitigation is auditing a server’s source before registering it. An audit raises confidence; it is not governance.
Bot-authored dependency PRs
Dependabot edits requirements.txt on GitHub, which never reaches a local hook. Those changes merge on a human decision and carry no ledger entry.

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

Put your next change on the docket.

  1. Clone and install

    git clone https://github.com/Nuralyn/bench.git
    cd bench
    pip install -r requirements.txt
  2. Pick a provider

    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.

  3. Register the hook in your project

    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.

  4. Keep the ledger out of git

    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.

  5. Verify governance

    python -m cli verify
    python -m cli stats

The court

Who sits where.

RoleModelPurpose
ChallengerClaude Sonnet 5Adversarial analysis
DefenderClaude Sonnet 5Soundness argument
OracleClaude Opus 4.8Binding verdict
UtilityClaude Haiku 4.5Reserved 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.