Symptom
repsel-census is failing on main (runs 31295652054 and 31240304595, both failure):
REGRESSION:
fixture_ptr_shape_elements: ptr-shape promoted 0, floor is 3 (-3)
fixture_ptr_shape_elements: ptr-shape-consumed promoted 0, floor is 3 (-3)
The job is not in branch protection's required contexts (its header says promotion was a deliberate follow-up after first landing), so merges proceed over it — CLAUDE.md "four ways a gate can be unable to fail", mode 2.
Localization
The fixture's two read forms isolate cleanly on main @423bb4405 (fresh worktree, debug build):
- Form A (
for (let i = 0; i < rows.length; i++) { const s = rows[i]; … }) — promotes fine on its own.
- Form B (
for (const r of rows) { … }) — promotes zero on its own, method call or not, and its presence in the full fixture voids the whole group (E3: the desugared use of rows is not licensed, so the array loses its facts and the producer is re-denied under rule 2).
Minimal repro (promotes 0; delete the for…of loop and the producer promotes):
class Row {
id: number; weight: number; score: number;
constructor(id: number, weight: number) { this.id = id; this.weight = weight; this.score = 0; }
}
function build(n: number): number {
const rows: Row[] = [];
for (let i = 0; i < n; i++) { const row = new Row(i, i * 0.5); rows.push(row); }
let total = 0;
for (const r of rows) { total = total + r.weight; }
return total;
}
console.log("b:" + build(6));
collectors/ptr_shape_elements.rs licenses the iterator form by matching the desugar's exact shape (module doc: "for (const r of A) desugars to exactly the E5 shape — a __idx local, __idx < __arr.length, Let r = IndexGet(__arr, __idx)"), and the fixture's own header predicted this failure: "If the desugar ever changes, this fixture's count drops and the gate goes red — which is the point." The gate went red; it just could not block. Suspect a change to lower/stmt_loops.rs::lazy_or_index_elem (or the alias binding it emits — e.g. a now-mutable __arr falls out of collect_alias_edges' mutable: false requirement and the bare LocalGet(rows) in its init disqualifies the array).
Found while
Validating #7770 / PR #7774 (element-group numeric proof): the census caught the drop; A/B on a pristine main worktree shows the branch and main behave identically (and the PR's indexed-form claims are unaffected — form A promotes with all three fields claimed under #7774).
Two follow-ups suggested: bisect main for the desugar change, and promote repsel-census to a required context once green (its header says exactly this).
Symptom
repsel-censusis failing onmain(runs 31295652054 and 31240304595, bothfailure):The job is not in branch protection's required contexts (its header says promotion was a deliberate follow-up after first landing), so merges proceed over it — CLAUDE.md "four ways a gate can be unable to fail", mode 2.
Localization
The fixture's two read forms isolate cleanly on main @423bb4405 (fresh worktree, debug build):
for (let i = 0; i < rows.length; i++) { const s = rows[i]; … }) — promotes fine on its own.for (const r of rows) { … }) — promotes zero on its own, method call or not, and its presence in the full fixture voids the whole group (E3: the desugared use ofrowsis not licensed, so the array loses its facts and the producer is re-denied under rule 2).Minimal repro (promotes 0; delete the
for…ofloop and the producer promotes):collectors/ptr_shape_elements.rslicenses the iterator form by matching the desugar's exact shape (module doc: "for (const r of A)desugars to exactly the E5 shape — a__idxlocal,__idx < __arr.length,Let r = IndexGet(__arr, __idx)"), and the fixture's own header predicted this failure: "If the desugar ever changes, this fixture's count drops and the gate goes red — which is the point." The gate went red; it just could not block. Suspect a change tolower/stmt_loops.rs::lazy_or_index_elem(or the alias binding it emits — e.g. a now-mutable__arrfalls out ofcollect_alias_edges'mutable: falserequirement and the bareLocalGet(rows)in its init disqualifies the array).Found while
Validating #7770 / PR #7774 (element-group numeric proof): the census caught the drop; A/B on a pristine main worktree shows the branch and main behave identically (and the PR's indexed-form claims are unaffected — form A promotes with all three fields claimed under #7774).
Two follow-ups suggested: bisect main for the desugar change, and promote
repsel-censusto a required context once green (its header says exactly this).