Skip to content

Commit e2c19f9

Browse files
committed
Merge origin/main (0ffc423) into claude/issue-11070-strict-face-read-keys
Brings in the @objectstack/spec 17.5.0 resolution (objectui#11073, #11086), whose ElementDataSourceSchema.filter takes the ViewFilterRule array, so this branch's pins can be measured on the tree the merge queue builds. No conflicts; six files auto-merged. Refs objectui#11070 Claude-Session: https://claude.ai/code/session_012UwY3ahMixEFkfTUxMVkYm Co-authored-by: Claude <noreply@anthropic.com>
2 parents 8628df2 + 0ffc423 commit e2c19f9

147 files changed

Lines changed: 5005 additions & 2745 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.

‎.changeset/10071-number-scale-ceiling.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ edit. Both now take the ruling the percent faces already took (objectui#9808):
1313
the width is clamped to 100 and a one-time `console.warn` names the declared
1414
width, the rendered width and the card. In-range, negative and non-integer
1515
widths are unchanged.
16+
17+
⚠️ **Dated note, 2026-09-29 — the clamp above was retired in this same release — objectui#11073.**
18+
Later in this release this repository began resolving `@objectstack/spec` 17.5.0, which refuses a field `scale` above 100 at the declaration (`too_big` at `scale`, a computed number field included). The objectui#9808 ruling this change followed retires at exactly that point, so the clamp and its one-time warning are gone from `NumberCellRenderer` and from a grid's computed column: the declared width is passed through again, and a width above 100 is no longer something an author can declare.

‎.changeset/10355-grid-currency-minor-unit.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,6 @@ line with the ruling on objectstack-ai/objectstack#19910 that a currency's
4343
decimal places are the currency's. A USD tenant's grid used to read `¥1,234.57`
4444
and now reads `$1,234.57`. Columns with an authored `scale`, and `number`
4545
columns, round as before.
46+
47+
⚠️ **Dated note, 2026-09-29 — one sentence above was made false in this same release — objectui#11073.**
48+
The sentence saying an authored currency `scale` above 100 "is clamped and reported on the display too" no longer holds. Later in this release this repository began resolving `@objectstack/spec` 17.5.0, which refuses a `scale` above 100 at the declaration, and the objectui#10071 clamp that sentence relied on was retired with it. The display now uses the authored width as it is, as the stored value does. Everything else above is unchanged.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
'@object-ui/types': minor
3+
'@object-ui/core': minor
4+
'@object-ui/data-objectstack': patch
5+
'@object-ui/fields': patch
6+
'@object-ui/components': patch
7+
'@object-ui/plugin-list': patch
8+
'@object-ui/app-shell': minor
9+
'@object-ui/console': patch
10+
---
11+
12+
objectui now resolves `@objectstack/*` 17.5.0 and `zod` 4.6.5, and follows every contract move that release makes (objectui#11073). `@objectstack/spec` 17.5.0 and `@objectstack/core` 17.5.0 require `zod ^4.6.1`, so objectui's own `zod` resolves to the same 4.6.5: two zod minors do not type-check against each other.
13+
14+
⚠️ Breaking in places, marked `minor` under this repo's version-alignment rule (a `major` in the fixed group would move all of it off the `@objectstack` major). Every narrowing below is the spec's own, and already reaches any consumer that resolves `@objectstack/spec ^17.5`.
15+
16+
- `@object-ui/types`: declares `@objectstack/spec ^17.5.0` and `zod ^4.6.1`. A named list view's `pageName` and `tabs` are retired, as the spec retired them: typed `never` and refused by name at parse. `DashboardWidgetSchema` attaches the spec's two new checks (`checkDashboardWidgetStageOrder`, `checkDashboardWidgetMetricMeasureArity`), so a widget the spec refuses is refused here too. Where a strict object is an arm of a plain union, its unknown-key refusal is terminal again (the spec's own mechanism, needed under zod 4.6): the union answers with every arm instead of the one that failed only on unknown keys. That changes the error shape, never the verdict (measured on every objectui union). Two by-name named-view checks that can no longer run are retired; the spec's refusal answers those documents.
17+
- `@object-ui/core`: declares `@objectstack/spec ^17.5.0`. `page` leaves the list-view kinds the normalizer knows, as the spec removed `type: 'page'`. `isRefusedTextComparand` and `textComparandRefusalReason` are re-exported from `@objectstack/spec/data`, whose copies are byte-identical. `SPEC_ACTION_KEYS` lists `execution`, which `ActionSchema` now declares.
18+
- `@object-ui/data-objectstack`: declares `@objectstack/spec ^17.5.0`, up from `^17.4.0`. Its bundle carries `@object-ui/core`'s filter converter, which now takes `isRefusedTextComparand` and `textComparandRefusalReason` from `@objectstack/spec/data`. `@objectstack/spec` 17.4.0 exports neither, so the old range admitted a spec under which the shipped module names exports that are not there (objectui#5793's floor gate). Nothing moves at runtime in this repository, because the lockfile already resolves 17.5.0. `patch`, as the floor raise of objectui#10864 was.
19+
- `@object-ui/fields`: the percent and number `scale` clamp is gone, at the sunset its own test named. The spec now refuses a `scale` above 100 at the declaration, so the width a formatter cannot render no longer arrives, and every face passes the declared width through as it did before the clamp.
20+
- `@object-ui/components`: two module-local prop interfaces of the action renderers are renamed (`ActionButtonRendererProps`, `ActionIconRendererProps`), because the spec now exports the old names for its authored props. Neither is reachable through the package's exports map; only the shipped per-file declarations change.
21+
- `@object-ui/plugin-list`: the README's view-type example no longer lists the retired `page` kind.
22+
- `@object-ui/app-shell`: the flow designer follows 17.5.0 (maintainer ruling on objectui#11088, decision 2). A new `wait` node is seeded `waitEventConfig: { eventType: 'timer', timerDuration: 'PT1H' }`, because the spec now refuses a timer wait with no duration; the inspector shows the Duration at once and it can be changed. The decision form offers the spec's new `mode` (exclusive or inclusive), with no default declared because the spec applies none. The screen form's `mode` states `create` again, because the spec now applies that default. `minor` because the decision form gains a control.
23+
- `@object-ui/app-shell`: declares `@objectstack/spec ^17.5.0`, up from `^17.4.0`, and `zod ^4.6.1`, up from `^4.4.3`. The designer now states 17.5.0 behaviour. The screen form's declared `create` default equals a default the spec applies only since 17.5.0, and objectui#9109 requires the two to be equal, so a range that admitted 17.4.0 claimed more than the designer holds to. The resolved versions do not move.
24+
- `@object-ui/console`: the bundle inlines the 17.5.0 packages, so its client-side validation answers as the published 17.5.0 contract does. The flow preview sample's script nodes use the 17.5.0 script contract. The eager-closure budget is re-baselined for the release's growth, under the maintainer ruling on objectui#11088 (decision 1).
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
---
4+
5+
fix(app-shell): a shared `?sel=nav:ID` link survives the designer's mount and opens that nav item, without entering editing on a read-only package (objectui#11153)
6+
7+
The nav-item deep link (objectui#2272) never opened anything, in either designer that
8+
carries it: Studio's Interfaces pillar and the metadata editor's `app` page. Each mirrors
9+
its nav selection back to `sel`, and that mirror's first pass runs at mount, before the
10+
app's draft has loaded and with no selection yet, so it deleted the param. When the draft
11+
arrived there was nothing left to apply, and the shared URL opened with no nav item
12+
selected.
13+
14+
Both copies now go through one hook, which keeps the param while it is unapplied and the
15+
draft has not loaded, and applies it once when the draft arrives. An id the app does not
16+
have changes nothing.
17+
18+
Applying the link reads the package's write state. On a read-only package the link
19+
selects the item without entering nav editing, because nav edits autosave and that
20+
autosave is blocked there: opening the editor would take edits on screen and discard
21+
them. The metadata editor shows that selection read-only (the row is marked and the
22+
inspector opens on it); the Interfaces pillar has no view-mode rendering of a nav
23+
selection, so there it is held in the URL. The Studio surface learns the write state from
24+
the package list, a request of its own, so the link waits for that answer instead of
25+
reading "not answered yet" as writable.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
---
4+
5+
fix(app-shell): the report and dashboard-widget pickers show a dataset member's label and the dataset's description
6+
7+
The report inspector and the dashboard-widget inspector now show the text a
8+
dataset declares for its author, beside the machine names. Each measure and
9+
dimension option shows the member's `label`, and each dataset option shows the
10+
dataset's `description`. Before, every measure and dimension option showed the
11+
bare name, and no picker showed a description.
12+
13+
The form is the same in both inspectors: the author's label, then the machine
14+
name. The add-member lists show the label with the name in a code chip beside
15+
it (`Revenue · sum` beside `revenue`). The report's chart-axis selects write
16+
`Revenue (revenue) · sum`, the form the dataset picker already used. The
17+
dashboard's filter-field picker shows the name, then the label. A measure keeps
18+
its ` · aggregate` hint where it showed before. A dataset option adds its
19+
description after ` — ` in the report's select, and as the muted hint in the
20+
dashboard's searchable picker. Where the dataset declares no label or
21+
description, each option reads as it did before.
22+
23+
The label, the description and the dataset label are `I18nLabel`. They resolve
24+
through the spec's `resolveI18nLabel` in the designer's language, so an inline
25+
per-locale map shows its entry for that language. Before, a map-valued dataset
26+
label showed the machine name instead. A language switch re-reads the text
27+
without refetching the catalog. The text is display only. What a pick stores
28+
(`report.values`, `rows`, `columns`, `chart` axes, `dataset`, and the widget's
29+
`dimensions`, `values` and `dataset`) is still the machine name.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
'@object-ui/components': patch
3+
---
4+
5+
`page:header` no longer draws an empty breadcrumb slot, and an authored `breadcrumb` is
6+
ignored (objectui#11166).
7+
8+
The renderer used to read `breadcrumb` (the spec's `PageHeaderProps.breadcrumb`, default
9+
`true`) and draw an empty `data-page-breadcrumb-slot` div above the title, in both the bare
10+
and the record-chip layout. Nothing ever filled it, and the console's app header already
11+
draws the breadcrumb trail, so the key is being retired rather than wired up; the spec half is
12+
objectstack#20758. Until that retirement reaches this package's `@objectstack/spec` pin the
13+
contract still accepts the key, so an authored `breadcrumb` (`true` or `false`) renders
14+
exactly like an absent one: no slot and no error. No trail is drawn in its place.
15+
16+
**Visible change: the title moves up.** The empty div still took space. In the bare layout
17+
it was an item of the root's `gap-2` column, so the title row sat one `gap-2` (0.5rem) below
18+
the top of the header; in the record-chip layout it carried `mb-1` (0.25rem) above the chip.
19+
Both are gone on every header that did not already set `breadcrumb: false`. No class string
20+
on the header changed.
21+
22+
The `page:header` registration keeps declaring the `breadcrumb` input while the contract
23+
accepts the key, with a description that says it is ignored.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
'@object-ui/cli': minor
3+
---
4+
5+
feat(cli): `objectui check` refuses a `${…}` on a text key its node never evaluates
6+
7+
`SchemaRenderer` evaluates an expression on the closed text keys `title`,
8+
`label`, `value` and `description` only where `@objectstack/spec`'s
9+
`expressionBindableTextKeysFor(type)` lists that key for the node's type.
10+
Anywhere else the expression is never resolved, so the user sees
11+
`${data.total}` as literal text, or nothing at all — and no step before the
12+
browser said so.
13+
14+
`objectui check` now refuses such an expression in every file it recognises as
15+
an ObjectUI schema, and the run exits non-zero. The refusal names the key, the
16+
path to it (spelled as `objectui validate` spells paths), the keys that type
17+
does evaluate, and the channels `SchemaRenderer` evaluates. Types with no row in
18+
the carriage map are refused too: `text.value` and `action:button.label` are
19+
never evaluated.
20+
21+
- **Component nodes only**: the file's root node and every node its `children`
22+
hold. Objects under other keys, such as a form's `fields` entries, are
23+
definitions rather than nodes and are not judged. A root of type `page` keeps
24+
its own `title`, which is a page key; its `children` are still judged.
25+
- **The type is matched as written**, as the runtime matches it: `ui:card` has
26+
no row, and is not read as `card`.
27+
- **A type no registered component answers to** gets a warning instead of a
28+
refusal, because a custom renderer may evaluate its own keys.
29+
- **There is no escape spelling**: a `${…}` meant as literal text on one of
30+
these keys, such as a code sample in a `code-editor`'s `value`, is refused
31+
too. Write it without `${`.
32+
33+
The key vocabulary and the per-type carriage map are read from
34+
`@objectstack/spec`, now a declared dependency of `@object-ui/cli`, so a row
35+
added upstream moves this check and the runtime together.

‎.changeset/7715-mirrors-carry-spec-object-checks.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@ A mirror built from the spec's `.shape` (`specFieldsExcept(...)`) takes the spec
1414
The spec's other `ListViewSchema` check, `checkListViewPageMount`, is **not** attached: it reads `type`, which on a `list-view` node is the component discriminator rather than the spec's view kind (that rides as `viewType`), so attaching it would refuse every `pageName`, a valid page mount included. The navigation-area, app, dashboard-widget and dashboard mirrors attach nothing because their spec objects carry no object-level check at the resolved spec release. `GlobalFilterSchema` already ran the spec's date-default check through its delegating re-parse and is unchanged.
1515

1616
`packages/types/src/__tests__/spec-object-refinements-7715.test.ts` accounts for every object-level check each of the six spec objects carries, so a check the spec adds in a later release fails there by site name instead of being dropped.
17+
18+
⚠️ **Dated note, 2026-09-29 — `@objectstack/spec` 17.5.0 moved two sentences above — objectui#11073.**
19+
Later in this same release this repository began resolving `@objectstack/spec` 17.5.0, which retired `type: 'page'` and `pageName` on list views (ADR-0049 enforce-or-remove) and no longer exports `checkListViewPageMount`. So the paragraph on that check describes a spec that is no longer installed: there is no such check to attach, and a `pageName` is refused by the spec itself as a retired key, not a "valid page mount". The same release adds two object-level checks to the spec's `DashboardWidgetSchema`, `checkDashboardWidgetStageOrder` and `checkDashboardWidgetMetricMeasureArity`, and objectui's `DashboardWidgetSchema` now attaches both, so "the dashboard-widget mirror attaches nothing" no longer holds either: a non-funnel widget carrying `options.stageOrder`, and a metric-family widget declaring more than one measure in `values`, are refused with the spec's own message.

‎.changeset/8201-quickadd-ruled-carve-out.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ bookkeeping (the `objectui#8176` backlog ceiling reaches 0, with the ruling reco
1111
data rather than prose) and the docblock in `packages/plugin-kanban/src/index.tsx`, which
1212
said the disposition was still with the maintainer. It is not — it was ruled on
1313
2026-09-07, and objectui#8285 owns the fix.
14+
15+
⚠️ **Dated note, 2026-09-29 — the carve-out recorded above was harvested in this same release — objectui#11073.**
16+
Later in this release this repository began resolving `@objectstack/spec` 17.5.0, which carries objectui#8285's ruled retirement: `object-kanban.quickAdd` is now a spec tombstone, refused by name. The exit the ruling named therefore landed. The carve-out's exemption entry was deleted, the ruled carve-out list is empty, and the key is pinned among the gate's tombstones instead. It is no longer a RULED CARVE-OUT awaiting a fix, and `OBJECT_KANBAN_INPUTS` still does not declare it.

‎.changeset/8285-kanban-quickadd-html-diagnostic.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,6 @@ Interim by ruling (objectui#8285, decision batch #91): the contract-side refusal
2323
retiring `object-kanban.quickAdd` from the spec's `ComponentPropsMap`, and this
2424
diagnostic is removed by the change that lands it. `kanban-ui` keeps the
2525
`quickAdd` / `onQuickAdd` pair untouched.
26+
27+
⚠️ **Dated note, 2026-09-29 — the contract moved in this same release — objectui#11073.**
28+
The reason given above, that "has no prop quickAdd" was false because `@objectstack/spec` publishes the key, no longer holds. Later in this release this repository began resolving `@objectstack/spec` 17.5.0, which carries the retirement this diagnostic was declared interim for: `object-kanban.quickAdd` is now a spec tombstone, refused by name at the authoring door. The diagnostic's own removal belongs to the change that ruled it and is not made here. Until then, the key it names is one the contract itself refuses.

0 commit comments

Comments
 (0)