plan-auditor 2.4.3__tar.gz → 2.4.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of plan-auditor might be problematic. Click here for more details.
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/.gitignore +5 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/CHANGELOG.md +132 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/CITATION.cff +2 -2
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/CONTRIBUTING.md +1 -1
- plan_auditor-2.4.4/PKG-INFO +290 -0
- plan_auditor-2.4.4/README.md +247 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/SECURITY.md +63 -13
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/SKILL.md +1 -1
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/bin/publish_mode_contract.test.js +11 -7
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/docs/benchmark.md +22 -22
- plan_auditor-2.4.4/docs/check_attestation_claims.py +482 -0
- plan_auditor-2.4.4/docs/check_readme_size.py +151 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/docs/cli.md +21 -7
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/docs/deployment-isolation.md +19 -9
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/docs/index.md +2 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/docs/quickstart.md +16 -16
- plan_auditor-2.4.4/docs/readme_size_baseline.json +15 -0
- plan_auditor-2.4.4/docs/release-status.md +120 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/docs/threat-model.md +10 -0
- plan_auditor-2.4.4/docs/workspace-artifacts.md +72 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/mkdocs.yml +1 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/package.json +1 -1
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/pyproject.toml +1 -1
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/scripts/audit_check.py +158 -150
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/scripts/contract.py +3 -3
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/__init__.py +1 -1
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_audit_check.py +13 -13
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_doc_transcripts.py +10 -10
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_docs_metadata.py +3 -3
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_exec_trust_gate.py +4 -4
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_full_contract_hardening.py +1 -1
- plan_auditor-2.4.4/tests/test_hmac_check_environment.py +52 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_runtime_root_hardening.py +2 -2
- plan_auditor-2.4.3/PKG-INFO +0 -399
- plan_auditor-2.4.3/README.md +0 -356
- plan_auditor-2.4.3/docs/release-status.md +0 -76
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/CODE_OF_CONDUCT.md +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/LICENSE +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/bin/launcher_contract.test.js +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/bin/plan-auditor.js +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/bin/prepublish_gate.js +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/bin/prepublish_gate_contract.test.js +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/bin/prepublish_lifecycle.test.js +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/docs/architecture.md +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/docs/dependency-graph.md +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/docs/formal-planning.md +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/docs/integrations.md +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/examples/fib/.plan-auditor/plan.json +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/examples/fib/fib.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/examples/fib/request-source.json +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/examples/fib/test_fib.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/hooks/README.md +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/hooks/gate_hook.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/index.js +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/references/plan-format.md +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/scripts/__init__.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/scripts/exec_trust.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/scripts/integrity.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/scripts/plan_graph.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/scripts/stop_gate.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/adversarial.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/agents.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/agents_hardening.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/audit_session.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/cli.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/config.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/contracts.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/control_plane.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/coverage.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/daemon.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/events.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/evidence.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/formal_compiler.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/formal_planning.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/formal_semantics.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/gate.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/goals.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/integrity.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/lifecycle.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/lock_hardening.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/orchestrator.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/plan_verifier.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/plans.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/policies.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/priority.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/request_contract.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/requirements.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/seal_migration.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/sealing.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/watchdog.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/supervisor/workspace.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/request_fixture.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_adversarial.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_agent_registry_chain.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_agents_gate.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_authenticated_integrity.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_cli.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_console_scripts.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_core_layers.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_daemon.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_dependency_graph.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_events.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_extra_layers.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_failure_injection.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_formal_compiler.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_formal_planning.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_formal_semantics.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_hooks.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_integration_hardening.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_npm_launcher.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_npm_registry_visibility.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_readme_quickstart.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_registry_lock_partial.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_request_contract_hardening.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/test_root_cause_fixes_v220.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/trusted_workspace.py +0 -0
- {plan_auditor-2.4.3 → plan_auditor-2.4.4}/tests/wheel_cli_smoke.py +0 -0
|
@@ -44,3 +44,8 @@ pack.json
|
|
|
44
44
|
# mypy cache from the type ratchet job
|
|
45
45
|
.mypy_cache/
|
|
46
46
|
.ruff_cache/
|
|
47
|
+
|
|
48
|
+
# Upstream commit lookups cached by .github/scripts/check_action_pins.py. The
|
|
49
|
+
# cache exists so repeated local runs and a cold CI runner do not re-query the
|
|
50
|
+
# API; it is machine-local state and must never be committed.
|
|
51
|
+
.action-pin-cache/
|
|
@@ -4,6 +4,138 @@ All notable changes to plan-auditor. Versions are published to PyPI and npm.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 2.4.4 — HMAC check subprocess boundary
|
|
8
|
+
|
|
9
|
+
### Security
|
|
10
|
+
|
|
11
|
+
- Do not inherit `PLAN_AUDITOR_HMAC_KEY` or `PLAN_AUDITOR_HMAC_KEY_FILE`
|
|
12
|
+
into project-controlled behavioral-check subprocesses. The supervisor
|
|
13
|
+
retains these credentials to authenticate the resulting audit evidence.
|
|
14
|
+
- Add regression tests for both credential variables, benign environment
|
|
15
|
+
preservation, parent environment preservation, and the public `run_check`
|
|
16
|
+
path.
|
|
17
|
+
- Clarify that environment sanitisation is defense in depth, **not** OS
|
|
18
|
+
sandboxing: an untrusted child running as the supervisor's user can still
|
|
19
|
+
open any HMAC key file that user can read. Deliberately hostile agents need
|
|
20
|
+
a separately isolated, keyless check-execution identity/container.
|
|
21
|
+
|
|
22
|
+
### Documentation
|
|
23
|
+
|
|
24
|
+
- **README reduced from 362 to 248 lines with no surface lost.** The previous
|
|
25
|
+
release traded a line target for coverage and stopped at 356, on the reasoning
|
|
26
|
+
that the layer table, command tables and artifact list were the coverage gap.
|
|
27
|
+
That was right about the priority and wrong about the arithmetic: the reduction
|
|
28
|
+
had not been attempted. Detail now lives on the docs site and the README keeps a
|
|
29
|
+
scannable map plus links. Measured against the same 66-surface checklist derived
|
|
30
|
+
from the code, **0 surfaces are undocumented**: 37 still appear in the README and
|
|
31
|
+
29 moved to a named docs page.
|
|
32
|
+
- The L0-L14 layer table became a five-row band map. It still names all fifteen
|
|
33
|
+
layers, and the two facts that carry the design are now stated in the prose
|
|
34
|
+
rather than buried in a row: **L10 (`scripts/audit_check.py`) is the only
|
|
35
|
+
component that can mark a step `verified`** and **L13 (`gate.py`) is the only
|
|
36
|
+
one that emits a final `PASS`/`FAIL`/`UNKNOWN`**. Per-layer detail was already
|
|
37
|
+
in `docs/architecture.md`.
|
|
38
|
+
- The fourteen workspace artifacts moved to a new **`docs/workspace-artifacts.md`**,
|
|
39
|
+
which also records what is *not* written and why the files are separated
|
|
40
|
+
(append-only evidence, host-owned input separate from agent-owned state, and a
|
|
41
|
+
stale verdict being detectable). The README still says the tool writes under
|
|
42
|
+
`.plan-auditor/` and links the page.
|
|
43
|
+
- The full command table was already in `docs/cli.md`; the README now names the
|
|
44
|
+
four entry points and the five check types, and `docs/cli.md` gained an explicit
|
|
45
|
+
`0`/`1`/`2`/`3` exit-code legend so the codes have one canonical home.
|
|
46
|
+
- `## Reference` was folded into `## Documentation` rather than kept as a second
|
|
47
|
+
index. The heading name is unchanged on purpose: a test splits the README on it.
|
|
48
|
+
- The `## Use it in CI` yaml block became one prose line pointing at
|
|
49
|
+
`docs/integrations.md`.
|
|
50
|
+
- The quick start keeps the structure `tests/test_readme_quickstart.py` requires:
|
|
51
|
+
exactly two JSON blocks, one console block, and the same four commands. Both
|
|
52
|
+
plan files and the transcript were compressed using the `...` elision the test
|
|
53
|
+
already tolerates. **The `request_sha256` changed** because the documented
|
|
54
|
+
`task` string was shortened, and it was re-derived by running the walkthrough,
|
|
55
|
+
not computed: `d39e577eb0577d8c0c81231fdd7fc559d1c6045ecc5e5bd3a00e7e8f2f49197b`.
|
|
56
|
+
- `docs/index.md` now links `workspace-artifacts.md` and `release-status.md`,
|
|
57
|
+
which it did not, so the docs home is a real index rather than a partial one.
|
|
58
|
+
|
|
59
|
+
- **`docs/check_readme_size.py` guards against re-inflation.** It fails when
|
|
60
|
+
`README.md` exceeds a recorded line and word budget, **and** when any single
|
|
61
|
+
`## ` section exceeds its own budget, so one section cannot quietly absorb the
|
|
62
|
+
whole allowance. `docs/readme_size_baseline.json` holds the recorded budget
|
|
63
|
+
(248 lines, 1490 words) and `--update` re-records it, printing a warning when a
|
|
64
|
+
budget is raised rather than lowered. Verified by mutation: appending twelve
|
|
65
|
+
invented bullets to `Honest limits` exits 1 naming that section, and a four-line
|
|
66
|
+
prose expansion of `Documentation` exits 1 naming lines, words and that section.
|
|
67
|
+
**It is not wired into CI by this change** — adding the job means editing
|
|
68
|
+
`.github/workflows/`, which is outside this work's file ownership. Until it is
|
|
69
|
+
wired, the guard only runs when invoked by hand.
|
|
70
|
+
|
|
71
|
+
- The `2.4.3` attestation facts were re-measured rather than assumed: the PyPI
|
|
72
|
+
per-file provenance endpoint returns `200` for both the wheel and the sdist, and
|
|
73
|
+
the npm attestations endpoint returns `404`. The README keeps the two-line
|
|
74
|
+
statement naming both channels, and `test_readme_states_the_npm_attestation_gap`
|
|
75
|
+
still passes against it.
|
|
76
|
+
|
|
77
|
+
### Fixed
|
|
78
|
+
|
|
79
|
+
- **Supply-chain claims are now measured, scoped and separated by mechanism.** The three
|
|
80
|
+
things that get blurred into "attested" are now named separately wherever they appear
|
|
81
|
+
in `README.md`, `SECURITY.md` and `docs/release-status.md`:
|
|
82
|
+
1. a **digest** (`dist.integrity`, `digests.sha256`) proves the bytes match what was
|
|
83
|
+
published and says nothing about the build;
|
|
84
|
+
2. npm's **`dist.signatures`** is a registry *transport* signature over the packument,
|
|
85
|
+
present for every package whether or not it was built in CI, and is never build
|
|
86
|
+
provenance;
|
|
87
|
+
3. a **build attestation** (Sigstore/in-toto on npm, PEP 740 on PyPI) is the only one of
|
|
88
|
+
the three that names a workflow, repository and commit.
|
|
89
|
+
- **The current version was stale at `2.4.2` in the release-status claims** while `2.4.3` is
|
|
90
|
+
the release on both registries. Refreshed, with the npm `shasum`, integrity, file count
|
|
91
|
+
and unpacked size, and the PyPI wheel and sdist SHA-256, all re-measured. The npm values
|
|
92
|
+
were re-checked by running `npm pack` on `main` (`45fd5ee`): integrity reproduces exactly.
|
|
93
|
+
- **The PyPI integrity URL shape is called out explicitly**, because reading the wrong shape
|
|
94
|
+
is how a false negative gets reported. PyPI serves attestations **per file**, so the path
|
|
95
|
+
ends in `/<filename>/provenance`. `https://pypi.org/integrity/plan-auditor/2.4.3/` is not
|
|
96
|
+
an endpoint and returns `404`; that `404` means "no such URL", **not** "no attestation".
|
|
97
|
+
The per-file endpoint returns `200` with an in-toto v1 statement, predicate type
|
|
98
|
+
`https://docs.pypi.org/attestations/publish/v1`, publisher
|
|
99
|
+
`kind=GitHub, repository=Furox-Art/plan-auditor, workflow=release.yml, environment=pypi`,
|
|
100
|
+
whose subject digest equals the SHA-256 PyPI serves for the file.
|
|
101
|
+
- **The condition for npm provenance is stated as pending**, with the four facts it needs:
|
|
102
|
+
a trusted publisher on npmjs.com for owner `Furox-Art`, package `plan-auditor`, workflow
|
|
103
|
+
filename `npm-publish.yml`, and the environment the publish job declares. Nothing in this
|
|
104
|
+
repository needs to change. Until that record exists, npm consumers verify by digest and
|
|
105
|
+
the docs keep saying so.
|
|
106
|
+
- `SECURITY.md` gained the per-channel verification commands and the mechanism table, so a
|
|
107
|
+
reader can check a claim without trusting this repository.
|
|
108
|
+
|
|
109
|
+
### Added
|
|
110
|
+
|
|
111
|
+
- **`docs/check_attestation_claims.py`** — a regression guard for supply-chain claims, with
|
|
112
|
+
its own negative control. It rejects any attestation claim that names no channel, that
|
|
113
|
+
states no definite status, that presents `dist.signatures` as provenance, or that calls a
|
|
114
|
+
stale version current. Run it three ways:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
python docs/check_attestation_claims.py # scan the docs
|
|
118
|
+
python docs/check_attestation_claims.py --online # also re-measure both registries
|
|
119
|
+
python docs/check_attestation_claims.py --self-test # negative control
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The negative control feeds the guard five deliberately false claims and fails unless all
|
|
123
|
+
five are rejected, plus one correct claim it must accept and two same-word-different-meaning
|
|
124
|
+
cases (`docs/benchmark.md` measurement provenance, `docs/formal-planning.md` source
|
|
125
|
+
provenance) it must not flag. A guard that cannot be shown to reject a known lie is not a
|
|
126
|
+
guard, so `--self-test` is part of the deliverable rather than a nicety.
|
|
127
|
+
|
|
128
|
+
It is not wired into CI, because this change set does not touch workflows. Adding one step
|
|
129
|
+
to `.github/workflows/plan-audit.yml` that runs
|
|
130
|
+
`python docs/check_attestation_claims.py --self-test && python docs/check_attestation_claims.py`
|
|
131
|
+
would close that; until then it runs on demand.
|
|
132
|
+
|
|
133
|
+
### Not claimed
|
|
134
|
+
|
|
135
|
+
- No security claim is weakened anywhere. npm is still described as digest-only, and the
|
|
136
|
+
PyPI attestation is still described as present, because that is what the registries
|
|
137
|
+
return.
|
|
138
|
+
|
|
7
139
|
## v2.4.3 - 2026-10-04
|
|
8
140
|
|
|
9
141
|
A documentation release. The README restructure and the three corrections below
|
|
@@ -21,8 +21,8 @@ authors:
|
|
|
21
21
|
repository-code: "https://github.com/Furox-Art/plan-auditor"
|
|
22
22
|
url: "https://github.com/Furox-Art/plan-auditor"
|
|
23
23
|
license: MIT
|
|
24
|
-
version: 2.4.
|
|
25
|
-
date-released: "2026-10-
|
|
24
|
+
version: 2.4.4
|
|
25
|
+
date-released: "2026-10-10"
|
|
26
26
|
keywords:
|
|
27
27
|
- AI coding agents
|
|
28
28
|
- deterministic verification
|
|
@@ -221,7 +221,7 @@ with a non-zero code if Python cannot be started at all.
|
|
|
221
221
|
- Every command you document must exist. `tests/test_docs_metadata.py` parses
|
|
222
222
|
fenced code blocks and checks the subcommand against the real argument parser.
|
|
223
223
|
- Every transcript must be copied from a real run, and any elision must say what
|
|
224
|
-
is elided.
|
|
224
|
+
is elided. An `output:` line whose interior depends on your Python version must be
|
|
225
225
|
scoped, not quoted.
|
|
226
226
|
- Never add a download count, a star count, a user count or a trust badge. Link to
|
|
227
227
|
the package page instead; the tests reject a copied number.
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: plan-auditor
|
|
3
|
+
Version: 2.4.4
|
|
4
|
+
Summary: Deterministic verification and evidence auditing for AI coding agents: sealed plans, hash-chained evidence, and an independent completion gate
|
|
5
|
+
Project-URL: Homepage, https://github.com/Furox-Art/plan-auditor
|
|
6
|
+
Project-URL: Repository, https://github.com/Furox-Art/plan-auditor
|
|
7
|
+
Project-URL: Issues, https://github.com/Furox-Art/plan-auditor/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/Furox-Art/plan-auditor/tree/main/docs
|
|
9
|
+
Project-URL: Changelog, https://github.com/Furox-Art/plan-auditor/blob/main/CHANGELOG.md
|
|
10
|
+
Project-URL: Security, https://github.com/Furox-Art/plan-auditor/blob/main/SECURITY.md
|
|
11
|
+
Project-URL: Contributing, https://github.com/Furox-Art/plan-auditor/blob/main/CONTRIBUTING.md
|
|
12
|
+
Project-URL: Citation, https://github.com/Furox-Art/plan-auditor/blob/main/CITATION.cff
|
|
13
|
+
Author: Furox-Art
|
|
14
|
+
License-Expression: MIT
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Keywords: agent-skills,ai-agents,ai-verification,audit-log,auditing,ci,ci-cd,cli,coding-agents,completion-gate,continuous-integration,developer-tools,evidence,formal-methods,formal-verification,hallucination-detection,llm-agents,model-checking,pddl,plan-execution,provenance,quality-assurance,software-testing,static-analysis,strips,supervisor,supply-chain-security,tamper-evident,test-automation,trust-but-verify,verification
|
|
17
|
+
Classifier: Development Status :: 4 - Beta
|
|
18
|
+
Classifier: Environment :: Console
|
|
19
|
+
Classifier: Intended Audience :: Developers
|
|
20
|
+
Classifier: Intended Audience :: Information Technology
|
|
21
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
22
|
+
Classifier: Natural Language :: English
|
|
23
|
+
Classifier: Operating System :: MacOS
|
|
24
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
25
|
+
Classifier: Operating System :: OS Independent
|
|
26
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
27
|
+
Classifier: Programming Language :: Python :: 3
|
|
28
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
29
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
30
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
31
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
32
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
33
|
+
Classifier: Topic :: Security
|
|
34
|
+
Classifier: Topic :: Software Development
|
|
35
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
36
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
37
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
38
|
+
Classifier: Topic :: Software Development :: Testing
|
|
39
|
+
Classifier: Topic :: System :: Software Distribution
|
|
40
|
+
Classifier: Topic :: System :: Systems Administration
|
|
41
|
+
Requires-Python: >=3.10
|
|
42
|
+
Description-Content-Type: text/markdown
|
|
43
|
+
|
|
44
|
+
# plan-auditor
|
|
45
|
+
|
|
46
|
+
[](https://github.com/Furox-Art/plan-auditor/actions/workflows/plan-audit.yml)
|
|
47
|
+
[](https://github.com/Furox-Art/plan-auditor/actions/workflows/release.yml)
|
|
48
|
+
[](https://pypi.org/project/plan-auditor/)
|
|
49
|
+
[](https://pypi.org/project/plan-auditor/)
|
|
50
|
+
[](https://www.npmjs.com/package/plan-auditor)
|
|
51
|
+
[](LICENSE)
|
|
52
|
+
|
|
53
|
+
Download numbers live on the package pages themselves, where they are always current:
|
|
54
|
+
[PyPI](https://pypi.org/project/plan-auditor/) |
|
|
55
|
+
[npm](https://www.npmjs.com/package/plan-auditor)
|
|
56
|
+
|
|
57
|
+
**An AI agent says "done." This tool makes "done" mean "here is the command output that proves it."**
|
|
58
|
+
|
|
59
|
+
## The problem
|
|
60
|
+
|
|
61
|
+
Ask a coding agent to change something and it reports success with confident prose.
|
|
62
|
+
Sometimes it never ran the tests. Sometimes it ran them once, failed, and edited the
|
|
63
|
+
test until it went green. What you are left with is narration, and narration looks
|
|
64
|
+
identical to a result until you re-run everything yourself.
|
|
65
|
+
|
|
66
|
+
## The solution
|
|
67
|
+
|
|
68
|
+
Verification runs in a **separate process with its own check implementation**, so the
|
|
69
|
+
implementing agent's claims carry no weight — only sealed command output does.
|
|
70
|
+
|
|
71
|
+
- Every step is a machine-checkable requirement, not a prose bullet.
|
|
72
|
+
- Every step needs at least one **behavioral** check (`run`, `pytest`, `exec`). A
|
|
73
|
+
file-existence check can never verify a step on its own.
|
|
74
|
+
- Output is appended to a SHA-256 hash-chained, tamper-evident log.
|
|
75
|
+
- The plan's verification contract is **sealed** on approval and can only be
|
|
76
|
+
strengthened afterwards, never weakened.
|
|
77
|
+
- A failed check fails closed: `audit` exits non-zero until every check really passes.
|
|
78
|
+
|
|
79
|
+
There is no LLM in the verification path, and no network call.
|
|
80
|
+
|
|
81
|
+
## Who it is for
|
|
82
|
+
|
|
83
|
+
- Anyone who ships AI-generated code and needs receipts before merge.
|
|
84
|
+
- Agent-skill authors who want a gate an agent cannot talk its way past.
|
|
85
|
+
- Teams adding a required CI step for "the agent must prove it".
|
|
86
|
+
- Researchers who want LLM-free STRIPS/PDDL-style reachability checks over a plan.
|
|
87
|
+
|
|
88
|
+
## Install
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pipx install plan-auditor # isolated CLI, recommended
|
|
92
|
+
pip install plan-auditor # into the current environment / virtualenv
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Python 3.10 or newer, no third-party runtime dependencies. The npm package is a thin Node
|
|
96
|
+
launcher for the same CLI and needs Python on `PATH`. The examples call the interpreter
|
|
97
|
+
`python`; on a system that only ships `python3`, use a virtualenv that provides `python`.
|
|
98
|
+
In CI, add `- uses: Furox-Art/plan-auditor@main` with `path: .` — see
|
|
99
|
+
[integrations](https://github.com/Furox-Art/plan-auditor/blob/main/docs/integrations.md).
|
|
100
|
+
|
|
101
|
+
**Release status:** `2.4.3` is current on both registries. PyPI publishes every artifact
|
|
102
|
+
with a PEP 740 provenance attestation; npm has **no** provenance attestation and its
|
|
103
|
+
attestations endpoint returns `404` for one. Measured per channel in
|
|
104
|
+
[docs/release-status.md](https://github.com/Furox-Art/plan-auditor/blob/main/docs/release-status.md).
|
|
105
|
+
|
|
106
|
+
## Quick start (verified, 5 minutes)
|
|
107
|
+
|
|
108
|
+
`tests/test_readme_quickstart.py` runs these commands on every CI run and compares the
|
|
109
|
+
transcript to real output without normalising hash values, so it cannot drift. Copy the
|
|
110
|
+
two files verbatim — `request-source.json` is the input to the `request_sha256` below.
|
|
111
|
+
|
|
112
|
+
**1. Create the project and the plan.**
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
mkdir plan-auditor-demo && cd plan-auditor-demo
|
|
116
|
+
mkdir .plan-auditor
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`.plan-auditor/plan.json`, and `request-source.json` beside it — the host-owned
|
|
120
|
+
statement of what you asked for, sealed on activation so the agent cannot restate it:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"task": "Prove README.md exists and prints its first line",
|
|
125
|
+
"created": "2026-07-24T00:00:00",
|
|
126
|
+
"requirements": [{ "id": "REQ-001", "description": "README.md must exist in the project root and print its first line.", "priority": "must" }],
|
|
127
|
+
"steps": [{
|
|
128
|
+
"id": 1, "title": "README.md exists and is readable", "covers": ["REQ-001"], "status": "pending",
|
|
129
|
+
"verify": [
|
|
130
|
+
{ "type": "file_exists", "path": "README.md" },
|
|
131
|
+
{ "type": "run", "cmd": "python -c \"print(open('README.md', encoding='utf-8').read().strip())\"", "expect_exit": 0 }
|
|
132
|
+
]
|
|
133
|
+
}]
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"format_version": 1,
|
|
140
|
+
"task": "Prove README.md exists and prints its first line",
|
|
141
|
+
"requirements": [{
|
|
142
|
+
"id": "REQ-001", "description": "README.md must exist in the project root and print its first line.", "priority": "must",
|
|
143
|
+
"acceptance_checks": [
|
|
144
|
+
{ "type": "file_exists", "path": "README.md" },
|
|
145
|
+
{ "type": "run", "cmd": "python -c \"print(open('README.md', encoding='utf-8').read().strip())\"", "expect_exit": 0 }
|
|
146
|
+
]
|
|
147
|
+
}]
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**2. Run the gate.**
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
plan-auditor request init . --file request-source.json
|
|
155
|
+
plan-auditor plan verify .
|
|
156
|
+
plan-auditor run . 1
|
|
157
|
+
plan-auditor audit .
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Real output. A lone `...` marks fields omitted for length; every other line is verbatim,
|
|
161
|
+
and every JSON level that is not elided lists exactly the keys the tool emits.
|
|
162
|
+
|
|
163
|
+
```console
|
|
164
|
+
$ plan-auditor request init . --file request-source.json
|
|
165
|
+
{
|
|
166
|
+
"activated": true,
|
|
167
|
+
"valid": true,
|
|
168
|
+
"reason": "request contract active",
|
|
169
|
+
"request_sha256": "d39e577eb0577d8c0c81231fdd7fc559d1c6045ecc5e5bd3a00e7e8f2f49197b",
|
|
170
|
+
"authenticated": false
|
|
171
|
+
}
|
|
172
|
+
$ plan-auditor plan verify .
|
|
173
|
+
{
|
|
174
|
+
"plans": {
|
|
175
|
+
...
|
|
176
|
+
},
|
|
177
|
+
"outcome": "PASS"
|
|
178
|
+
}
|
|
179
|
+
$ plan-auditor run . 1
|
|
180
|
+
[OK ] step 1: README.md exists and is readable (attempt 1/3)
|
|
181
|
+
- passed | README.md EXISTS
|
|
182
|
+
- passed | exit=0 (expected 0)
|
|
183
|
+
$ plan-auditor audit .
|
|
184
|
+
...
|
|
185
|
+
{
|
|
186
|
+
"outcome": "PASS",
|
|
187
|
+
"plans": {
|
|
188
|
+
"default": "PASS"
|
|
189
|
+
},
|
|
190
|
+
"deterministic_core": "fresh audit PASS for every active plan under workspace-wide freeze",
|
|
191
|
+
"gate": {
|
|
192
|
+
"outcome": "PASS",
|
|
193
|
+
...
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Scoped omission: the elided fields are the plan-inspection block and `seal`, the per-step
|
|
199
|
+
progress lines and verdict table, and the gate's remaining fields including
|
|
200
|
+
`policy_findings`, `verdict` and `seal_ok`. [docs/cli.md](https://github.com/Furox-Art/plan-auditor/blob/main/docs/cli.md)
|
|
201
|
+
shows each command's full output.
|
|
202
|
+
|
|
203
|
+
`audit` re-runs every check in a fresh subprocess, and only exit code `0` means the work is
|
|
204
|
+
proven. Progress lines are English human-readable output; the JSON verdict
|
|
205
|
+
is the stable machine interface, so parse `"outcome"`.
|
|
206
|
+
|
|
207
|
+
## How it works
|
|
208
|
+
|
|
209
|
+
Fifteen layers, arranged so a weaker signal can never overrule a stronger one. Two
|
|
210
|
+
facts carry the design: **L10 (`scripts/audit_check.py`) is the only component that can
|
|
211
|
+
mark a step `verified`**, and **L13 (`gate.py`) is the only one that emits a final
|
|
212
|
+
`PASS`/`FAIL`/`UNKNOWN`**. Everything else feeds those two.
|
|
213
|
+
|
|
214
|
+
| Band | Layers | Role |
|
|
215
|
+
|---|---|---|
|
|
216
|
+
| Sense | L0 `events`, L1 `requirements`, L2 `workspace`, L5 `plan_verifier` | Read the task, the tree and the plan |
|
|
217
|
+
| Decide | L3 `policies`, L4 `goals`, L7 `priority` | Deterministic rules; subsumption authority |
|
|
218
|
+
| Protect | L8 `sealing`, L9 `watchdog`, L11 `evidence`, L12 `adversarial` | Seal, monitor, chain, propose |
|
|
219
|
+
| Execute | **L10 `audit_check`**, L6 `lifecycle` | Run real checks; drive the state machine |
|
|
220
|
+
| Gate | **L13 `gate`**, L14 `agents` | Emit the verdict; coordinate parallel agents |
|
|
221
|
+
|
|
222
|
+
A failure at subsumption level N cannot be overridden by a PASS from any higher level.
|
|
223
|
+
Per-layer detail, profiles (`light`/`standard`/`strict`), run modes
|
|
224
|
+
(`serial`/`parallel-warn`/`parallel-strict`) and LLM tiers (`NO_LLM`, `SMALL_LOCAL`,
|
|
225
|
+
`STRONG_LOCAL`, `REMOTE`) are in
|
|
226
|
+
[docs/architecture.md](https://github.com/Furox-Art/plan-auditor/blob/main/docs/architecture.md).
|
|
227
|
+
|
|
228
|
+
## Use it as an Agent Skill
|
|
229
|
+
|
|
230
|
+
The skill is `SKILL.md` plus `scripts/`, `references/` and `hooks/`, either from a
|
|
231
|
+
checkout or from a `pip` install, which ships them under `plan_auditor_skill/`. Copy
|
|
232
|
+
them into your host's skills directory — `~/.claude/`, `~/.commandcode/`,
|
|
233
|
+
`~/.config/opencode/` or `~/.codex/`, each with a `skills/plan-auditor/` subdirectory.
|
|
234
|
+
`hooks/gate_hook.py` is the single authoritative hook gate; there are no per-host
|
|
235
|
+
adapter files, so wire each host's blocking stop or lifecycle hook to that one command.
|
|
236
|
+
Per-host paths and CI wiring:
|
|
237
|
+
[docs/integrations.md](https://github.com/Furox-Art/plan-auditor/blob/main/docs/integrations.md).
|
|
238
|
+
|
|
239
|
+
## Documentation
|
|
240
|
+
|
|
241
|
+
Reading order starts at [docs/index.md](https://github.com/Furox-Art/plan-auditor/blob/main/docs/index.md).
|
|
242
|
+
|
|
243
|
+
| You want | Go to |
|
|
244
|
+
|---|---|
|
|
245
|
+
| A verified task end to end; troubleshooting per real error | [quickstart](https://github.com/Furox-Art/plan-auditor/blob/main/docs/quickstart.md) |
|
|
246
|
+
| Every subcommand, real invocations, exit codes `0`/`1`/`2`/`3` | [cli](https://github.com/Furox-Art/plan-auditor/blob/main/docs/cli.md) |
|
|
247
|
+
| Per-layer detail, profiles, run modes, LLM tiers | [architecture](https://github.com/Furox-Art/plan-auditor/blob/main/docs/architecture.md) |
|
|
248
|
+
| What the tool writes into `.plan-auditor/`, and why | [workspace artifacts](https://github.com/Furox-Art/plan-auditor/blob/main/docs/workspace-artifacts.md) |
|
|
249
|
+
| Step DAGs, formal planning, threat model, deployment isolation | [dependency graph](https://github.com/Furox-Art/plan-auditor/blob/main/docs/dependency-graph.md) · [formal planning](https://github.com/Furox-Art/plan-auditor/blob/main/docs/formal-planning.md) · [threat model](https://github.com/Furox-Art/plan-auditor/blob/main/docs/threat-model.md) · [deployment isolation](https://github.com/Furox-Art/plan-auditor/blob/main/docs/deployment-isolation.md) |
|
|
250
|
+
| Skill hosts, blocking hooks, CI | [integrations](https://github.com/Furox-Art/plan-auditor/blob/main/docs/integrations.md) |
|
|
251
|
+
| Published versions, defects, attestations; what is measurable | [release status](https://github.com/Furox-Art/plan-auditor/blob/main/docs/release-status.md) · [benchmark](https://github.com/Furox-Art/plan-auditor/blob/main/docs/benchmark.md) |
|
|
252
|
+
| Plan schema and check types | [plan-format.md](https://github.com/Furox-Art/plan-auditor/blob/main/references/plan-format.md) |
|
|
253
|
+
|
|
254
|
+
Entry points: the `plan-auditor` CLI (`request`, `plan`, `evidence`, `integrity`,
|
|
255
|
+
`supervisor`, `task`, `agents`, `run`, `validate`, `audit`, `doctor`); the core
|
|
256
|
+
`python scripts/audit_check.py` (`validate`, `run`, `audit`, `status`, `snapshot`,
|
|
257
|
+
`rollback`); and `plan-auditor-formalize`, `plan-auditor-formal` (`verify`,
|
|
258
|
+
`export-pddl`, `make-check`) and `plan-auditor-migrate-seal`.
|
|
259
|
+
|
|
260
|
+
Check types are `run`, `exec`, `pytest`, `regex` and `file_exists`; `regex` and
|
|
261
|
+
`file_exists` are non-behavioural and cannot verify a step alone. Exit codes are `0`
|
|
262
|
+
proven, `1` failed, `2` blocked, `3` `UNKNOWN` — and `3` withholds completion rather than
|
|
263
|
+
passing it. The npm launcher mirrors them and fails closed. Runnable example:
|
|
264
|
+
[`examples/fib/`](https://github.com/Furox-Art/plan-auditor/tree/main/examples/fib).
|
|
265
|
+
|
|
266
|
+
No rendered documentation site exists yet. `mkdocs build --strict` is a required CI check,
|
|
267
|
+
so the Markdown is known to build, but nothing serves it; build it with
|
|
268
|
+
`python -m pip install mkdocs-material && mkdocs serve`. Files GitHub already renders:
|
|
269
|
+
[SKILL.md](https://github.com/Furox-Art/plan-auditor/blob/main/SKILL.md) ·
|
|
270
|
+
[CONTRIBUTING.md](https://github.com/Furox-Art/plan-auditor/blob/main/CONTRIBUTING.md) ·
|
|
271
|
+
[CHANGELOG.md](https://github.com/Furox-Art/plan-auditor/blob/main/CHANGELOG.md) ·
|
|
272
|
+
[SECURITY.md](https://github.com/Furox-Art/plan-auditor/blob/main/SECURITY.md)
|
|
273
|
+
|
|
274
|
+
## Honest limits
|
|
275
|
+
|
|
276
|
+
- **Not an OS sandbox.** In a normal install the agent and the verifier run as the
|
|
277
|
+
same OS user.
|
|
278
|
+
- Evidence is **tamper-evident**, not tamper-proof; HMAC integrity is only as strong
|
|
279
|
+
as the secrecy of the key.
|
|
280
|
+
- It verifies that *declared, checkable* requirements were met. Domain meaning that
|
|
281
|
+
cannot be a deterministic check is reviewed by a human, not guessed.
|
|
282
|
+
- The npm package needs Python on `PATH` and carries **no** Sigstore build
|
|
283
|
+
attestation: the npm attestations endpoint returns `404` for `2.4.3`. Its
|
|
284
|
+
`dist.signatures` block is a registry transport signature and is **not** build
|
|
285
|
+
provenance, so verify the npm tarball against `dist.integrity` instead.
|
|
286
|
+
PyPI does carry a PEP 740 provenance attestation for every artifact.
|
|
287
|
+
- No comparison against other tools has been measured, no telemetry is collected,
|
|
288
|
+
and no download or usage figure is printed anywhere in this repository.
|
|
289
|
+
- Maintained by one person, pre-1.0, with no external contributors yet. That means
|
|
290
|
+
slow review, not unwanted contributions.
|