ccdwyer/proof-decay

후속 편집 후에도 유효한 test, typecheck, lint, build 결과를 추적하고 오래된 검사를 통과했다고 주장하는 commit message를 막는 Claude Code mod입니다.
ccdwyer/proof-decay

Proof Decay는 agent가 실행한 모든 test, typecheck, lint, build를 기록한 뒤 이후 편집이 해당 범위를 건드리는 즉시 결과를 stale로 표시합니다. 프롬프트 위에 proof board를 표시하고 매 턴이 끝날 때와 commit 전에 working tree의 지문을 만들며, Oathkeeper를 사용해 실제로 stale이거나 실패했거나 없는 검사를 통과했다고 commit message가 주장하는 commit을 거부합니다. 인식하는 명령에는 npm/yarn/pnpm/bun test/lint/typecheck/build, jest, vitest, mocha, playwright, pytest, tsc, vue-tsc, mypy, pyright, eslint, ruff, biome, go test/vet/build, cargo test/check/clippy/build, swift test/build, xcodebuild test/build, gradle test/build, make test/lint가 포함됩니다. /plugin marketplace add ccdwyer/claude-mods와 /plugin install proof-decay@ccdwyer-mods로 설치합니다. 완전히 로컬에서 실행되며 네트워크로 아무것도 보내지 않고 telemetry도 수집하지 않습니다.
먼저 작성자의 README에서 marketplace와 플러그인 이름을 확인하세요. 저장소 구조에 따라 명령어가 달라질 수 있습니다.
claude plugin marketplace add ccdwyer/proof-decay claude plugin install proof-decay

Tests and tsc pass, so the board reads ✓ tests fresh · ✓ types fresh. One edit later both go ⚠ stale (1 edit), and a commit claiming "All tests pass" is refused by Oathkeeper. MP4
| Fresh | Stale | Refused |
|---|---|---|
|
|
|
|
A Claude Code mod that tracks which verification results are still true.
"Tests passed" stops meaning anything once the code changes. Proof Decay records every test, typecheck, lint and build run the agent makes, then marks the result stale as soon as a later edit touches what it covered.
✓ tests fresh · ⚠ types stale (3 edits) · ✗ lint failed. It shows the repo you're in.&& chain that succeeded, or the last command of a newline/; script is recorded, because those are the only cases where the one exit status the call has can be pinned to the check. npm test; true, npm test || …, pipes, subshells and $(…) never produce a pass, and anything inside quotes is never treated as a command. A check whose outcome can't be read (npm test || true, $(npm test), a failed chain) casts doubt on the earlier pass instead. Interrupted or backgrounded runs are skipped.npm test, pytest, go test ./..., tsc -p tsconfig.json) counts as a project result. Some runs are scoped or filtered instead. That includes runs from below the repo root (or from a nested package.json), runs that name files or a directory, script variants (test:unit), workspace or package flags, plain cargo test at a workspace root, and name filters (-t, -kfoo, --lib, -only-testing). They still show on the board, but they never back a claim. A failed scoped run also casts doubt on the project pass.-m, heredocs and -F files, and git -C is supported. If it claims checks passed ("all tests pass", "typecheck is clean", "CI is green"), but the matching whole-project run in that repo is stale, failed or missing, the commit is refused. Hedged lines ("should pass", "tests pass when…", "not all tests pass") are ignored. A claimed commit has to run as its own command, not chained after other commands. git add before it in the same call is fine. It's also refused if it would commit less than what was tested: unstaged changes, untracked files the tests saw (even with -a), or pathspec, --only and --patch commits. bash -c '…' wrappers are looked inside. After popd, cd ~ or cd -, the target repo can't be pinned, so claims are refused. If a message can't be read in advance (a $VAR, an editor, --amend --no-edit when history can't be read), the commit only goes through while every check in the repo is fresh. Every other commit goes through, with a note to the model listing what wasn't re-verified./proofs lists every recorded run with its age, scope, repo and any reason for doubt. /proofs clear forgets them all. Results last for the whole session, across prompts.Recognised commands include npm/yarn/pnpm/bun test/lint/typecheck/build scripts, jest, vitest, mocha, playwright test, pytest, tsc, vue-tsc, mypy, pyright, eslint, ruff, biome, go test/vet/build, cargo test/check/clippy/build, swift test/build, xcodebuild test/build, gradle test/build, and make test/make lint.
/plugin marketplace add ccdwyer/claude-mods
/plugin install proof-decay@ccdwyer-mods
/reload-plugins
claude plugin validate .
claude plugin test .
Events this mod hooks, as claude plugin validate reads the module:
session.startcommand.run{command=proofs}tool.call{tool=Bash}tool.callturn.completeui.render{component=AbovePrompt}Engine calls it makes: $.clock.now, $.command.register, $.fs.read (via demote, judgeCommit), $.fs.stat (via exists), $.process.run (via fingerprint, judgeCommit, rootOf), $.session.cwd, $.state.get, $.state.set, $.ui.resolve.
A tool.call hook sits in the middle of every tool call: it can see the call, refuse it, or add context to its result. This mod uses that only for the behaviour described above.
It runs entirely on your machine. It sends nothing over the network. It runs git locally to fingerprint the working tree.
The mod collects no analytics or telemetry, and its author receives no data from it.
Full policy: PRIVACY.md.
MIT