merge_pr.py's post-merge probe gate reports a FALSE all-red on headless Linux — it doesn't wrap probe_gate.py in xvfb-run nf-wfhi ← Beads

closed priority 2 task unassigned

Twinned from https://github.com/cfsh/ninefold/issues/659 by tools/beads/import_github.py's reconcile pass.

Unclaimed / unlabelled — inert backlog. Filed by nf-dev-argo, measured on nf-dev-sg at 15:1xZ on 2026-08-06 while merging #633.

⚠️ First: do not act on the issue-create command that gate printed

The post-merge sweep after #633 printed a ready-made command to file 34 regressions:

``` gh issue create ... --title "feat/t1-merge-perimeter: 037ddce regressed butterbar-gate chit-budget cold-start colour-modes cujs-gaps delete-confirm dial-reset explore-walk ..." (all 34) ```

Every one is phantom. main is not red. Nobody should file that, and if a later session sees a similar block in a merge log on this box, this issue is the explanation.

The measurement

Same probe, same tree (037ddce), same box, twice:

``` $ ./probe.py tools/probes/butterbar-gate.json ERROR: Unable to create DisplayServer, all display drivers failed. at: setup2 (main/main.cpp:3386)

$ xvfb-run -a ./probe.py tools/probes/butterbar-gate.json [probe] expect_bar '' OK ('') [probe] shot probe_out/bar-02-quick-tap-never-flashes.png (1920x1080) [probe] done ```

ls /tmp/.X11-unix is empty on this host. Godot cannot open a display, every probe dies in setup2 before running a single step, and the gate reads that as 0 passed, 34 failed — a whole-suite regression.

Cause

merge_pr.py:probe_gate() invokes the gate directly:

```python run([sys.executable, str(gate)], check=False, stream=True) ```

No xvfb-run. On the Windows workstation that is correct — there is a real display. On this box, and on any headless Linux runner, it cannot work. notes/machines.md already carries "⚠ merge_pr.py needs xvfb-run here" as a session-side warning; nothing in the tool acts on it.

Why this is worse than not running the gate

The UI gate's whole justification is in its own docstring: *"What matters is that a human is present at this exact moment and knows which merge did it."* A gate that is all-red on every merge trains its reader to skip it — and the one merge that does regress something looks identical to the 50 before it. It is a #389-shaped hole reopened from the other side.

It also composes badly with #580 (the sweep is REPORT-ONLY here because the baseline is a Windows stamp): a reader who knows about #580 may attribute the red to platform drift and miss that the probes never ran at all. Those are different failures and the output does not distinguish them.

Suggested fix

Detect the missing display and either wrap or refuse — do not silently produce red:

⚠️ Whichever way, the distinction that matters is "the probes ran and failed" vs "the probes could not start". Today those are the same output, and only one of them is a regression.

Refs #580, #389, #633.

Dependencies

None.

Comments

No comments.

Add a comment