dev.py pr refuses to open on ANY red --all, even failures nothing in the diff touches nf-152 ← Beads

closed priority 2 task gate-classify-red

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

./dev.py pr (and ./dev.py check) runs presubmit.py --all — the *whole* tree's python suite (~2877 tests today), not scoped to the diff — and refuses to open a PR if anything anywhere is red, regardless of whether the PR touches it. tools/nflib/devcli.py's gate() docstring says this is deliberate: pr must never gate on something narrower than what check reports green, "the drift that matters is the silent one."

That reasoning holds for *this PR's own* correctness. It doesn't hold for *unrelated* red: a broken test anywhere in the repo currently blocks every session on the box from opening *any* PR, including — worst case — the PR that would fix the broken test. Hit this for real today (2026-08-20): tools/beads/import_github_golden_test.py broke on main from #1152 (another, no-longer-running session), and ./dev.py pr refused to open my completely unrelated tools/web_frontend/ PR because of it. Verified via git stash that the failure is identical with my diff removed — pure pre-existing breakage, nothing to do with what I was shipping.

Why this is worth fixing, not just working around per-incident: - DEV_PRINCIPLES A2 (blast radius): a failure in one subsystem's golden fixture has *local* impact — its own tests, its own PRs. Gating every other PR on it turns a local failure into one with global, all-the-time impact, exactly backwards from where A2 says to spend the worry. - DEV_PRINCIPLES B6 (isolation): "sub-systems should not have side effects on each other... different dev agents should not be able to have side effects on each other." An unrelated dev's broken fixture currently has exactly that side effect on every other session's ability to ship. - The chicken-and-egg case: if the only way to fix a red gate is a PR, and no PR can open while the gate is red, the repo has no way out of that state except a human intervening by hand outside the normal loop. That should not be possible by design.

Not prescribing the fix — a few shapes worth considering, unclaimed: - Scope the python lane the way probes already are (affected_probes.py/ probe_select.py): only run tests the diff could plausibly affect for pr's gate, keep --all exhaustive for check/merge's own use. - Or: pr compares its failure set against main's own last recorded gate state (presubmit.json-style) and only blocks on *newly* red tests — the "stash and compare" check done by hand above, automated. - Or, at minimum, a documented override in the shape of UNCONVERGED_OK=1/ STALE_OK=1 for a presubmit failure a dev has verified (same method) is pre-existing and unrelated — a manual escape hatch beats no escape hatch, even if a real fix is bigger.

Whichever shape: gate()'s own "narrower than check" worry is really about *this PR's diff* being under-tested, not about *every other* PR on the box sharing one global pass/fail bit for the whole tree. Those are different properties and the fix should keep the first while dropping the second.

Filed unclaimed per CLAUDE.md's "strategic uplifts: file them, don't claim them" — found while shipping an unrelated tools/web_frontend/ PR, not part of that chunk.

Dependencies

None.

Comments

jcantsp-bot · 2026-08-20T08:53:47Z

Twin of gh-1155, closed with tracking moved here (design 011's bd-authoritative flip, 2026-08-20).

Work is already shipped as a stack of two PRs, both open, converged with the automated reviewer, waiting on @aedanpope's human approval (governance perimeter — tools/nflib/tools/pr core plumbing):

Nothing further to do until review lands.

Add a comment