Skip to content

Commit 8fbbd50

Browse files
docs(releases): state 18.0.0 as the v18 GA release, so the GA Version Packages PR renders (#24584)
Fixes #24569 Clause-②: no The v18 GA release prose for the two release-owned pages that refuse the GA Version Packages PR. This PR pairs with PR #24555, which exits Changesets pre mode. With both applied, the `version-pr` lane's Render, Validate and Restore steps all exit 0 and the lockstep group renders `18.0.0`. **Draft, for the maintainer to merge.** **Merge order:** PR #24555 first, this PR second, then one Version Packages refresh. ⛔ Nothing was published or tagged. No release workflow was dispatched. The Version Packages PR (#24524) and `changeset-release/main` were not touched. The dry-run ran in a scratch clone outside the worktree, and nothing from it was committed or pushed. No gate or rewriter changed. Head `b174b74605` is `ba4afcc239` (`origin/main`, merged in before opening) plus two docs commits. The worktree's base was `04669a467e`. ## The change (docs only, `content/docs/releases/` only) ### `content/docs/releases/index.mdx` 1. The v18 entry's trailing status is now in the one shape `sync-release-index-currency` rewrites (`STATUS_SHAPE`): ```text before: (prerelease: `18.0.0-next.N` on npm's `next` tag, no GA date) after: (current series: 18.0.0, released 2026-10-19) ``` The prose before the status now reads: "its breaking changes landed in stages through the `18.0.0-next.N` prereleases on npm's `next` tag, each with its own changeset and migration, and its GA release, 18.0.0, publishes to npm's `latest` tag and moves it from 17.x to 18". 2. The paragraph "**The v18 line is a major in prerelease.** …" (old lines 58-62) is now "**The v18 line is a major, and 18.0.0 is its GA release.**" The pre-mode regime is in the past tense, and the paragraph states the exited state: the 18.0.0 cut publishes to `latest`, and `check-changeset-no-major.mjs` again fails a pull request that declares a major bump. The wording follows PR #24555's edit of `backward-compatibility.mdx`. ### `content/docs/releases/v18/index.mdx` 1. The `description` front matter is now: "The v18 line and its GA release, 18.0.0, which closes the `18.0.0-next.N` prerelease train and publishes to npm's `latest` tag. …" 2. The release-status blockquote, in full: ```md > **Release status: 18.0.0 is GA — the release this page documents.** It > closes the v18 prerelease train, which published as `18.0.0-next.N` on npm's > `next` dist-tag. The 18.0.0 cut leaves Changesets pre mode, so the > `@objectstack/*` packages stop publishing as `18.0.0-next.N`, and 18.0.0 > publishes to npm's `latest` dist-tag, which moves from 17.x to 18 with it. A > `^17` dependency range still never moves to 18 by itself: move every > `@objectstack/*` dependency to 18 together, and read > [Upgrading](/docs/upgrading) before you do. ``` 3. The two pre-mode bullets are rewritten. "Through `next` before `latest`" (old `:27`) is now in the past tense and ends with "18.0.0 is the cut that takes the line to `latest`". "GA ends the prerelease" (old `:62`) is now "**18.0.0 ends the prerelease.** It is the GA cut: it leaves pre mode and publishes the line to `latest`." The "Curated notes … are not written yet" sentence is kept verbatim. 4. One more sentence, of the same class and in the same file (second commit `b174b74605`): "While the line is open, every other breaking change that lands on `main` ships on it too" is now in the past tense. That sentence stops being true once the guard fails a major bump again. Every heading and anchor is unchanged. In particular `## How a breaking stage lands on this line` stays as it is: its anchor is linked from the release index and five times from `protocol/backward-compatibility.mdx`. ### Why the text is worded this way - **The status shape.** `(current series: X.Y.Z, released YYYY-MM-DD)` is the only shape the rewriter rewrites, so the 18.1.0 version pass will stamp the next minor without a person. A probe of the rewriter's own functions on this text: `rewriteStatusField(field, '18.0.0', …)` returns `null`, meaning it leaves a field that already names the newest GA alone, date included. `rewriteStatusField(field, '18.1.0', '2026-11-01')` returns `current series: 18.1.0, released 2026-11-01`. - **The blockquote's assertion.** It uses "18.0.0 is GA", one of the forms `releasedAssertionRe` accepts. It contains none of the six `PAGE_STALE_SIGNALS`. Probed with the gate's own predicates: `pageStatusProblems(18)` returns `[]`, `indexStatusProblems(18)` returns `[]` and `indexCurrencyFindings(18, '18.0.0')` returns `[]`. The control on the base text: 1 page problem, the index signals `prerelease-word` and `prerelease-version`, and 1 currency finding. - **True on both sides of the publish.** Nothing here says that npm already serves 18.0.0 on `latest`, or that "a plain install now resolves 18.0.0". 18.0.0 is described as the release the page documents and by what it does: it "publishes to npm's `latest` dist-tag". That stays true for a reader on `main` between this merge and the publish, and after the publish. The one dated claim is the index status, discussed next. ## DATE `released 2026-10-19` is the UTC day this PR is opened. - No gate checks the date, re-measured: `indexCurrencyFindings` judges the version only, and `check:release-page-status`'s index matcher judges only the prerelease signals. - The rewriter never re-dates a field that already names the newest GA. The dry-run below printed "every in-scope entry … (v16, v17, v18) already names the newest GA release of its major … nothing rewritten", and the date came through the version pass unchanged. - So nothing corrects the date later. **If the maintainer merges on a later day, the seat re-dates it in this PR before the merge.** ## Proof: the paired dry-run (scratch clone, never pushed) Setup: - A clone of `/home/user/objectstack` at a short scratch path, with the push URL set to an invalid path. - Full history (`--is-shallow-repository` false). Local `main` is `ba4afcc239`. - Branch `rehearsal2` = this PR's head `b174b74605` merged with PR #24555's head `abec338235`, giving merge `468a6ad229`. That tree differs from `main` in exactly the 4 files of the two PRs, and `.changeset/pre.json` reads `mode: "exit"`. - `release-rehearsal-clone.mjs` reported "✓ FIT". `pnpm install --frozen-lockfile` ran with its scripts this time, since the short path stays under tsx's IPC socket limit. - The three `version-pr` steps were **extracted verbatim from `release.yml`** with a YAML parser. The blob `47db41eeea` is the same in the clone and on `main`. They ran under `bash -e` with `RUNNER_TEMP`, `GITHUB_OUTPUT` and `GITHUB_STEP_SUMMARY` pointed at scratch files, each under `os-verify-lock.sh`. | step | exit | reading | |---|---|---| | Render the post-version tree | **0** | `pending_before=1029`, 1205 paths moved. `sync-release-index-currency`: "(v16, v17, v18) already names the newest GA release … nothing rewritten". `check-skill-compatibility-version --fix`: 10 of 10 SKILL.md stamps moved to `18.0.0`. | | Validate the post-version tree | **0** | "Post-version tree validated.", with 15 of 15 content gates green, `check:release-page-status` and `check:release-index-currency-sync` among them. "1205 path(s), all inside the reviewed shape", "major-boundary surfaces left unvalidated: 0". | | Restore the pre-version tree | **0** | "Pre-version tree restored: 1029 pending changeset(s), working tree clean." | Rendered versions: - `@objectstack/spec` is **`18.0.0`**. - The fixed group reads 73 of 73 members at `18.0.0`. - `.changeset/pre.json` was deleted by the pass. - The index status survived the pass byte-identical: `(current series: 18.0.0, released 2026-10-19)`. The first round on head `3754bbeddb`, before commit 2, gave the same three exit codes and the same readings. NOT MEASURED: the read-rehearsal steps (`changesets/action`), because that is a GitHub Action. ## This PR alone on `main` (still `mode: "pre"`) It may sit on `main` briefly before or after #24555, so every docs gate was run on this branch's own head (`b174b74605`, `.changeset/pre.json` at `mode: "pre"`). Exit codes were captured before any pipe. - **Derived families:** `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derives **47** commands for the two-file diff, and all 47 exit 0. The `--ran` reconciliation reads "47 derived, 47 run, 0 NOT-MEASURED (a DERIVED zero — all 47 recorded an exit code and none of them is 3)". On the first pass, five families (`check:doc-formula-expressions`, `check:doc-security-posture`, `check:docs`, `check:skill-examples` and `check:docs-transcript-drift`) returned a PREREQUISITE refusal (exit 3, or exit 1 "Generate it first"). I built `@objectstack/spec` plus the `@objectstack/lint...` closure, and the `@objectstack/client-react...` closure, under `os-verify-lock.sh`, then re-ran all 47. - **Release-docs gates beyond the derivation, all exit 0:** `check:release-index-currency-sync`, `node scripts/sync-release-index-currency.mjs` (wrote nothing; the tree stayed clean), `check:docs-image-tag`, `check:docs-image-tag-sync`, `check:release-page-status`, `check-release-section-coverage.mjs --strict` and `check:release-notes`. On `main` the CHANGELOG has no `## 18.0.0` heading yet, so the v18 entry is not in those gates' GA scope. The text is green there for that reason, and green on the post-version tree as shown above. - **Control bytes:** the self-scan finds none in either file. ## Changeset and label There is no changeset, because nothing here publishes. Neither file is reachable from any public package's `files[]`: 73 public packages, none of whose `files[]` entries names `content`, `docs` or `releases` or climbs out of its package. The positive control is that 73 of 73 name `dist`. So `skip-changeset` rides the create. ## Acceptance notes - **After the GA publishes, the release-coverage patrol reports the v18 page.** Validate's advisory `check-release-section-coverage` already reports it on the post-version tree: "NO heading on this page names the 18.0 series". It is advisory in Validate and green there. The nightly `release-coverage-patrol.yml` runs `--strict` and records it on its anchor issue until the curated 18.0.0 notes are compiled. That compile is the release-time step the page itself names ("Curated notes … are compiled at release time"), as with every 17.x minor. Writing a heading only to satisfy the patrol would be a heading with no notes under it. Noted, not carded. - **Bullets 2-4 of "How a breaking stage lands on this line" are still in the present tense** ("ADR-0131 lands in stages", "Protocol 18 comes with it", "The AI skills move with the packages"). None of them states the pre-mode regime, and none is made false by the exit. Turning the section into the line's history belongs to the curated 18.0.0 notes. Noted only. - **The index link text stays `[v18]`.** GA lines use `[v17.0.0]`-style text, but no gate reads link text and the card did not ask for it. Noted only. ## 维护者速读(草稿) **改了什么**:只改了两页发布文档,都在 `content/docs/releases/` 下。 - 发布索引里 v18 条目的状态从"预发布、没有 GA 日期"改为 `(current series: 18.0.0, released 2026-10-19)`。这是版本步骤的改写器唯一能识别、以后能自动更新的格式。同一页的"v18 正在预发布"段落改成已退出预发布的说法。 - v18 发布页的 `description`、发布状态引用块,以及三句预发布模式下的现在时句子,改为"18.0.0 是 GA 版本,发布到 npm 的 `latest`"。 - 没有改任何代码、门禁、改写器或 changeset。 **为什么改**:PR #24555 退出预发布模式后,版本 PR 的刷新会在这两处按设计拒绝:Render 卡在 `sync-release-index-currency`,Validate 卡在 `check:release-page-status`。在临时克隆里同时套上 #24555 和本 PR,原样重放 `release.yml` 的 Render / Validate / Restore 三步:退出码都是 0,15 个内容门禁全绿,`@objectstack/spec` 渲染为 `18.0.0`,73 个锁步包全部是 `18.0.0`。 **风险与代价(含回滚)**: - 措辞在 npm 发布前后都成立:没有写"npm 已经在 `latest` 上提供 18.0.0",只写 18.0.0 是本页记录的 GA 版本,它会发布到 `latest`。唯一带日期的说法是索引里的 `released 2026-10-19`。 - 日期没有门禁校验,改写器也不会改它。如果合并不在 2026-10-19(UTC),席位会在合并前在本 PR 里改成合并当天的日期。 - 本 PR 单独留在 `main` 上(仍是 `mode: "pre"`)时,派生出的 47 个门禁全部为 0,其余发布文档门禁也全绿。 - 顺序反了的代价:如果本 PR 先于 #24555 合并,`main` 上会短暂出现"已退出预发布模式"的文字,但当时仍处于预发布模式。门禁不会变红。 - GA 发布后,夜间的 release-coverage patrol 会报告 v18 页还没有 18.0 的小节标题,直到整理好的 18.0.0 发布说明写完。这和每个 17.x 小版本的流程一样。 - 回滚:GA 版本 PR 合并前,直接 revert 本 PR 即可。 **席位意见**: **你要做的**: 1. 选定 GA 当天先合并 PR #24555,再合并本 PR,然后触发一次版本 PR 刷新。 2. 确认刷新后版本 PR 的 head 里 `@objectstack/spec` 是 `18.0.0`,再按发布流程合并版本 PR 并批准发布。 3. 如果合并日期不是 2026-10-19,先让席位改日期再合并。 --- _Generated by [Claude Code](https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 407f870 commit 8fbbd50

2 files changed

Lines changed: 26 additions & 20 deletions

File tree

‎content/docs/releases/index.mdx‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ migration steps, then covers new capabilities and notable fixes.
1818

1919
## Versions
2020

21-
- [v18](/docs/releases/v18) — The line that carries ADR-0131, total organization ownership with no NULL `organization_id`; its breaking changes land in stages, each with its own changeset and migration, and `latest` stays on 17.x until the line reaches GA (prerelease: `18.0.0-next.N` on npm's `next` tag, no GA date).
21+
- [v18](/docs/releases/v18) — The line that carries ADR-0131, total organization ownership with no NULL `organization_id`; its breaking changes landed in stages through the `18.0.0-next.N` prereleases on npm's `next` tag, each with its own changeset and migration, and its GA release, 18.0.0, publishes to npm's `latest` tag and moves it from 17.x to 18 (current series: 18.0.0, released 2026-10-19).
2222
- [v17.0.0](/docs/releases/v17) — Files become owned `sys_file` records with server-enforced `accept`/`maxSize` and a governed download path, bulk export becomes its own opt-in privilege, the SDK is reconciled against the routes the server actually mounts (21 dead methods out, 40+ real ones in), approval nodes route approvers dynamically via CEL expressions and decision outputs, a datasource that cannot connect fails the boot, and Node 22 becomes the supported floor; 17.1 adds partial field masking, record-view auditing on `sys_audit_log`, and a per-object read-only approval visibility tier — and makes a deactivated permission set or position actually stop granting access, withdraws the bulk-export wildcard from the shipped admin sets, and gives all three flow doors one honest HTTP status table; 17.2 tightens by-id `update`/`delete` against a silently-dropped `where` predicate or a mismatched id, retires `sys_position.permissions` and other dead ADR-0049 surfaces, and stops analytics from answering the wrong number on a cross-object filter (current series: 17.7.0, released 2026-10-06).
2323
- [v16.0.0](/docs/releases/v16) — One org identifier (`organizationId`) across hooks and actions, quorum + per-group sign-off (会签) approvals with metadata-declared decision actions, time-relative automations, filtered roll-ups, strict dashboard widgets, an identity-scoped MCP stdio transport, and a platform-wide enforce-or-remove sweep that makes dead metadata loud; 16.1 adds a `requires` capability-provider preflight, two more dashboard build gates, and `runAs:'user'` automations that run with the triggering user's real grants (final release: 16.1.0).
2424
- [v15.0.0](/docs/releases/v15) — Explain record access layer by layer, a docked AI workspace in the Console, project-ready Gantt charts, and phone sign-in; 15.1 adds permission-following attachments, no-code third-party connectors, dashboard-wide filters, pinyin search, and whole-record inline editing — with materially safer multi-tenant and write-path defaults (final release: 15.1.1).
@@ -55,10 +55,13 @@ shipped as a minor release.** It landed in a **minor** alongside a changeset
5555
entry marked `**BREAKING**`, and `scripts/check-changeset-no-major.mjs`
5656
failed a pull request that declared a major bump.
5757

58-
**The v18 line is a major in prerelease.** Changesets is in pre mode with the
59-
tag `next`, and `check-changeset-no-major.mjs` stands aside in pre mode, so a
60-
pull request may declare a major bump. Every release cut from `main` is the
61-
next `18.0.0-next.N` on npm's `next` tag, while `latest` stays on 17.x. See
58+
**The v18 line is a major, and 18.0.0 is its GA release.** While Changesets
59+
was in pre mode with the tag `next`, `check-changeset-no-major.mjs` stood
60+
aside, so a pull request could declare a major bump, and every release cut
61+
from `main` was the next `18.0.0-next.N` on npm's `next` tag while `latest`
62+
stayed on 17.x. Changesets has left pre mode for the 18.0.0 cut, which
63+
publishes to npm's `latest` tag, and the guard again fails a pull request that
64+
declares a major bump. See
6265
[how a breaking stage lands on the v18 line](/docs/releases/v18#how-a-breaking-stage-lands-on-this-line).
6366

6467
What that means when you read a version number:

‎content/docs/releases/v18/index.mdx‎

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,34 @@
11
---
22
title: v18
3-
description: "The v18 line, in prerelease on npm's `next` tag. It carries ADR-0131 (organization ownership is total, with no NULL `organization_id`) and lands its breaking changes in stages, each with its own migration. `latest` stays on 17.x until the line reaches GA."
3+
description: "The v18 line and its GA release, 18.0.0, which closes the `18.0.0-next.N` prerelease train and publishes to npm's `latest` tag. It carries ADR-0131 (organization ownership is total, with no NULL `organization_id`) and landed its breaking changes in stages, each with its own migration."
44
---
55

6-
> **Release status: v18 has no GA release yet.** The line publishes as
7-
> `18.0.0-next.N` prereleases on npm's `next` dist-tag. The `latest` tag stays
8-
> on the 17.x line, so a plain install keeps resolving 17.x, and a `^17`
9-
> dependency range never moves to 18. You get a v18 prerelease only by asking
10-
> for one: `@next` on every `@objectstack/*` dependency together, or an exact
11-
> `18.0.0-next.N`. There is no GA date.
6+
> **Release status: 18.0.0 is GA — the release this page documents.** It
7+
> closes the v18 prerelease train, which published as `18.0.0-next.N` on npm's
8+
> `next` dist-tag. The 18.0.0 cut leaves Changesets pre mode, so the
9+
> `@objectstack/*` packages stop publishing as `18.0.0-next.N`, and 18.0.0
10+
> publishes to npm's `latest` dist-tag, which moves from 17.x to 18 with it. A
11+
> `^17` dependency range still never moves to 18 by itself: move every
12+
> `@objectstack/*` dependency to 18 together, and read
13+
> [Upgrading](/docs/upgrading) before you do.
1214
1315
**The v18 line** exists for one decision whose changes do not fit in a 17.x
1416
minor: [ADR-0131](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0131-total-organization-ownership-no-null-organization-id.md),
1517
organization ownership is total — no NULL `organization_id`; declared metadata
1618
stays in code; a row exists only when an organization authored it. Its changes
1719
reshape stored data and narrow what the runtime accepts, so the ADR stages them
1820
in one major (its D14) instead of spreading them across 17.x minors. While the
19-
line is open, every other breaking change that lands on `main` ships on it too,
20-
under the same rules.
21+
line was open, every other breaking change that landed on `main` shipped on it
22+
too, under the same rules.
2123

2224
## How a breaking stage lands on this line
2325

2426
- **Through `next` before `latest`.** Every major is published to the `next`
2527
dist-tag for at least one RC cycle before `latest`
2628
([ADR-0087](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0087-metadata-protocol-upgrade-contract.md)
27-
D6). Changesets is in pre mode with the tag `next`, so every release cut from
28-
`main` is the next `18.0.0-next.N`, carrying everything merged since the cut
29-
before it.
29+
D6). While Changesets was in pre mode with the tag `next`, every release cut
30+
from `main` was the next `18.0.0-next.N`, carrying everything merged since
31+
the cut before it; 18.0.0 is the cut that takes the line to `latest`.
3032
- **One stage, one changeset, one migration.** ADR-0131 lands in stages, in the
3133
order the ADR records, and each stage that breaks something says so in its
3234
own changeset: what breaks, and how to move from the old shape to the new
@@ -59,6 +61,7 @@ under the same rules.
5961

6062
`npx skills remove --all` replaces the first command when these are the only
6163
skills the project has.
62-
- **GA ends the prerelease.** Reaching GA exits pre mode and publishes the line
63-
to `latest`. Curated notes for the line's releases are compiled at release
64-
time and are not written yet; until then, the changesets are the record.
64+
- **18.0.0 ends the prerelease.** It is the GA cut: it leaves pre mode and
65+
publishes the line to `latest`. Curated notes for the line's releases are
66+
compiled at release time and are not written yet; until then, the changesets
67+
are the record.

0 commit comments

Comments
 (0)