Uh oh!
There was an error while loading. Please reload this page.
ci(devx): label-gated opt-in pre-merge pack smoke - #14266
Conversation
Add a `pull_request` trigger that runs the existing pack-install smoke on a PR's merge preview while the PR carries `needs:pack-smoke`. The pack smoke previously ran only on `workflow_run` after a Release run, so its verdict landed as a commit status on the changesets release branch head -- a surface no PR author reads. A breaking auth/audience change therefore merged with zero packed-install coverage on its own PR, and the smoke then sat red on the release candidate for ~7 days. This adds the trigger only. The driver, its probes and every assertion in scripts/publish-smoke.sh are untouched: re-pinning those to the declared first-run contract was a separate deliverable that has already landed. Opt-in by ruling -- an unlabelled PR pays no new cost. The guard's second limb keeps an unrelated label add (size/*, ci/cd) from restarting a 45-minute smoke, and the concurrency group sits at job level so a run that skips can never cancel a run that is really smoking. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
Demonstration run — all three arms observed live on this PRThe trigger demonstrating itself. Three
The middle row is the one that would otherwise be easy to get wrong and impossible to notice: without that limb, every Note the smoke here exercises the merge preview of this PR, whose diff is CI wiring only — so its eventual colour demonstrates the trigger, not any auth/audience behaviour. Per the dispatch contract the report is filed at draft-PR time rather than waiting for the ~45-minute run to converge; the run above is cited at Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#14214
Adds the missing trigger for the packed-install smoke: while a PR carries
needs:pack-smoke, CI runs the existing pack smoke against that PR's merge preview, before the merge, as a check run the author already reads.Derived from the maintainer-approved ruling on #14000 (2026-09-01, director batch #23, 「同意」; the follow-up recommendation 「label 门控 opt-in」 was the one approved).
Premise re-check (done first, on fresh
origin/main)The card's premise holds. Verified at base
035951faf:git grep -n 'labeled' -- .github/workflows/returns nolabeledtrigger anywhere — every hit is prose, orpr-automation.ymlexplicitly excludinglabeled/unlabeledfrom its jobs. There was no pre-merge pack-smoke trigger of any kind to collide with.publish-smoke.ymltriggerson: workflow_run: workflows: [Release], resolves the openchangeset-release/mainPR, and reportspublish-smoke / packed-tarballsas a commit status on the release branch head. That is a release surface, not a PR surface — which is the whole gap.035951fa), so the driver reused here is the re-pinned one.Driver-contract verification (read off the driver, not invented)
Verified in
scripts/publish-smoke.shrather than assumed:bash scripts/publish-smoke.sh— identical topublish-smoke.yml's pack-smoke stepSMOKE_MODEdefaults topack, so no env is neededpackages/cli/distand the create-objectstack bin exist, i.e.pnpm install+pnpm run buildmust precede itREPO_ROOT, resolved from the script's own location — whatever tree is checked outThe merge preview is a valid target and needs no plumbing. The one risk worth checking was whether pack mode assumes a release-branch layout the preview lacks; it does not. The release-branch coupling in
publish-smoke.ymllives entirely in itsresolvejob (finding the release PR and areport-shato post a status to), never in the driver. Onpull_requestthe defaultactions/checkoutref is alreadyrefs/pull/N/merge, and the check run lands on the PR itself — so this workflow needs noresolvejob, noresolve-guard, and nostatuses: write. It runs withcontents: readonly. No driver changes were required, and none were made.Scope boundaries, honoured
scripts/publish-smoke.shhas zero changes in this PR — re-pinning the assertions was The release candidate has failed its fresh-install smoke for ~18h — POST /auth/sign-up/email returns 403 SELF_REGISTRATION_CLOSED (and the check-run is NOT about main) #14000's deliverable and landed in fix(devx): re-pin the publish smoke to the declared first-run contract #14255. This card is only about when the smoke runs.Design decisions worth review
labeledevent the label just added must be ours. Without the second limb every unrelated label the size labeler adds (size/l,ci/cd) to an already-labelled PR would start another 45-minute smoke of an unchanged tree.concurrencyis at JOB level, deliberately. At workflow level the group is taken by every run the workflow starts — including runs whose job then skips — so an unrelatedlabeledevent would cancel a smoke that was still running and then skip, leaving the PR with no verdict. That is the The release candidate has failed its fresh-install smoke for ~18h — POST /auth/sign-up/email returns 403 SELF_REGISTRATION_CLOSED (and the check-run is NOT about main) #14000 silence shape (a missing answer reading as a green one) rebuilt inside its own fix. A skipped job never enters a job-level group.types:restates the three defaults alongsidelabeled, because namingtypes:replaces rather than extends the default set (check-required-contexts asserts nopaths:on the pull_request trigger but nothing abouttypes:— a dropped default activity type is the same permanent-pending failure, unguarded #8304).merge_group:trigger, and that is not an oversight. Amerge_groupevent carries nopull_requestcontext, so neither guard limb can be evaluated there; and the ruling puts this cost pre-merge and opt-in, not in the queue. The job is correspondingly not a required context — it is advisory by design, and a PR that never opts in never produces it.The label
needs:pack-smokedid not exist. It was created on this repo (colour006b75, description 94 chars), and — more importantly — declared inscripts/pm/ensure-pm-labels.sh, the repo's only declared home for a label object. An undeclared label is the grey / empty-description drift that file's header describes: auto-created by its first application and unrepairable by any rerun. Declaring it also puts its description undercheck:pm-label-desc-cap.The added comment states plainly that this is the first row in that file that is not part of the PM state machine — it is written by the PR author about their own diff, names a property of the change rather than a position on the board, and no sweep in
scripts/pm/reads it.⛔ It is never auto-applied: no
.github/labeler.ymlrule, by design. Path-derived application would be a different design from the one ruled, and would put the ~45-minute cost back into the default inner loop the ruling kept it out of.Documentation line
One line in
CONTRIBUTING.md's "Before Submitting" checklist — where a PR author actually meets it — carrying the ruling's criterion verbatim in substance: the PR changes the auth/audience defaults or the accept/reject behaviour of the unauthenticated surface.Residual risk, stated rather than hidden
Self-declaration only covers the author who recognises their change as breaking. An author who does not realise they widened the unauthenticated surface still gets no pre-merge pack coverage; the release-time leg remains the backstop for that case. Closing that would need a detection rule — a different card and a different ruling. This is written into the workflow header too, so the next reader does not mistake the opt-in shape for full coverage.
Checks
Gate families derived mechanically from the real changeset —
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(no hand-written path list) — which named 31 families; harvested with--commandsand all 31 run.scripts/check-test-completeness.mjsexits 3 with no test log to read, and says so itself: "the local reading for this gate is NOT MEASURED … ⛔ It is not a red, and there is nothing here to fix." CI tees it a real log and passes the path, so that branch is unreachable there.Re-run union on the final commit
820a49923(12 families, all green), quoting each gate's own verdict line:Plus
pnpm check:ratchet-remedy-authority(green: 183 scripts swept) andpnpm check:pm-dispatch-gates(green: 1140 self-test cases), both requested for thescripts/**touch.The new workflow was also parsed with the repo's own
yamllibrary to confirmon:did not fall into the YAML-1.1truetrap and that the guard expression survives folding intact.Releases nothing (
.github/,scripts/pm/,CONTRIBUTING.md), soskip-changesetis applied per the Check Changeset step's own route 2.Demonstration run
needs:pack-smokeis applied to this draft PR so the new job fires on it — the trigger demonstrating itself. The run is cited in a follow-up comment once it has a URL. Note the smoke exercises the merge preview of this PR, whose diff is CI wiring only, so a green here demonstrates the trigger, not any auth/audience behaviour.⛔ Draft on purpose — not to be marked ready by an agent.
Generated by Claude Code