AI coding agents say “done” when they’re not — they skip the test, bypass the hook with
–no-verify, delete the failing test, leave the docs
stale. cogpin turns each of those corner-cuts into a gate the agent can’t talk its
way around.
agent sessioncogpin armed
git commit --no-verify -m "ship it"
⛔ cogpin · blocked--no-verify denied before it ran
tests/test_auth.py
⛔ cogpin · blockedforbid_delete · don’t delete the failing test
git commit -m wip
⛔ cogpin · blockedbranch-first · you’re on main
✓ fixed properlytests ran · on a branch · committed
git commit --no-verify -m "ship it"
⛔ cogpin · blocked--no-verify denied before it ran
tests/test_auth.py
⛔ cogpin · blockedforbid_delete · don’t delete the failing test
git commit -m wip
⛔ cogpin · blockedbranch-first · you’re on main
✓ fixed properlytests ran · on a branch · committed
Prose asks. cogpin enforces. — over facts the agent can’t fake.
The one rule that makes that possible: only things the agent can’t fake — the diff it’s
committing, the command it’s about to run, the branch, PR/commit metadata — are allowed to
hard-block. Anything that needs judgment can only warn. Said precisely:
severity = “block” REQUIRES kind = “fact”
A fact is exactly that ungameable signal; an LLM-judge or a self-checkbox is judgment,
so it stays advisory — it warns, never blocks.
One stdlib-only cogpin.py, one per-repo cogpin.toml, installed as a Claude Code
plugin. That’s the whole moat: an agent can’t pass a block it didn’t actually satisfy,
because it never authored the evidence the block reads.
What it catches →Every corner-cut mapped to the fact that catches it — including delete-the-test, strip-the-assert, commit-to-main.
Try it live →The real engine, running in your browser. Edit a policy + a diff, watch it block.
Install →One /plugin command for the agent layer; /cogpin-init wires the base-pinned change layer.
Concepts →Fact vs judgment, the two layers, and why base-pinning makes the gate un-loosenable.