Twinned from https://github.com/cfsh/ninefold/issues/675 by tools/beads/import_github.py's reconcile pass.
Suggestions from ninefold-reviewer's review of #662. None of these block it — the fix is sound and CONVERGED at f1fee13. Recorded so they survive a merge-as-is. #664 held rounds 1 and 2 and is correctly closed: C1–C4 and F1–F3 were all folded in, none shipped as-is.
tools/pr/probe_gate.py main(): the wipeout clears record_ok, and the shared not record_ok tail then prints
``` [probe-gate] NOT RECORDING: all 34 probes failed and none passed — that is far more often a broken host … [probe-gate] (the sweep above is still valid for this branch; run from main to record) ```
In the scenario the wipeout exists for — post-merge, on main, not --dry-run, platform matching, so record_reason is empty and the wipeout is the reason — both halves of that second line are wrong. The report four lines above says to read the sweep as the host rather than as main, and the operator is already on main. It is the last line on the screen, which is the position #632 is entirely about: its transcript is a complaint about what the operator's final screenful told them.
One if not wipeout(sweep) around the hint, or a wipeout-specific wording, closes it. (The "run from main to record" half is already wrong on main for the #566 platform-mismatch case, so a fix could cover both.)
nflib.godot.engine_problem() stops at Path(override).is_file() / find() is not None, and find() globs without an exec check. presubmit.py's doctor already carries the POSIX half:
```python runnable = exe is not None and exe.is_file() and (os.name == "nt" or os.access(exe, os.X_OK)) ```
with a comment recording why — a Python zipfile extraction drops the mode bits where real unzip keeps them, and the former is what the first Linux install used. #588's own body lists that state (#573 F3) among the reasons a wrong environment is now an ordinary condition rather than an exotic one.
Today it lands as 34 × 126 not executable → wipeout() → no attribution, no paste-ready issue, no baseline write. The answer is correct, so this is C4's residual for the third trigger rather than a gap: it costs a build and 34 launches instead of one os.access, and the report says "probably the host" instead of naming the engine. One clause in engine_problem, guarded to POSIX, would make it symmetric with the other two.
tools/tests/test_probes.py now has both declare_host() at module scope and NoDisplayTest._engine(), doing the same NamedTemporaryFile(suffix=".x86_64", delete=False) + addCleanup(os.unlink) dance. The two callers of _engine() need the path inside a mock.patch.dict, which is why it survived — but declare_host is the name that is supposed to be the one place. Cosmetic.
sweep() reads os.environ directly, although both preflights accept an injectable environdisplay_problem(environ=None) and engine_problem(environ=None) were both written with a seam, and neither call site in probe_all.sweep() uses it — which is why declaring the host is a test-side ritual rather than a parameter. declare_host makes it one named ritual instead of nine, but it is still opt-in: a new sweep() test class that forgets it is coupled to the box again, silently, exactly as F1 was. Threading an environ through sweep() would make it impossible instead of merely documented.
#412 is Refs'd by #662 as case law for item 5, and it carries the only aedanpope prose in this PR's reference set:
> re: 5) I wonder if we should be running a dedicated scheduler for probes, since we can only run them serially on one machine
Posted 2026-08-02, unanswered, on an issue that has since been closed — so it is stranded. Clearly not #662's job (that PR is about what the gate *says*, not when it runs), and no open issue tracks it. Worth its own issue before it is lost.
None.
No comments.