Skip to content

Commit e486abb

Browse files
committed
chore(objectui): move the console pin to 088e0f705520 (objectui#12175, PR-5: position-ref / permission-ref), and re-measure the spec's pin citations
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49
1 parent d4c22c8 commit e486abb

21 files changed

Lines changed: 290 additions & 71 deletions

‎.changeset/console-088e0f705520.md‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
"@objectstack/console": minor
3+
---
4+
5+
Console (objectui) refreshed to `088e0f705520`. Frontend changes in this range:
6+
7+
Derived from the changesets objectui declared over the range — 24 releasing of 26 changesets added across 27 non-merge commits; omitted: 2 release-nothing changesets, 1 commit carrying no changeset (they ship no package code).
8+
9+
- **minor** — A record-form field can name one item of a metadata registry by its machine name: a `text` field that declares `widget: 'position-ref'` lists the position registry, and one that d… (objectui `088e0f705`)
10+
- **minor** — **BREAKING** — Studio and the metadata admin read a metadata type's overlay flag under its new name, `allowEnvironmentOverlay`, and the read-only banners name `OS_METADATA_WRITABLE` (objectui#12… (objectui `e5311165a`)
11+
- **minor** — The marketplace package page's **Update** button opens an update dialog, and a package README's raw HTML is no longer printed as text (objectui#12146). (objectui `82bb1d584`)
12+
- **minor** — **BREAKING** — A form field declares `step` and `className` on both faces, so the strict authoring face stops telling authors to remove two keys that work. A built-in form branch now joins an en… (objectui `d2500d8be`)
13+
- **minor** — "Clone to customize" on a packaged permission set calls the server's clone door (objectui#7611, objectstack ADR-0126 §7.1). (objectui `6d5879fe9`)
14+
- **minor** — **A dashboard or a list view the server refuses you, opened by its URL, now says it was refused** (objectui#12112, the console half of objectstack#22611's ruling A). (objectui `43e150518`)
15+
- **minor** — Setup's "Assigned users" on a permission set writes a new grant by the set's name alone (objectui#7611, after objectstack#22863, ADR-0131 stage 6b-2-pre). (objectui `faf4ce952`)
16+
- **minor** — **BREAKING** — A form field declares `avatarField`, the record field each candidate of the search picker draws its avatar from, on both faces, so the strict authoring face stops telling authors… (objectui `c0c2f792b`)
17+
- **minor** — A `position` decision output lists the position registry and commits position names (objectui#7611, objectstack ADR-0131 D3/D4). (objectui `8cc7158b4`)
18+
- **minor** — The capability select lists the capability registry, and the permission-set editor's provenance badge reads the layered envelope (objectui#7611, objectstack ADR-0131 D3/D7). (objectui `53ee2f854`)
19+
- **minor** — **BREAKING** — A form field declares the rest of the field metadata its widget reads off the `fields[]` entry, on both faces, so the strict authoring face stops telling authors to remove keys th… (objectui `0665c3be7`)
20+
- **minor** — Screen readers hear the names of more controls in the viewer's language (objectui#12145). (objectui `e723f58ee`)
21+
- **minor** — The suggested-bindings panel shows each suggestion's real state and can revoke an acceptance (objectui#7611, after objectstack#22854). (objectui `f962cdc09`)
22+
- **minor** — The record feed and a related list's Add existing and fallback remove read the affordance-to-grant map, so a caller without the grant is no longer offered a write the server then… (objectui `158c75d90`)
23+
- **minor** — A paged table's first, previous, next and last page buttons have accessible names (objectui#12124). (objectui `dc6d28e86`)
24+
- **patch** — A position approver is read through the spec's registry binding, `{ source: 'registry', type }` (objectstack#22710): its readable label and its designer picker come from the posit… (objectui `83b9fade2`)
25+
- **patch** — A rich-text field no longer draws hint lines above its editor (objectui#12110, ruled B). The `markdown`, `html` and `richtext` editors used to show "Format: markdown" (or "Format:… (objectui `2498a0753`)
26+
- **patch** — The Studio app's root now opens the app's first navigation entry, like every other app's root, and `StudioHomePage`, Studio's old metadata overview, is retired (objectui#12113). (objectui `ed12d48ec`)
27+
- **patch** — A form field's own `defaultValue` is no longer drawn in its control, so the form never shows a value it does not save (objectui#12155). (objectui `f3d540814`)
28+
- **patch** — A grouped grid's own first, previous, next and last page buttons have accessible names (objectui#12143). (objectui `2381c07f3`)
29+
- **patch** — Console rendering fixes from the HotCRM browser pass (objectui#12110): (objectui `5330038f4`)
30+
- **patch** — The record page's discussion shows stored replies under their comment, and every comment offers the reply input where the caller may post one (objectui#12144). (objectui `a7d492011`)
31+
- **patch** — A record activity feed shows an object's `activityMilestones` rows of type `completed`, such as "Case resolved", instead of hiding them as completed tasks (objectui#12106). (objectui `1d1cfe0c1`)
32+
- **patch** — A record-source refusal (`RECORD_SOURCE_REQUIRED`, raised by every arm that requires a record source) now reports the same path every time (objectui#5250). (objectui `9b7550999`)
33+
34+
⚠️ 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.
35+
36+
**In this console build, declared nowhere** — objectui merged 1 commit in this range with no `.changeset/*.md`. The code is inside the pin above and ships here, but nothing upstream declared it, so it appears 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.
37+
38+
- _(no changeset)_ feat(scripts): the JSON-fence gate reads the published READMEs (objectui#12131, phase 2) (#12139) (objectui `ce9811c96`)
39+
40+
Clause-②: no
41+
42+
<!-- adr-0087: not-required (no-migration-prescription) The pin hop removes, renames or re-shapes no ObjectStack spec key, so there is nothing for `objectstack migrate meta` to rewrite and no tombstone. The four entries marked BREAKING above are objectui's own, each by its author's breaking annotation and none by a declared `major`: `@object-ui/app-shell`'s `RichMetadataTypeEntry.allowOrgOverride` member renamed to `allowEnvironmentOverlay` (objectui#12141, the console half of objectstack#22340 S2, which already renamed the server field), and three `@object-ui/types` form-field declarations (`step`, `className`, `avatarField` and the rest of the widget-read keys, objectui#12130) that widen objectui's strict authoring face and narrow its tolerant face to the declared value types. Each carries its own FROM → TO or fix in objectui's CHANGELOG. The SDUI manifest this console ships moves by one prop description (`record:activity` `inputs`), measured with `node scripts/gen-sdui-manifest-node.mjs`, so no html-page save-gate or `os validate` verdict moves. -->
43+
44+
objectui range: `4997995022f8...088e0f705520`
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
'@objectstack/spec': patch
3+
---
4+
5+
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 `088e0f705520`.
6+
7+
Clause-②: no
8+
9+
Every anchor was mapped through the objectui diff `4997995022f8..088e0f705520`: 325 paths over 27 commits. Four files a record cites changed on the hop, and every cited line in them moved or held with its text byte-identical:
10+
11+
- `ObjectGrid.tsx` (+27/-11: objectui#12143's grouped-pager button names and objectui#12110 item 1's column-label override): the bulk-selection block moved by +16 and still hashes to `c88443302d40`; the `keyboardNavigation`, `inlineEditable` and grid empty-state reads moved by +6 or +16.
12+
- `data-table.tsx` (+12/-1: objectui#12124's pager button names): the five arrow-key anchors moved by +7.
13+
- `record-related-list.tsx` (+22/-3: objectui#12082, the fallback remove reads the affordance-to-grant map): the five `requiredPermissions` gate anchors moved by +17.
14+
- `form.tsx` (+231/-79: objectui#12130, objectui#12155, objectui#12110 and objectui#7611 PR-5): `spanLadderFor` moved by +1 and its call site by +71, both unchanged, so `FormField.span: 'full'` still takes the whole row at every multi-column tier.
15+
16+
The records that cite only byte-identical files gain a hop sentence that says so. The six migration entries' corpus counts were re-taken with `git grep -o -F`, the method that reproduces every `4997995022f8` number. The corpus is now 8519 tracked files, and every retired name each entry counts still reads 0. The lit controls moved with the corpus, for example `objectstack` from 18271 to 18400 and `timeout` from 1704 to 1706.
17+
18+
No key, default, enum member or export moves.

‎.objectui-sha‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
4997995022f8e65946f6362b7434685539cc72b7
1+
088e0f705520e82bee1d65a5fa3c1f7a26672dde

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ Column footer summary configuration
213213
| **required** | `boolean` | optional | Required override |
214214
| **hidden** | `boolean` | optional | Hidden override |
215215
| **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. |
216-
| **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` = `4997995022f8`), 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. |
216+
| **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` = `088e0f705520`), 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. |
217217
| **widget** | `string` | optional | Custom widget/component name (overrides type-based inference) |
218218
| **language** | `string` | optional | Code editor language (for type=code) |
219219
| **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 |
@@ -343,7 +343,7 @@ Form-view select option — the object-field option shape minus the per-option `
343343
| **required** | `boolean` | optional | Required override |
344344
| **hidden** | `boolean` | optional | Hidden override |
345345
| **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. |
346-
| **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` = `4997995022f8`), 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. |
346+
| **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` = `088e0f705520`), 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. |
347347
| **widget** | `string` | optional | Custom widget/component name (overrides type-based inference) |
348348
| **language** | `string` | optional | Code editor language (for type=code) |
349349
| **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": "4997995022f8e65946f6362b7434685539cc72b7",
10-
"revDate": "2026-10-11T10:56:33+00:00",
9+
"rev": "088e0f705520e82bee1d65a5fa3c1f7a26672dde",
10+
"revDate": "2026-10-12T03:19:24+00:00",
1111
"source": "packages/sdui-parser/src",
1212
"files": [
1313
"packages/sdui-parser/src/body-dialect.ts",
@@ -21,7 +21,7 @@
2121
"packages/sdui-parser/src/validate.ts"
2222
]
2323
},
24-
"recordedAgainstPin": "4997995022f8e65946f6362b7434685539cc72b7",
24+
"recordedAgainstPin": "088e0f705520e82bee1d65a5fa3c1f7a26672dde",
2525
"grammarRegion": {
2626
"file": "packages/sdui-parser/src/parse.ts",
2727
"delimiter": "/* ---------------------- the JS literal subset (#6614) ---------------------- */",

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,20 @@ 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` = `499799502`, re-read there 2026-10-11:
64+
// (`.objectui-sha` = `088e0f705`, re-read there 2026-10-12:
65+
// in `packages/plugin-grid`, on the hop off `499799502`, `ObjectGrid.tsx`
66+
// changed again (27 insertions, 11 deletions: objectui#12143's grouped-pager
67+
// button names and objectui#12110 item 1's column-label override), none of it
68+
// inside the selection block, which only MOVED by +16: `ObjectGrid.tsx:4997-5024`
69+
// here (`4981-5008` at `499799502`), still hashing to
70+
// `c88443302d40c2db739ddb235470bafa29056e2e` (hash-object of the block),
71+
// re-READ with the same reading below; neither hunk touches the bulk defs or
72+
// their verdicts, so the `delete` verdict line MOVED `:1787` -> `:1793` and the
73+
// promoted def's params `:5165-5184` -> `:5181-5200` (called at `:5200` ->
74+
// `:5216`), each byte-identical. `hooks/useBulkExecutor.ts` is byte-identical
75+
// to `499799502` and its `:298-303` still hashes to
76+
// `01083348330f10a201cdf1078b4c21c236402b6a`. At `499799502`, re-read there
77+
// 2026-10-11:
6578
// in `packages/plugin-grid`, on the hop off `0df67f237`, `ObjectGrid.tsx`
6679
// changed again (89 insertions, 44 deletions: objectui#12081 item 3's
6780
// whole-set footer and objectui#12082 leg A), none of it inside the

‎packages/spec/src/kernel/functional-completeness.ts‎

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,10 @@ export function checkFieldCompleteness(def: unknown): CompletenessFinding[] {
298298
* English sentence. So the loss is total rather than partial — every
299299
* record, on every object — and the author is told at render time as well
300300
* as here. Both reads hold at the pin this repo builds against
301-
* (`.objectui-sha` = `499799502`, re-read there 2026-10-11:
301+
* (`.objectui-sha` = `088e0f705`, re-read there 2026-10-12:
302+
* every objectui file this record cites is byte-identical across the hop from
303+
* `499799502` (`git diff --quiet`), so every anchor held unmoved. At
304+
* `499799502`, re-read there 2026-10-11:
302305
* on the hop off `0df67f237` `ObjectCalendar.tsx` and `ListView.tsx` are
303306
* byte-identical (`git diff --quiet`), so `getCalendarConfig` `:311`, the
304307
* `if (!calendarConfig)` arm `:1354` with its `tt(…)` lines `:1361-1362` and
@@ -425,7 +428,10 @@ export function checkFieldCompleteness(def: unknown): CompletenessFinding[] {
425428
* This repo already records the same deletion one door over: the #13817
426429
* check in `../ui/view.zod.ts` names objectui#7029 as its runtime half.
427430
* - `gantt` → NO fallback, and no silence [#19630]. Measured at the pin
428-
* this repo builds against (`.objectui-sha` = `499799502`, re-read there 2026-10-11:
431+
* this repo builds against (`.objectui-sha` = `088e0f705`, re-read there 2026-10-12:
432+
* every objectui file this record cites is byte-identical across the hop from
433+
* `499799502` (`git diff --quiet`), so every anchor held unmoved. At
434+
* `499799502`, re-read there 2026-10-11:
429435
* on the hop off `0df67f237` `ObjectGantt.tsx` changed (+27/-4,
430436
* objectui#12082, objectui `752504520`: the chart's in-chart writes read the
431437
* affordance-to-grant map), none of it in `getGanttConfig` or the refusal arm,
@@ -524,6 +530,9 @@ export function checkFieldCompleteness(def: unknown): CompletenessFinding[] {
524530
* requires. So the view does not draw a blank chart: it refuses, by name.
525531
* - `timeline` → date axis: NO fallback [#19630]; title: `titleField || 'name'`,
526532
* which still stands. Measured at the same pin (`.objectui-sha` =
533+
* `088e0f705`, re-read there 2026-10-12:
534+
* every objectui file this record cites is byte-identical across the hop from
535+
* `499799502` (`git diff --quiet`), so every anchor held unmoved. At
527536
* `499799502`, re-read there 2026-10-11:
528537
* every objectui file this record cites is byte-identical across the hop from
529538
* `0df67f237` (`git diff --quiet`), so every anchor held unmoved. At
@@ -620,7 +629,10 @@ export function checkFieldCompleteness(def: unknown): CompletenessFinding[] {
620629
* block does render; the warning still fires there, because the block the
621630
* view TYPE names is the one that is missing. Unchanged by this row.
622631
* - `map` → NO fallback, and no silence [#19630]. Measured at the same
623-
* pin (`.objectui-sha` = `499799502`, re-read there 2026-10-11:
632+
* pin (`.objectui-sha` = `088e0f705`, re-read there 2026-10-12:
633+
* every objectui file this record cites is byte-identical across the hop from
634+
* `499799502` (`git diff --quiet`), so every anchor held unmoved. At
635+
* `499799502`, re-read there 2026-10-11:
624636
* every objectui file this record cites is byte-identical across the hop from
625637
* `0df67f237` (`git diff --quiet`), so every anchor held unmoved. At
626638
* `0df67f237`, re-read there 2026-10-11:

0 commit comments

Comments
 (0)