plan-auditor 2.0.2__tar.gz → 2.2.0__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.
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/.gitignore +10 -0
- plan_auditor-2.2.0/CHANGELOG.md +68 -0
- plan_auditor-2.2.0/PKG-INFO +309 -0
- plan_auditor-2.2.0/README.md +287 -0
- plan_auditor-2.2.0/SKILL.md +191 -0
- plan_auditor-2.2.0/docs/dependency-graph.md +95 -0
- plan_auditor-2.2.0/docs/deployment-isolation.md +59 -0
- plan_auditor-2.2.0/docs/integrations.md +122 -0
- plan_auditor-2.2.0/docs/threat-model.md +140 -0
- plan_auditor-2.2.0/hooks/README.md +100 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/pyproject.toml +2 -1
- plan_auditor-2.2.0/references/plan-format.md +173 -0
- plan_auditor-2.2.0/scripts/audit_check.py +1780 -0
- plan_auditor-2.2.0/scripts/integrity.py +170 -0
- plan_auditor-2.2.0/scripts/plan_graph.py +238 -0
- plan_auditor-2.2.0/scripts/stop_gate.py +72 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/supervisor/__init__.py +6 -1
- plan_auditor-2.2.0/supervisor/agents.py +779 -0
- plan_auditor-2.2.0/supervisor/agents_hardening.py +382 -0
- plan_auditor-2.2.0/supervisor/audit_session.py +140 -0
- plan_auditor-2.2.0/supervisor/cli.py +704 -0
- plan_auditor-2.2.0/supervisor/config.py +217 -0
- plan_auditor-2.2.0/supervisor/contracts.py +76 -0
- plan_auditor-2.2.0/supervisor/control_plane.py +88 -0
- plan_auditor-2.2.0/supervisor/coverage.py +108 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/supervisor/daemon.py +64 -4
- plan_auditor-2.2.0/supervisor/evidence.py +386 -0
- plan_auditor-2.2.0/supervisor/integrity.py +146 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/supervisor/lifecycle.py +3 -1
- plan_auditor-2.2.0/supervisor/lock_hardening.py +144 -0
- plan_auditor-2.2.0/supervisor/orchestrator.py +586 -0
- plan_auditor-2.2.0/supervisor/plan_verifier.py +188 -0
- plan_auditor-2.2.0/supervisor/plans.py +107 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/supervisor/policies.py +156 -32
- plan_auditor-2.2.0/supervisor/request_contract.py +367 -0
- plan_auditor-2.2.0/supervisor/seal_migration.py +157 -0
- plan_auditor-2.2.0/supervisor/sealing.py +447 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/supervisor/watchdog.py +27 -21
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/supervisor/workspace.py +30 -21
- plan_auditor-2.2.0/tests/request_fixture.py +47 -0
- plan_auditor-2.2.0/tests/test_agent_registry_chain.py +174 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/tests/test_agents_gate.py +3 -1
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/tests/test_audit_check.py +66 -1
- plan_auditor-2.2.0/tests/test_authenticated_integrity.py +146 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/tests/test_cli.py +30 -6
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/tests/test_daemon.py +43 -0
- plan_auditor-2.2.0/tests/test_dependency_graph.py +169 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/tests/test_extra_layers.py +4 -2
- plan_auditor-2.2.0/tests/test_full_contract_hardening.py +329 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/tests/test_hooks.py +29 -4
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/tests/test_integration_hardening.py +25 -5
- plan_auditor-2.2.0/tests/test_registry_lock_partial.py +40 -0
- plan_auditor-2.2.0/tests/test_request_contract_hardening.py +108 -0
- plan_auditor-2.2.0/tests/test_root_cause_fixes_v220.py +336 -0
- plan_auditor-2.2.0/tests/test_runtime_root_hardening.py +275 -0
- plan_auditor-2.2.0/tests/wheel_cli_smoke.py +291 -0
- plan_auditor-2.0.2/CHANGELOG.md +0 -30
- plan_auditor-2.0.2/PKG-INFO +0 -294
- plan_auditor-2.0.2/README.md +0 -272
- plan_auditor-2.0.2/SKILL.md +0 -100
- plan_auditor-2.0.2/docs/integrations.md +0 -54
- plan_auditor-2.0.2/docs/threat-model.md +0 -91
- plan_auditor-2.0.2/hooks/README.md +0 -141
- plan_auditor-2.0.2/references/plan-format.md +0 -47
- plan_auditor-2.0.2/scripts/audit_check.py +0 -703
- plan_auditor-2.0.2/scripts/stop_gate.py +0 -72
- plan_auditor-2.0.2/supervisor/agents.py +0 -252
- plan_auditor-2.0.2/supervisor/cli.py +0 -483
- plan_auditor-2.0.2/supervisor/config.py +0 -99
- plan_auditor-2.0.2/supervisor/evidence.py +0 -153
- plan_auditor-2.0.2/supervisor/orchestrator.py +0 -379
- plan_auditor-2.0.2/supervisor/plan_verifier.py +0 -96
- plan_auditor-2.0.2/supervisor/sealing.py +0 -181
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/CONTRIBUTING.md +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/LICENSE +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/docs/architecture.md +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/examples/fib/.plan-auditor/plan.json +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/examples/fib/fib.py +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/examples/fib/test_fib.py +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/scripts/__init__.py +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/supervisor/adversarial.py +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/supervisor/events.py +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/supervisor/gate.py +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/supervisor/goals.py +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/supervisor/priority.py +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/supervisor/requirements.py +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/tests/test_adversarial.py +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/tests/test_core_layers.py +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/tests/test_events.py +0 -0
- {plan_auditor-2.0.2 → plan_auditor-2.2.0}/tests/test_failure_injection.py +0 -0
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
__pycache__/
|
|
2
2
|
*.pyc
|
|
3
3
|
.pytest_cache/
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
*.egg-info/
|
|
4
7
|
.plan-auditor/evidence.jsonl
|
|
8
|
+
.plan-auditor/evidence.head.json
|
|
9
|
+
.plan-auditor/evidence.write.lock
|
|
10
|
+
.plan-auditor/audit.freeze.lock
|
|
11
|
+
.plan-auditor/request.json
|
|
12
|
+
.plan-auditor/activation.json
|
|
13
|
+
.plan-auditor/integrity.json
|
|
5
14
|
.plan-auditor/*.tmp
|
|
6
15
|
.plan-auditor/archive/
|
|
7
16
|
.plan-auditor/snapshots/
|
|
8
17
|
.plan-auditor/seal.json
|
|
18
|
+
.plan-auditor/seals/
|
|
9
19
|
.plan-auditor/supervisor-runtime.json
|
|
10
20
|
.plan-auditor/supervisor-assessment.json
|
|
11
21
|
.plan-auditor/supervisor.stop
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
## Unreleased
|
|
2
|
+
|
|
3
|
+
- None yet.
|
|
4
|
+
|
|
5
|
+
# Changelog
|
|
6
|
+
|
|
7
|
+
## v2.2.0 — 2026-09-05
|
|
8
|
+
|
|
9
|
+
- **Physical control-plane confinement:** existing `.plan-auditor`, plan, seal, request/activation and policy path components are inspected with `lstat`; symlinked parents/leaves cannot redefine the workspace trust root.
|
|
10
|
+
- **Policy read confinement:** `load_config` authorizes only symlink-free workspace policy directories before policy loading; a resolved external symlink target is rejected before its files are read.
|
|
11
|
+
- **Sealed scope freeze:** automatic monotonic strengthening remains available for extra deterministic checks/prerequisites, but new steps, requirements, tools, coverage assignments or declared outputs now require a new host-approved request generation.
|
|
12
|
+
- **Safe v3→v4 migration:** `plan-auditor-migrate-seal` provides a representation-only migration path for exact full-contract v3 seals. It requires authoritative request alignment and refuses any plan-scope change.
|
|
13
|
+
- **Seal self-consistency:** v3/v4 seals validate their contract hash and criteria count on load/save before being trusted or authenticated.
|
|
14
|
+
- **Streaming evidence verification:** JSONL verification, hashing and HMAC migration retain one record/chunk at a time instead of reading complete evidence/archive files into RAM.
|
|
15
|
+
- **PID-aware registry locking:** registry transaction locks carry PID + random token; live owners are never evicted because of age alone, and stale cleanup requires a provably dead PID plus unchanged lock identity.
|
|
16
|
+
- **Activation semantics:** a lone `.plan-auditor/supervisor.json`, log or cache no longer makes a plans-free workspace look like an activated failed task; request/seal/evidence/plan/integrity/registry state still prevents deletion from degrading to `NO_PLAN`.
|
|
17
|
+
- **Single audit freeze implementation:** the unused `workspace.audit.lock` implementation was removed; `audit.freeze.lock`/`final_audit_session` remains the sole workspace final-audit freeze path.
|
|
18
|
+
- **Version identity:** source/package version advances to `2.2.0`, preventing post-v2.1.0 hardening from producing a different wheel under the already-published `2.1.0` version.
|
|
19
|
+
- **Trust-boundary documentation:** deliberate same-OS-user interference is explicitly treated as an OS isolation problem; separate account/container/VM deployment is required when that attacker is in scope.
|
|
20
|
+
- **Regression coverage:** new tests cover plan/policy symlink escapes, scope expansion, config-only activation, PID-aware registry locks, streaming evidence verification and exact legacy-seal migration.
|
|
21
|
+
|
|
22
|
+
## v2.1.0 — 2026-09-05
|
|
23
|
+
|
|
24
|
+
- **Aggregate multi-plan completion:** the integrated supervisor now enumerates the default plan and every safe `.plan-auditor/plans/<name>.json` plan. Global PASS requires every active plan to PASS; a passing default plan cannot hide an unfinished named plan, and a named-only workspace is no longer misclassified as `NO_PLAN`.
|
|
25
|
+
- **Explicit requirement coverage:** Supervisor Mode requires explicit requirements and deterministic `covers` links from steps. Every `must`/`should` requirement must be covered; omitted user requirements, unknown coverage IDs and duplicate requirement contracts block plan approval/PASS.
|
|
26
|
+
- **Full-contract format-v3 seals:** seals bind task, requirements, required tools, step identity/order/title, requirement coverage, dependencies, required outputs, output contracts/checks, step checks, and the supervisor profile/mode/tier/policy fingerprint. Existing criteria may only be strengthened.
|
|
27
|
+
- **Authenticated seals:** external-key HMAC integrity authenticates plan seals in addition to evidence, checkpoints, registry state and the integrity marker. Seal tampering or missing/wrong key material fails closed after integrity initialization.
|
|
28
|
+
- **Configuration/policy downgrade prevention:** malformed supervisor configuration and configured policy files are explicit blocking errors. Profile/mode/tier and policy-file fingerprint are part of the sealed environment contract, so a post-seal downgrade is detected.
|
|
29
|
+
- **Evidence concurrency and rotation continuity:** evidence append/rotation uses a cross-process exclusive lock, active evidence links the latest archive tail, and failed-attempt limits are counted across archived plus active evidence instead of resetting after rotation.
|
|
30
|
+
- **Complete evidence verification:** `plan-auditor evidence verify` checks both active evidence and anchored archives.
|
|
31
|
+
- **Safe plan addressing:** named plan IDs are validated as safe basenames and cannot use lexical `..` traversal outside `.plan-auditor/plans`.
|
|
32
|
+
- **Canonical multi-agent ownership:** agent IDs are safe basenames and ownership paths are canonical workspace-relative paths before conflict comparison, preventing alternate spellings from evading `parallel-strict` overlap detection.
|
|
33
|
+
- **Transactional full-scope rollback:** default snapshots carry a manifest with file type, mode and hash; rollback restores that state and removes files introduced after the snapshot. Explicit snapshot lists remain intentionally scoped.
|
|
34
|
+
- **Stronger fresh-audit fingerprint:** workspace fingerprints include directories, file type and mode/executable bits in addition to contents and symlink targets.
|
|
35
|
+
- **Internal shell removal:** workspace/world-model and watchdog Git probes use structured argv with `shell=False`; behavioral plan checks still require explicit `shell: true` for shell interpretation.
|
|
36
|
+
- **Bounded verifier output:** command output is spooled/bounded instead of being captured without limit in memory; output-limit overflow fails the check.
|
|
37
|
+
- **Doctor fail-closed exit codes:** `doctor` recomputes a current assessment and returns nonzero on FAIL/UNKNOWN instead of hiding a failed assessment behind exit 0.
|
|
38
|
+
- **Authoritative hook unification:** `hooks/gate_hook.py` is the single integrated gate. `scripts/stop_gate.py` remains only as an exit-code-2 compatibility adapter and delegates to the same multi-plan full-contract assessment instead of trusting `status=verified`.
|
|
39
|
+
- **Three-platform packaging and release gates:** real wheels are built and installed in clean virtual environments on Ubuntu, Windows and macOS. Smoke tests exercise multi-plan discovery, DAG/output dependencies, requirement coverage, full-contract seals, external-key HMAC, integrated audit, doctor, and evidence/integrity CLI paths. PyPI publishing waits for the same three-platform wheel preflight.
|
|
40
|
+
- **Versioning:** development version advanced to `2.1.0` so the hardened source cannot be confused with the already-published `2.0.2` artifact.
|
|
41
|
+
- **Regression hardening:** dedicated failure-injection tests cover named-plan bypasses, seal-contract weakening, environment downgrade, HMAC seal tampering, invalid config/policies, path traversal, evidence races/rotation/retry history, active-log tampering, rollback cleanup, executable-bit fingerprint changes, canonical agent conflicts, missing tools and bounded verifier output.
|
|
42
|
+
- **Observational final audit:** a full audit fails if a verifier mutates product workspace content, type, or mode. Verification must prove pre-existing implementation state rather than creating the claimed result during the audit itself.
|
|
43
|
+
|
|
44
|
+
## v2.0.2 — 2026-09-05
|
|
45
|
+
|
|
46
|
+
- **Integrated supervisor pipeline:** new `supervisor/orchestrator.py` wires plan validation, requirements, workspace state, policies, sealing, deterministic evidence, adversarial review, completion gating, lifecycle state, and multi-agent state into one fail-closed assessment.
|
|
47
|
+
- **Real hook enforcement:** `hooks/gate_hook.py` no longer trusts `status=verified` or fabricated integrity flags; PASS requires a valid seal and matching fresh full-audit evidence.
|
|
48
|
+
- **Deterministic audit freshness:** full audits record SHA-256 fingerprints of the verification contract and workspace contents instead of relying on filesystem mtimes.
|
|
49
|
+
- **Cross-archive evidence anchoring:** rotations write archive anchors and L11 verifies internal JSONL hash chains and links between archives.
|
|
50
|
+
- **Persistent multi-agent state:** ownership and heartbeat updates are written to the shared registry; separate processes see the same state, and `parallel-strict` rejects overlapping file claims.
|
|
51
|
+
- **Adversarial gate integration:** high/critical L12 findings with no deterministic follow-up prevent PASS and produce UNKNOWN instead of being ignored.
|
|
52
|
+
- **User policy loading:** deterministic JSON/TOML policies load from configured policy directories.
|
|
53
|
+
- **Workspace safety:** file checks and rollback are path-confined; workspace observation is read-only and uses `shutil.which()` instead of shell redirections that could create files.
|
|
54
|
+
- **Daemon integration:** the background supervisor persists an integrated assessment and final gate outcome on every observation cycle.
|
|
55
|
+
|
|
56
|
+
## v1.1.0 — 2026-09-03
|
|
57
|
+
|
|
58
|
+
- **Portable skill paths:** `SKILL.md` resolves auditor scripts relative to the skill directory.
|
|
59
|
+
- **Hard attempt cap:** `run` refuses a step after the configured failed-attempt cap unless explicitly forced.
|
|
60
|
+
- **Multi-plan core support:** `--plan <name>` operates on `.plan-auditor/plans/<name>.json`; evidence is scoped per plan.
|
|
61
|
+
- **Snapshot / rollback:** snapshot and rollback support were introduced and recorded in evidence.
|
|
62
|
+
- **Evidence rotation:** large evidence logs rotate into `.plan-auditor/archive/`.
|
|
63
|
+
|
|
64
|
+
## v1.0.0 — 2026-09-03
|
|
65
|
+
|
|
66
|
+
- Initial strict plan + independent auditor Agent Skill.
|
|
67
|
+
- Machine-checkable `verify` checks (`run`, `exec`, `file_exists`, `regex`, `pytest`).
|
|
68
|
+
- Deterministic fresh execution, append-only SHA-256 evidence, tamper detection, and full-audit final gate.
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: plan-auditor
|
|
3
|
+
Version: 2.2.0
|
|
4
|
+
Summary: Independent multi-layer verification supervisor for AI coding agents
|
|
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
|
+
Author: Furox-Art
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai-agents,auditing,cli,supervisor,verification
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# plan-auditor
|
|
24
|
+
|
|
25
|
+
[](https://github.com/Furox-Art/plan-auditor/actions/workflows/plan-audit.yml)
|
|
26
|
+
|
|
27
|
+
**Independent deterministic verification for AI coding-agent plans.**
|
|
28
|
+
|
|
29
|
+
`plan-auditor` is designed to answer a narrow question reliably:
|
|
30
|
+
|
|
31
|
+
> Did the AI actually complete the user's requirements and its approved plan, or
|
|
32
|
+
> did it only say that it did?
|
|
33
|
+
|
|
34
|
+
The main agent's narration and persisted `status=verified` labels are not enough.
|
|
35
|
+
PASS requires reproducible behavioral checks, explicit requirement coverage, an
|
|
36
|
+
intact sealed verification contract, fresh audit evidence, and a valid aggregate
|
|
37
|
+
completion gate across **every active plan**.
|
|
38
|
+
|
|
39
|
+
## Core completion model
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
User requirements
|
|
43
|
+
│
|
|
44
|
+
▼
|
|
45
|
+
Explicit requirement IDs ──► plan steps (`covers`)
|
|
46
|
+
│ │
|
|
47
|
+
│ ├─ depends_on
|
|
48
|
+
│ ├─ outputs
|
|
49
|
+
│ └─ requires_outputs
|
|
50
|
+
│
|
|
51
|
+
▼
|
|
52
|
+
Format-v3 full-contract seal
|
|
53
|
+
│
|
|
54
|
+
▼
|
|
55
|
+
Deterministic execution / tests
|
|
56
|
+
│
|
|
57
|
+
▼
|
|
58
|
+
Hash-chained evidence + fresh workspace/plan fingerprint
|
|
59
|
+
│
|
|
60
|
+
▼
|
|
61
|
+
Aggregate supervisor gate
|
|
62
|
+
│
|
|
63
|
+
├─ default plan PASS
|
|
64
|
+
├─ named plan A PASS
|
|
65
|
+
├─ named plan B PASS
|
|
66
|
+
└─ policies / tools / registry / integrity PASS
|
|
67
|
+
│
|
|
68
|
+
▼
|
|
69
|
+
PASS / FAIL / UNKNOWN
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## What a PASS means
|
|
73
|
+
|
|
74
|
+
In Supervisor Mode, PASS requires all active plans to satisfy all of the
|
|
75
|
+
following:
|
|
76
|
+
|
|
77
|
+
- valid plan schema,
|
|
78
|
+
- explicit non-empty `requirements`,
|
|
79
|
+
- every `must`/`should` requirement covered by at least one step,
|
|
80
|
+
- at least one behavioral check (`run`, `exec`, `pytest`) per step,
|
|
81
|
+
- valid dependency DAG,
|
|
82
|
+
- concrete output contract for every explicit dependency edge,
|
|
83
|
+
- intact format-v3 seal,
|
|
84
|
+
- unchanged sealed supervisor profile/mode/tier/policy fingerprint,
|
|
85
|
+
- all steps verified in a fresh full audit,
|
|
86
|
+
- current plan contract matches the audited plan fingerprint,
|
|
87
|
+
- current workspace content/type/mode matches the audited workspace fingerprint,
|
|
88
|
+
- active and archived evidence chains valid,
|
|
89
|
+
- agent registry valid,
|
|
90
|
+
- required tools present,
|
|
91
|
+
- no blocking policy result.
|
|
92
|
+
|
|
93
|
+
If any active named plan is unfinished, the whole workspace is non-PASS. A
|
|
94
|
+
passing `plan.json` cannot hide `.plan-auditor/plans/backend.json`.
|
|
95
|
+
|
|
96
|
+
## Deterministic checks
|
|
97
|
+
|
|
98
|
+
Checks run as real subprocesses/filesystem assertions. Structured `argv` is
|
|
99
|
+
preferred:
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"type": "run",
|
|
104
|
+
"argv": ["python", "-m", "pytest", "tests/", "-q"],
|
|
105
|
+
"expect_exit": 0
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Shell interpretation is disabled by default. Legacy `cmd` strings are parsed into
|
|
110
|
+
an argument vector. Shell behavior requires explicit `"shell": true` and cannot
|
|
111
|
+
be combined with `argv`.
|
|
112
|
+
|
|
113
|
+
Verifier output is bounded to avoid unbounded-memory capture.
|
|
114
|
+
|
|
115
|
+
## Requirements, dependencies, and outputs
|
|
116
|
+
|
|
117
|
+
Example plan fragment:
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"task": "build and consume a verified model artifact",
|
|
122
|
+
"created": "2026-09-05T00:00:00Z",
|
|
123
|
+
"requirements": [
|
|
124
|
+
{"id": "REQ-001", "description": "produce the model artifact", "priority": "must"},
|
|
125
|
+
{"id": "REQ-002", "description": "consume the verified artifact", "priority": "must"}
|
|
126
|
+
],
|
|
127
|
+
"required_tools": ["python"],
|
|
128
|
+
"steps": [
|
|
129
|
+
{
|
|
130
|
+
"id": 1,
|
|
131
|
+
"title": "produce artifact",
|
|
132
|
+
"depends_on": [],
|
|
133
|
+
"covers": ["REQ-001"],
|
|
134
|
+
"verify": [{"type": "run", "argv": ["python", "tests/build_artifact.py"]}],
|
|
135
|
+
"outputs": [
|
|
136
|
+
{
|
|
137
|
+
"name": "artifact",
|
|
138
|
+
"verify": [{"type": "file_exists", "path": "results/model.json"}]
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"id": 2,
|
|
144
|
+
"title": "consume artifact",
|
|
145
|
+
"depends_on": [1],
|
|
146
|
+
"requires_outputs": [{"step": 1, "name": "artifact"}],
|
|
147
|
+
"covers": ["REQ-002"],
|
|
148
|
+
"verify": [{"type": "run", "argv": ["python", "tests/use_artifact.py"]}]
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
A downstream step cannot pass until the prerequisite passed and the upstream
|
|
155
|
+
output contract is independently rechecked.
|
|
156
|
+
|
|
157
|
+
## Full-contract sealing
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
plan-auditor plan verify .
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The v3 seal binds:
|
|
164
|
+
|
|
165
|
+
- task and requirements,
|
|
166
|
+
- required tools,
|
|
167
|
+
- step identity/order/title,
|
|
168
|
+
- `covers`,
|
|
169
|
+
- dependencies and required outputs,
|
|
170
|
+
- outputs and their checks,
|
|
171
|
+
- step verification checks,
|
|
172
|
+
- supervisor `profile`, `mode`, `tier`,
|
|
173
|
+
- configured-policy fingerprint.
|
|
174
|
+
|
|
175
|
+
Existing criteria may be strengthened, but removing/changing sealed criteria or
|
|
176
|
+
downgrading the sealed environment blocks completion.
|
|
177
|
+
|
|
178
|
+
## Evidence integrity
|
|
179
|
+
|
|
180
|
+
Evidence records are append-only JSONL records with SHA-256 `prev + hash`
|
|
181
|
+
continuity. The chain spans log rotations; the active log links the latest archive
|
|
182
|
+
tail. Concurrent evidence append/rotation is serialized with an exclusive lock.
|
|
183
|
+
Failed-attempt limits are counted across archived and active evidence.
|
|
184
|
+
|
|
185
|
+
Optional external-key HMAC adds authentication and signed tail checkpoints for:
|
|
186
|
+
|
|
187
|
+
- active/archive evidence records,
|
|
188
|
+
- evidence head,
|
|
189
|
+
- agent registry records/head,
|
|
190
|
+
- plan seals,
|
|
191
|
+
- integrity marker.
|
|
192
|
+
|
|
193
|
+
Initialize after sealing:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# set PLAN_AUDITOR_HMAC_KEY or PLAN_AUDITOR_HMAC_KEY_FILE first
|
|
197
|
+
plan-auditor plan verify .
|
|
198
|
+
plan-auditor integrity init .
|
|
199
|
+
plan-auditor audit .
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
A key file must resolve outside the workspace.
|
|
203
|
+
|
|
204
|
+
## Multi-agent state
|
|
205
|
+
|
|
206
|
+
The persisted agent registry uses `format_version + seq + prev + hash` and an
|
|
207
|
+
anti-truncation head checkpoint. Agent IDs are safe basenames and ownership paths
|
|
208
|
+
are canonical workspace-relative paths, so spellings such as
|
|
209
|
+
`src/../src/shared.py` and `./src/shared.py` cannot evade conflict detection.
|
|
210
|
+
|
|
211
|
+
Modes:
|
|
212
|
+
|
|
213
|
+
- `serial`
|
|
214
|
+
- `parallel-warn`
|
|
215
|
+
- `parallel-strict`
|
|
216
|
+
|
|
217
|
+
## Snapshot / rollback
|
|
218
|
+
|
|
219
|
+
Default snapshots capture the full workspace product state while excluding
|
|
220
|
+
`.git`, `.plan-auditor`, and cache metadata. The snapshot manifest stores file
|
|
221
|
+
type, mode and hash. Full-scope rollback restores the snapshot and removes files
|
|
222
|
+
introduced afterwards. A plan's explicit `snapshot` list deliberately creates a
|
|
223
|
+
narrower rollback scope.
|
|
224
|
+
|
|
225
|
+
## CLI
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
plan-auditor plan verify <dir> [--plan NAME] [--reseal]
|
|
229
|
+
plan-auditor plan inspect <dir> [--plan NAME]
|
|
230
|
+
plan-auditor validate <dir> [--plan NAME]
|
|
231
|
+
plan-auditor run <dir> [step ids ...] [--plan NAME]
|
|
232
|
+
plan-auditor audit <dir> [--plan NAME]
|
|
233
|
+
plan-auditor evidence verify <dir>
|
|
234
|
+
plan-auditor integrity init|status <dir>
|
|
235
|
+
plan-auditor doctor <dir>
|
|
236
|
+
plan-auditor task list <dir>
|
|
237
|
+
plan-auditor agents list|register|heartbeat|claim|release ...
|
|
238
|
+
plan-auditor supervisor start|stop|status ...
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
With no `--plan`, `plan verify` and the integrated final gate operate across all
|
|
242
|
+
active default/named plans.
|
|
243
|
+
|
|
244
|
+
`doctor` exits nonzero when an active workspace assessment is FAIL/UNKNOWN; JSON
|
|
245
|
+
consumers no longer need to detect a hidden failed assessment behind exit code 0.
|
|
246
|
+
|
|
247
|
+
## Hooks
|
|
248
|
+
|
|
249
|
+
`hooks/gate_hook.py` is the platform-neutral authoritative gate. It uses the same
|
|
250
|
+
aggregate supervisor assessment as the CLI.
|
|
251
|
+
|
|
252
|
+
`scripts/stop_gate.py` is only a compatibility adapter for hosts whose Stop hook
|
|
253
|
+
expects exit code `2`; it delegates to the same integrated gate and no longer
|
|
254
|
+
implements status-only verification.
|
|
255
|
+
|
|
256
|
+
See `docs/integrations.md`.
|
|
257
|
+
|
|
258
|
+
## Cross-platform packaging gate
|
|
259
|
+
|
|
260
|
+
GitHub Actions builds a real wheel independently on:
|
|
261
|
+
|
|
262
|
+
- Ubuntu,
|
|
263
|
+
- Windows,
|
|
264
|
+
- macOS.
|
|
265
|
+
|
|
266
|
+
Each job installs the wheel into a clean virtual environment outside the source
|
|
267
|
+
checkout and exercises the installed console script through:
|
|
268
|
+
|
|
269
|
+
- multi-plan discovery,
|
|
270
|
+
- explicit DAG/output contracts,
|
|
271
|
+
- requirement coverage,
|
|
272
|
+
- full-contract sealing,
|
|
273
|
+
- external-key HMAC initialization,
|
|
274
|
+
- integrated audit,
|
|
275
|
+
- doctor PASS,
|
|
276
|
+
- evidence/integrity verification.
|
|
277
|
+
|
|
278
|
+
Release publishing is additionally gated on the same three-platform wheel smoke,
|
|
279
|
+
so PyPI publishing cannot race ahead of platform packaging validation.
|
|
280
|
+
|
|
281
|
+
## Architecture
|
|
282
|
+
|
|
283
|
+
The supervisor combines deterministic layers for requirements, workspace state,
|
|
284
|
+
policy evaluation, plan/DAG validation, lifecycle, sealing, watchdog observation,
|
|
285
|
+
evidence integrity, completion gating, and multi-agent coordination. Optional
|
|
286
|
+
semantic/adversarial review may propose stronger deterministic checks but cannot
|
|
287
|
+
create PASS.
|
|
288
|
+
|
|
289
|
+
See:
|
|
290
|
+
|
|
291
|
+
- `docs/architecture.md`
|
|
292
|
+
- `docs/dependency-graph.md`
|
|
293
|
+
- `docs/threat-model.md`
|
|
294
|
+
- `references/plan-format.md`
|
|
295
|
+
|
|
296
|
+
## Trust boundary
|
|
297
|
+
|
|
298
|
+
Plan Auditor verifies completion; it is not an OS sandbox. External-key HMAC
|
|
299
|
+
protects against workspace-only rewriting while the untrusted process cannot read
|
|
300
|
+
the key. A deliberately malicious same-user process that can obtain the key is
|
|
301
|
+
outside that guarantee. See the threat model for exact boundaries.
|
|
302
|
+
|
|
303
|
+
## Version
|
|
304
|
+
|
|
305
|
+
Current development version: **2.1.0**.
|
|
306
|
+
|
|
307
|
+
## License
|
|
308
|
+
|
|
309
|
+
MIT
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# plan-auditor
|
|
2
|
+
|
|
3
|
+
[](https://github.com/Furox-Art/plan-auditor/actions/workflows/plan-audit.yml)
|
|
4
|
+
|
|
5
|
+
**Independent deterministic verification for AI coding-agent plans.**
|
|
6
|
+
|
|
7
|
+
`plan-auditor` is designed to answer a narrow question reliably:
|
|
8
|
+
|
|
9
|
+
> Did the AI actually complete the user's requirements and its approved plan, or
|
|
10
|
+
> did it only say that it did?
|
|
11
|
+
|
|
12
|
+
The main agent's narration and persisted `status=verified` labels are not enough.
|
|
13
|
+
PASS requires reproducible behavioral checks, explicit requirement coverage, an
|
|
14
|
+
intact sealed verification contract, fresh audit evidence, and a valid aggregate
|
|
15
|
+
completion gate across **every active plan**.
|
|
16
|
+
|
|
17
|
+
## Core completion model
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
User requirements
|
|
21
|
+
│
|
|
22
|
+
▼
|
|
23
|
+
Explicit requirement IDs ──► plan steps (`covers`)
|
|
24
|
+
│ │
|
|
25
|
+
│ ├─ depends_on
|
|
26
|
+
│ ├─ outputs
|
|
27
|
+
│ └─ requires_outputs
|
|
28
|
+
│
|
|
29
|
+
▼
|
|
30
|
+
Format-v3 full-contract seal
|
|
31
|
+
│
|
|
32
|
+
▼
|
|
33
|
+
Deterministic execution / tests
|
|
34
|
+
│
|
|
35
|
+
▼
|
|
36
|
+
Hash-chained evidence + fresh workspace/plan fingerprint
|
|
37
|
+
│
|
|
38
|
+
▼
|
|
39
|
+
Aggregate supervisor gate
|
|
40
|
+
│
|
|
41
|
+
├─ default plan PASS
|
|
42
|
+
├─ named plan A PASS
|
|
43
|
+
├─ named plan B PASS
|
|
44
|
+
└─ policies / tools / registry / integrity PASS
|
|
45
|
+
│
|
|
46
|
+
▼
|
|
47
|
+
PASS / FAIL / UNKNOWN
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## What a PASS means
|
|
51
|
+
|
|
52
|
+
In Supervisor Mode, PASS requires all active plans to satisfy all of the
|
|
53
|
+
following:
|
|
54
|
+
|
|
55
|
+
- valid plan schema,
|
|
56
|
+
- explicit non-empty `requirements`,
|
|
57
|
+
- every `must`/`should` requirement covered by at least one step,
|
|
58
|
+
- at least one behavioral check (`run`, `exec`, `pytest`) per step,
|
|
59
|
+
- valid dependency DAG,
|
|
60
|
+
- concrete output contract for every explicit dependency edge,
|
|
61
|
+
- intact format-v3 seal,
|
|
62
|
+
- unchanged sealed supervisor profile/mode/tier/policy fingerprint,
|
|
63
|
+
- all steps verified in a fresh full audit,
|
|
64
|
+
- current plan contract matches the audited plan fingerprint,
|
|
65
|
+
- current workspace content/type/mode matches the audited workspace fingerprint,
|
|
66
|
+
- active and archived evidence chains valid,
|
|
67
|
+
- agent registry valid,
|
|
68
|
+
- required tools present,
|
|
69
|
+
- no blocking policy result.
|
|
70
|
+
|
|
71
|
+
If any active named plan is unfinished, the whole workspace is non-PASS. A
|
|
72
|
+
passing `plan.json` cannot hide `.plan-auditor/plans/backend.json`.
|
|
73
|
+
|
|
74
|
+
## Deterministic checks
|
|
75
|
+
|
|
76
|
+
Checks run as real subprocesses/filesystem assertions. Structured `argv` is
|
|
77
|
+
preferred:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"type": "run",
|
|
82
|
+
"argv": ["python", "-m", "pytest", "tests/", "-q"],
|
|
83
|
+
"expect_exit": 0
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Shell interpretation is disabled by default. Legacy `cmd` strings are parsed into
|
|
88
|
+
an argument vector. Shell behavior requires explicit `"shell": true` and cannot
|
|
89
|
+
be combined with `argv`.
|
|
90
|
+
|
|
91
|
+
Verifier output is bounded to avoid unbounded-memory capture.
|
|
92
|
+
|
|
93
|
+
## Requirements, dependencies, and outputs
|
|
94
|
+
|
|
95
|
+
Example plan fragment:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"task": "build and consume a verified model artifact",
|
|
100
|
+
"created": "2026-09-05T00:00:00Z",
|
|
101
|
+
"requirements": [
|
|
102
|
+
{"id": "REQ-001", "description": "produce the model artifact", "priority": "must"},
|
|
103
|
+
{"id": "REQ-002", "description": "consume the verified artifact", "priority": "must"}
|
|
104
|
+
],
|
|
105
|
+
"required_tools": ["python"],
|
|
106
|
+
"steps": [
|
|
107
|
+
{
|
|
108
|
+
"id": 1,
|
|
109
|
+
"title": "produce artifact",
|
|
110
|
+
"depends_on": [],
|
|
111
|
+
"covers": ["REQ-001"],
|
|
112
|
+
"verify": [{"type": "run", "argv": ["python", "tests/build_artifact.py"]}],
|
|
113
|
+
"outputs": [
|
|
114
|
+
{
|
|
115
|
+
"name": "artifact",
|
|
116
|
+
"verify": [{"type": "file_exists", "path": "results/model.json"}]
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"id": 2,
|
|
122
|
+
"title": "consume artifact",
|
|
123
|
+
"depends_on": [1],
|
|
124
|
+
"requires_outputs": [{"step": 1, "name": "artifact"}],
|
|
125
|
+
"covers": ["REQ-002"],
|
|
126
|
+
"verify": [{"type": "run", "argv": ["python", "tests/use_artifact.py"]}]
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
A downstream step cannot pass until the prerequisite passed and the upstream
|
|
133
|
+
output contract is independently rechecked.
|
|
134
|
+
|
|
135
|
+
## Full-contract sealing
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
plan-auditor plan verify .
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The v3 seal binds:
|
|
142
|
+
|
|
143
|
+
- task and requirements,
|
|
144
|
+
- required tools,
|
|
145
|
+
- step identity/order/title,
|
|
146
|
+
- `covers`,
|
|
147
|
+
- dependencies and required outputs,
|
|
148
|
+
- outputs and their checks,
|
|
149
|
+
- step verification checks,
|
|
150
|
+
- supervisor `profile`, `mode`, `tier`,
|
|
151
|
+
- configured-policy fingerprint.
|
|
152
|
+
|
|
153
|
+
Existing criteria may be strengthened, but removing/changing sealed criteria or
|
|
154
|
+
downgrading the sealed environment blocks completion.
|
|
155
|
+
|
|
156
|
+
## Evidence integrity
|
|
157
|
+
|
|
158
|
+
Evidence records are append-only JSONL records with SHA-256 `prev + hash`
|
|
159
|
+
continuity. The chain spans log rotations; the active log links the latest archive
|
|
160
|
+
tail. Concurrent evidence append/rotation is serialized with an exclusive lock.
|
|
161
|
+
Failed-attempt limits are counted across archived and active evidence.
|
|
162
|
+
|
|
163
|
+
Optional external-key HMAC adds authentication and signed tail checkpoints for:
|
|
164
|
+
|
|
165
|
+
- active/archive evidence records,
|
|
166
|
+
- evidence head,
|
|
167
|
+
- agent registry records/head,
|
|
168
|
+
- plan seals,
|
|
169
|
+
- integrity marker.
|
|
170
|
+
|
|
171
|
+
Initialize after sealing:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# set PLAN_AUDITOR_HMAC_KEY or PLAN_AUDITOR_HMAC_KEY_FILE first
|
|
175
|
+
plan-auditor plan verify .
|
|
176
|
+
plan-auditor integrity init .
|
|
177
|
+
plan-auditor audit .
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
A key file must resolve outside the workspace.
|
|
181
|
+
|
|
182
|
+
## Multi-agent state
|
|
183
|
+
|
|
184
|
+
The persisted agent registry uses `format_version + seq + prev + hash` and an
|
|
185
|
+
anti-truncation head checkpoint. Agent IDs are safe basenames and ownership paths
|
|
186
|
+
are canonical workspace-relative paths, so spellings such as
|
|
187
|
+
`src/../src/shared.py` and `./src/shared.py` cannot evade conflict detection.
|
|
188
|
+
|
|
189
|
+
Modes:
|
|
190
|
+
|
|
191
|
+
- `serial`
|
|
192
|
+
- `parallel-warn`
|
|
193
|
+
- `parallel-strict`
|
|
194
|
+
|
|
195
|
+
## Snapshot / rollback
|
|
196
|
+
|
|
197
|
+
Default snapshots capture the full workspace product state while excluding
|
|
198
|
+
`.git`, `.plan-auditor`, and cache metadata. The snapshot manifest stores file
|
|
199
|
+
type, mode and hash. Full-scope rollback restores the snapshot and removes files
|
|
200
|
+
introduced afterwards. A plan's explicit `snapshot` list deliberately creates a
|
|
201
|
+
narrower rollback scope.
|
|
202
|
+
|
|
203
|
+
## CLI
|
|
204
|
+
|
|
205
|
+
```text
|
|
206
|
+
plan-auditor plan verify <dir> [--plan NAME] [--reseal]
|
|
207
|
+
plan-auditor plan inspect <dir> [--plan NAME]
|
|
208
|
+
plan-auditor validate <dir> [--plan NAME]
|
|
209
|
+
plan-auditor run <dir> [step ids ...] [--plan NAME]
|
|
210
|
+
plan-auditor audit <dir> [--plan NAME]
|
|
211
|
+
plan-auditor evidence verify <dir>
|
|
212
|
+
plan-auditor integrity init|status <dir>
|
|
213
|
+
plan-auditor doctor <dir>
|
|
214
|
+
plan-auditor task list <dir>
|
|
215
|
+
plan-auditor agents list|register|heartbeat|claim|release ...
|
|
216
|
+
plan-auditor supervisor start|stop|status ...
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
With no `--plan`, `plan verify` and the integrated final gate operate across all
|
|
220
|
+
active default/named plans.
|
|
221
|
+
|
|
222
|
+
`doctor` exits nonzero when an active workspace assessment is FAIL/UNKNOWN; JSON
|
|
223
|
+
consumers no longer need to detect a hidden failed assessment behind exit code 0.
|
|
224
|
+
|
|
225
|
+
## Hooks
|
|
226
|
+
|
|
227
|
+
`hooks/gate_hook.py` is the platform-neutral authoritative gate. It uses the same
|
|
228
|
+
aggregate supervisor assessment as the CLI.
|
|
229
|
+
|
|
230
|
+
`scripts/stop_gate.py` is only a compatibility adapter for hosts whose Stop hook
|
|
231
|
+
expects exit code `2`; it delegates to the same integrated gate and no longer
|
|
232
|
+
implements status-only verification.
|
|
233
|
+
|
|
234
|
+
See `docs/integrations.md`.
|
|
235
|
+
|
|
236
|
+
## Cross-platform packaging gate
|
|
237
|
+
|
|
238
|
+
GitHub Actions builds a real wheel independently on:
|
|
239
|
+
|
|
240
|
+
- Ubuntu,
|
|
241
|
+
- Windows,
|
|
242
|
+
- macOS.
|
|
243
|
+
|
|
244
|
+
Each job installs the wheel into a clean virtual environment outside the source
|
|
245
|
+
checkout and exercises the installed console script through:
|
|
246
|
+
|
|
247
|
+
- multi-plan discovery,
|
|
248
|
+
- explicit DAG/output contracts,
|
|
249
|
+
- requirement coverage,
|
|
250
|
+
- full-contract sealing,
|
|
251
|
+
- external-key HMAC initialization,
|
|
252
|
+
- integrated audit,
|
|
253
|
+
- doctor PASS,
|
|
254
|
+
- evidence/integrity verification.
|
|
255
|
+
|
|
256
|
+
Release publishing is additionally gated on the same three-platform wheel smoke,
|
|
257
|
+
so PyPI publishing cannot race ahead of platform packaging validation.
|
|
258
|
+
|
|
259
|
+
## Architecture
|
|
260
|
+
|
|
261
|
+
The supervisor combines deterministic layers for requirements, workspace state,
|
|
262
|
+
policy evaluation, plan/DAG validation, lifecycle, sealing, watchdog observation,
|
|
263
|
+
evidence integrity, completion gating, and multi-agent coordination. Optional
|
|
264
|
+
semantic/adversarial review may propose stronger deterministic checks but cannot
|
|
265
|
+
create PASS.
|
|
266
|
+
|
|
267
|
+
See:
|
|
268
|
+
|
|
269
|
+
- `docs/architecture.md`
|
|
270
|
+
- `docs/dependency-graph.md`
|
|
271
|
+
- `docs/threat-model.md`
|
|
272
|
+
- `references/plan-format.md`
|
|
273
|
+
|
|
274
|
+
## Trust boundary
|
|
275
|
+
|
|
276
|
+
Plan Auditor verifies completion; it is not an OS sandbox. External-key HMAC
|
|
277
|
+
protects against workspace-only rewriting while the untrusted process cannot read
|
|
278
|
+
the key. A deliberately malicious same-user process that can obtain the key is
|
|
279
|
+
outside that guarantee. See the threat model for exact boundaries.
|
|
280
|
+
|
|
281
|
+
## Version
|
|
282
|
+
|
|
283
|
+
Current development version: **2.1.0**.
|
|
284
|
+
|
|
285
|
+
## License
|
|
286
|
+
|
|
287
|
+
MIT
|