Loophole is a human-in-the-loop adversarial drafting tool for turning moral principles into a draft legal-style code, attacking that code with counterexamples, and revising it round by round.
It is designed to help surface pressure on a rule set. It is not a moral theorem prover, a formal verifier, or an autonomous policy engine.
Loophole runs a four-role loop:
- A Legislator drafts a legal code from your stated principles.
- A Loophole Finder looks for scenarios that appear legal under that code but violate the intended principles.
- An Overreach Finder looks for the opposite: scenarios the code prohibits even though a human may still judge them acceptable.
- A Judge decides whether a case looks locally resolvable or should be escalated back to the operator.
Every round produces explicit artifacts:
- the current legal code
- a case log
- serialized session state
- an HTML report
Loophole does not provide:
- formal consistency proofs
- exhaustive loophole coverage
- guaranteed preservation of moral intent
- autonomous high-stakes decision making
- evidence that an escalation reflects a deep moral contradiction rather than drafting ambiguity, validator conservatism, or model error
If a round finds no failures, that means only that this round of model-mediated search did not produce parseable cases that survived the loop. It does not establish completeness.
Loophole has a simple authority chain:
- Human principles
- Human clarifications and escalated resolutions
- Current legal code
- Resolved case history
- Model judgments and rewrites
The human remains the highest authority layer throughout.
The system attempts to preserve resolved precedent through prompt context and validator checks. That is a meaningful constraint, but it is not a formal guarantee.
new:
- collects a domain and principles
- drafts an initial code
- enters the adversarial loop
Each loop round:
- runs both adversarial finders
- evaluates every case through the judge
- auto-applies only revisions that survive validation against resolved cases
- escalates unresolved or regression-inducing cases to the operator
- saves session artifacts after each completed case
resume:
- reloads a saved session and continues the loop
visualize:
- renders an HTML report for a saved session
By default, each session writes:
state.jsoncurrent_code.mdcase_log.mdreport.html
See docs/operator-guide.md for current path behavior and the session_dir caveat.
- Python 3.12+
- a live API key for the configured provider
git clone https://github.com/McGluut/loophole_go
cd loophole_go
uv syncSet your key:
$env:LOOPHOLE_API_KEY="sk-ant-..."Run the app:
uv run loopholeIf you prefer the module form:
uv run python -m loophole.maingit clone https://github.com/McGluut/loophole_go
cd loophole_go
python -m pip install -e .
$env:LOOPHOLE_API_KEY="sk-ant-..."
python -m loophole.mainIf the console script is on your PATH, this also works:
loopholeUsing uv:
git clone https://github.com/McGluut/loophole_go
cd loophole_go
uv syncUsing plain Python tooling without uv:
git clone https://github.com/McGluut/loophole_go
cd loophole_go
python -m pip install -e .Preferred generic variable:
Bash:
export LOOPHOLE_API_KEY="sk-ant-..."PowerShell:
$env:LOOPHOLE_API_KEY="sk-ant-..."Backward-compatible provider variable:
export ANTHROPIC_API_KEY="sk-ant-..."Live runs in this repo still use the Anthropic SDK today. The generic LOOPHOLE_API_KEY name is provided so local setup does not have to depend on a provider-specific environment variable.
If you cloned the repo and are running from source, do not assume plain python -m loophole.main will pick up the uv environment. After uv sync, prefer uv run loophole or uv run python -m loophole.main.
With uv:
uv run loophole new --domain privacy --principles examples/privacy_principles.txtWithout uv, module form:
python -m loophole.main new --domain privacy --principles examples/privacy_principles.txtWithout uv, installed console script:
loophole new --domain privacy --principles examples/privacy_principles.txtInteractive menu with uv:
uv run loopholeInteractive menu without uv:
python -m loophole.mainWith uv:
uv run loophole resumeWithout uv:
python -m loophole.main resumeWith uv:
uv run loophole visualizeWithout uv:
python -m loophole.main visualizeThe default configuration lives in config.yaml:
model:
default: "claude-sonnet-4-20250514"
max_tokens: 4096
temperatures:
legislator: 0.4
loophole_finder: 0.9
overreach_finder: 0.9
judge: 0.3
loop:
max_rounds: 10
cases_per_agent: 3
session_dir: "sessions"Current operational caveat:
- this repo is still best run from the repository root
session_diris used for session storage and report output, but some operator assumptions remain root-oriented
Run the test suite:
python -m unittest discover -s tests -vThe current tests focus on:
- protocol contract failures
- session persistence
- report generation
- human-escalation rollback behavior
- docs/ARCHITECTURE.md
- docs/TRUST_MODEL.md
- docs/LIMITATIONS.md
- docs/operator-guide.md
- docs/SESSION_REVIEW_TEMPLATE.md
Most rule systems look stronger than they are until someone attacks their wording. Loophole is useful when you want a structured way to pressure-test a draft norm system, keep the human in charge, and leave behind auditable artifacts rather than a single polished answer.
That is the ambition.
The current repo should be read as an experimental application that helps surface candidate gaps, not as a settled engine for moral or legal judgment.