Twinned from https://github.com/cfsh/ninefold/issues/574 by tools/beads/import_github.py's reconcile pass.
Suggestions from ninefold-reviewer's review of #567. Unclaimed and unlabelled — pick up or close as you like.
#567 makes the test suites platform-honest so merge_pr.py can gate on Linux, and its central safety argument is that a platform skip must be loud: WindowsOnlyFact requires a because string, on the stated precedent that presubmit.py's shellcheck lane reports skip — N scripts UNCHECKED rather than green (#389). Two residuals where that discipline doesn't actually reach the output. Neither blocks #567 — it converged.
The shellcheck precedent works because suite_shellcheck sets its own lane status="skip" plus a detail, and the summary prints detail. The dotnet lane has no equivalent surface:
_shell_result sets detail="" on pass — presubmit.py:120-126status == "fail" — presubmit.py:523-527So under ./presubmit.py --all — what merge_pr.py runs — the entire dotnet test output is discarded and a Linux run prints:
``` ✓ dotnet pass 4.5s ```
The because string and the 1 skipped count reach nobody. #567's Test Plan claim that "the skip prints Windows-only — rename(2) …" is true of a bare dotnet test, not of the gate. Net effect: the fence against reaching for WindowsOnlyFact whenever a suite reddens on a new platform is documentation only — the gate looks identical either way.
Shape of a fix: have suite_dotnet parse the Passed! - Failed: 0, Passed: 589, Skipped: 1 summary line and surface a non-empty detail (e.g. 1 skipped — Windows-only) when the skip count is non-zero, so it lands in presubmit's own summary. SuiteResult already supports status="note" in the mark table (presubmit.py:530) if a distinct mark is wanted.
Deliberately kept out of #567: it touches presubmit.py, which #553 rewrites.
test_a_child_that_imports_nflib_can_print_these_glyphs in tools/tests/test_nflib_proc.py now drops two assertions on POSIX behind a bare if os.name == "nt": — no skip, no count, no reason in the output. That is the shape WindowsOnlyFact exists to prevent, three files away in the same PR. grep -c 'skipIf\|skipUnless' tools/tests/*.py is still 0, so the Python tier still has no convention.
A blanket @unittest.skipUnless on the method would lose the cross-platform half. The shape that keeps both claims is a split:
@unittest.skipUnless(os.name == "nt", "<reason>") test, where unittest always reports it in the skip count and prints the reason under -v.#565 argued for exactly this ("the reason belongs next to the assertion") and is still open, unreferenced by #567 — worth adopting or rebutting there either way.
notes/#567 establishes a repo-wide rule — when a platform skip is legitimate (*the production code path this asserts cannot be reached on this OS*) and what it must carry — documented only in WindowsOnlyFact's C# docstring, where the Python tier will not find it. Keeping notes/machines.md out of #567 was right, since #553 rewrites that section; worth a short entry once #553 lands.
---
57de96e7, commit 2 — probe_gate.py's platform guard)The first pass reviewed a stale sha and never saw the second commit. Three more residuals, none of which blocked the PR — it converged again. Item 4 is the one worth doing.
probe_gate.py:563-569 clears record_ok when the sweep's platform differs from
the baseline's. BaselinePlatformTest covers two pure helpers around it —
build_record stamping PLATFORM, and baseline_platform() folding absent/junk
to windows — but nothing drives main() through the mismatch branch. Delete
those four lines and the suite stays green on every platform.
Every sibling record_ok gate has such a test, and test_probe_gate.py says why
in its own words:
BaselineFetchTest.test_a_failed_fetch_stops_main_from_recording — *"Behavioural, not a source regex (#472 G3). Drives real main()…"*DryRunTest — *"⚠ These used to assert by regexing inspect.getsource(G.main), which pins…"*Two things sharpen it:
test_probe_gate.py:416 reads *"BaselinePlatformTest covers the platform gate itself."* It covers the helper. And test_a_matching_platform_does_not_block_recording never reaches record_baseline.PLATFORM == LEGACY_PLATFORM == "windows", and both updated fixtures stamp G.PLATFORM. The only machine that has ever run a merge never executes this path, in the suite or in life. Nor has it been seen by hand: the manual evidence is probe_gate --dry-run, and --dry-run sets record_ok = False first, so record_reason or … means the platform refusal string has never been printed by anything.The logic reads correct — this is a coverage hole, not a live defect. Fix is ~12 lines and platform-independent, since a literal foreign string mismatches on every box:
```python G.load_baseline = lambda root: ( True, {"sha": "old", "failing": {}, "platform": "some-other-os"}, True) # then assert recorded == [] and "recording would overwrite" in the output ```
Correct by design, and undocumented. The live baseline is
{"sha": "e010817c…", "failing": {}} — unstamped, zero standing failures. The
sequencing plan on #566 is that #567, #553 and #573 all merge from the WSL box;
none of them records. When the Windows box next merges, compute_delta compares
that single sweep against e010817c's empty set, and anything broken by any
intervening Linux merge prints under `████ NEW FAILURES — this merge regressed
main ████, with the paste-ready gh issue create` naming the innocent Windows
merge's sha.
#478 already lists *"a skipped or failed gate … leave the baseline where it was, so the next successful sweep spans every merge since"* as a narrow case. This makes it the default path, so #478 is worth re-reading as more urgent than when it was filed. Second-order: after a Linux merge, main is UI-unverified and nothing says so at the console.
Cheap partial mitigations, short of #478:
say() line on the platform-refusal path — *"main is now unverified; run ./tools/pr/probe_gate.py from the Windows box to re-baseline"*;notes/merging.md:44-52 describes the UI gate as verifying main unconditionally, and notes/probes.md:26-27 names the baseline without saying whose platform it describes. Both want a line, after #553 clears machines.md.probe_gate.pyThe module docstring now carries consecutive REPORTS/RECORDS paragraphs: lines
10-14 (new, with the platform condition) and lines 16-19 (pre-existing, stating
*"RECORDS only when HEAD is origin/main"* with no mention of it). A top-down
reader gets the superseded rule stated as authoritative. Fold them into one.
None.
No comments.