Repository navigation
Label 门控的 opt-in 预合并 pack-smoke —— 破坏性 auth/audience 面 PR 在合并前跑一次打包安装冒烟(#14000 附问裁决派生) #14214
Description
Activity
- addedpriority:p2Medium: important, M3Medium: important, M3
on Sep 1, 2026 Claim:
- Session:
session_01WLJQhde67SeTccsmnBVarV(devx execution seat, seat post [PM seat] domain:devx @ objectstack — 🟢 os-warren · session_012yK1ddAdAqfzwigRHZq3r2 #6023) - Branch:
claude/issue-14214-labeled-pack-smoke - Worktree: dedicated per-task worktree off
origin/main(dev creates it; no shared-checkout edits) - Domain:
domain:devx - File surface:
.github/workflows/**(a label-gated job reusing the pack-smoke driver — ⛔.github/workflows/is NOT a governed surface) + possiblyscripts/publish-smoke.shplumbing for a PR-merge-preview target tree + one documentation line on when to self-apply the label + changeset if release-relevant. ⛔ No changes to pack-smoke assertion content — that landed with 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 (PR fix(devx): re-pin the publish smoke to the declared first-run contract #14255); this card only adds a trigger point. - Container & model:
mode:subagent,claude-opus-5. Tier readout (dispatch-gates--tier, derived): "Model tier — no path-derived mandate … The tier stays the PM's per-card judgment call (floor sonnet · default opus · ceiling fable)." PM judgment: default opus. - Clause-②: path limb not engaged; content limb NOT engaged — CI trigger wiring per an explicit maintainer ruling (2026-09-01 director batch chore(ci)(deps): bump codelytv/pr-size-labeler from 1.10.1 to 1.10.3 #23, 「同意」, opt-in label gating approved), no contract accept/reject change.
- Serial constraints: cleared. Fresh
origin/maincarries fix(devx): re-pin the publish smoke to the declared first-run contract #14255 (035951fa), so the smoke driver this reuses is the re-pinned one; no queued card shares this file surface (Publish Smoke's run-list conclusion conflates the weekly registry canary with pack-smoke — a Monday canary green reads as "the RC smoke passed" and cost three seats a six-day duration misread #14190 is instrument-reading, adjacent-not-overlapping per the card's own boundary note).
Generated by Claude Code
- Session:
os-dev-report
{ "issue": 14214, "status": "done", "premise_still_valid": true, "pr": "https://github.com/objectstack-ai/objectstack/pull/14266", "branch": "claude/issue-14214-labeled-pack-smoke", "files_changed": [ ".github/workflows/pack-smoke-optin.yml (new)", "scripts/pm/ensure-pm-labels.sh (declares the needs:pack-smoke label object)", "CONTRIBUTING.md (the one documentation line, in the Before Submitting checklist)" ], "summary": "Added the label-gated opt-in pre-merge pack smoke as a TRIGGER only. Premise re-checked on fresh origin/main at 035951faf and it holds: no labeled trigger of any kind existed in .github/workflows (every grep hit is prose or pr-automation.yml explicitly excluding labeled/unlabeled), and the positive control is exactly as the card describes - publish-smoke.yml runs pack-smoke on workflow_run after Release and reports a commit status on the release branch head. Driver contract verified by reading scripts/publish-smoke.sh rather than inventing one: invocation is bash scripts/publish-smoke.sh, SMOKE_MODE defaults to pack, prereq is pnpm install + pnpm run build (the script fails fast without packages/cli/dist and the create-objectstack bin), and it packs from REPO_ROOT - i.e. whatever tree is checked out. So the merge preview needed NO driver plumbing and none was written: publish-smoke.yml's release-branch coupling lives entirely in its resolve job, never in the driver. On pull_request the default checkout ref is already refs/pull/N/merge and the check run lands on the PR, so this workflow needs no resolve job, no resolve-guard and no statuses:write - it runs contents:read only. Boundary honoured: scripts/publish-smoke.sh has ZERO changes; assertion content was #14000's deliverable (#14255). #14190 untouched.", "tests": "Gate families derived mechanically from the real changeset via 'node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack' (no hand-written path list; the script takes its own merge-base changeset) = 31 families, harvested with --commands and all 31 run. 30 green. 1 NOT MEASURED, not a red: scripts/check-test-completeness.mjs exits 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'). Re-run union on the FINAL commit 820a49923 (12 families, all green), quoting each gate's own verdict line: 'check-workflow-status-functions: OK (scanned 30 workflow file(s), 53 job(s), 26 job-level if: expression(s); 10 read needs.*.outputs.*, all naming a status function)'; 'check:pm-label-desc-cap: 22 label descriptions in scripts/pm/ensure-pm-labels.sh, all <=100 characters (longest: 100, repo:objectui)'; 'check-required-contexts: 6 required context name(s) pinned across 2 workflow(s)'; 'check-stall-guard-budget: OK (30 workflow file(s), 53 job(s), 572 step(s), 7 guard-wrapped step(s); every effective cap clears its job budget by at least one stall window)'; 'check-nul-bytes: OK (scanned 7794 text file(s); no raw ASCII control bytes)'; 'check:declared-population-live - 156 of 200 famil(ies) declare a path population, and every one reaches this tree'; 'check-bash32-floor: 26 tracked shell file(s) name no bash 4+ construct outside a comment'. Also requested for the scripts/** touch and both green: 'check-ratchet-remedy-authority: 183 scripts swept' and 'dispatch-gates self-test: 1140 cases pass'. The family list re-derived identically after the commit. New workflow additionally parsed with the repo's own yaml lib to confirm on: did not fall into the YAML-1.1 true trap and the folded guard expression survived intact. No ablation applies - this card adds a CI trigger, and the demonstration below is the live equivalent.", "checks_run": "31 derived families (30 green, 1 self-declared NOT MEASURED) + 12 re-run on final commit 820a49923 + check:ratchet-remedy-authority + check:pm-dispatch-gates. Zero reds.", "demo_run": "https://github.com/objectstack-ai/objectstack/actions/runs/33540022809", "demo_evidence": "All THREE arms of the guard observed live on PR #14266, not asserted: run 33539960970 (opened, no label) job SKIPPED = the ruling's zero-cost boundary for unlabelled PRs; run 33540022686 (labeled with skip-changeset, not ours) job SKIPPED = the guard's second limb, which is what stops every size/* and ci/cd label the automation adds from starting another 45-minute smoke; run 33540022809 (labeled with needs:pack-smoke) job IN_PROGRESS = the trigger fires against the merge preview. Reported at draft-PR time per the dispatch contract rather than waiting ~45 minutes for convergence.", "label_created": "needs:pack-smoke did not exist (confirmed absent before creation). Created on objectstack-ai/objectstack via REST with colour 006b75 and a 94-char description, and DECLARED in scripts/pm/ensure-pm-labels.sh so it is reproducible and its description falls under check:pm-label-desc-cap. Live object read back and it matches the declaration exactly. Never auto-applied: no .github/labeler.yml rule, deliberately - path-derived application is a different design from the one ruled and would put the ~45-minute cost back in the default inner loop.", "labels_applied": "skip-changeset (releases nothing: .github/, scripts/pm/, CONTRIBUTING.md - route 2 of the Check Changeset step's own text) and needs:pack-smoke (to demonstrate). Both written with an additive POST, never a whole-set PUT, and contrast read-back confirms both survived: target minus readback = none.", "mcp_calls": "3 - issue_read(get), issue_read(get_comments), get_label. All other GitHub work went through repo-scoped REST, probed green (200) first; gh CLI is absent in this container.", "open_questions": [ { "question": "I declared needs:pack-smoke in scripts/pm/ensure-pm-labels.sh, which is a PM-owned file whose header says 'the label set IS the PM state machine'. This is the first row there that is NOT a PM state label - it is written by the PR author about their own diff. Is that the home you want?", "options": [ "A. Keep it there (as shipped). It is the repo's only declared home for a label OBJECT; leaving it undeclared reproduces the grey/empty-description drift the file's own header describes - auto-created by first application and unrepairable by any rerun - and it gains check:pm-label-desc-cap coverage. The added comment states at length that it is not a card state, is one-of with nothing, and no scripts/pm/ sweep reads it.", "B. Move it out to a new non-PM label home and keep ensure-pm-labels.sh purely PM state.", "C. Drop the declaration; rely on the live object alone." ], "recommendation": "A. The file already carries several non-state labels (needs:contract-review is a PR gate, repo:* is routing, target:v* is the release board), so the precedent exists; and the file's own #13991 block argues at length that an UNDECLARED absence is indistinguishable from an oversight, which is exactly what C would leave behind. B buys purity for a one-row file. Cheap to reverse either way - it is one row plus its comment." } ], "out_of_scope_findings": [], "followups_filed": [] }
Generated by Claude Code
PM adjudication (devx seat, session
session_01WLJQhde67SeTccsmnBVarV) on the dev's open question — where theneeds:pack-smokelabel object is declared:A — keep it in
scripts/pm/ensure-pm-labels.sh, as shipped. Reasoning, within the delegated lane: that file is the repo's only declared home for a label OBJECT; an undeclared label reproduces exactly the grey/empty-description drift its own header warns about (auto-created by first application, unrepairable by rerun), and the declaration buyscheck:pm-label-desc-capcoverage. The precedent already exists in-file (needs:contract-reviewis a PR gate,repo:*is routing,target:v*is the release board — none of those is a card state either), and the shipped comment spends its length disclaiming kinship with the PM state machine, which is the honest shape. Option B buys purity at the cost of a second one-row label home (a new file nothing else reads); option C leaves the absence indistinguishable from an oversight. Cheap to reverse later if the maintainer ever wants a non-PM label home.This does not touch the maintainer floor: the label-gated opt-in shape itself was ruled (2026-09-01, director batch #23); this is only its bookkeeping location.
Generated by Claude Code
✅ ACCEPT + close-out (same window as the merge)
domain:devx, sessionsession_01WLJQhde67SeTccsmnBVarV, R1 wave 2. PR #14266 MERGED as54c37fb8(merge-queue witness: timelineadded_to_merge_queue@ 18:03:47Z; 39/39 checks on the head, zero red).Acceptance probes re-run on
origin/mainafter the merge, not on the report:.github/workflows/pack-smoke-optin.ymlpresent, two-limb guard verbatim (contains(...labels..., 'needs:pack-smoke') && (action != 'labeled' || label.name == 'needs:pack-smoke'));CONTRIBUTING.md:367carries the self-apply criterion line;scripts/pm/ensure-pm-labels.shdeclares theneeds:pack-smokelabel object (adjudicated option A on this card).
All three ruling deliverables verified: (1) label-gated smoke against the merge preview — demonstrated live on the PR itself, all three guard arms observed (unlabeled → skipped; other-label → skipped;
needs:pack-smoke→ ran the real pack smoke, green, run 33540022809); (2) zero cost for unlabeled PRs — the skip arms are the evidence; (3) the documentation line sits in the Before Submitting checklist. Boundaries held:scripts/publish-smoke.shzero changes; #14190 untouched; nomerge_grouptrigger and not a required context, by design and documented.Residual risk stated on the workflow header (self-declaration covers only the author who recognises the change as breaking; the release-time leg remains the backstop) — that is the ruled shape, not a gap this card owed.
pm:dispatchedstripped as the second write (auto-close strips no labels). Card complete.
Generated by Claude Code
由 #14000 的维护者裁决派生(2026-09-01,总监批 #23,维护者逐字:「同意」,附问推荐「label 门控 opt-in」获批)。
背景(一句话)
#11767(audience 默认改
invite_only,破坏性 auth 变更)合并时其 PR 上零打包安装覆盖 —— pack-smoke 只在 Release run 之后以workflow_run触发,判决落在 release 分支 head 上,没有任何 PR 作者会看那里 ⇒ RC 无声连红 7 天(#14000 实测)。交付
needs:pack-smoke)挂在自声明「破坏性 auth/audience 面变更」的 PR 上时,CI 追加运行一次打包安装冒烟(与publish-smoke.yml的 pack-smoke 同一驱动,目标树 = PR 合并预览);边界
Refs: #14000(主裁决与 7 天断边测量)· #11767(样本:零 PR 覆盖的破坏性 auth 变更)· #14190(仪器缺陷)· #3091(pack-smoke 存在的理由)。