Skip to content

chore(release): enter Changesets pre mode (next) with one major marker, so v18 opens at 18.0.0-next.0 - #22084

Open
objectstack-fleet[bot] wants to merge 3 commits into
mainfrom
claude/issue-22080-v18-pre-mode
Open

objectstack-fleet[bot] wants to merge 3 commits into
mainfrom
claude/issue-22080-v18-pre-mode

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #22080

Clause-②: no

Opens the v18 line on main, as ruled B on #22050 (record 6037890422). Changesets enters pre mode with the tag next, and one major changeset takes the fixed group to 18, so the first version cut is 18.0.0-next.0. File surface: .changeset/ plus one line in scripts/check-adr-0087-registration.mjs (the seat's surface amendment 6040954045 on #22080; see the patch round below). ⛔ No edit to .changeset/config.json, to either changeset guard's logic, or to .github/workflows/release.yml. ⛔ No changeset version output is committed, and nothing was published.

The change

  1. .changeset/pre.json, written by pnpm changeset pre enter next (@changesets/cli 3.0.3) and committed as the tool wrote it (commit d3d35a1029):

    {
      "mode": "pre",
      "tag": "next"
    }

    Under v3 the file holds mode and tag only. There is no initialVersions and no changesets list.

  2. .changeset/22080-v18-line-opens.md, front matter "@objectstack/spec": major (commit 52f7a509c6). Its body is the v18 line's opening note (ADR-0131; decision: open v18 now and ship it in stages — release the last 17.x from main first without waiting for #21908's deny (A), skip the last 17.x (B), or keep #22009's order (C)? #22050). It carries Clause-②: no and its ADR-0087 disposition (see Gates).

    • Step 2 was not skipped. The card's count command, re-run on the cut 3d9188502e, prints 17 : minor and 32 : patch, and no major. No major was pending, so without this marker pre mode would version 17.8.0-next.0.
    • Why @objectstack/spec. Any fixed-group member moves all 69 to the same version, so the choice decides only where the note lands and what the major means. @objectstack/spec is the protocol package. scripts/sync-protocol-version.mjs, which the root version script runs, derives PROTOCOL_VERSION from this package's major, and ADR-0131 C8 calls the line "protocol 18". So the major sits on the package whose major is the protocol version, and the note lands where an upgrading reader looks first: packages/spec/CHANGELOG.md, under ### Major Changes.

The no-major guard reads pre.json from the checkout it runs in (the head), so steps 1 and 2 ship together

  • scripts/check-changeset-no-major.mjs:396 sets REPO_ROOT to the checkout the script runs in. readPre(root) (:2018) reads join(root, '.changeset', 'pre.json') from that working tree, :2098 hands the result to judge, and judge returns exempt when pre?.mode === 'pre' (:662). --base sets only where the diff starts. It is never where pre.json is read.
  • In CI, the Check Changeset job in .github/workflows/pr-automation.yml checks out the PR merge ref (the default for a pull_request event) and runs node scripts/check-changeset-no-major.mjs --base "$MERGE_BASE" (:1130). The merge ref carries this PR's pre.json.
  • Both legs were measured at 52f7a509c6:
    • As committed: exit 0, ✓ Changesets is in pre-release mode (tag: next) — ... skipping the no-major guard., plus a notice naming @objectstack/spec.
    • Control: with .changeset/pre.json deleted from the working tree only, exit 1, ⛔ This PR introduces changeset(s) that declare a major bump. The base 3d9188502e has no pre.json at all, so a guard that read the base could never have answered exempt. Restored with git checkout HEAD -- .changeset/pre.json: git diff HEAD is empty, and the guard exits 0 again.
  • So no split is needed, and this PR carries steps 1 and 2.

Pins

Pin Reading
In a throwaway worktree, never committed, changeset version puts the fixed group at 18.0.0-next.0 Detached throwaway worktree at 52f7a509c6: pnpm changeset version exits 0. All 69 fixed-group members read 18.0.0-next.0, and pre.json is unchanged. The 37 consumed changesets (36 pending plus this one) moved to .changeset/pre/. packages/spec/CHANGELOG.md opens ## 18.0.0-next.0 / ### Major Changes with this note. The worktree was then removed.
check-changeset-no-major and check-changeset-fixed pass on the PR node scripts/check-changeset-no-major.mjs --base origin/main exits 0 on the pre-release exemption above. Driven with a pull_request payload carrying this body (--event), it also exits 0 with the level axis read. node scripts/check-changeset-fixed.mjs exits 0: ✓ .changeset/config.json "fixed" group is in sync with 69 public workspace packages.
.changeset/pre.json is present at the merge, with "mode": "pre" and "tag": "next" Added in d3d35a1029 with the content above. No later commit touches it. It is in the merge ref CI checks out, which is the file the guard's exemption reads.

release.yml: in pre mode, changeset publish publishes under next, and latest stays 17.7.0

