Pre-launch. Not deployable to production. This page states what the tests prove and what is missing — nothing else.

Deleting a safety rule on purpose to see whether a test notices

Try to break it yourself

People ask this as: how do i know my tests would actually catch a regression

A falsification kit, not a mutation-testing tool. It removes exactly one publicly stated rule at a time from real source, runs the suite that is supposed to defend it, reports which named test caught it, and restores every edit with a byte-for-byte verified restore. It refuses to start if any target file has uncommitted changes. Six hand-written mutations, naming four of the ledger's claims between them — not a coverage metric, and no percentage is computed, because a percentage derived from six mutations would mean nothing.

Where this stops

Read this before the rest of the page. Every line below is a thing this does not do.

  • It is not a mutation-testing tool. It generates no mutations, samples nothing, and computes no mutation score — a percentage derived from six hand-written mutations would mean nothing.
  • It does not prove the rules are correct, only that a test holds them. A wrong rule, faithfully defended, passes every mutation here.
  • It covers six rules, not the twenty-two claims in the ledger. Each mutation names the claims it defends; the rest rest on their own evidence.
  • It publishes no limitations[] array. Its machine-readable self-report is the stale outcome and the skipped[] list, and both fail or annotate the run rather than being absorbed silently.
  • It edits real source files. It refuses to start on a dirty target file precisely because it does, and a killed run leaves damage that git checkout undoes.
  • The default run is narrower than the full set: one mutation is skipped for speed, and printed as skipped rather than omitted.
  • It says nothing about which tests are missing — only whether these specific rules currently have a named witness.

No authentication, tenancy or RBAC. The server is local-development-only. An actor header is an assertion, not an identity. Do not expose it to a network. Every claim and every limitation is on one page.

What question it answers

A test count tells you how much was written. It does not tell you what would have to go wrong for a test to stay green, and that is the question a sceptical reader is actually asking.

So the kit answers it by breaking things on purpose: each mutation removes one rule this project makes in public, runs the suite that is supposed to defend it, and names the test that went red.

What it does

`npm run falsify` ran here on 2026-08-09 and printed, verbatim: "5 caught, 0 survived, 0 stale, in 2.2s" and "Every rule tested here fails loudly when removed." Each row named the rule and its witness — `approval-actor-guard` caught by "approval workflow rejects an agent pretending to make the human decision"; `approval-threshold-boundary` by "renewal at threshold requires approval and records the human decision"; `webhook-signature-verification` by "webhook verification is constant-time, replay-bounded and fail-closed"; `definition-version-immutability` by "persisted definition versions: registration is idempotent, drift fails loudly"; `managed-fields-public-write` by "a fully managed module generates no public write, and a mixed one does". A sixth, `delivery-cost-rounding`, printed as "not run (slow — run with --all)" rather than being quietly dropped from the set.

Three outcomes, two of which are failures. `caught` means the suite went red and the report names the test. `survived` means the suite stayed green with the rule removed — a gap in the tests. `stale` means the code the mutation aims at is gone, so it proved nothing, and that is a failure on purpose: a falsification kit that quietly stops aiming at anything is worse than not having one, because it goes on printing reassurance. The run exits non-zero on either.

Baselines are measured rather than assumed: every target suite runs unmutated first. A suite that is already red would make every mutation look caught, which is the one way this tool could lie in the flattering direction.

Each mutation carries the claim ids it defends. `--json` emits `falsifyContract: 1` with, per mutation, the file, the exact source string removed, the defending test, the rule, what breaking it would mean, the claim ids, how many occurrences were found against how many were expected, the outcome and the name of the catching test — plus a `skipped[]` array carrying the slow mutation and its reason. The `elapsedMs` field on the JSON runs here read between 2,110 and 2,385 ms, which is the honest precision available for a wall-clock number.

What it already found is the reason to keep it. `managed-fields-public-write` survived the first time it ran: removing the read-only rule from the module factory left the factory's own test green, and only the end-to-end suites noticed. A rule about generated output should fail in the test that reads the generated output, so a direct assertion was added. The interesting output of a falsification run is not the row of ticks.

What it refuses to claim

This is the second of the two tools in this cluster that publishes no `limitations[]` array. Its machine-readable self-reporting is different in kind: the `stale` outcome, which is how the kit reports that it has stopped aiming at anything, and the `skipped[]` list, which is how it reports that the default run is narrower than the full set. Both are in the JSON, and both fail or annotate the run rather than being silently absorbed.

The prose boundaries are three, and they are stated as flatly as anything in this repository. It is not a mutation-testing tool: it does not generate mutations, sample them or compute a mutation score, and six hand-written mutations aimed at six claims is a different instrument from a coverage metric. It does not prove the rules are correct, only that they are held by a test — a wrong rule, faithfully defended, passes every mutation here. And it covers six rules, not the ledger: the claims ledger carries twenty-two claims, each mutation names which ones it defends, and the rest rest on their own evidence and are not falsified by this command.

It does not tell you which tests are missing. It tells you that these five specific rules currently have a witness, and it will tell you loudly when one of them stops having one.

What it costs to run

About 2.6 seconds for the default set here, exit code 0. The full set with `--all` includes one mutation whose only witness takes roughly a minute.

It edits real source files in place, one at a time, and restores them in a `finally` with the restoration verified byte-for-byte. If a restore ever fails it throws immediately, naming the file and the command that fixes it, rather than letting the run scroll it away.

The safety property is a precondition, not a copy: it refuses to start if any target file has uncommitted changes. So even a killed process leaves damage that a single `git checkout -- <file>` undoes completely. A scratch copy of the tree would avoid the edit entirely and cost a full copy per run; the git precondition buys the same assurance for the price of one `git status`.

Where it fits

It sits beside the quality gates rather than inside them: the gates say the tests must pass, and this says what the tests would notice. Section 4 of the gates lists mutation tests for versioned policies as a production gate that does not exist — this kit is not that, and does not claim to be.

The five rules it currently defends are the ones where being wrong costs the most: an agent recording a human's approval decision, a deal exactly at the approval threshold, a forged signature webhook, a policy version edited in place so every historical decision citing it now cites something else, and generic CRUD writing fields only a trusted action may set.

The evidence this page rests on

Claims and limitations are printed from site/claims.json word for word. Job statuses come from docs/benchmarks/jobs.json; a job with no page of its own is listed with its status rather than linked.

Claims

  • C-23 Five rules can be removed on purpose in one command, and the suite catches every one in about two seconds — naming the test that caught it. Anything that survives is reported as a gap, not omitted.

    LimitIt falsifies six named rules, not the claims in this ledger, and it proves only that a test holds each one — a rule that is wrong but faithfully defended passes every mutation. It is not mutation testing: nothing is generated or sampled, and no score is derived.

  • C-20 701 tests, run on every push, covering happy paths and the policy boundaries that matter — hostile input, transaction rollback, idempotency, concurrency and immutability among them.

    LimitA test count measures effort, not correctness — read the adversarial-review categories in docs/QUALITY_GATES.md to see what is actually attacked. Real-browser tests are run manually and are not in CI.

  • C-03 Commercial policy is deterministic code, not a model's judgement: a renewal at or above the threshold stops and waits for a named human.

    LimitProven for the built-in renewal object and its single value threshold. A general policy engine over arbitrary custom objects does not exist.

Limitations

  • L-03 The build benchmark has not been run. The protocol is designed and published; no Successful Agent Build Rate exists yet. Any number you see quoted for this project is not ours.
  • L-01 No authentication, tenancy or RBAC. The server is local-development-only. An actor header is an assertion, not an identity. Do not expose it to a network.

Jobs it covers