Skip to content

Three cc-breaking regressions reached main in one week — a label-gated cc parity check should be a pre-merge gate for runtime/codegen PRs #9346

Description

@proggeramlug

The pattern

Three independent regressions broke claude --help — the primary real-app parity workload — on main within one week. Each shipped with its author's fixtures and unit suites fully green:

break mechanism how it shipped green
#9169 window (fixed by #9247) method dispatch / property lookup regression perf-only on fixtures; only the bundle showed it
#9305 (fixed by #9323) latent setjmp slot-coloring; the window's commits merely introduced the throw that detonated it needs a JS throw inside a microtask — no small corpus had one
#9341 (reverted in #9345) #9326's indexed-write change; trigger is a bundle-scale esbuild shape 88-fixture corpus + 64-check differential all green; the obvious __export mini-fixture passes — only the real bundle fails

The common property: the failing shape exists only at cli.js bundle scale. Unit fixtures cannot be made to cover it by adding more unit fixtures — two of the three triggers resisted deliberate minimization by the people who found them.

The cost side

Each break voids every cc measurement taken against main until attribution completes (a ~40-minute compile per bisect step), and manufactures false blame: whoever next measures their branch on top of broken main sees their own binary fail. This week that cost several sessions repeated multi-hour attribution work — far more compute than the gate below would spend.

Proposal: label-gated, like run-extended-tests

A workflow job cc-parity that:

  1. Triggers on the existing opt-in pattern — a run-cc-parity label (mirroring run-extended-tests), applied to any PR touching crates/perry-runtime/, crates/perry-codegen/, or crates/perry-hir/. (A paths-based auto-trigger is the stronger version, but the label form matches the repo's existing CI-budget conventions and can ship first.)
  2. Builds the toolchain, compiles a pinned cli_2.1.112.js (the bundle is already the de-facto acceptance corpus; pin its sha256 so the gate is deterministic), runs --help and --version under HOME=<scratch>, and asserts: rc=0 and byte-identical stdout vs the pinned node oracle output (checked-in golden bytes — no node needed in CI, no network, no API key; the bundle exits before any credentialed call on these paths).
  3. Budget: one ~25-40 min job, only on labelled PRs. Against the backlog (~29 jobs/merge), this replaces the multi-session bisects each break currently costs.

The golden-bytes detail matters: --help output is 9,175 stable bytes; storing them makes the job hermetic and makes a diff in CI immediately actionable.

Evidence this would have caught all three

Not filing a workflow PR directly because gating policy and CI budget are the maintainer's call; happy to write the workflow if the shape above is acceptable.

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