This is a reading of the file. Nothing was edited, and no publish was run.

  • .github/workflows/release.yml:1762 is job publish, step Publish to npm + push version tags. At :1772 it runs pnpm run release.
  • The root package.json release script is pnpm run build && bash scripts/build-console.sh && bash scripts/release-publish.sh.
  • scripts/release-publish.sh:64 runs changeset publish with no --tag.
  • In @changesets/cli 3.0.3, dist/getPublishPlan.mjs:599-603 getReleaseTag works like this: with no --tag and a pre state present, the tag is preState.tag, which is next. The one exception is a package whose every published version is already a next prerelease. Separately, dist/publish.mjs:61-63 refuses a custom --tag in pre mode.
  • npm view read today: all 69 fixed-group packages have latest = 17.7.0 and no next tag. So each publishes to next, and latest stays 17.7.0.

Gates (run on 52f7a509c6, exit codes captured before any pipe)

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derives 20 commands for this diff. All 20 exit 0, and --ran reconciles: 20 derived, 20 run, 0 NOT-MEASURED, 0 UNRUN.

Patch round, head a630de657d (seat-appended from addendum 6041313497). At 52f7a509c6 the required Lint & Repo Gates was red at PM dispatch-gates self-test, case the extension narrowing costs no lead … (refused: .changeset/pre): with pre.json tracked, the battery's loose and strict hint rules disagreed on the literal .changeset/pre/ at scripts/check-adr-0087-registration.mjs:536. That line now names the existing exclusion as CONSUMED_PRERELEASE_EXCLUDED (the predicate's match is unchanged), which the extractor reads as an excluded surface. At a630de657d: 41 derived commands, 41 run, all exit 0; pnpm check:pm-dispatch-gates → 1976 cases pass (965.7 s), the case reads (refused: none); check-adr-0087-registration --self-test 441 assertions and --base origin/main exit 0.

  • Changeset gates:
    • check-adr-0087-registration --base origin/main exits 0. The gate requires a disposition for a major: a probe commit without one was refused, exit 1, with declares a breaking change (major) but no adr-0087: disposition marker. The probe was never pushed. The changeset now carries the not-required (no-migration-prescription) marker in the ADR-0087 HTML-comment form, because the marker moves no authorable key, export, type or stored shape.
    • check-changeset-no-major --base origin/main and check-empty-changeset --base origin/main exit 0.
    • The self-tests of all three, plus check:changeset-gate-self-tests, exit 0.
  • Remaining derived commands, all exit 0: check-closing-keyword-parity and its self-test, check-comment-mask-corpus, release-rehearsal-clone --self-test, release-pending-publish --self-test, check:driver-memory-census, check:gitlink-declared, check:nul-bytes, check:objectui-changeset, check:pm-changeset-deadline-census, check:published-files, check:refd-timer-probe and check:watch-hint-literal.
  • Run beyond the derivation, all exit 0: check-changeset-fixed (an artifact roster under .changeset/), check:future-spec-major, check:lockstep-package-count and check:docs-image-tag.
  • NOT MEASURED: the four type-check lanes. The diff touches no TypeScript.

Read before merging: after this lands, the version-PR refresh goes red until its major-boundary gates are wired

The card expects changesets/action to refresh #21988 into the 18.0.0-next.0 version PR once this lands. On the files as they stand, it will not.

  • The version-pr job in release.yml (cron 0 */6 * * *) runs pnpm run version in the step Render the post-version tree (:450). The step Validate the post-version tree (:518) then exits 1 at :610-613 when the pass wrote any major-boundary path: "this version pass crossed a MAJOR boundary ... Wire them in before letting this refresh through." The step Create or update the "chore: version packages" PR has no if:, so it does not run after that failure.
  • I measured this in the same throwaway. After changeset version, the other three rewriters of the root version script exit 0. Replaying the step's shape assertion gives 0 unexpected paths and 4 major-only paths: packages/spec/src/kernel/protocol-version.ts (PROTOCOL_VERSION 17.0.0 to 18.0.0) and the blank template's objectstack.config.ts, objectstack.manifest.json and package.json.
  • The other lane, cut-rc.yml, refuses a pre tag other than rc (:232-237) and a version not shaped X.Y.Z-rc.N (:156-159). The ruled tag is next.
  • What this means: once this lands, no lane in this repository cuts 18.0.0-next.0 without a workflow change. That change is outside this card, which forbids any release.yml edit. The red is the lane's own designed refusal. It publishes nothing and queues nothing. chore: version packages #21988 stays at its current 17.8.0 content and, as the card says, ⛔ is not merged.

Acceptance notes

  • The same throwaway pnpm run version shows two more things that the lane wiring has to account for.
    • scripts/sync-release-index-currency.mjs re-dates the v17 entry in content/docs/releases/index.mdx from 17.7.0, released 2026-10-06 to released 2026-10-07. That is the prerelease cut's date. 17.7.0's version commit 4e4e881427 is dated 2026-10-06. Reported to the seat as a finding.
    • scripts/sync-docs-image-tags.mjs moves the 9 pins in docker/README.md, content/docs/deployment/self-hosting.mdx and content/docs/upgrading.mdx from 17.7.0 to 18.0.0-next.0. The self-hosting docs on main would then name a prerelease while latest is 17.7.0. Noted only.
  • The opening note says the dist-tag latest stays on 17.x until GA. The pre-mode publish path above is what makes that true.

