Skip to content

Commit f86a10d

Browse files
docs(releases): the v18 landing page — the page check:release-notes needs before 18.0.0-next.0, behind the URL the CLI's @next pointer names (#22928)
Fixes #22919 Clause-②: no ## What this is The short v18 landing page that ruling `6049734955` (Q2 → A, on #22085) asks for, written on the maintainer's word on #22919 (release-owned channel 1). It gives the URL `packages/cli/src/utils/protocol-version-gap.ts` sends `@next` installers to (`https://objectstack.ai/docs/releases/v18`) a page behind it, and it is the page `check:release-notes` demands once the version pass writes an `18.x` heading into `packages/spec/CHANGELOG.md`. `scripts/check-release-notes.mjs` is not edited; no release action is taken. Files, v17's folder shape: - `content/docs/releases/v18/index.mdx` (new): a release-status blockquote, the line's purpose, and the rule for its breaking stages. - `content/docs/releases/v18/meta.json` (new): `"pages": ["index"]`. - `content/docs/releases/meta.json`: `"v18"` at the head of `pages`. - `content/docs/releases/index.mdx`: one line above the v17 line. - `scripts/docs-audit/handwritten-docs.json`: **+1 generated entry, outside the card's declared surface** (see Deviations). ## What the page says, and the source of each claim | Claim on the page | Source on `main` at `018b077fb` | | :--- | :--- | | No GA release yet; the line publishes as `18.0.0-next.N` on npm's `next` tag; `latest` stays on 17.x; a `^17` range never moves; install by `@next` or an exact `18.0.0-next.N` | `.changeset/pre.json` (`"mode": "pre"`, `"tag": "next"`, landed `a87d8be29`, PR #22084); `.changeset/22080-v18-line-opens.md` | | The line exists for ADR-0131 (its title), staged in one major per its D14 | `docs/adr/0131-…md` D14; the line-opens changeset ("ADR-0131 … lands on this line in stages") | | Every major goes to `next` at least one RC cycle before `latest` | ADR-0087 D6 | | Each breaking stage says so in its own changeset, with its migration; those changesets ship as each package's CHANGELOG | the line-opens changeset ("Each stage that breaks something says so in its own changeset, with its own migration"); AGENTS.md Post-Task Checklist step 3 | | `PROTOCOL_VERSION` is `18.0.0`; the handshake admits `'^18'` and refuses `'^17'` | `packages/spec/src/kernel/protocol-version.ts`, landed `4e9fe9ff6` (PR #22215); `.changeset/22130-protocol-18.md` | | GA exits pre mode and publishes to `latest` | the line-opens changeset ("What ends it") | The page names no change beyond those landed facts, states no date, and names no 18.x version other than `18.0.0-next.N`. Per H3, the 21 pending changesets carrying an `@objectstack/…: major` line (33 such lines in all) were read as a source for the staging rule and are not transcribed. One wording choice: the banner reads "v18 has no GA release yet" rather than "no v18 release yet". It stays true after `18.0.0-next.0` publishes, which is exactly what this page unblocks, so the page is not stale on its first prerelease. ## H1: the gate this clears fires only on the post-version tree (measured) `check-release-notes.mjs` reads majors from `packages/spec/CHANGELOG.md` headings, unanchored, so on this PR's head it is green with or without the page. The red it clears is the version PR's post-version tree. The simulation ran on scratch copies (`git archive` of `packages/spec/CHANGELOG.md`, `packages/spec/package.json`, `content/docs/releases`, `content/docs/meta.json` and `content/docs/index.mdx`), with the CHANGELOG given a `## 18.0.0-next.0` heading and `package.json` set to `18.0.0-next.0`, which is the shape the version pass writes. The worktree was not touched. | tree | `node scripts/check-release-notes.mjs` | | :--- | :--- | | base `018b077fb`, as committed | exit 0 | | base `018b077fb`, simulated post-version | **exit 1** (output below) | | head `0efecc249`, simulated post-version | **exit 0** (output below) | | head, simulated post-version, `"v18"` dropped from `meta.json` (control) | exit 1, "v18.mdx exists but is not listed in content/docs/releases/meta.json" | Without the page: ``` check-release-notes: 1 problem(s) • content/docs/releases/v18.mdx (or content/docs/releases/v18/index.mdx) is missing — @objectstack/spec shipped a 18.x release but there is no curated release page. Write it (lead with breaking changes + migration), then add "v18" to content/docs/releases/meta.json. ``` That is the message the triage reading `6087315917` quotes from the scheduled run's log. With the page: ``` check-release-notes: OK — every released major has a curated, navigable release page. ``` The other release-docs gates the post-version step runs, on the same simulated head tree: - `check-release-page-status`: exit 0. - `check-release-section-coverage --strict`: exit 0. - The version-pass rewriter `sync-release-index-currency` (`syncIndex()` on the scratch root): no rewrites, no findings, `index.mdx` byte-identical. ## H2: what `check:release-page-status` asks of this page (measured) - **During the `next` line: nothing.** `gaMajors()` matches only end-anchored headings, so `## 18.0.0-next.0` is not a GA heading and v18 is outside the set it judges. The `package.json` cross-check skips a prerelease version. It cannot express "no release yet", and it does not need to. - **At GA it reads exactly two places**: the first blockquote after the frontmatter, and the trailing parenthetical of the `index.mdx` line. The page puts its status in both on purpose. Simulated GA (`## 18.0.0`, version `18.0.0`) with this page unchanged gives exit 1 with three problems: the blockquote never states that an 18.x version is released, and the index status carries the `prerelease-word` and `prerelease-version` signals. So the gate forces the status rewrite at the GA cut. This page cannot go stale silently there, which is the v16/v17 status class the gate was built for. ## Gates Derived on this diff with `node scripts/pm/dispatch-gates.mjs --commands` (no paths): 57 commands for the five paths. The 47 the dispatch named are among them; adding `handwritten-docs.json` brought 10 more. All 57 exit 0 on head `0efecc249`. `--ran` with recorded exit codes reads: "57 derived, 57 run, 0 NOT-MEASURED, 0 UNRUN". Two prerequisites had to be met first, by building `@objectstack/spec`, `@objectstack/formula`, `@objectstack/lint`, `@objectstack/client` and `@objectstack/client-react`. On a fresh tree, `check:docs`, the two `@objectstack/lint` doc gates, `check:docs-transcript-drift` and `check:skill-examples` answer PREREQUISITE NOT MET (exit 3), not a verdict. MDX: the page compiles with `@mdx-js/mdx` 3.1.1. NOT MEASURED: `Build Docs`, which is CI's, and the live URL, because this container's egress denies `objectstack.ai`. ## Deviations - **`scripts/docs-audit/handwritten-docs.json` (+1 line), outside the card's `content/docs/releases/**`.** `check:docs-audit-scope` (in `lint.yml`, Lint & Repo Gates) reds on any hand-written page under `content/docs` that the generated list does not carry. On this branch's first commit it read: "1 hand-written doc(s) exist but are not listed … + content/docs/releases/v18/index.mdx. Fix: node scripts/docs-audit/check-audit-scope.mjs --write". The entry was regenerated with that command. The 17.7.0 release page carried the same one-line companion edit (`21c804c03`, PR #21994). It is its own commit (`62e32ad55`) so the seat can judge it apart from the page. Without it this PR cannot pass the required lint job. - The card asks this PR to follow SKILL.md's path fork "for a governed path". `content/docs/releases/**` is in no row of `GOVERNED_SURFACES` (`scripts/pm/check-governed-merges.mjs`), so the fork lands on the ordinary branch, and this body carries no maintainer quick-read section. The PR stays draft for the seat. ## Acceptance notes - The page links `/docs/upgrading`, not the generated `/docs/protocol-upgrade/18`. That page is built at docs-build time into a gitignored directory, so the offline lychee lane (`check-links.yml`, `--root-dir content`) cannot resolve it in a fresh checkout. - The "Versioning policy" section of `content/docs/releases/index.mdx` (unchanged here) still says a breaking change ships as a minor release and that `check-changeset-no-major.mjs` fails any pull request declaring a major. In pre mode that guard's RC exemption stands aside, and 21 changesets with a `major` line are pending on `main`. Release-side text; noted for whoever compiles the v18 notes, not edited here (the card asks for one index line). Labels: `skip-changeset`. The diff moves nothing any package's `files[]` ships. --- _Generated by [Claude Code](https://claude.ai/code/session_012yK1ddAdAqfzwigRHZq3r2)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent e357a44 commit f86a10d

