Skip to content

fix(gates): manifest-l10n-coverage is gate-101, not a second gate-99 - #615

Merged
rubenvdlinde merged 1 commit into
mainfrom
fix/gate-99-number-collision
Aug 28, 2026
Merged

fix(gates): manifest-l10n-coverage is gate-101, not a second gate-99#615
rubenvdlinde merged 1 commit into
mainfrom
fix/gate-99-number-collision

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Two different gates both declared number 99:

10818: # GATE 99 — manifest-l10n-coverage   (#604, 2026-08-27)
10997: # GATE 99 — demo-data-coverage       (#590, earlier)

demo-data-coverage held 99 first and COVERED-ELSEWHERE.md records it there, so manifest-l10n-coverage is the one that moves.

What the collision broke

The declared inventory silently dropped a gate. It is built with

... | sort -n -k1,1 -s | awk "!seen[\$1]++"

First declaration of each number wins — so one of the two gates was absent from the inventory entirely and _declared_n counted 80 where 81 exist. The coverage line then printed arithmetic that cannot be true. From a real pipelinq run:

COVERAGE: 72 of 80 declared gates reported a result (9 not applicable; 72 of 71 applicable gates ran)

72 of 71. That is the duplicate surfacing as a number nobody can act on.

It also made Package invariants unpassable on main. test_gate99_demo_data_scope.sh greps the runner for gate-99 output and received manifest-l10n-coverage's NOT APPLICABLE verdict on every arm:

FAIL — expected FAIL on planted, got: [gate-99] manifest-l10n-coverage: NOT APPLICABLE — ...
FAIL — expected PASS on clean,   got: [gate-99] manifest-l10n-coverage: NOT APPLICABLE — ...

So this repo's own CI has been red on main, masking any real regression behind a failure nobody could fix by editing the test.

Verification

check result
bash -n on the runner OK
test_gate99_demo_data_scope.sh ALL PASS (was 3 FAILURES), all four arms
test_gate_acceptance_matrix.sh 193 passed, 0 failed
fixtured-gate count 80 → 81 — the shadowed gate reappearing
duplicate gate numbers remaining none
demo-data-coverage call sites untouched (5)

Two different gates both declared number 99:

    10818: # GATE 99 — manifest-l10n-coverage   (#604, 2026-08-27)
    10997: # GATE 99 — demo-data-coverage       (#590, earlier)

demo-data-coverage held 99 first and COVERED-ELSEWHERE.md records it there, so
manifest-l10n-coverage is the one that moves.

WHAT IT BROKE. The declared inventory is built with

    ... | sort -n -k1,1 -s | awk '!seen[$1]++'

first declaration of each NUMBER wins — so one of the two gates was absent from
the inventory entirely, and `_declared_n` counted 80 where 81 gates exist. The
coverage line then printed arithmetic that cannot be true. From a real pipelinq
run:

    COVERAGE: 72 of 80 declared gates reported a result (9 not applicable; 72 of 71 applicable gates ran)

72 of 71. That is the duplicate, surfacing as a number nobody can act on.

It also made `test_gate99_demo_data_scope.sh` unpassable: it greps the runner's
gate-99 output and received manifest-l10n-coverage's NOT APPLICABLE verdict on
all three arms, so `Package invariants` has been red on main — masking any real
regression in this repository behind a failure nobody could fix.

Verified:
  - `bash -n` on the runner
  - test_gate99_demo_data_scope.sh: ALL PASS (was 3 FAILURES) — all four arms
  - test_gate_acceptance_matrix.sh: 193 passed, 0 failed
  - the fixtured-gate count moves 80 -> 81, which is the shadowed gate
    reappearing in the inventory
  - no duplicate gate number remains
  - demo-data-coverage's five call sites are untouched
@rubenvdlinde
rubenvdlinde merged commit 1ec8e28 into main Aug 28, 2026
39 checks passed
@rubenvdlinde
rubenvdlinde deleted the fix/gate-99-number-collision branch August 28, 2026 08:54
rubenvdlinde added a commit that referenced this pull request Aug 28, 2026
The runner declared GATE 101 twice: manifest-l10n-coverage and
demo-data-coverage, each calling _pass/_fail with the same number under
different names.

