Does your regression test actually catch the bug?
AssertLedger runs the same test on the fixed code, on the known bug and on a neutral control. It vouches for a test only when it fails on the bug and nowhere else — then seals the evidence so anyone can replay it.
npm install --save-dev assertledger
| Candidate test |
Fixed code
value % 2 === 0
|
Known bug
value % 2 === 1
|
Neutral control
(value & 1) === 0
|
Verdict | Why |
|---|---|---|---|---|---|
Checks the type
assert.equal(typeof isEven(2), "boolean")
|
pass, both attempts | pass, both attempts missed the bug | pass, both attempts |
REJECTED
WEAK_ORACLE
|
Green everywhere proves nothing: this test would have let the bug ship. TARGET_STRENGTH_INSUFFICIENT
|
Checks the answer
assert.equal(isEven(2), true)
|
pass, both attempts | fail, assertion failure on both attempts caught it | pass, both attempts |
VERIFIED
ELIGIBLE
|
Red on the bug, green everywhere else. That is what a regression test is for. POLICY_SATISFIED
|
isEven() from the bundled example. Each row is one candidate test, run
alone: three worlds, two attempts per world. Recorded with assertledger 1.1.1.
Four more tests that look fine. None of them qualify.
Same function, same three worlds, real runs of the engine. Only an attributed assertion failure on the known bug counts as a catch. Timeouts, crashes, compile and collection failures are recorded, never credited.
| Candidate test |
Fixed code
value % 2 === 0
|
Known bug
value % 2 === 1
|
Neutral control
(value & 1) === 0
|
Verdict | Why |
|---|---|---|---|---|---|
Checks the answer and the source
assert.match(String(isEven), /% 2 === 0/)
|
pass, both attempts | fail, assertion failure on both attempts caught it | fail, assertion failure on both attempts false alarm |
REJECTED
INVALID
|
It catches the bug, but also fails on a harmless rewrite: it checks how the code is written, not what it does. NEUTRAL_NOT_GREEN
|
Hangs on the bug
if (!isEven(2)) for (;;) {}
|
pass, both attempts | timeout, both attempts no credit | pass, both attempts |
INCONCLUSIVE
INCONCLUSIVE
|
A timeout is never a catch, nor evidence either way: the hung runs observed nothing, so the verdict is inconclusive. CANDIDATE_EXECUTION_INCONCLUSIVE
|
Throws instead of asserting
if (!isEven(2)) throw new TypeError("unexpected parity")
|
pass, both attempts | crash, both attempts no credit | pass, both attempts |
REJECTED
INVALID
|
A thrown TypeError is recorded as a crash, not an assertion failure. Only attributed assertion failures count. CANDIDATE_DISCOVERY_INVALID
|
Flaky
assert.equal(isEven(2) && Math.random() < 0.5, true)
|
pass · fail, one attempt each attempts disagree | fail, assertion failure on both attempts | pass, both attempts |
INCONCLUSIVE
UNSTABLE
|
Its two attempts disagreed on the fixed code. A retry that passes never erases the one that failed. OBSERVATIONS_DIVERGE
|
isEven(), recorded with
assertledger 1.1.1. The flaky row shows one recorded run; its outcomes change between
runs, which is the point.
The four campaign verdicts
- VERIFIED
- At least one test met the declared policy and was selected.
- REJECTED
- The evidence is conclusive, and no test qualifies.
- INCONCLUSIVE
- Observations are unstable or incomplete, or a control is invalid.
- ENGINE_ERROR
- The evidence could not be normalized safely. Fix the setup, then rerun.
Same bytes. Three worlds. Fixed gates.
-
Declare
Name the buggy revision, its fix, and a neutral control that must keep the behavior — with the reason it does. AssertLedger never guesses what your bug means.
--before BUGGY_COMMIT --after FIX_COMMIT --neutral NEUTRAL_COMMIT --neutral-reason "Why it keeps the behavior" -
Run
The exact same candidate bytes run in a fresh workspace for every world, as many times as the policy requires. Each world first runs without the candidate, as a control.
control candidate fixed code known bug neutral control -
Decide
A pure core — no model, no clock, no randomness — applies six gates in a fixed order. When a prerequisite fails, the gates that depend on it are recorded as not run.
COMPLETENESSevery world has the required attemptsSTABILITYthe attempts agreeDISCOVERYthe test is found and attributedREFERENCEpasses on the fixed codeNEUTRALpasses on the neutral controlTARGET_STRENGTHfails, by assertion, on the bug
-
Seal
Two SHA-256 digests bind the evidence into a manifest. Replay recomputes both digests and the verdict, without rerunning a single test.
decisionDigest- binds the evidence the verdict depends on
artifactDigest- binds the whole manifest, down to each timing
Don’t trust this page. Replay it.
Each deploy of this site runs the bundled example through AssertLedger on GitHub Actions and publishes the manifest it produced. Replay needs no model and runs no test: it re-derives the verdict and both digests from the recorded evidence.
- candidate tests
- 2
- worlds
- 3
- observations
- 18
{
"decision": {
"status": "VERIFIED",
"selectedCandidateIds": ["strong"],
"reasonCodes": ["POLICY_SATISFIED"]
},
"decisionDigest": "sha256:…",
"artifactDigest": "sha256:…"
}
Download manifest.json
Replay it anywhere
npx assertledger replay manifest.json --json
Expected output, as documented
validtrueschemaValidtruedecisionDigestValidtrueartifactDigestValidtruedecisionSemanticsValidtrue
Flip a single recorded outcome and replay rejects the file: the digests and the re-derived verdict stop matching.
Replay proves integrity and decision consistency. It does not prove who produced the observations.
Start with one command.
Install it in the repository you want to check. doctor reads the repository
without running its tests or writing a file.
CLI
npm install --save-dev assertledger
npx assertledger doctor .
npx assertledger check . \
--before BUGGY_COMMIT --after FIX_COMMIT \
--neutral NEUTRAL_COMMIT \
--neutral-reason "Why this revision keeps the behavior" \
--test tests/regression.test.js \
--base-test tests/base.test.js \
--out .assertledger/evidence-001 \
--allow-unsafe-execution
Trusted code only. --allow-unsafe-execution runs the
repository’s code on this machine, unsandboxed. Since 1.1,
--container-image NAME@sha256:DIGEST runs each observation in a fresh
Linux container instead.
Blocked by a refusal? npx assertledger explain REASON_CODE prints a safe
next action.
SDK
import { readFile } from "node:fs/promises";
import { AssertLedger } from "assertledger";
const ledger = new AssertLedger();
const request = JSON.parse(await readFile("request.json", "utf8"));
const manifest = await ledger.verify(request);
console.log(manifest.decision.status); // VERIFIED, REJECTED, INCONCLUSIVE or ENGINE_ERROR
console.log(ledger.replay(manifest).valid); // true
A request declares the worlds, the candidates and the policy — see the bundled example. The SDK reuses the engine’s gates; it never reimplements them.
Agents · MCP
# Preview the configuration and the packaged skill
npx assertledger connect . --client claude-code
# Install both
npx assertledger connect . --client claude-code --write
# Codex, or a generic MCP descriptor
npx assertledger connect . --client codex
npx assertledger connect . --client mcp
An agent can propose a candidate test; the deterministic engine judges the observations. The generated MCP server starts read-only, and running candidates needs a separate, explicit opt-in.
The fine print, in large print.
A verdict is only as good as its limits. Here is what AssertLedger does not prove.
-
That your code is bug-free.
A verdict covers the declared bug, the recorded worlds and the observed attempts. Nothing beyond them.
-
That your worlds make sense.
You supply the bug and the neutral control. AssertLedger records them; it does not invent what they mean.
-
That a test will never flake.
Stability is measured over the attempts it observed, not promised beyond them.
-
Who produced the evidence.
Replay checks integrity and decision consistency. Authenticating the producer needs a separate signed attestation.
-
That local runs are sandboxed.
trusted-localis explicitlyUNSANDBOXED: run trusted code only. Container isolation runs without network or host mounts, but still shares the host’s kernel.