Skip to content

chore: merge train 243 (v0.5.1622) - #10838

Merged
proggeramlug merged 5 commits into
mainfrom
train243r
Sep 20, 2026
Merged

proggeramlug merged 5 commits into
mainfrom
train243r

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

Merge train 243 — the last compiler-output-regression blocker, released as v0.5.1622.

Contents

source Change
#10804 fix(codegen): point the module-global Ptr<Shape> denial at #10803, not closed #7109
#10782 ci: give compiler-output-regression's cold runtime builds their own budget

What was still red, and why it is the last one

compiler-output-regression is a main-gate input and has been red for weeks. As of v0.5.1618 its structural verdicts are all fixed — failed_workloads: [] — and the only remaining failure was 2 × TimeoutExpired on h1_native_rep_equivalence, which is the residual recorded when #10782 was closed: that fix suppressed auto-optimize on the HIR probe but deliberately not on the linking compile, so the 343 s cold build simply moved into a different 300 s budget.

The exclusion had to stand. runtime_budgets' allocations_traced / gc_collections_traced / write_barriers_traced are derived solely from the executed binary's PERRY_GC_TRACE stderr, and optimized_libs/freshness.rs:288-293 adds perry-runtime/diagnostics to the rebuild because the compiler sees that variable — a derivation that only runs on the auto-optimize branch. Those budgets are maxima, so a runtime emitting no trace scores 0 and passes all three vacuously.

So the fix pays the cold build in a step of its own, before the gates.

Two cold builds, not one

This is the part worth reading. The obvious design warms once. It is wrong:

The perry-auto-<hash> directory name excludes the cross-feature set, but the build stamp inside it includes it. The harness sets PERRY_GC_TRACE=1 only for workloads carrying *_traced budgets, and that variable adds perry-runtime/diagnostics. loop_bound_semantics is the one gated workload with no *_traced budget — so it wants the other feature set, hits a stamp mismatch, and re-runs cargo. A single-warm design would have left exactly one gate step to absorb a cold build.

The step therefore warms both, then verifies.

It asserts it actually warmed — twice

A pre-warm that silently no-ops is worse than none: the gates then fail exactly as before while looking warmed. Two independent assertions:

  1. Presence — a target/perry-auto-*/ holding both a build stamp and a non-empty libperry_runtime.a, or ::error::pre-warm warmed nothing and exit 1.
  2. Effect — a third verification compile whose duration must be under half the 300 s budget every gate step runs under, or an explicit error saying auto-optimize is still rebuilding.

The second is the one that discriminates. Presence can pass on a stale or partial directory; "a compile after warming still took 150 s" measures the property directly.

A gate caught the new step, which is the gate working

The first validation aborted at lint:

post-build subject inventory drifted; expected [9 steps] found [10 steps]

scripts/compiler_output_step_liveness.py pins that job's post-build step inventory. Registered in COMPILER_SUBJECTS rather than exempted — it depends on the build and already carries the matching if: guard, so a sibling failure cannot hide it. Gate now passes at 10 subjects, and its own self-test still passes at 8 cases, which was checked separately: a registry edit that broke the checker would be worse than the drift.

Listing it matters beyond satisfying the check. The pre-warm carries its own liveness assertions and can fail, so it is a subject; were it ever silently removed, every gate step below would quietly inherit the timeout it exists to prevent, and the failure would look exactly like the red it just fixed.

Provenance

The #10782 work was produced by an agent that died on an authentication error after committing but before pushing. The commit was recovered locally, rebased twice as main moved beneath it, and pushed. Because it never reached lint, the workflow change was verified here instead: test.yml parses at 28 jobs, the pre-warm sits at step 10 with all seven gates at 11–17, and ci_plan.py --self-test passes.

Validation

Assembled on e2a0839074; both source heads asserted fresh; PR fully represented — zero missing insertions; no attribution trailers. Ten cheap gates, cargo check --workspace --all-targets under -D warnings, all five pinned artifacts byte-identical before and after, six unit suites with an empty failing set, and lint complete at 6-of-6 with nothing outside the known-red public-baseline step on the re-run.

