AssertLedger v1.1.1 · MIT · Node ≥ 22.15
Language
GitHub

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
ledger · isEven(value)
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.
01 / Try to fool it Ledger, continued

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
Four single-candidate campaigns against 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.
02 / How it works No model in the loop

Same bytes. Three worlds. Fixed gates.

  1. 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"
  2. 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.

  3. 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.

    1. COMPLETENESSevery world has the required attempts
    2. STABILITYthe attempts agree
    3. DISCOVERYthe test is found and attributed
    4. REFERENCEpasses on the fixed code
    5. NEUTRALpasses on the neutral control
    6. TARGET_STRENGTHfails, by assertion, on the bug
  4. 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
03 / Evidence Replayable offline

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.

manifest.json expected result
VERIFIED
candidate tests
2
worlds
3
observations
18
{
  "decision": {
    "status": "VERIFIED",
    "selectedCandidateIds": ["strong"],
    "reasonCodes": ["POLICY_SATISFIED"]
  },
  "decisionDigest": "sha256:…",
  "artifactDigest": "sha256:…"
}

Replay it anywhere

npx assertledger replay manifest.json --json

Expected output, as documented

  • validtrue
  • schemaValidtrue
  • decisionDigestValidtrue
  • artifactDigestValidtrue
  • decisionSemanticsValidtrue

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.

04 / Get started Node.js ≥ 22.15 · node:test

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

Install and diagnose
npm install --save-dev assertledger
npx assertledger doctor .
Qualify a committed regression test
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

verify.mjs
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

Project-local setup
# 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.

05 / Fine print Explicit non-claims

The fine print, in large print.

A verdict is only as good as its limits. Here is what AssertLedger does not prove.

  1. That your code is bug-free.

    A verdict covers the declared bug, the recorded worlds and the observed attempts. Nothing beyond them.

  2. That your worlds make sense.

    You supply the bug and the neutral control. AssertLedger records them; it does not invent what they mean.

  3. That a test will never flake.

    Stability is measured over the attempts it observed, not promised beyond them.

  4. Who produced the evidence.

    Replay checks integrity and decision consistency. Authenticating the producer needs a separate signed attestation.

  5. That local runs are sandboxed.

    trusted-local is explicitly UNSANDBOXED: run trusted code only. Container isolation runs without network or host mounts, but still shares the host’s kernel.