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
Cut the first Perry release since v0.5.1220. Cargo.toml is at 0.5.1512 — roughly 290 commits have landed untagged.
This ticket is self-contained: it states what the release gate mechanically requires, what is red today, what work closes the gap, and how to execute the release once green. No other context needed.
1. What "release-ready" mechanically means
release-packages.yml is dispatched with cut_release: true on a branch pinned at the release-candidate commit. Its await-tests job then:
dispatches test.yml with tier=full on that ref, and
waits for a run whose full-suite-gate job succeeded on that SHA, and
waits for simctl-tests.yml.
Two consequences people keep tripping on:
A green PR-tier (pr-gate) or post-merge sweep (main-gate) run on the same SHA does NOT count. Only the full tier carries the release-grade suites.
Nothing in the full tier carries continue-on-error any more (ci: restructure CI into PR gate / main sweep / full suite tiers #8187). One red suite blocks the tag. There is no "publish past it" path short of consciously re-adding a job-level continue-on-error: true with an issue number.
Only after that does it tag vX.Y.Z from Cargo.toml, create the GitHub Release, and publish. Tag-LAST — the tag is an output of a green run, not an input.
The full tier
lint, check, warnings, cargo test --workspace, the gap suite (8-shard auto-optimize mode, not the PR tier's prebuilt fast mode), gc-stress, Windows x64 + ARM64, compiler-output-regression, repsel-census, harmonyos-smoke, security-audit, binary-size, parity, compile-smoke, doc-tests (macOS + Windows), the package smokes (drizzle-mysql-smoke, ink-link-smoke, effect-basic-smoke), native-abi-evidence-packet. Benchmark regressions hard-fail on release tags.
parity has its own contract: clear the threshold in test-parity/threshold.json (aggregate ≥ 83%) and add no new / stale known_failures.json entries. The second half is the binding one.
2. Where we actually are
The full tier had been effectively unmeasured for six weeks (tag-gated + continue-on-error before #8187; the one unsharded parity attempt died at GitHub's 6-hour job cap). Since it started reporting, every full-tier run has failed.
Latest nightly (7441e1f73, run 32099242562), still in flight, already red on:
Job
Notes
warnings
recurring — -D warnings, so any new lint is a build failure
cargo-test
gc-stress
compiler-output-regression
effect-basic-smoke
doc-tests (macos-14)
parity shards were still queued at the time of writing.
The dominant debt is #8271: the first complete parity run since 2026-07-04 found 93 new unlisted parity failures + 27 compile failures + 16 crashes, at 90.7% aggregate, against a then-9-entry known_failures.json. That file now has 123 entries, so a large share has been registered — #8271 is still open and is the single biggest item on this ticket.
3. Why this needs a merge freeze
This is the part that has repeatedly defeated a "just fix the list" approach, and it is measurable:
full-suite-gate requires every job green on one SHA. With the tip moving faster than the gate can measure it, there may simply be no such SHA.
Therefore: pin a release-candidate branch off main and land only release-blocking fixes on it. Do not chase green on a moving main.
4. The work
A. Parity debt — #8271 (biggest, mostly triage not debugging)
Every remaining unlisted failure must either be fixed or registered in known_failures.json with an issue number (the provenance policy from #797), and the 3 stale entries removed. #8271 groups them into families, several of which look like one shared cause, so the number of distinct bugs is far below the failure count:
npm-package parity (~15: lodash / moment / dayjs / date-fns / uuid / nanoid / validator / commander / cron / dotenv / decimal / lru_cache / argon2) — "smells like one shared import/oracle change, worth bisecting as a family"
Linux-gtk4 UI compile failures (~15) — fixtures never skip-listed for a host without the toolchain
Bisect each family before fixing individuals.
B. Recurring gate failures
warnings, cargo-test, gc-stress, compiler-output-regression, effect-basic-smoke, doc-tests (macos-14). These need per-run triage; each has been a different root cause across runs, so treat the job name as a symptom, not an issue.
C. Never-yet-green surfaces
simctl-tests.yml is a release gate and I have seen no evidence of a recent green run. binary-size and the benchmark hard-fail arm are also release-only paths. Verify these actually pass before assuming they do — a job that never ran is not a job that passes.
5. Execution, once the candidate is green
Pin a release-candidate branch at the chosen commit.
Land only blocker fixes on it; re-dispatch test.yml with tier=full on that ref after each.
When full-suite-gate succeeds on that SHA and simctl-tests.yml is green, dispatch release-packages.yml with cut_release: true on that branch.
It gates on tests, builds every leg, then creates the tag from Cargo.toml, the GitHub Release, and publishes. Changelog fragments in changelog.d/ fold into the release notes at tag time.
Do not push a tag by hand. The tag is the output of the gate.
One test.ymltier=full run with full-suite-gate: success on the release-candidate SHA
simctl-tests.yml green on that SHA
release-packages.yml dispatched with cut_release: true, tag + Release + npm published
Version bumped and changelog.d/ fragments present for everything since v0.5.1220
Verification note
gh pr checks reports cancelled jobs as fail, and the fan-in job reports failure when its shards are cancelled. Several "red" gates during this effort were cancellations, not test failures. Always confirm a job's own conclusion before treating it as a blocker — and confirm a test actually ran (grep for a positive ... ok, not for the absence of FAILED); a cancelled run silently looks like a passing one.
Goal
Cut the first Perry release since v0.5.1220.
Cargo.tomlis at 0.5.1512 — roughly 290 commits have landed untagged.This ticket is self-contained: it states what the release gate mechanically requires, what is red today, what work closes the gap, and how to execute the release once green. No other context needed.
1. What "release-ready" mechanically means
release-packages.ymlis dispatched withcut_release: trueon a branch pinned at the release-candidate commit. Itsawait-testsjob then:test.ymlwithtier=fullon that ref, andfull-suite-gatejob succeeded on that SHA, andsimctl-tests.yml.Two consequences people keep tripping on:
pr-gate) or post-merge sweep (main-gate) run on the same SHA does NOT count. Only the full tier carries the release-grade suites.continue-on-errorany more (ci: restructure CI into PR gate / main sweep / full suite tiers #8187). One red suite blocks the tag. There is no "publish past it" path short of consciously re-adding a job-levelcontinue-on-error: truewith an issue number.Only after that does it tag
vX.Y.ZfromCargo.toml, create the GitHub Release, and publish. Tag-LAST — the tag is an output of a green run, not an input.The full tier
lint,check,warnings,cargo test --workspace, the gap suite (8-shard auto-optimize mode, not the PR tier's prebuiltfastmode),gc-stress, Windows x64 + ARM64,compiler-output-regression,repsel-census,harmonyos-smoke,security-audit,binary-size,parity,compile-smoke,doc-tests(macOS + Windows), the package smokes (drizzle-mysql-smoke,ink-link-smoke,effect-basic-smoke),native-abi-evidence-packet. Benchmark regressions hard-fail on release tags.parityhas its own contract: clear the threshold intest-parity/threshold.json(aggregate ≥ 83%) and add no new / staleknown_failures.jsonentries. The second half is the binding one.2. Where we actually are
The full tier had been effectively unmeasured for six weeks (tag-gated +
continue-on-errorbefore #8187; the one unshardedparityattempt died at GitHub's 6-hour job cap). Since it started reporting, every full-tier run has failed.Latest nightly (
7441e1f73, run 32099242562), still in flight, already red on:warnings-D warnings, so any new lint is a build failurecargo-testgc-stresscompiler-output-regressioneffect-basic-smokedoc-tests (macos-14)parityshards were still queued at the time of writing.The dominant debt is #8271: the first complete parity run since 2026-07-04 found 93 new unlisted parity failures + 27 compile failures + 16 crashes, at 90.7% aggregate, against a then-9-entry
known_failures.json. That file now has 123 entries, so a large share has been registered — #8271 is still open and is the single biggest item on this ticket.3. Why this needs a merge freeze
This is the part that has repeatedly defeated a "just fix the list" approach, and it is measurable:
maintakes ~58 merges/day (ci: restructure CI into PR gate / main sweep / full suite tiers #8187's own measurement).cargo-test,gc-stress,compiler-output-regressionandwarnings, from different causes.warningsalone has broken, been fixed (fix(runtime): drop the duplicateduse super::*in release_tests #8326), and re-broken (fix(codegen): silence a pre-existing dead_code warning on a test helper #8339) inside 24 hours.full-suite-gaterequires every job green on one SHA. With the tip moving faster than the gate can measure it, there may simply be no such SHA.Therefore: pin a release-candidate branch off
mainand land only release-blocking fixes on it. Do not chase green on a movingmain.4. The work
A. Parity debt — #8271 (biggest, mostly triage not debugging)
Every remaining unlisted failure must either be fixed or registered in
known_failures.jsonwith an issue number (the provenance policy from #797), and the 3 stale entries removed. #8271 groups them into families, several of which look like one shared cause, so the number of distinct bugs is far below the failure count:ink(React-based TUI framework) end-to-end viaperry.compilePackages#348's areajs_jwt_sign_dyn)Bisect each family before fixing individuals.
B. Recurring gate failures
warnings,cargo-test,gc-stress,compiler-output-regression,effect-basic-smoke,doc-tests (macos-14). These need per-run triage; each has been a different root cause across runs, so treat the job name as a symptom, not an issue.C. Never-yet-green surfaces
simctl-tests.ymlis a release gate and I have seen no evidence of a recent green run.binary-sizeand the benchmark hard-fail arm are also release-only paths. Verify these actually pass before assuming they do — a job that never ran is not a job that passes.5. Execution, once the candidate is green
test.ymlwithtier=fullon that ref after each.full-suite-gatesucceeds on that SHA andsimctl-tests.ymlis green, dispatchrelease-packages.ymlwithcut_release: trueon that branch.Cargo.toml, the GitHub Release, and publishes. Changelog fragments inchangelog.d/fold into the release notes at tag time.Do not push a tag by hand. The tag is the output of the gate.
Definition of done
known_failures.jsonentries; aggregate parity ≥ thresholdtest.ymltier=fullrun withfull-suite-gate: successon the release-candidate SHAsimctl-tests.ymlgreen on that SHArelease-packages.ymldispatched withcut_release: true, tag + Release + npm publishedchangelog.d/fragments present for everything since v0.5.1220Verification note
gh pr checksreports cancelled jobs asfail, and the fan-in job reports failure when its shards are cancelled. Several "red" gates during this effort were cancellations, not test failures. Always confirm a job's ownconclusionbefore treating it as a blocker — and confirm a test actually ran (grep for a positive... ok, not for the absence ofFAILED); a cancelled run silently looks like a passing one.