Skip to content

chore(deps): move @objectstack/* to the next prerelease ^18.0.0-next.0 and follow its contract (objectui#12030) - #12337

Merged
os-zhuang merged 21 commits into
mainfrom
claude/issue-12030-objectstack-next-18
Oct 14, 2026
Merged

os-zhuang merged 21 commits into
mainfrom
claude/issue-12030-objectstack-next-18

Conversation

@objectstack-fleet

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

Copy link
Copy Markdown
Contributor

Fixes #12030
Clause-②: yes — 22 published @object-ui/* packages declare a consumer-facing @objectstack/* range that moves from ^17.x to ^18.0.0-next.0 (21 in dependencies, 1 in peerDependencies, counted from the manifests at the head), so a release would carry a published-contract change. node scripts/check-changeset-presence.mjs at 0cc4e8fcc: "102 source file(s) and 1 published-contract change(s) of 18 released package(s) changed, and this change declares 3 changeset(s)". .changeset/12030-objectstack-next-18.md declares the 22 packages minor, with the breaking-for-consumers note in its body; the changeset coverage of the other touched packages is below.

follow-up: #12334

Scope: the @objectstack/* move to ^18.0.0-next.0 and the fixes it forces. No objectui release. Releasing objectui 18.x (the AGENTS.md §版本号策略 sync major, Changesets pre mode on next, and the two gate edits ruled in records 6148150305 and 6149296149) moves to the follow-up card above, per the scope split recorded as 6149376719. This branch carried the sync major and .changeset/pre.json for a while (0b942ba); they are reverted (7ec3c2b), and neither gate script is edited.

Known effect after merge, intended: Spec Range Floors (scripts/check-spec-range-floors.mjs) cannot read ^18.0.0-next.0: at the head it exits 1 with "The scan collapsed: 0 package(s) declare @objectstack/spec in a consumer-facing field". Its nightly alarm on main turns red, and pnpm changeset:publish cancels any publish until the follow-up lands. That is the fail-safe that stops a 17.x release declaring 18 ranges. The open version PR #11600 (changeset-release/main) refreshes toward 17.8.0 and must not be merged before the follow-up.

What this does

Changeset coverage

Every published package this change touches, measured on the net diff from 72594f29e (the merge base since the main merge; the earlier rounds measured from cea429b98, before it, and the set is the same 32 published packages):

  • .changeset/12030-objectstack-next-18.md: the 22 packages whose consumer-facing ranges move, minor.
  • .changeset/12030-i18n-capability-labels.md: @object-ui/i18n, minor. The ten locale packs drop capability.label.manage_org_presentation and add capability.label.manage_mailboxes with spec 18's capability set. A key a consumer could read is removed, so the bump is minor, not patch.
  • .changeset/12030-console-bundles-spec-18.md: @object-ui/console and @object-ui/runner, minor. In both, the @objectstack/* ranges are devDependencies, but each is an app build whose published dist bundles them. The console bundles them in its vendor-objectstack chunk, measured under chore(console): lower the eager-closure line by the objectstack#22044 payback once objectui resolves an @objectstack/spec release carrying 93125aeeb8 #11762 below. The runner is a Vite app build (vite build, no build.lib, no external) whose aliases compile @object-ui/components, core, types and other @object-ui/* packages from src; those import @objectstack/spec at runtime. The runner line was added in the second patch round, after the opus re-review 6158463307 measured it.
  • @object-ui/plugin-calendar and @object-ui/plugin-kanban changed only a comment, and get no line. Measured: both rebuilt from source at 2c15e40cf (pnpm --filter … run build, after removing dist); grep -rF over each dist (their files[] publish dist, README.md, CHANGELOG.md, LICENSE) finds neither the changed sentence nor the unchanged comment sentence beside it, while code strings such as startDateField and ObjectKanbanRenderer are found.
  • @object-ui/collaboration, mobile, plugin-charts, plugin-report and sdui-parser get no line. The test: does the package's published files[] bundle anything this change touched? In each, the only manifest change is devDependencies["@objectstack/spec"], and the package's own sources are unchanged. collaboration, mobile and sdui-parser build with tsc, so their dist holds their own sources only. plugin-charts and plugin-report are Vite lib builds whose rollupOptions.external externalises every bare import, so no other package is compiled into them. None of them imports @objectstack/spec from non-test source.

Pending changesets on main reworded (patch round 3)

Commit 0cc4e8fcc. Eight pending .changeset/*.md that this change did not add carried sentences the spec-18 move makes false at release time. Each false clause is corrected in place, mostly by one clause pointing at objectui#12030; history is kept. In the quotes below, a type argument is spelled in words (PublicBlockNodeOf for 'element:repeater'), because GitHub's body sanitizer eats angle-bracket fragments; the files spell it as code. The wording is all that changed: every file's frontmatter (packages and levels) is byte-identical to 0d457fe1f (sha1 of each frontmatter block compared), and check-changeset-overwrite reports "declared at base" equal to "declares now" for all eight.

  • .changeset/6152-grid-default-filters-gantt-map-filter.md (@object-ui/types minor; core, plugin-grid, plugin-map, plugin-view patch)
    • before: "@objectstack/spec has typed ComponentPropsMap['object-grid'].defaultFilters as the same ViewFilterRule array as filter, [{ field, operator, value }, ...], since 17.6.0: the legacy fallback ObjectGrid reads only when filter is absent, …"
    • after: "@objectstack/spec typed ComponentPropsMap['object-grid'].defaultFilters as the same ViewFilterRule array as filter, [{ field, operator, value }, ...], from 17.6.0 until 18 retired it (see objectui#12030): the legacy fallback ObjectGrid read only when filter was absent, …"
    • before: "… so table: { defaultFilters: [{ field: 'status', operator: 'equals', value: 'open' }] } now parses there, on the tolerant and the strict face and through safeValidateSchema."
    • after: "… so table: { defaultFilters: [{ field: 'status', operator: 'equals', value: 'open' }] } parsed there through 17.x, on the tolerant and the strict face and through safeValidateSchema; retired in 18, see objectui#12030: the row's tombstone refuses defaultFilters by name, so every value, the rule array included, is refused there now."
    • before: "… with the protocol's own message, which computes the rule array from the record's keys. Respell defaultFilters: { status: 'open' } as defaultFilters: [{ field: 'status', operator: 'equals', value: 'open' }], or, better, move it to filter, which takes the same array and wins when both are written."
    • after: "… with the protocol's own message, which computed the rule array from the record's keys through 17.x (since 18, see objectui#12030, it is the retired-key message, which names filter). Respell defaultFilters: { status: 'open' } as filter: [{ field: 'status', operator: 'equals', value: 'open' }]; the rule-array defaultFilters spelling this entry first offered is retired in 18 too."
    • before: "ObjectGrid lowers defaultFilters through the same toFilterNode sink as filter, so a rule array there sends the same $filter and draws the same rows as the same array written as filter; the sink still lowers a record or an AST that reaches the slot at runtime, …"
    • after: "ObjectGrid lowered defaultFilters through the same toFilterNode sink as filter, so a rule array there sent the same $filter and drew the same rows as the same array written as filter (retired in 18, see objectui#12030: ObjectGrid and ObjectView no longer read defaultFilters, so a view that still carries it renders unfiltered); the sink still lowers a record or an AST that reaches filter at runtime, …"
    • before: "… and @object-ui/plugin-grid a pin of the above through the real renderer."
    • after: "… and @object-ui/plugin-grid a pin of the above through the real renderer (since 18 it pins that defaultFilters is not read)."
  • .changeset/11880-grid-filter-handoff.md (@object-ui/plugin-view patch)
    • before: "… else table.filter unless it lowers to nothing (absent, [] or {}), else the deprecated table.defaultFilters."
    • after: "… else table.filter unless it lowers to nothing (absent, [] or {}), else the deprecated table.defaultFilters (a rung retired in 18, see objectui#12030: ObjectView no longer reads it)."
    • before: "What did not change: which filter applies (each rung and each pair sends the same query and draws the same rows), and …"
    • after: "What did not change: which filter applies (each rung and each pair sends the same query and draws the same rows; in 18 the table.defaultFilters rung is retired, see objectui#12030), and …"
    • Left as written: the export and page-1 bullets, which say in the past tense what a table.defaultFilters did before this entry's change.
  • .changeset/12056-repeater-object-waiver.md (@object-ui/types minor)
    • before: "The zod arm ElementRepeaterBlockSchema now applies the same object waiver as the spec's props gate (objectui#12056)."
    • after: "The zod arm ElementRepeaterBlockSchema now applies the same object waiver as the spec's props gate (objectui#12056); superseded in 18, see objectui#12030: spec 18 retires the flat object, so the arm is the row by reference, a node may omit properties.object whether or not it binds one, and a properties.object is refused by name."
    • before: "ComponentPropsMap['element:repeater'] requires object." … "a node refinement puts the requirement back wherever no binding names the object."
    • after: "ComponentPropsMap['element:repeater'] required object through 17.x." … "a node refinement puts the requirement back wherever no binding names the object. Both waivers and both refinements are gone in 18 (objectui#12030): the row has no flat object left to waive."
    • before: "Still refused at properties.object. A bag with no object is refused when the node has no binding that names one: … The refusal is a custom issue with params.code ELEMENT_REPEATER_OBJECT_REQUIRED, and its message names both remedies. A properties.object of the wrong type is still refused by the row itself."
    • after: "Still refused at properties.object through 17.x. A bag with no object was refused when the node had no binding that names one: … The refusal was a custom issue with params.code ELEMENT_REPEATER_OBJECT_REQUIRED, and its message named both remedies; retired in 18, see objectui#12030: the refinement and its code are deleted, so such a bag is accepted. A properties.object of the wrong type is still refused by the row itself, and since 18 so is any properties.object, by name."
    • before: "TypeScript. The inferred ElementRepeaterBlockSchema type now types properties.object as optional, and so does the authoring type PublicBlockNodeOf for 'element:repeater' derived from it."
    • after: "TypeScript. The inferred ElementRepeaterBlockSchema type typed properties.object as optional through 17.x, and so did the authoring type PublicBlockNodeOf for 'element:repeater' derived from it; since 18 (objectui#12030) both follow the row, which retires object, so a typed properties.object: string no longer type-checks."
  • .changeset/7611-approver-registry-read.md (@object-ui/app-shell patch)
    • before: "A data binding (user, team, department, and position under the installed spec 17.7.0) still renders the record lookup … The type that admits the registry member before the installed spec declares it is marked for removal when objectui moves to spec 18."
    • after: "A data binding (user, team, department, and position under spec 17.7.0; spec 18, which objectui installs from objectui#12030, binds position to the registry) still renders the record lookup … The type that admitted the registry member before the installed spec declared it was marked for removal when objectui moves to spec 18; removed in 18, see objectui#12030."
  • .changeset/11880-element-datasource-only.md (@object-ui/components, app-shell, i18n patch)
    • before: "The flat keys stay published until @objectstack/spec retires them in v18; each input's description now says it is not read and names the binding member that is."
    • after: "The flat keys stayed published, each input's description saying it is not read and naming the binding member that is, until @objectstack/spec retired them in 18: the record picker's four inputs left with that retirement (objectui#12030), and element:number's two with objectui#12085."
  • .changeset/12056-repeater-datasource.md (@object-ui/app-shell patch)
    • before: "… and objectui validate accepts the node the designer now writes, because @object-ui/types takes the spec gate's object waiver for this element in the same change."
    • after: "… and objectui validate accepts the node the designer now writes: @object-ui/types took the spec gate's object waiver for this element in the same change, and since 18 (objectui#12030) the row has no flat object left to require."
  • .changeset/11880-repeater-datasource.md (@object-ui/types minor, @object-ui/components patch), found by the grep beyond the six named
    • before: "Its flat properties.object / filter / sort / limit stay read, as the fallback, until @objectstack/spec retires them in v18, so a repeater that carries only the flat keys reads exactly as before."
    • after: "Its flat properties.object / filter / sort / limit stay read, as the fallback (spec 18 retires them as authored keys, see objectui#12030, and the renderer keeps this read for metadata written before), so a repeater that carries only the flat keys reads exactly as before."
    • before: "… by reference, and its bag's object stays required. Clause-②: the strict authoring face (StrictAnyComponentSchema) now ACCEPTS a repeater carrying properties.object plus a well-formed dataSource, which it refused as an unrecognized key; …"
    • after: "… by reference, and its bag's object stays required (until objectui#12056's waiver, and retired in 18, see objectui#12030). Clause-②: the strict authoring face (StrictAnyComponentSchema) now ACCEPTS a repeater carrying properties.object plus a well-formed dataSource, which it refused as an unrecognized key (since 18 it refuses properties.object by name, so the accepted node carries the binding alone); …"
    • before: "A repeater whose bag omits object is refused at properties.object on both faces, as before."
    • after: "A repeater whose bag omits object is refused at properties.object on both faces, as before; retired in 18, see objectui#12030: such a repeater is accepted."
    • One clause here went false with objectui#12085, not with this change, and is corrected in the same edit because it sits in the same bullet: before "The registration now publishes the injected dataSource input; object stays required." after "The registration now publishes the injected dataSource input; object stays required (until objectui#12085 dropped the flat query inputs)." Evidence: the element:repeater registration in packages/components/src/renderers/basic/data-list.tsx at the head publishes titleField, fields, emptyText, divided and no object, and .changeset/12085-element-binding-inputs.md states the drop. The seat may ask for this one clause back out.
  • .changeset/12093-spec-main-compile.md (empty frontmatter, no release)
    • before: "… a retired-key tombstone on objectstack main), and @object-ui/app-shell's zh-CN overlay-scope label table keys org beside the spec's union (objectstack main narrows that union to env)."
    • after: "… a retired-key tombstone on objectstack main; the read itself is retired in 18, see objectui#12030), and @object-ui/app-shell's zh-CN overlay-scope label table keys org beside the spec's union (objectstack main narrows that union to env; the org label is dropped in 18, see objectui#12030)."

The grep over all 438 pending .changeset/*.md, besides this change's own three: defaultFilters hits 6152, 11880-grid-filter-handoff and 12093; ELEMENT_REPEATER_OBJECT_REQUIRED hits 12056-repeater-object-waiver only; ELEMENT_NUMBER_OBJECT_REQUIRED and manage_org_presentation hit nothing; the overlay-scope org hits 12093 only (12171-environment-overlay-copy names the environment overlay and stays true); the flat element query keys and the record picker hit 11880-element-datasource-only, 11880-repeater-datasource, 12056-repeater-datasource, 12056-repeater-object-waiver and 12085-element-binding-inputs. Read and left as written, each still true at release: 12085-element-binding-inputs.md (the repeater renderer still reads its flat keys as the fallback; this change does not touch it), 11903-record-picker-layout.md (the RecordPickerDialog, not element:record_picker), 12086-edit-inline-default-on.md, 7611-capability-registry.md (names no curated capability), 7611-decision-output-position-registry.md, and the "since 17.7.0" mentions elsewhere, which date a fact and do not say what is installed.

Merge of main

main at 72594f29e is merged into this branch (merge commit 1c95e13af): six commits, merged cleanly, none touching a manifest or the lockfile. Files both sides changed: packages/app-shell/src/views/metadata-admin/i18n.ts, packages/plugin-grid/src/ObjectGrid.tsx and the ten packages/i18n locale packs. The re-run after the merge is under Gates.

The break list (measured first, at a3f41ed: the bump and changeset alone)

Full vitest suite in five lock-held groups: 50 files, 159 tests red (types/core 15 files / 58 tests, app-shell 21 / 45, plugins A 6 / 20, plugins B 1 / 4, console + scripts 7 / 32). turbo run build and every package's type-check were green at that commit (81/81). Two repo gates were red: check:eager-closure (exit 2, ceilings drifted to 1.74x / 1.21x) and check:installed-pin-claims (23 findings). By area, and how each is closed:

  • Overlay scope is env only (objectstack#15206 S5; card comment 6098299437): data-objectstack overlay fixtures and docblock, two app-shell fixtures, and the zh scope label table drops its org row (an org from an older server renders raw), as the ruling's seat judgment says.
  • Index unique: true refused at protocol 18 (objectstack#22103): the index-fallback probe pins the refusal with a false control, the validation-preview help (en, zh) names unique: 'organization' / unique: 'global', and the data-protocol.ts docblock says refused. These are the three sites console: three sites still teach or pin a declared index's bare unique: true, which @objectstack/spec refuses since objectstack#22103 (the help text leads a user into a save-time 422) #11864 names; its legacy-row rendering case still passes and is left as is.
  • Capabilities: manage_mailboxes in, manage_org_presentation out; curated label set, default label, ten locale packs.
  • Page blocks: the element:number / element:repeater / element:record_picker flat query keys and object-grid defaultFilters are tombstones refusing by name (objectstack#11509). The number and repeater arms take the spec row by reference; the record_picker node and registration stop publishing the four keys; the parity, arm, harvest and ratchet pins read the tombstones.
  • Retired reads removed (seat judgment under the ruling): ObjectGrid no longer reads defaultFilters and ObjectView no longer reads table.defaultFilters; no in-repo producer writes the key. The tests that pinned it as a working alias are flipped to pin it inert beside a canonical filter control; the plugin-view README and docs page, the registration's filter description and the type's JSDoc say retired. The element:repeater renderer's flat object / filter / sort / limit fallback reads stay: apps/console/src/dev/DevLists.tsx writes properties.object and properties.limit and is routed in App.tsx, a live in-repo producer, reported instead of deleted. element:number and element:record_picker already read the binding only.
  • New spec checks and keys: checkPageSlotPair attached to both page node schemas beside the existing page checks (and listed among the chained refinements in the import-boundary census); checkPagePrintComposition and checkListViewChartBinding read a discriminator and are listed as not attachable; ObjectSchema's 45th key attachedOnRead; record:details sections' experimental count listed as deferred; the three new record component types stay out of the block palette, as today.
  • ListView requiredPermissions: pinned as the one pending declaration; the seat files a declare-and-enforce card.
  • Flow dialect (ADR-0032 §3): flow fixtures move to the spellings v18 accepts. The value-role ledger now names six key/value maps; each node's own config schema was measured to refuse a malformed envelope with exactly the sentences the editor shows. A {token} string in a value slot is refused by the spec and the editor shows that refusal; the recipient picker's {…} spellings and a blank Notify title are pinned as PENDING. The Studio cutover rides v18: Studio's flow text slots insert and prescribe {{ }} (the objectui half of objectstack-ai/objectstack#22110) #11824.
  • Approver position is a registry binding in v18: the spec-17 loosening is removed and the identity, directory and lookup pins read the registry arm.
  • Submit-redirect / url action: the refusal pins read the spec's own message; a url action target fixture is a path.
  • Installed-spec claims: re-measured and restamped where the fact holds, one historical mention ledgered; e2e/live/ci/backend.env moves to 18.0.0-next.0; QUICK_REFERENCE.md re-synced by its script; lockfile-integrity samples re-keyed; the declared-floor reader in core's test reads a prerelease floor by its core triple.

#11762: the eager-closure line comes down by the payback

objectstack#22044 (93125aeeb8) is an ancestor of the 18.0.0-next.0 tag commit (compare ahead, behind 0; control: the 17.7.0 tag commit 4e4e881427 also reads ahead). Two console builds, one container, one instrument (CI=true pnpm exec turbo run build --filter=@object-ui/console... --concurrency=2 under the verify lock, reading apps/console/dist/eager-closure.json):

chunk cea429b (main, 17.7.0) 5488ae7 (this branch) delta
vendor-objectstack 1,599,281 1,512,690 -86,591
ui-components 285,771 284,925 -846
everything else (70 names) 1,324,632 1,324,848 +216
aggregate 3,209,684 3,122,463 -87,221

MAX_EAGER_CLOSURE_GZIP_BYTES 3,281,467 to 3,194,246 and BASELINE onto 5488ae7; vendor-objectstack ceiling 1,623,000 to 1,536,409 and its baseline onto the same build. Lowered by the amount, not re-derived and not rounded; REGRESSION_THIS_GATE_MUST_CATCH_BYTES untouched. Headroom 71,783 bytes = 0.79x on the aggregate, 23,719 = 0.26x on vendor-objectstack: what main had on cea429b. The ruling's two later edits reach bundler inputs; the console build of 5db13ba reads 3,122,375 (-88), inside the band, recorded in the BASELINE prose and not re-pinned. The upstream figure (-226,301 on the chunk) was on an injected dist; the real release nets -86,591 here.

Held cards: their Restart-when probes at the head

card probe at the head (18.0.0-next.0) control
#11773 MetadataConflictErrorSchema in the spec's .d.ts exit 0 (next tarball and installed tree) @latest (17.7.0) tarball: exit 1
#11545 anonymousFormIntakeCandidates is a function exit 0 17.7.0: exit 1
#11681 a release carrying the objectstack#21995 change (objectstack-ai/objectstack#22021, c5658133fc) met: ancestor of d889448b93
#11970 lockfile resolves @objectstack/core and @objectstack/objectql carrying 4578c56e65 half: core 18.0.0-next.0 carries it; objectql is in no objectui manifest or lockfile, so the probe cannot be met as written
#11958 spec/ui exports PagePrintSchema and PRINTABLE_PAGE_COMPONENT_TYPES exit 0 17.7.0: exit 1
#11864 spec carries ef1fcb26a2 met; its three sites are changed in this PR
#11762 spec tag commit has 93125aeeb8 as ancestor met; executed in this PR
#12270 EmptyStateSchema link + InterfacePageConfigSchema.emptyState exit 0 17.7.0: exit 1
#12271 ListDraftsResponseSchema reads a draft's member exit 1 as written: the probe's fixture has no label, which the schema requires (drafts.0.label invalid_union). With label added: exit 0 with label, 17.7.0: exit 1
#12192 SECTION_HEADING_COUNT_HOLE is a RegExp exit 0 17.7.0: exit 1
#12314 stampCommentBodyEdit in @objectstack/plugin-audit dist the probe reads @latest (17.7.0): exit 1. Run against @next (18.0.0-next.0): exit 0

Gates (final head 0cc4e8fcc; each reading names the commit it ran on)

Patch round 3 (0cc4e8fcc: pending-changeset wording only, eight .changeset/*.md, no code, manifest or lockfile):

  • At 0cc4e8fcc, one script under the verify lock, VERDICT command-exit 0 (the script exits 1 if any gate does), each gate exit 0: check-changeset-presence ("102 source file(s) and 1 published-contract change(s) of 18 released package(s) changed, and this change declares 3 changeset(s)"), check-changeset-no-major ("No changeset declares a major bump."), check-changeset-fixed, check-changeset-overwrite (report-only: "3 changeset(s) added, 8 modified, 0 deleted", and for each of the eight the declared packages and levels at base equal those now), check:changeset-claims ("No pending changeset names a file this change touches."), check:pending-changeset-literals ("No test source names a pending changeset."), check:new-line-citations (0 new), check:control-bytes ("OK (scanned 8636 tracked text file(s); skipped 85 binary)"), check:installed-pin-claims (OK).
  • The script tests that read the live .changeset/ or run a changeset gate against this tree, at 0cc4e8fcc under the verify lock: pnpm exec vitest run --project unit --maxWorkers=2 over changeset-polarity-census, check-changeset-no-major, body-dialect-census, dollar-dialect-alias-census, check-changeset-claims, check-pending-changeset-literals, check-control-bytes, check-changeset-presence and check-changeset-overwrite: 9 files, 376 tests passed, VERDICT command-exit 0. No code moved, so no package test or type-check was re-run.

Patch round 2 (0d457fe1f: the runner changeset line, the three objectui-side moves named in the main changeset, and the last defaultFilters-is-read prose reworded, in the ObjectGridSlotKey docblock that ships in the published .d.ts, the zod mirror's member comment, the grid round-10 test header, the grid registration note and the ObjectGrid props note):

  • At 0d457fe1f, under the verify lock, each exit 0: check-changeset-presence ("declares 3 changeset(s)"), check-changeset-no-major, check-changeset-fixed, check:changeset-claims, check:pending-changeset-literals, check:new-line-citations (0 new), check:control-bytes, check:spec-symbols, check:installed-pin-claims.
  • pnpm exec turbo run type-check --filter=@object-ui/types --filter=@object-ui/plugin-grid --concurrency=2 --continue: 16/16. Then grid-default-filters-gantt-map-filter-round10-6152, object-view-slot-key-lists and imported-defaults-8317: 3 files, 392 tests passed.
  • git grep defaultFilters over non-test sources (READMEs, docs and changelogs aside): what is left says retired, not read; describes history (objectui#6152, objectui#11880); or is the declaration typed by the row's tombstone.

Patch round, after the main merge (1c95e13af; a1ca2ad55 only rewords the i18n changeset):

  • Changeset family and i18n gates at a1ca2ad55, under the verify lock, each exit 0: check-changeset-presence (above, "declares 3 changeset(s)"), check-changeset-no-major, check-changeset-fixed, check:changeset-claims, check:pending-changeset-literals, check:i18n-keys ("Every in-scope call-site key resolves against the en pack (3375 keys)"), check:i18n-drift, check:i18n-designer-parity, check:i18n-dead-keys (a report), check:control-bytes.
  • Type-check of the packages the merge touched, at 1c95e13af: pnpm exec turbo run type-check --filter=@object-ui/app-shell --filter=@object-ui/components --filter=@object-ui/data-objectstack --filter=@object-ui/i18n --filter=@object-ui/plugin-detail --filter=@object-ui/plugin-grid --filter=@object-ui/types --concurrency=2 --continue, 36/36.
  • Tests the merge brings into contact with this diff, at 1c95e13af. The set: every package main and this branch both changed (plugin-grid, i18n, data-objectstack, types) in full; every test file main added or changed, now running on spec 18; and every app-shell test that imports metadata-admin/i18n. Result: 920 files passed, 16,446 tests passed, 13 skipped. The merge touches no manifest and no lockfile, so the whole suite was not re-run; this head's CI shards are the whole-workspace reading.

Before the patch round:

  • Install: pnpm install --frozen-lockfile exit 0, then a plain pnpm install leaves pnpm-lock.yaml byte-identical (sha256 compared), at e8e9a35; the lockfile and every manifest are unchanged since (git diff e8e9a35 HEAD over them is empty). Lockfile diff against cea429b: +106 / -106.
  • Build: CI=true pnpm exec turbo run build --filter=@object-ui/console... --concurrency=2, exit 0, 35/35 tasks, at 5db13ba (the last commit touching a bundler input); the whole published set was built (43 tasks) by pnpm check:published-dist at e8e9a35.
  • Type-check: pnpm exec turbo run type-check --concurrency=2 --continue, 81/81, at 5db13ba (later commits touch only scripts, tests and the changeset); pnpm type-check:scripts && pnpm type-check:vitest-setup && pnpm type-check:e2e && pnpm type-check:vitest-config, exit 0, at 2c15e40cf.
  • Tests (pnpm exec vitest run --maxWorkers=2, five lock-held groups):
    • types, core, react, i18n, cli, data-objectstack and 12 more at 5488ae7: 1019 of 1020 files; the red one (imported-defaults-8317, from attaching checkPageSlotPair) is fixed in ef2054e and re-ran green (267 tests). Later commits touch these packages only in one JSDoc.
    • app-shell at ef2054e: 1319 passed, 1 skipped (12,730 tests). After the org label drop, the four overlay-scope files re-ran green at 2e80824ea (21 tests).
    • plugin-detail, plugin-grid, plugin-form, plugin-dashboard, components at 2e80824ea: 1207 passed, 2 skipped (12,292 tests).
    • fields and the other 15 plugins at 7ec3c2b: 1031 passed, 2 skipped (11,505 tests).
    • apps/console, scripts, eslint-rules, examples at 7ec3c2b: 429 passed, 2 failed. check-eager-closure-budget.test.ts pinned the rendered BASELINE literal: re-taken in 2c15e40cf and green there. date-only-zone-pins-10183.test.ts is red at 2c15e40cf too, and is NOT caused by this diff: its forked child fails one case, the suite-zone control of FormulaFunctions.dateOnlyZone-10866, which reads Asia/Shanghai (11:00) instead of UTC (03:00). That is the zone another pin file sets last. The unit project runs isolate: false, and the file order comes from each worktree's vitest cache. Run alone in the same forked child at 2c15e40cf, that file passes (39/39). The same driver passed 28/28 at a3f41ed in a fresh worktree. This diff touches neither the pin files nor the code they exercise.
  • Repo gates at 2c15e40cf, exit 0 unless noted: check-changeset-presence (above), check-changeset-no-major ("No changeset declares a major bump."), check-changeset-fixed, check:changeset-claims, check:pending-changeset-literals, check:installed-pin-claims (OK), check:spec-symbols, check:phantom-deps, check:new-line-citations (0 new), check:control-bytes, check:eager-closure ("3049.2 KB gzipped across 72 of 2255 chunks (budget: 3119.4 KB, headroom: 70.2 KB)", every ceiling in range). check:spec-floors exits 1, the known effect above. .changeset/pre.json is absent. check:lockfile-integrity, check:lockfile-dedupe, check:unused-deps and check:published-dist were green at 2e80824ea / e8e9a35 and nothing they read has changed since.

Acceptance notes


Generated by Claude Code

claude added 15 commits October 13, 2026 09:09
…0 (objectui#12030)

Every @objectstack/* range in dependencies, devDependencies and
peerDependencies (40 ranges in 32 manifests) moves from ^17.x to
^18.0.0-next.0. The ranges were raised textually, so no other manifest
byte moved, and pnpm-lock.yaml was regenerated by `pnpm install` only.
A frozen install exits 0 and a second plain install leaves the lockfile
byte-identical.

Claude-Session: https://claude.ai/code/session_01CsyMRsFJBKNEMa4oPY1b5z
Co-authored-by: Claude <noreply@anthropic.com>
…ectui#12030)

The 22 published packages whose dependencies or peerDependencies name an
@objectstack/* range take a minor, with the consumer-facing break stated
in the body. No major is declared.

Claude-Session: https://claude.ai/code/session_01CsyMRsFJBKNEMa4oPY1b5z
Co-authored-by: Claude <noreply@anthropic.com>
…ope and its refusal of a bare unique index (objectui#12030)

@objectstack/spec 18 narrows the metadata overlay scope to 'env' (the 'org'
member is gone), so the overlay fixtures write 'env' and the scope's docblock
and type pin read the one-member enum. The zh scope label table keeps its
'org' row beside the union, unchanged, for a server still on 17.x.

Protocol 18 refuses a bare `unique: true` on an index: the index-fallback
probe now pins that refusal with a `false` control, and the validation-preview
help text names the scoped spellings ('organization', 'global') instead.

The connect lifecycle in data-objectstack's index.ts is not touched.

Claude-Session: https://claude.ai/code/session_01CsyMRsFJBKNEMa4oPY1b5z
Co-authored-by: Claude <noreply@anthropic.com>
…n, manage_org_presentation out (objectui#12030)

@objectstack/spec 18 adds `manage_mailboxes` to PLATFORM_CAPABILITIES and
retires `manage_org_presentation` (objectstack#15206 S3). The curated label
set the spec-parity pin compares against follows, the default label and the
ten locale packs swap the retired key's label for the new one.

Claude-Session: https://claude.ai/code/session_01CsyMRsFJBKNEMa4oPY1b5z
Co-authored-by: Claude <noreply@anthropic.com>
…ontract (objectui#12030)

@objectstack/spec 18 retires the flat query keys of element:number,
element:repeater and element:record_picker (object / filter / sort / limit and
the record_picker display keys' query siblings, objectstack#11509) and
object-grid's `defaultFilters` as tombstones that refuse by name. The
number / repeater arms drop their pre-18 waiver and take the row by
reference; the record_picker node and registration stop publishing the four
keys; the parity, arm and harvest pins read the tombstones.

The spec adds `checkPageSlotPair`, now attached to both page node schemas
beside the other page checks (its siblings `checkPagePrintComposition` and
`checkListViewChartBinding` read a discriminator and are listed as not
attachable); ListView gains `requiredPermissions` (pinned as the one
pending declaration, see the PR), ObjectSchema gains `attachedOnRead`
(45 keys), record:details sections gain an experimental `count`, and three
new record component types (approvals, attachments, approval_decision) stay
out of the block palette, as today.

Claude-Session: https://claude.ai/code/session_01CsyMRsFJBKNEMa4oPY1b5z
Co-authored-by: Claude <noreply@anthropic.com>
…egistry and redirect messages (objectui#12030)

@objectstack/spec 18 (ADR-0032 §3) reads a flow text slot's `{{ }}` template
only and a value slot's string as the literal it spells, refusing a `{…}`
token there in favour of a CEL value envelope. Flow fixtures move to the
spellings the spec accepts; the value-role ledger now names six key/value
maps (screen defaults, script inputs and subflow input join), measured to
refuse a malformed envelope with the editor's own sentences; and the pins
that restated `{token}` acceptance now read the spec's refusal. The Studio
behaviour is unchanged: the editor still writes what it wrote and shows the
spec's verdict; the recipient picker's template spellings and a blank Notify
title are pinned as pending, for the decision the PR names.

Approver `position` is a registry binding in spec 18, so the spec-17
loosening of the value-source table is removed and the identity, directory
and lookup pins read the registry arm. The submit-redirect refusal pins
read the spec's message instead of a dated ruling citation it dropped, and a
url action target is a path, as the spec now requires.

Claude-Session: https://claude.ai/code/session_01CsyMRsFJBKNEMa4oPY1b5z
Co-authored-by: Claude <noreply@anthropic.com>
…e floor reader to 18.0.0-next.0 (objectui#12030)

Each claim that named 17.7.0 as the installed @objectstack/spec was
re-measured on 18.0.0-next.0 and restamped where the fact still holds; the
one that names 17.7.0 as the release that closed a fork is ledgered as
historical. The live-backend pin moves to the release the tag
@objectstack/cli@18.0.0-next.0 names, QUICK_REFERENCE is re-synced by its
script, the lockfile-integrity samples are re-keyed, and the declared-floor
reader reads a prerelease floor by its core triple, refusing the floor's own
prerelease.

Claude-Session: https://claude.ai/code/session_01CsyMRsFJBKNEMa4oPY1b5z
Co-authored-by: Claude <noreply@anthropic.com>
…rrors chain (objectui#12030)

Attaching spec 18's checkPageSlotPair to PageNodeSchema and PageKindNodeSchema
puts a raw spec read in layout.zod.ts; the import-boundary census accepts a
chained check function by name, as it does checkPageRequiresKind.

Claude-Session: https://claude.ai/code/session_01CsyMRsFJBKNEMa4oPY1b5z
Co-authored-by: Claude <noreply@anthropic.com>
… payback the 18.0.0-next.0 bump carries (objectui#12030, objectui#11762)

The fourth raise (objectui#11717) filed objectstack#22044 as its payback;
the 18.0.0-next.0 release carries it, so the ceiling, BASELINE and the
vendor-objectstack per-chunk rows come down by what the bump recovered,
measured on two console builds in one container: cea429b (main, 17.7.0)
3,209,684 against 5488ae7 (this branch) 3,122,463, -87,221 aggregate and
-86,591 on vendor-objectstack. Lowered by the amount, not re-derived as a
reading plus half a regression and not rounded; the regression constant is
untouched.

Claude-Session: https://claude.ai/code/session_01CsyMRsFJBKNEMa4oPY1b5z
Co-authored-by: Claude <noreply@anthropic.com>
…eased from Changesets pre mode on tag next (objectui#12030)

The maintainer's ruling (record 6148150305 on objectui#12030): objectui's
next release ships v18. This PR's changeset becomes the AGENTS.md
§版本号策略 sync major, the one major that policy admits, and the
repository enters Changesets pre mode on tag `next`
(`pnpm changeset pre enter next`), so the release is 18.0.0-next.N on the
npm `next` dist-tag and `latest` stays on 17.7.0.

Claude-Session: https://claude.ai/code/session_01CsyMRsFJBKNEMa4oPY1b5z
Co-authored-by: Claude <noreply@anthropic.com>
… enum (objectui#12030)

Spec 18 narrows the overlay scope to 'env' (objectstack#15206 S5). The seat's
judgment under the maintainer's ruling 6148150305, as break-list item
6098299437 prescribes: the zh label table keys the union alone, and an 'org'
from an older server renders raw.

Claude-Session: https://claude.ai/code/session_01CsyMRsFJBKNEMa4oPY1b5z
Co-authored-by: Claude <noreply@anthropic.com>
…faultFilters (objectui#12030)

@objectstack/spec 18 tombstones object-grid.defaultFilters (objectstack#11509)
and refuses it by name; the seat's judgment under the maintainer's ruling
6148150305 is that a retirement takes effect at once. ObjectGrid drops its
alias read and ObjectView drops the table.defaultFilters rung, as
objectui#12093 said it would at the pin that carries the tombstone. No
in-repo producer writes the key. The tests that pinned it as a working alias
are flipped to pin it inert beside a canonical filter control; the plugin-view
docs, the registration's filter description and the type's JSDoc say retired.

Claude-Session: https://claude.ai/code/session_01CsyMRsFJBKNEMa4oPY1b5z
Co-authored-by: Claude <noreply@anthropic.com>
…wo edits, not re-pinned (objectui#12030)

The org label drop and the defaultFilters read removal reach bundler inputs
after the 5488ae7 reading BASELINE carries. The console build of 5db13ba
reads 3,122,375 (-88), inside the band, so neither constant moves; the
BASELINE prose says so instead of claiming no later commit reaches a bundler
input.

Claude-Session: https://claude.ai/code/session_01CsyMRsFJBKNEMa4oPY1b5z
Co-authored-by: Claude <noreply@anthropic.com>
… 18, released from Changesets pre mode on tag next (objectui#12030)"

This reverts commit 0b942ba.

The scope split recorded as 6149376719: this change is the dependency move
only, so its changeset goes back to minor and .changeset/pre.json is removed.
The objectui 18.x release (the sync major, pre mode on tag next, and the two
gate edits of 6148150305 and 6149296149) moves to objectui#12334.

Claude-Session: https://claude.ai/code/session_01CsyMRsFJBKNEMa4oPY1b5z
Co-authored-by: Claude <noreply@anthropic.com>
…e suite pins, 3160.1 to 3049.3 (objectui#12030)

The literal is BASELINE.gzipBytes rendered, re-taken each time the baseline
moves; objectstack#22044's payback moved it.

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

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: opus — maintainer waiver 6158097279, in place of CONTRACT_REVIEW_TIER
Head-sha: 0cc4e8fcc2c74835de7a0616ab81231a8faec981
Local-runs: none

Inputs read:

  • Card deps(v18): move objectui's @objectstack/* dependencies to the next prereleases (18.0.0-next.N) ahead of 18.0 GA — the maintainer's ruling, since 17.x ships no new release #12030: its body and all 14 comments. These are the break-list items 6082075642, 6093491679, 6095969443 and 6098299437, triage 6141844088, claim 6142088237, rulings 6148150305, 6149296149 and 6149376719, report 6151240488, seat ACCEPT 6151458792, and addenda 6158199329, 6158558223 and 6158973185.
  • PR chore(deps): move @objectstack/* to the next prerelease ^18.0.0-next.0 and follow its contract (objectui#12030) #12337: its body and its 154-file list over two API pages. The list and its per-file +/− counts are identical to git diff --numstat 72594f29ec...0cc4e8fcc.
  • The net three-dot diff from merge base 72594f29ec, read in full: 7,340 lines, lockfile included.
  • The records 6158813708, 6158463307 and 6151661549.
  • The 35 check-runs on the head, the Spec Main Shape Gate annotations, and the job logs of Changeset Declaration, Changeset Bump Policy, Changeset Claim Re-read and Changeset Overwrite Report.
  • AGENTS.md §版本号策略 at the head.
  • Head-ref reads: .changeset/config.json, the touched manifests, the eight reworded pending changesets in full, a grep of every pending .changeset/*.md for the symbols this diff moves, app-shell's entry, toFilterNodeSafely in filter-converter.ts, the Spec Main Shape Gate workflow header, and git grep for defaultFilters and for runtime @objectstack/* imports in the five devDependency-only packages.

Nothing was built, run or re-run.

① Derived judgments

Gate verdicts on the head.

  • 35 check-runs, all completed on 0cc4e8fcc: 31 success, 3 skipped (dependabot and the two Test (coverage) jobs) and 1 failure.
  • The failure is Spec Main Shape Gate (job 115633533324).
    • Its 20 failure annotations (10 distinct, each reported twice) name two files only: packages/core/src/adapters/resolveDataSource.ts:59-62 and packages/react/src/hooks/useViewData.ts:124-125.
    • Every one is the view-level provider: 'api' retirement (objectstack#23160), compiled against a spec built from objectstack main 18cd410dc405, not against 18.0.0-next.0.
    • This PR touches neither file and no .github/ file. The workflow header at the head calls the context advisory on a pull request (objectui#12240).
    • Not a defect of this head. Its carrier is objectui#12325.
  • Every other context is success: Lint, Type Check, Repo Gates, Test with all 12 shards, Test (dist pins), both lockfile checks, the five changeset guards, Governed Surface Queue Guard, Line Citation Gate, Bundle Analysis, Build & E2E, Build Docs, Live E2E and label.
  • The changeset guards name 2b06a91e6 as the merge base with main. So main has moved two commits past 72594f29e (objectui#12340 and objectui#12336, which touch the ten locale packs again), and these runs are on the PR merged with it. The green covers current main.

Delta since the last record (0d457fe1f → 0cc4e8fcc). One commit, eight .changeset/*.md, +32/−27.

  • Wording only. Each file's frontmatter block hashes the same (sha1) at 72594f29e, at 0d457fe1f and at the head. Changeset Overwrite Report prints "declared at base" equal to "declares now" for all eight. No other file moves.
  • Each new clause is true at the head:
    • 6152-grid-default-filters-gantt-map-filter.md:
      • The tombstone refuses every value by name. grid-default-filters-gantt-map-filter-round10-6152 pins it on the row, on the mirror and on table.defaultFilters.
      • The retired-key message names filter, which is pinned.
      • "The sink still lowers a record or an AST that reaches filter" is true: ObjectGrid lowers filter through toFilterNodeSafely, which wraps toFilterNode.
      • The plugin-grid pin now pins that the key is not read.
    • 11880-grid-filter-handoff.md: the rung is retired, and gridTableFilterRung answers undefined.
    • 12056-repeater-object-waiver.md:
      • The arm is the row by reference.
      • A node with no object is accepted.
      • properties.object is refused by name.
      • The refinement and its code are deleted.
    • 7611-approver-registry-read.md: APPROVER_VALUE_SOURCES.position is { source: 'registry', type: 'position' } (pinned), and the loosening is removed.
    • 11880-element-datasource-only.md: the record picker's four inputs leave in this diff. element:number's two left with objectui#12085, as 12085-element-binding-inputs.md says.
    • 12056-repeater-datasource.md: true.
    • 11880-repeater-datasource.md:
      • The renderer keeps its flat reads; data-list.tsx is untouched.
      • The strict face refuses properties.object by name.
      • A bag with no object is accepted.
      • The dev's extra clause "(until objectui#12085 dropped the flat query inputs)" is true: the 12085 changeset says the repeater registration drops object, which was required: true.
    • 12093-spec-main-compile.md: no release, and both added clauses are true.
  • Nit, not blocking. 11880-grid-filter-handoff.md's page-1 bullet still says that changing a table.defaultFilters in place now returns the grid to page 1. This PR deleted that test row, saying "a key nothing reads cannot move the page". The lead paragraph's new retirement clause covers it for a careful reader.

Accept-set and public-surface changes the whole net diff implies, judged afresh:

  1. Ranges and lockfile. Right.
    • 40 ranges in 32 manifests: 26 in dependencies, 13 in devDependencies and 1 in peerDependencies.
    • 22 published packages carry the range in a consumer-facing field: 21 in dependencies plus plugin-list's peer. These match the main changeset's 22 names one for one.
    • The lockfile diff is +106/−106. It moves only @objectstack/{spec,client,core,formula,lint,types,sdui-parser} from 17.7.0 to 18.0.0-next.0, with their seven integrity lines.
  2. packages/types. Right.
    • ElementNumberBlockSchema and ElementRepeaterBlockSchema. The .partial({ object: true }) bags and the two ELEMENT_*_OBJECT_REQUIRED refinements go, and both bags are the rows through propsBag.
      • NARROWS: a flat object or filter is refused by name (invalid_type), and so are the repeater's sort and limit. Each is pinned against the row's own verdict.
      • WIDENS: a node that binds no object is accepted, as PageComponentSchema and the row accept it. This follows the module's rule to refuse nothing the spec accepts. The differential probes carry both verdicts.
    • ElementRecordPickerNode's bag is the published row.
    • checkPageSlotPair is chained on PageNodeSchema and PageKindNodeSchema. This narrows the accept set. The test asserts the spec's own issue at slots.details, with either-slot-alone controls, and it closes pointer 6093491679.
    • Recorded as not attachable: checkPagePrintComposition and checkListViewChartBinding. They read type and regions, which are not carried by reference. So objectui's faces accept those two compositions, and only the spec doors judge them. This is the checkListViewPageMount precedent, and both checks are new in 18.
    • ObjectGridSchema.defaultFilters is typed by the row's tombstone on both twins, and table.defaultFilters is refused for every value. Its docblocks say retired.
    • Census counts:
      • named list view: 50 → 51 keys, with requiredPermissions pinned PENDING by name (Q2, objectui#12341);
      • ObjectSchema: 44 → 45 keys (attachedOnRead);
      • record:details sections: count becomes the ninth deferred key.
  3. packages/components. Right.
    • The element:record_picker registration drops its object, filter, sort and limit inputs. A JSX page that writes one gets unknown-prop, pinned with a labelField control.
    • The block is not in PUBLIC_BLOCKS, so sdui.manifest.json does not move.
    • The repeater's flat fallback reads stay for the live producer DevLists.tsx. objectui#12345 carries them.
  4. packages/plugin-grid and packages/plugin-view. Right.
    • ObjectGrid drops the defaultFilters read, its legacy $filter branch, its effect dependency and the toFilterNode import.
    • ObjectView drops the third rung on all three paths.
    • Consumer effect: a stored view that carries only defaultFilters now renders and exports unfiltered. Q4 ordered this, and the changeset, the README and the docs page say so.
    • Every flipped test keeps a canonical filter control.
  5. packages/data-objectstack. Right. The exported MetadataOverlayScope narrows to 'env' | null by derivation from the spec enum. This is break-list item 6098299437.
  6. packages/app-shell. Right.
    • Approver position reads the registry arm. No exported symbol moves: the package exports only ., and its index names none of these utils.
    • LAYER_SCOPE_ZH drops org (Q8). translateConsoleValue hands an unknown value back raw.
    • Flow dialect:
      • The value-slot editor shows VALUE_SLOT_TEMPLATE_REFUSAL on a {…} string.
      • The envelope toggle reaches three more maps, each measured against its own node schema.
      • The recipient {…} spellings and a blank Notify title are pinned PENDING by name (objectui#11824, objectui#12343).
    • Other edits:
      • PALETTE_EXCLUSIONS gains three entries (objectui#12342).
      • The unique help names 'organization' and 'global'.
      • The submit-redirect pins compare against the spec's own submitBehavior.url message.
  7. packages/fields and packages/i18n. Right. manage_mailboxes comes in, and manage_org_presentation leaves the curated set, the default label map and all ten packs. This is break-list item 6082075642.
  8. packages/plugin-detail. Right. The published sections input description names count as a ninth key the renderer does not read yet, which is true (deferred, objectui#12192).
  9. Scripts and pins. Right.
    • The eager-closure ceilings come down by exactly the measured delta: aggregate 3,281,467 → 3,194,246, and vendor-objectstack 1,623,000 → 1,536,409.
    • REGRESSION_THIS_GATE_MUST_CATCH_BYTES is untouched, and Bundle Analysis is success.
    • One historical row is added to the installed-pin ledger.
    • The core floor reader refuses a prerelease whose triple equals the floor.
    • No gate script named by the split is edited, and there is no .changeset/pre.json.
  10. The main merge (1c95e13af). Right. Current main (2b06a91e6) is also green under these check-runs.

No accept-set or public-surface change in the diff is wrong.

② Semver level

  • Three new changesets, all minor, none major. Right under AGENTS.md §版本号策略 (objectui's own breaking changes ship as minor), as split ruling 6149376719 narrows it.
    • Bump Policy: "No changeset declares a major bump."
    • Declaration: "102 source file(s) and 1 published-contract change(s) of 18 released package(s) changed, and this change declares 3 changeset(s)".
    • 12030-objectstack-next-18.md covers the 22 consumer-facing packages, the consumer break, the three objectui-side moves and the defaultFilters retirement.
    • 12030-i18n-capability-labels.md covers @object-ui/i18n.
    • 12030-console-bundles-spec-18.md covers @object-ui/console and @object-ui/runner, two app builds whose dist bundles spec 18 and the changed sources.
  • Every touched published package is accounted for. That is 32 published packages; site and test-support are private and ignored.
    • collaboration, mobile and sdui-parser (tsc builds) and plugin-charts and plugin-report (lib builds that externalise every bare import) change only a devDependency range. Re-measured at the head: every @objectstack/ mention in their non-test sources is a comment, with no runtime import. No line: right.
    • In plugin-calendar and plugin-kanban the edits are comments only: one inside a component body, one above a non-exported const. No line: right.
    • Every other source edit falls in a package that the main changeset names.
  • The eight reworded pending changesets keep their packages and levels. Their frontmatter is byte-identical, so the release's level set does not move.
  • ⚠️ Went false, level unaffected: one more sentence the round-3 sweep did not reach.
    • .changeset/11788-notify-recipients-picker.md:8 (@object-ui/app-shell patch, pending) says the recipient picker's {record.FIELD} rows are "the values the messaging service already resolves".
    • This diff's own pin in FlowRecipientsField.test.tsx says spec 18 refuses a {…} token in recipients, "so a flow it writes is refused by an 18 server". Both sentences publish into the same release.
    • Record 6158813708 routed this as a note for objectui#11824's carrier. Judged afresh, it is the same WENT FALSE class as the eight this PR reworded: the spec-18 move in this diff falsifies it.
    • The PR body's sweep names the classes it grepped: defaultFilters, the element flat keys, the record picker, the capability and the org scope. The flow-dialect class is not among them, and 11788 is in neither its "reworded" list nor its "read and left as written" list.
    • Read and left: 11838-rename-expression-refs.md uses {x.field} only as an example. Its claim, what a rename updates, stays true.
  • Clause-②: line. It is on PR line 2 as yes, with 22 packages (21 in dependencies, 1 in peerDependencies). Right.
  • Release consequence, already ruled. Merging releases nothing. Spec Range Floors cancels any publish until objectui#12334 lands, and chore: release packages (next) #11600 must not merge before it (6149376719).

③ Boundary flags

Escalations of record 6158813708, each re-read at this head:

  • ② pending changesets this diff made false: ANSWERED. All six named are reworded, plus two the dev found (11880-repeater-datasource and 12093-spec-main-compile). The edits are wording only, the frontmatter is byte-identical, and each is now true (①).
  • PR-body nit: ANSWERED. The coverage section now measures from 72594f29e and names the earlier base.
  • The 11788 note for objectui#11824's carrier: NOT RECORDED on the card or in the PR body. It is re-escalated as the ② finding above.

Escalations of record 6158463307, still answered:

  • the @object-ui/runner line;
  • the stale defaultFilters prose: git grep over non-test sources at the head leaves only retirement and history wording, plus the tombstone-typed declaration;
  • the Q4 card: the PR body names objectui#12345.

Escalations of record 6151661549, still answered:

Dev flags:

  • Addendum 6158973185, two deviations:
    • The objectui#12085 clause in 11880-repeater-datasource is right. It is true, and it sits in the bullet being corrected. The seat may keep it.
    • The extra gates (check-changeset-overwrite, check:installed-pin-claims) are harmless, and CI's Overwrite Report agrees with them.
  • Addendum 6158558223, one deviation: right. The two extra prose spots are still true at the head.
  • Addendum 6158199329, three deviations: they stand as answered.
    • The console line beyond the seat's list is right.
    • The guard-refused call ran nothing.
    • The BASELINE prose stops at 2c15e40cf, and Bundle Analysis is success on this head.
  • Report 6151240488, eight deviations: they stand as answered in 6151661549. Re-read here:
    • no gate script named by the split is in the file list;
    • there is no pre.json;
    • date-only-zone-pins-10183 passes in this head's shards.
  • Report 6151240488 out-of-scope findings:
    • the time-zone leak: carrier none, and the shards are green;
    • the OBJECTUI_ALLOW_MAJOR sentence: objectui#12334;
    • the repeater flat reads: objectui#12345.

open_questions: one, the two held-card probes that cannot exit 0 as written (objectui#11970 and objectui#12271). ANSWERED by seat ACCEPT 6151458792, option A. The addenda raise none.

New escalation from this review, to the seat, not blocking. Before pr_ready, do one of these:

  • give 11788-notify-recipients-picker.md:8 the same one-clause correction the eight got (through 17.x; spec 18 refuses a {…} token in recipients, objectui#12030, pending objectui#11824);
  • or record on objectui#11824 that its carrier owns that sentence.

Optionally, reword the 11880-grid-filter-handoff page-1 bullet in the same edit (the ① nit).

Recorded consequences, already ruled; neither is a defect of this head:

  • Spec Range Floors goes red on main after the merge until objectui#12334.
  • Spec Main Shape Gate stays red on the objectstack#23160 drift until objectui#12325 (advisory).

Implemented-by: claude/issue-12030-objectstack-next-18
Reviewed-by: session_01CsyMRsFJBKNEMa4oPY1b5z

VERDICT: PASS

@os-zhuang
os-zhuang marked this pull request as ready for review October 14, 2026 02:09
@os-zhuang
os-zhuang enabled auto-merge October 14, 2026 02:13
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 72 chunks) 3050.0 KB 3119.4 KB
Main entry chunk (gzip) 73.8 KB 350 KB
Entry file index-C1FguJeT.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 20.69KB 7.62KB
app-shell (runtime-config.js) 22.59KB 7.89KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 41.19KB 11.12KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.26KB 8.03KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (commentAuthorship.js) 1.39KB 0.78KB
collaboration (index.js) 1.93KB 0.85KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 588.00KB 141.49KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 248.06KB 69.39KB
fields (index.js) 279.74KB 71.33KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 40.26KB 11.71KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 15.35KB 5.51KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 55.05KB 16.09KB
plugin-charts (index.js) 84.72KB 23.27KB
plugin-chatbot (index.js) 201.72KB 48.07KB
plugin-dashboard (index.js) 143.63KB 38.79KB
plugin-designer (index.js) 233.77KB 50.02KB
plugin-detail (index.js) 258.92KB 68.34KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 178.42KB 46.26KB
plugin-gantt (index.js) 178.63KB 45.19KB
plugin-grid (index.js) 258.68KB 72.10KB
plugin-kanban (index.js) 53.23KB 16.71KB
plugin-list (index.js) 123.39KB 31.55KB
plugin-map (index.js) 27.24KB 9.03KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 46.66KB 13.13KB
plugin-timeline (index.js) 39.21KB 11.85KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 91.99KB 23.23KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.81KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@os-zhuang
os-zhuang added this pull request to the merge queue Oct 14, 2026
Merged via the queue into main with commit c5406c2 Oct 14, 2026
35 of 36 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-12030-objectstack-next-18 branch October 14, 2026 02:36
This was referenced Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment