This repository was archived by the owner on Oct 26, 2026. It is now read-only.
Repository navigation
Commit 6f3299f
release(v18): objectui's first 18.x release — the sync major, Changesets pre mode on next, and the two gate edits (objectui#12334) (#12401)
Fixes #12334
Clause-②: no
objectui's first 18.x release, prepared in one PR: the sync `major` that
follows `@objectstack/*` from 17 to 18, Changesets pre mode on the
`next` tag, and the two gate edits. Nothing is published by this PR.
Publishing stays the maintainer's act (merging the version PR);
`changeset version` and `publish-plan` ran only on a scratch clone and
nothing they wrote is committed.
## What changes
1. **The sync major.** `.changeset/12334-objectstack-18-sync-major.md`
declares `major` for all 40 members of the `fixed` group, so every
package's CHANGELOG says why it crossed to 18. Its body is published
text; for what a consumer must do it points at the `@objectstack/*` 18
entry of objectui#12030.
2. **Pre mode on `next`.** `.changeset/pre.json`, written by `pnpm
changeset pre enter next`: `{ "mode": "pre", "tag": "next" }`.
3. **`scripts/check-changeset-no-major.mjs`, under the maintainer's
ruling on objectui#12030 (comment 6149296149).** A `major` entry passes
only when its package is in a `fixed` group AND that group's current
major (the `version` its members declare, one major for all) plus one
equals the major of the `@objectstack/spec` range its members declare in
`dependencies` / `peerDependencies` / `optionalDependencies` (one major
for all). Every other `major` is refused, with the reason printed per
entry. The range reader is narrow (`^`, `~`, `=` or a bare `X.Y.Z`,
prerelease allowed): a union, an open lower bound, an x-range or a
protocol spelling refuses the `major` instead of guessing one, and so do
members that disagree, a missing manifest, and a group none of whose
members declares the spec. Manifests are read only when a `major` is
pending. `OBJECTUI_ALLOW_MAJOR` is retired: the script reads no
environment, pinned by a test on its comment-masked source. No workflow
file changes.
4. **`scripts/check-spec-range-floors.mjs` reads a prerelease floor.** A
lower bound may name a prerelease, and that exact prerelease is the
floor: fetched from the registry and judged by its own export surface,
like a release floor. No ordering is added: two different prerelease
floors in one manifest, a `||` union with a prerelease branch, and the
replacement-floor search (now `replacementFloorLine`, extracted from
`main` so it is testable) still refuse or name nothing, and an
unrecognised spelling still throws.
5. **Prose.** In `AGENTS.md` and `content/docs/guide/ci-cd-pipeline.md`,
only the sentence that named `OBJECTUI_ALLOW_MAJOR` changes; each now
states the computed admission and points at the script header as the
authoritative statement. Six pending changesets get a one-clause
correction (below).
## The `.changeset/pre/` question, measured
Changesets 3 (installed `@changesets/cli` 3.0.1) keeps no consumed ids
in `pre.json`. `enterPre` (`@changesets/pre`) writes `mode` and `tag`
only. In pre mode, `changeset version` MOVES each consumed changeset to
`.changeset/pre/` (`@changesets/apply-release-plan`). The planner leaves
`pre/` out while `mode` is `pre` (`getRelevantChangesets` in
`@changesets/assemble-release-plan`) and reads it again only on `pre
exit`.
So the bump gate reads top-level `.changeset/*.md` only. It always did;
this PR states why in the header and pins it:
- **It does not trip on a consumed `major`.** After the first prerelease
the group is on `18.0.0-next.0`, whose major is already the spec's, so
reading `pre/` would refuse the consumed sync major.
- **It does not miss a pending one.** A new `major` lands at the top
level and is refused, because 18 + 1 is not 18. That is "every other
`major` is refused".
- **On `pre exit`** the planner reads `pre/` again, but it increments
the group's prerelease. A pre-major `X.0.0-TAG.N` increments to `X.0.0`
for every bump type, so a consumed `major` cannot move the group off 18.
Measured on a scratch clone of `bd8892e70`:
- `pnpm changeset:version` printed `Version: 17.7.0 → 18.0.0-next.0`.
All 40 group manifests went to `18.0.0-next.0`, 471 of the 471 pending
changesets moved to `.changeset/pre/` (0 left at the top level), and
`pre.json` was unchanged.
- On that tree the bump gate exited 0 ("No changeset declares a `major`
bump."). With one probe `major` added at the top level it exited 1:
"carries the group from 18 to 19, but its @objectstack/spec range names
18".
- `changeset publish-plan --output`: 39 entries, every one `publish` at
`18.0.0-next.0` on tag `next`. The 40th member, `object-ui`, is private.
- The release lane's post-version validation on that tree:
`quick-reference:check` exit 0 and `check:control-bytes` exit 0. `vitest
run scripts/__tests__`: 184 files passed and 3 failed. Two of the
failures, `check-lint-rule-coverage` and `turbo-lint-inputs`, come from
the scratch clone itself: its `node_modules` is a symlink, and `git
check-ignore` refuses a path "beyond a symbolic link". Both pass in the
real worktree. The third, `markdown-test-inputs` `stale-test`, was this
branch's own: the rewritten bump-gate test read `.changeset/` only
through the gate, which the scanner cannot see. `3cbf4dbb6` fixes it,
and the ledger needed no edit.
- Not exercised: the `Changeset Release` workflow itself. Its publish
lane on a pre-mode tree is read from its clear step, which already
removes `.changeset/pre/*.md` and keeps `pre.json`. It is not measured.
## The dispatch's mechanism assumptions, measured on `main` at `28fb2a0`
- **A1 holds.** Every `@objectstack/spec` range in the workspace is
`^18.0.0-next.1`. The fixed group is 40 members, all at `17.7.0`, and 22
of them declare the spec in a consumer-facing field.
- **A2: both readings are right, at different layers.** `minVersionOf`
throws on every range. `effectiveFloor` turns each throw into an
`unreadable-range` finding, and no package counts as floored. `main()`
then stops at the collapse alarm before printing any finding. `pnpm
check:spec-floors` exited 1 with "The scan collapsed: 0 package(s)
declare @objectstack/spec in a consumer-facing field, fewer than the 8
this repository has."
- **A3 holds.** On `main` there is no `.changeset/pre.json` and no
`.changeset/pre/`. `node scripts/check-changeset-no-major.mjs` exited 0
with "No changeset declares a `major` bump."
- **A4 holds.** `git grep OBJECTUI_ALLOW_MAJOR` finds it in the script,
`AGENTS.md` and the CI/CD guide, and nowhere under `.github/`. Control:
the same grep for `check-changeset-no-major` finds 4 lines in
`.github/workflows/changeset-guard.yml`.
- **A5: carried by objectui#11824** (PR #12355, `cfb2947`). That PR
rewrote the `{record.FIELD}` spelling in
`.changeset/11788-notify-recipients-picker.md` as the CEL value
envelope. Re-read at this head, "These are the values the messaging
service already resolves" holds: the notify node evaluates an envelope
recipient per run (`resolveRecipients` in objectstack `notify-node.ts`)
and hands the messaging service the resolved values. Left unchanged.
## Pending changesets re-read (6159211733)
The six corrections below each add one clause. Every frontmatter is
byte-identical: `check-changeset-overwrite` reports "declared at base"
equal to "declares now" for all six.
- **`.changeset/11880-grid-filter-handoff.md`, the page-1 bullet.** This
is the item the review named. "It now returns to page 1" now says that
in 18 this holds for a named view's filter only, because `ObjectView` no
longer reads `table.defaultFilters` (objectui#12030).
- **The general check found four more.** The grep was by symbol and by
the words that spell it, not by file path. Three retirements had landed
after objectui#12030's sweep, and one more was a flow-template spelling:
- `.changeset/11838-rename-expression-refs.md`: "a record field reads
`{x.field}`". In 18 that value is a CEL value envelope, because spec 18
refuses the single-brace token there (objectui#12101). This is the
flow-template class the review found.
- `.changeset/11880-repeater-datasource.md` and
`.changeset/12085-element-binding-inputs.md`: both still said the
repeater reads its flat `properties.object` / `filter` / `sort` /
`limit` as a fallback. objectui#12345 (PR #12366) removed that read
today and left these two unchanged.
- `.changeset/11865-access-panels-shared-select.md` and
`.changeset/11865-object-settings-shared-select.md`: both still named
the external sharing-model picker. objectui#12353 removed it today.
These two spell it "external sharing model" in words, so a grep for
`externalSharingModel` alone misses them.
- **Read and left as written:**
- `.changeset/12032-approval-requests-data-source.md`: "a record page
over a `provider: 'api'` source". This is historical wording about
`ApiDataSource`, the same reading objectui#12364's PR recorded.
- The `defaultFilters`, `manage_org_presentation`, `*_OBJECT_REQUIRED`,
`element:record_picker`, `actionType: 'navigation'` and `onSuccess`
hits: each is already corrected, is its own retirement entry, or
describes something that still holds.
- **This list is valid at this head only.** Changesets that land before
this PR goes ready need the same re-read.
## Acceptance, mapped
| Acceptance | Result |
|:--|:--|
| This PR's changeset passes the bump gate | exit 0,
"`.changeset/12334-objectstack-18-sync-major.md`: 17 → 18, 40 `major`
entries" |
| `pnpm check:spec-floors` reads every floor at `18.0.0-next.N`, exit 0
on a built workspace | exit 0; 22 of 39 published packages floored; 11
entry points of `@objectstack/spec@18.0.0-next.1`; `--cross-check`
agrees |
| `changeset version` + `publish-plan` on a scratch copy plan every
package at `18.0.0-next.N` on `next` | 39 of 39 `publish`,
`18.0.0-next.0`, tag `next` |
| A `major` when the group already equals the spec's major is refused |
fixture, and live on the post-version tree (18 to 19) |
| A `major` two above the group's major is refused | fixture (group 16,
spec 18) |
| An unreadable range still fails the floor gate | fixtures, plus a live
leg below |
| `.changeset/pre/` measured, the gate neither misses a pending `major`
nor trips on a consumed one | section above; pinned by two fixture tests
and a live-tree enumeration test |
| One ablation leg | below |
| Nightly `Spec Range Floors` alarm green on `main` after landing | not
measurable before merge |
## Verification at `3cbf4dbb6`
- **Tests.** `pnpm exec vitest run` on `check-changeset-no-major`,
`check-spec-range-floors`, `markdown-test-inputs`, `ci-cd-pipeline-doc`,
`check-pre-install-import-graph` and `check-changeset-presence`: 6
files, 268 tests passed, exit 0. `pnpm type-check:scripts` exit 0, and
`tsc --listFilesOnly` lists both test files. `eslint` on the four
changed scripts: exit 0.
- **Gates, run locally, all exit 0:**
- `check-changeset-no-major`, `check-changeset-overwrite` (report-only,
six "declared at base = declares now"), `check-changeset-fixed`,
`check-changeset-presence` ("no changeset is owed") and
`check-changeset-claims`;
- `check-pending-changeset-literals`, `check-control-bytes`, and
`check-pre-install-import-graph` (plus its `--self-test`);
- `check-new-cross-file-line-citations` (0 new), `check-doc-links`,
`check-doc-fence-languages`, `check-shell-escape-residue` and
`check-entry-guard`.
- **`pnpm check:spec-floors -- --cross-check`** exited 0 after `turbo
run build` of the 22 floored packages and their dependencies (33 tasks).
- **Ablation, three legs, each restored by a trap and checked by blob
hash.** `git diff HEAD` was empty after all three.
1. The base `check-changeset-no-major.mjs` restored over the head
(on-disk blob = the base blob). The repository test "declares no pending
`major` the gate refuses — run as CI runs it" goes red on its assertion
with the base gate's own message: "A changeset declares a `major` bump:
@object-ui/types (.changeset/12334-objectstack-18-sync-major.md:2) …".
The other red tests are the new exports the base lacks.
2. `minVersionOf`'s lower-bound reader put back to plain `X.Y.Z`: 5
tests red, all prerelease-floor pins.
3. Live negative control: `packages/core/package.json` given a union
with a prerelease branch. The gate exits 1 with `@object-ui/core
[unreadable-range] … cannot order "18.0.0-next.1" against "17.0.0"`.
## Acceptance notes (observations, not filed)
- `.github/workflows/changeset-release.yml`, the comment on "Clear
pending changesets for the publish branch", still describes Changesets
2's `pre.json.changesets`. It says this repository has no `pre.json` and
no `.changeset/pre/`, which is false once this lands. The step's code
already removes `.changeset/pre/*.md`, so behaviour is unaffected. The
file is governed and outside this PR's surface. Carrier: none.
## Landing holds
- `AGENTS.md` is a governed surface (`node
scripts/check-governed-queue-guard.mjs --test` names it), so this PR
stays draft until a `GOVERNED_APPROVERS` approval.
- Every row of the pre-release list on objectui#12334 (`6164681402` and
its updates) must be closed, or released by the maintainer, before this
PR goes ready. That check is the seat's.
## 维护者速读(草稿)
**改了什么**:为 objectui 第一次发 18.x 做好准备,但本 PR 本身不发版。四件事:① 一个 changeset 把整个
fixed 组(40 个包)从 17 升到 18,对齐 `@objectstack` 18;② 进入 Changesets 的 pre
模式,标签 `next`,所以发出去的是 `18.0.0-next.N`,npm 的 `latest` 不动;③ 「禁止 major」门禁按您在
objectui#12030 的裁决收窄:只有正好把 objectui 带到 `@objectstack/spec` 所依赖的那个大版本的
major 才放行,其余照旧拦,原来那个靠手动设置的环境变量开关同时退役;④ spec 版本下限门禁学会读 `18.0.0-next.1`
这种预发布下限,否则发版命令会在发布前自己中止。另外顺手改正了 6 条待发 changeset 里在 18 下已不成立的半句话。
**为什么改**:您的指示是「objectui 的下一个版本,发 v18」。依赖已经在 objectui#12030、#12370 两步升到
`@objectstack` 18 的预发布线,但版本号没跟上;两道门禁在 18 预发布线上要么误拦(major
门禁),要么直接把发版命令卡死(下限门禁)。
**风险与代价(含回滚)**:合并本身不发包;真正的发布仍是您合并版本 PR 那一步。pre 模式下每次版本 PR 都会发 `next`
标签,直到 `@objectstack` 18 正式版后再执行 `changeset pre exit` 发
`18.0.0`。回滚办法:revert 本 PR,也就是删掉 `pre.json` 和那条 major
changeset,门禁恢复原样。已知未验证的一处:发布流水线本身在 pre 模式下的实际运行,目前只按其清理步骤的写法推断能正常走。
**席位意见**:
**你要做的**:批准本 PR,它改了 AGENTS.md,属于受管面。版本 PR 是否合并、何时发 `18.0.0-next.0`,由您决定。
---
_Generated by [Claude
Code](https://claude.ai/code/session_01JZnppgHRp4sREcouhkQYDB)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: os-zhuang <jack@objectstack.ai>1 parent 140916c commit 6f3299f
14 files changed
Lines changed: 809 additions & 71 deletions
File tree
- .changeset
- content/docs/guide
- scripts
- __tests__
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
| 5 | + | |
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
| 5 | + | |
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
9 | 9 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
10 | 10 | | |
11 | 11 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
282 | 282 | | |
283 | 283 | | |
284 | 284 | | |
285 | | - | |
| 285 | + | |
286 | 286 | | |
287 | 287 | | |
288 | 288 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2576 | 2576 | | |
2577 | 2577 | | |
2578 | 2578 | | |
2579 | | - | |
2580 | | - | |
| 2579 | + | |
| 2580 | + | |
| 2581 | + | |
| 2582 | + | |
| 2583 | + | |
| 2584 | + | |
| 2585 | + | |
2581 | 2586 | | |
2582 | 2587 | | |
2583 | 2588 | | |
| |||
0 commit comments