launch-quickly
Decisions

0008 — There is one validation verb

Five commands means an agent remembers zero. lq check is what the hook runs, what the rules mandate, and what CI runs — the same code path in all three.

Context

The usual shape is lint, typecheck, test, format:check, plus whatever the framework adds. A human learns them. An agent, told to verify its work, runs whichever it remembers — often the fastest one — and reports success.

Decision

lq check is the only validation verb. It runs the typechecker, the convention rules, formatting, the migration check and the structure check in one pass.

It is what the PostToolUse hook runs, what CLAUDE.md mandates before an agent may claim it is done, and what CI runs — the same code path in all three. Five commands means the agent remembers zero, and a convention the agent cannot verify is a convention that drifts.

lq check --changed scopes to what differs from HEAD, and is the fast signal the hook fires after every edit. It reports which checks it skipped, because a skipped check has not passed — and saying so was a fix, not a feature: it used to claim skipped work had succeeded.

Rejected

Separate verbs. Rejected on agent recall, not on speed. The speed argument actually points the other way, and --changed exists to answer it.

Consequences

Formatting is its own step. The lint preset includes eslint-config-prettier, which switches off every formatting rule on the assumption prettier owns them — so without a separate step, nothing checks formatting at all, and generated code drifts from hand-written code in a way no other check can see.

A passing step can still have something to say. drizzle-kit prints "Everything's fine 🐶🔥", which read as a finding when treated as output, so advisories are a separate channel from failure detail. That channel later turned out to be load-bearing for a different reason: eslint exits 0 when every finding is a warning, and the runner discarded output from a command that exited 0. Two design lint rules were demoted to warnings for one release to stop an upgrade breaking builds — and would have produced fifty-plus findings per project that nobody could see. A warning nobody sees is not a softer rule, it is no rule.

The highest-value check is the least obvious one. A tenant-owned table with no RLS policy looks completely correct to every other check. The structure check reads drizzle's journal to catch it, because a .sql file that is not in the journal is never applied — which is exactly the bug that motivated it. It fails in the safe direction when the journal is unreadable.

On this page