Both compiler-output suites at failed_workloads=[]; repsel_census rc=0 wasted_promotion=False.

Gap sweep at PERRY_RUN_TIMEOUT=30, six areas weighted to #10804's Ptr<Shape> surface, 197 fixtures, every area asserted live, zero unexplained regressions:

class 84   gc_ 54   shape 23   property 18   module 14   const_ 4

Ralph Küpper added 5 commits September 20, 2026 19:54
…udget

`compiler-output-regression` is a `main-gate` input and has been failing
with `TimeoutExpired` on `h1_native_rep_equivalence`, the head of both
proof suites, so every merge bypasses it.

`perry compile` resolves `optimized_libs` unconditionally
(`run_pipeline.rs:6169`), hundreds of lines before `--no-link`'s early
return, so the first linking compile in the job blocks on a nested
`cargo build --release -p perry-runtime-static -p perry-stdlib-static`.
#10782 moved that off the harness's `--print-hir --no-link` probe but
deliberately not off the linking compile, whose executed binary is where
`runtime_budgets`' `*_traced` maxima come from -- suppressing it there
would pass them vacuously. So the build only changed which 300s
`--compile-timeout` it did not fit inside.

Pre-warm before the gates instead, with `--skip-run --compile-timeout
2400`. It is TWO cold builds, not one: all gated workloads share one
`target/perry-auto-<hash>/`, but the build stamp inside it keys on the
cross-feature set, and `loop_bound_semantics` is the only gated workload
with no `*_traced` budget -- so the harness leaves `PERRY_GC_TRACE`
unset for it and it wants a runtime without `perry-runtime/diagnostics`.
Measured with a debug compiler on an M-series mini: 244.6s and 242.1s
respectively, each against 300s; warming one variant only moves the
timeout to the other workload.

Two assertions, because a pre-warm that silently no-ops is worse than
none -- `perry compile` exits 0 when auto-optimize fails and falls back
to prebuilt libraries. One requires a stamped `target/perry-auto-*/`
holding a non-empty `libperry_runtime.a` (the directory alone proves
nothing: cargo creates it before building into it). The other reads the
third pre-warm's own compile duration, which flips the stamp and is only
cheap if both variants are cached.

Validated on a cleared `target/perry-auto-*`: pre-warm 476s exit 0
("post-warm flip compile: 4.0s"), then both suites pass with
`failed_workloads: []` and a slowest gated compile of 6.0s -- with
`loop_bound_semantics` down from 242.1s to 3.0s and `native-region-proof`
from 294s to 58s. Both assertions were sabotage-checked back to red.
`gc_trace_unavailable` is False on all 23 suite workloads, i.e. the
executed binaries still report `perry-runtime/diagnostics` compiled in,
so the #10782 exclusion is intact and the budgets are not vacuous.
@proggeramlug
proggeramlug merged commit ba303c1 into main Sep 20, 2026
25 of 26 checks passed
@proggeramlug
proggeramlug deleted the train243r branch September 20, 2026 19:28
@coderabbitai

coderabbitai Bot commented Sep 20, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 21b35959-6900-4b0d-a92c-58c8c34b9bb8

📥 Commits

Reviewing files that changed from the base of the PR and between e2a0839 and 473ea9b.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • .github/workflows/test.yml
  • CLAUDE.md
  • Cargo.toml
  • changelog.d/10782-prewarm-compiler-output.md
  • changelog.d/10782-step-liveness-registry.md
  • changelog.d/10804-stale-denial-issue-pointer.md
  • crates/perry-codegen/src/expr/slot_rep.rs
  • scripts/compiler_output_step_liveness.py
 _______________________________________________________
< Once upon a dream, I found all the bugs in your code. >
 -------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

repsel: module-init / program-entry bodies are excluded from canonical i32+Str selection, so a top-level hot loop promotes nothing

1 participant