Twinned from https://github.com/cfsh/ninefold/issues/539 by tools/beads/import_github.py's reconcile pass.
CLAUDE.md tells every session, in the #503 bullet:
> Two habits still worth keeping regardless: git diff origin/main...HEAD --name-only before pushing, and don't trust gh pr diff.
Nothing runs it. presubmit.py doesn't, merge_pr.sh doesn't, no hook does — grep -rn "origin/main\.\.\.HEAD" tools/ presubmit.py returns only manifest.py, for an unrelated purpose. It is advice in a doc, and the failure it guards has now happened four times, each caught by a human or a bot reading the diff afterwards.
This is the #389 shape: *nothing ran probe_all, so main's UI gate rotted unnoticed.* Same structure — a rule everybody agrees with, written down, never executed.
| | what got in | caught by |
|---|---|---|
| #455 | ~31 *.Tests.cs.uid from #485, via rebuild_f5.sh + git add -A | aedanpope, reading the diff |
| #501 | the same ~31 files, regenerated after being deleted | aedanpope, reading the diff |
| #530 | the same ~31 files again — in the PR fixing #503 | me, running the check by hand after the PR was open |
| #530 | a one-line # wip: scratch comment | ninefold-reviewer, reading the diff (G1) |
The fourth is the one that makes this worth filing rather than closing with #530. The worktree removes the source of the first three — no session generates other branches' sidecars any more. It does nothing about the fourth, because that file was contamination the session created itself, in the file it was editing, with no rebuild involved. git add -A over a tree you have been experimenting in is the vector, and it survives #530 intact.
Worth being blunt: I read #503 closely enough to rewrite the script around it, wrote the CLAUDE.md bullet recommending the check, and then shipped both #530 escapes inside an hour. The habit is not hard to remember — it is hard to remember *at the one moment it matters*, which is a commit you are making for some other reason.
Every other gate in this repo was moved out of memory for exactly that reason: presubmit.py exists because "run the tests" was advice, probe_gate.sh exists because "check the probes" was advice, the merge ledger exists because "reply to feedback" was advice.
Not a design; whoever takes this should pick.
presubmit.py — it already runs before every merge and is the natural home. Diff origin/main...HEAD --name-only and flag paths that look unowned: generated sidecars (.uid, .import) with no corresponding source in the diff, files matching a gitignore-adjacent pattern, or a lone one-line comment change in a file whose other hunks are large. Advisory print, or gate — probably print first, and see how noisy it is.merge_pr.sh — later, but it is the last chance before main and already refuses on other grounds.pre-push hook — closest to the moment, but hooks are not versioned into a clone and every session would need to install one, which is the same "advice" problem one level down.The bar is low: every one of these four was one git diff --name-only away from being obvious. The reviewer bot currently does this work by reading diffs, which is a good backstop and an expensive primary.
Related: #503 (the source, fixed by #530), #512 item 1, #481 (nothing checks that a coder's claims match the tree), #450 (nothing verifies the verifier).
Filed unclaimed.
None.
No comments.