You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
gc-root-dominance.yml has been red at --audit-poll-reach since 2026-08-15, so its corpus and checker never run #8821
gc-root-dominance.yml is structurally unable to report on the thing it exists to check. Over the last 60 runs:
58 skipped
2 failure
0 success
Both failures are scheduled main runs, and both die at the same early step — before the corpus is ever emitted:
run 32820308411 (2026-08-25 07:10, schedule)
job: gc-root-dominance step FAILED: ALLOC_RE symbols that reach a poll-capable one must be listed
job: gc-root-dominance-statepoints step FAILED: ALLOC_RE symbols that reach a poll-capable one must be listed
That is the --audit-poll-reach audit. It exits 2 on all recent scheduled main runs. Every pull_request run is skipped (the job is label-gated behind run-extended-tests).
Consequence
The corpus step (scripts/gc_root_dominance_corpus.sh) and the checker step (scripts/gc_root_dominance_check.py) have never executed in CI. So neither of these has ever been observable at any profile:
CLAUDE.md enumerates four ways a gate can be unable to fail. This hits two of them simultaneously — not in branch protection's required contexts (label-gated, so skipped on every PR) and the gate runs but its subject never did (the one path that does run stops before reaching its subject). A third is arguably in play: a skipped check satisfies a required context.
What needs deciding
Fix the --audit-poll-reach failure so the workflow can proceed to its actual subject, or split that audit into its own job so an unrelated failure cannot mask the corpus and checker.
Decide whether this gate should be label-gated at all. A GC-rooting dominance check that never runs on a PR cannot prevent the class of bug it was written for — and docs/src/internals/gc-rooting-invariant.md describes that class as one this project has shipped repeatedly.
Correcting this issue — the headline claim is wrong, and it was my measurement error.
I wrote "0 success / 58 skipped / 2 failure in 60 runs" and concluded the gate had never reached its corpus step. That figure came from an unfiltered gh run list --workflow=gc-root-dominance.yml --limit 60, which returns the newest 60 runs across all branches — and nearly all of those are label-skipped pull_request runs. It was never a view of main.
Filtered properly:
$ gh run list --workflow=gc-root-dominance.yml --branch main --limit 60 --json conclusion
47 failure
5 success
8 cancelled
Last green on main is run 31870805900 (2026-08-15T06:59Z), which printed corpus (shadow): 144/144 sources compiled and === violations: 0.
The corrected — and more actionable — picture
The gate is red for 10 days, not forever. It worked, it reached its subject, and it was clean. The first failure after that green run is 2026-08-15T13:00Z, and every scheduled run since dies at --audit-poll-reach ("ALLOC_RE symbols that reach a poll-capable one must be listed") before reaching the corpus.
This makes the situation worse, not better, in one specific way: because 2026-08-15 is a clean 0-violation reference, the violations reported in #8809 are new regressions that landed during the dark window — not pre-existing debt as I characterised them there.
What remains true from the original report: the job is label-gated behind run-extended-tests, so it is skipped on every PR and cannot block a merge. That is still worth deciding on — a GC-rooting dominance check that cannot go red on a PR did not stop the two regressions #8809 identifies from landing.
Retitling accordingly. Apologies for the noise; the underlying "this gate has been unable to report for 10 days" concern stands, but my numbers did not support the claim I made.
changed the title [-]gc-root-dominance.yml has never reached its corpus step: 0 success / 58 skipped / 2 failure in 60 runs[/-][+]gc-root-dominance.yml has been red at --audit-poll-reach since 2026-08-15, so its corpus and checker never run[/+]on Aug 25, 2026
Item 1 is fixed in #9012 (merged). Leaving this open for items 2 and 3.
One correction to the timeline above. The 2026-08-15 red was the third wave, and #8823 cleared it on 08-25. What is red now is a fresh recurrence: #8965 added js_string_concat_value_box on 2026-08-28 without listing it, and the audit went red the same day. So this is not one continuous fourteen-day breakage — it is the same pattern happening twice, which strengthens rather than weakens the argument here.
That symbol was a plain omission, not a judgement call: it is the exact analogue of js_string_concat_box listed directly above it (SSO fast arm, then js_string_concat_value as the fallback at string/concat.rs:496), and that callee was already in the list.
Also took the cheap half of item 2. Rather than un-label-gating the whole workflow, #9012 runs --audit-poll-reach (plus --self-test) in lint, which is a required context. It is static, build-free and 0.6 s, so it costs nothing there — and it is the same placement argument the runtime GC-pointer holder audit already makes a few steps above it in test.yml. Had it been there, #8965 would have been told at PR time instead of reddening a scheduled run.
What is still open:
Whether the corpus and checker arms should stay label-gated. That is the expensive half and a real decision — un-gating it makes every PR pay for a compiler build plus IR emission, and per this repo's own rule a gate that has never been green cannot be promoted straight to required. It also cannot be judged until 3.
Worth noting the structural point in the issue still stands independently of the fix: an early static step that can fail is sitting in front of the expensive subject, so any future omission masks the corpus again. Splitting the three static audits into their own job would remove that coupling for good; I did not do it here because it changes the workflow's job graph and interacts with the item-2 decision.
Still open and still accurate in its conclusion — gc-root-dominance is dark — but the failure modes have changed twice since this was written, so the body no longer describes what is happening. Verified on main@12efed1222 today.
--audit-poll-reach is green now. The failure this issue documents ("ALLOC_RE symbols that reach a poll-capable one must be listed") no longer reproduces:
and greps it for pub(crate) const STATEPOINT_REWRITE_PASSES. A file-cap split moved that constant to crates/perry-codegen/src/linker.rs:37; inprocess.rs now only does use crate::linker::STATEPOINT_REWRITE_PASSES;. The read returns empty, the script exits 2, no ir-corpus-native artifact is produced ("No files were found with the provided path: ir-corpus-native"), and the job dies before the corpus exists.
The script's own perl regex matches the new location unchanged:
So the fix is the src path. Worth noting the comment directly above that read says the single-sourcing exists "so formatting cannot silently disconnect this corpus from production's pass pipeline" — a moved file did exactly what the comment was written to prevent, because the path is trusted rather than searched. Suggest failing loudly when the constant is found in no file, rather than trusting one hard-coded path.
2. gc-root-dominance fails a corpus-size floor while reporting zero violations.
error: checked 5625 function(s), need at least 6000. The corpus compiled but is
too thin to have exercised the lowerings this invariant runs through.
=== violations: 0 (moving-minor reachable: 0)
=== seeded violations: 40 planted, 40 caught, 0 MISSED
The invariant is clean and its sabotage arm is working — 40 planted, 40 caught. Only the floor is unmet. Either the dependency corpus shrank (which is the finding the floor exists to surface, in which case say which sources were lost) or the floor needs recalibrating. The script's own comment distinguishes "corpus shrank" from "sources failed to compile" as two different failures with two different messages; the current message conflates them.
Both are gate-maintenance defects rather than product regressions, which is exactly why they have survived: the workflow is not a pr-gate context, so nothing blocks on it, and it has now been red on every main run since 2026-08-31.
Cross-link: the live bot alert for this gate is #9925. Per the last comment here, the original --audit-poll-reach failure no longer reproduces, so the body could be refreshed to describe the current failure mode.
The original --audit-poll-reach failure no longer reproduces (see the last comments), and the live alert for this gate is tracked in #9925. Closing as superseded by #9925.
Activity
proggeramlug commentedon Aug 25, 2026
Correcting this issue — the headline claim is wrong, and it was my measurement error.
I wrote "0 success / 58 skipped / 2 failure in 60 runs" and concluded the gate had never reached its corpus step. That figure came from an unfiltered
gh run list --workflow=gc-root-dominance.yml --limit 60, which returns the newest 60 runs across all branches — and nearly all of those are label-skippedpull_requestruns. It was never a view ofmain.Filtered properly:
Last green on
mainis run 31870805900 (2026-08-15T06:59Z), which printedcorpus (shadow): 144/144 sources compiledand=== violations: 0.The corrected — and more actionable — picture
The gate is red for 10 days, not forever. It worked, it reached its subject, and it was clean. The first failure after that green run is 2026-08-15T13:00Z, and every scheduled run since dies at
--audit-poll-reach("ALLOC_RE symbols that reach a poll-capable one must be listed") before reaching the corpus.This makes the situation worse, not better, in one specific way: because 2026-08-15 is a clean 0-violation reference, the violations reported in #8809 are new regressions that landed during the dark window — not pre-existing debt as I characterised them there.
What remains true from the original report: the job is label-gated behind
run-extended-tests, so it isskippedon every PR and cannot block a merge. That is still worth deciding on — a GC-rooting dominance check that cannot go red on a PR did not stop the two regressions #8809 identifies from landing.Retitling accordingly. Apologies for the noise; the underlying "this gate has been unable to report for 10 days" concern stands, but my numbers did not support the claim I made.
[-]gc-root-dominance.yml has never reached its corpus step: 0 success / 58 skipped / 2 failure in 60 runs[/-][+]gc-root-dominance.yml has been red at --audit-poll-reach since 2026-08-15, so its corpus and checker never run[/+]fix(gc): unblock the poll-reach audit and run it on every PR (#9012)
proggeramlug commentedon Aug 29, 2026
Item 1 is fixed in #9012 (merged). Leaving this open for items 2 and 3.
One correction to the timeline above. The 2026-08-15 red was the third wave, and #8823 cleared it on 08-25. What is red now is a fresh recurrence: #8965 added
js_string_concat_value_boxon 2026-08-28 without listing it, and the audit went red the same day. So this is not one continuous fourteen-day breakage — it is the same pattern happening twice, which strengthens rather than weakens the argument here.That symbol was a plain omission, not a judgement call: it is the exact analogue of
js_string_concat_boxlisted directly above it (SSO fast arm, thenjs_string_concat_valueas the fallback atstring/concat.rs:496), and that callee was already in the list.Also took the cheap half of item 2. Rather than un-label-gating the whole workflow, #9012 runs
--audit-poll-reach(plus--self-test) inlint, which is a required context. It is static, build-free and 0.6 s, so it costs nothing there — and it is the same placement argument the runtime GC-pointer holder audit already makes a few steps above it intest.yml. Had it been there, #8965 would have been told at PR time instead of reddening a scheduled run.What is still open:
mainrun should be the first time the corpus and checker actually execute — that run is the thing to read before deciding item 2.Worth noting the structural point in the issue still stands independently of the fix: an early static step that can fail is sitting in front of the expensive subject, so any future omission masks the corpus again. Splitting the three static audits into their own job would remove that coupling for good; I did not do it here because it changes the workflow's job graph and interacts with the item-2 decision.
proggeramlug commentedon Sep 5, 2026
Still open and still accurate in its conclusion —
gc-root-dominanceis dark — but the failure modes have changed twice since this was written, so the body no longer describes what is happening. Verified onmain@12efed1222today.--audit-poll-reachis green now. The failure this issue documents ("ALLOC_RE symbols that reach a poll-capable one must be listed") no longer reproduces:Anyone picking this up from the body above would chase a fixed problem. The two failures that keep the workflow red today are different:
1.
gc-root-dominance-statepointsreads a constant from a file it no longer lives in.scripts/gc_root_dominance_corpus.sh:209hard-codes:and greps it for
pub(crate) const STATEPOINT_REWRITE_PASSES. A file-cap split moved that constant tocrates/perry-codegen/src/linker.rs:37;inprocess.rsnow only doesuse crate::linker::STATEPOINT_REWRITE_PASSES;. The read returns empty, the script exits 2, noir-corpus-nativeartifact is produced ("No files were found with the provided path: ir-corpus-native"), and the job dies before the corpus exists.The script's own perl regex matches the new location unchanged:
So the fix is the
srcpath. Worth noting the comment directly above that read says the single-sourcing exists "so formatting cannot silently disconnect this corpus from production's pass pipeline" — a moved file did exactly what the comment was written to prevent, because the path is trusted rather than searched. Suggest failing loudly when the constant is found in no file, rather than trusting one hard-coded path.2.
gc-root-dominancefails a corpus-size floor while reporting zero violations.The invariant is clean and its sabotage arm is working — 40 planted, 40 caught. Only the floor is unmet. Either the dependency corpus shrank (which is the finding the floor exists to surface, in which case say which sources were lost) or the floor needs recalibrating. The script's own comment distinguishes "corpus shrank" from "sources failed to compile" as two different failures with two different messages; the current message conflates them.
Both are gate-maintenance defects rather than product regressions, which is exactly why they have survived: the workflow is not a
pr-gatecontext, so nothing blocks on it, and it has now been red on everymainrun since 2026-08-31.tooling(gc): enforce the column-0 precondition in a REQUIRED context
tooling(gc): enforce the column-0 precondition in a REQUIRED context
tooling(gc): enforce the column-0 precondition in a REQUIRED context
TheHypnoo commentedon Sep 28, 2026
Cross-link: the live bot alert for this gate is #9925. Per the last comment here, the original
--audit-poll-reachfailure no longer reproduces, so the body could be refreshed to describe the current failure mode.proggeramlug commentedon Oct 12, 2026
The original --audit-poll-reach failure no longer reproduces (see the last comments), and the live alert for this gate is tracked in #9925. Closing as superseded by #9925.