retire(studio): drop the global_nav designer surfaces with the rc.6 spec bump (objectstack#7100) - #4169
Merged
Conversation
…pec bump (objectstack#7100) `global_nav` was an `ACTION_LOCATIONS` member no running-app surface ever rendered — the console's ⌘K palette reads no action metadata at all — and the Studio designer previewed a mock command-palette frame for it anyway. @objectstack/spec 17.0.0-rc.6 retired the member (objectstack#6888, maintainer ruling 2026-08-09 direction 2); this removes the designer surfaces that outlived it, plus the bump that makes them stop compiling. - ActionPreview.tsx: the mock ⌘K placement frame is gone. The metadata strip still echoes the declared token, deliberately — reporting what a draft says is honest; the frame CLAIMED the platform renders it. - ActionDefaultInspector.tsx: the `LOCATION_LABELS` entry is gone. The map is `Record<ActionLocation, string>`, so the retirement arrived as a compile error (objectui#3017's mechanism firing as designed). - block-config.ts + both locale tables: the palette option and its now-orphaned i18n key. - components' action:bar doc comment aligned (its enum is `[...ACTION_LOCATIONS]` and followed on its own). - ActionEngine.getActionsForLocation is UNCHANGED: narrowing it would be a second rejection point beside the schema's. The type and `ActionLocationSchema` are the enforcement, both pinned. The bump (all 37 `@objectstack/*` declarations, rc.5 -> rc.6) rides along because the two cannot compile apart, and its fallout is repaired here: the `…Input` alias retirement (types/theme, types/spec-report, core/ActionRunner), the five dead i18n re-exports, the `I18nLabel` widening at 8 render sites, `.extend` -> `.safeExtend` on a now-refined `GlobalFilterSchema`, and two parity lists re-pointed. NOT green: the bump's remaining surface is out of this card's scope and filed — objectui#4165 (contract conflict, blocks), #4167 (adaptation remainder), #4163 (I18nLabel consumer story), #4164 (name reclaim available). Part of objectstack-ai/objectstack#7100 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
ℹ️ Console Performance Budget — not measuredThis run did not produce a console bundle to measure, so there is no pass/fail verdict for the performance budget. This is not a budget violation. Nothing was measured — the numbers a real violation would carry are simply absent.
See the workflow run for details. No package size report: it is only generated from a complete package build, so a partial one is never shown. |
… one conflict
Second pass over the @objectstack/spec 17.0.0-rc.6 bump. The first commit fixed
every COMPILE error; a full `vitest run` (14615 tests) then surfaced the runtime
half. All mechanical, each pinned; the one non-mechanical case is left as a
tripwire rather than decided.
- types/zod/complex.zod.ts: `GlobalFilterSchema` composes by spreading the spec's
`.shape`. rc.6 closed BOTH extension doors on a now-refined schema — `.extend()`
throws at module load, `.safeExtend()` types the three overridden keys as
`never` (TS2322, which only `apps/site`'s build caught). The spread preserves
rc.5 behaviour exactly and decides nothing: the refinement-vs-stored-`{preset}`
conflict is objectui#4165, pinned by a new tripwire that reds from either side.
The pin isolates the refinement by widening `defaultValue` first — the bare spec
schema rejects `{preset}` on the OLD field type and the refinement never runs,
so the obvious shorter assertion would have pinned the wrong thing.
- core/actionKeys.ts: `description` joins SPEC_ACTION_KEYS (rc.6 added it to
`ActionSchema`). Inventory only — `ActionDef` is untouched.
- metadata-admin flow tests x2: `FlowNodeSchema` became pipe-wrapped, so `.shape`
read `undefined`. Access-path repair (walk the wrapper); the blocks themselves
are unchanged upstream, and a non-vacuity guard now says so.
- clientValidation.optOuts: INVERTED — rc.6 makes `SharingRuleSchema` declare the
seven ADR-0010 envelope keys, so the create door now ACCEPTS a stamped
`_packageId`. Upstream convergence, pinned as accept, with a bogus-key case
proving the door is still a door.
- clientValidation.viewDiagnostics: fixture supplies a `label`; rc.6's widened
`I18nLabel` made every label a LEAF union, which #3606's root-union expansion
does not reach. The resulting bare `Invalid input` is recorded as its own pin
(objectui#4163), not papered over.
- components/record-picker parity: fixture drops `displayField` — an ADR-0087 D2
tombstone refused by name, which was failing all three `filter` assertions.
- console registry parity: `SPEC_SHAPE_EMPTY_ON_THE_PIN` deleted exactly as its
own self-clearing test instructed (rc.6 lands `PageContainerProps`), with a
tombstone assertion so the deletion cannot be silently undone.
- i18n residue ratchet: matches `const { t, … } = useObjectTranslation(` by
pattern. Both sidebars legitimately also take `language` now, to resolve the
spec's inline per-locale labels.
Still red, filed, NOT fixed here: 2 console-parity exemption-list entries and
`check:spec-symbols`' 13 name collisions (objectui#4167) — each is per-symbol
triage, not a mechanical edit — and objectui#4165, which blocks ready.
Part of objectstack-ai/objectstack#7100
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
This was referenced Aug 10, 2026
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
This was referenced Aug 10, 2026
yinlianghui
marked this pull request as ready for review
August 11, 2026 03:30
yinlianghui
pushed a commit
that referenced
this pull request
Aug 11, 2026
Picks up the rc.6 spec bump (#4169) and the vite alias completion (#4218) so this branch is verified against the same @objectstack/spec CI resolves. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
yinlianghui
pushed a commit
that referenced
this pull request
Aug 11, 2026
Three residual reds on main after the rc.5→rc.6 spec bump (#4169), none of which the train cars themselves covered. QUICK_REFERENCE.md's "Current Release" block still quoted `^17.0.0-rc.5` for both `@objectstack/spec` and `@objectstack/client` while every manifest it names as its anchor declares `rc.6`. The pin test for that block (quick-reference-current-release-4143) landed on main AFTER the train was built, so no car ever ran against it. recordDetailsInputs.spec-parity carried `layout: 'custom'` in both fixtures of its object-sections case. `layout` was removed in @objectstack/spec 17.0.0 (objectstack#6946, ADR-0087 D2) and rc.6 gave it a named `never` rejection, so the object-form fixture failed on `layout` while its `sections` were valid — and the id-list fixture above it kept PASSING on `layout`'s own `invalid_type` without ever reaching `sections`. Dropping the key puts both verdicts back on `sections`; the id-list case now also pins the issue PATH, since a bare code could not tell the two rejections apart. AddressField re-exports `AddressValue` through its declaring module rather than bare. main's #4222 moved the declaration into the pure `address-format` module while this train re-sourced the type from `@objectstack/spec/data`; the merge keeps both by importing the spec type in `address-format` (where the definition now lives) and letting the widget re-export from there, which is the form check:spec-symbols resolves to a declaration site instead of reading as a second local declaration of a name the spec owns.
This was referenced Aug 11, 2026
This was referenced Aug 13, 2026
Merged
akarma-synetal
pushed a commit
to akarma-synetal/objectui
that referenced
this pull request
Aug 17, 2026
…stack-ai#4208) * retire(studio): drop the global_nav designer surfaces with the rc.6 spec bump (objectstack#7100) `global_nav` was an `ACTION_LOCATIONS` member no running-app surface ever rendered — the console's ⌘K palette reads no action metadata at all — and the Studio designer previewed a mock command-palette frame for it anyway. @objectstack/spec 17.0.0-rc.6 retired the member (objectstack#6888, maintainer ruling 2026-08-09 direction 2); this removes the designer surfaces that outlived it, plus the bump that makes them stop compiling. - ActionPreview.tsx: the mock ⌘K placement frame is gone. The metadata strip still echoes the declared token, deliberately — reporting what a draft says is honest; the frame CLAIMED the platform renders it. - ActionDefaultInspector.tsx: the `LOCATION_LABELS` entry is gone. The map is `Record<ActionLocation, string>`, so the retirement arrived as a compile error (objectui#3017's mechanism firing as designed). - block-config.ts + both locale tables: the palette option and its now-orphaned i18n key. - components' action:bar doc comment aligned (its enum is `[...ACTION_LOCATIONS]` and followed on its own). - ActionEngine.getActionsForLocation is UNCHANGED: narrowing it would be a second rejection point beside the schema's. The type and `ActionLocationSchema` are the enforcement, both pinned. The bump (all 37 `@objectstack/*` declarations, rc.5 -> rc.6) rides along because the two cannot compile apart, and its fallout is repaired here: the `…Input` alias retirement (types/theme, types/spec-report, core/ActionRunner), the five dead i18n re-exports, the `I18nLabel` widening at 8 render sites, `.extend` -> `.safeExtend` on a now-refined `GlobalFilterSchema`, and two parity lists re-pointed. NOT green: the bump's remaining surface is out of this card's scope and filed — objectui#4165 (contract conflict, blocks), objectstack-ai#4167 (adaptation remainder), objectstack-ai#4163 (I18nLabel consumer story), objectstack-ai#4164 (name reclaim available). Part of objectstack-ai/objectstack#7100 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3 * fix(deps): repair the rc.6 fallout the first pass missed, and pin the one conflict Second pass over the @objectstack/spec 17.0.0-rc.6 bump. The first commit fixed every COMPILE error; a full `vitest run` (14615 tests) then surfaced the runtime half. All mechanical, each pinned; the one non-mechanical case is left as a tripwire rather than decided. - types/zod/complex.zod.ts: `GlobalFilterSchema` composes by spreading the spec's `.shape`. rc.6 closed BOTH extension doors on a now-refined schema — `.extend()` throws at module load, `.safeExtend()` types the three overridden keys as `never` (TS2322, which only `apps/site`'s build caught). The spread preserves rc.5 behaviour exactly and decides nothing: the refinement-vs-stored-`{preset}` conflict is objectui#4165, pinned by a new tripwire that reds from either side. The pin isolates the refinement by widening `defaultValue` first — the bare spec schema rejects `{preset}` on the OLD field type and the refinement never runs, so the obvious shorter assertion would have pinned the wrong thing. - core/actionKeys.ts: `description` joins SPEC_ACTION_KEYS (rc.6 added it to `ActionSchema`). Inventory only — `ActionDef` is untouched. - metadata-admin flow tests x2: `FlowNodeSchema` became pipe-wrapped, so `.shape` read `undefined`. Access-path repair (walk the wrapper); the blocks themselves are unchanged upstream, and a non-vacuity guard now says so. - clientValidation.optOuts: INVERTED — rc.6 makes `SharingRuleSchema` declare the seven ADR-0010 envelope keys, so the create door now ACCEPTS a stamped `_packageId`. Upstream convergence, pinned as accept, with a bogus-key case proving the door is still a door. - clientValidation.viewDiagnostics: fixture supplies a `label`; rc.6's widened `I18nLabel` made every label a LEAF union, which objectstack-ai#3606's root-union expansion does not reach. The resulting bare `Invalid input` is recorded as its own pin (objectui#4163), not papered over. - components/record-picker parity: fixture drops `displayField` — an ADR-0087 D2 tombstone refused by name, which was failing all three `filter` assertions. - console registry parity: `SPEC_SHAPE_EMPTY_ON_THE_PIN` deleted exactly as its own self-clearing test instructed (rc.6 lands `PageContainerProps`), with a tombstone assertion so the deletion cannot be silently undone. - i18n residue ratchet: matches `const { t, … } = useObjectTranslation(` by pattern. Both sidebars legitimately also take `language` now, to resolve the spec's inline per-locale labels. Still red, filed, NOT fixed here: 2 console-parity exemption-list entries and `check:spec-symbols`' 13 name collisions (objectui#4167) — each is per-symbol triage, not a mechanical edit — and objectui#4165, which blocks ready. Part of objectstack-ai/objectstack#7100 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3 * fix(deps): triage the 14 rc.6 spec-symbol collisions and refresh the console parity exemptions (objectstack-ai#4167) objectui#4167, objectstack#4115. `check:spec-symbols` reported 13 collisions on the @objectstack/spec 17.0.0-rc.6 bump and a 14th (`GlobalFilterSchema`) appeared during the bump itself; each is triaged on its own rather than blanket-renamed. Renamed (3) — the spec's same-named export means something else: MetadataState -> MetadataCacheState (react, app-shell) resolveI18nLabel -> resolveKeyedI18nLabel (react, app-shell, + apps/console) DateRangePreset -> FilterBuilderDateRangePreset (types) Bound or derived (10): DATE_RANGE_PRESETS (+ a `satisfies` completeness pin on the local bounds table), NavigationMode (+ a both-directions type pin), AddressValue, BreakpointColumnMap, BreakpointOrderMap, KanbanConfig, CalendarConfig, GanttConfig. Four copies were losing information: GanttConfig declared 6 of the spec's 17 keys while plugin-gantt reads all of them, AddressValue 5 of 7 parts, and DATE_RANGE_PRESETS was the third copy objectstack#4614 extracted the vocabulary to collapse. ALLOW (1): GlobalFilterSchema, the same `.shape`-spread dialect as SelectOptionSchema beside it — it collided only because rc.6's refinement forced `.extend()` to be respelled, moving a derivation the guard could see into an object literal it deliberately does not descend into. Nothing about objectstack-ai#4165 is encoded. Console registry-inputs-spec-parity: all 12 off-spec exemptions deleted (rc.6 landed objectstack#6776 and objectstack#5775, verified per key against the resolved shape), and `element:record_picker` publishes `sort` / `limit` / `emptyText` — read by the renderer all along, and the red demanding them was predicted in writing by the exemption it replaces. 49 tests/2 failing -> 51/0. Also repairs 3 pre-existing type-check errors of this card's own rc.6 family, found only by running `type-check` (which the bump PR did not): the retired `ThemeInput` alias re-pointed BY SIDE, and `DroppedFieldsEvent.reason`'s new `primary_key` arm. The consumer gap that arm exposes is objectui#3935. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3 * fix(i18n): render I18nLabel objects at the 13 remaining sites `@objectstack/spec` 17.0.0-rc.6 widened `I18nLabel` from `string` to `string | Record<string, string>`, so an author may inline a per-locale map (`label: { en: 'Owner', 'zh-CN': '负责人' }`) anywhere the spec accepts a display label. PR objectstack-ai#4169 repaired eight such sites; thirteen more were invisible to it because the five packages involved build through vite/rolldown, so `turbo run build` never type-checks their sources — only `turbo run type-check` does. Read sites now resolve the map to the viewer's locale instead of reaching a text node as `[object Object]`: - `@object-ui/layout` — `NavigationArea.label` (area switcher button + tooltip) - `@object-ui/plugin-list` — `ViewTab.label` (pill row, dropdown trigger, menu) - `@object-ui/plugin-dashboard` — `DashboardWidget.title` (heading + attribute) - `@object-ui/plugin-designer` — `DashboardWidget.title` (card + preview tile) - `@object-ui/app-shell` — `ActionParam.label` and each option's `label`, fixed on the `RawActionParam` DECLARATION rather than on the test that surfaced it Two edges are deliberate rather than mechanical: `DashboardEditor`'s title `<input>` is an authoring WRITE, not a display. Resolving a map into it and writing `e.target.value` back would collapse every other locale on the first keystroke, so the write is GUARDED — a map-valued title renders resolved and read-only, and survives an unrelated edit-and-save round trip untouched. The type error dies from the guard, not from a cast. What Studio should actually offer for authoring a per-locale label is objectstack-ai#4163 part 2, which stays unclaimed and pending design. `@object-ui/layout` carries no i18n dependency by design (its whole i18n story is injection), so it uses the PRODUCER's resolver — `resolveI18nLabel` from `@objectstack/spec/ui` — at the spec's documented `en` default rather than hand-rolling a resolution that could drift. The three plugin packages sit inside objectui's i18n tree and already hold the live language, so they use `pickLocalized`; `plugin-list/src/__tests__/i18nLabel-resolver-parity.test.ts` pins the two resolvers limb for limb so the runtime dashboard and the designer's preview of it cannot start disagreeing about which entry wins. Also re-points four `plugin-list` type-test assertions at `ViewTabParsed`: rc.6's `…Input`-alias retirement moved the bare `ViewTab` onto the input side, so following the NAME left them comparing the authoring side against itself. Invisible until now because `type-check` is `tsc --noEmit && tsc -p tsconfig.typetests.json` and the `&&` never reached that project. Part of objectstack-ai#4163 * fix(rc.6): finish the rc.6 adaptation the train never saw Three residual reds on main after the rc.5→rc.6 spec bump (objectstack-ai#4169), none of which the train cars themselves covered. QUICK_REFERENCE.md's "Current Release" block still quoted `^17.0.0-rc.5` for both `@objectstack/spec` and `@objectstack/client` while every manifest it names as its anchor declares `rc.6`. The pin test for that block (quick-reference-current-release-4143) landed on main AFTER the train was built, so no car ever ran against it. recordDetailsInputs.spec-parity carried `layout: 'custom'` in both fixtures of its object-sections case. `layout` was removed in @objectstack/spec 17.0.0 (objectstack#6946, ADR-0087 D2) and rc.6 gave it a named `never` rejection, so the object-form fixture failed on `layout` while its `sections` were valid — and the id-list fixture above it kept PASSING on `layout`'s own `invalid_type` without ever reaching `sections`. Dropping the key puts both verdicts back on `sections`; the id-list case now also pins the issue PATH, since a bare code could not tell the two rejections apart. AddressField re-exports `AddressValue` through its declaring module rather than bare. main's objectstack-ai#4222 moved the declaration into the pure `address-format` module while this train re-sourced the type from `@objectstack/spec/data`; the merge keeps both by importing the spec type in `address-format` (where the definition now lives) and letting the widget re-export from there, which is the form check:spec-symbols resolves to a declaration site instead of reading as a second local declaration of a name the spec owns. --------- Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal
pushed a commit
to akarma-synetal/objectui
that referenced
this pull request
Aug 17, 2026
…}` becomes an ADR-0089 legacy alias (objectstack-ai#4246) Executes the maintainer ruling on objectui#4165: the spec stays strict, the bare preset NAME is the single canonical spelling of a `type: 'date'` global filter's `defaultValue`, and the stored `{ preset }` object form becomes a documented legacy alias — lifted on read, rewritten on next save, with the retirement window recorded at the read site. - `@object-ui/types`: the `defaultValue` divergence is retired and the spec's rc.6 refinement is carried. A refined object schema in zod 4 closes `.extend()`, `.omit()` and (by typing overrides `never`) `.safeExtend()`, so the schema spreads the spec's `.shape` and re-attaches the spec's object-level rules by delegating to the spec schema itself — no local restatement of the grammar. `options`/`optionsFrom` divergences unaffected. - New zod-free module `dashboard-filter-alias.ts` exports the lift, carrying the ADR-0089 window. - `@object-ui/core`: `resolveDashboardFilterDefs` lifts each stored entry and warns, so a surviving legacy document is visible rather than silently tolerated. - `@object-ui/plugin-designer`: `DashboardDesignPage` lifts into the editable draft and at the save funnel, so the next save persists the canonical name. - objectstack-ai#4169's standstill tripwire went red exactly as designed and is deleted with its note; the `check:spec-symbols` ALLOW entry for `GlobalFilterSchema` is burned down, because the delegation made the derivation visible to that guard again. Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3 Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal
pushed a commit
to akarma-synetal/objectui
that referenced
this pull request
Aug 17, 2026
…e alias's on its renderer read (objectstack-ai#3829) (objectstack-ai#4794) * retire(studio): drop the canonical page:header icon field, restate the alias's on its renderer read (objectstack-ai#3829) objectui#3829 was filed as a three-way fork over `page:header.icon` and `page:card.actions` (wire them / declare them with a KNOWN GAP / retire them upstream). The maintainer ruled route (c) on 2026-08-09 and objectstack#6946 / PR objectstack#7115 executed it: both keys are ADR-0087 D2 tombstones in @objectstack/spec 17.0.0, live on the rc.6 this repo pins. This is the objectui follow-through, and the measurement behind it found the retirement's "zero producers" premise held for one key and not the other. - previews/block-config.ts + both locale tables: the canonical `page:header` icon box and its two now-orphaned i18n keys. This was the one live producer. Before the retirement an authored value was silently dropped; after it the platform rejects the node BY NAME, so a designer field left standing is strictly worse than the gap it papered over. Negative pin (plus the positive non-vacuity half and the spec-side tombstone assertion) in previews/__tests__/block-config.test.ts. Precedent followed verbatim: 38ab505 / PR objectstack-ai#4169's global_nav cleanup, "the palette option and its now-orphaned i18n key". - page:card.actions had no producer at all — it is a clean retirement, and only the exemption prose changes for it. - registry-inputs-spec-parity.test.ts: both exemptions rewritten from the "wire it or declare it" MENU to the retired-upstream class, templated on the `record:details.layout` entry. They are NOT deleted: D2 retirement replaces the member with `z.never()` rather than removing it, so `Object.keys(shape)` still reports both keys and the reverse direction still demands cover. They resolve via objectui#3809's tombstone recognition, which the entries now say. Stale line numbers repaired (822-1570 -> 973-1677, 666-695 -> 703-745) and the block header re-based on rc.6. - layout's `page-header` / `layout:page-header` alias KEEPS its `icon` input (route A). That is a different renderer which really reads and draws it (PageHeader.tsx:123, :231-233), the docs page publishes it and the repo's only live demo writes it — withdrawing it would delete a working capability. What changes is the LICENCE: the comment now rests on the renderer read instead of spec parity, and page-header-authorable-keys.test.tsx skips tombstones when it derives the spec key set, so `icon` stops passing the dialect guard for the wrong reason. The carve-out is a named, issue-backed, self-clearing list. The renderer read points themselves are untouched. - content/docs/layout/page-header.mdx: line 40 still taught `icon` as a member of `PageHeaderProps`. Rewritten to rc.6 reality, and the component prop is now distinguished from the retired spec key rather than conflated with it. - PageBlockInspector.i18n.test.tsx: the objectstack-ai#3979 placeholder pair re-pointed from `page:header` to `record:alert`, which reproduces the symptom (prose hint under a translated label) on a key the renderer really reads. Same move and same reason as objectui#4649's re-point a few tests above. Part of objectstack-ai#3829 Co-authored-by: Claude <noreply@anthropic.com> * docs(layout): point the icon retirement at its issue, not at a version literal (objectstack-ai#3829) CI red on `scripts/__tests__/doc-version-claims.test.ts`, self-inflicted by the previous commit: the new PageHeader paragraph wrote "retired in `@objectstack/spec` 17.0.0", and a first-party package name followed by a dotted version IS a version claim on a scanned surface (`content/docs` is a SCAN_ROOT). Nothing in this repo can check that literal, so the ratchet demands it be deleted or registered. Deleted, which is the ratchet's own stated preference and the right one here: the sentence already cites objectstack#6946 and ADR-0087 D2, so the version number carried no fact those two do not — while being exactly the kind of literal objectui#3645 froze at `^3.3.0` for thirteen majors. The actionable form of "which release" is already in the same paragraph as `os migrate meta --from 16`, which is a migration command rather than a claim about a dependency's current version. The same literal appears in this PR's test comments, block-config.ts and the changeset and does NOT trip the gate — those are not scanned surfaces. Only the mdx is, so only the mdx changes here. Verified against the gate's own matcher rather than by eye: FIRST_PARTY + SEP + VERSION, where SEP cannot cross an opening parenthesis, so "`@objectstack/spec` (objectstack#6946" is not a claim. Re-ran the file through a probe built from the test's exact regex fragments (1 hit before, 0 after) and then the test itself. Part of objectstack-ai#3829 Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of objectstack-ai/objectstack#7100 (cross-repo, so no auto-close — the PM closes the card).
⛔ Draft, and the reason is a decision, not a missing edit. The card's own work is complete and green. The
@objectstack/spec17.0.0-rc.6bump it is coupled to is a far larger release than a lockfile move, and one consequence is a producer/consumer contract conflict whose deciding half belongs to the spec owner: #4165.Three separable reviewable units, in the order they are easiest to read:
global_navretirement — the card1. The retirement (the card)
global_navwas anACTION_LOCATIONSmember no running-app surface ever rendered. The console's ⌘K palette —app-shell/src/chrome/CommandPalette.tsx— builds its groups from nav items, objects, dashboards, pages, reports, recent items, record search and theme; it holds no reference toglobal_nav, toactionRendersAt, or to any action-metadata source at all. So an action declaringlocations: ['global_nav']never reached a user.The Studio designer previewed it anyway — a mock frame reading
⌘K · Command palettewith the author's own button inside it. That is the sharp edge the ruling names: an authoring tool promising a surface the product does not have teaches authors, and every AI copying this corpus, to declare dead metadata.Ruling of record, maintainer 2026-08-09 on objectstack-ai/objectstack#6888, direction 2:
The spec half landed in objectstack-ai/objectstack#7322;
ACTION_LOCATIONSis 6 members in rc.6. This is the objectui half.metadata-admin/previews/ActionPreview.tsxmetadata-admin/inspectors/ActionDefaultInspector.tsxLOCATION_LABELSentry removedmetadata-admin/previews/block-config.tsrecord:quick_actionslocation option removedmetadata-admin/i18n.ts…option.location.global_navkey, in BOTH locale tablescomponents/renderers/action/action-bar.tsxThree judgement calls, each pinned in the source:
ActionPreviewlists whateverlocationsthe draft carries as chips. Deliberately untouched: reporting what a possibly-stale draft says is honest, whereas the frame claimed the platform renders it. That distinction is the whole retirement, so the new tests scope their queries to the placement section — an unscoped query matches the echo and cannot tell the two apart.ActionDefaultInspector's map needed no new guard.LOCATION_LABELSis typedRecord< ActionLocation, string >, so the retirement arrived as a TS2353 excess-property error the moment the resolved vocabulary dropped to six. That is objectui#3017's mechanism firing as designed, and a stronger pin than any runtime test — a re-added member is a compile error too.ActionEngine.getActionsForLocationis UNCHANGED. It still answers a literal string match, so asking it for'global_nav'still returns a stale action. Narrowing it would put a second rejection point beside the schema's — the tolerant-consumer shape AGENTS.md #0.1 forbids, inverted. Enforcement stays where it belongs and both halves are pinned: the parameter type is six-membered so no type-correct caller can spell the value, andActionLocationSchemarejects it by name with the retirement message.Not touched:
ROADMAP.md:1369listsglobal_navamong the locationsaction:barfiltered by. That line sits under a dated, completed milestone (P2.10 … ✅) — a historical record, not a live contract statement. Called out so it reads as a decision, not an oversight.Tests
New
previews/__tests__/ActionPreview.locations.test.tsxand a new block inpreviews/__tests__/block-config.test.ts, converting the coverage the deleted entries carried into negative pins — each beside a positive one over the same render, so a vacuous pass needs both halves to fail at once: a live location still draws its frame / the option list still equalsACTION_LOCATIONS, andglobal_navdraws no frame, noCommand palettemock survives, the option list omits it, andt()returns the key unchanged in both locales.useActionEngine.test.tskeeps its staleglobal_navfixture — the posture the file already takes for retiredbulkEnabled/shortcut— and pins that the action leaks into none of the six live locations.Reverse verification
Restored both removals (
git checkout origin/main -- block-config.ts ActionPreview.tsx):Direction as predicted; the 19 that stayed green are what shows the pins are not vacuous. Restored to HEAD, 54/54 green.
One measurement went the other way and is reported rather than forced: I expected
getActionsForLocation('global_nav')to return[]; it returns the stale action. That is correct for a vocabulary-agnostic registry, so the test pins what is true and says why, instead of the symmetric assertion that looked tidier.2. The rc.6 bump and its forced repairs
All 37
@objectstack/*declarations across 30package.jsonfiles move^17.0.0-rc.5→^17.0.0-rc.6;pnpm-lock.yamlresolves one copy of each family package at rc.6 (pnpm why @objectstack/spec→ a single17.0.0-rc.6). Count and shape follow this repo's last family bump, objectui#3560 / PR #3568; siblings move withspecfor its stated reason —client/formula/lintpinspecexactly, so leaving them behind keeps two copies in the tree.The bump and the removals cannot be split: at rc.5 the total
Record< ActionLocation, string >is missing a key, at rc.6 it has an excess one.What the bump actually is: diffing the resolved
dist/ui/index.d.ts, 40 exports removed, 29 added — an…Input-alias retirement across ~14 vocabularies, the standalone i18n vocabulary retired withI18nLabelwidened, the widget-manifest vocabulary retired, and refinements added to schemas this repo derives from. The dispatch premise was that the ranges already admitting rc.6 made this lockfile-only; falsified, and written up in #4167.2a. Compile fallout
types/theme.ts—ThemeInput as Theme→Theme. rc.6 moved the bare name onto the input side (X=z.input,XParsed=z.infer), so the rename preserves this binding's meaning exactly.ThemeParsedwould have been the silent swap:modeis required in the parsed shape because.default('auto')has run, and everything here is authoring-side.types/spec-report.ts— four aliases re-pointed by SIDE:SpecReport/SpecReportChart→ReportParsed/ReportChartParsed,SpecReportInput/SpecReportChartInput→Report/ReportChart. By name alone both pairs would have swapped.types/index.ts— five retired i18n re-exports dropped. Measured dead: nothing imported them from@object-ui/types; every apparent consumer is anIntl.NumberFormatcall site or@object-ui/i18n's own locally declared vocabulary.I18nLabelsurvives and stays bound.core/ActionRunner.ts—ActionInput as SpecActionInput→Action as SpecActionInput; all 18SpecActionInput[…]derivations unchanged in meaning.I18nLabelwidenedstring→string | Record< string, string >. Eight sites where such a label reaches a text slot now go through the spec'sresolveI18nLabel, so the map form renders its locale instead of[object Object]— two sidebars'NavigationArea.label, sixDashboardWidget.titlereads. Imported asresolveInlineI18nLabel, because this repo has its OWNresolveI18nLabelover a different vocabulary (a translation-key ref{ key, defaultValue, params }); neither accepts the other's shape.types/zod/complex.zod.ts—GlobalFilterSchemacomposes by spreading the spec's.shape. See unit 3: this is the forced spelling, not a resolution.2b. Runtime fallout (found by a full
vitest run, 14,615 tests)FlowNodeSchemabecame pipe-wrapped in rc.6, so.shapereadundefinedand two suites died onCannot read properties of undefined. The blocks (waitEventConfig/connectorConfig/boundaryConfig) are unchanged upstream, verified by walking the wrapper — so this restores the access path, not the expectation, and a non-vacuity guard now asserts the walk resolves.clientValidation.optOuts— INVERTED, and it is upstream convergence. The pin readexpect(create.ok).toBe(false)on the premise thatSharingRuleSchema"declares NONE of the seven ADR-0010 envelope keys". rc.6 makes it declare all seven, asActionSchemahas since rc.2, so a stamped_packageIdis legal input and the create door accepts it. Pinned as accept, with a bogus-key case proving the door is still a door.clientValidation.viewDiagnostics. The fixture now supplies alabel: rc.6's widenedI18nLabelmade every label a LEAF union, which objectui#3606's ROOT-union expansion does not reach. The resulting bareInvalid inputis recorded as its own pin namingI18nLabelnow admits an inline per-locale map — audit every read the compiler cannot see, and give Studio a way to author one #4163 rather than papered over — teaching the mapper about leaf unions is a diagnostics design change, not a bump repair.componentsrecord-picker parity. Fixture dropsdisplayField— an ADR-0087 D2 tombstone (objectstack#5775) refused by name, which was failing all threefilterassertions on the wrong key.consoleregistry parity.SPEC_SHAPE_EMPTY_ON_THE_PINdeleted exactly as its own self-clearing test instructed (rc.6 landsPageContainerProps, sochildrenappears), with a tombstone assertion so the deletion cannot be silently undone.SPEC_ACTION_KEYSgainsdescription(rc.6 added it toActionSchema). Inventory only —ActionDefis untouched, because whether anything should READ it is a separate question.const { t, … } = useObjectTranslation(by pattern; both sidebars legitimately also takelanguagenow.spec-ui-schema-reexportsdrops five deny-list rows whose names no longer exist (its own guard prescribes this).page-nav-misc-spec-parity's tripwire fired for the second time — rc.6 vacatedWidgetManifest/WidgetSource, so those rows move to "the spec no longer owns", keeping the vacancy pinned. The reclaim they unlock is recorded, not taken: spec rc.6 vacatedWidgetManifest/WidgetSource— theRuntime…prefixes may be reclaimed #4164.2c. One judgement call, flagged
DashboardWidgetInspector's title editor is the single authoring read of a widenedI18nLabel, and the only place where following the widening mechanically would have destroyed data: resolving a map into a single-line input and writinge.target.valueback collapses every other locale on the first keystroke. The conservative branch is taken — a map-valued title renders resolved and read-only — and nothing can reach that path yet, sinceI18nLabelwas plainstringthrough rc.5. A placeholder, not an answer; the design is #4163 part 2.3. The blocker — #4165
rc.6 added a refinement to
GlobalFilterSchemathat refusesdefaultValue: { preset: 'last_7_days' }on atype: 'date'filter — the exact object form@object-ui/core'snormalizeDateDefaultproduces and stored dashboards carry (framework#4475), and the stated reason for one of this repo's three pinned divergences.rc.6 closed both extension doors:
.extend()throws at module load ("Cannot overwrite keys on object schemas containing refinements"), and.safeExtend()types all three overridden keys (options,optionsFrom,defaultValue) asnever. So a spelling change was forced. The spread used here carries the spec's fields by reference, replaces the three, and does not carry the refinement — byte-for-byte the rc.5 behaviour, so neither answer is encoded. A tripwire pins the standstill and reds from either side.Measuring it correctly is subtle and #4165 spells it out: parsing
{ preset }against the bare spec schema fails on the OLD field type and the refinement never runs. It has to be isolated by wideningdefaultValuefirst — which is what the new pin does.The two candidate resolutions and their costs are in #4165; the short form is that they differ only in who moves, and the answer is a fact about the spec owner's intent.
Still red, filed, deliberately not fixed here
check:spec-symbols— 13 name collisions (ci.yml's Type Check job). rc.6 published 9 names this repo already declares locally. Each is objectstack#4115-class per-symbol triage;resolveI18nLabelin particular is a genuine clash over two different vocabularies. → Track the@objectstackfamily at17.0.0-rc.6— the adaptation surface beyond what objectstack#7100 could carry #4167console/registry-inputs-spec-parity— a stale exemption list and three record-picker inputs the spec now declares. Mostly mechanical, but each published input is an authoring-surface addition wanting its own read. → Track the@objectstackfamily at17.0.0-rc.6— the adaptation surface beyond what objectstack#7100 could carry #4167GlobalFilter.defaultValueto reject{ preset }— the exact shape objectui's normalizer produces and stored dashboards carry #4165 — gates ready.Local verification
pnpm exec turbo run build— 44/44 successful (includingapps/site, which is where the.safeExtendTS2322 surfaced — the earlier--filter='!@object-ui/site'pass missed it)pnpm exec vitest run(whole repo) — 14,609 passed / 14,615, the 6 remaining being the two console-parity assertions above and their filed siblingsturbo run lintover the touched packages — 0 errors (warnings pre-existing)check-changeset-presence✅ ·check-changeset-no-major✅ ·check-changeset-fixed✅ ·check-control-bytes✅ ·check-i18n-call-site-keys✅ ·check-i18n-en-drift✅check-spec-symbols❌ — 13 findings, all rc.6-introduced → Track the@objectstackfamily at17.0.0-rc.6— the adaptation surface beyond what objectstack#7100 could carry #4167Generated by Claude Code