Repository navigation
ci(release): retire the rc channel — delete cut-rc.yml, remove the retired rc dist-tag - #26394
Conversation
…d dist-tags Claude-Session: https://claude.ai/code/session_01ADHkmS6EcuQGiiD6cwnYUT Co-authored-by: Claude <noreply@anthropic.com>
…inters Claude-Session: https://claude.ai/code/session_01ADHkmS6EcuQGiiD6cwnYUT Co-authored-by: Claude <noreply@anthropic.com>
…he 360-minute default, bounds the npm settle budget Claude-Session: https://claude.ai/code/session_01ADHkmSfkkJZXxR3bPjvRzh Co-authored-by: Claude <noreply@anthropic.com>
…-pjabey # Conflicts: # docs/releases-maintenance.md
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
席位核对 · ACCEPT · devx seat 2 · 2026-10-27T02:04ZSeat
For the approver, the one behaviour change that reaches npm: after this merges, the next stable publish that runs |
Requested by Steve · project thread
Fixes #26196
Clause-②: no
Metadata-protocol: none
维护者速读
cut-rc.yml),发布通道只剩latest(正式版)和next(预发布);发布后整理 npm 标签的脚本对rc改为删除而不是挪动;文档和脚本注释里指向 cut-rc 的说法全部改掉。rc,留着会让人和 AI 以为rc通道还活着;npm 上 68 个包至今还挂着rc: 17.0.0-rc.6。release.yml)只改了注释,行为不变;变化在下一次正式版发布后的标签整理步骤:它会删掉rc标签(该步骤本来就是非阻塞的)。回滚 = revert 本 PR。scripts/release-dist-tags.mjs的RETIRED_TAGS与planTags删除分支;②docs/releases-maintenance.md新的「Release channels」节;③scripts/check-changeset-no-major.mjs改写的 wiring 断言(原来要求 cut-rc.yml 存在)。node scripts/release-dist-tags.mjs(只读计划,不写 npm),预期末行73 tag(s) would move, 68 retired tag(s) would be removed … 0 failure(s)。.github/workflows/**)改动,需要 GOVERNED_APPROVERS(os-zhuang、hotlong)批准后落地;PR 保持 draft,席位不转 ready、不开自动合并。What changes
.github/workflows/cut-rc.ymlis deleted. It could only cutX.Y.Z-rc.Nand refused to run unless.changeset/pre.jsonsaidtag: rc.docs/releases-maintenance.mdunder a new### Release channels:latest= stable,next= pre-release (release.ymlin pre mode,.changeset/pre.jsontagnext, published bychangeset publishunder that tag), norc. The two-route table and the whole "Cutting an rc — the snapshot flow" section (bypass-list prerequisite, stale chore: version packages #6208 note, runtime-image note) are removed; the ADR-0125 environment-gate paragraph is kept and reworded for the one lane. Two other lines that namedcut-rc.yml(Console build,fetch-depth: 0) and one "snapshot flow above" back-reference are reworded.scripts/release-dist-tags.mjsgainsRETIRED_TAGS = ['rc'](exported, frozen).planTagsnow returns{ moves, removes, kept }: a retired tag is removed whatever it points at (a stale, an ahead, a stable or a non-semver value), checked before any version test; every other tag keeps today's rule, sonextstill moves.sweep/maintake aremovewriter (npmDistTagRm=npm dist-tag rm NAME TAG); plan mode printsplan NAME rc: VERSION → removed (retired channel)and the summary counts removals separately. A pre-releaseRELEASE_VERSIONstill does nothing (the header says a retired tag goes at the next stable publish). Therelease.ymlstep name and wiring are unchanged.scripts/check-changeset-no-major.mjs: the wiring battery asserted thatcut-rc.ymlexists and calls this script twice with no--event. Those 4 assertions are replaced by 4 over every workflow: the walk lists workflow files; control: it finds the real scan inpr-automation.yml; every call site is inpr-automation.yml; every workflow that runs the script has apull_requesttrigger. So a new non-PR caller cannot silently land in theno-pull-requeststand-down lane. Theno-pull-requestcomment, verdict-table line and its runtime message now name a local run as the only caller (the message is not pinned by any test:git grepof the old and new text).git grep cut-rcstops pointing at a deleted lane:lint.yml(thejqnote),release.yml(3 comments: the allowlist twin sentence, the one-list principle, the five-filter note), and inscripts/:check-docs-image-tag.mjs,check-self-test-wired.mjs(header + one control comment),check-skill-compatibility-version.mjs,docs-audit/README.md,pm/clause2-line.mjs,pm/dispatch-gates.self-test.mjs,pm/release-rehearsal-clone.mjs,release-spec-changes.sh,sync-release-index-currency.mjs(4 comments + one self-test case title),sync-template-versions.mjs. These 11 files were added to the claim's file surface by the seat before editing.scripts/release-verify-npm.mjs, comment only (from the seat's check of ci(workflows): measured timeout-minutes on 17 jobs, PR-only concurrency on 11 workflows, a paths filter on check-links #26376, which setrelease.yml's publish job totimeout-minutes: 120): the header said the publish job "declares notimeout-minutes, so GitHub's 360-minute job default bounds this step"; it now names the 120-minute bound and that raising the 35-minute settle budget means re-checking that sum. Applied after mergingorigin/main(756220c, which carries ci(workflows): measured timeout-minutes on 17 jobs, PR-only concurrency on 11 workflows, a paths filter on check-links #26376 as fa5d72e) as the seat's prepared commit;node scripts/release-verify-npm.mjs --self-test→ exit 0,131 cases pass across 14 batteries.Why
The maintainer, in the triage seat thread: 「现在只有 latest 和 next」, then 「同意」 to retiring the rc lane. A lane that can only cut a channel that no longer exists tells every reader, human or AI, that
rcis live; the registry still servesrc: 17.0.0-rc.6, and the dist-tag sweep after each stable publish would keep moving it forward instead of letting it go.Tests
node scripts/release-dist-tags.mjs --self-test→ exit 0:OK release-dist-tags self-test: 54 cases pass across 7 batteries. New battery 7 "Retired channels: removed, never moved, and only those" (9 cases, floor 9; roster floor 6 → 7): the list is exactlyrc; today's registry shape givesrc= remove andnext= move; a retired tag on a stable, an ahead and a non-semver value is removed;nextis never retired; control: with an empty listrcmoves again; the plan line names the removal;--applyremovesrcthrough the remover and neveradds it. Batteries 1–5 updated: everysweep/maincall that could reach a removal passes a stub remover, so the self-test never spawns a realnpm; the end-to-end battery's stubnpmon PATH recordsdist-tag add @objectstack/cli@18.1.0 next,dist-tag rm @objectstack/cli rc,dist-tag rm create-objectstack rc.node scripts/check-changeset-no-major.mjs --self-test→ exit 0, 456 assertions (wiring battery stays at its 22 floor: 4 removed, 4 added).Acceptance notes
git grep -n 'cut-rc' -- .github scripts docs/releases-maintenance.mdon the head returns one line:scripts/pm/check-half-states.mjs:26115, the recorded title of card [finding] cut-rc.yml's hotcrm smoke warning still tells the readerchangeset pre exitre-arms that gate — release.yml records the keying was changed away from pre-exit #9828 inside a fixture roster. It is history and stays.docs/releases-maintenance.mdnames "the Cut RC lane" once, in the channel section, as the retired lane.node scripts/release-dist-tags.mjsagainst registry.npmjs.org, anonymous GETs only, nothing written:Planning (read-only; pass --apply to write) the dist-tags of 111 package(s)→73 tag(s) would move, 68 retired tag(s) would be removed, 0 kept ahead of latest, 0 package(s) skipped, 0 failure(s).Every move isnext: 18.0.0-next.5 → 18.1.0, every removal isrc: 17.0.0-rc.6 → removed (retired channel). The card says 73 packages carryrc; measured today it is 68:@objectstack/connector-imap,organizations,service-mailbox,service-printandskillscarrynextbut norc. Not run with--apply(AGENTS.md directive 15); release: one-time npm dist-tag sweep for the pre-release tags that 18.1.0 left stale (maintainer-run) #25764's one-time sweep is not touched.scripts/that namesrelease.ymlorlint.ymland has a--self-test(49 files) was run with--self-teston 088f95b: 48 exit 0;scripts/pm/dispatch-gates.mjs --self-testhit the loop's 280 s cap (exit 124) and is covered bypnpm check:pm-dispatch-gatesbelow, which runs it. On 2b9dd3d the derived set re-ran the ones it names, andrelease-verify-npm.mjs --self-testpassed after the merge (131 cases).packages/cli/test/scaffold-exact-objectstack-pin.test.ts:12,packages/create-objectstack/src/runtime-image.test.ts:237,template-consistency.test.ts:799,template-version-stamps.test.ts:11,51,274,338,387. ADRs anddocs/audits/**are history and unchanged.scripts/release-spec-changes.sh --generatehad one workflow caller,cut-rc.yml; after this PR no workflow calls that mode (release.ymluses--prepare/--verify/--attach). Observation only.check-changeset-no-major.mjsstill says "RC window" / "RC exemption" for Changesets pre mode in general; that is pre mode, not the deleted lane, and is unchanged.Verification
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon the final head 2b9dd3d (merge base 756220c) derived 81 commands (the 79 of the pre-merge head 088f95b pluscheck-adr-links.mjsand its--self-test). All ran locally with stdin from/dev/null, exit captured before any pipe;check:dts-closureandcheck:dual-build-cjs-loadsafterturbo run build --concurrency=2 --filter='./packages/**'under the verify lock (VERDICT command-exit 0, 546 s).--ranreconciliation on 2b9dd3d: 81 derived, 81 run, 0 NOT-MEASURED, 0 UNRUN (a derived zero). The same 79 had also all exited 0 on 088f95b. Every other family is CI's, read from this PR's check-runs.Gate readings
pnpm check:changeset-gate-self-tests,pnpm check:doc-authoring,pnpm check:required-contexts,pnpm check:template-version-sync,pnpm check:release-index-currency-sync,node scripts/check-self-test-wired.mjs(+--self-test),node scripts/pm/release-rehearsal-clone.mjs --self-test,node scripts/release-dist-tags.mjs --self-test.pnpm check:pm-dispatch-gateson 2b9dd3d: exit 0, captured by its wrapper (fast tier, 501.3 s on this box).node scripts/check-comment-mask-corpus.mjsfirst hit the loop's 300 s cap (exit 124) while the build held the box; re-run alone: exit 0,18308 files, 0 disagree, 0 unparseable, 232.7s.check:dts-closure: 75 built packages swept, 233/233 declaration files present.check:dual-build-cjs-loads: provenance line 112/69/2381/1 over floors 90/58/520/1.Human Minimum
Each item is one rule from
CONTRIBUTING.md › Human Minimum,
which links the AGENTS.md text that states it.
packages/specholds no runtime logic. (packages/specis not touched.)RETIRED_TAGS,npmDistTagRm,plannedRemovals.)pnpm lintpasses. (No formatter ran;pnpm lintis CI's run, read fromLint & Repo Gateson this PR.)main, one pull request. (origin/main756220c merged in.)packages/spectouched: its generated artifacts are regenerated and committed. (Not touched.)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Changeset
None: the diff touches workflows, a doc and repo-internal scripts under
scripts/, which no package publishes.skip-changesetis set at creation.Generated by Claude Code