Skip to content

Commit 35ad101

Browse files
Elon Muskclaude
andauthored
feat(spec): retire the themes carrier key and ThemeSchema — app.branding is the one colour surface (#10485, ADR-0049) (#10695)
* feat(spec): retire the themes carrier key and ThemeSchema (#10485, ADR-0049) Ruled B (退役授权面, 2026-08-21): strict-delete the stack themes key with a guidance prescription, delete ui/theme.zod.ts whole, drop the ingest mapping and the PLURAL_TO_SINGULAR fold (so /meta/theme gets the #8421 refusal), register six retired-def entries and the D3 semantic entry stack-themes-carrier-retired, pin the refusal, re-base docs and the showcase on app.branding. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B4h3medzvhB9rpfoja9jcw * test: retriage theme specimens across consumer suites; light gates green Specimen swaps (theme -> webhook) in metadata-protocol, objectql, rest and runtime meta-door tests; new #10485 refusal pins; stack-collection-maps waivers updated; PROTOCOL_MAP row removed; Iso pin count 839 -> 834. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B4h3medzvhB9rpfoja9jcw * docs(audits): strictness ledger — theme.zod.ts row becomes a retirement paragraph (#10485) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B4h3medzvhB9rpfoja9jcw * chore: regenerate spec artifacts on merged tree (post-merge lap, #10485) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B4h3medzvhB9rpfoja9jcw * docs(quick-reference): drop the retired Theme row and recount the UI section (10 of 16) (#10485) check:quick-reference-counts [row]+[total] remedies: references/ui/theme.mdx was deleted with the retired surface, so the row goes (retired, not moved) and M drops 17 -> 16, N 11 -> 10. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B4h3medzvhB9rpfoja9jcw --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent dccbcec commit 35ad101

68 files changed

Lines changed: 687 additions & 1833 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
"@objectstack/spec": minor
3+
---
4+
5+
feat(spec): retire the `themes` carrier key and `ThemeSchema` — the authoring surface nothing ever applied (#10485, ADR-0049)
6+
7+
**BREAKING** accept-set narrowing, landing after the v17.0.0 cut (the lockstep
8+
launch-window convention ships it as `minor`; the migration prescription is
9+
registered under protocol major 18, where `os migrate meta` users will look).
10+
Maintainer ruling 2026-08-21, recorded verbatim on #10485: 「B:退役授权面 —
11+
收掉 `themes` 载体键与 schema,`app.branding` 留作唯一颜色面;objectui 引擎代码
12+
与单测保留。」
13+
14+
`defineStack({ themes })` was a real authoring surface — parsed strictly at the
15+
authoring gate, ingested and stored by artifact ingest
16+
(`ARTIFACT_FIELD_TO_TYPE`) — with ZERO consumers past that point, measured:
17+
no non-test read of `.themes` or of stored `theme` items anywhere in
18+
core/runtime/rest/services/plugins; `theme` never in `MetadataTypeSchema`,
19+
`DEFAULT_METADATA_TYPE_REGISTRY` or `BUILTIN_METADATA_TYPE_SCHEMAS`; the only
20+
mounted `ThemeProvider` is the app-shell chrome light/dark toggle (unrelated to
21+
`ThemeSchema`); and no stack- or app-level key ever selected an active theme.
22+
An author who wrote a theme shipped it through every green gate and the console
23+
looked exactly the same.
24+
25+
**What is refused:** the top-level `themes:` key. `ObjectStackDefinitionSchema`
26+
is a `strictObject`, so the key is deleted from the shape and the unknown-key
27+
rejection carries the retirement prescription via the schema's `guidance` entry
28+
(removal citation, why it was inert, and the `app.branding` replacement).
29+
`ThemeSchema`, `ColorPaletteSchema`, `TypographySchema`, `BorderRadiusSchema`,
30+
`ShadowSchema`, `ThemeModeSchema`, `defineTheme` and the `Theme` /
31+
`ThemeParsed` / `ColorPalette` / `Typography` / `BorderRadius` / `Shadow` /
32+
`ThemeMode` types are removed from `@objectstack/spec` / `@objectstack/spec/ui`
33+
(orphaned value schemas leave with their one consumer, #3950). `PUT
34+
/api/v1/meta/theme/:name` now gets the #8421 unrecognised-type refusal — the
35+
`themes: 'theme'` fold left `PLURAL_TO_SINGULAR` and with it the generated
36+
URL-spelling contract — instead of the pre-#10194 store-anything branch.
37+
38+
**What stays:** `app.branding.primaryColor` / `accentColor` — the one live
39+
colour surface (objectui's `AppShell` reads it and derives `--primary`,
40+
`--accent` and friends) — plus objectui's `ThemeEngine` / `ThemeContext` engine
41+
code and their unit tests, explicitly retained by the ruling. Legacy stored
42+
`theme` rows are untouched: reads still answer, DELETE still works, and
43+
`applyConversionsToStoredItem` passes them through unchanged.
44+
45+
The retirement kit:
46+
47+
- strict deletion + `guidance` prescription at the stack schema
48+
(`packages/spec/src/stack.zod.ts`); `packages/spec/src/ui/theme.zod.ts`
49+
deleted whole
50+
- ADR-0087 registration: retired-def entries `ui/Theme`, `ui/ThemeMode`,
51+
`ui/ColorPalette`, `ui/Typography`, `ui/BorderRadius`, `ui/Shadow` and the
52+
D3 **semantic** entry `stack-themes-carrier-retired` (protocol 18). Semantic
53+
rather than a D2 conversion on the lossless-only scope guard: a stack may
54+
declare N themes and M apps, so which palette entry becomes which app's
55+
`branding.primaryColor` is a judgment the transform cannot make — the entry
56+
prescribes the hand move instead of auto-deleting authored content
57+
- ingest mapping removed (`packages/metadata/src/plugin.ts`), CLI stats row
58+
removed, showcase example re-based on app branding
59+
- pin tests: `stack-top-level-strict.test.ts` (refusal carries `#10485` +
60+
`app.branding` + no rename suggestion; replacement parses green; no theme
61+
export survives on `./ui`) and `protocol.unrecognised-meta-type.test.ts`
62+
(`/meta/theme` refused with the ADR-0112 envelope, nothing stored)
63+
- generated baselines/docs follow the schema (`authorable-surface/`,
64+
`json-schema.manifest/`, api-surface, export-origins, meta-url-spelling,
65+
spec-changes, upgrade guide, reference docs, skill references)
66+
67+
## FROM → TO
68+
69+
```ts
70+
// before — parsed green, stored by artifact ingest, applied by NOTHING:
71+
defineStack({
72+
themes: [{ name: 'corporate', label: 'Corporate', mode: 'light',
73+
colors: { primary: '#7C3AED' } }],
74+
});
75+
76+
// after — delete the key; colour the console where something reads it:
77+
defineApp({
78+
name: 'my_app',
79+
label: 'My App',
80+
branding: { primaryColor: '#7C3AED', accentColor: '#06B6D4' },
81+
});
82+
// a custom CSS variable your own stylesheet consumed has no spec slot any
83+
// more — move it into your own CSS.
84+
```
85+
86+
<!-- adr-0087: registered stack-themes-carrier-retired -->

‎content/docs/getting-started/examples.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ os compile # Build to dist/objectstack.json
293293
A kitchen-sink workspace built for demonstration and debugging. It exercises
294294
nearly every metadata type, view type, and chart type in a single app — objects,
295295
views, apps, pages, dashboards, reports, datasets, flows, jobs, agents, security
296-
profiles, translations, themes, webhooks, and more. Use it as a living reference
296+
profiles, translations, webhooks, and more. Use it as a living reference
297297
when you want to see how a particular metadata type is authored.
298298

299299
```bash

‎content/docs/getting-started/quick-reference.mdx‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ Core business logic and data modeling schemas.
4646
| **[Postgres Driver](/docs/references/data/driver-postgres)** | `driver/postgres.zod.ts` | PostgresConfig | PostgreSQL configuration |
4747
| **[Mongo Driver](/docs/references/data/driver-mongo)** | `driver/mongo.zod.ts` | MongoConfig | MongoDB configuration |
4848

49-
## UI Protocol (11 of 17 schemas)
49+
## UI Protocol (10 of 16 schemas)
5050

51-
Presentation layer - views, forms, dashboards, and themes.
51+
Presentation layer - views, forms, dashboards, and app branding.
5252

5353
| Protocol | Source File | Key Schemas | Purpose |
5454
|:---------|:-----------|:------------|:--------|
@@ -61,7 +61,6 @@ Presentation layer - views, forms, dashboards, and themes.
6161
| **[Action](/docs/references/ui/action)** | `action.zod.ts` | Action, ActionType | UI button actions |
6262
| **[Component](/docs/references/ui/component)** | `component.zod.ts` | PageComponent variants | Reusable UI components |
6363
| **[Chart](/docs/references/ui/chart)** | `chart.zod.ts` | Chart, ChartType | Chart definitions |
64-
| **[Theme](/docs/references/ui/theme)** | `theme.zod.ts` | Theme, ColorPalette | Theming and branding |
6564
| **[Widget Contract](/docs/protocol/objectui/widget-contract)** ↗ | `widget.zod.ts` | FieldWidgetProps | Props a custom field widget receives — the contract is documented with ObjectUI, outside `references/ui/` |
6665

6766
## Kernel Protocol (17 of 31 schemas)

‎content/docs/getting-started/quick-start.mdx‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ app-showcase/
160160
├── objectstack.config.ts
161161
├── src/
162162
│ ├── data/ # objects, extensions, hooks, mappings, analytics, seed
163-
│ ├── ui/ # views, pages, apps, actions, dashboards, reports, datasets, themes
163+
│ ├── ui/ # views, pages, apps, actions, dashboards, reports, datasets
164164
│ ├── automation/ # flows, jobs, webhooks
165165
│ ├── security/ # permission sets, positions, sharing rules, capabilities
166166
│ ├── system/ # apis, books, connectors, datasources, emails, server, translations
@@ -203,7 +203,6 @@ is the full authorable set, ordered data → interface → automation → integr
203203
| `dashboards` | Chart and metric boards | [Dashboards](/docs/ui/dashboards) |
204204
| `reports` | Saved analytical queries with grouping and totals | [Reference](/docs/references/ui/report) |
205205
| `actions` | Buttons and bulk operations, with CEL visibility | [Actions](/docs/ui/actions) |
206-
| `themes` | Color tokens and branding | [Reference](/docs/references/ui/theme) |
207206
| `translations` | i18n bundles for labels and messages | [Translations](/docs/ui/translations) |
208207
| `docs` | In-app Markdown documentation items | [Doc Pages](/docs/ui/doc-pages) |
209208
| `books` | Ordered navigation spines over those doc items | [Reference](/docs/references/system/book) |

‎content/docs/protocol/objectui/widget-contract.mdx‎

Lines changed: 21 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -269,54 +269,29 @@ parse-clean no-op. Large datasets page via the view's `pagination` block.
269269

270270
## Theme
271271

272-
ObjectUI theming is defined by `ThemeSchema` in `packages/spec/src/ui/theme.zod.ts`, and it declares **ten** authorable keys — that list is the whole vocabulary. Five of them are identity and inheritance: `name` (a snake_case identifier) and `label` are required, `description` is optional, `mode` is one of `light`, `dark`, or `auto` (default `light`), and `extends` names another theme to inherit from. The other five are the token surface:
273-
274-
| Key | Required | Shape | What it puts on the document |
275-
|-------|-------|-------|-------|
276-
| `colors` | ✅ | `ColorPalette`; only `primary` is mandatory inside it | The shadcn palette variables — **renamed on the way out**: `surface` emits `--card`, `text` emits `--foreground`, `textSecondary` emits `--muted-foreground`, `disabled` emits `--muted`, `error` emits `--destructive`. |
277-
| `borderRadius` | — | A scale object (`none`/`sm`/`base`/`md`/`lg`/`xl`/`2xl`/`full`), not a single token | `--radius-sm`, `--radius-md`, ... — and `base` emits the bare `--radius`. |
278-
| `shadows` | — | The same stops plus `inner` | `--shadow-sm`, `--shadow-md`, ... — and `base` emits the bare `--shadow`. |
279-
| `typography` | — | One live key since #5021: `fontFamily.base` | `--font-sans`. |
280-
| `customVars` | — | A flat string map | Every entry verbatim, `--` prefixed if you omit it: `z-modal: '1050'` emits `--z-modal: 1050`. This is the declared door for any other custom property. |
281-
282-
```yaml
283-
name: corporate
284-
label: Corporate
285-
mode: light
286-
colors:
287-
primary: '#2563eb'
288-
surface: '#ffffff'
289-
text: '#111827'
290-
borderRadius:
291-
base: 0.25rem
292-
md: 0.375rem
293-
shadows:
294-
base: '0 1px 3px rgb(0 0 0 / 0.1)'
295-
typography:
296-
fontFamily:
297-
base: 'Inter, system-ui, sans-serif'
298-
customVars:
299-
space-4: 1rem
272+
The `themes` authoring surface was **retired** in `@objectstack/spec` 17.1
273+
(#10485, ADR-0049 enforce-or-remove). Authored themes were parsed and stored,
274+
but no framework package ever read them back and nothing selected an active
275+
theme, so a declared theme never changed anything on screen. A stack that still
276+
declares `themes:` is now refused at parse with a prescription pointing here.
277+
278+
**`app.branding` is the one colour surface.** Set
279+
`branding.primaryColor` / `branding.accentColor` on the app
280+
(`packages/spec/src/ui/app.zod.ts`): objectui's `AppShell` converts them to
281+
HSL and writes `--primary`, `--primary-foreground`, `--ring`,
282+
`--sidebar-primary`, `--sidebar-ring`, `--accent` and `--accent-foreground`,
283+
re-deriving them on the light/dark flip.
284+
285+
```ts
286+
export const MyApp = defineApp({
287+
name: 'my_app',
288+
label: 'My App',
289+
branding: { primaryColor: '#2563eb', accentColor: '#06b6d4' },
290+
});
300291
```
301292

302-
`ThemeSchema` is `.strict()` (#4001), so a key outside that list is a **parse failure** at `defineStack({ themes })` / `defineTheme()`, carrying its own prescription — not a value silently dropped while the theme still reports valid.
303-
304-
<Callout type="warn">
305-
**Older theme samples no longer parse** — check yours before copying it forward.
306-
**#3494** removed `spacing`, `breakpoints`, `logo`, `density`, `wcagContrast`,
307-
`rtl`, `touchTarget` and `keyboardNavigation`: the theme engine never emitted a
308-
variable for any of them, so authoring one was a silent no-op. **#5021**
309-
(`@objectstack/spec` 17.0.0, ADR-0049) removed `animation`, `zIndex`, the
310-
`typography.fontSize` / `fontWeight` / `lineHeight` / `letterSpacing` scales and
311-
`typography.fontFamily.heading` / `mono`: those *were* emitted, faithfully and
312-
for years, but no first-party component or stylesheet has ever read one.
313-
The prescription in both waves is `customVars`, and it is a byte-for-byte
314-
replacement — `customVars` carrying `font-size-lg: 1.125rem` puts exactly the
315-
same `--font-size-lg` on the document the retired scale did. Run
316-
`os migrate meta --from 16` to rewrite stored metadata automatically.
317-
</Callout>
318-
319-
Widgets inherit the active theme automatically; they do not each carry their own copy of the palette or the font stack.
293+
Widgets read the resulting CSS variables (`hsl(var(--primary))`, …); they do
294+
not each carry their own copy of the palette.
320295

321296
## What's Next?
322297

‎content/docs/references/index.mdx‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: Protocol Reference
3-
description: Every schema published by @objectstack/spec — 1589 schemas across 14 protocol modules
3+
description: Every schema published by @objectstack/spec — 1583 schemas across 14 protocol modules
44
---
55

66
{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}
@@ -32,8 +32,8 @@ counts are sums of the rows they head. Regenerate with
3232
| [Shared Protocol](/docs/references/shared) | 8 | 31 | Primitives used across every protocol — identifiers, HTTP, expressions, error maps, enums. |
3333
| [Studio Protocol](/docs/references/studio) | 3 | 35 | Studio designer metadata — the authoring surfaces for the protocols above. |
3434
| [System Protocol](/docs/references/system) | 36 | 287 | The runtime environment — logging, jobs, cache, metrics, notifications, i18n and compliance. |
35-
| [UI Protocol](/docs/references/ui) | 17 | 162 | Apps, pages, views, dashboards, reports, actions and themes — the ObjectUI layer. |
36-
| **Total** | **199** | **1589** | 14 protocol modules |
35+
| [UI Protocol](/docs/references/ui) | 16 | 156 | Apps, pages, views, dashboards, reports, actions and themes — the ObjectUI layer. |
36+
| **Total** | **198** | **1583** | 14 protocol modules |
3737

3838
---
3939

@@ -364,7 +364,7 @@ The runtime environment — logging, jobs, cache, metrics, notifications, i18n a
364364

365365
## UI Protocol
366366

367-
**Source:** `packages/spec/src/ui/` · **Import:** `@objectstack/spec/ui` · **17 pages, 162 schemas**
367+
**Source:** `packages/spec/src/ui/` · **Import:** `@objectstack/spec/ui` · **16 pages, 156 schemas**
368368

369369
Apps, pages, views, dashboards, reports, actions and themes — the ObjectUI layer.
370370

@@ -385,7 +385,6 @@ Apps, pages, views, dashboards, reports, actions and themes — the ObjectUI lay
385385
| [`report.zod.ts`](/docs/references/ui/report) | `JoinedReportBlock`, `Report`, `ReportChart`, `ReportSort`, `ReportType` |
386386
| [`responsive.zod.ts`](/docs/references/ui/responsive) | `BreakpointColumnMap`, `BreakpointName`, `BreakpointOrderMap`, `ResponsiveConfig`, `ResponsiveStyles`, `StyleMap` |
387387
| [`sharing.zod.ts`](/docs/references/ui/sharing) | `SharingConfig` |
388-
| [`theme.zod.ts`](/docs/references/ui/theme) | `BorderRadius`, `ColorPalette`, `Shadow`, `Theme`, `ThemeMode`, `Typography` |
389388
| [`view.zod.ts`](/docs/references/ui/view) | `AddRecordConfig`, `AppearanceConfig`, `CalendarConfig`, `ColumnPrefix`, `ColumnSummary`, `ColumnSummaryConfig`, `FormButtonConfig`, `FormField`, `FormFieldPublicPicker`, `FormSection`, `FormView`, `GalleryConfig`, `GanttConfig`, `GanttQuickFilter`, `GroupingConfig`, `GroupingField`, `HttpMethodSubset`, `HttpRequest`, `KanbanConfig`, `ListChartConfig`, `ListColumn`, `ListMapConfig`, `ListView`, `NavigationConfig`, `NavigationMode`, `ObjectListView`, `ObjectUserFilters`, `PaginationConfig`, `RowColorConfig`, `RowHeight`, `SelectionConfig`, `TimelineConfig`, `TreeConfig`, `UserActionsConfig`, `UserFilterField`, `UserFilters`, `View`, `ViewData`, `ViewFilterRule`, `ViewItem`, `ViewItemName`, `ViewItemWire`, `ViewKind`, `ViewScope`, `ViewSharing`, `ViewTab`, `VisualizationType` |
390389

391390
---

‎content/docs/references/ui/index.mdx‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,5 @@ This section contains all protocol schemas for the ui layer of ObjectStack.
2121
<Card href="/docs/references/ui/report" title="Report" description="Source: packages/spec/src/ui/report.zod.ts" />
2222
<Card href="/docs/references/ui/responsive" title="Responsive" description="Source: packages/spec/src/ui/responsive.zod.ts" />
2323
<Card href="/docs/references/ui/sharing" title="Sharing" description="Source: packages/spec/src/ui/sharing.zod.ts" />
24-
<Card href="/docs/references/ui/theme" title="Theme" description="Source: packages/spec/src/ui/theme.zod.ts" />
2524
<Card href="/docs/references/ui/view" title="View" description="Source: packages/spec/src/ui/view.zod.ts" />
2625
</Cards>

‎content/docs/references/ui/meta.json‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
"report",
1717
"---Interaction & Layout---",
1818
"responsive",
19-
"theme",
2019
"---Platform---",
2120
"i18n",
2221
"notification",

0 commit comments

Comments
 (0)