Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
3796d59
chore(deps): resolve @objectstack/* 17.6.0 in pnpm-lock.yaml (objectu…
claude Oct 2, 2026
b6684fd
chore(scripts): spec-symbols allows @object-ui/components' EmptyState…
claude Oct 2, 2026
c2dc334
refactor(app-shell,data-objectstack): retire the `| 'computed'` widen…
claude Oct 2, 2026
3b3cc6b
test(plugin-dashboard): read the ADR-0087 registry from @objectstack/…
claude Oct 2, 2026
1eff255
fix(components): page:header stops publishing `breadcrumb`, which @ob…
claude Oct 2, 2026
6e76e90
test(console): strike the two `endpoint` bookings @objectstack/spec 1…
claude Oct 2, 2026
7ca5a36
fix(i18n): recognise a served translation document by its `picklists`…
claude Oct 2, 2026
5ef3050
test(plugin-designer): the `constructor` field-name refusal is read a…
claude Oct 2, 2026
74fd7eb
docs(types,core,app-shell,plugins): restamp the installed-pin claims …
claude Oct 2, 2026
d73f74e
chore(changeset): declare the @objectstack/* 17.6.0 bump (objectui#11…
claude Oct 2, 2026
8879fe5
test(scripts,app-shell,console): re-pin the counts and keys @objectst…
claude Oct 3, 2026
31c6905
test(types): object-grid's bag `grouping` is judged since @objectstac…
claude Oct 3, 2026
2ba091c
test(types): the card footer is a judged child position since @object…
claude Oct 3, 2026
060cec8
chore(scripts): lower the eager-closure ceilings by the 250,096 bytes…
claude Oct 3, 2026
40d9b5a
Merge remote-tracking branch 'origin/main' into claude/issue-11438-ob…
claude Oct 3, 2026
bb6d7d3
Merge origin/main (c73cdb5) into claude/issue-11438-objectstack-17-6-0
claude Oct 3, 2026
00c13e7
test(console): book record:line_items' 17.6.0 differences to objectui…
claude Oct 3, 2026
c9121f9
test(console): the group-5 booking's prose names no installed version…
claude Oct 3, 2026
acd62a3
fix(core): ValueDataSource executes is_empty / is_not_empty and $empt…
claude Oct 3, 2026
158204d
fix(core): convertFiltersToAST lowers $empty, the canonical operator …
claude Oct 3, 2026
9786e01
test: promote the staged-$empty tripwires to @objectstack/spec 17.6.0…
claude Oct 3, 2026
4ac6be7
feat(plugin-grid,plugin-list,types): follow object-grid's 17.6.0 desc…
claude Oct 3, 2026
518c855
chore(changeset): objectui#11227's changeset, and corrections to thre…
claude Oct 3, 2026
ed622b4
test: type the two casts the slice's new pins added instead of wideni…
claude Oct 3, 2026
8a9cf1b
test(core): the refusal-subject census names the $empty flag refusal,…
claude Oct 3, 2026
6a86dd1
test(types),docs: register EmptyStateSchema at the import boundary, r…
claude Oct 3, 2026
da4c629
Merge origin/main (6f5719e1c) into claude/issue-11438-objectstack-17-6-0
claude Oct 3, 2026
9187c5c
Merge trunk claude/issue-11438-objectstack-17-6-0 (da4c629f1) into ob…
claude Oct 3, 2026
0a518da
test(types): book the dimensionless measure-arity check on the 7715 c…
claude Oct 3, 2026
c4775ed
test(types,plugin-dashboard): book the dimensionless measure-arity ro…
claude Oct 3, 2026
6c5011d
test(console): book row 1 of the 17.6.0 bump, object-grid.keyboardNav…
claude Oct 3, 2026
bebd7ec
test(console): the row-1 booking's docblock cites ruling A″ by record…
claude Oct 3, 2026
13f07dd
test(core): book row 5 of the 17.6.0 bump, ActionSchema.outcomeMessag…
claude Oct 3, 2026
6b8a0ed
fix(types): raise the declared @objectstack/spec floor to ^17.6.0 (ob…
claude Oct 3, 2026
56fe66b
Merge trunk claude/issue-11438-objectstack-17-6-0 (13f07dd0f) into cl…
claude Oct 3, 2026
0507d67
docs(changeset): the 17.6.0 bump's range sentence names the one floor…
claude Oct 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/11068-grid-declared-keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,9 @@ now authors only keys the grid reads.
**Unchanged.** An `object-view`'s `table` slot still withholds `description` and `emptyState`.
Write them on the `object-grid` node itself. `keyboardNavigation` is still declared and still
not read.

**Correction, 2026-10-03 (objectui#11227).** The Zod twin's `emptyState` is no longer three
optional strings. It is the spec's `EmptyStateSchema` by reference, which `@objectstack/spec`
17.6.0 declares on its `object-grid` row: `title` and `message` are `string | I18nLabel` (a
plain string or an inline locale map, which the grid resolves against the display locale), and
an unknown member is still refused by name (`.changeset/11227-object-grid-17-6-keys.md`).
4 changes: 4 additions & 0 deletions .changeset/11068-row1-booking-17-6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
---

Test-only change in `@object-ui/console`; no published behaviour changes. Under objectui#11438 ruling A″, row 1 of the `@objectstack/spec` 17.6.0 bump, `object-grid.keyboardNavigation`, is booked as owed to objectui#11068 in `registry-inputs-spec-parity.test.ts`, with an expiry (2026-11-02, or when objectui#11068's build lands). The entry joins the file's objectui#11111 ledger, whose `unpublishedKeys` cap rises by exactly this one entry. The GA-block split row admits this one id by name and refuses every other exemption on the four GA blocks as before. The file sits under `apps/console/src/__tests__/`, which nothing outside `__tests__/` imports, so neither the console bundle nor `plugin.*` carries it.
13 changes: 13 additions & 0 deletions .changeset/11094-value-source-empty-operator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@object-ui/core': minor
---

`ValueDataSource` executes the empty pair `is_empty` / `is_not_empty` and the `$empty` operator, and `convertFiltersToAST` lowers `$empty` (objectui#11094).

`@objectstack/spec` 17.6.0 admits `$empty` to `FILTER_OPERATORS` (objectstack#20446). It also stops folding `is_empty` / `isempty` onto `is_null`, and `is_not_empty` / `isnotempty` onto `is_not_null`, and lowers them to `$empty: true` / `$empty: false` instead (objectstack#20570). `ValueDataSource` canonicalises AST operators through the spec's `canonicalAstOperator` and had arms only for the null pair. So on 17.6.0 a stored `is_empty` or `is_not_empty` rule on a `provider: 'value'` source reached the refusal arm: it selected no row and logged one refusal per `find()`.

**After.** `is_empty` and `$empty: true` select a row whose value is null, absent, `''` or `[]`. `is_not_empty` and `$empty: false` select exactly the other rows. The answer is the spec's own `isEmptyFilterValue`, called without a field declaration, because this adapter holds none. That is the by-value reading the spec gives a face with no declarations, the same call `@objectstack/formula`'s matcher makes. A `$empty` flag that is not `true` or `false` is refused like every other refusal in this adapter: the row is excluded and the reason is logged once.

**What moves for a stored rule.** On 17.5.0 the empty pair was a null test here. A row whose value is `''` or `[]` is now selected by `is_empty` and no longer by `is_not_empty`. Rows holding a value, null or no key answer as before.

`convertFiltersToAST` lowers `{ f: { $empty: true } }` to `['f', 'is_empty', true]` and `$empty: false` to `['f', 'is_not_empty', true]`, the inverse of the spec's `parseFilterAST`. A flag that is not a boolean throws a `FilterOperatorError` (`code: 'INVALID_FILTER'`, `httpStatus: 400`). Before this, the operator reached the unknown-operator throw. The unknown-operator message now lists `$empty` among the supported operators. `@object-ui/data-objectstack`'s `find()` lowers an object `$filter` through this function, so an object filter carrying `$empty` reaches the wire there instead of throwing.
39 changes: 39 additions & 0 deletions .changeset/11227-object-grid-17-6-keys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
'@object-ui/plugin-grid': minor
'@object-ui/plugin-list': patch
'@object-ui/types': minor
---

An `object-grid` publishes `description` and `emptyState` now that `@objectstack/spec` 17.6.0
declares them on its `object-grid` row, and `emptyState.title` / `.message` take an inline
locale map on both the grid and the list view (objectui#11227).

**`@object-ui/plugin-grid` (feature and fix).**

- `description` and `emptyState` are in the grid's declared inputs, so the designer panel, the
component manifest and the generated `sdui-intrinsics.d.ts` offer them, and the SDUI parser
no longer reports an authored `emptyState` as `unknown-prop`. `description` declares both
arms of the `I18nLabel` union, so a locale map on it is not a `type-mismatch`.
- `emptyState.title` and `emptyState.message` are resolved against the display locale, as
`label` and `description` are. Before, a locale map on either reached the empty-state
component as an object, and the grid failed to render. A map with no usable entry keeps
that member's default: the table's "No results found" heading, and no message line.
- `keyboardNavigation`, the row's third 17.6.0 key, is not published. The spec marks it
`[EXPERIMENTAL — not enforced]`, and nothing in the grid reads it yet.

**`@object-ui/plugin-list` (fix).** A list view's authored `emptyState.title` and
`emptyState.message` are resolved against the display locale. Before, a locale map on either
was treated as absent, and the empty state drew the default copy in every locale. A plain
string is drawn as before.

**`@object-ui/types` (breaking for a reader of the text members, hence `minor`).**

- `ObjectGridSchema.emptyState` is the spec's `EmptyState`, and the Zod twin takes the spec's
`EmptyStateSchema` by reference. `title` and `message` are `string | I18nLabel`, `icon` stays
a string, and an unknown member is still refused by name. A locale map on `title` or
`message` now parses, and a value that is neither a string nor a map is refused at that
member.
- `NamedListView.emptyState` is `ListViewSchema['emptyState']`, the same spec type.
- TypeScript code that reads `emptyState.title` or `.message` as a `string` no longer
type-checks. Resolve the value first, for example with `resolveI18nLabel` from
`@objectstack/spec/ui`.
18 changes: 18 additions & 0 deletions .changeset/11227-types-spec-floor-17-6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
'@object-ui/types': patch
---

Raise `@object-ui/types`' declared `@objectstack/spec` floor from `^17.5.0` to
`^17.6.0` (objectui#11227). The package's published types now read
`EmptyState` from `@objectstack/spec/ui`, because the `object-grid`
`emptyState` member is typed by reference to the protocol's own shape, and its
published zod mirror reads `EmptyStateSchema` from the same subpath. Neither
export exists in `@objectstack/spec` 17.5.0, which the old range admitted; both
ship from 17.6.0. A consumer resolution landing on 17.5.0 therefore got types
and a mirror that name exports their declared spec dependency does not have.

Nothing moves at runtime in this repository: the lockfile already resolves
`@objectstack/spec` 17.6.0 for this specifier, so only the declared range was
stale. For a consumer, the range now refuses `@objectstack/spec` 17.5.0. The
instrument that re-derives this floor is `pnpm check:spec-floors`, read over a
full workspace build.
7 changes: 7 additions & 0 deletions .changeset/11276-object-grid-properties-bag.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,10 @@ Nothing changes at render time: `SchemaRenderer` hoists every `properties` key o
**What did not move.** The TypeScript `ObjectGridSchema` and its zod mirror `ObjectGridSchema` stay published and unchanged in shape. They are the node as `ObjectGrid` reads it after the hoist, and as code composes it, and the `object-view` `table` slot is still built from the mirror.

**Correction, 2026-10-02 (objectui#6152, round 6).** The list above of keys "the row declares and the flat mirror does not" is no longer true for ten of them: the flat `ObjectGridSchema` mirror now declares `rowHeight`, `grouping`, `aggregations`, `conditionalFormatting`, `rowColor`, `bulkActionDefs`, `navigation`, `singleClickEdit`, `reorderableColumns` and `operations`, each typed as its TypeScript twin types it (`.changeset/6152-objectgrid-round6-mirrored.md`). `resizableColumns` is still the row's alone. The bag is unchanged: the spec row still judges these keys inside `properties`.

**Correction, 2026-10-03 (objectui#11227).** At `@objectstack/spec` 17.6.0 the row declares
`description`, `emptyState` and `keyboardNavigation`, so the sentence above saying it does not
declare `emptyState` or `keyboardNavigation` no longer holds. All three parse in the bag, and
each written flat on the node is refused by name toward its bag member, like the row's other
members. `emptyState` is authorable in a document, and so is `description`, which no longer
stays on the node beside the bag (`.changeset/11227-object-grid-17-6-keys.md`).
5 changes: 5 additions & 0 deletions .changeset/11276-plugin-grid-properties-bag-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@
docs(plugin-grid): authored `object-grid` examples write their props in the `properties` bag (objectui#11276)

The README's authored `object-grid` examples now write `{ "type": "object-grid", "properties": { … } }`, the spelling `@objectstack/spec`'s `ComponentPropsMap['object-grid']` row declares and `objectui validate` now requires, each bag checked with `satisfies ObjectGridProps` (the spec's row type). `emptyState` is described as what it is today: a key `ObjectGrid` reads that the spec's row does not declare, so not authorable in a document. The examples that mount `ObjectGrid` directly keep the flat `schema` prop: a component mounted without `SchemaRenderer` receives the node as it reads it, and nothing hoists a bag there. Under `src/`, a new render pin holds that the bag and a stored flat node draw the same grid, and the CRUD-guide render pin reads the guide's bag. No runtime change.

**Correction, 2026-10-03 (objectui#11227).** The README no longer describes `emptyState` as
not authorable: `@objectstack/spec` 17.6.0 declares it, with `description`, on the `object-grid`
row, so both are written in the `properties` bag, and the README's example shows them there
(`.changeset/11227-object-grid-17-6-keys.md`).
4 changes: 4 additions & 0 deletions .changeset/11334-row3-booking-17-6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
---

Test-only change in `@object-ui/types` and `@object-ui/plugin-dashboard`; no published behaviour changes. Under objectui#11438 ruling A″, the spec's dimensionless measure-arity check is booked as owed to objectui#11334, with an expiry, in three tests. In `spec-object-refinements-7715.test.ts` it goes on the census's `DashboardWidgetSchema (complex.zod.ts)` row. In the two objectui#8894 measure-door tests, it is a bounded ledger of the seven types objectui's door does not refuse yet, and a cap row requires that set to equal the ledger. All three files sit under `__tests__/`, which each package's `tsconfig.json` excludes from the published `dist`.
4 changes: 4 additions & 0 deletions .changeset/11344-row5-booking-17-6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
---

Test-only change in `@object-ui/core`; no published behaviour changes. Under objectui#11438 ruling A″, row 5 of the `@objectstack/spec` 17.6.0 bump, `ActionSchema.outcomeMessages`, is booked as owed to objectui#11344 in `actionKeys.pin.test.ts`, with an expiry (2026-11-02, or when objectui#11344's slice lands, whichever is first). The file's spec-inventory row now requires its `missing` set to equal that one-entry ledger exactly, and a new row asserts today's difference: the spec declares the key, and neither `SPEC_ACTION_KEYS` nor `KNOWN_ACTION_KEYS` knows it. The file sits under `packages/core/src/actions/__tests__/`, which the package's `tsconfig.json` excludes from the build program, so the published `dist` does not carry it.
11 changes: 11 additions & 0 deletions .changeset/11438-objectstack-17-6-bump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@object-ui/components': patch
'@object-ui/i18n': patch
'@object-ui/console': patch
---

objectui now resolves `@objectstack/*` 17.6.0 (objectui#11438). One declared range moves: `@object-ui/types` raises its `@objectstack/spec` floor to `^17.6.0` in objectui#11227's own changeset, because its published types read `EmptyState` / `EmptyStateSchema`, which 17.5.0 does not export. Every other `@objectstack/*` range already admits 17.6.0 and stays as it was, and `check:spec-floors` names no other floor that has to rise. Everything below is a contract move 17.6.0 made, and it already reaches any consumer that resolves `@objectstack/spec ^17.6`.

- `@object-ui/components`: the `page:header` registration no longer publishes a `breadcrumb` input. 17.6.0 retires the key (objectstack#20758) and refuses it by name; the renderer has ignored it since objectui#11166.
- `@object-ui/i18n`: a served translation document is recognised as a spec payload when it carries only the `picklists` group, which 17.6.0's `GetTranslationsResponseSchema` adds. Such a bundle used to be returned untransformed, so nothing read it. The group is now namespaced under `app` like every other group.
- `@object-ui/console`: the bundle inlines the 17.6.0 packages, so its client-side validation answers as a 17.6.0 server does. The first screen is smaller: 17.6.0's spec root no longer carries the migration chain, so the eager closure is 250,096 gzipped bytes lighter (measured against a `main` build), and the bundle budget comes down by that amount.
10 changes: 6 additions & 4 deletions apps/console/src/__tests__/i18nLabelInputsManifest-10993.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
* (`ObjectMetric.i18nLabel-10993.test.tsx` in `plugin-dashboard` pins the
* render);
* - `object-grid`: `label` (`ObjectGrid.labelI18nLabel-10993.test.tsx` in
* `plugin-grid`). `view:grid` registers the same inputs, so its declaration
* carries the same two arms, but it is not in the public manifest, so it has
* no row here: this door does not reach it;
* `plugin-grid`), and `description` since objectui#11227 published it at
* `@objectstack/spec` 17.6.0 (`ObjectGrid.declaredKeys-11068.test.tsx`).
* `view:grid` registers the same inputs, so its declaration carries the same
* two arms, but it is not in the public manifest, so it has no row here: this
* door does not reach it;
* - `record:related_list`: `title`
* (`record-related-list.titleI18nLabel-10993.test.tsx` in `plugin-detail`).
*
Expand Down Expand Up @@ -45,7 +47,7 @@ const manifest = manifestFromConfigs(
/** Each block, a minimal node the gate reads as clean, and its `I18nLabel` inputs. */
const BLOCKS: ReadonlyArray<{ block: string; base: Record<string, unknown>; keys: readonly string[] }> = [
{ block: 'object-metric', base: { objectName: 'deal' }, keys: ['label', 'description', 'title'] },
{ block: 'object-grid', base: { objectName: 'account' }, keys: ['label'] },
{ block: 'object-grid', base: { objectName: 'account' }, keys: ['label', 'description'] },
{
block: 'record:related_list',
base: { objectName: 'task', relationshipField: 'account_id', columns: ['name'] },
Expand Down
Loading
Loading