01The undici bug
Booting it locally exposed what 279 green tests had hidden. Node's global fetch wraps every network error in a generic TypeError("fetch failed") with the real libuv code nested under .cause, while my mock HTTP layer threw top-level codes, so the suite passed cleanly and every real outage would have read "fetch failed" instead of "connection refused" or "DNS lookup failed". The classifier now walks .cause, and I added five regression tests in the undici shape with it.
02Delivery-gated alerts
I started the Incident table's downNotifiedAt and upNotifiedAt as audit stamps, which quietly made them a failure mode: if SMTP hiccuped at the moment a site went down, the stamp was written anyway and the outage produced no alert, ever. The dispatcher now reports whether at least one channel actually succeeded, and the state machine stamps only on confirmed delivery. A DOWN send that fails on every channel is retried on the next pass rather than lost.
03Database-gated idempotency
The cron pass takes a flock, but the dashboard's Check now button does not go through it, so a manual re-check can race a scheduled pass holding a stale copy of the monitor row and open a second incident or double-send. I gate both transitions on the persisted open incident instead: down is find-or-create, recovery closes an incident only if one is open. A down monitor with no incident recovers silently rather than emailing a spurious zero-second recovery.
04Dead-man's switch
Because the monitor runs on the same box as the sites, it cannot report its own death, so I end every pass with a GET to an external heartbeat service. I put the ping deliberately after the work rather than before, so it means the checker ran and did not hang, not that the box booted. It never throws, and I wrapped the prune step for the same reason: a database hiccup must not skip the heartbeat and page the owner over nothing.
05Verifiers, then fixes
I ran the build from a written specification: interfaces and file ownership frozen in CONTRACTS.md first, then nine parallel lane agents, then ten independent adversarial verifiers pointed at the finished code. I fixed their findings forward and logged them append-only in DECISIONS.md, including the write-only notification stamps and a Telegram Markdown 400 that would have silently dropped any alert for a URL containing an underscore. Two of the corrections above came out of that pass, not out of the tests.