shipwithjev

Catalog / Tools & apps

0327GitHub

Canny

Evidence ledger that challenges unsupported "done" claims from coding agents.

qkal/CannyREADME ↗
# Canny

A warden for AI coding agents. It hooks into Claude Code and Codex CLI, keeps a ledger of what the agent actually did, and will not let it finish on a claim.

[](https://github.com/qkal/canny/actions/workflows/ci.yml)
[](LICENSE)
[](#install-by-pasting-a-prompt)
[](#claude-code-and-codex-differ-in-four-places)
[](package.json)
[](https://typesafe.ai)
[](https://github.com/qkal/canny/commits/main)

> Done. Skipped tests — one-liner, no branch to break.

That is Claude Code, verbatim, during this project's first live run. It had been asked to add a function, it wrote the file with a shell heredoc, ran nothing, and finished. No error. No warning. Nothing in `CLAUDE.md` could have stopped it, because a rules file only asks the model to remember, and nothing checks that it did.

Canny is the hook that noticed. On the next run of the same prompt, the agent's "done" was refused with this message:

> Canny: math.js changed, but no check has passed since the last edit. The last command was `cat > math.js <<'EOF' …` (exit 0). Run the project's checks and fix what fails before finishing. A test, build, lint, or type-check command counts. If no check applies to this change, say so explicitly and stop again.

Claude ran `npm test`. It passed. The next "done" went through. The whole exchange is in the [session ledger](#what-a-guarded-session-looks-like) below.

## The one rule

**Facts go to code. Judgments go to Jev. Only facts can block.**

A fact is something the ledger can prove: a file changed, a command ran, it exited 1, the same command failed with the same output three times, the text about to be written contains an AWS key. Code decides those, offline, with no API key.

A judgment is something code cannot decide: does this message claim the work is done, does this d

Also filed under Tools & apps

  1. 0573

    Support chat: agent offered a human escalation path

    A frustrated customer hits a bot loop twice; the judge checks whether a human handoff was offered.

    everyai-com · Tools & apps

  2. 0572

    Subscription cancel: effective date is explicit

    An agent cancels a subscription; the judge checks the exact date the cancellation takes effect.

    everyai-com · Tools & apps

  3. 0571

    Sales quote: numbers match the official price list

    An agent quotes $29/seat against a price list; the judge checks the quote matches exactly.

    everyai-com · Tools & apps

  4. 0570

    Refund chat: agent stated the amount before issuing it

    A support agent issues a $42.50 refund; the judge checks the exact amount was stated before the refund was confirmed.

    everyai-com · Tools & apps