Note · what stops a bad change before it ships

The Local Safety Net

Every change reaches the same gate before it merges — whether it started as a customer request on our shared board or someone on the team typing directly into the codebase. Most of that gate is a checklist, run every time. A smaller, sharper part of it isn’t optional: it’s enforced by code, before the edit is even made.

Our build process blueprint covers what happens to a request end to end. This one covers the layer underneath it — the gate every branch clears before it merges to the integration branch, and the handful of rules nobody can get wrong by accident, because the tooling itself refuses the edit.

01

Nothing merges without clearing the checklist

The same checks, every branch, every time — there’s no separate, lighter path for something built by a person instead of built automatically.

Scope check
Every changed file has to map back to what the branch says it’s for. Anything that doesn’t gets split into its own change first — before the rest of the checklist even runs.
Types, lint, unit tests
Including a set of structural tests that check things like authorization coverage and route-permission wiring directly, not just business logic.
Production build
A real build, not a type-check standing in for one — some failures only show up once code is actually bundled for the client and the server separately.
Targeted regression
Automated browser tests scoped to exactly the product areas the diff touches, on top of a fixed baseline that always runs regardless of what changed.
Migration ledger
A database change has to already be applied to a staging database and recorded before the branch merges — never an unapplied file just sitting in version control.
Code review
Depth scales to what the change could actually break, not a fixed pass every time. More on that below.
02

Some of it is enforced, not just written down

A written rule only works if whoever’s making the change remembers to follow it. A short list of ours doesn’t depend on that — the tooling itself refuses to make the edit.

What gets blocked before the edit is even made
blocked a hand-typed query bypassing the generated schema
blocked a lint warning silenced instead of fixed
blocked a database change missing from the migration ledger
blocked a commit to the integration or production branch directly
blocked a push that targets the production branch

One narrower case — a hardcoded reference to a specific AI model version, outside the one sanctioned place that’s allowed to live — gets a warning instead of a hard block, since a pattern match can’t always tell a real violation from a false positive. A person still looks at that one.

That list stays short on purpose. It’s not a stand-in for everything else in Section 01 — it’s the narrow set of rules reliable enough to enforce mechanically. Everything else still depends on actually being run, which is exactly why it’s a required step in the checklist, not a suggestion in a document nobody re-reads.

03

Review scaled to what could actually break

A one-line copy fix and a change to how a session gets authenticated don’t call for the same scrutiny — and pretending they should just makes the expensive version too costly to run consistently, on the change that actually needs it.

Standard depth

  • Most changes: new UI, a new endpoint following an already-reviewed pattern, a test-only diff.
  • Still a full, independent AI review — just not the wider, multi-pass version below.

Extended, multi-pass depth

  • Authentication, session handling, or anything platform-wide.
  • A third-party integration — payments, identity providers, and the like.
  • A database policy change touching an existing table’s rows, or billing internals.

Even the deepest local tier stops short of the much larger, multi-agent review reserved for a release promotion — cost stays matched to actual risk at every step, instead of maxed out by default on changes that never needed it.

04

Every database change ships in two safe steps, not one

Additive first, destructive later — and applying either one is always a person, never a script holding a production credential.

1
Additive first. A change that adds a column or a table ships alongside the code that will use it. Nothing that already exists changes shape yet.
2
Applied to staging. By a person, pasting the exact file a reviewer already saw — never a script run automatically as part of a build.
3
Applied to production the same way. Verbatim, at a scheduled window, by a person. No automated path ever holds a production database credential.
4
Drift check. After every apply, an automated check confirms the repository, staging, and production all agree on what actually ran.
5
Destructive follow-up, later. Dropping the old column or table ships in a separate, later release — once nothing in production still depends on the old shape.
05

Keeping the product’s own AI honest about itself

The same in-app assistant that answers a customer’s “how do I—” question reads from a small set of internal product-description entries. Those go stale exactly the way any documentation does: quietly, and usually not until a customer gets the wrong answer.

internal product knowledge baseproduct drift
A branch changed how one of our own reporting views computes a number. The merge checklist resolved the change to the specific in-app help entries it touched and printed them for review — the ones already published, not a blank search. One was still accurate. The other was updated in the same change instead of left to drift.
checked via: an automated diff-to-topic mapping, reused from the same mapping that decides which regression tests a change needs

It’s a checklist, not a scan — it tells a reviewer exactly what to look at, not whether the content is still true. That judgment call stays a person’s, every time.

None of this is about trusting an AI to write good code unsupervised. It’s about not needing to — the gate catches what supervision would have caught anyway, every time, instead of whenever someone happens to remember to look.