Skip to content

Commit 48c91e9

Browse files
chore(objectui): bump the console pin to 62597c588072 (carries the fail-closed quick_actions requiredPermissions fix) with 46 re-measured citations, the FormField.span describe re-point and the lockstep re-record (#19832)
Fixes #19503 Clause-②: no Moves the console pin to objectui `main` `62597c588072`. That tip carries objectui#10153, the fail-closed `record:quick_actions.requiredPermissions` fix. The PR also carries the bump's two required follow-ups, folded in under the PM ruling on #19503 (comment 5791879469, option A): the sdui-parser lockstep re-record, and a re-MEASURE of the `packages/spec/src/**` citations that `check:objectui-pin-citations` names. The citation edits touch comments and migration-rationale prose only; there are no schema or export changes. The one published sentence that moves is the `FormField.span` `.describe()` pin citation, authorised by the second ruling (comment 5793509969) and carried with `.changeset/19503-pin-bump-describe-corrections.md` (`@objectstack/spec: patch`) plus a regenerated `content/docs/references/ui/view.mdx`. Clause-②: no, because every authored document is accepted and refused exactly as before. `check:objectui-pin-citations` exits 0 on the head: "47 asserting objectui pin citation(s) match .objectui-sha (62597c588) … 7 anchor content assertion(s) verified". ## Ancestry reading (fix → new pin: AHEAD) Measured in a FULL (non-shallow) clone of `objectstack-ai/objectui`. `git rev-parse --is-shallow-repository` returns `false`, so an exit 0 is self-proving: | command | exit | reading | |---|---|---| | `git merge-base --is-ancestor 28b065800c7d1b6069c06aa906d0716377b5e281 62597c588072636e9c30ea35b3d89b1e46fd765d` | 0 | the fix is IN the new pin | | `git rev-list --count 28b065800c7d..62597c588` | 33 | the new pin is 33 commits ahead of the fix | | `git merge-base --is-ancestor 87af769e9a3e 28b065800c7d` | 0 | the old pin was 4 behind the fix (the card's REST `compare`: behind_by 4) | The bump's own changeset lists the fix: `fix(plugin-detail): record:quick_actions.requiredPermissions is an ADR-0066 capability set, read fail-closed ... (objectui 28b065800)`. ## What moved, and how each artefact was produced | artefact | producer | |---|---| | `.objectui-sha` + `.changeset/console-62597c588072.md` | `bash scripts/bump-objectui.sh --no-commit 62597c588072…` exit 0 (27 releasing changesets, 0 breaking, `@objectstack/console: minor`) | | `scripts/sdui-manifest.record.json` | `node scripts/gen-sdui-manifest-node.mjs --objectui-version 17.6.0` exit 0. `sdui.manifest.json` came out BYTE-IDENTICAL (sha256 `49211fee7792`, 57 components), because `packages/core` ships `17.6.0` at both pins; only the record moves | | `packages/sdui-parser/objectui-lockstep.json` | `pnpm gen:sdui-lockstep` with `OBJECTUI_ROOT` at a checkout of `62597c588`, exit 0. Diff: 3+/3-, only `rev`, `revDate` and `recordedAgainstPin`. Grammar blob `0131f27cf86d` unchanged, 214 lines, all 26 diagnostic codes agree. `check:sdui-lockstep` exit 0: "byte-identical to objectui@62597c588072". No parser port is owed | | `packages/spec/src/migrations/registry.ts` | `pnpm --filter @objectstack/spec gen:migration-registry`, from the six edited entries | | the console | `bash scripts/build-console.sh` exit 0: "Console dist ready (60524 KB) from objectui@62597c588072", bundle canary present. `check:console-sha` exit 0 | ## Citation re-measure: method - **Read-point records.** For every cited objectui file I ran `git diff --quiet 87af769e9a3e 62597c588 -- FILE`. - Unchanged file: the anchor holds by identity. The prose names that, keeps the earlier hop's history, and says where the last content re-read happened. - Changed file: each anchor was mapped through the `git diff -U0` hunks and its text compared at both pins. It was then re-read in the new tree. - **Corpus counts.** These are the six migration entries plus `registry.ts`. I re-counted with `git grep -o -F TOKEN SHA | wc -l`. The method was calibrated first: at `87af769e9a3e` it reproduces every recorded count exactly (8228 files, `useState` 2383, `timeout` 1075, `objectstack` 12966, `@objectstack/spec` 4997, `window` 3464, `interval` 170, `tenant` 976, …). - Every dark token still counts 0 at `62597c588`: the def exports and key names each entry names, 95 tokens in all. - The `Span` / `SpanSchema` collisions are unchanged at 486 / 53. - Only the corpus size (8303) and the lit controls move. ## Re-read sites (all 46 the gate named) | site(s) | objectui file(s) | reading at `62597c588` | |---|---|---| | 6 migration entries + their 6 `registry.ts` copies | whole corpus | re-counted: dark tokens still 0. The `kernel-health-check…` entry keeps its `87af769e9` lit-control clause verbatim (now dated) and adds the new counts after it. `check:future-spec-major` holds a measurement exemption to that exact sentence, and the new figure "`@objectstack/spec` 5043" would read as a version | | `component.test.ts` accordion/tabs icon; `component.zod.ts` `PageTabs` / `PageAccordion` `icon` | `containers.tsx` (changed, `4c6f549ef`) | re-read: `853-859`, `912`, `1069-1075` and `1116` did NOT move, text byte-identical | | `component.test.ts` button icon; `component.zod.ts` `element:button` `icon` | `resolve-icon.ts`, `button.tsx`, `lazy-icon.tsx` | byte-identical, so no anchor moved | | `component.zod.ts` metric `icon` | plugin-dashboard `index.tsx`, `ObjectMetricWidget.tsx`, `MetricWidget.tsx` | byte-identical | | `component.test.ts` / `component.zod.ts` kanban `limit` ×3, `quickAdd` ×2, `navigation` | plugin-kanban (all), `objectql.ts`, `ElementDataSourceGate`, `ListView.tsx`, `ObjectView.tsx`, `plugin-kanban.mdx` | byte-identical. ⚠️ The `quickAdd` block's lit control said 6 `onCardClick`; the identical file counts 11 at both pins (the test-side twin already says 11). It was miscounted, not moved, and is corrected; the verdict rests on the 0 | | `component.zod.ts` calendar `navigation` | `ObjectCalendar.tsx` (changed, `afb228418`) | re-read: `921-935`, `936` and `938-939` unmoved; `1293→1317`, `1218→1237` and `1228-1241→1250-1263`, text byte-identical | | `component.zod.ts` `object-map` header, `filter`, `sort`; `component.test.ts` / `component.zod.ts` map/gantt/tree rows; `functional-completeness.ts` map row | `ObjectMap.tsx` (changed, `2252653d0`: only `warnOnTopLevelStyleUrl`'s docblock and dev-warning text) | every anchor from `:289` on MOVED 16-19 lines with its text byte-identical (e.g. `814→833`, `895→914`, `377→396`, `382→401`, `1058→1077`); no read point or key set changed | | `component.zod.ts` gantt / tree ×3 / timeline ×2 headers; `functional-completeness.ts` gantt, timeline rows | plugin-gantt, plugin-tree, plugin-timeline, `record-source.ts`, `ListView.tsx` | byte-identical. The tree's `ElementDataSourceGate` count was re-taken: tree 0, map/gantt/grid/calendar 3 each (`plugin-grid/src/index.tsx` changed and still reads 3) | | `api-methods-batch-conformance.test.ts` `sys_api_key` | `ObjectGrid.tsx` (changed, `804831c2a` + `62597c588`) | ⚠️ the selection block's CONTENT moved: objectui#10218 rewrote the `selection` arm to "presence enables; an explicit off wins". The span is now `4024-4051` (hash `c88443302d40`, was `6133933199…` over the last three hops). Re-read, the record's claim holds: with neither `selection` nor `selectable` authored, multi-select is enabled only by `hasBulkActions`, and none of the four views declares `selection` | | `dataset.zod.ts` measure `format` | `date-display.ts` (changed, `516583b54`), `dataset-format.ts` | `formatDate` now parses via `toDisplayDate` (date-only values keep their calendar day); the cited style handling is unchanged; `198-233→271-306`, `152→225` | | `view.zod.ts` view-face `limit` reach (#19228) | 9 files | both instruments re-run: the probe returns 0, and the control returns the same 13 lines across 6 files, line for line. All 9 cited files are byte-identical | | `view.zod.ts:1975/:1978` ObjectMap anchors (content-asserted) | `ObjectMap.tsx` | re-READ against `2252653d0`: it rewrote the docblock and dev warning ABOVE `getMapConfig` (the remedy now names the declared `map: { style }`, carried out as `mapStyle`). `getMapConfig` is byte-identical, so `385→404` and `390→409`; the quoted `getMapConfig` comment is intact (`:361→:380`) | | `view.zod.ts` `FormField.span` docblock | `autoLayout.ts` (changed, `e026e15f9`), `form.tsx` | `resolveColSpan` `153→154` (an import added above it). `form.tsx` is byte-identical, so `spanLadderFor` still emits the ladder | `pnpm exec tsx scripts/check-objectui-pin-citations.ts --verify-anchors` reads: all 7 content-asserted anchors pass at `62597c588`. ## The two sites first reported, then resolved under the second ruling (comment 5793509969, option A) 1. **`packages/spec/src/kernel/functional-completeness.ts`, the calendar row: its claim had become FALSE, so it is RESTATED.** The row said the "Calendar configuration required" literal "is the text RENDERED at the pin: objectui#10101 landed AFTER the pin". `git merge-base --is-ancestor afb228418 62597c588` → 0 (and → 1 against `87af769e9a3e`). - At the new pin the screen's copy goes through `tt('calendar.configRequired', …)` (`ObjectCalendar.tsx:1207-1208`). Its default and the `en` pack read the same English sentence; `zh`, `de` and the other packs render their own words. - The `if (!calendarConfig)` refusal arm is unchanged (the `ObjectCalendar.tsx` diff on this hop is copy-only). - The row now says what renders, names the arm rather than the English sentence as the thing to match, and cites `.objectui-sha` = `62597c588`. Comment only. 2. **`packages/spec/src/ui/view.zod.ts` `FormField.span` `.describe()`: its claim still holds, so the citation is RE-POINTED.** The describe now names `.objectui-sha` = `62597c588`. - Re-read there: `plugin-form`'s `WIDE_FIELD_TYPES` is unchanged (it shifted one line; repeater still reaches it through `field:grid`), and `form.tsx` is byte-identical. - Regenerated with `pnpm --filter @objectstack/spec gen:schema && gen:docs`, which touches only the two `span` rows in `view.mdx`. - `.changeset/19503-pin-bump-describe-corrections.md` (`@objectstack/spec: patch`) states the correction, after PR #19398's `17429-pin-bump-describe-corrections.md`. ## Gates `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` on head `3fd40bedd` derives 124 families. The docs families are added by `view.mdx`. Per-family exit codes are in the os-dev-report comment on #19503. Summary: - `check:objectui-pin-citations` exit 0; `pnpm --filter @objectstack/spec check:generated` exit 0 (all 15 artefacts) - run as CI runs it and green: `check:react-declaration-parity` (`MANIFEST=$PWD/sdui.manifest.json … --baseline react-declaration-parity.baseline.json --strict`, "no new DECLARATION divergence"); the derived spelling omits the manifest input - `check:skill-examples` read exit 3 (PREREQUISITE NOT MET: `@objectstack/client-react` unbuilt) in the sweep; after `pnpm --filter '@objectstack/client-react...' build` it reads exit 0 (259 prose examples type-check). `dispatch-gates --ran`: 124 derived, 122 run, 2 NOT-MEASURED, 0 UNRUN - NOT MEASURED, left to CI: `check:dual-build-cjs-loads` and `check:type-check-debt` (both exit 3, PREREQUISITE NOT MET: they need a full workspace `pnpm build`; this diff changes only comments and migration-rationale strings in spec) - tests: `@objectstack/spec` vitest on `component.test.ts`, `api-methods-batch-conformance.test.ts`, `src/migrations`, `functional-completeness` and `src/ui/view*`: 22 files, 1562/1562 pass Changed lines: 560 (+364 / -196, 19 files), under the 5000 threshold. `origin/main` was merged in twice (`d3ff597a` before the PR was opened; `16329059b` for this round, with `view.mdx` regenerated from the merged tree as the pre-push `os-regen` check requires). ## Acceptance notes - `component.zod.ts`'s flat-map guidance block also cites `ObjectMap.tsx:382-396` without a pin. That spelling is outside the gate's population, and it now reads `401-415` (byte-identical). It was left as it is: the gate does not name it. - #18508 is not absorbed here: its trigger commit `bd09957380` is already an ancestor of the OLD pin `87af769e9a3e`. ## 维护者速读(草稿) - **改了什么**:把控制台钉住的 objectui 版本推进到 `62597c588`(包含权限修复 objectui#10153:`record:quick_actions.requiredPermissions` 改为失败即拒绝);同时按 PM 裁决 A,重录 sdui-parser 的对齐记录(只动了出处字段),并在新版本上逐条重新核对 spec 里引用 objectui 代码行号的注释。 - **为什么改**:当前发布的控制台仍按旧逻辑“失败即放行”,这是 #19186 的解锁前提;钉住版本一动,引用旧版本的注释门禁必然变红,所以这些注释必须随版本重新测量,不能只替换哈希。 - **风险与代价(含回滚)**:不改任何 schema 或导出,已写的元数据接受/拒绝结果完全不变;唯一对外文字变化是 `FormField.span` 的 describe 把所引版本改为新钉住版本(说法本身仍成立,附 spec patch changeset)。控制台行为只随 objectui 这 37 个提交变化(27 条带发布说明)。日历那一行说法在新版本上已不成立(提示文案改为按语言翻译),已按第二次裁决改写。回滚:还原本 PR 即可。 - **席位意见**: - **你要做的**:本 PR 需要在最终 head 上做一次同档合约审查,记录后才能排队;PR 保持草稿。 Dev session: `session_01852ixPjE785Lt8MUeYGDEb` (PM seat `domain:devx#1`, `session_01VDtqoecgES7ScQYGbFVDRv`). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01852ixPjE785Lt8MUeYGDEb --- _Generated by [Claude Code](https://claude.ai/code/session_01852ixPjE785Lt8MUeYGDEb)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 30854f4 commit 48c91e9

19 files changed

Lines changed: 364 additions & 196 deletions
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'@objectstack/spec': patch
3+
---
4+
5+
One published `describe` sentence that dates itself to the `.objectui-sha` pin is re-pointed to the pin this release builds against, objectui `62597c588072`, after being re-read there (#19503).
6+
7+
`Clause-②: no`
8+
9+
- `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 `87af769e9`. Re-read at `62597c588`, the claim still holds: `plugin-form`'s `WIDE_FIELD_TYPES` is unchanged (it shifted one line when an import was added above it; repeater still reaches it through `field:grid`), and `form.tsx`'s `spanLadderFor` is byte-identical, so `'full'` is still the whole row at every multi-column tier. Only the pin the sentence names moves.
10+
11+
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.

‎.changeset/console-62597c588072.md‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
"@objectstack/console": minor
3+
---
4+
5+
Console (objectui) refreshed to `62597c588072`. Frontend changes in this range:
6+
7+
Derived from the changesets objectui declared over the range — 27 releasing of 30 changesets added across 37 non-merge commits; omitted: 3 release-nothing changesets, 7 commits carrying no changeset (they ship no package code).
8+
9+
- **minor** — fix(plugin-grid): `object-grid`'s `pagination` and `selection` now read their own presence by the SAME rule — presence enables, an explicit off wins (objectui `62597c588`)
10+
- **minor** — A render-time filter refusal now renders a named "this view's filter is malformed" state instead of throwing out of render (objectui#9050). (objectui `804831c2a`)
11+
- **minor** — `record:related_list` `add.picker.filter` is declared as the contract's rule array on the authoring face, not as `unknown` (objectui#9964). (objectui `9a9780072`)
12+
- **minor** — feat(core): `object-tree` joins the curated public tier — the spec declared the block, the roster withheld it (objectui `c131d9e69`)
13+
- **minor** — A signed-in user's language has one source of truth: `sys_user.locale`. (objectui `63f4f928f`)
14+
- **minor** — A record form can no longer be saved while an upload is still in flight (objectui#10166). (objectui `e686f4d9a`)
15+
- **minor** — Nav `visible`: an ancestor's predicate now reaches the whole subtree, and a group no longer outlives its children (objectui#10119) (objectui `73a3c89af`)
16+
- **minor** — A field-backed action param reaches its record picker, and a param whose backing field cannot be read is refused instead of rendered as an empty text box (objectui#10129). (objectui `6cc910b6d`)
17+
- **patch** — fix(react): the refused-`data` dev warning can be reset between tests (objectui `befd40ccd`)
18+
- **patch** — fix(components): a half-typed `between` range in the filter builder shows itself as incomplete instead of being dropped with no signal (objectui#10061) (objectui `777fca22f`)
19+
- **patch** — fix(plugin-detail): a related list resolves `user` columns to names, like every other list (objectui `0d379f571`)
20+
- **patch** — fix(core): a date-only value renders the calendar day it names, in every viewer timezone (objectui `516583b54`)
21+
- **patch** — fix(plugin-detail): the record-grained write verdict is memoised PER PRINCIPAL (objectui#10107). (objectui `b06c3de2a`)
22+
- **patch** — fix(console): a `file` field on a FormView renders the shared upload control, not a text box (objectui `7725c10a0`)
23+
- **patch** — Stop the Studio permission matrix' Delegated Admin Scope editor authoring an `adminScope` the framework spec refuses, and make the section's collapsed badge report a scope it is c… (objectui `2d7fff3b8`)
24+
- **patch** — fix(console): mint a `sys_file` id for files picked in the global action dialogs (objectui `98178b206`)
25+
- **patch** — fix(plugin-detail): `requiredPermissions` on `record:details`, `record:highlights` and `record:related_list` is an ADR-0066 capability set, read fail-closed — it used to pass for… (objectui `c2dabf032`)
26+
- **patch** — A form no longer submits — nor offers — a field the CALLER may read but not edit (objectui#10120). (objectui `80c54122e`)
27+
- **patch** — fix(components): `page:header` resolves a lookup title candidate instead of handing its expanded object to JSX (objectui#10117) (objectui `4c6f549ef`)
28+
- **patch** — `ObjectCalendar`'s user-visible copy now reaches the locale packs. The component was already i18n-aware — it imports and calls both translation hooks — and a set of English senten… (objectui `afb228418`)
29+
- **patch** — `useSettledSchema` no longer republishes an EQUAL definition as a new object, so swapping the adapter on a record-bound view costs ONE record query instead of two. (objectui `162621b6a`)
30+
- **patch** — A form no longer emits the columns the server owns, and a master-detail batch sends only the cells the user changed (objectui#10108). (objectui `e026e15f9`)
31+
- **patch** — fix(plugin-calendar): the month gridcell's accessible name follows the resolved locale (objectui `708f2711b`)
32+
- **patch** — The AI build bar, the Studio workbench and the chat transcript's draft cards report the runtime authoring gate's per-draft advisories (objectui#10039) (objectui `e16f504d9`)
33+
- **patch** — fix(plugin-detail): `record:quick_actions.requiredPermissions` is an ADR-0066 capability set, read fail-closed — it used to pass for every reader of the object (objectui `28b065800`)
34+
- **patch** — fix(plugin-map): the top-level-`style` warning now prescribes a spelling the runtime reads (objectui `2252653d0`)
35+
- **patch** — `record:history` refuses a row cap the contract rejects instead of repairing it (objectui#10005). (objectui `cd2cb4183`)
36+
37+
**In this console build, declared nowhere** — objectui merged 7 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.
38+
39+
- _(no changeset)_ docs(agents): 一次派发跑出来的 PR 停在 draft —— 给自行合并条款加第二条例外 (#10213) (objectui `87a0ed8cf`)
40+
- _(no changeset)_ docs(agents): state the attribution-footer append as conditional on absence (#10212) (objectui `2ec310198`)
41+
- _(no changeset)_ docs(skills): the console guide names the resolver `/` actually has (objectui#10140) (#10215) (objectui `8d7915ed2`)
42+
- _(no changeset)_ ci(pm): adopt the board-snapshot archiver — route B, and the five files this repo's own gates demanded (objectui#9387) (#10203) (objectui `0cf2d6644`)
43+
- _(no changeset)_ ci: compile objectui against @objectstack/spec@main as the shape gate (objectui#9860) (#9877) (objectui `6cae9a0b3`)
44+
- _(no changeset)_ perf(console): move the `types` zod validators off the eager budgeted line (#10082) (objectui `64d250c8a`)
45+
- _(no changeset)_ ci(bundle-analysis): retire the exhausted-headroom leg, keep every ceiling (#10151) (objectui `cbda340f0`)
46+
47+
objectui range: `87af769e9a3e...62597c588072`

‎.objectui-sha‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
87af769e9a3ee28ace099fdd653d3ebd79fe82e2
1+
62597c588072636e9c30ea35b3d89b1e46fd765d

‎content/docs/references/ui/view.mdx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ Column footer summary configuration
199199
| **required** | `boolean` | optional | Required override |
200200
| **hidden** | `boolean` | optional | Hidden override |
201201
| **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. |
202-
| **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` = `87af769e9`), 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. |
202+
| **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. |
203203
| **widget** | `string` | optional | Custom widget/component name (overrides type-based inference) |
204204
| **language** | `string` | optional | Code editor language (for type=code) |
205205
| **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 |
@@ -364,7 +364,7 @@ View filter rule
364364
| **required** | `boolean` | optional | Required override |
365365
| **hidden** | `boolean` | optional | Hidden override |
366366
| **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. |
367-
| **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` = `87af769e9`), 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. |
367+
| **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. |
368368
| **widget** | `string` | optional | Custom widget/component name (overrides type-based inference) |
369369
| **language** | `string` | optional | Code editor language (for type=code) |
370370
| **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 |

‎packages/sdui-parser/objectui-lockstep.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
],
77
"objectui": {
88
"repo": "https://github.com/objectstack-ai/objectui.git",
9-
"rev": "87af769e9a3ee28ace099fdd653d3ebd79fe82e2",
10-
"revDate": "2026-09-20T15:03:40+00:00",
9+
"rev": "62597c588072636e9c30ea35b3d89b1e46fd765d",
10+
"revDate": "2026-09-23T02:43:52+00:00",
1111
"source": "packages/sdui-parser/src",
1212
"files": [
1313
"packages/sdui-parser/src/body-dialect.ts",
@@ -22,7 +22,7 @@
2222
"packages/sdui-parser/src/validate.ts"
2323
]
2424
},
25-
"recordedAgainstPin": "87af769e9a3ee28ace099fdd653d3ebd79fe82e2",
25+
"recordedAgainstPin": "62597c588072636e9c30ea35b3d89b1e46fd765d",
2626
"grammarRegion": {
2727
"file": "packages/sdui-parser/src/parse.ts",
2828
"delimiter": "/* ---------------------- the JS literal subset (#6614) ---------------------- */",

‎packages/spec/src/data/api-methods-batch-conformance.test.ts‎

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,29 +61,36 @@ const SINGLE_RECORD_WRITE_ONLY: Record<string, string> = {
6161
// `revoked` on ONE key. The multi-select surface this rule protects does not
6262
// exist for API keys, and the shape a future one would take does not need
6363
// `bulk` either — both read off the console build this release pins
64-
// (`.objectui-sha` = `87af769e9`, `packages/plugin-grid`; re-measured at
65-
// that pin, 2026-09-20 — previously measured at `53ded82bf`, `a472b0716`,
66-
// `00d3f09c5`, `67dadd602`, before that at `d8ec8d6d4`, `9602dc820`,
67-
// `190fbd01d`, `9a3daf8d3`, originally at `6314e87f2`. `ObjectGrid.tsx` DID
68-
// change again across the move off `53ded82bf` (721 insertions, 159
69-
// deletions), so the selection block this record means was re-READ rather
70-
// than carried: it is `ObjectGrid.tsx:3940-3955` here, was `3538-3553` at
71-
// `53ded82bf` and `3544-3559` at `a472b0716`, and the sixteen lines are
72-
// BYTE-IDENTICAL across the hop — `git hash-object` on both spans returns
73-
// `6133933199230670e29d8c7f51c558d86a0af1d2`, the same id the previous two
74-
// hops recorded, so the block only shifted 402 lines DOWN and none of its
75-
// substance moved. The earlier hop off
64+
// (`.objectui-sha` = `62597c588`, `packages/plugin-grid`; re-measured at
65+
// that pin, 2026-09-23 — previously measured at `87af769e9`, `53ded82bf`,
66+
// `a472b0716`, `00d3f09c5`, `67dadd602`, before that at `d8ec8d6d4`,
67+
// `9602dc820`, `190fbd01d`, `9a3daf8d3`, originally at `6314e87f2`.
68+
// `ObjectGrid.tsx` changed again across the move off `87af769e9` (119
69+
// insertions, 9 deletions), and THIS time the selection block's CONTENT
70+
// moved, not only its position: objectui#10218 (`62597c588` itself)
71+
// rewrote the `selection` arm to "presence enables; an explicit off wins",
72+
// so an authored `selection` object with no `type` now selects
73+
// (`DEFAULT_SELECTION_TYPE`, `'multiple'`) where it used to fall through.
74+
// The block is `ObjectGrid.tsx:4024-4051` here — `3940-3955` at `87af769e9`,
75+
// `3538-3553` at `53ded82bf` — and no longer hashes to the
76+
// `6133933199230670e29d8c7f51c558d86a0af1d2` the previous three hops
77+
// recorded (`c88443302d40c2db739ddb235470bafa29056e2e` now). Re-READ, the
78+
// arm this record relies on is unchanged: with neither `selection` nor
79+
// `selectable` authored, multi-select is still enabled only by
80+
// `hasBulkActions`, and the rewritten arm is reachable only by a view that
81+
// declares `selection` — which none of these four does. The earlier hop off
7682
// `00d3f09c5` is the one that caught the previous record's OWN grid anchor as
7783
// wrong rather than merely shifted: `3790-3805` there is
7884
// `runBulkActionAggregate` and says nothing about selection. That is the
7985
// #10274 class, and the reason a citation refresh re-READS instead of moving
8086
// numbers — arithmetic on a wrong anchor produces a fresh-looking span still
8187
// describing the wrong function. The second claim,
82-
// `hooks/useBulkExecutor.ts:298-303`, sits in a file that is NO LONGER
83-
// byte-identical across this hop (36 insertions, 22 deletions), so it was
84-
// re-READ rather than carried on file identity: the six lines are themselves
85-
// byte-identical (`git hash-object` on both spans returns
86-
// `01083348330f10a201cdf1078b4c21c236402b6a`) and still end on
88+
// `hooks/useBulkExecutor.ts:298-303`, sits in a file that is byte-identical
89+
// to `87af769e9` on this hop (it last changed on the hop off `53ded82bf`, 36
90+
// insertions, 22 deletions, when it was re-READ rather than carried on file
91+
// identity): the six lines hash to
92+
// `01083348330f10a201cdf1078b4c21c236402b6a` at every one of those pins and
93+
// still end on
8794
// `label = 'bulk delete'`, the line the `284-288` span cited six
8895
// pins ago stopped short of, truncating the second of the two branches it
8996
// names (byte-identity is never taken as proof an anchor is right):

0 commit comments

Comments
 (0)