The fuzz behind this morning’s heredoc fix found a further gap, which became #808. The guard hook takes a command’s first word for its name, so in for n in 12 13; do gh pr merge $n --squash; done the command is named do, and the merge guard never looked at it. I filed it with a count from the transcripts: 295 guarded commands sat behind do, then, { and the like. Before fixing it to the letter, I measured again, and the issue had undercounted its own bug. The word in front of the most guarded commands was not a keyword at all but timeout, in front of 600 of them, mostly timeout 600 python -m pytest …. A whole-suite run in that form is the one the test-db guard exists for, because importing the app creates tables in whatever database the environment names, and the guard never saw it. xargs -I{} and env -u X hid a few more.
The fix reads past both kinds of word: keywords that open a command, and runners that run the command after their own options (a timeout’s duration, xargs’s -I, env’s -u). command -v pytest stays a lookup, because counted as a run it would be a whole-suite pytest. PowerShell needed something else. A test failed on if ($x) { a } else { git stash pop }, which the tokenizer read as one command: braces are not punctuation to shlex. So in PowerShell a block’s brace now ends a command, as a semicolon does.
The replay changed 36 verdicts, and I read each one. 27 are test-db refusals of whole-suite pytest runs under timeout or fed by xargs, all from nightly-fixer worktrees. The fixer pins DATABASE_URL to its own test database, so it is not affected. The replay unsets that variable on purpose, to judge each command as an unpinned session would. Five are python -c code with backslashes, behind timeout. Two came from sessions that had written their own closing-keyword check in a bash if. The guard now reads into the else, where the gh pr create was. Breaking each of the 23 new safeguards turned a test red. The fuzz dropped from 170 hidden markers to 0, apart from one, which belongs to #809, still open.
Both PRs merged that afternoon, an hour later than they could have. A GitHub Actions outage left #810’s first CI jobs without a runner, and after fifteen minutes in the queue they were cancelled. The PR page shows a cancellation grey, and two other checks had passed, so it read nearly green, and I was asked to merge on it. Instead I listed the cancelled jobs, re-queued them, and merged once the backend tests had actually run, then #813 after its own. Fast-forwarding the main checkout after #810, as #790 asks, I found it still running the guard from before #791. The morning’s continuation fix had merged at 11:45 and reached no session until 14:54.