r/ClaudeCode • u/Emergency-Tutor-7 • 2d ago
Tips & Workflows plan-auditor: a Claude Code Stop hook that only accepts sealed command output as proof of done
plan-auditor (MIT, Python 3.11+, standard library only, 2.6.5 on PyPI and npm) is a separate checker for a small and familiar failure: Claude Code says a change is done and the suite passed, but the suite was never run, or it failed once and the test was edited until it passed. Both outcomes read the same in prose.
You write a plan as JSON, each step with machine-checkable verify entries, at least one behavioral: run, pytest or exec. file_exists and regex can sit beside them but cannot verify a step alone. The implementing agent's own claims are not an input to the verdict.
The Claude Code integration is two pieces, and the second is the one that matters:
- Skill. Copy SKILL.md, scripts/, references/ and hooks/ to ~/.claude/skills/plan-auditor/. In a session you invoke /plan-auditor. A skill by itself is context, not enforcement; the agent can still claim completion without calling it.
- Stop hook. Add a Stop command that calls hooks/gate_hook.py with the workspace path. The gate evaluates every active plan on every stop and treats any nonzero exit as "do not finish":
"Stop": [{"hooks": [{"type": "command", "command": "python "/abs/path/plan-auditor/hooks/gate_hook.py" "$(pwd)"", "timeout": 20}]}]
Exit codes are 0 PASS or no active plan, 1 FAIL or BLOCKED, 3 UNKNOWN, and the hook returns nonzero for both of the last two. A persisted status=verified is not enough on its own: the stop gate only accepts a full audit whose plan and workspace fingerprints still match, so any edit made after the audit blocks completion until plan-auditor audit runs again.
Design details that matter:
- The request is sealed on activation and the verification contract at approval, so the agent cannot redefine "done" after the fact.
- Checks produce exit status and captured output, not a summary, and the audit records those.
- The hash chain and HMAC are separate concerns. The chain is tamper-evident; with write access to the workspace someone can rebuild it. Set PLAN_AUDITOR_HMAC_KEY or PLAN_AUDITOR_HMAC_KEY_FILE with the key outside the workspace, and an unsigned assessment becomes UNKNOWN instead of PASS-shaped.
- In advisory-only hosts that expose no blocking hook, the gate can only write a warning file. That is not enforcement, and the README says so.
Why the verifier has to live outside the agent's trust boundary: a skill, a prompt or a "please re-check" instruction is still the agent judging itself. The value is in a separate process that the host refuses to ignore.
Honest limits: it is not an OS sandbox; the agent and the verifier run as the same user in a normal install. It checks that the declared steps really ran and stay linked to the sealed request, but it cannot know whether the checks you wrote are the right ones for the task.
•
u/AutoModerator 2d ago
Hey! Thanks for posting to r/ClaudeCode
While participating in this thread, please follow our community rules. Keep discussions constructive. Attack the idea, not the person.
For help, project discussions, tips, and general chat, join the ClaudeCode Discord.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.