fix(gate-28): an empty diff scope is not a structural gap — it is ADR-020 working - #182
Merged
Merged
Conversation
…-020 working
gate-28 turned RED on every PR in the fleet whose diff does not touch
lib/**/*.php, which is most of them. It reported the DIFF's shape as the
REPOSITORY's defect.
`_lt_files` empty had two causes, and the final `else` stated them as one:
a) the repo has lib/**/*.php but this diff touches none of them — ADR-020
diff-scoping working, the same state gate-4 reports NOT APPLICABLE for
the same diff;
b) lib/ exists but holds no tracked .php at all.
Neither is (c) "files WERE in scope and none carried a declaration", the
genuine structural gap that branch describes. All three printed (c), and for
(a) that message is FALSE: with zero files in scope, "0 in-scope file carried
a declaration" is true only vacuously.
Not cosmetic. hydra-gates-require-full-coverage defaults to TRUE (#164) and a
structural gap fails the run with exit 98, so this was a fleet-wide falsely-RED
gate — the mirror of the falsely-GREEN shape #172 built this taxonomy to kill.
It surfaced the moment a repo unpinned to main, because gate-28 does not exist
at v1.3.0.
Measured on nldesign against the real runner, three arms, before and after:
diff = .github/workflows/code-quality.yml before SKIPPED(structural) -> exit 98
after NOT APPLICABLE
diff = 3 files under lib/ before PASS after PASS
diff = one lib/*.php declaring AGPL while
composer.json declares EUPL-1.2 after FAIL — 1 file(s)
The third arm is the one that matters: turning a red into a not-applicable is
exactly how a gate gets muted, so the mismatch it exists to catch was injected
and confirmed still caught.
The (c) message now also states the in-scope count, so a reader can tell it
apart from the case it used to be conflated with.
rubenvdlinde
pushed a commit
to ConductionNL/nldesign
that referenced
this pull request
Aug 6, 2026
…it was cut development moved from v1.3.0 to v1.5.0 while this branch was open, which fixes the symptom that opened it: v1.5.0 satisfies #177's capability probe, so Hydra Gates no longer fails before a gate runs. Unpinning entirely still matters, and the reason is now sharper than when this branch started. v1.5.0 carries a fleet-wide falsely-RED gate. gate-28 license-triangle reported a `structural` coverage gap whenever the diff scope was empty — that is, on every PR that does not touch lib/**/*.php, which is most of them — because "no file in scope" and "files in scope, none carried a licence declaration" reached the same branch. With hydra-gates-require-full-coverage defaulting TRUE, that is exit 98. It is fixed in ConductionNL/.github#182, on main. A repo pinned to v1.5.0 cannot see that fix, and the tag will not move. Measured here against the real runner, three arms: diff = .github/workflows/code-quality.yml before SKIPPED(structural) after NOT APPLICABLE diff = 3 files under lib/ PASS, both diff = a lib/*.php declaring AGPL while composer.json declares EUPL-1.2 FAIL — 1 file(s) That is the whole argument for #177's contract in one branch: this repo was pinned at v1.3.0, bumped to v1.5.0 to clear one breakage, and would have needed a third commit to clear the next one. A pin is a silent expiry date on every upstream fix. Verified on this PR's own run after the unpin: Hydra Gates PASS in 20s, 58 applicable gates green, 5 correctly NOT APPLICABLE. Rollback for this repo alone stays available: set hydra-gates-ref explicitly. An escape hatch, not a resting state.
rubenvdlinde
pushed a commit
to ConductionNL/nldesign
that referenced
this pull request
Aug 6, 2026
…it was cut development moved from v1.3.0 to v1.5.0 while this branch was open, which fixes the symptom that opened it: v1.5.0 satisfies #177's capability probe, so Hydra Gates no longer fails before a gate runs. Unpinning entirely still matters, and the reason is now sharper than when this branch started. v1.5.0 carries a fleet-wide falsely-RED gate. gate-28 license-triangle reported a `structural` coverage gap whenever the diff scope was empty — that is, on every PR that does not touch lib/**/*.php, which is most of them — because "no file in scope" and "files in scope, none carried a licence declaration" reached the same branch. With hydra-gates-require-full-coverage defaulting TRUE, that is exit 98. It is fixed in ConductionNL/.github#182, on main. A repo pinned to v1.5.0 cannot see that fix, and the tag will not move. Measured here against the real runner, three arms: diff = .github/workflows/code-quality.yml before SKIPPED(structural) after NOT APPLICABLE diff = 3 files under lib/ PASS, both diff = a lib/*.php declaring AGPL while composer.json declares EUPL-1.2 FAIL — 1 file(s) That is the whole argument for #177's contract in one branch: this repo was pinned at v1.3.0, bumped to v1.5.0 to clear one breakage, and would have needed a third commit to clear the next one. A pin is a silent expiry date on every upstream fix. Verified on this PR's own run after the unpin: Hydra Gates PASS in 20s, 58 applicable gates green, 5 correctly NOT APPLICABLE. Rollback for this repo alone stays available: set hydra-gates-ref explicitly. An escape hatch, not a resting state.
rubenvdlinde
added a commit
to ConductionNL/zaakafhandelapp
that referenced
this pull request
Aug 6, 2026
…it was cut (#331) This repo has been bumped twice already (v1.0.1 -> v1.3.0 -> v1.5.0), each time to clear a breakage the pin itself caused, and a third was queued. v1.5.0 ships gate-28 reporting a `structural` coverage gap whenever the diff scope is empty — i.e. on every PR that does not touch lib/**/*.php, which is most of them. With hydra-gates-require-full-coverage defaulting TRUE that is exit 98. It is fixed in ConductionNL/.github#182, on main, and a pinned repo cannot see that fix because the tag will not move. Tracking main is the fleet contract as of ConductionNL/.github#177, which also added the guard that makes it safe: an unresolvable reusable workflow produces no red check at all, just zero jobs, so quality-resolve-probe.yml counts the jobs a caller materialises and asserts > 0. Supersedes #329, which set v1.4.0 — a DOWNGRADE from what development now carries, and to a ref that fails #177's capability probe outright (v1.4.0 ships none of check_spec_anchors.py, check_form_labels.py or check_license_triangle.py). Rollback for this repo alone stays available: set hydra-gates-ref explicitly. Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
gate-28 goes RED on every PR whose diff does not touch
lib/**/*.php— which is most of them. It reports the diff's shape as the repository's defect.Found while unpinning nldesign to
mainper #177: with the pin removed both capability probes pass, all 58 applicable gates go green, and the only failure is gate-28 not running. It does not exist atv1.3.0, so unpinning is what surfaced it — and it would have turned the whole fleet red as the sweep landed.The conflation
_lt_filesempty had two causes, and the finalelsestated them as one:lib/**/*.phpbut this diff touches none — ADR-020 diff-scoping working, the same state gate-4 reports NOT APPLICABLE for the same diff;lib/exists but holds no tracked.phpat all.Neither is (c) "files were in scope and none carried a declaration" — the genuine structural gap that branch describes. All three printed (c), and for (a) that message is simply false: with zero files in scope, "0 in-scope file carried a declaration" is true only vacuously.
Not cosmetic:
hydra-gates-require-full-coveragedefaults TRUE (#164) and a structural gap exits 98. This is a fleet-wide falsely-RED gate — the mirror of the falsely-GREEN shape #172 built this taxonomy to kill.Three arms, measured on nldesign against the real runner
.github/workflows/code-quality.ymllib/lib/*.phpdeclaring AGPL while composer.json declares EUPL-1.2The third arm is the one that matters. Turning a red into a not-applicable is exactly how a gate gets muted, so the mismatch gate-28 exists to catch was injected on a throwaway branch and confirmed still caught.
The (c) message now also reports the in-scope file count, so a reader can tell it apart from the case it used to be conflated with.