Skip to content

CI: required contexts lint and cargo-test are red for every PR (and lint on main itself), so every merge bypasses them #8092

Description

@proggeramlug

Summary

Two required status contexts, lint and cargo-test, currently fail for every pull request, including on trees that change nothing related to them. lint also fails on a pristine origin/main checkout. While that holds, neither context can distinguish a good PR from a bad one, and every merge necessarily goes through admin bypass.

This is the CLAUDE.md "★ four ways a gate can be unable to fail" pattern in its most expensive form: the jobs run, genuinely report failure, and are required — so the only way to land anything is to ignore them, which trains the team to ignore them for the PR that actually broke something.

lint is red on main itself

Reproduced locally on a clean detached worktree at origin/main = 506f4ab11a5d2a1b7a498e965c79d11e2fa63043, running the exact commands from test.yml:

$ ./scripts/check_file_size.sh
File size limit exceeded (2000 lines).
   2010  crates/perry-runtime/src/timer.rs

$ python3 scripts/gc_store_site_inventory.py
GC store-site inventory failed; add nearby GC_STORE_AUDIT markers:
  crates/perry-codegen/src/expr/property_set.rs:1475: raw generated heap/global store: blk.store(DOUBLE, &numeric_value, &field_ptr);

$ python3 scripts/raw_handle_debt.py
bare raw-handle reads: 996 (baseline 998)
per-module raw-handle rules: 2 violation(s)
  crates/perry-runtime/src/json_tape.rs: 22 bare reads exceeds its ceiling of 21
  crates/perry-runtime/src/object/spill.rs: 5 bare reads exceeds its ceiling of 3

All three are independent of any open PR. Note the global raw-handle count (996) is below its baseline (998) — it is the per-module rules that fail, which is exactly the failure mode raw_handle_debt_files.txt was designed to catch, so the gate is working correctly and the debt is real.

cargo-test fails identically on unrelated PRs

The same four tests fail on #8086 (73-file ShapeId change), #8090 (small typed-array fix), and #8087 (CI gates):

inprocess::tests::rs4gc_canonicalizes_construction_time_folds_before_root_liveness
native_emit::tests::native_construction_lowers_precise_roots_before_rs4gc
native_emit::tests::split_native_construction_lowers_precise_roots_before_rs4gc
native_emit::tests::split_native_construction_propagates_shadow_backend_to_workers

Byte-for-byte the same set on all three. These assert that two compilation arms produce byte-identical objects. Decoding the assertion dumps, the arms differ only in an embedded module/source name:

test control arm native arm
rs4gc_canonicalizes_… .file "constant_fold_text" .file "constant_fold_native"
native_construction_… ELF STT_FILE = perry_llvm_7386555fbfde02f7.ll ELF STT_FILE = perry_native_module

The generated code, stack maps, and PGCM payloads appear identical; the delta is the name each arm records for its translation unit. compile_ll_to_object routes through a scratch perry_llvm_<hash>.ll, while the in-process native arm names its module perry_native_module.

This is consistent with the platform split: both ELF arms of native-roots-rs4gc fail, while macOS/Mach-O and Windows/PE pass — Mach-O and PE do not carry an STT_FILE-style source-name symbol, so the difference is invisible there.

I have not bisected which change introduced this, and I have not confirmed it on a pristine main build (it does not reproduce on macOS, which is the only host I measured on). What is established is that it is not caused by any of the three PRs above.

Also red across the same unrelated PRs

Not diagnosed here, listed so the scope is not understated — every one of these is red on both #8086 and #8090:

gc-stress, ext-link, compiler-output-regression, e2e-scoped, gc-native-roots-complete, gc-root-dominance-statepoints, windows-arm64-build, Warnings (host-compatible), Warnings (product), and both ELF native-roots-rs4gc arms.

The last run of test.yml to conclude success on any branch was 2026-07-24.

Why this is worth fixing before more merges

A required-and-always-red context is strictly worse than no context: it is indistinguishable from a gate that is doing its job, it forces bypass as the normal path, and the bypass is what lands the next real regression. #6925's PERRY_PTR_SHAPE_LOCALS=0 regression landed visibly red and survived three merges for exactly this reason.

Suggested split

  1. Land the three lint fixes against main directly — timer.rs is 10 lines over the cap, property_set.rs needs one GC_STORE_AUDIT marker, and json_tape.rs/object/spill.rs each need one converted pair (which also lowers their ceilings, per the file's own "lower a ceiling whenever you convert a pair" rule).
  2. Decide whether the four byte-identity tests should compare normalized objects (masking the translation-unit name) or whether both arms should name the module identically. A byte-identity assertion whose only observed delta is a filename is testing the filename.
  3. Triage the remaining red jobs separately; several may share the ELF/STT_FILE root cause.

Refs #7737 (gate promotion), #8085 (gate freshness).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions