Skip to content

ci(release): retire the rc channel — delete cut-rc.yml, remove the retired rc dist-tag - #26394

Merged
os-zhuang merged 5 commits into
mainfrom
claude/project-thread-pjabey
Oct 27, 2026
Merged

os-zhuang merged 5 commits into
mainfrom
claude/project-thread-pjabey

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steve · project thread
Fixes #26196
Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:删掉 Cut RC 工作流(cut-rc.yml),发布通道只剩 latest(正式版)和 next(预发布);发布后整理 npm 标签的脚本对 rc 改为删除而不是挪动;文档和脚本注释里指向 cut-rc 的说法全部改掉。
  • 为什么改:维护者裁定「现在只有 latest 和 next」。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

  1. .github/workflows/cut-rc.yml is deleted. It could only cut X.Y.Z-rc.N and refused to run unless .changeset/pre.json said tag: rc.
  2. Channel rule, stated once in docs/releases-maintenance.md under a new ### Release channels: latest = stable, next = pre-release (release.yml in pre mode, .changeset/pre.json tag next, published by changeset publish under that tag), no rc. 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 named cut-rc.yml (Console build, fetch-depth: 0) and one "snapshot flow above" back-reference are reworded.
  3. scripts/release-dist-tags.mjs gains RETIRED_TAGS = ['rc'] (exported, frozen). planTags now 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, so next still moves. sweep/main take a remove writer (npmDistTagRm = npm dist-tag rm NAME TAG); plan mode prints plan NAME rc: VERSION → removed (retired channel) and the summary counts removals separately. A pre-release RELEASE_VERSION still does nothing (the header says a retired tag goes at the next stable publish). The release.yml step name and wiring are unchanged.
  4. scripts/check-changeset-no-major.mjs: the wiring battery asserted that cut-rc.yml exists 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 in pr-automation.yml; every call site is in pr-automation.yml; every workflow that runs the script has a pull_request trigger. So a new non-PR caller cannot silently land in the no-pull-request stand-down lane. The no-pull-request comment, 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 grep of the old and new text).
  5. Comment-only rewording (no behaviour), so git grep cut-rc stops pointing at a deleted lane: lint.yml (the jq note), release.yml (3 comments: the allowlist twin sentence, the one-list principle, the five-filter note), and in scripts/: 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.
  6. 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 set release.yml's publish job to timeout-minutes: 120): the header said the publish job "declares no timeout-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 merging origin/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 rc is live; the registry still serves rc: 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 exactly rc; today's registry shape gives rc = remove and next = move; a retired tag on a stable, an ahead and a non-semver value is removed; next is never retired; control: with an empty list rc moves again; the plan line names the removal; --apply removes rc through the remover and never adds it. Batteries 1–5 updated: every sweep/main call that could reach a removal passes a stub remover, so the self-test never spawns a real npm; the end-to-end battery's stub npm on PATH records dist-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

  • Card acceptance 1: git grep -n 'cut-rc' -- .github scripts docs/releases-maintenance.md on 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 reader changeset pre exit re-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.md names "the Cut RC lane" once, in the channel section, as the retired lane.
  • Card acceptance 2 (plan, read-only): node scripts/release-dist-tags.mjs against 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 is next: 18.0.0-next.5 → 18.1.0, every removal is rc: 17.0.0-rc.6 → removed (retired channel). The card says 73 packages carry rc; measured today it is 68: @objectstack/connector-imap, organizations, service-mailbox, service-print and skills carry next but no rc. 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.
  • Card acceptance 3: every script under scripts/ that names release.yml or lint.yml and has a --self-test (49 files) was run with --self-test on 088f95b: 48 exit 0; scripts/pm/dispatch-gates.mjs --self-test hit the loop's 280 s cap (exit 124) and is covered by pnpm check:pm-dispatch-gates below, which runs it. On 2b9dd3d the derived set re-ran the ones it names, and release-verify-npm.mjs --self-test passed after the merge (131 cases).
  • Left as written, outside the acceptance grep (comments only): 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 and docs/audits/** are history and unchanged.
  • scripts/release-spec-changes.sh --generate had one workflow caller, cut-rc.yml; after this PR no workflow calls that mode (release.yml uses --prepare/--verify/--attach). Observation only.
  • check-changeset-no-major.mjs still 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/objectstack on the final head 2b9dd3d (merge base 756220c) derived 81 commands (the 79 of the pre-merge head 088f95b plus check-adr-links.mjs and its --self-test). All ran locally with stdin from /dev/null, exit captured before any pipe; check:dts-closure and check:dual-build-cjs-loads after turbo run build --concurrency=2 --filter='./packages/**' under the verify lock (VERDICT command-exit 0, 546 s). --ran reconciliation 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
  • all 81 derived commands on 2b9dd3d: exit 0, including 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-gates on 2b9dd3d: exit 0, captured by its wrapper (fast tier, 501.3 s on this box).
  • node scripts/check-comment-mask-corpus.mjs first 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.

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (packages/spec is not touched.)
  • 2. Every name I added uses the casing for its kind. (RETIRED_TAGS, npmDistTagRm, plannedRemovals.)
  • 3. No formatter ran; pnpm lint passes. (No formatter ran; pnpm lint is CI's run, read from Lint & Repo Gates on this PR.)
  • 4. One issue, one branch off an up-to-date main, one pull request. (origin/main 756220c merged in.)
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. (Nothing publishes; both lines are above.)
  • 6. packages/spec touched: its generated artifacts are regenerated and committed. (Not touched.)
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English. (All English except the 维护者速读 block, which the fleet's dev contract asks for in Chinese.)
  • The Before Submitting list in CONTRIBUTING.md is done. (Not walked item by item; the gate readings above are what was run.)

Changeset

None: the diff touches workflows, a doc and repo-internal scripts under scripts/, which no package publishes. skip-changeset is set at creation.


Generated by Claude Code

@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 27, 2026
…-pjabey

# Conflicts:
#	docs/releases-maintenance.md
@os-zhuang
os-zhuang marked this pull request as ready for review October 27, 2026 01:53
@os-zhuang
os-zhuang enabled auto-merge October 27, 2026 01:53
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing 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): node scripts/docs-audit/affected-docs.mjs --json abb9046057b6713b78712dfe53a329deefa534ba → packageMentionDocs.

@github-actions github-actions Bot added ci/cd documentation Improvements or additions to documentation labels Oct 27, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · devx seat 2 · 2026-10-27T02:04Z

Seat domain:devx#2 (#20163) · session_01Q4MDXRbEJCNdPAP4SiXwp9 · reviewed head 3d7c8703 · card #26196, claim 6430749968 (wave 8, delta D, amended twice: the 11 scripts/ comment files, then the release-verify-npm.mjs comment from #26376's review). Tier H (check-governed-merges: governed, tier H, humanMerge); +235/−1104, of which 877 is the deleted cut-rc.yml. The readying and auto-merge on this PR are a GOVERNED_APPROVERS member's own acts.

  • Lane retired cleanly: cut-rc.yml deleted; every live reference in lint.yml, release.yml and the 11 scripts is reworded so nothing points at a deleted file. What still names cut-rc on the head is history or comment text only: ADR-0082 / ADR-0087 (governed, historical record), the 2026-09 gate census, a check-half-states fixture string, and 8 comment lines in 4 package test files (listed in the report, outside the claim). None of them reads the file, so nothing breaks on its absence.
  • Channel rule stated once: docs/releases-maintenance.md gains ### Release channels (latest = stable, next = pre-release via pre mode, no rc), and the rc snapshot procedure is removed.
  • release-dist-tags.mjs: RETIRED_TAGS = ['rc'] (frozen) is planned as a removal (npm dist-tag rm), never a move, whatever its value (stable, ahead of latest, non-semver); next keeps moving as before. Plan mode calls neither writer nor remover; a refused removal is a named failure; a latest that never agrees removes nothing. Battery 7 is new and the floor goes 6 → 7. Plan read on the registry: 111 packages, 73 next moves, 68 rc removals (the card said 73 rc; 68 is the measured count).
  • check-changeset-no-major.mjs: the cut-rc wiring pin becomes a walk over every workflow file asserting the script's only call site is pr-automation.yml, with a control that the walk found it. A new non-PR caller can no longer stand down silently. Agreed, and stronger than the old pin.
  • release-verify-npm.mjs: the header now states the publish job's 120-minute bound from ci(workflows): measured timeout-minutes on 17 jobs, PR-only concurrency on 11 workflows, a paths filter on check-links #26376, and that raising the 35-minute budget means re-checking that sum.

For the approver, the one behaviour change that reaches npm: after this merges, the next stable publish that runs release-dist-tags.mjs --apply removes the rc dist-tag from about 68 packages. That is the ruling's intent (retired tag removed, not moved). It happens only inside the human-approved release environment lane; no seat or dev runs it (Directive 15).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd documentation Improvements or additions to documentation size/xl skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

3 participants