The checklist that could not be checked
A numbered prose list has no state. A phase shipped missing the deliverable its own item 10 named.
Plan-drift guardA field report from six months of building
How we shipped a production-grade financial platform with Claude Code, and the guardrails that made it safe to trust.
Measured against the private repository on 22 October 2026. The product is deployed and pre-launch, with no paying clients yet. 162 database migrations, 30 guard tests, 30 decision records, 22 project skills.
The product is a B2B SaaS that handles invoices, contracts and compliance for its customers. Money is computed with exact decimals, every tenant's data is isolated by the database itself, and every financial change writes an audit row. That is a lot of rules for a small team to hold in their heads, and an AI agent holds none of them between sessions.
So we stopped relying on anyone remembering. Claude Code wrote most of the keystrokes. We wrote the rules it works under, the scripts that enforce them, and the reviews that check its work. This page is about that layer.
The one idea
Every mistake in the project goes through the same four steps, and the fourth is what makes the rest stick.
The method
The reason is written next to every rule in the project constitution, so nobody tidies a rule away without knowing why it exists.
| # | Rule | The incident behind it |
|---|---|---|
| 01 | A written constitution that every session loads | Making the same correction in session after session |
| 02 | Classify every task first: Bug, Change Request or Plan | "Simple" edits to auth and schema files that were not simple |
| 03 | Plans touching money, dates or concurrency carry a Boundary and Invariant Table | A month-end date overflow shipped even though the plan named the risk, in a sentence |
| 04 | Verification items are checkboxes, and a guard blocks shipping with one unticked | A phase shipped without its approved UI while its own checklist named the miss |
| 05 | Choose the cheapest model that handles what is still unknown | The top model used about half the spend on an eighth of the turns, mostly on work already specified |
| 06 | Two-tier review before every ship, with a fresh-context reviewer for risky diffs | Two internal sweeps missed five bugs one independent reviewer found |
| 07 | One scripted release path, and a hook that blocks the agent from committing | Migrations that reached main and silently never reached production |
| 08 | Six-point vetting of every tool before install, reading the code on disk | Any skill or server that reads the repo can carry the code off the machine |
| 09 | Tracking docs open with a summary table, linted for alignment | Detail-only trackers stop being read, and unread trackers drift |
Incident stories
Picked from 80 logged lessons because none of them is specific to one product or industry. The full write-ups are in the repo.
A numbered prose list has no state. A phase shipped missing the deliverable its own item 10 named.
Plan-drift guardHand-written security migrations never matched the release script's trigger, so production never got them.
Trigger pinned by test51 test files skipped on every run because the env file silently failed to load. The suite still said green.
judgmentAt round numbers, the right formula and the wrong one gave the same answer. Three rows, all read as rigorous.
Wrong implementations kept in the test"Every table with a tenant column" missed tables scoped only through a parent key.
Population defined by foreign keyThe guard for this exact bug class existed. Its skip branch had never been proven against anything.
Exemption proven red71 files drifted back to the old button pattern after a cleanup that shipped no guard.
Guard per pattern, same commitA hardcoded status in an update still type-checked after the rename, and silently matched zero rows.
Literal guardA cascading foreign key removed rows in a table the archive code had never heard of.
Dependents declaredEach read fine alone. The code silently picked one and made the other unreachable.
judgmentA confident accusation built on a clean git status. A second session sharing the folder was the real explanation.
List live sessions first"Two files" changed 176 usages. "Everywhere" reached 14 files. Neither was counted before it was said.
judgmentUse it
Copy the constitution, cut it down to your project, and add guards as your own incidents earn them. Do not install every guard on day one.
New to Claude Code? Start here: six steps from an empty project to rules, a lessons log, a first guard, plans and reviews, in about an hour.
git clone https://github.com/mahi9119/claude-code-playbook.gitcp claude-code-playbook/templates/CLAUDE.md ./CLAUDE.mdcp claude-code-playbook/templates/lessons.md ./docs/lessons.md