Both gates were introduced as gate-99 within 14 minutes of each other, and the
fix for THAT collision (#615) moved l10n from 99 to 101 - onto a number
demo-data-coverage already held. The collision moved rather than closing.

The symptom is not a duplicate-number warning. test_gate101_demo_data_scope.sh
fails with 'expected FAIL on planted, got: [gate-101] manifest-l10n-coverage:
NOT APPLICABLE' - the demo-data test greps for its own gate number and reads
the OTHER gate's verdict. Any PR touching hydra-gates is red on it.

l10n moves rather than demo-data because demo-data has a test file whose NAME
pins its number (test_gate101_demo_data_scope.sh) and l10n has none, so this is
the change with no rename in it.
rubenvdlinde added a commit that referenced this pull request Aug 28, 2026
#620)

* fix(gates): manifest-l10n-coverage is gate-102 - 101 was already taken

The runner declared GATE 101 twice: manifest-l10n-coverage and
demo-data-coverage, each calling _pass/_fail with the same number under
different names.

Both gates were introduced as gate-99 within 14 minutes of each other, and the
fix for THAT collision (#615) moved l10n from 99 to 101 - onto a number
demo-data-coverage already held. The collision moved rather than closing.

The symptom is not a duplicate-number warning. test_gate101_demo_data_scope.sh
fails with 'expected FAIL on planted, got: [gate-101] manifest-l10n-coverage:
NOT APPLICABLE' - the demo-data test greps for its own gate number and reads
the OTHER gate's verdict. Any PR touching hydra-gates is red on it.

l10n moves rather than demo-data because demo-data has a test file whose NAME
pins its number (test_gate101_demo_data_scope.sh) and l10n has none, so this is
the change with no rename in it.

* fix(gates): the l10n fixture follows its gate to 102

test_gate_acceptance_matrix.sh keys a fixture to its gate by NUMBER, so moving
manifest-l10n-coverage off the duplicated 101 orphaned its own acceptance
bundle: 'gate-102 is DECLARED by the runner but has neither a planted/clean
fixture nor a reasoned row in UNCOVERED.md'.

The fixture, its two arms and its reasoning are unchanged - only the number it
is filed under.

* docs(gates): record that the 99 -> 101 fix collided a second time

The note explained the first collision and stopped there, so it read as closed.
It was not: moving l10n 99 -> 101 landed on the number this gate had just
taken, and the identical failure reappeared hours later.

Both times the tell was this suite failing while the gate it names was fine,
because a test that greps [gate-N] reads whichever gate printed that number
last. Recording the second occurrence is the part that stops a third.
rubenvdlinde added a commit that referenced this pull request Aug 28, 2026
… checked (#623)

TWO SESSIONS FIXED ONE COLLISION AND MADE IT WORSE.

gate-99 was claimed by `manifest-l10n-coverage` and `demo-data-coverage` at
once. #612 moved demo-data-coverage to 101. #615 moved manifest-l10n-coverage
to 101. Both diffs were correct in isolation; together they relocated the
collision from 99 to 101 and left gate-99 orphaned. Nothing noticed until the
same acceptance suite failed again with the number changed:

    FAIL — expected FAIL on planted, got:
    [gate-101] manifest-l10n-coverage: NOT APPLICABLE ...

demo-data-coverage takes 102. manifest-l10n-coverage keeps 101, because #615
says so in its title and its own suite keys on it; mine is the newer claim in
conflict, so mine moves. gate-99 stays vacant rather than being reused: its
history now points at two different gates, and a number that has meant two
things is worse than a gap.

🔴 MY OWN VERIFICATION MISSED IT. After the first renumbering I checked the
`# GATE N — name` COMMENT headers and confirmed "no duplicates". The headers
were distinct (99 and 101) while both gates called `_pass 101`. I verified the
labels and not the behaviour.

So the new check reads the CALL SITES, which are what the report, the COVERAGE
tally and every acceptance suite actually key on. There is a gate-95 for ADR
number collisions and nothing for GATE numbers; this is that check.

Five arms, and ARM 2 reconstructs the exact state that reached main and asserts
both gate names appear in the error. ARM 3 plants distinct headers over
colliding calls — the precise thing my manual check waved through. ARM 4 pins
that a runner with no gates exits 2, because a silent zero is how this class
hides.

81 gates, every number claimed once.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants