Skip to content

Commit 31bb63b

Browse files
committed
Merge origin/main (c30c8dd) into claude/issue-9256-e3-residual
One conflict, in packages/types/src/__tests__/zod-mirror-parity.test.ts: both sides rewrote the two KnownDrift header figures. Resolved by RECOUNTING the merged KnownDrift table with the test's own AST reader, not by picking a side: base 0c50f18 49 entries / 89 keys objectui#10874 (c30c8dd) drops ai.zod.ts#AIFormAssistSchema -1 entry / -2 keys objectui#9256 (this branch) adds form.zod.ts#InputShorthandSchema +1 entry / +1 key merged 49 entries / 88 keys Both header sites (the population bullet and the KNOWN_DRIFT ratchet restatement) now read 49 / 88, and the bullet keeps both histories in landing order. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DuWo5bdP9SdVebamn99GGk
2 parents 14fd13c + c30c8dd commit 31bb63b

85 files changed

Lines changed: 4431 additions & 614 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: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
'@object-ui/plugin-view': patch
3+
---
4+
5+
`ObjectView`'s host delegation reads the rest of a named view's protocol members off the named view (objectui#10758).
6+
7+
A host that composes `ObjectView` with both `listViews` and its own `renderListView` receives a `list-view` node for the active view. Twenty-three members the protocol declares on a named view (`ObjectListViewSchema`) never came off the named view on that node: the delegation took them from the host `views` entry or the object-view node only, so a named view authoring one of them was accepted and rendered with some other value. This is bucket ① of the objectui#7924 ruling.
8+
9+
Each of them is now read off the active named view first, then the host `views` entry, then the node where that rung already read it:
10+
11+
- list chrome: `description`, `compactToolbar`, `allowPrinting`, `showRecordCount`, `sharing`, `aria`, `emptyState`;
12+
- record actions: `addRecord`, `inlineEdit`, `rowActions`, `bulkActions`, `bulkActionDefs`, `exportOptions`;
13+
- grid presentation: `rowHeight`, `pagination`, `selection`, `resizable`, `hiddenFields`, `conditionalFormatting`;
14+
- search, filter and navigation: `searchableFields`, `filterableFields`, `userFilters`, `navigation`.
15+
16+
`description`, `exportOptions` and `bulkActionDefs` had no rung before and are read off the two views only, never off the node, so the objectui#5097 host-composition exemption keeps its 27 names. A named view's `rowHeight` is read as itself; the host `views` entry still goes through the density fold.
17+
18+
What moves for a host: where the active named view and the host `views` entry both carry one of these members, the named view's value now wins. A named view that carries none of them hands down exactly what it did before. The registered `object-view` renderer passes no `renderListView`, so an authored node is unaffected.

‎.changeset/10859-ai-node-zod-arms.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,13 @@
1313
- `@object-ui/types/zod` exports `AIFormAssistSchema`, `AIRecommendationsSchema`, `NLQuerySchema`, their sub-schemas `AIConfigSchema`, `AIFieldSuggestionSchema`, `AIRecommendationItemSchema` and `NLQueryResultSchema`, and the category union `AIComponentSchema`, which `AnyComponentSchema` now lists. The strict authoring face (`StrictAnyComponentSchema`) derives from `AnyComponentSchema` and accepts the same three types, closed to undeclared keys like every other arm.
1414
- Each arm restates its TypeScript declaration member for member. The objectui#8178 retired members (`formId`, `objectName`, `fields`, `autoFill`, `maxResults`) and both content channels (objectui#9256) are refused by name, as they already were on the TypeScript face.
1515
- ⚠️ The `on*` members are the one place the two faces differ. The TypeScript face still types `onApplySuggestion`, `onRejectSuggestion`, `onSelect`, `onDismiss` and `onSubmit` as `string`; the zod face refuses an authored value on each, by name, following objectui#6182 (the handler-expression string dialect is not an authoring form) and objectui#6124 (`onSelect` / `onDismiss` / `onSubmit` are runtime slots a React host fills; the other two have no reader). An authored string was never a working handler: `onSelect`, `onDismiss` and `onSubmit` are called only as function props a React host passes, and `onApplySuggestion` / `onRejectSuggestion` are read by nothing — delete the key from the document. The TypeScript face's `string` typing is objectui#10874's to correct.
16+
17+
⚠️ **Dated note, 2026-09-28 — the TypeScript face now types the `on*` members per key, and `config` / `context` are refused — objectui#10874.**
18+
Later in this same release the TypeScript face settles the five `on*` members by the objectui#6124
19+
rule, so the `string` typing described above is gone. `onSelect`, `onDismiss` and `onSubmit` are typed
20+
as the callables their components invoke: the objectui#6124 shape, a callable twin beside the named
21+
refusal this entry added. `onApplySuggestion` and `onRejectSuggestion` are `?: never`, so both faces
22+
refuse those two. The same change retires `config` (all three types) and `context` (`ai-form-assist`,
23+
`ai-recommendations`) on both faces, so `safeValidateSchema` — and `objectui validate` — refuses a
24+
document that carries one of them, by name, where the arms this entry added accepted it. The rest of
25+
this entry is kept as the reading of this change; the objectui#10874 entry states what ships.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
---
4+
5+
fix(app-shell): the admin previews and the CEL lint advisories read the designer locale (objectui#10862, slice 2)
6+
7+
Under zh-CN these designer surfaces rendered their own words in English beside
8+
Chinese text:
9+
10+
- the app, book, datasource, email template, permission set, position and
11+
translation previews: their empty prompts, section and column headings,
12+
pills, badges, legends, notes, toolbar links and their tooltips, the
13+
permission set's sanity-check warnings, the email template's envelope
14+
labels and variable placeholders, and the translation bundle's category
15+
names;
16+
- the two advisories the CEL lint writes itself beneath the CEL editors: the
17+
wrong-layer `data.*` root on a record-scope expression, and an RLS `USING`
18+
read filter that cannot be pushed down to the query.
19+
20+
Each new en row is the English the literal carried, so en renders unchanged.
21+
Author data (labels, names, doc names, config keys and values, variable
22+
names, a translation bundle's own locale), identifiers (navigation kinds, tab
23+
visibility values, access-scope tokens, the C / R / U / D column letters,
24+
"SSL"), the expression engine's own messages and `@objectstack/lint`'s
25+
field-rule message show as written in every locale.
26+
27+
This is slice 2 of objectui#10862 (the admin previews). The object / data
28+
previews and the preview error-boundary hints remain for slice 3.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
---
4+
5+
Raise `@object-ui/app-shell`'s declared `@objectstack/spec` floor from
6+
`^17.3.0` to `^17.4.0` (objectui#10864) — the old range admitted a spec that
7+
lacks four symbols this package's own shipped artifact imports.
8+
9+
`packages/app-shell/src/views/metadata-admin/previews/screen-spec.ts` imports
10+
`predicateSlotRefusal` from `@objectstack/spec/automation`;
11+
`packages/app-shell/src/views/metadata-admin/previews/simulator/flow-sim-validate.ts`
12+
imports `structuralConditionRefusal` from the same subpath plus
13+
`EVALUATED_EXPRESSION_SOURCE_REQUIRED` and `EvaluatedExpressionSchema` from
14+
`@objectstack/spec/shared`. `@objectstack/spec` was declared as `^17.3.0`, so
15+
any resolution landing on 17.3.0 (which the range allows) gets a module that
16+
names exports its own declared spec dependency does not have.
17+
18+
Measured against the published `@objectstack/spec` tarballs (`npm pack`):
19+
`predicateSlotRefusal`, `structuralConditionRefusal`,
20+
`EVALUATED_EXPRESSION_SOURCE_REQUIRED` and `EvaluatedExpressionSchema` are
21+
absent from every file under 17.3.0's `dist/`, and present under 17.4.0's
22+
`dist/automation` and `dist/shared`. `@object-ui/types` already declares
23+
`^17.4.0`.
24+
25+
In this repository nothing moves at runtime: the lockfile already resolved
26+
`@objectstack/spec` 17.4.0 for this specifier, so only the declared
27+
`specifier:` range was stale. For a consumer, the range now refuses
28+
`@objectstack/spec` 17.3.0, which the old range admitted and under which the
29+
metadata-admin preview modules named four exports the installed spec does not
30+
have.
31+
32+
`pnpm check:spec-floors` was red before this change (4 `floor-too-low`
33+
findings, all in `@object-ui/app-shell`) and green after, over a full
34+
workspace build.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
'@object-ui/plugin-calendar': patch
3+
'@object-ui/plugin-gantt': patch
4+
'@object-ui/types': patch
5+
---
6+
7+
fix(plugin-calendar,plugin-gantt): a stored date-only day shows on that day in every viewer zone, and a `date` field is written back as a calendar day (objectui#10866, slice 1)
8+
9+
The calendar and the gantt read a record's `YYYY-MM-DD` value with the engine's own `Date` parse, which reads it as UTC midnight. West of UTC a task due on the 5th therefore showed on the 4th, in both views. Moving it then wrote `toISOString()` into the field: a UTC instant stored in a `Field.date`.
10+
11+
- **Reads.** Every date-only read in the two plugins now goes through `toDisplayDate` from `@object-ui/core`, which reads the value at local midnight of the day it names. In the calendar these are the object calendar's event start and end, and the `calendar-view` node's events and its authored `currentDate`. In the gantt they are the task start, end and baselines, a marker authored as a day, and the day typed into the inline editor. A value with a time keeps its instant.
12+
- **Writes.** A calendar drop, a calendar quick-create and a gantt drag now write a field declared `date` as the local calendar day, `yyyy-MM-dd`. A `datetime` field keeps its instant. When no object schema is available to say which type a field is, the stored value's own shape decides, which is the same split the read makes; a calendar quick-create has no stored value, so there it still writes the instant.
13+
- **Gantt `timeZone`.** A chart with a business `timeZone` re-bases every instant into that zone. A date-only day is not re-based: its bar and its marker stand on that day of the chart's calendar for every viewer, and a drop writes the day of the chart's calendar that the bar was dropped on.
14+
- **Gantt working calendar.** `skipWeekends` / `holidays` now count the chart's own calendar days (local midnight, the same keys the day columns already folded by) rather than UTC days. The UTC floor put a rescheduled successor on the previous day in every zone except UTC once date-only values read as local days. `@object-ui/types` updates the `holidays` description to match.
15+
16+
The timeline, charts, formula date functions and i18n helpers are later slices of objectui#10866.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
'@object-ui/core': patch
3+
'@object-ui/types': patch
4+
---
5+
6+
fix(core): `normalizeListViewSchema`'s density fold tests an own key, not `in` (objectui#10868)
7+
8+
The fold turned a legacy `densityMode` into `rowHeight` when the value was `in`
9+
`DENSITY_MODE_TO_ROW_HEIGHT`, and `in` walks the prototype chain. So
10+
`densityMode: 'toString'` came back with `rowHeight` set to
11+
`Object.prototype.toString`, a function, and the key was dropped. The fold now
12+
uses the same own-key test that `rowHeightToDensityMode` uses in the read
13+
direction. An inherited key such as `'toString'` or `'constructor'` is now
14+
treated like any other unrecognized density, such as `'cozy'`: nothing is
15+
folded, `rowHeight` stays unset, and `densityMode` is kept. The three densities
16+
`compact`, `comfortable` and `spacious` fold exactly as before.
17+
18+
Such a value reaches the fold only on a render path that does not validate.
19+
`@object-ui/types`' zod schemas already refuse it: the `list-view` node declares
20+
`densityMode` as a three-value enum, and a named view refuses `densityMode` by
21+
name.
22+
23+
docs(types): `NamedListView`'s docblock no longer says the type is used in
24+
`ObjectViewSchema.listViews`. Since objectui#7928 that member has been the
25+
protocol's `ObjectListViewSchema`, by reference. The docblock now says what the
26+
type is: exported, and the type of no member of the contract. The type itself is
27+
unchanged.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
'@object-ui/types': minor
3+
---
4+
5+
**BREAKING (authoring)** — the three `@object-ui/plugin-ai` node declarations stop offering members that no runtime honours, and type the handler slots their components call (objectui#10874, ADR-0049, the objectui#6124 per-key rule).
6+
7+
**Clause-②: yes** — authorable members of published `@object-ui/types` declarations narrow. Three members become callable: `string` to a function type (`onSelect`, `onDismiss`, `onSubmit`). `config` and `context` become `never` on both faces, five members across the three declarations. `onApplySuggestion` and `onRejectSuggestion` become `never` on the TypeScript face, and the zod face already refused them. Scored `minor`, not `major`: this repository scores its own breaking changes `minor` and spells the breaking semantics out in the body (`check:changeset-no-major`).
8+
9+
**What changes, on which face.**
10+
11+
| Member | Was on | TypeScript face | zod face |
12+
|---|---|---|---|
13+
| `onSelect`, `onDismiss` | `AIRecommendationsSchema` | CALLABLE: `(item: AIRecommendationItem) => void` (was `string`) | refused by name, unchanged |
14+
| `onSubmit` | `NLQuerySchema` | CALLABLE: `(query: string) => void` (was `string`) | refused by name, unchanged |
15+
| `onApplySuggestion`, `onRejectSuggestion` | `AIFormAssistSchema` | `?: never` (was `string`) | refused by name, unchanged |
16+
| `config` | `AIFormAssistSchema`, `AIRecommendationsSchema`, `NLQuerySchema` | `?: never` (was `AIConfig`) | refused by name (was accepted) |
17+
| `context` | `AIFormAssistSchema`, `AIRecommendationsSchema` | `?: never` (was a string-keyed record) | refused by name (was accepted) |
18+
19+
**Why.**
20+
21+
- `onSelect`, `onDismiss` and `onSubmit` are RUNTIME SLOTS. Each node type is registered to its raw component, `SchemaRenderer` spreads the node's own keys onto the component's props, and `AIRecommendations` and `NLQueryInput` call these keys as functions. So a function on the node was always called, and a string there was called as a function and threw at click. The TypeScript face now declares the callable the component invokes, as objectui#6124 rules for a key a runtime consumer calls. The zod face keeps refusing an authored value, because JSON has no function value.
22+
- `onApplySuggestion` and `onRejectSuggestion` were read by nothing: `AIFormAssist` takes `onApply` and `onRefresh`, so a string there did nothing.
23+
- `config` and `context` were read by nothing in `@object-ui/plugin-ai`. The three components are presentation only and call no model, so a `provider`, `model`, `systemPrompt` or context written on the node did nothing and changed nothing on screen.
24+
- Before this change the zod face refused all five `on*` strings (objectui#10859) while the TypeScript face offered them, so `onSelect: 'x'` passed `tsc` and was then refused by the validator. Now `tsc` refuses the string too.
25+
26+
**Migration.**
27+
28+
- `onSelect`, `onDismiss`, `onSubmit`: pass a function, never a string — either as the component prop of the same name, or on a node you build in TypeScript. `AIRecommendations` and `NLQueryInput` take the same signatures as props, unchanged.
29+
- `onApplySuggestion`: delete it, and use the `onApply` prop of the `AIFormAssist` component. `onRejectSuggestion`: delete it; the component has no reject callback.
30+
- `config`: delete it. Configure the model in your host's own AI service (ObjectUI has no AI-provider API; these components call no model), and hand its output to the node as `suggestions`, `recommendations` or `result`.
31+
- `context`: delete it, and pass the context to your host's own AI service when you ask it for suggestions or recommendations.
32+
33+
```tsx
34+
// before: compiled; `config` did nothing, and the string was called as a function and threw at click
35+
const picks: AIRecommendationsSchema = {
36+
type: 'ai-recommendations',
37+
recommendations,
38+
config: { model: 'gpt-4' },
39+
onSelect: 'openItem',
40+
};
41+
42+
// after
43+
const picks: AIRecommendationsSchema = {
44+
type: 'ai-recommendations',
45+
recommendations,
46+
onSelect: (item) => openItem(item),
47+
};
48+
```
49+
50+
**What does not change.** The renderers are untouched, so a stored document renders exactly as it did: `config` and `context` were ignored and still are, and a function reaching `onSelect`, `onDismiss` or `onSubmit` is still called. What moves is the verdict. `tsc` refuses the four retired keys, on all seven member slots that carried them, and a string on the three slots. The validator refuses `config` and `context` by name, where the arms objectui#10859 added in this same release accepted them. The exported `AIConfig` type and `AIConfigSchema` stay; no node member takes them any more.
51+
52+
⚠️ **The census behind "read by nothing" is the in-repo half.** Every package, app, example, doc and skill in this repository was searched: none reads `config` or `context` off an AI node, and none authors a changed member. Customer applications and published documents outside it were not enumerated. A TypeScript consumer that authored one of these keys gets a compile error naming it.

‎.changeset/5920-flow-runner-translation-overlay.md‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,15 @@ Submitting… / completion chrome (the console's message catalogue), and the flo
2626

2727
`@object-ui/app-shell` now declares `@objectstack/spec` `^17.3.0`, the first release that
2828
exports the resolver family; `^17.0.0` admitted three releases that do not.
29+
30+
⚠️ **Dated note, 2026-09-28 — the declared floor has since moved again —
31+
objectui#10864.** At this change `@object-ui/app-shell` declared `^17.3.0`, and
32+
the paragraph above is kept as the reading of that change: `17.3.0` was in fact
33+
the first release exporting the resolver family this fix uses. Later in this
34+
same release the floor was raised again, to `^17.4.0`, because two other
35+
shipped app-shell sources (`screen-spec.ts`, `flow-sim-validate.ts`) import
36+
four symbols (`predicateSlotRefusal`, `structuralConditionRefusal`,
37+
`EVALUATED_EXPRESSION_SOURCE_REQUIRED`, `EvaluatedExpressionSchema`) that
38+
`17.3.0` does not export — a defect this changeset's own range did not
39+
introduce and did not need to guard against. `@object-ui/app-shell` now
40+
declares `^17.4.0`.

‎.changeset/6771-retire-body-child-list-dialect.md‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,18 @@ Ruled 2026-09-01: one concept, one spelling, and the spelling is `children`.
3030
reads named below** — `div`, `card`, `button`, `aspect-ratio`, the sectioning tags,
3131
the safe-HTML tag factory behind ~36 tags, `page`'s flat content list, and
3232
`@object-ui/core`'s recursive `validateSchema`.
33-
- **Item-level `body` is a DIFFERENT key and is untouched.** `list` draws each entry
34-
as `item.content || renderChildren(item.body)` and `tabs` as
33+
- **Item-level `body` is a DIFFERENT key and is untouched.** At this change, `list`
34+
draws each entry as `item.content || renderChildren(item.body)` and `tabs` as
3535
`item.content || item.body`, both filed under the ITEM type rather than the node,
3636
and `tabs` still ships `body` inside its own `defaultProps`. ⛔ Neither is this
3737
spelling and neither is refused here: the node-level retirement does not reach a
3838
member of a declared `items` array. Retiring the item-level dialect is
3939
objectui#9590's card, and the two named above are recorded on it.
40+
⚠️ **Dated note, 2026-09-25 — neither half of this bullet holds any longer — objectui#9590.**
41+
objectui#9941 respelled the `tabs` `defaultProps` items to `content`, and
42+
objectui#9590 retired both item-level reads: a `list` item and a `tabs` item draw
43+
`content` and nothing else, and both item faces now refuse `body` by name,
44+
pointing at `content`. The rest of this bullet is kept as the reading of this change.
4045
- **What still reads `body` at NODE level, and why.** Four renderer reads, all `page:*`: `page:card`
4146
(renderer and Studio canvas) and the three thin `page:section` / `page:footer` /
4247
`page:sidebar` containers. ⛔ Authoring the key is refused on them as it is
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
---
3+
4+
Docs and test-ledger change; no package is released. The seven HTML sectioning tags (`article`, `aside`, `footer`, `header`, `main`, `nav`, `section`) in the console's declared-layout-container ledger (`UNCURATED_LAYOUT_CONTAINERS`) no longer read "NOT YET RULED": they record the ruling on objectui#8775 (letter B). They are html-tier intrinsics that render on `kind:'html'` pages, the curated `page:section` / `page:header` / `page:footer` / `page:sidebar` blocks already carry the landmarks a JSON page needs, and curating one of the seven would add a near-synonym pair. The page-builder skill guide no longer teaches `section` as a JSON layout primitive and points to those four blocks instead, and the semantic-elements docs page no longer teaches the `body` child-list key that objectui#6771 retired. `PUBLIC_BLOCKS`, `sdui.manifest.json`, the generated intrinsics and every published type are unchanged, and every pin over the ledger keeps its assertion.

0 commit comments

Comments
 (0)