5 files changed

Lines changed: 51 additions & 0 deletions

File tree

‎content/docs/releases/index.mdx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +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).
2122
- [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).
2223
- [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).
2324
- [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).

‎content/docs/releases/meta.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"title": "Releases",
33
"pages": [
4+
"v18",
45
"v17",
56
"v16",
67
"v15",
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
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."
4+
---
5+
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.
12+
13+
**The v18 line** exists for one decision whose changes do not fit in a 17.x
14+
minor: [ADR-0131](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0131-total-organization-ownership-no-null-organization-id.md),
15+
organization ownership is total — no NULL `organization_id`; declared metadata
16+
stays in code; a row exists only when an organization authored it. Its changes
17+
reshape stored data and narrow what the runtime accepts, so the ADR stages them
18+
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+
22+
## How a breaking stage lands on this line
23+
24+
- **Through `next` before `latest`.** Every major is published to the `next`
25+
dist-tag for at least one RC cycle before `latest`
26+
([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.
30+
- **One stage, one changeset, one migration.** ADR-0131 lands in stages, in the
31+
order the ADR records, and each stage that breaks something says so in its
32+
own changeset: what breaks, and how to move from the old shape to the new
33+
one. Those changesets become the `CHANGELOG.md` entries shipped inside each
34+
`18.0.0-next.N` package, so read the CHANGELOG of every prerelease you move
35+
to — moving from one `18.0.0-next.N` to the next can break you.
36+
- **Protocol 18 comes with it.** `PROTOCOL_VERSION` is `18.0.0` on `main`, so a
37+
v18 prerelease's handshake admits `engines.protocol: '^18'` and refuses
38+
`'^17'`. Read [Upgrading](/docs/upgrading) before you move an app's declared
39+
range.
40+
- **GA ends the prerelease.** Reaching GA exits pre mode and publishes the line
41+
to `latest`. Curated notes for the line's releases are compiled at release
42+
time and are not written yet; until then, the changesets are the record.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"title": "v18",
3+
"pages": [
4+
"index"
5+
]
6+
}

‎scripts/docs-audit/handwritten-docs.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@
203203
"content/docs/releases/v17/17-6.mdx",
204204
"content/docs/releases/v17/17-7.mdx",
205205
"content/docs/releases/v17/index.mdx",
206+
"content/docs/releases/v18/index.mdx",
206207
"content/docs/releases/v9.mdx",
207208
"content/docs/ui/actions.mdx",
208209
"content/docs/ui/apps.mdx",

0 commit comments

Comments
 (0)