Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/20029-pin-bump-describe-correction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@objectstack/spec': patch
---

One published `describe` sentence that dates itself to the `.objectui-sha` pin is re-pointed to the pin this release builds against, objectui `f8a9d0fb0596`, after being re-read there (#20029).

`Clause-②: no`

- `FormField.span`: the `'auto'` clause says that at the pin this repo builds against, only textarea, markdown, html, richtext and repeater resolve to the full column count. It named `62597c588`. Re-read at `f8a9d0fb0596`, the claim still holds: `plugin-form`'s `autoLayout.ts` (`WIDE_FIELD_TYPES`, `resolveColSpan`) is byte-identical, and `form.tsx` changed only in its registration's input list (a `children` slot input), with `spanLadderFor` byte-identical, so `'full'` is still the whole row at every multi-column tier. Only the pin the sentence names moves.

No key, default, enum member or export moves: the same authored metadata is accepted and refused as before, and `content/docs/references/ui/view.mdx` is regenerated from the sentence.
122 changes: 122 additions & 0 deletions .changeset/console-f8a9d0fb0596.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .objectui-sha
Original file line number Diff line number Diff line change
@@ -1 +1 @@
62597c588072636e9c30ea35b3d89b1e46fd765d
f8a9d0fb0596f4521076628e2bbfe27e6ce67d52
4 changes: 2 additions & 2 deletions content/docs/references/ui/view.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,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` = `62597c588`), 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` = `f8a9d0fb0596`), 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<string, string>; placeholder?: string \| Record<string, string>; helpText?: string \| Record<string, string>; … }` | optional | Key column config for record-typed fields |
Expand Down Expand Up @@ -364,7 +364,7 @@ View filter rule
| **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` = `62597c588`), 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` = `f8a9d0fb0596`), 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<string, string>; placeholder?: string \| Record<string, string>; helpText?: string \| Record<string, string>; … }` | optional | Key column config for record-typed fields |
Expand Down
6 changes: 3 additions & 3 deletions packages/sdui-parser/objectui-lockstep.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
],
"objectui": {
"repo": "https://github.com/objectstack-ai/objectui.git",
"rev": "62597c588072636e9c30ea35b3d89b1e46fd765d",
"revDate": "2026-09-23T02:43:52+00:00",
"rev": "f8a9d0fb0596f4521076628e2bbfe27e6ce67d52",
"revDate": "2026-09-24T20:41:09+00:00",
"source": "packages/sdui-parser/src",
"files": [
"packages/sdui-parser/src/body-dialect.ts",
Expand All @@ -22,7 +22,7 @@
"packages/sdui-parser/src/validate.ts"
]
},
"recordedAgainstPin": "62597c588072636e9c30ea35b3d89b1e46fd765d",
"recordedAgainstPin": "f8a9d0fb0596f4521076628e2bbfe27e6ce67d52",
"grammarRegion": {
"file": "packages/sdui-parser/src/parse.ts",
"delimiter": "/* ---------------------- the JS literal subset (#6614) ---------------------- */",
Expand Down
21 changes: 13 additions & 8 deletions packages/spec/src/data/api-methods-batch-conformance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,22 @@ const SINGLE_RECORD_WRITE_ONLY: Record<string, string> = {
// `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` = `62597c588`, `packages/plugin-grid`; re-measured at
// that pin, 2026-09-23 — previously measured at `87af769e9`, `53ded82bf`,
// `a472b0716`, `00d3f09c5`, `67dadd602`, before that at `d8ec8d6d4`,
// `9602dc820`, `190fbd01d`, `9a3daf8d3`, originally at `6314e87f2`.
// `ObjectGrid.tsx` changed again across the move off `87af769e9` (119
// insertions, 9 deletions), and THIS time the selection block's CONTENT
// (`.objectui-sha` = `f8a9d0fb0`, `packages/plugin-grid`; re-measured at
// that pin, 2026-09-24 — previously measured at `62597c588`, `87af769e9`,
// `53ded82bf`, `a472b0716`, `00d3f09c5`, `67dadd602`, before that at
// `d8ec8d6d4`, `9602dc820`, `190fbd01d`, `9a3daf8d3`, originally at
// `6314e87f2`. On the hop off `62597c588`, `ObjectGrid.tsx` changed again
// (18 insertions, 5 deletions: objectui#10083's `rowActionsDeclared` row-menu
// signal and objectui#9909's currency display locale), none of it inside the
// selection block, which only MOVED: `ObjectGrid.tsx:4032-4059` here, still
// hashing to `c88443302d40c2db739ddb235470bafa29056e2e`, re-READ with the
// same reading below. `ObjectGrid.tsx` changed across the move off
// `87af769e9` too (119 insertions, 9 deletions), and THAT time the selection block's CONTENT
// moved, not only its position: objectui#10218 (`62597c588` itself)
// rewrote the `selection` arm to "presence enables; an explicit off wins",
// so an authored `selection` object with no `type` now selects
// (`DEFAULT_SELECTION_TYPE`, `'multiple'`) where it used to fall through.
// The block is `ObjectGrid.tsx:4024-4051` here — `3940-3955` at `87af769e9`,
// The block was `ObjectGrid.tsx:4024-4051` at `62597c588` — `3940-3955` at `87af769e9`,
// `3538-3553` at `53ded82bf` — and no longer hashes to the
// `6133933199230670e29d8c7f51c558d86a0af1d2` the previous three hops
// recorded (`c88443302d40c2db739ddb235470bafa29056e2e` now). Re-READ, the
Expand All @@ -86,7 +91,7 @@ const SINGLE_RECORD_WRITE_ONLY: Record<string, string> = {
// numbers — arithmetic on a wrong anchor produces a fresh-looking span still
// describing the wrong function. The second claim,
// `hooks/useBulkExecutor.ts:298-303`, sits in a file that is byte-identical
// to `87af769e9` on this hop (it last changed on the hop off `53ded82bf`, 36
// to `62597c588` and to `87af769e9` on the last two hops (it last changed on the hop off `53ded82bf`, 36
// insertions, 22 deletions, when it was re-READ rather than carried on file
// identity): the six lines hash to
// `01083348330f10a201cdf1078b4c21c236402b6a` at every one of those pins and
Expand Down
30 changes: 20 additions & 10 deletions packages/spec/src/kernel/functional-completeness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,16 +283,23 @@ 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` = `62597c588`, re-read 2026-09-23: `ListView.tsx` is
* byte-identical to `87af769e9`, and `ObjectCalendar.tsx` changed there only
* in its copy), so this describes the console this repo SHIPS and not only
* (`.objectui-sha` = `f8a9d0fb0`, re-read 2026-09-24: `ObjectCalendar.tsx`
* is byte-identical to `62597c588`, where it had changed only in its copy;
* `ListView.tsx` changed on this hop — objectui#10275's `$select` and the
* self-querying `gantt` / `tree` / `chart` filter and search of
* objectui#10037 / objectui#10250 — with its `case 'calendar'` arm
* untouched), so this describes the console this repo SHIPS and not only
* objectui's head.
* 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` = `62597c588`; `ListView.tsx`
* and `ObjectGantt.tsx` are byte-identical to `87af769e9`, where this was
* first measured, re-checked 2026-09-23). ① `ListView.tsx`'s
* this repo builds against (`.objectui-sha` = `f8a9d0fb0`, re-read
* 2026-09-24; first measured at `87af769e9`, and both files were
* byte-identical to it at `62597c588`). On this hop `ListView.tsx`'s
* `case 'gantt'` gained the EFFECTIVE `filter` and the toolbar `search` /
* `searchableFields` (objectui#10037, objectui#10250) and `ObjectGantt.tsx`
* sends them as `$search` / `$searchFields`; neither touches the date
* bindings or the config gate read below. ① `ListView.tsx`'s
* `case 'gantt'` spreads `startDateField` / `endDateField` / `titleField`
* only when the view DECLARED them — the `'start_date'` / `'end_date'`
* floors were deleted by objectui#7070, and the `'progress'` /
Expand All @@ -305,7 +312,8 @@ 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` =
* `62597c588`; `ObjectTimeline.tsx` is byte-identical to `87af769e9` too).
* `f8a9d0fb0`; `ObjectTimeline.tsx` is byte-identical to `87af769e9` and
* `62597c588` too, and `ListView.tsx`'s `case 'timeline'` did not move).
* ① `ListView.tsx`'s `case 'timeline'` resolves the axis
* through `resolveTimelineDateBinding` and spreads it only when one was
* declared — the `startDateField || 'created_at'` floor was deleted by
Expand All @@ -321,9 +329,11 @@ 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` = `62597c588`; `ObjectMap.tsx` changed on the hop
* from `87af769e9` only in a docblock and a dev-warning string, objectui
* `2252653d0`, and every read named below re-reads unchanged), both faces
* pin (`.objectui-sha` = `f8a9d0fb0`; `ObjectMap.tsx` is byte-identical to
* `62597c588`, and changed on the hop before that, from `87af769e9`, only
* in a docblock and a dev-warning string, objectui `2252653d0`;
* `ListView.tsx`'s `case 'map'` did not move, and every read named below
* re-reads unchanged), both faces
* moved together in
* objectui#8169. ① `ListView.tsx`'s `case 'map'` forwards
* `resolveListMapConfig(schema)` and carries no `locationField || 'location'`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,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` = `62597c588072636e9c30ea35b3d89b1e46fd765d` — names '
+ 'against, `.objectui-sha` = `f8a9d0fb0596f4521076628e2bbfe27e6ce67d52` — 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 8303 tracked files, against lit '
+ 'the string debounceDelay each occur 0 times across its 8512 tracked files (0 across the '
+ '8303 at 62597c588 too), against lit '
+ 'controls objectstack 12966 and @objectstack/spec 4997 on the same corpus at 87af769e9, '
+ 'which re-count at this pin to 13125 and 5043 respectively (git grep -o -F, the method '
+ 'that reproduces every earlier count).',
+ 'which re-count to 13125 and 5043 respectively at 62597c588 and to 13347 and 5123 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 '
+ 'one of a HotReloadConfig spells debounceDelayMs — concretely '
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,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` = `62597c588072636e9c30ea35b3d89b1e46fd765d`, re-read from this tree — '
+ '`.objectui-sha` = `f8a9d0fb0596f4521076628e2bbfe27e6ce67d52`, re-read from this tree — '
+ 'spells resourceLimits.timeout 0 times across '
+ '8303 tracked files, against lit controls timeout 1086, RuntimeConfig 240 and resourceLimits '
+ '2 on the same corpus; both resourceLimits hits are prose in packages/app-shell recording '
+ '8512 tracked files, against lit controls timeout 1096, RuntimeConfig 245 and resourceLimits '
+ '2 on the same corpus (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. #15939, #15678, '
+ '#14478, ADR-0087.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,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` = `62597c588072636e9c30ea35b3d89b1e46fd765d` — spells '
+ 'objectui checkout — `.objectui-sha` = `f8a9d0fb0596f4521076628e2bbfe27e6ce67d52` — spells '
+ '`flushInterval` 0 times, `initialDelay` 0, `HttpDestinationConfig` 0 and `LoggingConfig` 0 '
+ 'across its 8303 tracked files, against lit controls `useState` 2389 and `timeout` 1086 on '
+ 'the same corpus.',
+ 'across its 8512 tracked files, against lit controls `useState` 2391 and `timeout` 1096 on '
+ 'the same corpus (all four 0 across 8303, against 2389 and 1086, at 62597c588).',
acceptanceCriteria:
'Every HTTP log destination spells `batch.flushIntervalMs`, `retry.initialDelayMs` and '
+ '`timeoutMs`, and every logging buffer spells `buffer.flushIntervalMs`; authoring any of the '
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,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` = `62597c588072636e9c30ea35b3d89b1e46fd765d`, re-read from this tree — '
+ 'spells all six metrics def names and both distinctive keys 0 times across 8303 tracked '
+ 'files at that sha, against lit controls window 3526, timeout 1086, period 170, '
+ 'interval 179 and metrics 324 on that same corpus and sha, so no pin bump is owed. '
+ '`.objectui-sha` = `f8a9d0fb0596f4521076628e2bbfe27e6ce67d52`, re-read from this tree — '
+ 'spells all six metrics def names and both distinctive keys 0 times across 8512 tracked '
+ 'files at that sha, against lit controls window 3581, timeout 1096, period 171, '
+ 'interval 179 and metrics 326 on that same corpus and sha (0 across 8303, against 3526 / '
+ '1086 / 170 / 179 / 324, at 62597c588), so no pin bump is owed. '
+ '#15939, #15679, #14478, ADR-0087.',
acceptanceCriteria:
'Every metric definition spells summary.maxAgeSeconds, every error-budget burn rate window '
Expand Down
Loading
Loading