Uh oh!
There was an error while loading. Please reload this page.
feat(types,providers): localize the theme document types — objectui owns Theme, ThemeMode, ColorPalette (#5716) - #5752
Merged
Conversation
The spec retired its theme module (objectstack#10485); objectui retains the theme SYSTEM, so under the #5716 ruling (option A) @object-ui/types now OWNS Theme / ThemeMode / ColorPalette, hand-written from the last-published @objectstack/spec 17.1.0 shapes. Typography / BorderRadius / Shadow / ThemeDefinition are DELETED under the zero-reader rider (shapes live on as inline Theme members). ThemePreference derives from the local ThemeMode; THEME_MODES is the vocabulary's runtime witness. The UI namespace re-points its theme members at the local owner via a shim so the pin refresh cannot narrow them silently. Retirement-era tripwires cleaned: batch7 deny-list row, batch7 spec imports, parity test re-pointed at the new owner. check:spec-symbols carries three ALLOW entries that turn stale (loud) on the pin refresh. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EuPCi56cnGyykygi3z9w4m
Contributor
✅ Console Performance Budget
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
Size Limits
|
os-zhuang
marked this pull request as ready for review
August 23, 2026 04:57
Uh oh!
There was an error while loading. Please reload this page.
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 freeto 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.
Fixes#5716
Maintainer ruling (2026-08-23, live PM chat, adopting recommendation A — localize): objectui assumes ownership of the theme document types. The spec retired its whole theme module (objectstack-ai/objectstack#10485, PR objectstack-ai/objectstack#10695); objectui retains the theme SYSTEM (ThemeEngine, ThemeProvider, theme documents), so the type home moves here, with the last-published
@objectstack/spec17.1.0 shapes as the authority. This unblocks the post-release spec-pin refresh chain (#5668 Restart-when exit; #5601 / #4935 ride the same bump).Published-API decisions, stated by name (contract-review clause)
1. Deleted published names (zero-reader rider: not migrated — deleted)
Each name below leaves the
@object-ui/typessurface. The changeset states all four plainly.Typography— shape lives on as the inlineTheme.typographymember.BorderRadius— lives on as inlineTheme.borderRadius.Shadow— lives on as inlineTheme.shadows.ThemeDefinition— deprecated alias ofTheme; deleted outright.Zero-reader census. Five instruments, each with a positive control (a control that came back empty would have meant a broken instrument, not a proved zero):
packages apps examples e2efor imports of each name from@object-ui/typesor a relativethemepath. Zero hits for all four. Control:Themereturns 5 real import sites (ThemeEngine.ts, ThemeContext.tsx, two test files, page-nav parity test).grep -w) acrosspackages apps examples e2e scripts eslint-rules, declaration files excluded.Typography: 3 hits, all prose comments.BorderRadius: 1 comment.Shadow: 3 comments about DOM shadowing in plugin-form tests, unrelated.ThemeDefinition: zero hits anywhere in code. Control:ColorPalettereturns live code hits in ThemeEngine.ts including a keyof position.UI.followed by any theme-family name, and for any-alias member access of the four names — this is exactly the shape that hid clientValidation.tstheme:entry readsspec.ThemeSchema, which the spec retired — dangling dynamic read on a metadata type that is not registered #5715's dangling entry. Zero hits. Control: the broadUI.member pattern catchesUI.ListViewin the index.ts docblock at line 971, so the instrument sees the access shape.exportblocks carrying any of the names. Zero rows. Control: the same pattern family finds the real chainplugin-form/src/successBehavior.ts:16re-exportingSubmitBehaviorfrom@object-ui/types.@object-ui/typesrebuilt,type-checkof the dependents that the census names as the only theme-family importers (types, providers, core, react) is green. Reverse control: deleting the KNOWN-READColorPalettefrom the surface, rebuilding, and re-running the consumer sweep goes red at exactlyThemeEngine.ts(20,22) error TS2305— so a green sweep over the deletions is a measurement, not silence. (Consumers resolve the package throughdist/index.d.ts, so both control legs rebuilt dist and confirmed the mutation landed there by anchored counts before reading any result; restore was trapped and re-verified.)Stated instrument limits: plain grep cannot tell a comment from code (every nonzero I2 hit was read and classified by hand); text search cannot see a namespace member access (I3 + I5 cover that shape); the census is in-repo only — external consumers of the four names are unknowable from here, which is why the changeset names every removal. Doc snippets under
content/declare their own inline interfaces (not imports), so nothing there reads the deleted names either.2. Hand-written shapes and how each was established
Theme,ThemeMode,ColorPaletteare hand-written inpackages/types/src/theme.ts, following the house shape this file's own pointer names (the localized touch vocabulary block inmobile.ts, including the runtime-witness-tuple pattern:THEME_MODESkeeps the providers parity pins executable, asSPEC_GESTURE_TYPESdid).How parity with the 17.1.0 blueprint was established, per shape:
Theme,ThemeMode,ColorPalette, plus the deleted shapes viaTheme.typography/Theme.borderRadius/Theme.shadowsagainst the spec'sTypography/BorderRadius/Shadow, with is-any guards proving the spec side is real. Forward leg: exit 0, zero diagnostics. Reverse leg (probe must be falsifiable): flipping oneColorPalettekey from optional to required went red at exactly the two assertions that read the palette; restore leg exit 0. Mutations confirmed on disk by anchored counts in both directions.page-nav-misc-spec-parity.test.ts(untouched, outside the fence) keeps compiling mutual assignability between the localThemeand the spec's authoringThemein CI on every commit — it is now a live drift gate for the hand-written shape, and its spec leg retires with the pin refresh.@objectstack/spec/uiwould turn red on the very upgrade this card unblocks. What stays executable forever:THEME_MODES(runtime witness; both providers pins fail if the vocabulary gains, loses, or misspells a member — ablation-proven below), and ThemeEngine's color map, declared as a Record keyed by keyof ColorPalette, which makes the compiler reject any palette-key change that does not move the CSS-variable mapping with it.animation,zIndex, the typography scales — kept as optional-never) are carried over with their provenance comments condensed at the declarations.3. The
UInamespace clause (index.ts line 978)Measured first: zero in-repo readers of any
UI.member (I3 above); the spec/ui surface is 230 runtime keys plus type-only names, so a full explicit list would be a second copy of the spec and was rejected. Chosen shape: a shim modulepackages/types/src/spec-ui-namespace.ts— star re-export of spec/ui plus explicit re-exports ofTheme/ThemeMode/ColorPalettefrom the local owner (an explicit export beats a star export of the same name).index.tsline 978 now points at the shim. Result: the surviving theme members can no longer narrow silently — they resolve locally today and unchanged after the refresh. The non-theme members keep tracking the spec by star, deliberately the same posture as the fifteen non-theme re-export blocks the ruling left out of scope. Spec/ui theme names the refresh retires (ThemeSchema, ThemeModeSchema, ThemeParsed, the three deleted shape names, defineTheme) drop out of the namespace with it; the changeset says so.4. Retirement-era tripwires cleaned (ruled in-scope)
spec-ui-schema-reexports.test.ts: theThemeModeSchemadeny-list row removed ahead of its ratchet firing, with the reason recorded in place.spec-symbol-batch7.test.ts: the designed tripwire fired its purpose ("if the spec retires Theme, the rename is up for re-triage" — the re-triage was this ruling). Rewritten with zero spec imports: pinsThemePreferenceequalsThemeMode | 'system', the witness-tuple/type identity, and the system-not-in-vocabulary exclusion, all against the new owner.theme-mode-spec-parity.test.tsx: behavioral coverage kept intact; only the vocabulary read re-pointed from the spec schema toTHEME_MODES.providers/types.ts:ThemePreferencederives from the localThemeMode; the batch-7 naming history is preserved at the declaration. Providers src now has zero@objectstack/specimports.Ablations (tests bite; runs resolve
@object-ui/typesto src via the root vitest alias table, vitest.config.mts line 261, so the mutation legs are source-level by measured configuration): addingsystemtoTHEME_MODESfails exactly the batch7 exclusion pin (1 failed); adding an unhandledbogusmember fails exactly the parity loop with "mode 'bogus' must resolve to light/dark, got [bogus]". Both mutations confirmed on disk by anchored counts, both restored under a trap and re-verified.Fence deviations — both reported on #5716 before editing (mid-task report)
scripts/check-spec-symbol-derivation.mjs:check:spec-symbolsreds on the ruled outcome (measured: exit 1, naming exactly the three hand-written names) because the installed pin still publishes them. Three ALLOW entries added citing this ruling — the gate's own designed route. Deliberate property: the ALLOW list is shrink-only and stale-checked, so the pin refresh turns all three entries stale and fails the gate LOUDLY — a second gauge for the ruling's silent-half axis. The refresh PR deletes them.packages/types/src/spec-ui-namespace.ts: new file, exists solely to implement the ruled line-978 clause — TypeScript cannot compose a namespace export from two sources inside one file.Verification (union at head
cf05dd125, zero uncommitted files)type-checkof@object-ui/types,@object-ui/providers,@object-ui/core,@object-ui/react— the DEPENDENTS direction, and per the census the only in-repo theme-family importers: 4 of 4 Done, exit 0. Declared narrowing: the full dependent farm is CI's run.check:spec-symbolsexit 0: "16 declared dialects, 4 untriaged collisions in 2 packages" / claims leg unchanged at 18 pre-existing.check:control-bytesOK (4799 files); changeset presence / no-major / fixed-group all green;type-check:coveragegreen (45 of 46 plus 41 of 41 test projects, pre-existing ledger unchanged).check:self-import,check:phantom-depsgreen;check:node-esm-loadgreen (load leg 34 of 39 entries evaluated) — ran one tree-state before the changeset file was added, which that gate does not read.pnpm lintis CI's run; eslint on the 9 changed files exits 0 (two pre-existing warnings on untouched lines of providers/types.ts).Out of scope, noted
ThemeSwitcherSchema/ThemePreviewSchemauntouched (finding:ThemeSwitcherSchema/ThemePreviewSchemaare the same dead component kind #5489 retires —theme-switcherandtheme-previeware registered by nothing either #5647).page-nav-misc-spec-parity.test.tskeeps its spec-side Theme rows on purpose (live drift gate until the refresh; its spec leg is refresh-day cleanup, announced by compile error there).Theme,ThemeMode,ColorPalette, …) still derives from@objectstack/spec/ui, which retired it — objectui cannot refresh its spec pin past 17.1.0 until this is re-homed or dropped, and the choice needs a ruling #5716).Generated by Claude Code
Generated by Claude Code