Skip to content

What is measurable here — and what is not

This page replaces a previous version of this file that contained comparative numbers which were never produced by any harness in this repository. Those numbers are gone. This page tells you exactly what you can measure yourself, and how to reproduce it.

Why there is no comparison table

A useful comparison would need a shared task set, a defined metric, an agreed definition of a "false completion", and re-runs of every competing tool under the same conditions. This repository has no such harness, so any table of numbers here would be invented. Rather than publish numbers we cannot defend, we publish the checks we can run and let you run them too.

If you want to build that harness, open an issue.

The verified flow (authenticated since 2.5.0)

Every number on this page is only meaningful for a completed run, and since 2.5.0 a run can only complete when its evidence is HMAC-authenticated. The full flow:

# 1. Authorize the host-owned request contract
plan-auditor request init . --file request-source.json

# 2. Seal the plan's contract
plan-auditor plan verify .

# 3. Configure an external HMAC key (OUTSIDE the workspace) and initialise
#    integrity. Without this the audit cannot pass: a keyless chain is
#    tamper-evident but rebuildable by anyone with write access.
mkdir -p ~/.plan-auditor && printf 'plan-auditor: %s' "$(openssl rand -hex 32)" > ~/.plan-auditor/hmac.key
export PLAN_AUDITOR_HMAC_KEY_FILE=~/.plan-auditor/hmac.key
plan-auditor integrity init .

# 4. Run the checks and audit
plan-auditor run .
plan-auditor audit .   # exits 0 only with authenticated evidence

Exit codes are the documented four (0 proven, 1 failed, 2 request refused, 3 undetermined); see docs/cli.md for the authoritative table.

Provenance for every number on this page

Nothing on this page is a hand-copied figure. Each quality claim below is tied to the exact command that produces it, so you can regenerate it and compare. If a number ever changes, the command changes too — that is the point.

