Repository navigation
Cross-repo pair gate never resolves a DECLARED Pairs-with: when the diff removes no public surface #7397
Description
Core's
Cross-repo pair (public surface)gate never resolves a DECLAREDPairs-with:when the diff removes no public type or member. So a dependency-only removal that a satellite depends on (a PackageReference or PackageVersion leaving core) gets no enforced landing order.Evidence (core main, 2026-10-26):
scripts/check-cross-repo-pair.pyreturns 0 atif not removed: out.append("No public type or member left src/ in this diff — no cross-repo pair to gate."). That return comes before anyPairs-with:parsing.scripts/check-package-pin-removal.pychecks only that aSatellite-pins:declaration is present; its docstring says so on purpose ("WHAT IT CANNOT DO"), so it cannot hold the order either.Where it surfaced: MeshWeaver#7205 (drops YamlDotNet from core) declares
Pairs-with: Systemorph/MeshWeaver.Plugins#4227, and its body claimed the pair gate held it red until #4227 merged. The Copilot review (thread 4371264675) pointed out that no gate held it. In practice the PR was kept in DRAFT and readied by a script only after #4227 merged, so nothing broke this time.Possible fix (triage's call): when the PR body DECLARES
Pairs-with:, resolve it even if the surface diff is empty. A declaration is the author asserting a coupling, so the gate should hold the PR to it whatever the detector found. The gate would still not fire for undeclared dependency-only removals;Satellite-pins:covers those by declaration only.NOT established: whether any past merge actually landed a dependency-only removal before its counterpart because of this gap. I checked only #7205.
Context (triage): reported from Doc/Architecture/CrossRepoPairGate (the page that documents this gate, its cross-repo-pair job in .github/workflows/dotnet-test.yml, and the Pairs-with: declaration forms). Found while landing the YamlDotNet removal, core#7205 paired with Plugins#4227 (merged as 9142c1c99b). Incidental: it did not block that task. The reporter proposes resolving a declared Pairs-with: even when the public-surface detector reports nothing removed — the same "an author who believes they declared something and a gate that believes they did not is indistinguishable from a skip" principle the gate itself already carries.
Origin: https://control.systemorph.com/Feedback/_Submissions/fb-e7f711c6dd753a9af48a2708204d120d
filed by the triage agent on behalf of someone on control.systemorph.com via systemorph-com
Triage routing: filed in Systemorph/MeshWeaver — agent: Systemorph/MeshWeaver — The feedback names scripts/check-cross-repo-pair.py and scripts/check-package-pin-removal.py; the Doc/Architecture/CrossRepoPairGate page documents these as this repository's own gates (cross-repo-pair job in .github/workflows/dotnet-test.yml, beside the scripts under scripts/), and the incident it cites (MeshWeaver#7205 paired with the private Systemorph/MeshWeaver.Plugins#4227) is a core pull request..
Activity
rbuergi commentedon Oct 27, 2026
Unique detail from #7384, now closed as a duplicate of this one. It is the same early return, seen on the pin-removal shape: #7179 dropped GUI
PackageVersionpins that MeshWeaver.Plugins consumes versionless via Plugins#4202. Nothing held it to that order, becausecheck-cross-repo-pair.pyreturns at L342-343 (if not removed:) before readingPairs-with:.check-package-pin-removal.pyonly checks that every removed id is named underSatellite-pins:. The cost of landing first is NU1010 in the satellite at its next platform move. The suggested fix there is forcheck-package-pin-removal.py, when it sees removals, to resolve anyPairs-with:with the pair gate's resolver. Both scripts are unchanged at core main1fa6e093ca.