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 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