Claim Command that produces it Tool Commit this text describes Where the live value lives
Regression suite result python -m pytest tests/ -q the version of pytest in your environment main at the time of reading the audit CI job for that commit
Example regression python -m pytest examples/fib/test_fib.py -q same same the same CI run
Branch and statement coverage (Linux, root) sudo -n "$(command -v python)" -m pytest tests/ -q -rs --cov --cov-report=term-missing pytest-cov same the TOTAL row the command prints, and the fail_under value in [tool.coverage.report] in pyproject.toml
Docs build cleanly python -m mkdocs build --strict mkdocs-material same the docs (mkdocs --strict) required CI check
Docs and package metadata are consistent python -m pytest tests/test_docs_metadata.py tests/test_readme_quickstart.py tests/test_doc_transcripts.py -q pytest same the same CI run
Wheel and sdist carry the skill assets python .github/scripts/check_dist_assets.py none (standard library) same the build (wheel + sdist) required CI check
npm launcher behaviour and tarball npm test, npm run test:contract, npm run test:gate the version of Node you run them with same the npm-launcher required CI check
Published package contents python -m build, twine check --strict dist/*, npm pack --dry-run build, twine, npm the tag you check out the build and publish jobs

Note that the coverage command no longer names the source directories. pytest-cov reads branch, source_pkgs and fail_under from [tool.coverage.*] in pyproject.toml, and conftest.py pins the suite to the installed distribution, so --cov=supervisor --cov=scripts against the checkout is no longer the command that measures the shipped code.

Two things are deliberately not in that table:

  • The coverage figure for any given commit. The command prints it, the floor is enforced from pyproject.toml, and a number typed into this file would silently go stale, so the floor and the run output are the only places it appears.
  • Any number describing how many people use this. No telemetry is collected, so such a figure could not be substantiated. The package pages carry whatever the registries report.

Platform note: these commands were last exercised by this project's maintainer on Windows 11 with CPython 3.12. CI runs the suite on ubuntu-latest across the supported Python versions, wheel-cli-smoke exercises the installed CLI on Linux, Windows and macOS, and the branch coverage is measured against the installed distribution. Numbers can differ slightly by platform because a handful of tests are skipped when an optional interpreter or helper is absent; the pass and skip counts the command prints tell you which run you are looking at.

What is reproducible: the in-repo example

examples/fib/ is a complete, runnable plan. It is in the repository and in the sdist, but not in the wheel, so a pip-only install will not have it — use a checkout if you want to run this. (The wheel does ship the Agent Skill assets, namespaced under plan_auditor_skill/; examples/ is deliberately not among them.)

cd examples/fib
python -m pytest test_fib.py -q

examples/fib/.plan-auditor/plan.json declares two steps, and the second step's verification is the pytest run above:

{
  "id": 2,
  "title": "pytest regression for fib() passes",
  "verify": [
    {"type": "file_exists", "path": "test_fib.py"},
    {"type": "pytest", "args": "test_fib.py -q"}
  ],
  "status": "pending"
}

So the property being demonstrated is narrow and checkable: a step is not verified until its declared command exits 0. Run the whole gate yourself:

cd examples/fib
plan-auditor request init . --file request-source.json
plan-auditor plan verify .
plan-auditor run .
plan-auditor audit .
$ plan-auditor run .
[OK ] step 1: fib.py defines a correct fib() function (attempt 1/3)
       - passed | fib.py EXISTS
       - passed | pattern matched
       - passed | exit=0 (expected 0)
       - output fib-implementation | passed
[OK ] step 2: pytest regression for fib() passes (attempt 1/3)
       - passed | test_fib.py EXISTS
       - passed | exit=0 (expected 0)

Now break the implementation and watch the gate refuse to pass. Replace the body of fib.py with return 0:

$ plan-auditor run .
[FAIL] step 1: fib.py defines a correct fib() function (attempt 1/3)
       - passed | fib.py EXISTS
       - passed | pattern matched
       - FAILED | exit=1 (expected 0)
...
       - output fib-implementation | passed
[BLOCKED] step 2: prerequisite/output validation failed

Scoped omission: the single elided line is the tool's output: block, which carries the captured Python traceback as one physical output line joined with " | ". Its interior frames depend on your Python version — 3.11 and newer add the offending source line and a caret — so quoting it verbatim would be correct on some interpreters and wrong on the rest. Every remaining line above is verbatim, the step fails with exit=1, and the invocation exits 1.

The same run through the published npm bin exits 1 too, because the launcher propagates the child's code rather than defaulting to success. bin/plan-auditor.js is what npx plan-auditor resolves to:

$ node bin/plan-auditor.js run /path/to/examples/fib
[FAIL] step 1: fib.py defines a correct fib() function (attempt 1/3)
       - passed | fib.py EXISTS
       - passed | pattern matched
       - FAILED | exit=1 (expected 0)
...
       - output fib-implementation | passed
[BLOCKED] step 2: prerequisite/output validation failed
$ echo $?
1

The same scoped omission applies to the launcher's output: line; the launcher exit code of 1 is reproduced by tests/test_npm_launcher.py, which also asserts that a passing run yields 0 and that an unstartable Python fails closed.

Step 2 is not merely "unverified" — it is blocked, because its prerequisite output contract no longer holds. Restoring fib.py and re-running returns both steps to VERIFIED, and the evidence log records the failing and the passing attempts in one hash-chained sequence. plan-auditor evidence verify . re-validates that chain.

The same experiment works without any agent involved: the gate does not care who wrote the code.

What is reproducible: the regression suite

This is the number this project is willing to stand behind, because it is produced by the same command CI runs:

python -m pytest tests/ -q
python -m pytest examples/fib/test_fib.py -q
sudo -n "$(command -v python)" -m pytest tests/ -q -rs --cov --cov-report=term-missing

The coverage floor lives in [tool.coverage.report] as fail_under in pyproject.toml, so the workflow and a local run cannot disagree about it, and the workflow requires all statement and branch counts to be fully covered, with zero skipped tests. conftest.py pins the suite to the installed distribution, so the number measures the code that would ship rather than the working tree. A regression in coverage fails CI instead of quietly lowering a claim.

What is not claimed

Claim Status
This tool catches unverified completions Demonstrated above on a runnable example
Evidence tampering is detected Covered by test_chain_ok_and_tamper_detected in tests/test_audit_check.py and test_evidence_chain_break_detected in tests/test_failure_injection.py
Plan criteria cannot be weakened after sealing Covered by tests/test_full_contract_hardening.py and tests/test_failure_injection.py
Cross-tool detection rates Not measured. No harness exists
Productivity or time saved Not measured. No study exists
Adoption by size or organization Not claimed. No telemetry is collected

Overhead you can measure yourself

Verification is real work: every behavioral check runs a subprocess, and audit runs them all again in fresh shells. Measure it on your own task:

time plan-auditor run . 1
time plan-auditor audit .

time is a POSIX shell builtin, so those two lines apply to a POSIX shell. In PowerShell use Measure-Command, and in cmd.exe measure with %TIME%.

For a cheap sanity check, plan-auditor doctor . reports whether the required toolchain is present in your environment before you commit to a plan that needs it.

Reproducing every check in this project

python -m pytest tests/ -q
python -m pytest examples/fib/test_fib.py -q
python -m build
twine check --strict dist/*
python .github/scripts/check_dist_assets.py
python -m mkdocs build --strict
npm test
npm run test:contract
npm run test:gate
plan-auditor request init . --file .plan-auditor/request-source.json
plan-auditor plan verify .
plan-auditor audit .

build, twine, mkdocs-material and Node are contributor-only tools and are not declared as runtime dependencies, so install them first:

python -m pip install build twine mkdocs-material

CI pins mkdocs==1.6.1 and mkdocs-material==9.6.14 for its strict build, so pin the same pair locally if you want the check to match exactly. Note that python -m mkdocs build --strict needs the dependency installed for the same interpreter you build with; it is not a runtime dependency of the package.

The documentation and package-metadata checks that keep the README and this site truthful live in tests/test_docs_metadata.py and tests/test_readme_quickstart.py.

Next steps