diff --git a/.changeset/console-f0268ad78485.md b/.changeset/console-f0268ad78485.md new file mode 100644 index 00000000000..b4d194739ef --- /dev/null +++ b/.changeset/console-f0268ad78485.md @@ -0,0 +1,154 @@ +--- +"@objectstack/console": minor +--- + +Console (objectui) refreshed to `f0268ad78485`. Frontend changes in this range: + +Derived from the changesets objectui declared over the range — 173 releasing of 175 changesets added across 170 non-merge commits; omitted: 2 release-nothing changesets, 4 commits carrying no changeset (they ship no package code). + +- **minor** — The chat build panel reads cloud's post-apply verification loop, and an unknown build phase no longer reads as "Building" (objectui#11988, the receiver objectstack-ai/cloud#2172's… (objectui `6d5eb3430`) +- **minor** — feat(types)!: a list view's legacy `options` bag is the `@objectstack/spec` list overlay's bag by reference, `ListViewTimelineConfig` is the list view's own `timeline` block, and… (objectui `5d77c099b`) +- **minor** — The built-in metadata designers leave the console's first load: `@object-ui/app-shell` registers them from a chunk it loads on its own, once the package entry has run (objectui#11… (objectui `4babf4035`) +- **minor** — The Studio landing (`/studio`) gets the console's own header (objectui#11863). Its old header held one control, the product wordmark linking back to Home. It now mounts `AppHeader… (objectui `7ebff3991`) +- **minor** — feat(types)!: the list view's `kanban`, `calendar`, `gallery` and `timeline` blocks are the `@objectstack/spec` 17.7.0 `ListViewSchema` slots by reference, and their `.passthrough… (objectui `cf62edf68`) +- **minor** — `element:repeater` reads the node-level `dataSource` binding first (objectui#11880, the repeater half of the objectui step of objectstack#11509, ruled A-narrow). (objectui `aaba8655a`) +- **minor** — The Studio landing (`/studio`) lists the packages the author was last in, above its package cards (objectui#11863). A visit to a package's pillar builder (`/studio/PKG/TAB`) is re… (objectui `054fd8441`) +- **minor** — The Import Wizard's preview checks a `time` column, and the user import's email column, the way the server's import judges them, so the import button no longer counts rows the ser… (objectui `fbad07885`) +- **minor** — feat(types)!: `ObjectGridSchema.defaultFilters` and the flat `ObjectGanttSchema` / `ObjectMapSchema` `filter` follow their `@objectstack/spec` rows (objectui#6152, round 10) (objectui `b13ea3c67`) +- **minor** — A console object list's toolbar grouping is now in the URL, beside its Filter panel conditions, search term and sort, so a grouped list can be shared as a link or bookmarked (obje… (objectui `75bacf93b`) +- **minor** — **BREAKING** — A form field declares `scale` and `currencyConfig` on both faces, by reference to `@objectstack/spec`'s `FieldSchema`, so the strict authoring face accepts the decimal places and… (objectui `18d7b489c`) +- **minor** — The list's Sort picker lists a field it keeps only for the current sort as removable, never as a new choice (objectui#11943). (objectui `4f4fc03f7`) +- **minor** — feat(types)!: the `object-calendar` element's `calendar` container is the `@objectstack/spec` 17.7.0 slot by reference, and its `.passthrough()` is gone (objectui#6152, round 9) (objectui `1473757bf`) +- **minor** — feat(types)!: `object-grid` `operations` and the `object-grid` / `object-kanban` / `object-calendar` `filter` follow the `@objectstack/spec` 17.7.0 rows (objectui#6152, round 8) (objectui `d7e9e9ab6`) +- **minor** — The metadata designer registries are observable, so a designer registered after a surface rendered now appears in it (objectui#11939, step 1 of objectui#6795). (objectui `a835c3149`) +- **minor** — **BREAKING** — The `sidebar` node declares `side` on both faces, so the strict authoring face accepts the edge the sidebar is drawn against (objectui#11070). (objectui `172acc313`) +- **minor** — New SDUI widget `cloud:workspace-timezone-notice`: one line on the Cloud welcome page naming the timezone a workspace was seeded with at creation (objectui#11930, the objectui hal… (objectui `45d585363`) +- **minor** — A new workspace now takes its creator's browser timezone when it is created, so its first administrator is no longer asked for a zone the browser already knows (objectui#11908). (objectui `dfa15c860`) +- **minor** — **BREAKING** — The metric sub-caption is retired on the reader side (objectui#11389, ruling C, the objectui half after `@objectstack/spec` 17.7.0). **BREAKING** for any dashboard that drew a cap… (objectui `d92b2a15d`) +- **minor** — `action:button` delivers `undoable` where a record is in scope, and publishes it (objectui#11168, ruling B on objectui#11754). (objectui `f0496bdf1`) +- **minor** — feat(types)!: retire `object-grid`'s `resizableColumns` on both faces, and stop `ObjectGrid` reading it (objectui#6152, round 7) (objectui `d73d98770`) +- **minor** — A record action greyed out by its declared `disabled` predicate now says why (objectui#11811). It shows the reason "Not available for this record", and the same text is its access… (objectui `455c64665`) +- **minor** — The list filter builder starts on the view's first column, hides hidden fields, and offers one empty check where "empty" and "null" mean the same records (objectui#11810). (objectui `1e1f09e99`) +- **minor** — Dates and times render in the time zone the server answers for the signed-in workspace (objectui#11693). (objectui `d50f7241b`) +- **minor** — The console asks an administrator once to set the workspace timezone while it is still the platform default, pre-filled with the browser's zone (objectui#11758, the gate the objec… (objectui `3bf8894ef`) +- **minor** — Installed Apps now reads a package the runtime refused to load at startup as "Not loaded", says why, and keeps its Uninstall (objectui#11645). (objectui `7b1770590`) +- **minor** — `DashboardWidgetSchema` chains `@objectstack/spec`'s `checkDashboardWidgetChartMeasureArity` after the metric-family check (objectui#11334, objectui#11417), so `safeValidateSchema… (objectui `c0862c1cc`) +- **minor** — `element:text` drops the two pre-convergence `variant` spellings `heading` and `subheading`, which `@objectstack/spec` 17.7.0 retires (objectstack#21015, objectui#11717). The regi… (objectui `c0862c1cc`) +- **minor** — The `page` node and the spec page-kind nodes (`record` / `home` / `utility`) chain `@objectstack/spec`'s `checkPageRequiresKind` (objectui#11717), as they already chain `checkPage… (objectui `c0862c1cc`) +- **minor** — Screen readers can name and reach the controls of the view tab bar, the settings form, the sidebar menus, the table's selection column and the percent cell (objectui#11690). axe-c… (objectui `9fc68aadb`) +- **minor** — A record delete confirmation now names what it deletes and confirms with a destructive "Delete" button (objectui#11695). (objectui `17acfbb9b`) +- **minor** — The organization Settings page no longer offers a slug edit the framework will refuse (objectui#11720). From framework 17.7.0, better-auth's organization update refuses a new slug… (objectui `ded4494b6`) +- **minor** — Object list pages are titled with the object's plural label (objectui#11696). (objectui `6be0f7a46`) +- **minor** — Read-only boolean values, the boolean list face and the Home greeting's punctuation follow the language (objectui#11689). (objectui `22b503c30`) +- **minor** — An empty list's copy no longer contradicts the page it sits on (objectui#11687). (objectui `834c5594b`) +- **patch** — Studio's "New automation" dialog opens on common starting points in plain words, with the trigger form under "Advanced" (objectui#11861: the automations entry, the last of the thr… (objectui `f0268ad78`) +- **patch** — A permission set's advanced facets pick with the shared `Select`, the control the rest of Studio picks with (objectui#11865, the facets' part of that card): a Row-Level Security p… (objectui `1ad0c0824`) +- **patch** — A quick-filter selection restored from the URL now applies when the list's dropdown chips come from the object definition (objectui#12001). (objectui `e616327ab`) +- **patch** — The list toolbar's hide-fields popover, Group editor and Row color select, and its user-filter chips, no longer offer a field the user may not read (objectui#11984). They now ask… (objectui `164f02cf6`) +- **patch** — Studio on a smaller or resized window (objectui#11795). Studio stays a desktop tool; three things change below desktop width: (objectui `70f1b2755`) +- **patch** — An `object-view` grid now exports the filter it shows, and returns to page 1 when that filter changes (objectui#11880, item 5). (objectui `5bc55c0c5`) +- **patch** — The designer forms pick with the shared `Select`, the control the rest of the console picks with (objectui#11865, the designer forms' part of that card): `FieldDesigner`'s type fi… (objectui `e8f9977f5`) +- **patch** — The console's Public Forms, Flow Runs and Profile pages pick with the shared `Select`, the control the rest of the console picks with (objectui#11865, the console pages' part of t… (objectui `28557855f`) +- **patch** — The dashboard designer's widget property panel picks a widget's Type and Color Variant with the shared `Select`, and the designers' property panel (`PropertyEditor`) draws a `sele… (objectui `5ad818310`) +- **patch** — The list toolbar's field-list read check is rolled back to restore the console's first-load budget, and it re-lands with objectui#11984 after objectui#11939's reclaim. (objectui `902fbe190`) +- **patch** — Studio's Interfaces create dialog picks a new page's source kind, and a new report's dataset and measure, with the shared `Select`, the control the rest of Studio picks with (obje… (objectui `fb361efe0`) +- **patch** — Studio's package record sharing overview picks each object's internal and external sharing model with the shared `Select`. That is the control Studio's object Settings tab already… (objectui `b1f0dcc00`) +- **patch** — A console list's view-tab switch starts the next view with the quick-filter selections its own URL carries (objectui#11992). The object page read the `uf_FIELD` selections once pe… (objectui `9c3798249`) +- **patch** — Studio's object Settings tab picks the sharing model, the external sharing model, the name field, the lifecycle field and the next highlight field with the shared `Select`, the co… (objectui `d21bd083e`) +- **patch** — A rolled-back Studio publish shows its "Nothing was published" banner again (objectui#11985). (objectui `1b8388bef`) +- **patch** — Studio's *Explain access* panel picks the object and the operation with the shared `Select`, the control Studio's validation rule editor already picks with (objectui#11865, the *E… (objectui `0bbb67b9a`) +- **patch** — **BREAKING** — `element:record_picker` and `element:number` bind data through the node-level `dataSource` only (objectui#11880, part of the objectui half of objectstack#11509, ruled A-narrow). (objectui `74add0c12`) +- **patch** — The console header no longer shows a "Search ⌘K" trigger where it would open nothing (objectui#11912). (objectui `a920d8c29`) +- **patch** — A refused package publish names each refused item with the server's reason, on the package sheet and on Home's *Publish all* and the draft-preview bar (objectui#11922). (objectui `c6e1b8c6b`) +- **patch** — Studio's action "New" menu opens on common actions in plain words, with the blank action under "Advanced" (part of objectui#11861: the actions entry). (objectui `d8be368c7`) +- **patch** — Studio's flow-node inspector, in its fallback form, writes only config keys the node's contract declares (objectui#11968). (objectui `0ab2b9885`) +- **patch** — Studio's validation rule editor picks a rule's type, field, built-in format and severity with the shared `Select`, the control the condition builder beside them already uses (obje… (objectui `f19b91540`) +- **patch** — Studio keeps a dashboard widget as an unsaved edit while the author changes its measure, instead of showing a red error the moment the last measure is removed (objectui#11951). (objectui `989b19082`) +- **patch** — Studio's field inspector gives `rating`, `slider` and `progress` fields a number *Default value* control, so the default saves as a number (objectui#11966). (objectui `31741d5f4`) +- **patch** — Studio Interfaces: a leaf save that goes through now clears the red "Changes not saved" strip an earlier refused save showed (objectui#11950). (objectui `402adc8aa`) +- **patch** — Studio's field type catalog now holds every field type the spec declares: it gains `user`, `secret` and `record` (objectui#11909). (objectui `0c9fb8ea3`) +- **patch** — Studio's Interfaces pillar can now create a page in a writable package, and opens it on its source beside a live preview (objectui#11823, step 3). (objectui `7546570a4`) +- **patch** — Studio's validation-rule "New" menu opens on common rules in plain words, with the rule types under "Advanced" (part of objectui#11861: the validation-rule entry). (objectui `7546570a4`) +- **patch** — Studio keeps a new dashboard widget as an unsaved edit until a dataset and a measure are picked, instead of showing a red error right after *Add widget* (objectui#11910). (objectui `a523a3e2e`) +- **patch** — Studio's action editor writes a script body that names its language, so the first keystroke is no longer refused (objectui#11921). (objectui `7129cd575`) +- **patch** — Studio's field inspector offers no *Default value* control on a `record`, `location` or `address` field, as it offers none on a `composite` or `repeater` field (objectui#11947). (objectui `bcd3f0803`) +- **patch** — The record picker (`RecordPickerDialog`) is laid out from the design system's own primitives (objectui#11903). It is the dialog behind a multi-select lookup's "Browse all records"… (objectui `5ab2f19b3`) +- **patch** — A create form preselects the option a field's option list marks `default: true` (objectui#11914). (objectui `ccddd1186`) +- **patch** — The list's Sort picker no longer offers a field the user may not read (objectui#11943). Choosing such a field sent a sort the server refuses, and the list went blank on "no access… (objectui `e44f9bc43`) +- **patch** — A read-only package's form designer no longer tells a screen reader how to drag a field card (objectui#11924). (objectui `94f48a28b`) +- **patch** — Studio's condition builder no longer writes `!field` or a bare `field` for a field that is not a boolean, when it knows the field's type (objectui#11894). (objectui `247f50349`) +- **patch** — Studio's page previews draw the page's own kind, as the running app does (objectui#11933): the live preview beside an `html` or `react` page's source, and the Interfaces page canv… (objectui `ccc2824cf`) +- **patch** — The list Group panel picks its field with the shared `Select`, the control the Filter and Sort panels beside it pick a field with (objectui#11865, the Group panel's part of that c… (objectui `7241a81e0`) +- **patch** — Studio's validation-rule "Runs on" boxes follow the spec's events (objectui#11923). (objectui `70e3d7721`) +- **patch** — Studio's form designer can be arranged from the keyboard on a canvas of any width (objectui#11898). With a field card picked up, each arrow key now moves it one place in the form'… (objectui `60d11cd61`) +- **patch** — Studio's field pickers offer the fields of an object that is still an unpublished draft (objectui#11895). (objectui `2fec2e007`) +- **patch** — The list's Filter panel offers only the fields the user may read (objectui#11925). Its field list now asks the same field-level read check the list's columns already use, `checkFi… (objectui `077d19825`) +- **patch** — The console is back under its first-load budget. Two recent Studio changes are rolled back to get there: the common-rule starting points in an object's Validations "New" menu (obj… (objectui `3c888c6e6`) +- **patch** — The console's record page now says what its record read actually answered: no access, not found, or could not load (objectui#11902). It used to answer every failed read with "Reco… (objectui `f1781be3a`) +- **patch** — Studio's landing page now points a read-only package at the routes that exist for customizing it (objectui#11808). (objectui `e81c84693`) +- **patch** — Four more editors stop asking for the layers of an item that was never published, so the browser console no longer logs a 404 for it (objectui#11799). The framework answers `GET /… (objectui `a025f4d12`) +- **patch** — Studio's flow designer connects two nodes the flow already has (objectui#11905). (objectui `4ebc25001`) +- **patch** — Studio's automation canvas header names the open flow by its label, not by the metadata type word (objectui#11665, the residual of objectui#11659 ruling 6). (objectui `d52d90855`) +- **patch** — Studio's form designer announces a field card's role in the author's language (objectui#11872). (objectui `fc82a31a6`) +- **patch** — Studio, and the app designer's navigation canvas, show a label first and the machine name or id as secondary text, in the places that showed only the machine name or id (objectui#… (objectui `0feabe8f6`) +- **patch** — Studio's field inspector picks a field type from a searchable list grouped by category, where it was one flat select of every type (objectui#11793). (objectui `72f5c608e`) +- **patch** — Studio's new validation rules, hooks and actions start from safe defaults (objectui#11820). (objectui `b4693b7b7`) +- **patch** — A console object list's Filter panel conditions, search term and sort are now in the URL, so a filtered, sorted list can be shared as a link or bookmarked (objectui#11860). (objectui `340bfabf8`) +- **patch** — Studio's publish review and publish confirmation say what changes (objectui#11807). (objectui `b9d9397b3`) +- **patch** — The Import Wizard preview marks a cell exactly where the server's import refuses it on dates, on rating, slider, progress and toggle columns, and on email columns, so the import b… (objectui `9fc6ad784`) +- **patch** — Studio's Interfaces pillar can now create a dashboard or a report in a writable package (objectui#11823, step 2). (objectui `a49c4bd27`) +- **patch** — Metadata-form code fields stay editable when Monaco cannot load (objectui#11858). (objectui `368359179`) +- **patch** — The Approvals Inbox no longer links to a record when the approver has no read of its object at all (objectui#11878, ruling C on objectstack-ai/objectstack#7497). Such an approver… (objectui `230e4b230`) +- **patch** — The login and register pages say when the server cannot be reached, and offer sign-up only once the server has said whether it accepts sign-ups (objectui#11806). This applies to t… (objectui `09821b1db`) +- **patch** — The console's first page load no longer downloads the documentation reader's markdown extras (objectui#11854). (objectui `7afcea06e`) +- **patch** — Both *Duplicate* forms judge a new package id by the spec's id rule, the one the server refuses by (objectui#11855). (objectui `475bda1a2`) +- **patch** — Grid inline edit marks a row modified only when a value really changed, draws one "Actions" column, and the "Edit inline" toggle reports its state (objectui#11816). (objectui `9844bbf92`) +- **patch** — Studio's form designer can be arranged from the keyboard (objectui#11871). Picking a field card up with Space or Enter, moving it with the arrow keys and dropping it with Space or… (objectui `a476dee29`) +- **patch** — The profile page states the access the console resolves, not the auth library's raw `user.role` (objectui#11866). (objectui `0855fc671`) +- **patch** — Studio stops asking questions whose expected answer is an error, so the browser console no longer fills with red lines that hide real failures (objectui#11799). (objectui `5dff0272d`) +- …and 73 more releasing changesets in this range (list capped at 100; see the objectui range below). + +⚠️ 4 of these carry a breaking change: 4 by the author's own breaking annotation in the changeset body — objectui declares no `major` inside a launch window (`scripts/check-changeset-no-major.mjs`). Each is marked **BREAKING** in the list above — read them before compiling the release record. + +**In this console build, declared nowhere** — objectui merged 4 commits in this range with no `.changeset/*.md`. The code is inside the pin above and ships here, but nothing upstream declared them, so they appear in no objectui CHANGELOG and in no entry above. Listed by subject rather than counted, because a count cannot tell a dependency bump from a form-behaviour change (objectstack#6174); the upstream gate that would prevent this is objectui#3387. + +- _(no changeset)_ fix(plugin-list): the hide-fields, Group and Row color lists and the user-filter chips ask the field read (objectui#11984) (#11999) (objectui `aa67386a5`) +- _(no changeset)_ chore(scripts): raise the console eager-closure ceiling by a fixed 5,120-byte allowance for Studio repairs while the designers are eager (objectui#11942) (#11949) (objectui `1c51e973b`) +- _(no changeset)_ feat(app-shell): Studio Interfaces pillar creates a page and opens it on source plus live preview (objectui#11823 step 3) (#11932) (objectui `f3a0488c9`) +- _(no changeset)_ feat(app-shell): Studio's validation New menu opens on common rules, with the rule types under Advanced (part of objectui#11861) (#11931) (objectui `19a734866`) + + + +objectui range: `a58626c88dc8...f0268ad78485` diff --git a/.changeset/objectui-pin-citations-f0268ad78485.md b/.changeset/objectui-pin-citations-f0268ad78485.md new file mode 100644 index 00000000000..826285c56a8 --- /dev/null +++ b/.changeset/objectui-pin-citations-f0268ad78485.md @@ -0,0 +1,19 @@ +--- +'@objectstack/spec': patch +--- + +The spec's objectui citations, and the shipped description text that names the `.objectui-sha` pin (the `FormField.span` describe and six migration-entry descriptions), are re-measured against the new console pin, objectui `f0268ad78485`. + +Clause-②: no + +Every anchor was mapped through the objectui diff `a58626c88dc8..f0268ad78485`, 1061 paths over 170 commits. Where a cited line moved with its text byte-identical, the record is re-pointed and its new hop sentence says by how much. Where objectui rewrote a cited line around the same read, the range is re-read and the hop sentence says so. + +Three records said something that is false at the new pin, and only those sentences are rewritten: + +- `element:repeater` reads the node-level `dataSource` binding first since objectui#11880 (objectui `aaba8655a`), with its flat `object` / `filter` / `sort` / `limit` keys as the fallback. The row's docblock said the binding was not read. It now states the precedence the renderer applies, and that a node naming its object only through `dataSource` renders while this row still requires `object`: that requirement can follow the renderer only by a schema change, which is objectstack#11509's. +- `action:button` now publishes `undoable` and hands the runner the record in scope as its Undo baseline (objectui#11168, objectui `f0496bdf1`). The row's docblock said the input stayed unpublished because the block wrote no row stash. +- `action:icon` reads `label` six times, not five: the tooltip of a predicate-disabled icon takes it as its heading (objectui#11839, objectui `cef0eeec0`). + +The `FormField.span` describe changes its sha only: `WIDE_FIELD_TYPES`, the field-type alias table and `spanLadderFor` are byte-identical at the new pin. The six migration entries' corpus counts were re-taken with `git grep -o -F`, the method that first reproduced every `a58626c88dc8` number. The corpus is now 8234 tracked files. All 99 checked tokens still read zero, except `Span` / `SpanSchema`, which read 517 / 57: the eight new `Span` hits are each a `colSpan`. + +No key, default, enum member or export moves. diff --git a/.objectui-sha b/.objectui-sha index ef0e8f17940..4a89f6917c7 100644 --- a/.objectui-sha +++ b/.objectui-sha @@ -1 +1 @@ -a58626c88dc85954bd0af24f16ebb69454c03eee +f0268ad784854568aa58a2aa791f6a7502259186 diff --git a/content/docs/references/ui/view.mdx b/content/docs/references/ui/view.mdx index eff88c1bf1a..bb2caf93d2c 100644 --- a/content/docs/references/ui/view.mdx +++ b/content/docs/references/ui/view.mdx @@ -213,7 +213,7 @@ Column footer summary configuration | **required** | `boolean` | optional | Required override | | **hidden** | `boolean` | optional | Hidden override | | **colSpan** | `integer` | optional | Absolute column span (1-4). The renderer clamps it to the form grid's current column count, so the cell starts at a real column boundary at every surface width and never overflows (`colSpan: 4` in a 3-column grid renders as 3); a `colSpan` within the column count renders as authored, and `colSpan: 1` emits no span class at all. | -| **span** | `Enum<'auto' \| 'full'>` | optional (default: `"auto"`) | Relative field width. 'auto' (default — omit it): the renderer sizes the field from its widget type × the current column count — at the pin this repo builds against (`.objectui-sha` = `a58626c88dc8`), only textarea, markdown, html, richtext and repeater resolve to the full column count (repeater reaches it through the wide `field:grid` widget it maps to). 'full': resolves to the form grid's full column count. How far down the container-query tiers that span is emitted is the renderer's, not this key's: at that same pin the renderer emits one clamped col-span class per multi-column tier (`@md:col-span-2 @2xl:col-span-3` for a 3-column grid), so the field takes the whole row at every multi-column tier, not just the widest. | +| **span** | `Enum<'auto' \| 'full'>` | optional (default: `"auto"`) | Relative field width. 'auto' (default — omit it): the renderer sizes the field from its widget type × the current column count — at the pin this repo builds against (`.objectui-sha` = `f0268ad78485`), only textarea, markdown, html, richtext and repeater resolve to the full column count (repeater reaches it through the wide `field:grid` widget it maps to). 'full': resolves to the form grid's full column count. How far down the container-query tiers that span is emitted is the renderer's, not this key's: at that same pin the renderer emits one clamped col-span class per multi-column tier (`@md:col-span-2 @2xl:col-span-3` for a 3-column grid), so the field takes the whole row at every multi-column tier, not just the widest. | | **widget** | `string` | optional | Custom widget/component name (overrides type-based inference) | | **language** | `string` | optional | Code editor language (for type=code) | | **keyField** | `{ field?: string; label?: string \| Record; placeholder?: string \| Record; helpText?: string \| Record; … }` | optional | Key column config for record-typed fields | @@ -343,7 +343,7 @@ Form-view select option — the object-field option shape minus the per-option ` | **required** | `boolean` | optional | Required override | | **hidden** | `boolean` | optional | Hidden override | | **colSpan** | `integer` | optional | Absolute column span (1-4). The renderer clamps it to the form grid's current column count, so the cell starts at a real column boundary at every surface width and never overflows (`colSpan: 4` in a 3-column grid renders as 3); a `colSpan` within the column count renders as authored, and `colSpan: 1` emits no span class at all. | -| **span** | `Enum<'auto' \| 'full'>` | optional (default: `"auto"`) | Relative field width. 'auto' (default — omit it): the renderer sizes the field from its widget type × the current column count — at the pin this repo builds against (`.objectui-sha` = `a58626c88dc8`), only textarea, markdown, html, richtext and repeater resolve to the full column count (repeater reaches it through the wide `field:grid` widget it maps to). 'full': resolves to the form grid's full column count. How far down the container-query tiers that span is emitted is the renderer's, not this key's: at that same pin the renderer emits one clamped col-span class per multi-column tier (`@md:col-span-2 @2xl:col-span-3` for a 3-column grid), so the field takes the whole row at every multi-column tier, not just the widest. | +| **span** | `Enum<'auto' \| 'full'>` | optional (default: `"auto"`) | Relative field width. 'auto' (default — omit it): the renderer sizes the field from its widget type × the current column count — at the pin this repo builds against (`.objectui-sha` = `f0268ad78485`), only textarea, markdown, html, richtext and repeater resolve to the full column count (repeater reaches it through the wide `field:grid` widget it maps to). 'full': resolves to the form grid's full column count. How far down the container-query tiers that span is emitted is the renderer's, not this key's: at that same pin the renderer emits one clamped col-span class per multi-column tier (`@md:col-span-2 @2xl:col-span-3` for a 3-column grid), so the field takes the whole row at every multi-column tier, not just the widest. | | **widget** | `string` | optional | Custom widget/component name (overrides type-based inference) | | **language** | `string` | optional | Code editor language (for type=code) | | **keyField** | `{ field?: string; label?: string \| Record; placeholder?: string \| Record; helpText?: string \| Record; … }` | optional | Key column config for record-typed fields | diff --git a/packages/sdui-parser/objectui-lockstep.json b/packages/sdui-parser/objectui-lockstep.json index 365c666c8ee..a96f26f7aaa 100644 --- a/packages/sdui-parser/objectui-lockstep.json +++ b/packages/sdui-parser/objectui-lockstep.json @@ -6,8 +6,8 @@ ], "objectui": { "repo": "https://github.com/objectstack-ai/objectui.git", - "rev": "a58626c88dc85954bd0af24f16ebb69454c03eee", - "revDate": "2026-10-06T15:08:56+00:00", + "rev": "f0268ad784854568aa58a2aa791f6a7502259186", + "revDate": "2026-10-09T01:49:47+00:00", "source": "packages/sdui-parser/src", "files": [ "packages/sdui-parser/src/body-dialect.ts", @@ -21,7 +21,7 @@ "packages/sdui-parser/src/validate.ts" ] }, - "recordedAgainstPin": "a58626c88dc85954bd0af24f16ebb69454c03eee", + "recordedAgainstPin": "f0268ad784854568aa58a2aa791f6a7502259186", "grammarRegion": { "file": "packages/sdui-parser/src/parse.ts", "delimiter": "/* ---------------------- the JS literal subset (#6614) ---------------------- */", diff --git a/packages/spec/src/data/api-methods-batch-conformance.test.ts b/packages/spec/src/data/api-methods-batch-conformance.test.ts index 99a0cd875e4..6259723603b 100644 --- a/packages/spec/src/data/api-methods-batch-conformance.test.ts +++ b/packages/spec/src/data/api-methods-batch-conformance.test.ts @@ -61,7 +61,19 @@ const SINGLE_RECORD_WRITE_ONLY: Record = { // `revoked` on ONE key. The multi-select surface this rule protects does not // exist for API keys, and the shape a future one would take does not need // `bulk` either — both read off the console build this release pins - // (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + // (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + // in `packages/plugin-grid`, on the hop off `a58626c88`, `ObjectGrid.tsx` + // changed again (85 insertions, 27 deletions: objectui#11880 item 5's grid + // filter hand-off, objectui#6152 rounds 7 and 10, objectui#11817's link cell, + // objectui#11809's option order and objectui#11689's boolean face), none of + // it inside the selection block and no hunk naming a bulk action, a delete + // affordance or `operations`, so the block only MOVED by +54: + // `ObjectGrid.tsx:4867-4894` here (`4813-4840` at `a58626c88`), still hashing + // to `c88443302d40c2db739ddb235470bafa29056e2e` (hash-object of the block), + // re-READ with the same reading below; `hooks/useBulkExecutor.ts` is + // byte-identical to `a58626c88` and its `:298-303` still hashes to + // `01083348330f10a201cdf1078b4c21c236402b6a`. At `a58626c88`, re-read there + // 2026-10-06: // every objectui file this record cites is byte-identical across the hop from // `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. // At `0abd4f9f8`, re-read there 2026-10-05: diff --git a/packages/spec/src/kernel/functional-completeness.ts b/packages/spec/src/kernel/functional-completeness.ts index 892aa425472..70ec2c89773 100644 --- a/packages/spec/src/kernel/functional-completeness.ts +++ b/packages/spec/src/kernel/functional-completeness.ts @@ -298,7 +298,16 @@ export function checkFieldCompleteness(def: unknown): CompletenessFinding[] { * English sentence. So the loss is total rather than partial — every * record, on every object — and the author is told at render time as well * as here. Both reads hold at the pin this repo builds against - * (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * on the hop off `a58626c88` `ObjectCalendar.tsx` changed in one comment line + * only, line for line (`:1250`, objectui `c0862c1cc` re-citing the installed spec + * as 17.7.0), so `getCalendarConfig` `:294`, the `if (!calendarConfig)` arm + * `:1296` and its `tt(…)` lines `:1303-1304` did not move and are byte-identical; + * `ListView.tsx` changed (+286/-46: objectui#11984, objectui#6152 round 12, + * objectui#11860, objectui#11943, objectui#11925, objectui#11816, objectui#11810 + * and objectui#11687), every `case` arm byte-identical and moved by 83; and the + * `en` / `zh` / `de` packs changed (17 commits) but not their + * `calendar.configRequired` strings. At `a58626c88`, re-read there 2026-10-06: * on the hop off `0abd4f9f8` `ObjectCalendar.tsx` and `ListView.tsx` are * byte-identical (`git diff --quiet`), so every anchor held unmoved, and the * `en` / `zh` / `de` packs changed (objectui#11658, objectui#11659, @@ -375,7 +384,12 @@ export function checkFieldCompleteness(def: unknown): CompletenessFinding[] { * This repo already records the same deletion one door over: the #13817 * check in `../ui/view.zod.ts` names objectui#7029 as its runtime half. * - `gantt` → NO fallback, and no silence [#19630]. Measured at the pin - * this repo builds against (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * this repo builds against (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * on the hop off `a58626c88` `ObjectGantt.tsx` is byte-identical + * (`git diff --quiet`), so `getGanttConfig` `:610` and the `if (!ganttConfig)` + * arm `:2307` did not move, and `ListView.tsx` changed (+286/-46, the same eight + * objectui changes as above) with its `case 'gantt'` byte-identical, moved by 83. + * At `a58626c88`, re-read there 2026-10-06: * every objectui file this record cites is byte-identical across the hop from * `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. * At `0abd4f9f8`, re-read there 2026-10-05: @@ -443,7 +457,15 @@ export function checkFieldCompleteness(def: unknown): CompletenessFinding[] { * requires. So the view does not draw a blank chart: it refuses, by name. * - `timeline` → date axis: NO fallback [#19630]; title: `titleField || 'name'`, * which still stands. Measured at the same pin (`.objectui-sha` = - * `a58626c88`, re-read there 2026-10-06: + * `f0268ad78`, re-read there 2026-10-09: + * on the hop off `a58626c88` `ObjectTimeline.tsx` changed in three comments only + * (+19/-8, objectui#6152 round 12: the nested block's type is the spec slot by + * reference, its legacy `dateField` refused by name while the read stays), so its + * start-date chain and its `if (!hasAuthoredItems && !startDateField)` refusal + * arm are byte-identical, MOVED `:578-580` → `:589-591` and `:941` → `:952`, and + * `ListView.tsx` changed (+286/-46) with its `case 'timeline'` and + * `resolveTimelineDateBinding` byte-identical, moved by 83 and by 13. At + * `a58626c88`, re-read there 2026-10-06: * on the hop off `0abd4f9f8` `ObjectTimeline.tsx` changed (+39/-9: * objectui#11675 starts the date buckets' week on the display locale's first * day, and objectui#11676 heads a past date "Earlier" and retires the @@ -504,7 +526,15 @@ export function checkFieldCompleteness(def: unknown): CompletenessFinding[] { * block does render; the warning still fires there, because the block the * view TYPE names is the one that is missing. Unchanged by this row. * - `map` → NO fallback, and no silence [#19630]. Measured at the same - * pin (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * pin (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * on the hop off `a58626c88` `ObjectMap.tsx` changed (85 insertions, 4 deletions, + * objectui#11819: without WebGL2 the map lists its records instead of crashing), + * which touches no coordinate read: `getMapConfig` and `hasCoordinateBinding` are + * byte-identical and moved `:387` → `:421` and `:493` → `:527` under the WebGL2 + * probe above them, and the refusal arm is byte-identical, moved `:1291` → + * `:1337`; and `ListView.tsx` changed (+286/-46) with its `case 'map'` + * byte-identical, moved by 83, and `resolveListMapConfig` byte-identical, moved + * `:146` → `:147`. At `a58626c88`, re-read there 2026-10-06: * every objectui file this record cites is byte-identical across the hop from * `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. * At `0abd4f9f8`, re-read there 2026-10-05: diff --git a/packages/spec/src/migrations/entries/semantic/18.kernel-health-check-and-hot-reload-durations-unit-in-key.ts b/packages/spec/src/migrations/entries/semantic/18.kernel-health-check-and-hot-reload-durations-unit-in-key.ts index 957f6774e5e..6afbfc8077e 100644 --- a/packages/spec/src/migrations/entries/semantic/18.kernel-health-check-and-hot-reload-durations-unit-in-key.ts +++ b/packages/spec/src/migrations/entries/semantic/18.kernel-health-check-and-hot-reload-durations-unit-in-key.ts @@ -52,13 +52,13 @@ export const entry: SemanticMigration = { + 'the audience that does not parse. Measured on 884e8347d: the only in-repo readers are ' + 'packages/core/src/health-monitor.ts and packages/core/src/hot-reload.ts, both moved in ' + 'this same change; and the pinned objectui checkout — the pin this repo builds ' - + 'against, `.objectui-sha` = `a58626c88dc85954bd0af24f16ebb69454c03eee` — names ' + + 'against, `.objectui-sha` = `f0268ad784854568aa58a2aa791f6a7502259186` — names ' + 'neither def and neither key: all thirteen exports of plugin-lifecycle-advanced.zod.ts and ' - + 'the string debounceDelay each occur 0 times across its 7754 tracked files (0 across the 7650 at 0abd4f9f8, the 7632 at 9dfaca654, the 7579 at 2e818d0b5, the 10267 at ab1879721, the 10071 at 89cad75d5, the 9912 at 31971ff1e, the 9800 at e420df310, the 9546 at db11afd49, the 9283 at dd3f7e1be, the ' + + 'the string debounceDelay each occur 0 times across its 8234 tracked files (0 across the 7754 at a58626c88, the 7650 at 0abd4f9f8, the 7632 at 9dfaca654, the 7579 at 2e818d0b5, the 10267 at ab1879721, the 10071 at 89cad75d5, the 9912 at 31971ff1e, the 9800 at e420df310, the 9546 at db11afd49, the 9283 at dd3f7e1be, the ' + '8512 at f8a9d0fb0 and the 8303 at 62597c588 too), against lit ' + 'controls objectstack 12966 and @objectstack/spec 4997 on the same corpus at 87af769e9, ' + 'which re-count to 13125 and 5043 respectively at 62597c588, to 13347 and 5123 at ' - + 'f8a9d0fb0, to 13745 and 5466 at dd3f7e1be, to 14704 and 5545 at db11afd49, to 15352 and 6024 at e420df310, to 15691 and 6206 at 31971ff1e, to 16044 and 6461 at 89cad75d5, to 16377 and 6665 at ab1879721, to 17227 and 7134 at 2e818d0b5, to 17313 and 7186 at 9dfaca654, to 17390 and 7209 at 0abd4f9f8 and to 17468 and 7246 at this pin (git grep -o -F, the method that reproduces ' + + 'f8a9d0fb0, to 13745 and 5466 at dd3f7e1be, to 14704 and 5545 at db11afd49, to 15352 and 6024 at e420df310, to 15691 and 6206 at 31971ff1e, to 16044 and 6461 at 89cad75d5, to 16377 and 6665 at ab1879721, to 17227 and 7134 at 2e818d0b5, to 17313 and 7186 at 9dfaca654, to 17390 and 7209 at 0abd4f9f8, to 17468 and 7246 at a58626c88 and to 17956 and 7522 at this pin (git grep -o -F, the method that reproduces ' + 'every earlier count).', acceptanceCriteria: 'Every producer and reader of a PluginHealthCheck spells intervalMs and timeoutMs, and every ' diff --git a/packages/spec/src/migrations/entries/semantic/18.kernel-runtime-config-timeout-unit-in-key.ts b/packages/spec/src/migrations/entries/semantic/18.kernel-runtime-config-timeout-unit-in-key.ts index 8a0ce1427cc..d6da9681075 100644 --- a/packages/spec/src/migrations/entries/semantic/18.kernel-runtime-config-timeout-unit-in-key.ts +++ b/packages/spec/src/migrations/entries/semantic/18.kernel-runtime-config-timeout-unit-in-key.ts @@ -46,10 +46,10 @@ export const entry: SemanticMigration = { + 'spells timeout 0 times; outside the zod file and its test the only live occurrences are the ' + 'generated rows in content/docs/references/kernel/plugin-security-advanced.mdx, which this ' + 'rename regenerates. The pinned objectui checkout — this is the pin we build against, ' - + '`.objectui-sha` = `a58626c88dc85954bd0af24f16ebb69454c03eee`, re-read from this tree — ' + + '`.objectui-sha` = `f0268ad784854568aa58a2aa791f6a7502259186`, re-read from this tree — ' + 'spells resourceLimits.timeout 0 times across ' - + '7754 tracked files, against lit controls timeout 1431, RuntimeConfig 299 and resourceLimits ' - + '2 on the same corpus (0 across 7650, and 1360 / 293 / 2, at 0abd4f9f8; 0 across 7632, and 1360 / 293 / 2, at 9dfaca654; 0 across 7579, and 1351 / 276 / 2, at 2e818d0b5; 0 across 10267, and 1348 / 273 / 2, at ab1879721; 0 across 10071, and 1331 / 273 / 2, at 89cad75d5; 0 across 9912, and 1303 / 273 / 2, at 31971ff1e; 0 across 9800, and 1293 / 273 / 2, at e420df310; 0 across 9546, and 1197 / 273 / 2, at db11afd49; 0 across 9283, and 1172 / 263 / 2, at dd3f7e1be; 0 across 8512, and 1096 / 245 / 2, at f8a9d0fb0; 0 across 8303, and ' + + '8234 tracked files, against lit controls timeout 1658, RuntimeConfig 337 and resourceLimits ' + + '2 on the same corpus (0 across 7754, and 1431 / 299 / 2, at a58626c88; 0 across 7650, and 1360 / 293 / 2, at 0abd4f9f8; 0 across 7632, and 1360 / 293 / 2, at 9dfaca654; 0 across 7579, and 1351 / 276 / 2, at 2e818d0b5; 0 across 10267, and 1348 / 273 / 2, at ab1879721; 0 across 10071, and 1331 / 273 / 2, at 89cad75d5; 0 across 9912, and 1303 / 273 / 2, at 31971ff1e; 0 across 9800, and 1293 / 273 / 2, at e420df310; 0 across 9546, and 1197 / 273 / 2, at db11afd49; 0 across 9283, and 1172 / 263 / 2, at dd3f7e1be; 0 across 8512, and 1096 / 245 / 2, at f8a9d0fb0; 0 across 8303, and ' + '1086 / 240 / 2, at 62597c588); both resourceLimits hits are prose in packages/app-shell recording ' + 'that objectui\'s own AppShellRuntimeConfig shares not one key with the spec\'s ' + 'RuntimeConfig, so nothing there authors this key and no pin bump is owed. ADR-0087.', diff --git a/packages/spec/src/migrations/entries/semantic/18.logging-durations-unit-in-key.ts b/packages/spec/src/migrations/entries/semantic/18.logging-durations-unit-in-key.ts index bbfb441cc39..4f8ac62b0a7 100644 --- a/packages/spec/src/migrations/entries/semantic/18.logging-durations-unit-in-key.ts +++ b/packages/spec/src/migrations/entries/semantic/18.logging-durations-unit-in-key.ts @@ -47,10 +47,10 @@ export const entry: SemanticMigration = { + 'no in-repo runtime reads any of the four — outside `packages/spec/src/system/logging.zod.ts` ' + 'and its test the only occurrences are the generated rows in ' + '`content/docs/references/system/logging.mdx`, which this rename regenerates; and the pinned ' - + 'objectui checkout — `.objectui-sha` = `a58626c88dc85954bd0af24f16ebb69454c03eee` — spells ' + + 'objectui checkout — `.objectui-sha` = `f0268ad784854568aa58a2aa791f6a7502259186` — spells ' + '`flushInterval` 0 times, `initialDelay` 0, `HttpDestinationConfig` 0 and `LoggingConfig` 0 ' - + 'across its 7754 tracked files, against lit controls `useState` 2491 and `timeout` 1431 on ' - + 'the same corpus (all four 0 across 7650, against 2478 and 1360, at 0abd4f9f8, 0 across 7632, against 2477 and 1360, at 9dfaca654, 0 across 7579, against 2477 and 1351, at 2e818d0b5, 0 across 10267, against 2476 and 1348, at ab1879721, 0 across 10071, against 2470 and 1331, at 89cad75d5, 0 across 9912, against 2469 and 1303, at 31971ff1e, 0 across 9800, against 2464 and 1293, at e420df310, 0 across 9546, against 2449 and 1197, at db11afd49, 0 across 9283, against 2435 and 1172, at dd3f7e1be, 0 across 8512, ' + + 'across its 8234 tracked files, against lit controls `useState` 2622 and `timeout` 1658 on ' + + 'the same corpus (all four 0 across 7754, against 2491 and 1431, at a58626c88, 0 across 7650, against 2478 and 1360, at 0abd4f9f8, 0 across 7632, against 2477 and 1360, at 9dfaca654, 0 across 7579, against 2477 and 1351, at 2e818d0b5, 0 across 10267, against 2476 and 1348, at ab1879721, 0 across 10071, against 2470 and 1331, at 89cad75d5, 0 across 9912, against 2469 and 1303, at 31971ff1e, 0 across 9800, against 2464 and 1293, at e420df310, 0 across 9546, against 2449 and 1197, at db11afd49, 0 across 9283, against 2435 and 1172, at dd3f7e1be, 0 across 8512, ' + 'against 2391 and 1096, at f8a9d0fb0, and 0 across ' + '8303, against 2389 and 1086, at 62597c588).', acceptanceCriteria: diff --git a/packages/spec/src/migrations/entries/semantic/18.system-metrics-jsdoc-durations-unit-in-key.ts b/packages/spec/src/migrations/entries/semantic/18.system-metrics-jsdoc-durations-unit-in-key.ts index 77eafa0ec57..7aed489e334 100644 --- a/packages/spec/src/migrations/entries/semantic/18.system-metrics-jsdoc-durations-unit-in-key.ts +++ b/packages/spec/src/migrations/entries/semantic/18.system-metrics-jsdoc-durations-unit-in-key.ts @@ -73,10 +73,11 @@ export const entry: SemanticMigration = { + 'against a lit control of 1195 defineStack occurrences on that same corpus at fc28c1d38 ' + '(1195 again at 9b62f54671); and the objectui ' + 'checkout this repo builds against — this is the pin, ' - + '`.objectui-sha` = `a58626c88dc85954bd0af24f16ebb69454c03eee`, re-read from this tree — ' - + 'spells all six metrics def names and both distinctive keys 0 times across 7754 tracked ' - + 'files at that sha, against lit controls window 4255, timeout 1431, period 247, ' - + 'interval 200 and metrics 401 on that same corpus and sha (0 across 7650, against 4194 / ' + + '`.objectui-sha` = `f0268ad784854568aa58a2aa791f6a7502259186`, re-read from this tree — ' + + 'spells all six metrics def names and both distinctive keys 0 times across 8234 tracked ' + + 'files at that sha, against lit controls window 4430, timeout 1658, period 249, ' + + 'interval 213 and metrics 404 on that same corpus and sha (0 across 7754, against 4255 / ' + + '1431 / 247 / 200 / 401, at a58626c88, 0 across 7650, against 4194 / ' + '1360 / 238 / 195 / 401, at 0abd4f9f8, 0 across 7632, against 4193 / ' + '1360 / 238 / 195 / 401, at 9dfaca654, 0 across 7579, against 4175 / ' + '1351 / 238 / 195 / 374, at 2e818d0b5, 0 across 10267, against 4044 / ' diff --git a/packages/spec/src/migrations/entries/semantic/18.system-tracing-otel-exporter-durations-unit-in-key.ts b/packages/spec/src/migrations/entries/semantic/18.system-tracing-otel-exporter-durations-unit-in-key.ts index 4d37031781a..40fde1ff536 100644 --- a/packages/spec/src/migrations/entries/semantic/18.system-tracing-otel-exporter-durations-unit-in-key.ts +++ b/packages/spec/src/migrations/entries/semantic/18.system-tracing-otel-exporter-durations-unit-in-key.ts @@ -69,12 +69,13 @@ export const entry: SemanticMigration = { + 'dark control of 0; inside packages/spec the ' + 'only occurrences are tracing.zod.ts, its test, and the generated rows in ' + 'content/docs/references/system/tracing.mdx, which this rename regenerates. And the ' - + 'pinned objectui checkout — `.objectui-sha` = `a58626c88dc85954bd0af24f16ebb69454c03eee` — names none of it: all 37 exports of ' - + 'tracing.zod.ts and each of the four key names occur 0 times across the 7754 files ' - + 'tracked at that sha (the 509 Span and 57 SpanSchema hits are objectui\'s own HTML ' + + 'pinned objectui checkout — `.objectui-sha` = `f0268ad784854568aa58a2aa791f6a7502259186` — names none of it: all 37 exports of ' + + 'tracing.zod.ts and each of the four key names occur 0 times across the 8234 files ' + + 'tracked at that sha (the 517 Span and 57 SpanSchema hits are objectui\'s own HTML ' + 'text-span component, TextSpanSchema, an unrelated name, plus colSpan and prose), against ' - + 'two lit controls on that same corpus and sha: 17468 hits for the bare token objectstack, ' - + 'and 7246 for the package specifier @objectstack/spec (at 0abd4f9f8: 0 across 7650, Span 508, ' + + 'two lit controls on that same corpus and sha: 17956 hits for the bare token objectstack, ' + + 'and 7522 for the package specifier @objectstack/spec (at a58626c88: 0 across 7754, Span 509, ' + + '17468 and 7246; at 0abd4f9f8: 0 across 7650, Span 508, ' + '17390 and 7209; at 9dfaca654: 0 across 7632, Span 508, ' + '17313 and 7186; at 2e818d0b5: 0 across 7579, Span 505, ' + '17227 and 7134; at ab1879721: 0 across 10267, Span 491, ' diff --git a/packages/spec/src/migrations/entries/semantic/18.tenant-schema-cache-ttl-unit-in-key.ts b/packages/spec/src/migrations/entries/semantic/18.tenant-schema-cache-ttl-unit-in-key.ts index bee8e434d30..fe452dfdba3 100644 --- a/packages/spec/src/migrations/entries/semantic/18.tenant-schema-cache-ttl-unit-in-key.ts +++ b/packages/spec/src/migrations/entries/semantic/18.tenant-schema-cache-ttl-unit-in-key.ts @@ -31,9 +31,9 @@ export const entry: SemanticMigration = { + 'bd25e897dc: no in-repo runtime reads the key — outside `packages/spec/src/system/tenant.zod.ts` ' + 'and its test the only occurrences are the four generated rows in ' + '`content/docs/references/system/tenant.mdx`, which this rename regenerates; and the pinned ' - + 'objectui checkout — `.objectui-sha` = `a58626c88dc85954bd0af24f16ebb69454c03eee` — spells it 0 ' - + 'times across 7754 tracked files, against lit controls `TTL` 184 and `tenant` 1319 on the ' - + 'same corpus (0 across 7650, against 182 and 1318, at 0abd4f9f8; 0 across 7632, against 182 and 1318, at 9dfaca654; 0 across 7579, against 182 and 1317, at 2e818d0b5; 0 across 10267, against 180 and 1238, at ab1879721; 0 across 10071, against 181 and 1237, at 89cad75d5; 0 across 9912, against 181 and 1237, at 31971ff1e; 0 across 9800, against 181 and 1235, at e420df310; 0 across 9546, against 181 and 1200, at db11afd49; 0 across 9283, against 181 and 1185, at dd3f7e1be; 0 across 8512, against 156 and 1034, at f8a9d0fb0; 0 across 8303, against 156 ' + + 'objectui checkout — `.objectui-sha` = `f0268ad784854568aa58a2aa791f6a7502259186` — spells it 0 ' + + 'times across 8234 tracked files, against lit controls `TTL` 184 and `tenant` 1338 on the ' + + 'same corpus (0 across 7754, against 184 and 1319, at a58626c88; 0 across 7650, against 182 and 1318, at 0abd4f9f8; 0 across 7632, against 182 and 1318, at 9dfaca654; 0 across 7579, against 182 and 1317, at 2e818d0b5; 0 across 10267, against 180 and 1238, at ab1879721; 0 across 10071, against 181 and 1237, at 89cad75d5; 0 across 9912, against 181 and 1237, at 31971ff1e; 0 across 9800, against 181 and 1235, at e420df310; 0 across 9546, against 181 and 1200, at db11afd49; 0 across 9283, against 181 and 1185, at dd3f7e1be; 0 across 8512, against 156 and 1034, at f8a9d0fb0; 0 across 8303, against 156 ' + 'and 987, at 62597c588).', acceptanceCriteria: 'Every schema-level tenant isolation source spells `performance.schemaCacheTtlSeconds`; ' diff --git a/packages/spec/src/migrations/registry.ts b/packages/spec/src/migrations/registry.ts index 0153882b1c4..eacf7bbd3e9 100644 --- a/packages/spec/src/migrations/registry.ts +++ b/packages/spec/src/migrations/registry.ts @@ -15158,13 +15158,13 @@ const step18: MigrationStep = { + 'the audience that does not parse. Measured on 884e8347d: the only in-repo readers are ' + 'packages/core/src/health-monitor.ts and packages/core/src/hot-reload.ts, both moved in ' + 'this same change; and the pinned objectui checkout — the pin this repo builds ' - + 'against, `.objectui-sha` = `a58626c88dc85954bd0af24f16ebb69454c03eee` — names ' + + 'against, `.objectui-sha` = `f0268ad784854568aa58a2aa791f6a7502259186` — names ' + 'neither def and neither key: all thirteen exports of plugin-lifecycle-advanced.zod.ts and ' - + 'the string debounceDelay each occur 0 times across its 7754 tracked files (0 across the 7650 at 0abd4f9f8, the 7632 at 9dfaca654, the 7579 at 2e818d0b5, the 10267 at ab1879721, the 10071 at 89cad75d5, the 9912 at 31971ff1e, the 9800 at e420df310, the 9546 at db11afd49, the 9283 at dd3f7e1be, the ' + + 'the string debounceDelay each occur 0 times across its 8234 tracked files (0 across the 7754 at a58626c88, the 7650 at 0abd4f9f8, the 7632 at 9dfaca654, the 7579 at 2e818d0b5, the 10267 at ab1879721, the 10071 at 89cad75d5, the 9912 at 31971ff1e, the 9800 at e420df310, the 9546 at db11afd49, the 9283 at dd3f7e1be, the ' + '8512 at f8a9d0fb0 and the 8303 at 62597c588 too), against lit ' + 'controls objectstack 12966 and @objectstack/spec 4997 on the same corpus at 87af769e9, ' + 'which re-count to 13125 and 5043 respectively at 62597c588, to 13347 and 5123 at ' - + 'f8a9d0fb0, to 13745 and 5466 at dd3f7e1be, to 14704 and 5545 at db11afd49, to 15352 and 6024 at e420df310, to 15691 and 6206 at 31971ff1e, to 16044 and 6461 at 89cad75d5, to 16377 and 6665 at ab1879721, to 17227 and 7134 at 2e818d0b5, to 17313 and 7186 at 9dfaca654, to 17390 and 7209 at 0abd4f9f8 and to 17468 and 7246 at this pin (git grep -o -F, the method that reproduces ' + + 'f8a9d0fb0, to 13745 and 5466 at dd3f7e1be, to 14704 and 5545 at db11afd49, to 15352 and 6024 at e420df310, to 15691 and 6206 at 31971ff1e, to 16044 and 6461 at 89cad75d5, to 16377 and 6665 at ab1879721, to 17227 and 7134 at 2e818d0b5, to 17313 and 7186 at 9dfaca654, to 17390 and 7209 at 0abd4f9f8, to 17468 and 7246 at a58626c88 and to 17956 and 7522 at this pin (git grep -o -F, the method that reproduces ' + 'every earlier count).', acceptanceCriteria: 'Every producer and reader of a PluginHealthCheck spells intervalMs and timeoutMs, and every ' @@ -15369,10 +15369,10 @@ const step18: MigrationStep = { + 'spells timeout 0 times; outside the zod file and its test the only live occurrences are the ' + 'generated rows in content/docs/references/kernel/plugin-security-advanced.mdx, which this ' + 'rename regenerates. The pinned objectui checkout — this is the pin we build against, ' - + '`.objectui-sha` = `a58626c88dc85954bd0af24f16ebb69454c03eee`, re-read from this tree — ' + + '`.objectui-sha` = `f0268ad784854568aa58a2aa791f6a7502259186`, re-read from this tree — ' + 'spells resourceLimits.timeout 0 times across ' - + '7754 tracked files, against lit controls timeout 1431, RuntimeConfig 299 and resourceLimits ' - + '2 on the same corpus (0 across 7650, and 1360 / 293 / 2, at 0abd4f9f8; 0 across 7632, and 1360 / 293 / 2, at 9dfaca654; 0 across 7579, and 1351 / 276 / 2, at 2e818d0b5; 0 across 10267, and 1348 / 273 / 2, at ab1879721; 0 across 10071, and 1331 / 273 / 2, at 89cad75d5; 0 across 9912, and 1303 / 273 / 2, at 31971ff1e; 0 across 9800, and 1293 / 273 / 2, at e420df310; 0 across 9546, and 1197 / 273 / 2, at db11afd49; 0 across 9283, and 1172 / 263 / 2, at dd3f7e1be; 0 across 8512, and 1096 / 245 / 2, at f8a9d0fb0; 0 across 8303, and ' + + '8234 tracked files, against lit controls timeout 1658, RuntimeConfig 337 and resourceLimits ' + + '2 on the same corpus (0 across 7754, and 1431 / 299 / 2, at a58626c88; 0 across 7650, and 1360 / 293 / 2, at 0abd4f9f8; 0 across 7632, and 1360 / 293 / 2, at 9dfaca654; 0 across 7579, and 1351 / 276 / 2, at 2e818d0b5; 0 across 10267, and 1348 / 273 / 2, at ab1879721; 0 across 10071, and 1331 / 273 / 2, at 89cad75d5; 0 across 9912, and 1303 / 273 / 2, at 31971ff1e; 0 across 9800, and 1293 / 273 / 2, at e420df310; 0 across 9546, and 1197 / 273 / 2, at db11afd49; 0 across 9283, and 1172 / 263 / 2, at dd3f7e1be; 0 across 8512, and 1096 / 245 / 2, at f8a9d0fb0; 0 across 8303, and ' + '1086 / 240 / 2, at 62597c588); both resourceLimits hits are prose in packages/app-shell recording ' + 'that objectui\'s own AppShellRuntimeConfig shares not one key with the spec\'s ' + 'RuntimeConfig, so nothing there authors this key and no pin bump is owed. ADR-0087.', @@ -15608,10 +15608,10 @@ const step18: MigrationStep = { + 'no in-repo runtime reads any of the four — outside `packages/spec/src/system/logging.zod.ts` ' + 'and its test the only occurrences are the generated rows in ' + '`content/docs/references/system/logging.mdx`, which this rename regenerates; and the pinned ' - + 'objectui checkout — `.objectui-sha` = `a58626c88dc85954bd0af24f16ebb69454c03eee` — spells ' + + 'objectui checkout — `.objectui-sha` = `f0268ad784854568aa58a2aa791f6a7502259186` — spells ' + '`flushInterval` 0 times, `initialDelay` 0, `HttpDestinationConfig` 0 and `LoggingConfig` 0 ' - + 'across its 7754 tracked files, against lit controls `useState` 2491 and `timeout` 1431 on ' - + 'the same corpus (all four 0 across 7650, against 2478 and 1360, at 0abd4f9f8, 0 across 7632, against 2477 and 1360, at 9dfaca654, 0 across 7579, against 2477 and 1351, at 2e818d0b5, 0 across 10267, against 2476 and 1348, at ab1879721, 0 across 10071, against 2470 and 1331, at 89cad75d5, 0 across 9912, against 2469 and 1303, at 31971ff1e, 0 across 9800, against 2464 and 1293, at e420df310, 0 across 9546, against 2449 and 1197, at db11afd49, 0 across 9283, against 2435 and 1172, at dd3f7e1be, 0 across 8512, ' + + 'across its 8234 tracked files, against lit controls `useState` 2622 and `timeout` 1658 on ' + + 'the same corpus (all four 0 across 7754, against 2491 and 1431, at a58626c88, 0 across 7650, against 2478 and 1360, at 0abd4f9f8, 0 across 7632, against 2477 and 1360, at 9dfaca654, 0 across 7579, against 2477 and 1351, at 2e818d0b5, 0 across 10267, against 2476 and 1348, at ab1879721, 0 across 10071, against 2470 and 1331, at 89cad75d5, 0 across 9912, against 2469 and 1303, at 31971ff1e, 0 across 9800, against 2464 and 1293, at e420df310, 0 across 9546, against 2449 and 1197, at db11afd49, 0 across 9283, against 2435 and 1172, at dd3f7e1be, 0 across 8512, ' + 'against 2391 and 1096, at f8a9d0fb0, and 0 across ' + '8303, against 2389 and 1086, at 62597c588).', acceptanceCriteria: @@ -19973,10 +19973,11 @@ const step18: MigrationStep = { + 'against a lit control of 1195 defineStack occurrences on that same corpus at fc28c1d38 ' + '(1195 again at 9b62f54671); and the objectui ' + 'checkout this repo builds against — this is the pin, ' - + '`.objectui-sha` = `a58626c88dc85954bd0af24f16ebb69454c03eee`, re-read from this tree — ' - + 'spells all six metrics def names and both distinctive keys 0 times across 7754 tracked ' - + 'files at that sha, against lit controls window 4255, timeout 1431, period 247, ' - + 'interval 200 and metrics 401 on that same corpus and sha (0 across 7650, against 4194 / ' + + '`.objectui-sha` = `f0268ad784854568aa58a2aa791f6a7502259186`, re-read from this tree — ' + + 'spells all six metrics def names and both distinctive keys 0 times across 8234 tracked ' + + 'files at that sha, against lit controls window 4430, timeout 1658, period 249, ' + + 'interval 213 and metrics 404 on that same corpus and sha (0 across 7754, against 4255 / ' + + '1431 / 247 / 200 / 401, at a58626c88, 0 across 7650, against 4194 / ' + '1360 / 238 / 195 / 401, at 0abd4f9f8, 0 across 7632, against 4193 / ' + '1360 / 238 / 195 / 401, at 9dfaca654, 0 across 7579, against 4175 / ' + '1351 / 238 / 195 / 374, at 2e818d0b5, 0 across 10267, against 4044 / ' @@ -20197,12 +20198,13 @@ const step18: MigrationStep = { + 'dark control of 0; inside packages/spec the ' + 'only occurrences are tracing.zod.ts, its test, and the generated rows in ' + 'content/docs/references/system/tracing.mdx, which this rename regenerates. And the ' - + 'pinned objectui checkout — `.objectui-sha` = `a58626c88dc85954bd0af24f16ebb69454c03eee` — names none of it: all 37 exports of ' - + 'tracing.zod.ts and each of the four key names occur 0 times across the 7754 files ' - + 'tracked at that sha (the 509 Span and 57 SpanSchema hits are objectui\'s own HTML ' + + 'pinned objectui checkout — `.objectui-sha` = `f0268ad784854568aa58a2aa791f6a7502259186` — names none of it: all 37 exports of ' + + 'tracing.zod.ts and each of the four key names occur 0 times across the 8234 files ' + + 'tracked at that sha (the 517 Span and 57 SpanSchema hits are objectui\'s own HTML ' + 'text-span component, TextSpanSchema, an unrelated name, plus colSpan and prose), against ' - + 'two lit controls on that same corpus and sha: 17468 hits for the bare token objectstack, ' - + 'and 7246 for the package specifier @objectstack/spec (at 0abd4f9f8: 0 across 7650, Span 508, ' + + 'two lit controls on that same corpus and sha: 17956 hits for the bare token objectstack, ' + + 'and 7522 for the package specifier @objectstack/spec (at a58626c88: 0 across 7754, Span 509, ' + + '17468 and 7246; at 0abd4f9f8: 0 across 7650, Span 508, ' + '17390 and 7209; at 9dfaca654: 0 across 7632, Span 508, ' + '17313 and 7186; at 2e818d0b5: 0 across 7579, Span 505, ' + '17227 and 7134; at ab1879721: 0 across 10267, Span 491, ' @@ -20317,9 +20319,9 @@ const step18: MigrationStep = { + 'bd25e897dc: no in-repo runtime reads the key — outside `packages/spec/src/system/tenant.zod.ts` ' + 'and its test the only occurrences are the four generated rows in ' + '`content/docs/references/system/tenant.mdx`, which this rename regenerates; and the pinned ' - + 'objectui checkout — `.objectui-sha` = `a58626c88dc85954bd0af24f16ebb69454c03eee` — spells it 0 ' - + 'times across 7754 tracked files, against lit controls `TTL` 184 and `tenant` 1319 on the ' - + 'same corpus (0 across 7650, against 182 and 1318, at 0abd4f9f8; 0 across 7632, against 182 and 1318, at 9dfaca654; 0 across 7579, against 182 and 1317, at 2e818d0b5; 0 across 10267, against 180 and 1238, at ab1879721; 0 across 10071, against 181 and 1237, at 89cad75d5; 0 across 9912, against 181 and 1237, at 31971ff1e; 0 across 9800, against 181 and 1235, at e420df310; 0 across 9546, against 181 and 1200, at db11afd49; 0 across 9283, against 181 and 1185, at dd3f7e1be; 0 across 8512, against 156 and 1034, at f8a9d0fb0; 0 across 8303, against 156 ' + + 'objectui checkout — `.objectui-sha` = `f0268ad784854568aa58a2aa791f6a7502259186` — spells it 0 ' + + 'times across 8234 tracked files, against lit controls `TTL` 184 and `tenant` 1338 on the ' + + 'same corpus (0 across 7754, against 184 and 1319, at a58626c88; 0 across 7650, against 182 and 1318, at 0abd4f9f8; 0 across 7632, against 182 and 1318, at 9dfaca654; 0 across 7579, against 182 and 1317, at 2e818d0b5; 0 across 10267, against 180 and 1238, at ab1879721; 0 across 10071, against 181 and 1237, at 89cad75d5; 0 across 9912, against 181 and 1237, at 31971ff1e; 0 across 9800, against 181 and 1235, at e420df310; 0 across 9546, against 181 and 1200, at db11afd49; 0 across 9283, against 181 and 1185, at dd3f7e1be; 0 across 8512, against 156 and 1034, at f8a9d0fb0; 0 across 8303, against 156 ' + 'and 987, at 62597c588).', acceptanceCriteria: 'Every schema-level tenant isolation source spells `performance.schemaCacheTtlSeconds`; ' diff --git a/packages/spec/src/ui/action-outcome-messages.test.ts b/packages/spec/src/ui/action-outcome-messages.test.ts index 2ee42b7a36c..f5088168e4e 100644 --- a/packages/spec/src/ui/action-outcome-messages.test.ts +++ b/packages/spec/src/ui/action-outcome-messages.test.ts @@ -12,7 +12,11 @@ * runner default) and the `${result.*}` INTERPOLATION are the console's — the * reader is objectstack-ai/objectui#11344, a later link of the same ruling, * carried from the pin this repo builds against (`.objectui-sha` = - * `a58626c88`, re-read there 2026-10-06: + * `f0268ad78`, re-read there 2026-10-09: + * `ActionRunner.composeSuccessMessage`, in `core/src/actions/ActionRunner.ts`, is + * byte-identical in body to `a58626c88` and MOVED by 7 (objectui#11695 added the + * confirmation handler's `destructive` option above it). At `a58626c88`, re-read + * there 2026-10-06: * every objectui file this record cites is byte-identical across the hop from * `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. * At `0abd4f9f8`, re-read there 2026-10-05: diff --git a/packages/spec/src/ui/action.zod.ts b/packages/spec/src/ui/action.zod.ts index 8038754f9ce..dd745b7cf0d 100644 --- a/packages/spec/src/ui/action.zod.ts +++ b/packages/spec/src/ui/action.zod.ts @@ -1364,7 +1364,11 @@ const actionObject = () => strictObject({ * * Liveness: the ledger row was `planned` until the console reader landed, * and it is `live` from the pin this repo builds against (`.objectui-sha` = - * `a58626c88`, re-read there 2026-10-06: + * `f0268ad78`, re-read there 2026-10-09: + * `core/src/actions/ActionRunner.ts` changed above the reader only (+7/-0, + * objectui#11695: the confirmation handler's `destructive` option and its + * docblock), so `composeSuccessMessage` MOVED `1497` -> `1504` with its body + * byte-identical. At `a58626c88`, re-read there 2026-10-06: * every objectui file this record cites is byte-identical across the hop from * `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. * At `0abd4f9f8`, re-read there 2026-10-05: @@ -1375,7 +1379,7 @@ const actionObject = () => strictObject({ * `ab1879721`, where it was read 2026-10-03, so the anchor below held * unmoved). The reader is objectui#11344 (objectui * `c476be0e0`): `ActionRunner.composeSuccessMessage` - * (`core/src/actions/ActionRunner.ts:1497`) picks `outcomeMessages[outcome]` + * (`core/src/actions/ActionRunner.ts:1504`) picks `outcomeMessages[outcome]` * off the handler's return value, falls back to `successMessage` and then to * the runner's default text, and fills `${result.*}` in whichever it shows. * The four action renderers forward the key to the runner (`action:bar` diff --git a/packages/spec/src/ui/component.test.ts b/packages/spec/src/ui/component.test.ts index 776b6d64bb5..bac7e104fb2 100644 --- a/packages/spec/src/ui/component.test.ts +++ b/packages/spec/src/ui/component.test.ts @@ -288,7 +288,12 @@ describe('PageAccordionProps variant — declared because the accordion renderer // same file's `ComponentRegistry.register('accordion', …)` publishes the key to // the Studio block designer at `:1222` (the `items` input, documented as // `[{ label, icon?, collapsed?, children }]`). Measured at the pin this repo -// builds against — `.objectui-sha` = `a58626c88`, re-read there 2026-10-06: +// builds against — `.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: +// `containers.tsx` changed across the hop from `a58626c88` (+92/-6, +// objectui#11811: a record action disabled by its predicate says why, in the +// `page:header` renderer), every hunk at `:1512` or below, so both anchors were +// re-READ in place and NEITHER moved, each byte-identical. At `a58626c88`, +// re-read there 2026-10-06: // every objectui file this record cites is byte-identical across the hop from // `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. // At `0abd4f9f8`, re-read there 2026-10-05: @@ -440,7 +445,12 @@ describe('PageTabsProps items[].value / items[].count — declared because the t // same file's `ComponentRegistry.register('tabs', …)` publishes the key to the // Studio block designer at `:1007` (the `items` input, documented as // `[{ label, value?, icon?, count?, visibleWhen?, children }]`). Measured at -// the pin this repo builds against — `.objectui-sha` = `a58626c88`, re-read there 2026-10-06: +// the pin this repo builds against — `.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: +// `containers.tsx` changed across the hop from `a58626c88` (+92/-6, +// objectui#11811: a record action disabled by its predicate says why, in the +// `page:header` renderer), every hunk at `:1512` or below, so both anchors were +// re-READ in place and NEITHER moved, each byte-identical. At `a58626c88`, +// re-read there 2026-10-06: // every objectui file this record cites is byte-identical across the hop from // `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. // At `0abd4f9f8`, re-read there 2026-10-05: @@ -3699,7 +3709,16 @@ describe('object-* block props schemas — declared, so the props gate has a sch // #16503 — the spec half of objectui#8172 (decision batch #68, 2026-09-07, // option A: the contract declares the capability that already ships, is // documented and is in use). Measured at the objectui pin this repo builds -// against (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: +// against (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: +// `ObjectKanban.tsx`, `plugin-kanban/src/types.ts` and `plugin-kanban.mdx` are +// byte-identical to `a58626c88` (`git diff --quiet`), so the `$top` read +// `:762`, the default `:98`, the `limit` row and the `limit: 250` snippet did +// not move or change; `plugin-kanban/src/index.tsx` changed only below the +// mapping (+3/-3: a comment re-cited to 17.7.0, and objectui#6152 round 8's +// `filter` input description), which did not move from `488-492`; and +// `objectql.ts` (+218/-125: objectui#6152 rounds 7 to 12, objectui#11880 item 5 +// and the 17.7.0 moves) MOVED the member `4754` -> `4838` byte-identical, still +// inside `ObjectKanbanSchema`. At `a58626c88`, re-read there 2026-10-06: // `ObjectKanban.tsx` changed (+65/-2, objectui#11629: each column header totals // the view's `summarizeField`), which MOVED the `$top` read `752` -> `762` and // the default `:97` -> `:98`, both byte-identical; `plugin-kanban.mdx` gained @@ -3816,7 +3835,7 @@ describe('object-* block props schemas — declared, so the props gate has a sch // `OBJECT_KANBAN_DATA_SOURCE`, ⚠️ `KanbanSchema` is RETIRED at this pin and // `plugin-kanban/src/types.ts` declares the member no more — the published // twin is `ObjectKanbanSchema`, declaring `limit?: number` at -// `packages/types/src/objectql.ts:4754` — and `content/docs/plugins/plugin-kanban.mdx` +// `packages/types/src/objectql.ts:4838` — and `content/docs/plugins/plugin-kanban.mdx` // teaches `limit: 250` with a Properties row. The strict map refused the key by // name — the same `unrecognized_keys` verdict as the `bogusProp` control — so an // author following the published docs wrote a node the save gate rejected. @@ -3878,7 +3897,12 @@ describe('ObjectKanbanPropsSchema limit — the row cap four objectui faces alre // since retired that block, objectui#8257). Unlike `limit` above — a key four // objectui faces already implemented, so the spec was the half that was wrong // — `quickAdd` was FORWARDED and never read: at the pin this repo builds -// against (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: +// against (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: +// `KanbanBoardCore.tsx`, `ObjectKanban.tsx` and `KanbanImpl.tsx` are +// byte-identical across the hop from `a58626c88` (`git diff --quiet`), so +// `:78`, `:111-112`, the spread `:1731` and the gate `:668` / `:681` did not +// move, and the counts re-read the same, 2 / 2 / 11. At `a58626c88`, re-read +// there 2026-10-06: // `KanbanBoardCore.tsx` is byte-identical (`git diff --quiet`), so `:78` and // `:111-112` did not move; `ObjectKanban.tsx` (+65/-2) and `KanbanImpl.tsx` // (+48/-1) changed for objectui#11629 (each column header totals the view's @@ -4051,7 +4075,10 @@ describe('ObjectKanbanPropsSchema quickAdd is retired', () => { // #9881 and commit 60e0f900a recorded the accordion and tab items; these two close the set. // // The button record re-measured at the pin this repo builds against — -// `.objectui-sha` = `a58626c88`, re-read there 2026-10-06: +// `.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: +// every objectui file this record cites is byte-identical across the hop from +// `a58626c88` (`git diff --quiet`), so every anchor held unmoved. At +// `a58626c88`, re-read there 2026-10-06: // every objectui file this record cites is byte-identical across the hop from // `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. // At `0abd4f9f8`, re-read there 2026-10-05: @@ -4222,7 +4249,14 @@ describe('ObjectMetricPropsSchema icon liveness', () => { // // The acceptance the card names, pinned: each row's KEY SET is the one the // renderer's read points support at the pin this repo builds against -// (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: +// (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: +// `ObjectGantt.tsx`, `ObjectTree.tsx` and `record-source.ts` are byte-identical +// across the hop off `a58626c88` (`git diff --quiet`), so every anchor in them +// held unmoved, the tree's three reads at `:714`, `:945` and `:1135`; +// `ObjectMap.tsx` +85/-4 changed for objectui#11819 (without WebGL2 the map +// lists its records instead of crashing), none of it on a read, and the set of +// `schema.*` keys each renderer reads is the same at both pins. At `a58626c88`, +// re-read there 2026-10-06: // `ObjectMap.tsx`, `ObjectGantt.tsx` and `record-source.ts` are byte-identical // across the hop off `0abd4f9f8` (`git diff --quiet`), so every anchor in them // held unmoved; `ObjectTree.tsx` +81/-3 changed for objectui#11686 (a tree cell diff --git a/packages/spec/src/ui/component.zod.ts b/packages/spec/src/ui/component.zod.ts index 0e8ed804c3d..da77709a098 100644 --- a/packages/spec/src/ui/component.zod.ts +++ b/packages/spec/src/ui/component.zod.ts @@ -830,7 +830,13 @@ export const PageTabsProps = strictObject({ * false candidate a component over). * * The key is LIVE at the objectui pin this repo builds against - * (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `containers.tsx` changed across the hop from `a58626c88` (+92/-6, + * objectui#11811: a record action disabled by its predicate says why, in the + * `page:header` renderer), every hunk at `:1512` or below, so both anchors + * were re-READ in place and NEITHER moved, each byte-identical; + * `lib/lazy-icon.tsx` is byte-identical (`git diff --quiet`). At `a58626c88`, + * re-read there 2026-10-06: * every objectui file this record cites is byte-identical across the hop * from `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. * At `0abd4f9f8`, re-read there 2026-10-05: @@ -1055,7 +1061,18 @@ export const PageCardProps = strictObject({ * declarations identical. * * Each clause is read off the objectui pin this repo builds against - * (`.objectui-sha` = `a58626c88dc8`, re-read there 2026-10-06: + * (`.objectui-sha` = `f0268ad78485`, re-read there 2026-10-09: + * across the hop from `a58626c88dc8` `record-details.tsx`, + * `record-highlights.tsx` and the three `permissions` files are byte-identical + * (`git diff --quiet`), so NO anchor in those five moved; + * `record-related-list.tsx` (+62/-4: objectui#11768's author-facing + * action-refusal notice and objectui#11733's plural titles) and + * `record-quick-actions.tsx` (+55/-3: objectui#11811's disabled-reason text) + * changed above and below the gate without touching a cited line, so every anchor + * in those two MOVED with its cited text byte-identical, by 35 and by 9 — `393` + * -> `428`, `380` -> `415`, `326` -> `361`, `344` -> `379`, `393-401` -> + * `428-436`; `273` -> `282`, `262` -> `271`, `273-281` -> `282-290` — and each is + * cited below at this pin. At `a58626c88dc8`, re-read there 2026-10-06: * across the hop from `0abd4f9f8769` `record-highlights.tsx`, * `record-related-list.tsx`, `record-quick-actions.tsx` and the three * `permissions` files are byte-identical (`git diff --quiet`), so NO anchor in @@ -1122,22 +1139,22 @@ export const PageCardProps = strictObject({ * * 1. CAPABILITIES, NOT OBJECT ACTIONS. Every block gates through * `perms.hasCapabilities(required)` — `record-details.tsx:347`, - * `record-highlights.tsx:102`, `record-related-list.tsx:393`, - * `record-quick-actions.tsx:273` — and never `perms.can(objectName, …)`; + * `record-highlights.tsx:102`, `record-related-list.tsx:428`, + * `record-quick-actions.tsx:282` — and never `perms.can(objectName, …)`; * each renderer's docblock states the capability "is not object-scoped" * (`record-details.tsx:336`, `record-highlights.tsx:81`, - * `record-related-list.tsx:380`, `record-quick-actions.tsx:262`). `read` + * `record-related-list.tsx:415`, `record-quick-actions.tsx:271`). `read` * is looked up in the capability set like any other name. * 2. ALL OF THEM. `MePermissionsProvider.tsx:416` is * `required.every((p) => held.has(p))`. * 3. THE OUTCOME. Each block returns a `role="status"` "Insufficient * permissions to view …" notice instead of its content — * `record-details.tsx:347-355`, `record-highlights.tsx:160-173`, - * `record-related-list.tsx:393-401`, `record-quick-actions.tsx:273-281`. + * `record-related-list.tsx:428-436`, `record-quick-actions.tsx:282-290`. * Checks that already withhold the content run first on two of them (no * record bound, `record-details.tsx:291`; no object, - * `record-related-list.tsx:326`; the related object's read gate, - * `record-related-list.tsx:344`), which is why the text says "wherever it + * `record-related-list.tsx:361`; the related object's read gate, + * `record-related-list.tsx:379`), which is why the text says "wherever it * would otherwise render" rather than promising the notice unconditionally. * 4. PRESENTATION ONLY. The gate is renderer code: nothing in this repo's * server packages reads a page component's `requiredPermissions`. The data @@ -2370,7 +2387,13 @@ export const PageAccordionProps = strictObject({ * re-derive the same false candidate). * * The key is LIVE at the objectui pin this repo builds against - * (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `containers.tsx` changed across the hop from `a58626c88` (+92/-6, + * objectui#11811: a record action disabled by its predicate says why, in the + * `page:header` renderer), every hunk at `:1512` or below, so both anchors + * were re-READ in place and NEITHER moved, each byte-identical; + * `lib/lazy-icon.tsx` is byte-identical (`git diff --quiet`). At `a58626c88`, + * re-read there 2026-10-06: * every objectui file this record cites is byte-identical across the hop * from `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. * At `0abd4f9f8`, re-read there 2026-10-05: @@ -2717,7 +2740,10 @@ export const ElementButtonPropsSchema = lazySchema(() => strictObject({ * the button. * * The key is LIVE at the objectui pin this repo builds against - * (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * every objectui file this record cites is byte-identical across the hop from + * `a58626c88` (`git diff --quiet`), so every anchor held unmoved. At + * `a58626c88`, re-read there 2026-10-06: * every objectui file this record cites is byte-identical across the hop from * `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. * At `0abd4f9f8`, re-read there 2026-10-05: @@ -3206,7 +3232,38 @@ export const ElementTextInputPropsSchema = lazySchema(() => strictObject({ * had no row for — `action:button`, `action:group`, `action:menu`, * `action:icon`, `element:definition-list`, `element:repeater` * (`core/src/registry/public-blocks.ts:117-122` at the pin this repo builds - * against, `.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * against, `.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `public-blocks.ts`, `auto-trigger.ts`, `static-params.ts` and `ui/button.tsx` + * are byte-identical across the hop from `a58626c88` (`git diff --quiet`), so + * their anchors held unmoved. All four `action-*.tsx` renderers changed for + * objectui#11839 (objectui `cef0eeec0`: a predicate-disabled control says why, + * through a reason hook in each renderer and a wrapper around the drawn control), + * and `action-button.tsx` also for objectui#11168 (objectui `f0496bdf1`: an + * `undoable` update of the record in scope carries that record as its Undo + * baseline, and the input is published), +95/-9, +22/-0, +23/-2 and +10/-1; so + * every action anchor MOVED with its cited line byte-identical — by 57 to 80 in + * `action-button.tsx`, by 1 to 22 in `action-icon.tsx`, by 6 to 21 in + * `action-group.tsx` and by 1 to 9 in `action-menu.tsx` (the `objectName` + * forwards `318` -> `389`, `211` -> `218`, `373` -> `394`, `320` -> `329`) — + * except where objectui rewrote a line around the same read, each range re-read: + * the button's `params` statement (`180-183` -> `247-254`, now wrapped in + * `withUndoBaseline`), and the members' drawn label (a `` became + * `DisabledReasonMenuLabel`, still `action.label || action.name`) in the group's + * dropdown item (`205-243` -> `219-264`) and the menu item (`108-147` -> + * `109-156`), the group's inline member growing `114-171` -> `120-184`. Two row + * sentences turned false and are rewritten where they stand: `action:button` now + * publishes and delivers `undoable`, and `action:icon` reads `label` six times. + * `basic/data-list.tsx` changed for objectui#11880's repeater half (objectui + * `aaba8655a`, +99/-16): every `element:definition-list` anchor MOVED by 10 with + * its text byte-identical; the repeater's display anchors MOVED by 19 to 83, and + * its query reads were rewritten to take the node-level `dataSource` binding + * first, so the row's "NOT read at the pin" sentence is false at this pin and is + * rewritten there. `data-objectstack/src/index.ts` (+51/-9, objectui#11699) moved + * the `translateFilterArray` arm `5000-5011` -> `5042-5053` and left + * `serializeOrderBy` (`868-894`) unmoved; `previews/block-config.ts` (+33/-13, + * objectui#11880's designer rows and the `@objectstack/*` 17.7.0 moves) moved the + * `columns` control `320` -> `335`. Each moved anchor is cited below at this pin. + * At `a58626c88`, re-read there 2026-10-06: * `public-blocks.ts`, `auto-trigger.ts`, `action-button.tsx`, * `action-icon.tsx`, `basic/data-list.tsx` and `ui/button.tsx` are * byte-identical across the hop from `0abd4f9f8` (`git diff --quiet`), so their @@ -3331,10 +3388,10 @@ export const ElementTextInputPropsSchema = lazySchema(() => strictObject({ * * `objectName` IS declared on `action:button` / `action:icon`: absent at the * first measurement, it is forwarded to the runner at the current pin - * (`action-button.tsx:318`, `action-icon.tsx:211`), and the console resolves + * (`action-button.tsx:389`, `action-icon.tsx:218`), and the console resolves * its dispatch target as `action.objectName || `. On * `action:group` / `action:menu` the forward is the MEMBER's - * (`action-group.tsx:373`, `action-menu.tsx:320`), so it rides each member + * (`action-group.tsx:394`, `action-menu.tsx:329`), so it rides each member * object and the container rows gain no key. */ @@ -3413,28 +3470,28 @@ const ACTION_NODE_GUIDANCE = { * runner (`components/src/renderers/action/action-button.tsx` at the pin). * Read points, per key: * - * - `name` — `:123` (the visibility-diagnostic label, `schema.name ?? - * schema.label`) and `:216` (forwarded). OPTIONAL, as it is read: an inline + * - `name` — `:180` (the visibility-diagnostic label, `schema.name ?? + * schema.label`) and `:287` (forwarded). OPTIONAL, as it is read: an inline * page button is not a registered object action, and the runner takes a * nameless action on its `type` leg. `UIActionSchema` declares it required; * the read does not. - * - `label` — `:394`, placed as a React child (so a literal string: an inline + * - `label` — `:468`, placed as a React child (so a literal string: an inline * locale map is not resolved on this path; the translation bundle's - * `components..label` is the localization channel); also `:123`, `:220`. - * - `icon` — `:138`, through the shared `resolveIcon`. - * - `actionType` — `:215`, forwarded as the runner's `type`. - * - `variant` / `size` — `:141` / `:142`: `primary` → the primitive's + * `components..label` is the localization channel); also `:180`, `:291`. + * - `icon` — `:202`, through the shared `resolveIcon`. + * - `actionType` — `:286`, forwarded as the runner's `type`. + * - `variant` / `size` — `:205` / `:206`: `primary` → the primitive's * `default` and `md` → `default`, everything else handed to `Button` as-is. - * - `visible` / `disabled` — `:121` + `:346` / `:134` + `:382`, evaluated + * - `visible` / `disabled` — `:178` + `:417` / `:191` + `:453`, evaluated * against the row the host binds (`usePredicateRecordContext`). - * - `params` — `:180-183`. An array is the input list, forwarded as + * - `params` — `:247-254`. An array is the input list, forwarded as * `actionParams`; the static values are read off `properties.params` * itself (`readStaticParamValues`, `static-params.ts:98-108`). On a page * node the two are one key: this row IS `properties`, and `SchemaRenderer`'s * hoist makes `schema.params` the same object, so an array here is the input * list and an object is the static values. (A node-level object `params` * outside `properties` is ignored with a development warning.) - * - Forwarded to the runner (`action-button.tsx:215-318` first line + * - Forwarded to the runner (`action-button.tsx:286-389` first line * `type: schema.actionType,`): `description`, `target`, `openIn`, * `method`, `bodyExtra`, `bodyShape`, `operation`, `patch`, * `confirmText`, `successMessage`, `errorMessage`, `refreshAfter`, @@ -3442,11 +3499,11 @@ const ACTION_NODE_GUIDANCE = { * `onSuccess`, `objectName` — and, since objectui#11344, `outcomeMessages`. * * ⚠️ New at this pin, and NOT a key of this row: objectui#11344 forwards - * `outcomeMessages` (`:261`), the success copy per handler outcome that + * `outcomeMessages` (`:332`), the success copy per handler outcome that * `ActionSchema` declares, because an `action:bar` member is spread onto an * `action:button` node whole and a registered action's map would otherwise * never reach the success toast. objectui leaves the input unpublished - * (`:422-426`) until this row declares it. So the key reaches the renderer + * (`:502-506`) until this row declares it. So the key reaches the renderer * only on that member path; written on an `action:button` node, this strict * row refuses it at save. The row stays as measured from the block's own * authorable reads: declaring the key is a contract decision, not a pin @@ -3459,16 +3516,20 @@ const ACTION_NODE_GUIDANCE = { * `target` (`ACTION_NODE_ALIASES` above) — one concept, one spelling, one * verdict on the action and on the block that runs it. * - * The registration's `inputs` (`:427-572`) publish twenty-seven of the - * twenty-nine keys the renderer forwards or reads since objectui#11168 slice 1 - * (at `db11afd49` they published seven, `:395-416`), and since slice 2 the + * The registration's `inputs` (`:507-658`) publish twenty-eight of the + * twenty-nine keys the renderer forwards or reads at this pin — twenty-seven + * since objectui#11168 slice 1, and `undoable` since objectui `f0496bdf1` (at + * `db11afd49` they published seven, `:395-416`) — and since slice 2 the * `size` input publishes the same five values this row declares (`default`, - * `sm`, `md`, `lg`, `icon`); the two left unpublished are `endpoint` (refused - * here, above) and `undoable`, each still forwarded (`:215-318`), on - * objectui's measurement that the console's own `api` handler reads `target` - * and never `endpoint`, and that the runner offers Undo only with a host row - * stash this block never writes. It also publishes `className`, which is read - * but is a node key. + * `sm`, `md`, `lg`, `icon`); the one left unpublished is `endpoint` (refused + * here, above), still forwarded (`:286-389`), on objectui's measurement that + * the console's own `api` handler reads `target` and never `endpoint`. + * `undoable` is published because the block now writes the row stash the + * runner's Undo needs: an `undoable` `operation: 'update'` of the record in + * scope carries that record as its Undo baseline (`withUndoBaseline`, + * `:72-81`, called at `:247-251`; objectui#11168, ruling B on objectui#11754), + * where at `a58626c88` it wrote none. It also publishes `className`, which is + * read but is a node key. */ export const ActionButtonPropsSchema = lazySchema(() => strictObject({ surface: 'this `action:button`', @@ -3534,27 +3595,30 @@ export type ActionButtonPropsParsed = z.infer; * (`components/src/renderers/action/action-icon.tsx` at the pin). The same * runner path as `action:button`, measured separately because the two differ: * - * - `size` is NOT read — `:120` pins the primitive's `icon` size — so it is + * - `size` is NOT read — `:127` pins the primitive's `icon` size — so it is * not declared (the registration does not publish it either). - * - `undoable` and `recordIdField` are NOT forwarded (`:147-212` lists the + * - `undoable` and `recordIdField` are NOT forwarded (`:154-219` lists the * rest of `action:button`'s forward and not these two), so not declared. - * - `label` is read five times at this pin (four at `db11afd49`): - * `:109` (the visibility-diagnostic label, `schema.name ?? schema.label`, - * new with objectui#11212's fail-closed `visible`), `:165` (forwarded), - * `:281` (`aria-label`, falling back to `name`), `:290` (its first letter - * when no icon resolves) and `:296` / `:302` (the tooltip). `description` - * is the tooltip's fallback (`:302`) as well as forwarded (`:166`). - * - `visible` / `disabled` — `:107` + `:245` / `:115` + `:274`; `visible` + * - `label` is read six times at this pin (five at `a58626c88`, four at + * `db11afd49`): `:110` (the visibility-diagnostic label, `schema.name ?? + * schema.label`, new with objectui#11212's fail-closed `visible`), `:172` + * (forwarded), `:288` (`aria-label`, falling back to `name`), `:301` (its + * first letter when no icon resolves), `:311` (the heading of the + * disabled-reason tooltip a predicate-disabled icon is wrapped in, new with + * objectui#11839, objectui `cef0eeec0`) and `:318` / `:324` (the tooltip). + * `description` is the fallback of both tooltips (`:311`, `:324`) as well as + * forwarded (`:173`). + * - `visible` / `disabled` — `:108` + `:252` / `:116` + `:281`; `visible` * fails CLOSED on a faulting predicate since objectui#11212, as on - * `action:button`. `variant` — `:119`, `primary` mapped to `default`, + * `action:button`. `variant` — `:126`, `primary` mapped to `default`, * renderer default `ghost`. - * - `params` — `:143-146`, routed exactly as on `action:button`. - * - Forwarded (`action-icon.tsx:160-211` first line + * - `params` — `:150-153`, routed exactly as on `action:button`. + * - Forwarded (`action-icon.tsx:167-218` first line * `type: schema.actionType,`): `actionType`, `name`, `target`, `openIn`, * `method`, `bodyExtra`, `bodyShape`, `operation`, `patch`, * `confirmText`, `successMessage`, `errorMessage`, `refreshAfter`, * `locations`, `toast`, `resultDialog`, `onSuccess`, `objectName`. - * - `outcomeMessages` is forwarded too since objectui#11344 (`:189`) and NOT + * - `outcomeMessages` is forwarded too since objectui#11344 (`:196`) and NOT * declared, for `action:button`'s reason: it is an `ActionSchema` key that * reaches this renderer on the `action:bar` member path, and objectui * leaves its input unpublished until the row declares it. @@ -3698,9 +3762,12 @@ export type ActionIconPropsParsed = z.infer; * * [#21855] The rows' value ratchet for this one member, with its own * inventory. A member's `params` is its `ActionParam[]` input list: both - * containers forward an array as `actionParams` (group `:325-327`, menu - * `:261-263`, re-read at the pin this repo builds against, `.objectui-sha` = - * `a58626c88`). Any + * containers forward an array as `actionParams` (group `:346-348`, menu + * `:270-272`, re-read at the pin this repo builds against, `.objectui-sha` = + * `f0268ad78`, 2026-10-09: both MOVED with their text byte-identical, by 21 + * and by 9, from `a58626c88`'s `:325-327` and `:261-263`, for objectui#11839's + * disabled-reason wrapper above them; `static-params.ts` is byte-identical). + * Any * other value goes through `readActionEntryParamValues` * (`static-params.ts:164-174`), which returns it unchanged for a `type: 'api'` * member — the inline-action payload window (#5777), as the request payload @@ -3881,37 +3948,37 @@ const actionMenuMember = () => (actionMenuMemberOnce ??= buildActionMenuMember() * (`components/src/renderers/action/action-group.tsx` at the pin). Read * points, per key: * - * - `actions` — `:300`, then filtered by `location` through `actionRendersAt` - * (`:301`); members are read at `:114-171` (inline), `:205-243` (dropdown), - * both through the shared `useMemberVisible` for `visible` (`:81-86`), and - * forwarded at `action-group.tsx:325-374` first line + * - `actions` — `:321`, then filtered by `location` through `actionRendersAt` + * (`:322`); members are read at `:120-184` (inline), `:219-264` (dropdown), + * both through the shared `useMemberVisible` for `visible` (`:87-92`), and + * forwarded at `action-group.tsx:346-395` first line * `const paramsPayload: ActionDef = Array.isArray(action.params)` (`params` - * `:325-327`, no longer joined by the member's own `properties.params` - * since objectui#11638; `objectName` `:373`; the member's + * `:346-348`, no longer joined by the member's own `properties.params` + * since objectui#11638; `objectName` `:394`; the member's * `outcomeMessages` too since objectui#11344). - * - `display` — `:396`, `inline` unless it is `dropdown`. - * - `label` / `icon` — `:416` / `:400`: the DROPDOWN trigger's text (default + * - `display` — `:417`, `inline` unless it is `dropdown`. + * - `label` / `icon` — `:437` / `:421`: the DROPDOWN trigger's text (default * `Actions`) and icon. Inline mode renders neither. - * - `variant` — `:406` (dropdown trigger) and `:448` (each inline member's + * - `variant` — `:427` (dropdown trigger) and `:469` (each inline member's * fallback); no `primary` mapping at group level, so the primitive's six. - * - `size` — `:407` maps `md` → `default` for the dropdown trigger, but `:449` - * hands the group size to each inline member raw, and `:124` maps only a + * - `size` — `:428` maps `md` → `default` for the dropdown trigger, but `:470` + * hands the group size to each inline member raw, and `:136` maps only a * member's OWN `md`. So `md` renders only in dropdown mode, and in the * default inline mode reaches the Button primitive, which has no `md`. * Declared: the primitive's four sizes. (Since objectui#11168 the - * registration publishes those same four, `:479-520`; through `db11afd49` + * registration publishes those same four, `:500-541`; through `db11afd49` * it published `sm` / `md` / `lg`. A stored `md` is still mapped in * dropdown mode only, which objectui records as a back-compat read.) - * - `visible` — `:287` + `:393`; `:287` fails CLOSED on a faulting predicate - * since objectui#11212. `:393` tests the raw value's truthiness, so a + * - `visible` — `:308` + `:414`; `:308` fails CLOSED on a faulting predicate + * since objectui#11212. `:414` tests the raw value's truthiness, so a * literal `false` is honoured by `SchemaRenderer`'s node gate, which also * evaluates the hoisted value, rather than by this check. * * ⚠️ New at this pin, and NOT a key of this row: objectui#11182 has the group - * consume the host's EVALUATED `disabled` verdict by name (`:274`), the one + * consume the host's EVALUATED `disabled` verdict by name (`:295`), the one * `SchemaRenderer`'s generic enablement gate computes from a hoisted - * `disabled` on any node, and apply it to every inline member (`:159`) or to - * the dropdown trigger (`:410`). So a `properties.disabled` on this block now + * `disabled` on any node, and apply it to every inline member (`:171`) or to + * the dropdown trigger (`:431`). So a `properties.disabled` on this block now * greys it out at render while this strict row refuses the key at save. The * row stays as measured from the block's own reads: declaring the key is a * contract decision, not a pin re-measure. @@ -3920,7 +3987,7 @@ const actionMenuMember = () => (actionMenuMemberOnce ??= buildActionMenuMember() * and inline mode only spreads it onto the wrapping `
` as a DOM * attribute. The registration published it through `db11afd49` (`:415` * there); objectui#11168 stopped publishing it because nothing reads it and - * this row refuses it (`action-group.tsx:40-42`). Refused with a + * this row refuses it (`action-group.tsx:46-48`). Refused with a * prescription, the `page:accordion` item `value` precedent: an author * copying an older designer's output is told what happened rather than * merely refused. @@ -3966,27 +4033,27 @@ export type ActionGroupPropsParsed = z.infer; * (`components/src/renderers/action/action-menu.tsx` at the pin). Read * points, per key: * - * - `actions` — `:335`; members are read at `:80`, `:108-147` and `:401`, run - * through `ActionAutoTrigger` (`:356-363`), and forwarded at - * `action-menu.tsx:261-321` first line + * - `actions` — `:344`; members are read at `:81`, `:109-156` and `:410`, run + * through `ActionAutoTrigger` (`:365-372`), and forwarded at + * `action-menu.tsx:270-330` first line * `const paramsPayload: ActionDef = Array.isArray(action.params)` (`params` - * `:261-263`, no longer joined by the member's own `properties.params` - * since objectui#11638; `objectName` `:320`; the member's + * `:270-272`, no longer joined by the member's own `properties.params` + * since objectui#11638; `objectName` `:329`; the member's * `outcomeMessages` too since objectui#11344). - * - `label` — `:382` (`aria-label`, default: the translated "More actions") - * and `:391-392` (trigger text; icon-only when omitted). - * - `icon` — `:237`, default the `MoreHorizontal` glyph. - * - `variant` / `size` — `:238` / `:239`, handed to the Button primitive + * - `label` — `:391` (`aria-label`, default: the translated "More actions") + * and `:400-401` (trigger text; icon-only when omitted). + * - `icon` — `:246`, default the `MoreHorizontal` glyph. + * - `variant` / `size` — `:247` / `:248`, handed to the Button primitive * unmapped (defaults `ghost` / `icon`): no `primary`, no `md` here. - * - `visible` — `:232` + `:329`, fail-closed; the same truthiness note as + * - `visible` — `:241` + `:338`, fail-closed; the same truthiness note as * `action:group`'s applies to a literal `false`. * - * The registration's `inputs` (`:428-456`) publish `label`, `icon`, + * The registration's `inputs` (`:437-465`) publish `label`, `icon`, * `actions`, `variant`, `size`, `visible` and `className` since objectui#11168 * slice 1, every key this row declares; through `db11afd49` (`:410-419` * there) `size` and `visible` were read and unpublished. ⚠️ As on * `action:group`, objectui#11182 has the trigger consume the host's evaluated - * `disabled` verdict (`:219`, `:381`) — at `db11afd49` it already reached the + * `disabled` verdict (`:228`, `:390`) — at `db11afd49` it already reached the * trigger through the `...rest` spread — so a `properties.disabled` here greys * the trigger out while this row refuses it; recorded, not declared. */ @@ -4021,21 +4088,21 @@ export type ActionMenuPropsParsed = z.infer; /** * `element:definition-list` — a compact key/value `
` * (`components/src/renderers/basic/data-list.tsx` at the pin). Props are read - * through `readProps` (`data-list.tsx:42-47` first line + * through `readProps` (`data-list.tsx:52-57` first line * `const props = readProps<{`, `properties` first). Read points: `items` - * (`:48`), `columns` (`:49`), `inline` (`:63`), and per item `term` (`:66`) and - * `description` (`:68`). + * (`:58`), `columns` (`:59`), `inline` (`:73`), and per item `term` (`:76`) and + * `description` (`:78`). * * - `columns` is compared as the NUMBER `2` (`props.columns === 2`); any other * value renders one column. Declared as the literal pair `1 | 2`, which is * what the Studio designer writes (a `number` control, - * `previews/block-config.ts:320`). The registration's enum published the + * `previews/block-config.ts:335`). The registration's enum published the * STRINGS `'1'` / `'2'` until objectui#11168 slice 2, and the string `'2'` * renders one column; it now publishes the numbers `1` and `2` - * (`data-list.tsx:99-105`), as this row declares. + * (`data-list.tsx:109-115`), as this row declares. * - `items` is optional, as it is read: absent and empty both render the - * renderer's own "No details" state (`:51-53`). The registration marked it - * required until objectui#11168 slice 2, and no longer does (`:91-97`). + * renderer's own "No details" state (`:61-63`). The registration marked it + * required until objectui#11168 slice 2, and no longer does (`:101-107`). * - An item is strict. `term` is required — it is the row's only label, placed * as a React child, so a literal string — and `description` takes any value * (`toText` prints objects as JSON and an absent one as an em dash). The @@ -4084,39 +4151,54 @@ export type ElementDefinitionListProps = z.input strictObject({ surface: 'this `element:repeater`', @@ -4338,7 +4420,13 @@ const GridOperationsSchema = lazySchema(() => strictObject({ * control `schema.editable` in `ObjectGrid.tsx`. It was declared ahead of its * reader on purpose (the BUILD objectui#11068 chose), and its describe carried * the `[EXPERIMENTAL — not enforced]` marker that said so. Re-measured at the - * pin this repo builds against (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * pin this repo builds against (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `ObjectGrid.tsx` (+85/-27: objectui#11880 item 5, objectui#6152 rounds 7 and + * 10, objectui#11817, objectui#11809, objectui#11689) and `data-table.tsx` + * (+434/-30: objectui#11816, objectui#11690, objectui#11682) changed across the + * hop from `a58626c88`; the read MOVED `5461` -> `5519` with its line + * byte-identical, and the same method still finds 15 hit lines against 3 for the + * control. At `a58626c88`, re-read there 2026-10-06: * `ObjectGrid.tsx` and `data-table.tsx` are byte-identical across the hop from * `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved, and the same * method still finds 15 hit lines against 3 for the control. @@ -4356,7 +4444,7 @@ const GridOperationsSchema = lazySchema(() => strictObject({ * `ab1879721`): the BUILD landed — objectui `154075ab1` (objectui#11068), inside * `89cad75d5570..ab1879721595` — and the grid reads the key. The same method * finds 0 hit lines at `89cad75d5570` and 15 at `ab1879721595`, at `2e818d0b51ec` and at this pin, against 3 for the - * control `schema.editable` in `ObjectGrid.tsx` at each: `ObjectGrid.tsx:5461` + * control `schema.editable` in `ObjectGrid.tsx` at each: `ObjectGrid.tsx:5519` * hands `schema.keyboardNavigation ?? inlineEditable` to the `data-table` it * renders, and `components/src/renderers/complex/data-table.tsx` acts on it. * So the marker is gone, as the member's record prescribed; see the member. @@ -4435,7 +4523,13 @@ export const ObjectGridPropsSchema = lazySchema(() => strictObject({ * same members, and objectui's grid follows this declaration. * * ⚠️ That gap is closed at the pin this repo builds against (`.objectui-sha` - * = `a58626c88`, re-read there 2026-10-06: + * = `f0268ad78`, re-read there 2026-10-09: + * `ObjectGrid.tsx` changed across the hop from `a58626c88` (+85/-27: + * objectui#11880 item 5, objectui#6152 rounds 7 and 10, objectui#11817, + * objectui#11809, objectui#11689), every hunk above both reads (the last at + * `:5383`), so both MOVED by 58 with their lines byte-identical: `6471-6472` + * -> `6529-6530`, `6488-6489` -> `6546-6547`. At `a58626c88`, re-read there + * 2026-10-06: * every objectui file this record cites is byte-identical across the hop from * `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. * At `0abd4f9f8`, re-read there 2026-10-05: @@ -4449,7 +4543,7 @@ export const ObjectGridPropsSchema = lazySchema(() => strictObject({ * `6158e4c93`) resolves both members against the display locale before they * reach `DataEmptyState` — * `resolveInlineI18nLabel(authoredEmptyState?.title, displayLocale)` and the - * same for `message` (`ObjectGrid.tsx:6471-6472`, drawn at `:6488-6489`) — so + * same for `message` (`ObjectGrid.tsx:6529-6530`, drawn at `:6546-6547`) — so * both `I18nLabel` forms draw, and a locale map with no usable entry keeps * that member's default. At `89cad75d5570` the two still reached * `DataEmptyState` raw. @@ -4826,7 +4920,16 @@ export const ObjectGridPropsSchema = lazySchema(() => strictObject({ * `ComponentPropsMap` key. This record said to drop the marker in the change * that lands the BUILD at the pin, and it is dropped here. * - * Read at the pin this repo builds against (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * Read at the pin this repo builds against (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `ObjectGrid.tsx` (+85/-27: objectui#11880 item 5, objectui#6152 rounds 7 and + * 10, objectui#11817, objectui#11809, objectui#11689) and `data-table.tsx` + * (+434/-30: objectui#11816, objectui#11690, objectui#11682) changed across + * the hop from `a58626c88` around the reads without touching one, so every + * anchor MOVED with its line byte-identical — `5461` -> `5519`, `1815` -> + * `1824`; `787` -> `1018`, `2235` -> `2607`, `2700` -> `3101`, `1964` -> + * `2257`, `1990` -> `2283` — and no hunk lands in the arrow-key handling + * between `navigationTarget` and the end of `handleCellKeyDown`. At + * `a58626c88`, re-read there 2026-10-06: * every objectui file this record cites is byte-identical across the hop from * `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. * At `0abd4f9f8`, re-read there 2026-10-05: @@ -4841,17 +4944,17 @@ export const ObjectGridPropsSchema = lazySchema(() => strictObject({ * and `data-table.tsx` were * byte-identical across the hop from `ab1879721`, where they were measured * 2026-10-03; the BUILD is objectui `154075ab1`, objectui#11068): - * `plugin-grid/src/ObjectGrid.tsx:5461` hands the data table + * `plugin-grid/src/ObjectGrid.tsx:5519` hands the data table * `keyboardNavigation: schema.keyboardNavigation ?? inlineEditable`, where - * `inlineEditable` (`:1815`) is the authored `editable` AND the viewer's + * `inlineEditable` (`:1824`) is the authored `editable` AND the viewer's * write verdict — so an absent key follows whether the grid RENDERS * editable, `true` turns the navigation on for a read-only grid, and `false` * turns it off on an editable one. `components/src/renderers/complex/data-table.tsx` - * (`keyboardNavigation = false` by default, `:787`) then gives the table - * `role="grid"` (`:2235`) and makes the data cells one roving Tab stop - * (`tabIndex` 0 on one cell and -1 on the rest, `:2700`) that the arrow + * (`keyboardNavigation = false` by default, `:1018`) then gives the table + * `role="grid"` (`:2607`) and makes the data cells one roving Tab stop + * (`tabIndex` 0 on one cell and -1 on the rest, `:3101`) that the arrow * keys, Home / End and Ctrl+Home / Ctrl+End move (`navigationTarget`, - * `:1964`; `handleCellKeyDown`, `:1990`). A widget a cell renders keeps its + * `:2257`; `handleCellKeyDown`, `:2283`). A widget a cell renders keeps its * own Tab stop. Off, every data cell is its own Tab stop, as before. */ keyboardNavigation: z.boolean().optional() @@ -5227,7 +5330,10 @@ export const ObjectMetricPropsSchema = lazySchema(() => strictObject({ * same record for the metric tile. * * The key is LIVE at the objectui pin this repo builds against - * (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * every objectui file this record cites is byte-identical across the hop from + * `a58626c88` (`git diff --quiet`), so every anchor held unmoved. At + * `a58626c88`, re-read there 2026-10-06: * `plugin-dashboard/src/index.tsx`, `ObjectMetricWidget.tsx` and * `lazy-icon.tsx` are byte-identical to `0abd4f9f8` (`git diff --quiet`), so * their anchors hold unmoved; `MetricWidget.tsx` (+19/-7) and @@ -5472,7 +5578,10 @@ const ObjectKanbanLaneSchema = lazySchema(() => strictObject({ * DESIGNER's spelling with * zero read points (#7973 class) — aliased to the `groupBy` the board reads. * `limit` (#16503) was measured later, at the pin this repo builds against - * (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `ObjectKanban.tsx` is byte-identical across the hop from `a58626c88` + * (`git diff --quiet`), so the anchor did not move and was re-read in place. At + * `a58626c88`, re-read there 2026-10-06: * `ObjectKanban.tsx` changed across the hop from `0abd4f9f8`, +65/-2 * (objectui#11629: each column header totals the view's `summarizeField`), so * the anchor was re-READ and MOVED `752` -> `762` with its text byte-identical. @@ -5576,7 +5685,20 @@ export const ObjectKanbanPropsSchema = lazySchema(() => strictObject({ * Row cap (#16503 — the spec half of objectui#8172; decision batch #68, * 2026-09-07, option A: the contract declares the capability that already * ships, is documented and is in use). Measured at the objectui pin this - * repo builds against (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * repo builds against (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `ObjectKanban.tsx`, `plugin-kanban/src/types.ts` (still no row-cap member), + * `element-data-source.ts`, `ElementDataSourceGate.tsx` and + * `plugin-kanban.mdx` are byte-identical to `a58626c88` (`git diff --quiet`), + * so the query `755-765`, the default `:98`, the `queryFilter` resolution + * `:624-625`, the import `:10`, `:268-272`, `:218-220` and `:437-456` did not + * move, and the `limit` row and the `limit: 250` snippet did not change; + * `plugin-kanban/src/index.tsx` changed only below the mapping (+3/-3: a + * comment re-cited to 17.7.0, and objectui#6152 round 8's `filter` input + * description), which did not move from `488-492`; and `objectql.ts` + * (+218/-125: objectui#6152 rounds 7 to 12, objectui#11880 item 5 and the + * 17.7.0 moves) MOVED the member `4754` -> `4838` byte-identical, still + * inside `ObjectKanbanSchema`. + * At `a58626c88`, re-read there 2026-10-06: * `plugin-kanban/src/types.ts` (still no row-cap member), * `plugin-kanban/src/index.tsx`, `element-data-source.ts`, * `ElementDataSourceGate.tsx` and `objectql.ts` are byte-identical to @@ -5733,7 +5855,7 @@ export const ObjectKanbanPropsSchema = lazySchema(() => strictObject({ * through is `ObjectKanbanSchema` — ⚠️ `KanbanSchema` was RETIRED on this hop * (maintainer ruling 2026-09-09) and `plugin-kanban/src/types.ts` no longer * declares the member at all — imported at `ObjectKanban.tsx:10` and - * declaring `limit?: number` at `packages/types/src/objectql.ts:4754`, + * declaring `limit?: number` at `packages/types/src/objectql.ts:4838`, * and `content/docs/plugins/plugin-kanban.mdx` * teaches it with a typed snippet (`limit: 250`) plus a Properties row. So * an author following the published docs wrote a node the save gate @@ -5828,7 +5950,15 @@ export const ObjectKanbanPropsSchema = lazySchema(() => strictObject({ * quick-add control and no block a document can name offers one either). * * Measured at the objectui pin this repo builds against - * (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `KanbanBoardCore.tsx`, `ObjectKanban.tsx` and `KanbanImpl.tsx` are + * byte-identical across the hop from `a58626c88` (`git diff --quiet`), so + * `:78`, `:668` and `:681` did not move; `plugin-kanban/src/index.tsx` changed + * only at `:552` and below (+3/-3: a comment re-cited to 17.7.0, and + * objectui#6152 round 8's `filter` input description), so the pass-through did + * not move from `345-346`; `ObjectKanban.tsx` still names `quickAdd` and + * `onQuickAdd` 2 times each against 11 for `onCardClick`, and objectui still + * registers no `kanban-ui` block. At `a58626c88`, re-read there 2026-10-06: * `KanbanBoardCore.tsx` and `plugin-kanban/src/index.tsx` are byte-identical * across the hop from `0abd4f9f8` (`git diff --quiet`), so `:345-346` did not * move; `ObjectKanban.tsx` (+65/-2) and `KanbanImpl.tsx` (+48/-1) changed for @@ -6012,6 +6142,9 @@ export const ObjectKanbanPropsSchema = lazySchema(() => strictObject({ * element schemas). * * Measured at the pin this repo builds against (`.objectui-sha` = + * `f0268ad78`, re-read there 2026-10-09: + * every objectui file this record cites is byte-identical across the hop from + * `a58626c88` (`git diff --quiet`), so every anchor held unmoved. At * `a58626c88`, re-read there 2026-10-06: * `useNavigationOverlay.ts` is byte-identical to `0abd4f9f8` (`git diff * --quiet`), and `ObjectKanban.tsx` changed above and between the anchors @@ -6221,7 +6354,14 @@ export const ObjectCalendarPropsSchema = lazySchema(() => strictObject({ * `object-kanban`'s above. * * Measured at the pin this repo builds against (`.objectui-sha` = - * `a58626c88`, re-read there 2026-10-06: + * `f0268ad78`, re-read there 2026-10-09: + * `ObjectCalendar.tsx` changed across the hop from `a58626c88` in one comment + * line only, line for line (`:1250`, objectui `c0862c1cc` re-citing the + * installed spec as 17.7.0), and `useNavigationOverlay.ts` is byte-identical, + * so every anchor held unmoved and was re-read in place: the read `1018`, the + * hand-off `1020-1021`, the event click `1413`, the overlay render `1333` and + * its `NavigationOverlay` `1346-1359`. At `a58626c88`, re-read there + * 2026-10-06: * every objectui file this record cites is byte-identical across the hop from * `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. * At `0abd4f9f8`, re-read there 2026-10-05: @@ -7423,7 +7563,16 @@ const OBJECT_MAP_FLAT_CONFIG_GUIDANCE: readonly KeySetGuidance[] = [ /** * `object-map` (objectui `plugin-map/src/ObjectMap.tsx` plus the registry shell * `plugin-map/src/index.tsx`, read at the pin this repo builds against — - * `.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * `.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `ObjectMap.tsx` changed across the hop from `a58626c88` (+85/-4, + * objectui#11819, objectui `fbaa79d19`: without WebGL2 the map lists its records + * instead of crashing — a WebGL2 probe above every reader and a list fallback at + * the render), no hunk touching a cited line, so every anchor in it MOVED with + * its cited text byte-identical — by 34 above the first render hunk (at + * `a58626c88`'s `:653`), and by 38 to 46 below it (`:186-187` -> `:220-221`, + * `:1205` -> `:1251`); `index.tsx` and + * `core/src/utils/record-source.ts` are byte-identical (`git diff --quiet`), so + * their anchors held unmoved. At `a58626c88`, re-read there 2026-10-06: * every objectui file this record cites is byte-identical across the hop from * `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. * At `0abd4f9f8`, re-read there 2026-10-05: @@ -7509,11 +7658,11 @@ const OBJECT_MAP_FLAT_CONFIG_GUIDANCE: readonly KeySetGuidance[] = [ * At `87af769e9` (2026-09-22) none was carried from `53ded82bf` either, and * one of them is a read that no longer exists rather than a number that * moved.) - * Read points per key: `data` (`:186-187` — `getDataConfig` is now that one + * Read points per key: `data` (`:220-221` — `getDataConfig` is now that one * `resolveRecordSourceConfig(schema, 'view-data')` call, rung 1 of the ruled * record-source ladder, `core/src/utils/record-source.ts:307`. ⚠️ The * array-shorthand head this record used to cite beside it is GONE, deleted on - * objectui#8348 — `:155-162` records the deletion and `:174-180` records the + * objectui#8348 — `:189-196` records the deletion and `:208-214` records the * carrier that used to survive it and no longer does: objectui#9571 stopped * `SchemaRenderer` spreading an authored `data` array onto object-arm blocks * as a React prop, so an authored array reaches this renderer neither through @@ -7522,27 +7671,27 @@ const OBJECT_MAP_FLAT_CONFIG_GUIDANCE: readonly KeySetGuidance[] = [ * it, reading an objectui docblock that was itself stale), * `staticData` (rung 2, * `record-source.ts:311`), `objectName` (rung 3, `record-source.ts:318`; also - * here at `:1190`, the `useNavigationOverlay` binding, and as a cache key at - * `:240`, `:243`, `:318` and `:364`. ⚠️ The dependency-key read this record + * here at `:1228`, the `useNavigationOverlay` binding, and as a cache key at + * `:274`, `:277`, `:352` and `:398`. ⚠️ The dependency-key read this record * cited at `:965` is GONE at this pin: objectui#10664 replaced the metadata - * effect whose dependency list it was with `useSettledSchema` (`:802-805`), - * keyed on the ladder's `recordSourceObjectName` (`:776`), so the object is + * effect whose dependency list it was with `useSettledSchema` (`:840-843`), + * keyed on the ladder's `recordSourceObjectName` (`:814`), so the object is * still read there, only no longer through that list), - * `filter` (`:864`, read once through `useResolvedFilter`, which resolves its - * context tokens — objectui#10666 — and holds the result, which `:958` and - * `:1037` hand to `$filter` on the inline and the object fetch respectively; + * `filter` (`:902`, read once through `useResolvedFilter`, which resolves its + * context tokens — objectui#10666 — and holds the result, which `:996` and + * `:1075` hand to `$filter` on the inline and the object fetch respectively; * at `f8a9d0fb0` both handed `schema.filter` verbatim), - * `sort` (`:959` and `:1038`, through the shared `convertSortToQueryParams` sink - * to `$orderby`), `map` (`:412` — `getMapConfig` branch 1, the author face and + * `sort` (`:997` and `:1076`, through the shared `convertSortToQueryParams` sink + * to `$orderby`), `map` (`:446` — `getMapConfig` branch 1, the author face and * the registration's declared `{ name: 'map', type: 'object' }` input, * `plugin-map/src/index.tsx:116`; the second copy this record cited at `:78` * belonged to the bare `map` registration, retired on objectui#10393, so * `object-map` is now the one registration declaring it), `mapStyle` - * (`:407`, `schema.mapStyle || schema.map?.style`, read ahead of `map.style` + * (`:441`, `schema.mapStyle || schema.map?.style`, read ahead of `map.style` * on every return path since objectui#11168 slice 3 — through `31971ff1e` the * declared-block path returned `config.style || style`, so a map writing - * both drew `map.style`), `navigation` (`:1189`) and `enableClustering` - * (`:1205`). Since objectui#11168 slice 3 the registration also declares + * both drew `map.style`), `navigation` (`:1227`) and `enableClustering` + * (`:1251`). Since objectui#11168 slice 3 the registration also declares * `mapStyle`, `navigation` and `enableClustering` inputs * (`plugin-map/src/index.tsx:121-123`). * @@ -7551,7 +7700,7 @@ const OBJECT_MAP_FLAT_CONFIG_GUIDANCE: readonly KeySetGuidance[] = [ * - the flat `map`-config spellings — the ObjectView/ListView flatten product, * ruled an internal transport form (objectui#5018). They get * {@link OBJECT_MAP_FLAT_CONFIG_GUIDANCE}'s wrong-layer prescription. - * - `style`. `ObjectMap.tsx:315`, inside `warnOnTopLevelStyleUrl` (`:309`), + * - `style`. `ObjectMap.tsx:349`, inside `warnOnTopLevelStyleUrl` (`:343`), * reads it only to say it is NOT consumed as a map style (objectui#5017): * it is `BaseSchema.style`, the node's inline CSS * record, and `COMPONENT_NODE_KEYS` above already sends it back to the node. @@ -7561,11 +7710,11 @@ const OBJECT_MAP_FLAT_CONFIG_GUIDANCE: readonly KeySetGuidance[] = [ * * VALUE posture for `map`: {@link ListMapConfigSchema}, this repo's own block — * the later value ratchet the previous posture here deferred, taken now that the - * one-key gap is closed. `:415` validates the authored block against objectui's + * one-key gap is closed. `:449` validates the authored block against objectui's * `ObjectMapConfigSchema` and this block declares the same eight keys, `style` * included; until that declaration landed the door had to stay `z.unknown()`, * because pointing it at a schema missing `style` would have refused a value - * `getMapConfig` honours at `:407` (`schema.mapStyle || schema.map?.style`). + * `getMapConfig` honours at `:441` (`schema.mapStyle || schema.map?.style`). * `mapStyle` above is unaffected: it stays the component-level spelling read * FIRST, and is not a member of the config block. */ @@ -7603,7 +7752,13 @@ export const ObjectMapPropsSchema = lazySchema(() => strictObject({ * Base query filter — the `ViewFilterRule` ARRAY form, the one filter * orthography every `filter` door in this map shares (ui#6206-B reaching the * `object-*` family: #15449, decision batch #55, option A). Measured at the - * pin this repo builds against (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * pin this repo builds against (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `ObjectMap.tsx` changed above all three anchors (+85/-4, objectui#11819, + * objectui `fbaa79d19`: the WebGL2 probe and the list fallback), so each MOVED + * down 38 with its text byte-identical, `:864` -> `:902`, `:958` -> `:996` and + * `:1037` -> `:1075`; and `plugin-map/src/index.tsx` is byte-identical + * (`git diff --quiet`), so the `filter` input held unmoved at `:119`. At + * `a58626c88`, re-read there 2026-10-06: * every objectui file this record cites is byte-identical across the hop from * `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. * At `0abd4f9f8`, re-read there 2026-10-05: @@ -7648,8 +7803,8 @@ export const ObjectMapPropsSchema = lazySchema(() => strictObject({ * `schema.filter` verbatim. At `f8a9d0fb0`, byte-identical to `62597c588` * and re-READ there 2026-09-23, both anchors had MOVED 19 lines from * `:814` / `:895` with their text byte-identical, that hop changing only a - * docblock and a dev warning above them): `ObjectMap.tsx:864` reads - * `schema.filter`, and `:958` and `:1037` hand it, tokens resolved, to + * docblock and a dev warning above them): `ObjectMap.tsx:902` reads + * `schema.filter`, and `:996` and `:1075` hand it, tokens resolved, to * `$filter` on the inline and the object fetch, where the adapter lowers a * rule array exactly as it does for the kanban and the calendar. The record * form is refused at `filter`. @@ -7665,7 +7820,13 @@ export const ObjectMapPropsSchema = lazySchema(() => strictObject({ * Marker order — the `SortItem` ARRAY form, the one sort orthography every * DECLARED `sort` door on this platform carries (objectui#8221, decision batch * #77, option B). Measured at the pin this repo builds against - * (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `ObjectMap.tsx` changed above both anchors (+85/-4, objectui#11819, objectui + * `fbaa79d19`: the WebGL2 probe and the list fallback), so both MOVED down 38 + * with their text byte-identical, `:959` -> `:997` and `:1038` -> `:1076`; and + * `plugin-map/src/index.tsx` is byte-identical (`git diff --quiet`), so the + * `sort` input held unmoved at `:120`. At `a58626c88`, re-read there + * 2026-10-06: * every objectui file this record cites is byte-identical across the hop from * `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. * At `0abd4f9f8`, re-read there 2026-10-05: @@ -7710,7 +7871,7 @@ export const ObjectMapPropsSchema = lazySchema(() => strictObject({ * retired (objectui#10393), still declares no `sort`. At `f8a9d0fb0` both files were byte-identical * to `62597c588`, re-READ there 2026-09-23 — both anchors had MOVED 19 * lines from `:815` / `:896` with their text byte-identical): - * `ObjectMap.tsx:959` and `:1038` + * `ObjectMap.tsx:997` and `:1076` * hand `schema.sort` to the shared `convertSortToQueryParams` sink as the * fetch's `$orderby` — the same sink `object-grid` and `object-calendar` * declare against, so the legacy string clause is refused here for the same @@ -7849,7 +8010,12 @@ function objectGanttMarker() { /** * `object-gantt` (objectui `plugin-gantt/src/ObjectGantt.tsx` plus the registry * shell `plugin-gantt/src/index.tsx`, read at the pin this repo builds against - * — `.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * — `.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `ObjectGantt.tsx` and `record-source.ts` are byte-identical across the hop from + * `a58626c88` (`git diff --quiet`), so every anchor in them held unmoved; + * `plugin-gantt/src/index.tsx` changed in one line only, the `markers` input's + * description (`:190`, objectui `c0862c1cc`), below the `gantt` input, which did + * not move from `:179`. At `a58626c88`, re-read there 2026-10-06: * every objectui file this record cites is byte-identical across the hop from * `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. * At `0abd4f9f8`, re-read there 2026-10-05: @@ -8085,10 +8251,18 @@ export type ObjectGanttPropsParsed = z.infer; /** * The flat `TreeConfig` spellings `getTreeConfig` reads ahead of the `tree` * block (`ObjectTree.tsx:289-302`) and that `ObjectView` / `ListView` EMIT when - * they flatten `options.tree` (`ListView.tsx:3770-3789`, `case 'tree'`: the + * they flatten `options.tree` (`ListView.tsx:3853-3872`, `case 'tree'`: the * product carries these keys, the EFFECTIVE `filter` objectui#10250 added, and * NO `tree` key). Both halves re-READ at the - * pin this repo builds against (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * pin this repo builds against (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `ObjectTree.tsx` and `plugin-tree/src/index.tsx` are byte-identical to + * `a58626c88` (`git diff --quiet`), so `289-302` and `240-261` did not move; + * `ListView.tsx` changed above and below its `case 'tree'` arm (+286/-46: + * objectui#11984, objectui#6152 round 12, objectui#11860, objectui#11943, + * objectui#11925, objectui#11816, objectui#11810 and objectui#11687), which + * MOVED byte-identical `3770-3789` -> `3853-3872`, `:3784` -> `:3867` with it, + * so the flat key set each reads or emits did not move. At `a58626c88`, + * re-read there 2026-10-06: * `plugin-tree/src/index.tsx` and `ListView.tsx` are byte-identical to * `0abd4f9f8` (`git diff --quiet`), so `3770-3789` and `:3784` did not move; * `ObjectTree.tsx` changed (+81/-3, objectui#11686: five import lines at the @@ -8157,7 +8331,7 @@ export type ObjectGanttPropsParsed = z.infer; * * `titleField` is in the set although no `tree` block key is spelled that way: * `ListView`'s flatten resolves `treeCfg.titleField` into `labelField` before - * emitting (`ListView.tsx:3784`, `labelField: treeCfg.labelField || + * emitting (`ListView.tsx:3867`, `labelField: treeCfg.labelField || * treeCfg.titleField || 'name'`), so the author's intent is always the block's * `labelField`, and the prescription below says so. * @@ -8186,7 +8360,10 @@ const OBJECT_TREE_FLAT_CONFIG_GUIDANCE: readonly KeySetGuidance[] = [ /** * `object-tree` (objectui `plugin-tree/src/ObjectTree.tsx` plus the registry * shell `plugin-tree/src/index.tsx`, read at the pin this repo builds against - * — `.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * — `.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * every objectui file this record cites is byte-identical across the hop from + * `a58626c88` (`git diff --quiet`), so every anchor held unmoved. At `a58626c88`, + * re-read there 2026-10-06: * `plugin-tree/src/index.tsx` and `core/src/utils/record-source.ts` are * byte-identical to `0abd4f9f8` (`git diff --quiet`), so their anchors held * unmoved; `ObjectTree.tsx` changed (+81/-3, objectui#11686: a tree cell draws @@ -8370,7 +8547,13 @@ export const ObjectTreePropsSchema = lazySchema(() => strictObject({ * holds for them because each registers through `ElementDataSourceGate`, * which lowers the spec binding onto `objectName` before the renderer sees * the node. `plugin-tree/src/index.tsx` does NOT: at the pin this repo - * builds against (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * builds against (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * re-COUNTED by the same method, 0 for the tree and `plugin-map`'s 4, both + * shells byte-identical across the hop from `a58626c88` (`git diff --quiet`), + * and 3 each for `plugin-calendar`, `plugin-gantt` and `plugin-grid`, whose + * shells changed on the hop in input descriptions and one comment only + * (objectui#6152 rounds 7 and 8, objectui `c0862c1cc`), their wiring unchanged. + * At `a58626c88`, re-read there 2026-10-06: * re-COUNTED by the same method, all five `src/index.tsx` shells are * byte-identical across the hop from `0abd4f9f8` (`git diff --quiet`) and * read 0 for the tree, 3 each for `plugin-calendar`, `plugin-gantt` and @@ -8752,7 +8935,18 @@ function objectTimelineItemsFitVariant() { * `object-timeline` (objectui `plugin-timeline/src/ObjectTimeline.tsx`, the * presentational `plugin-timeline/src/renderer.tsx` it composes into, and the * registry shell `plugin-timeline/src/index.tsx` — all read at the pin this - * repo builds against (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * repo builds against (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `renderer.tsx` is byte-identical to `a58626c88` (`git diff --quiet`), so its + * three anchors held unmoved; `index.tsx` rewrote two description constants in + * place, line for line (`:432` and `:438`, objectui `c0862c1cc`), so `:334` and + * `:446` did not move; `ObjectTimeline.tsx` changed in three comments only + * (+19/-8, objectui#6152 round 12, objectui `5d77c099b`: the nested block's type + * is the spec slot by reference, its legacy `dateField` refused by name while the + * read stays), so every anchor in it MOVED with its cited text byte-identical — + * by 10 past the second comment (`:298` -> `:308` through `:555` -> `:565`) and + * by 11 past the third (`:580` -> `:591` through `:1022-1023` -> `:1033-1034`), + * `:30` not moving — and each is cited below at this pin. The `schema.*` read set + * of all three is unchanged. At `a58626c88`, re-read there 2026-10-06: * `renderer.tsx` and `index.tsx` are byte-identical to `0abd4f9f8` (`git diff * --quiet`), so their anchors held unmoved; `ObjectTimeline.tsx` changed * (+39/-9: objectui#11675 starts the date buckets' week on the display locale's @@ -8858,32 +9052,32 @@ function objectTimelineItemsFitVariant() { * directions: nothing accepted a real key and nothing refused a typo. * * Read points per key, in `ObjectTimeline.tsx` unless named otherwise: - * `objectName` (`:298` the fetch gate, `:378-381` the object-def load through - * `useSettledSchema`, `:416` the `fetchesForItself` gate — the check that + * `objectName` (`:308` the fetch gate, `:388-391` the object-def load through + * `useSettledSchema`, `:426` the `fetchesForItself` gate — the check that * sat inside the fetch effect at `:420` is hoisted to render scope at this - * pin, where `:417` also subscribes the invalidation bus on it - * (objectui#10623) and the effect reads it at `:521` — `:423` / `:481` + * pin, where `:427` also subscribes the invalidation bus on it + * (objectui#10623) and the effect reads it at `:531` — `:433` / `:491` * inside the fetch effect, - * `:821` the pull-to-refresh gate, `:606` the entry composition and `:834` - * the navigation binding), `timeline` (`:315`, + * `:832` the pull-to-refresh gate, `:617` the entry composition and `:845` + * the navigation binding), `timeline` (`:325`, * the canonical nested config every field resolution prefers), `filter` - * (`:404`, read once through `useResolvedFilter`, which resolves its context - * tokens — objectui#10666 — and holds the result; `:405` keys the fetch on - * it and `:482` sends it to `$filter`, where `f8a9d0fb0` sent `schema.filter` - * verbatim at `:341` / `:405`), `sort` (`:406`, `:483` — through + * (`:414`, read once through `useResolvedFilter`, which resolves its context + * tokens — objectui#10666 — and holds the result; `:415` keys the fetch on + * it and `:492` sends it to `$filter`, where `f8a9d0fb0` sent `schema.filter` + * verbatim at `:341` / `:405`), `sort` (`:416`, `:493` — through * the shared `convertSortToQueryParams` sink, as `object-calendar`'s does), - * `limit` (`:484`, the fetch's one top-level `$top`, through + * `limit` (`:494`, the fetch's one top-level `$top`, through * `resolveRowLimit(schema.limit, DEFAULT_TIMELINE_LIMIT)` with the default - * `100` at `:30` and the refused-cap diagnostic at `:332`), `items` (`:296`, `:416`, `:591`, - * `:850` — the authored pass-through that short-circuits the object query), - * `data` (`:297`, `:416`, `:543`, `:545` — the pre-fetched record source, + * `100` at `:30` and the refused-cap diagnostic at `:342`), `items` (`:306`, `:426`, `:602`, + * `:861` — the authored pass-through that short-circuits the object query), + * `data` (`:307`, `:426`, `:553`, `:555` — the pre-fetched record source, * read off REACT PROPS rather than `schema`; the door's own docblock carries * how an authored key reaches that channel and why a `schema.*` sweep alone * publishes a false refusal), - * `descriptionField` (`:582`), `mapping` (`:555`, `:580`, `:582`, `:583`), - * `variant` (`:888`) and `navigation` (`:832-835` → `:967` → `:1022-1023`). + * `descriptionField` (`:593`), `mapping` (`:565`, `:591`, `:593`, `:594`), + * `variant` (`:899`) and `navigation` (`:843-846` → `:978` → `:1033-1034`). * Four more are read by the presentational renderer off the schema this - * component spreads into it (`effectiveSchema`, `:951-970`): `dateFormat` + * component spreads into it (`effectiveSchema`, `:962-981`): `dateFormat` * (`plugin-timeline/src/renderer.tsx:1569`, every variant — its number was the * same at `53ded82bf` and `87af769e9`, as `plugin-timeline/src/index.tsx:333`'s * also was (`:334` since the hop off `31971ff1e`), which is why the number alone is never the reading) and the gantt @@ -8898,8 +9092,8 @@ function objectTimelineItemsFitVariant() { * ({@link OBJECT_TIMELINE_FLAT_CONFIG_GUIDANCE}) — the runtime handoff * `ListView` emits, not a second authoring spelling; * - `bind` — the objectui data-scope key the section header above rules out - * for every block in this family (`:336` here); - * - `className` (`:954`) — a node-level key on `PageComponentSchema`, not a + * for every block in this family (`:346` here); + * - `className` (`:965`) — a node-level key on `PageComponentSchema`, not a * per-block prop; * - `onItemClick` / `onRowClick` — host callbacks JSON cannot carry. * @@ -8921,8 +9115,8 @@ function objectTimelineItemsFitVariant() { * (`plugin-timeline/src/index.tsx:446`, in the one `OBJECT_TIMELINE_INPUTS` * list both registrations spread) and the renderer reads it — but the * OBJECT-BOUND composed path REFUSES it loudly (objectui#6655, - * `ObjectTimeline.tsx:888-890`: - * `:888` gates on `!hasAuthoredItems && schema.variant === 'gantt'` and `:890` + * `ObjectTimeline.tsx:899-901`: + * `:899` gates on `!hasAuthoredItems && schema.variant === 'gantt'` and `:901` * renders `timeline-unsupported-variant`. ⚠️ The `:518` this clause carried is * that gate at the RETIRED `53ded82bf` and was a comment line at `31971ff1e`. It sat on * a line the 2026-09-22 conversion never touched — and so did eight other @@ -8974,7 +9168,15 @@ export const ObjectTimelinePropsSchema = lazySchema(() => strictObject({ * first publishes a refusal for a key the renderer honours. * * Read points at the pin this repo builds against (`.objectui-sha` = - * `a58626c88`, re-read there 2026-10-06: + * `f0268ad78`, re-read there 2026-10-09: + * `record-source.ts` and `SchemaRenderer.tsx` are byte-identical across the hop + * from `a58626c88` (`git diff --quiet`), so the prop channel above still + * carries the key; the file changed in three comments only (+19/-8, + * objectui#6152 round 12, objectui `5d77c099b`), away from these reads, so + * every anchor MOVED with its cited read byte-identical, by 10 above the third + * comment and by 11 below it: `:297` -> `:307`, `:416` -> `:426`, `:521` -> + * `:531`, `:543` -> `:553`, `:545` -> `:555`, `:667-668` -> `:678-679`, `:698` + * -> `:709`. At `a58626c88`, re-read there 2026-10-06: * `record-source.ts` and `SchemaRenderer.tsx` are byte-identical across the * hop from `0abd4f9f8` (`git diff --quiet`), so the prop channel above still * carries the key; the file changed (+39/-9: objectui#11675's locale week @@ -9046,13 +9248,13 @@ export const ObjectTimelinePropsSchema = lazySchema(() => strictObject({ * `recordDisplayValueAt` (`:653`, objectui#10530), not `item[titleField]`. * At `f8a9d0fb0` the file was byte-identical to `62597c588` and * `87af769e9`, where they were re-READ 2026-09-22), all in - * `ObjectTimeline.tsx`: `:297` seeds the loading state off it, `:416` + * `ObjectTimeline.tsx`: `:307` seeds the loading state off it, `:426` * SKIPS the object query when it is present (the gate the effect reads at - * `:521`), `:543` tracks it, and `:545` + * `:531`), `:553` tracks it, and `:555` * is the row source itself — `(props as any).data || boundData || * fetchedData`, so it wins over both the data-scope binding and the fetch. * Unlike `items` one line down, these rows are RECORDS: they go through the - * same `timeline` field bindings a fetched row takes (`:667-668`, `:698`). + * same `timeline` field bindings a fetched row takes (`:678-679`, `:709`). */ data: z.array(z.unknown()).optional() .describe("Pre-fetched records — read FIRST as the rail's row source, ahead of the data-scope binding and the fetch, and composed into entries through the same `timeline` field bindings a fetched row takes; authoring it suppresses the object query entirely. Distinct from `items`, which is the already-composed entry shape and wins over this key when both are written"), @@ -9274,6 +9476,20 @@ export const ComponentPropsMap = { // set from this map's keys), on the three-part evidence that vocabulary's // string-arm ledger asks of a type admitted without an enum member — all // measured at the pin this repo builds against (`.objectui-sha` = + // `f0268ad78`, re-read there 2026-10-09: + // `public-blocks.ts` is byte-identical across the hop from `a58626c88` + // (`git diff --quiet`), so `:117-118` did not move; `data-list.tsx` changed + // (+99/-16, objectui#11880's repeater half, objectui `aaba8655a`), the + // `definition-list` registration MOVING `75` -> `85` byte-identical and the + // `repeater` one MOVING `233` -> `311`, its first line now registering the + // renderer through `elementDataSourceBlock` (it reads the node-level + // `dataSource` binding at this pin), both still in the `element` namespace; + // `block-types.ts` changed (+14/-7, objectui `c0862c1cc`) above the palette + // entries, which MOVED `136-137` -> `137-138` byte-identical; and + // `block-config.ts` changed (+33/-13: objectui#11880's binding-homed rows for + // `element:record_picker` and `element:number`, and objectui `c0862c1cc`) + // around the two inspectors, which MOVED `296-330` -> `311-345` + // byte-identical. At // `a58626c88`, re-read there 2026-10-06: // every objectui file this record cites is byte-identical across the hop from // `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. @@ -9306,13 +9522,13 @@ export const ComponentPropsMap = { // anchor below held unmoved; at `db11afd49`, 2026-09-29, all four files were // byte-identical to `dd3f7e1be`): // - registration: `@object-ui/components` registers both in the `element` - // namespace (`components/src/renderers/basic/data-list.tsx:75`, `:233`); + // namespace (`components/src/renderers/basic/data-list.tsx:85`, `:311`); // - publication: both are `PUBLIC_BLOCKS` members // (`core/src/registry/public-blocks.ts:117-118`), which is how the // tracked `sdui.manifest.json` carries both; // - authorship: the Studio page designer's palette offers both - // (`app-shell/src/views/metadata-admin/previews/block-types.ts:136-137`), - // each with its own inspector (`previews/block-config.ts:296-330`), so + // (`app-shell/src/views/metadata-admin/previews/block-types.ts:137-138`), + // each with its own inspector (`previews/block-config.ts:311-345`), so // stored pages hold them. 'element:definition-list': ElementDefinitionListPropsSchema, 'element:repeater': ElementRepeaterPropsSchema, @@ -9346,7 +9562,13 @@ export const ComponentPropsMap = { // authority for map and gantt while tree's rung-1 `data` read stayed // undeclared on every face. Key sets measured from the renderers' read // points at the pin this repo builds against (`.objectui-sha` = - // `a58626c88`, re-read there 2026-10-06: + // `f0268ad78`, re-read there 2026-10-09: + // `ObjectGantt.tsx` and `ObjectTree.tsx` are byte-identical to `a58626c88` + // (`git diff --quiet`); `ObjectMap.tsx` (+85/-4) changed for objectui#11819 + // (without WebGL2 the map lists its records instead of crashing) and was + // re-READ: its anchors MOVED byte-identical and its `schema.*` read set is + // unchanged (the same 17 names at both pins), so no declared key set moved and + // no read point died. At `a58626c88`, re-read there 2026-10-06: // `ObjectMap.tsx` and `ObjectGantt.tsx` are byte-identical to `0abd4f9f8` // (`git diff --quiet`); `ObjectTree.tsx` (+81/-3) changed for objectui#11686 // (a tree cell draws the same field face a list cell does) and was re-READ: @@ -9414,7 +9636,13 @@ export const ComponentPropsMap = { // it — so `object-timeline` was unjudged in both directions, a real key and // a typo riding through alike. Key set measured from the renderer's read // points at the pin this repo builds against (`.objectui-sha` = - // `a58626c88`, re-read there 2026-10-06: + // `f0268ad78`, re-read there 2026-10-09: + // `renderer.tsx` is byte-identical to `a58626c88` (`git diff --quiet`); + // `index.tsx` rewrote two input descriptions in place and `ObjectTimeline.tsx` + // changed in three comments only (objectui#6152 round 12, the nested block's + // type by reference to the spec slot), both re-READ: every anchor moved or held + // with its text byte-identical, the `schema.*` read set is unchanged, and no + // declared key set moved. At `a58626c88`, re-read there 2026-10-06: // `renderer.tsx` and `index.tsx` are byte-identical to `0abd4f9f8` (`git diff // --quiet`); `ObjectTimeline.tsx` changed for objectui#11675 and // objectui#11676 (the date buckets' locale week start and the "Earlier" diff --git a/packages/spec/src/ui/dataset.zod.ts b/packages/spec/src/ui/dataset.zod.ts index 97e73ddfb36..6c137e0561a 100644 --- a/packages/spec/src/ui/dataset.zod.ts +++ b/packages/spec/src/ui/dataset.zod.ts @@ -283,6 +283,16 @@ export const DatasetMeasureSchema = lazySchema(() => strictObject({ * and this docblock and the `describe` beneath it both said so. * * Measured at the pin this repo builds against (`.objectui-sha` = + * `f0268ad78`, re-read there 2026-10-09: + * `dataset-format.ts` is byte-identical to `a58626c88` (`git diff --quiet`), so + * `formatMeasureDate` `:240-274`, its datetime arm `:270`-`:272` and its call + * `:380` held unmoved; `date-display.ts` changed (+152/-16, objectui#11693, + * objectui `d50f7241b`: an instant renders in the time zone the server answers + * for the workspace), so `formatDate` `445-480` -> `568-605` was re-READ: it + * now names an instant's day in that display zone, while its style handling — + * `short`, `relative`, and the default face for anything else, a date pattern + * included — reads unchanged, and the ±7-day fallback `399` -> `522` MOVED + * byte-identical, its day count now taken in the display zone above it. At * `a58626c88`, re-read there 2026-10-06: * every objectui file this record cites is byte-identical across the hop from * `0abd4f9f8` (`git diff --quiet`), so every anchor held unmoved. @@ -356,9 +366,9 @@ export const DatasetMeasureSchema = lazySchema(() => strictObject({ * non-numeric value through `formatMeasureDate` (`:240-274`, was `:229-263`, * `:229-264` and before that `:185-198`) at `:380`, * whose date-only arm threads `format` into the STYLE parameter of - * `formatDate` (`utils/date-display.ts:445-480`, was `:378-413`, `:355-390`, `:271-306`, + * `formatDate` (`utils/date-display.ts:568-605`, was `:445-480`, `:378-413`, `:355-390`, `:271-306`, * `:198-233` and before that `:131-164`, whose `relative` branch falls back to the absolute form - * beyond ±7 days at `:399`, was `:332`, `:309`, `:225`, `:152` and `:117` — the fallback strips the style through + * beyond ±7 days at `:522`, was `:399`, `:332`, `:309`, `:225`, `:152` and `:117` — the fallback strips the style through * `absoluteFallbackOptions`), while its datetime arm answers `relative` with * `formatRelativeDate` (`:270`), `short` with * `formatDateTime(v, { locale, style: 'compact' })` (`:271`) and everything diff --git a/packages/spec/src/ui/view.zod.ts b/packages/spec/src/ui/view.zod.ts index 48b21f8d925..26426fc83fd 100644 --- a/packages/spec/src/ui/view.zod.ts +++ b/packages/spec/src/ui/view.zod.ts @@ -2180,16 +2180,30 @@ export const TreeConfigSchema = lazySchema(() => strictObject({ * and still without `map`. The third is `case 'map':` in `ObjectView.tsx`, * `2299` -> `2300`, the whole arm byte-identical: objectui#8347 grew one * comment line above it. `ObjectMap.tsx` and `ListView.tsx` are - * byte-identical, so their anchors did not move. Each anchor quotes the line it was read at, + * byte-identical, so their anchors did not move. RE-READ again at pin + * `f0268ad78` on 2026-10-09: that bump redded all seven anchors, and none of + * them changed what it reads. `ListView.tsx` gained one import line above + * both of its anchors (objectui#11860), so `resolveListMapConfig` `146` -> + * `147` and `FLAT_MAP_CONFIG_SPELLING` `85` -> `86`, each byte-identical; + * `case 'map':` in `ObjectView.tsx` `2300` -> `2340`, the whole arm + * byte-identical (objectui#11695, objectui#11775, objectui#11880 item 5 and + * objectui#6152 rounds 8 and 10 changed the file around it); in + * `objectql.zod.ts`, which grew above them again (+218/-125: + * objectui#6152 rounds 7 to 12 among others), `ObjectMapConfigSchema` `2388` + * -> `2513`, its declaration byte-identical and still closed with + * `.strict()`, and `LIST_VIEW_LOCAL_OVERRIDES` `1437` -> `1506`, the whole + * list byte-identical and still without `map`; and the two `getMapConfig` + * lines `415` -> `449` and `420` -> `454`, byte-identical, objectui#11819's + * WebGL2 probe landing above them. Each anchor quotes the line it was read at, * so the next pin bump reds instead of rotting * (`check:objectui-pin-citations`): * * - **The block this face feeds is FLATTENED, not forwarded.** `ListView` - * (`packages/plugin-list/src/ListView.tsx:146` first line + * (`packages/plugin-list/src/ListView.tsx:147` first line * `function resolveListMapConfig(schema: { map?: unknown; options?: { map?: unknown } }): Record {`) - * and `ObjectView` (`packages/plugin-view/src/ObjectView.tsx:2300` first line + * and `ObjectView` (`packages/plugin-view/src/ObjectView.tsx:2340` first line * `case 'map':`) copy it through a HAND-LISTED whitelist - * (`packages/plugin-list/src/ListView.tsx:85` first line + * (`packages/plugin-list/src/ListView.tsx:86` first line * `export const FLAT_MAP_CONFIG_SPELLING = {`) — ⚠️ re-read at the new pin: * the whitelist was a key LIST named `FLAT_MAP_CONFIG_KEYS` carrying this * block's keys MINUS `style`, and objectui#9950 made it a total map from @@ -2199,7 +2213,7 @@ export const TreeConfigSchema = lazySchema(() => strictObject({ * there, but by a whitelist and in SILENCE: no parse, no warning, no * diagnostic of any kind. * - **The renderer's own zod schema does not close the set.** - * `packages/types/src/zod/objectql.zod.ts:2388` first line + * `packages/types/src/zod/objectql.zod.ts:2513` first line * `export const ObjectMapConfigSchema = z.object({` — a plain `z.object` at `dd3f7e1be`, * NOT strict, so an undeclared key parses clean there: zero issues, no * warning. ⚠️ At `db11afd49` the declaration is closed with `.strict()` @@ -2208,10 +2222,10 @@ export const TreeConfigSchema = lazySchema(() => strictObject({ * the node with an `unrecognized_keys` issue at `map` — the flatten whitelist * above still drops the key in silence, and the spread below still returns the * authored block. `getMapConfig` consults that `safeParse` - * (`packages/plugin-map/src/ObjectMap.tsx:415` first line + * (`packages/plugin-map/src/ObjectMap.tsx:449` first line * `const result = ObjectMapConfigSchema.safeParse(config);`) only to decide * whether to `console.warn`, then returns a spread of the AUTHORED block - * (`:420` first line `return { ...config, style };`), + * (`:454` first line `return { ...config, style };`), * undeclared key and all. That spread is reached by objectui's own * component-node `map` prop, never by this face's flatten product ("neither * flattener emits a `map` key at all", `getMapConfig`). @@ -2222,7 +2236,7 @@ export const TreeConfigSchema = lazySchema(() => strictObject({ * `db11afd49` it is closed by `.strict()` and still warn-only). And this parse is * the only * place an author is told ANYWHERE: `map` is not in objectui's - * `LIST_VIEW_LOCAL_OVERRIDES` (`packages/types/src/zod/objectql.zod.ts:1437` + * `LIST_VIEW_LOCAL_OVERRIDES` (`packages/types/src/zod/objectql.zod.ts:1506` * first line `const LIST_VIEW_LOCAL_OVERRIDES = [`), so objectui's own * `ListViewSchema` imports THIS block by reference and the document check on * that side is this same schema. The two key sets MIRROR each other, key for @@ -3280,7 +3294,16 @@ const FormFieldBaseSchema = lazySchema(() => { * inside the `53ded82bf7...87af769e9` range, so the widest-tier-only * under-span this block used to record (#17328: one cell of two at * 720px) no longer reproduces at the pin this repo builds against - * (`.objectui-sha` = `a58626c88`, re-read there 2026-10-06: + * (`.objectui-sha` = `f0268ad78`, re-read there 2026-10-09: + * `autoLayout.ts` and `fields`' `field-type-alias.ts` are byte-identical to + * `a58626c88` (`git diff --quiet`), so `resolveColSpan` `:154`, + * `WIDE_FIELD_TYPES` `:58-69` and the `repeater` -> `field:grid` mapping held + * unmoved, and `form.tsx` changed on this hop — 100 insertions, 5 deletions: + * objectui#11777, ungrouped fields rendered as their own block rather than + * under the last group's heading — none of it inside `spanLadderFor`, which + * MOVED `:204-231` -> `:274-301` byte-identical, and its one call site moved + * `:3132` -> `:3202` with the call byte-identical, so it still emits the + * ladder. At `a58626c88`, re-read there 2026-10-06: * `autoLayout.ts` and `fields`' `field-type-alias.ts` are byte-identical to * `0abd4f9f8` (`git diff --quiet`), so `resolveColSpan` `:154`, * `WIDE_FIELD_TYPES` `:58-69` and the `repeater` -> `field:grid` mapping held @@ -3344,7 +3367,7 @@ const FormFieldBaseSchema = lazySchema(() => { * had changed only in its registration's input list, objectui#9910's * `children` slot; at `62597c588` it was byte-identical to `87af769e9`). */ - span: z.enum(['auto', 'full']).default('auto').describe("Relative field width. 'auto' (default — omit it): the renderer sizes the field from its widget type × the current column count — at the pin this repo builds against (`.objectui-sha` = `a58626c88dc8`), only textarea, markdown, html, richtext and repeater resolve to the full column count (repeater reaches it through the wide `field:grid` widget it maps to). 'full': resolves to the form grid's full column count. How far down the container-query tiers that span is emitted is the renderer's, not this key's: at that same pin the renderer emits one clamped col-span class per multi-column tier (`@md:col-span-2 @2xl:col-span-3` for a 3-column grid), so the field takes the whole row at every multi-column tier, not just the widest."), + span: z.enum(['auto', 'full']).default('auto').describe("Relative field width. 'auto' (default — omit it): the renderer sizes the field from its widget type × the current column count — at the pin this repo builds against (`.objectui-sha` = `f0268ad78485`), only textarea, markdown, html, richtext and repeater resolve to the full column count (repeater reaches it through the wide `field:grid` widget it maps to). 'full': resolves to the form grid's full column count. How far down the container-query tiers that span is emitted is the renderer's, not this key's: at that same pin the renderer emits one clamped col-span class per multi-column tier (`@md:col-span-2 @2xl:col-span-3` for a 3-column grid), so the field takes the whole row at every multi-column tier, not just the widest."), /** Custom widget override — only needed when auto-inference is insufficient */ widget: z.string().optional().describe('Custom widget/component name (overrides type-based inference)'), diff --git a/scripts/sdui-manifest.record.json b/scripts/sdui-manifest.record.json index dc0b782c67c..032af6469cb 100644 --- a/scripts/sdui-manifest.record.json +++ b/scripts/sdui-manifest.record.json @@ -11,12 +11,12 @@ "a pin bump without regeneration goes RED there — that is the anti-rot half of the freshness gate.", "Regenerate + re-record: pnpm objectui:build && node scripts/gen-sdui-manifest-node.mjs" ], - "objectuiSha": "a58626c88dc85954bd0af24f16ebb69454c03eee", + "objectuiSha": "f0268ad784854568aa58a2aa791f6a7502259186", "source": "built-tree", - "modulesRoot": ".cache/objectui-a58626c88dc8/apps/console", + "modulesRoot": ".cache/objectui-f0268ad78485/apps/console", "objectuiWorkspaceVersion": "17.7.0", "generator": "scripts/gen-sdui-manifest-node.mjs", - "generatedAt": "2026-10-06", - "sha256": "e0654735a318ef5ad51332b32984a0e200c37fa753097dfd8f1d6d338fca11f1", + "generatedAt": "2026-10-09", + "sha256": "097ae3cbcf9533189f0c8d689e385414bf175d19d105480df746f7c3353e0f1f", "components": 107 } diff --git a/sdui.manifest.json b/sdui.manifest.json index e93b552a590..8b037a555b6 100644 --- a/sdui.manifest.json +++ b/sdui.manifest.json @@ -17,7 +17,7 @@ { "name": "filter", "type": "array", - "description": "Filter criteria in JSON-rules form. The canonical spelling — the deprecated `defaultFilters` is only read when this is absent." + "description": "Base query filter — the `ViewFilterRule` array `[{ field, operator, value }, ...]`, lowered to `$filter`. The canonical spelling — the deprecated `defaultFilters` is only read when this is absent." }, { "name": "label", @@ -76,7 +76,7 @@ { "name": "resizable", "type": "boolean", - "description": "Let users drag column borders to resize. The canonical spelling — the deprecated `resizableColumns` is only read when this is absent." + "description": "Let users drag column borders to resize. On by default. The only spelling — the legacy `resizableColumns` is retired and refused by name (objectui#6152)." }, { "name": "reorderableColumns", @@ -161,7 +161,7 @@ { "name": "operations", "type": "object", - "description": "Toggles for the built-in create/read/update/delete/export/import affordances, e.g. `{ delete: false }`." + "description": "Toggles for the built-in affordances, `{ create, update, delete, export }`, e.g. `{ delete: false }`. A declared block replaces the default, so an `update` / `delete` it does not name is withheld." }, { "name": "exportOptions", @@ -571,7 +571,7 @@ "type": "array", "of": "object", "required": true, - "description": "The child collections, one OBJECT per entry, judged by the spec's closed `details` entry: `childObject` (required) names the child object; `relationshipField` is the FK on the child back to the parent, derived from the child's metadata when omitted; `columns` are the line grid's columns as the spec's inline grid column objects (`{ name, … }`, never a bare field name), derived from the child's fields when omitted; `formFields` names the per-row form's fields; `inlineMode` is `grid` (editable cells) or `form` (list + per-row form); `amountField` is the CHILD column summed and `totalField` the PARENT field that sum is saved to; `title`, `minRows`, `maxRows` and `addLabel` dress the section and its grid. An undeclared member key is refused by name. The entry's `sortField` is read by nothing here — the line-position field is derived from the child object (objectui#11070) — and objectstack retires the key on its `main` (objectstack-ai/objectstack#21589, after 17.6.0)." + "description": "The child collections, one OBJECT per entry, judged by the spec's closed `details` entry: `childObject` (required) names the child object; `relationshipField` is the FK on the child back to the parent, derived from the child's metadata when omitted; `columns` are the line grid's columns as the spec's inline grid column objects (`{ name, … }`, never a bare field name), derived from the child's fields when omitted; `formFields` names the per-row form's fields; `inlineMode` is `grid` (editable cells) or `form` (list + per-row form); `amountField` is the CHILD column summed and `totalField` the PARENT field that sum is saved to; `title`, `minRows`, `maxRows` and `addLabel` dress the section and its grid. An undeclared member key is refused by name. `sortField` is not a member: the line-position field is derived from the child object (objectui#11070), and since `@objectstack/spec` 17.7.0 the entry refuses an authored `sortField` with the spec's retired-key message (objectstack-ai/objectstack#21589)." }, { "name": "recordId", @@ -659,7 +659,7 @@ { "name": "filter", "type": "array", - "description": "Filter criteria in JSON-rules form, narrowing the records the board fetches. Lowered to `$filter` on the query." + "description": "Base query filter — the `ViewFilterRule` array `[{ field, operator, value }, ...]`, narrowing the records the board fetches. Lowered to `$filter` on the query." }, { "name": "limit", @@ -741,7 +741,7 @@ { "name": "filter", "type": "array", - "description": "Filter criteria in JSON-rules form, narrowing the records the calendar fetches. Lowered to `$filter` on the query." + "description": "Base query filter — the `ViewFilterRule` array `[{ field, operator, value }, ...]`, narrowing the records the calendar fetches. Lowered to `$filter` on the query." }, { "name": "sort", @@ -862,7 +862,7 @@ { "name": "markers", "type": "array", - "description": "Extra vertical reference lines drawn like the Today marker ({ date, label?, color? }). `date` places the line, and a date outside the chart's range draws none; `label` is the text drawn against it; `color` is its CSS colour, the theme's primary colour when omitted." + "description": "Extra vertical reference lines drawn like the Today marker — each `{ date, label?, color? }`: `date` places the line (a date outside the drawn range draws none), `label` is drawn against it, `color` paints it. `color` is a CSS colour, the theme's primary colour when omitted." }, { "name": "criticalPath", @@ -943,7 +943,7 @@ { "name": "items", "type": "array", - "description": "Static inline entries — read ahead of every record source, `data` above included, and bypasses the object query entirely (the renderer becomes a pass-through). Each element is objectui's declared timeline element, `@object-ui/types`'s `TimelineFeedItem` (`variant` absent / `vertical` / `horizontal`) or `TimelineGanttItem` (`variant: 'gantt'`), the arm this node's `variant` selects. They are drawn as written: the `timeline` block’s field bindings, `mapping` and `descriptionField` do not apply to them." + "description": "Static inline entries — read ahead of every record source, `data` above included, and bypasses the object query entirely (the renderer becomes a pass-through). Each entry is the kind this node's `variant` selects: a feed entry `{ time?, title, description?, variant?, icon?, content?, className? }` (`variant` absent / `vertical` / `horizontal`), or a gantt row `{ label, items? }` (`variant: 'gantt'`) whose bars are `{ title?, startDate?, endDate?, variant? }`, each date a string or epoch milliseconds. These are `@object-ui/types`'s `TimelineFeedItem` and `TimelineGanttItem`. They are drawn as written: the `timeline` block’s field bindings, `mapping` and `descriptionField` do not apply to them." }, { "name": "dateFormat", @@ -978,7 +978,7 @@ { "name": "mapping", "type": "object", - "description": "Record-to-entry field mapping ({ title, date, description, variant }) — the objectui-side binding record read BETWEEN the `timeline` block and the flat fallbacks. Its `variant` member (the field whose value picks each marker colour, renderer default `variant`) is the only spelling that binding has. On the vertical rail a colour that `timeline.colorField` resolves for an entry outranks that marker colour." + "description": "Record-to-entry field mapping `{ title?, date?, description?, variant? }`, each a field name — the binding record read BETWEEN the `timeline` block and the flat fallbacks. Its `variant` member (the field whose value picks each marker colour, renderer default `variant`) is the only spelling that binding has. On the vertical rail a colour that `timeline.colorField` resolves for an entry outranks that marker colour." }, { "name": "dataSource", @@ -2078,11 +2078,9 @@ "h6", "body", "caption", - "overline", - "heading", - "subheading" + "overline" ], - "description": "One of the nine text styles ui:text uses: h1-h6 (rendered as that heading level), body, caption or overline. heading and subheading are earlier spellings the contract still accepts and renders as h2 and h3; write h2 or h3 instead." + "description": "One of the nine text styles ui:text uses: h1-h6 (rendered as that heading level), body, caption or overline. The earlier spellings heading and subheading are refused; write h2 or h3 instead." }, { "name": "align", @@ -2102,7 +2100,7 @@ { "name": "object", "type": "string", - "description": "Object the aggregate runs over. Required unless a node-level `dataSource` binding names one; when both are set, `dataSource.object` wins." + "description": "NOT READ (objectui#11880): the aggregate runs over the object the node-level `dataSource.object` names, and a node without one shows the \"no object named\" notice. `@objectstack/spec` retires this flat key in v18 (objectstack#11509)." }, { "name": "aggregate", @@ -2124,7 +2122,7 @@ { "name": "filter", "type": "array", - "description": "Criteria the aggregate is scoped by. When a node-level `dataSource` binding also supplies a filter (its own, or the saved view its `view` names), the two are AND-combined: neither is dropped." + "description": "NOT READ (objectui#11880): the aggregate is scoped by the node-level `dataSource.filter`, AND-combined with the filter of the saved view its `view` names. This flat key is not combined with it and never applies; `@objectstack/spec` retires it in v18 (objectstack#11509)." }, { "name": "format", @@ -2248,7 +2246,7 @@ "name": "object", "type": "string", "required": true, - "description": "Object whose records the list repeats over" + "description": "Object whose records the list repeats over; a node-level `dataSource.object` wins" }, { "name": "titleField", @@ -2283,6 +2281,12 @@ "name": "divided", "type": "boolean", "description": "Separator between rows" + }, + { + "name": "dataSource", + "type": "object", + "binding": "object", + "description": "Per-element data binding: { object, view, filter, sort, limit }. Overrides the page-level object context for this block; `view` names a saved view of `object`, and `filter` is ANDed with the view’s own rather than replacing it." } ] }, @@ -2466,6 +2470,11 @@ "name": "recordIdField", "type": "string", "description": "For a `script` action run against a single selected row: the row field whose value is sent as the record id (default `id`)" + }, + { + "name": "undoable", + "type": "boolean", + "description": "Offer an Undo affordance after an update action: once an `operation: update` succeeds, its success toast offers Undo, which writes back the values the fields it wrote held on the record in scope (the record page's record, or the row the host binds), provided that record carries each of them. The one limit: a button with no record in scope (standalone, or writing a record other than the one in scope) offers no Undo, because there is no row to restore" } ] },