维护者速读(草稿)

改了什么:在 main 上进入 Changesets 预发布模式(标签 next),并加一条把 @objectstack/spec 标为 major 的 changeset。合并后,下一次切版本得到的是 18.0.0-next.0,而不是 17.8.0。改动是 .changeset/ 下的两个文件,加上门禁脚本里的一行重命名:scripts/check-adr-0087-registration.mjs 把已有的排除路径 .changeset/pre/ 写成 _EXCLUDED 命名常量(匹配逻辑不变),这样 pre.json 存在后 PM 门禁自检能正确识别它。没有代码或工作流改动。

为什么改:按 #22050 的裁决 B,v18 直接在 main 上开发。v18 的破坏性改动要以 18.0.0-next.N 预发布版发到 npm 的 next 标签上;latest 保持 17.7.0,普通安装的用户不受影响,直到 18.0 正式版。

风险与代价(含回滚):合并后,版本 PR 的自动刷新(release.yml 的 version-pr,每 6 小时一次)会在 "Validate the post-version tree" 一步变红。原因是这一版跨了大版本,会改写 PROTOCOL_VERSION 和模板文件,而这条通道对这些文件还没有门禁,按设计会拒绝。它不发布,也不排队任何东西,但在另开卡把这些门禁接上之前,#21988 不会变成 18.0.0-next.0。cut-rc.yml 只接受 rc 标签,也走不通。#21988 无论如何都不要合并。回滚办法:删除 .changeset/pre.json 和 .changeset/22080-v18-line-opens.md 两个文件(在切出任何预发布版之前,这一步没有副作用)。

席位意见:

你要做的:确认后合并本 PR。合并后需要另开一张卡,让版本通道能切出 18.0.0-next.0;这张卡由席位提出。


Generated by Claude Code

claude added 2 commits October 7, 2026 13:44
`pnpm changeset pre enter next` writes `.changeset/pre.json` as
`{"mode": "pre", "tag": "next"}`. From this commit, `changeset version`
computes prerelease versions and `changeset publish` publishes them under
the npm dist-tag `next`.

Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw
Co-authored-by: Claude <noreply@anthropic.com>
…xt.0

Every publishable package is in the Changesets `fixed` group, which takes
the highest pending bump. Every changeset pending on main is `minor` or
`patch`, so pre mode alone would version 17.8.0-next.0. One `major` on
`@objectstack/spec` takes the group to 18; `sync-protocol-version.mjs`
reads PROTOCOL_VERSION from that package's major.

The changeset states its ADR-0087 disposition (not-required,
no-migration-prescription): the marker moves no authorable key, export,
type or stored shape.

Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw
Co-authored-by: Claude <noreply@anthropic.com>
…` constant

`check-adr-0087-registration.mjs` filters `.changeset/pre/` (consumed
prerelease changesets) out of its audit surfaces. The literal now sits in a
top-level `CONSUMED_PRERELEASE_EXCLUDED` constant that `isConsumedPrerelease`
reads; the literal and the predicate's match are unchanged.

The constant's name meets dispatch-gates' exclusion-declaration predicate, so
the watch-hint extractor reads the literal as the excluded surface it is.
Without it, once `.changeset/pre.json` is tracked the extracted hint
`.changeset/pre` resolves to `pre.json` under the PM self-test's loose rule
and not under its strict rule, and `check:pm-dispatch-gates` fails its
"extension narrowing costs no lead" case.

Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读 — PR #22084(#22080,v18 开版)

席位 domain:devx#2 · session_01VF48aw8RPG6wzDnMgp6rtw · 2026-10-07T15:46Z。终稿,对照席位自己读的 diff 校正自 PR 正文草稿。复核记录在 #22080 的 ACCEPT 评论。

改了什么

  • .changeset/ 下两个文件(+18 行):
    • pre.json 让 main 进入 Changesets 预发布模式(标签 next);
    • 一条 changeset 把 @objectstack/spec 标为 major。
  • 门禁脚本里一行重命名(+2 −1):scripts/check-adr-0087-registration.mjs 把已有的排除路径 .changeset/pre/ 写成 _EXCLUDED 常量,匹配逻辑不变。不改的话,pre.json 一进来,必过的 Lint 就会在 PM 门禁自检上变红。
  • 合并后,下一次切版本是 18.0.0-next.0,不是 17.8.0。没有产品代码或工作流改动。

为什么改

风险与代价(含回滚)

席位意见

你要做的

确认后合并本 PR(席位不翻 ready 以外的任何开关,不入队)。

This branch has not been deployed

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

Labels

documentation Improvements or additions to documentation needs-user-decision size/s tooling

Projects

None yet

2 participants