Testing cadence
Three tiers, three costs, one rule.
| Tier | What | Cost |
|---|---|---|
| fast | pure kernel files under node | ~1.5 s targeted, ~20 s all |
| node | real stack, no DOM, hosts driving the kernel | ~2 min |
| browser | Playwright over the built app | ~2.5 min |
Certificates make the rule mechanical
Each tier carries the content hash of every file it reads, written when it passes. certify run runs only the tiers whose inputs changed; a page-component edit leaves the node tier fresh because the node tier never reads pages. A pre-commit hook runs certify check and refuses a tree that is not certified for every tier. The rule stopped slipping the day it became a check.
node tooling/certify.mjs check # FRESH / STALE per tier, exit 1 if any stale
node tooling/certify.mjs run # run the stale tiers, certify on passConfigure the tiers' input sets and commands for your repository at the top of the script; the MVP's copy is the reference.
Instruments, in the order to reach for them
- Read the artifact. The trace, the page-level trace, the captured log. A failure re-run before its artifact is read costs the artifact.
- Profile the page, not the box. A "starved" verdict from load average or frame gaps is not evidence about the machine: the CPU profile of a page at 97 % busy named a read-receipt loop the DOM never showed. The MVP's capture fixture takes
CLEAN_PROFILE=1. - Count what went on the wire. A regression test for a loop counts frames, not pixels.
What a spec may not do
If a spec has to be edited to pass, stop and report it. A longer timeout is not a fix. A retry on a refusal is not a fix. A run that is green two times in three has a defect, not a flake.