cursorrules — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited cursorrules (Rules) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Your AI agent just said "Done ✅" — but did it verify? This one-file gate forces it to record fresh evidence before it can declare success. Works with Claude Code, Cursor, and Codex. Copy. Paste. Ship.
agent: All tests pass — task complete! ✅
stop-gate: BLOCKED — no NEW passing check since your last completion — re-verify this change
agent: $ bash done-gate.sh capture --label test -- npm test
✗ 1 test failed (exit=1)
stop-gate: BLOCKED — your most recent check FAILED (exit=1) — fix it, don't ship itThat's the whole point: "it works" stops being a confidence claim and becomes a receipt.
▶ Watch the terminal cast: docs/demo.cast — play locally with asciinema play docs/demo.cast.
AI coding agents routinely announce a task is "done" without running anything to back it up. It's the loudest complaint in the agent ecosystem (claude-code#42796), and the fix is simple: don't let the agent say done — make it show done.
agent-done-or-not records every check as a tamper-evident receipt (command + exit code + SHA-256 of the output) and blocks the agent from finishing until the most recent check is a fresh, passing one. Because the capture step exits with the command's own code, a failing check can't be dressed up as success.
a rule in CLAUDE.md | agent-done-or-not | |
|---|---|---|
| Agent can ignore it | yes — it's a suggestion | no — the Stop hook blocks the turn |
| Proof it actually ran | none | hashed receipt (proof.json) |
| Failing check caught | only if the agent admits it | always — exit code is recorded |
| Works in CI / pre-commit | no | yes — done-gate.sh assert |
| Cross-tool | per-tool prose | one engine for Claude, Cursor, Codex |
| Dependencies | — | none (bash + git + sha) |
From the repo you want to protect:
npx agent-done-or-not init --yesPrefer to inspect first? Use npx agent-done-or-not init --dry-run, or use the manual two-file install in [examples/install.md](examples/install.md).
Then wire the rule + hook for your tool — see [examples/install.md](examples/install.md).
CLAUDE.md + the Stop hook = hard enforcement..cursorrules.AGENTS.md.npx skills add mohamedzhioua/agent-done-or-notInstalls the proof-of-done rule as a skill for Claude Code / Codex / other agents. A skill-only install gives the agent instructions, not repo-root gate scripts; use npx agent-done-or-not capture ... from the skill, or run agent-done-or-not init / the installer first to add local done-gate.* scripts and hook config.
Run the gate without cloning — handy in a CI step, an npm script, or a skill-only install:
npx agent-done-or-not capture --label test -- npm test
npx agent-done-or-not assert --label test --ttl 3600The npm wrapper uses the bundled Bash engine when Bash is available, and falls back to the bundled PowerShell engine on Windows.
Fast local smoke check for the npm wrapper:
npm run smokeInstall a global agent-done-or-not launcher:
# macOS / Linux
brew install mohamedzhioua/tap/agent-done-or-not# Windows (native PowerShell launcher)
scoop bucket add agent-done-or-not https://github.com/mohamedzhioua/scoop-bucket
scoop install agent-done-or-notThe pinned formula and manifest live in packaging/; see packaging/README.md for publishing them to a tap/bucket.
done-gate.ps1 is a native port of the engine with identical behavior and an identical receipt format. It runs on Windows PowerShell 5.1 and PowerShell 7+ with built-ins only — no bash required:
pwsh done-gate.ps1 capture --label test -- your-test-command
pwsh done-gate.ps1 assert --label test --ttl 3600Receipts written by done-gate.ps1 and done-gate.sh are interchangeable.
Use the composite action to gate a workflow job on receipts created earlier in the same checkout:
- uses: actions/checkout@v4
- uses: mohamedzhioua/agent-done-or-not@v0
with:
mode: assert
labels: "test build"
ttl: "3600"
pr-comment: "true" # optional: upsert a sticky proof comment on the PRRun actions/checkout first, then produce receipts earlier in the job with bash done-gate.sh capture before the action asserts them. With pr-comment: "true" on a pull request, the action upserts a single sticky proof comment (✅/❌ status + the gate output); it never changes the job's pass/fail — assert still decides that.
Install the thin Claude Code plugin wrapper:
claude plugin marketplace add mohamedzhioua/agent-done-or-not
claude plugin install agent-done-or-notThe plugin keeps the bash core canonical at the repo root and only wires stop-gate.sh as Claude Code's Stop hook for hard enforcement. You still drop the CLAUDE.md rule into the protected repo for the agent-facing instruction.
# Run any check through the gate — it exits with the command's own code:
bash done-gate.sh capture --label test -- npm test
# Inspect the receipts:
bash done-gate.sh show
# Render a compact proof summary:
npx agent-done-or-not report --format markdown{"label":"test","command":"npm test","exit_code":0,"sha256":"9f2c…","log":".agent-proof/…/test.log","at":"2026-06-21T19:44:00Z","epoch":1781034240,"session":""}See examples/proof.jsonl for a full ledger sample.
Add this to your .pre-commit-config.yaml:
repos:
- repo: https://github.com/mohamedzhioua/agent-done-or-not
rev: v0.8.0
hooks:
- id: agent-done-assertThis runs done-gate.sh assert before every commit and blocks unless a fresh passing proof-of-done receipt exists in .agent-proof/. Pass extra options via args:, for example:
- id: agent-done-assert
args: [--label, test, --ttl, "3600"]assert checks the ledger without running anything — perfect for a CI step or a pre-commit hook that refuses to proceed unless the right checks passed:
# Require BOTH a passing test and build receipt, no older than 1h,
# and make sure the "test" receipt really came from your test runner:
bash done-gate.sh assert --label test --label build \
--allow-command-regex '(npm|pnpm) test' --ttl 3600
# Machine-readable for Actions / tooling:
bash done-gate.sh assert --json --label test
# {"ok":true,"run":"…","ttl":3600,"checks":[{"label":"test","ok":true,…}]}Every command supports --json for stable, dependency-free output.
A rule in CLAUDE.md makes the agent run something. A policy makes it run the right things. Drop an agent-done.json at your repo root:
{
"required": [
{ "label": "test", "command_regex": "(npm|pnpm|yarn) (run )?test|pytest" },
{ "label": "build", "command_regex": "(npm|pnpm) run build" }
],
"ttl": 3600
}Now assert (with no --label) requires a fresh, passing receipt for every listed label and checks that each was produced by a command matching its command_regex — so true or echo ok can't satisfy a test requirement:
bash done-gate.sh assert # reads agent-done.json automatically
bash done-gate.sh assert --json # adds a "policy" fieldResolution order is explicit `--label` → policy file → most-recent receipt; pass --no-policy to force the legacy path, or --policy <file> to point elsewhere. Receipts captured in separate runs still count (policy mode searches all runs per label). Scaffold one from your detected stack with npx agent-done-or-not init --policy. The format is documented in policy.schema.json.
Wrong-check warning. Labels carry a strength taxonomy (strong: test, build, typecheck, e2e, smoke…; weak: lint, format, manual…). If the only passing evidence is a weak check, assert and report print an advisory latest proof is lint-only — this may not verify the requested behavior. It's a nudge, never a blocker — the exit code is unchanged.
Turn a ledger into something pasteable. report leads with a human card; the pr format is a sticky, marker-wrapped comment for pull requests:
npx agent-done-or-not report # card + table
npx agent-done-or-not report --format pr # paste into a PR / issue### ✅ Proof of Done
| | |
|---|---|
| **Status** | PASS |
| **Latest** | `npm test` · exit 0 · 2m ago |
**Checks**
- ✅ `test` — `npm test` — exit `0` — 2m ago — `sha256:9f2c…`In CI, the GitHub Action can post this as a sticky PR comment — set pr-comment: "true".
receipt to .agent-proof/<run>/ledger.jsonl. It exits with the command's own exit code.
turn unless the most recent receipt is:
mtime, which touch could forge); older than AGENT_DONE_TTL (default 1h) is rejected, so it never honors yesterday's ledger, and
own proof).
It fails closed. Once a stop is being gated, any missing, empty, unparseable, or stale proof state blocks. The only ways past are a verified passing receipt, the escape hatch, or an anti-infinite-loop safety valve (it gives up and warns loudly after AGENT_DONE_MAX_RETRIES consecutive blocks so the agent can never get permanently stuck).
Dependency-free: portable bash + git + one of sha256sum/shasum/python. No network, no LLM, no config file. The receipt format is documented in proof.schema.json. Hardened with an independent cross-model (Codex) security review — see CONTRIBUTING.md.
agent-done-or-not is built to resist an agent that wants to look done. It is a forcing function, not a sandbox; here's the honest boundary.
It stops these:
capture records and exitswith the real non-zero code).
epoch inside the receipt, so touch won't refresh it).
closed**).
AGENT_DONE_MAX_RETRIES).agent-done.jsonpolicy (per-label command_regex) or assert --allow-command-regex. A policy that is present but unparseable fails closed — it never silently degrades to the most-recent receipt.
It does NOT claim to stop these (out of scope by design):
pair it with --allow-command-regex and real tests.
.agent-proof/ it can forge anything — treat the ledger as you would any workspace file. (verify --sha lets a second party confirm a specific hash.)
advisory, but every receipt is still recorded for you and CI to audit.
Report a bypass — see SECURITY.md. It's the most valuable issue you can file.
export AGENT_DONE_OFF=1 # disable the gateDoes it need Node / Python / jq? No. Just bash, git, and one of sha256sum / shasum / python for hashing.
Windows? Fully supported natively. done-gate.ps1 and stop-gate.ps1 are native PowerShell ports (PS 5.1 + PS 7+, no bash required). Receipts are interchangeable between the bash and PowerShell engines.
Won't it get my agent stuck? No — after AGENT_DONE_MAX_RETRIES consecutive blocks it fails open with a loud warning, and AGENT_DONE_OFF=1 disables it.
Is the receipt private? Yes — .agent-proof/ is local and gitignored; it's never committed.
What's the difference between `capture` and `assert`? capture runs a check and records proof (use it in the agent loop). assert checks the ledger without running anything (use it in CI / pre-commit).
Extracted and sharpened from the evidence/verify-gate layer of [zhioua-os](https://github.com/zhioua-os), an AI engineering OS for coding agents ("replace trust with evidence"). MIT licensed — fork it, ship it.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.