A
?
← Handbook

Verification

Nothing is working until it has run. A passing build is not evidence.

Why this rule exists

Every one of these passed tsc, lint, unit tests and next build:

  • The standalone server bound to the container hostname, so nothing could reach it
  • Caddy never received DOMAIN and listened on no port at all
  • A client component imported the renderer, pulling sharp into the browser bundle — blank page
  • Services threw on malformed ids, so a bad request 500'd and the guardrail test read that as *not enforced*
  • Token persistence failed with EACCES on every write, degrading to "works until restart"
  • A skill file a worker loads at runtime was written outside the repository and never committed. The code referencing it typechecked perfectly, because a missing file is a runtime error. The register recorded the feature as Live for a day.

Static checks cannot see any of these. Only booting the thing and asking it for a page can.

The gate

./scripts/qa.sh                          # static: typecheck, lint, unit tests, build
./scripts/qa.sh https://<host>           # static + smoke against a running instance
npm run smoke -- https://<host>          # smoke alone

Smoke runs automatically after every deploy.

What the smoke test asserts

Behaviour, never status codes:

  • pages serve real content above a minimum size — a blank 200 is what a status check misses
  • generation returns real JPEGs above a minimum decoded size — a 200-byte "image" is a broken render, not an image
  • one scene still yields twelve creatives — a scene-reuse regression fails loudly instead of quietly costing money
  • an unapproved request is rejected with 400 — proving the guardrail rather than assuming it
  • ids are discovered, never hardcoded; hardcoded ids are why it failed to notice the move to a database

Guard what the compiler cannot see

Runtime dependencies that are not imports — skill files, migrations, layout specs — are invisible to typechecking. src/lib/agents/skills.test.ts asserts every skill a worker references actually exists, and that the check itself references something, so it cannot silently pass against an empty set.

Any new runtime-loaded asset needs the same treatment.

The register

docs/register.md distinguishes Built (code exists and typechecks) from Live (it has run, evidence stated). Blurring those is how a system comes to be believed to work when it does not.

Running the gate

DATABASE_URL=... ATLAS_API_TOKEN=... ./scripts/qa.sh dev.atlasconsulting.tech

Both variables are required and neither failure is self-explanatory. Without DATABASE_URL the build fails collecting page data for /_not-found, because @/lib/db opens the pool as an import side effect and throws — an error that names nothing relevant. Without ATLAS_API_TOKEN every smoke request returns 401. A scheme-less host is assumed to be https.

Run the checks after the change, not before it. A test fixture with a type error once reached a deploy because tsc --noEmit had been run before the fixture was written and npm run build was the first thing to see it. tsc does cover test files — the gap was in the ordering, not the tool. The lesson is the ordinary one: a green check proves the tree as it was when the check ran.

Lint runs at --max-warnings=0. That means an unused import anywhere fails the gate for a change that has nothing to do with it. Keep it clean rather than discovering eleven standing warnings the day you need the gate to be trustworthy.