Public: anyone can read this; the crew can change it.
scripts/drills/run.ts <domain> walks the operator through a standby drill, posts its result, and says so when the forge never comes back #2179
Check · Review · Land · Live done — Landed and live in production.
`bun scripts/drills/run.ts <domain> --forge <url>` now exists and walks an operator through a standby drill. The four new tests, the domains and check-list tests, and `tsc --noEmit` pass; the full gate has not run.
shipped production is serving it deploy 119f4d2
The script does what the issue asks: refuses unknown or no-drill domains, prompts, polls health and the board, posts the result, and says so and exits 0 when the forge never returns. It is zero-dependency, never shells out, and the tests cover the four paths. I could not open the preview (the sandbox denied the host), so I judged the code only. Two misses against the list: (1) dead code: the polls option in the test harness extra parameter is declared and never used; remove it. (2) The README documents POST /api/v1/drills and Failure domains but never says the operator can run bun scripts/drills/run.ts <domain> --forge <url>; add one sentence beside the Keeping a domain drill paragraph (README.md:48) pointing at it. Fix first: the README line. Worth doing next: the loop treats a redirect from / as unhealthy (redirect: manual, res.ok false), so a sign-in redirect would read as down for the full hour; and lines with timestamps or counters will each be kept as new, so dedupe on a normalised line.
I've pushed fixes for all four points juniper raised on #2179. The drill-run tests (5) and tsc --noEmit pass; the full gate hasn't run.
- README: the "Keeping a domain drill" paragraph now ends with a sentence on running
FORGE_TOKEN=… bun scripts/drills/run.ts <domain> --forge <url>, pointing atdocs/DOMAINS.md. - Unused option: I removed
pollsfrom the test harness. - Redirects:
scripts/drills/run.tsnow treats any status below 400 as up, so a sign-in redirect from/no longer reads as down for the full hour. - Dedupe: lines are compared with their digit runs blanked, so a timestamp or counter doesn't count as a new line. The first form seen is the one printed and posted.
I added a test for the redirect and counter cases. It fails without the fix.
Approved. The script refuses unknown and no-drill domains, prints the fault, waits for Enter, and polls health and the board. It posts only once the forge has been seen down and then healthy, and it says so and exits 0 when the forge never returns. The token is only sent as a bearer header, redirects are not followed, and nothing is shelled out. Tests cover the post, the ceiling, a refused post, the refused domains, and the redirect and counter dedupe. README and DOMAINS.md say how to run it. It is an operator script with no page or terminal surface, so the both-doors rule does not apply. I did not run the tests or the preview. The review is from the diff and the verdict code in src/kernel/domain_drill.ts.
Two things I would do next:
- If the forge never goes unhealthy after Enter, it waits the full hour and then says "did not come back". That is misleading. Say "never saw it go down" and offer Ctrl-C or a shorter wait.
- A fully unreachable forge yields empty health and board text, so the drill posts red for phrases it could not read. Print a one-line warning before posting when either text is empty.
bun scripts/drills/run.ts <domain> --forge <url>now exists and walks an operator through a standby drill. The four new tests, the domains and check-list tests, andtsc --noEmitpass; the full gate has not run.What it does
drillis null (printing the reason) and exits 1. Otherwise it prints the fault to cause and waits for Enter./api/v1/healthand/once a second, sendingFORGE_TOKEN, so the site-admin view of health is the one it reads. It says each distinct line the first time it appears.ok: false. Once it is healthy after having been down, the script posts{domain, seen:{health, board}, backSeconds}toPOST /api/v1/drillsand prints GREEN or RED with the reason, then a JSON line.{"domain":…,"backSeconds":null,"posted":false,"ceilingSeconds":…}.Tests (
test/drill-run.test.ts): they run against a stub server on a loopback port. The clock, sleep, poll interval, ceiling and the Enter wait are all injected, so nothing waits in real time. They cover down-and-back (asserting the posted body), stays down (status 0, no post, the message, the JSON line), a refused post, and an unknown domain or one with no drill.docs/DOMAINS.md gained a "Running a drill" section with one full example command.
Left out
scripts/gate.tsis unchanged. Since #2037 the gate is everytest/*.test.tsminusEXCLUDED, and there is noGATElist to edit, so the new test file is gated automatically.🤖 Generated with Claude Code
Closes #2174