diff --git a/.changeset/console-00d3f09c500c.md b/.changeset/console-00d3f09c500c.md new file mode 100644 index 00000000000..3fab0d2d390 --- /dev/null +++ b/.changeset/console-00d3f09c500c.md @@ -0,0 +1,146 @@ +--- +"@objectstack/console": minor +--- + +Console (objectui) refreshed to `00d3f09c500c`. Frontend changes in this range: + +Derived from the changesets objectui declared over the range — 80 releasing of 106 changesets added across 152 non-merge commits; omitted: 26 release-nothing changesets, 49 commits carrying no changeset (they ship no package code). + +- **minor** — `resolveTitleField` delegates to the shared ADR-0079 ladder (objectui#7287). (objectui `b61d7d80a`) +- **minor** — The last two exported type names with two authorities *inside* `@object-ui/types` now have one each (objectui#6349, second batch — the remaining intra-package collisions from the… (objectui `ac8abb0f5`) +- **minor** — `ChartSchema` declares the data model it renders — chart-level `data` and `xAxisKey`, with the bare-string `xAxis` folded onto the latter — and `ChartDataSeries` accepts both bind… (objectui `5f789538d`) +- **minor** — Repair the `filter-builder` mirror: the field key is `value`, the type vocabulary is the value families the component actually folds a column into, and a filter group is `{ id, lo… (objectui `d4493fdbc`) +- **minor** — **`BaseSchema.hidden` now declares the predicate string the renderer already evaluates** (objectui#7455, maintainer ruling 2026-09-03). (objectui `3e01cb55f`) +- **minor** — **BREAKING** — Rename `KanbanColumn.items` to `cards`, in both halves of the published surface (objectui#6939, maintainer ruling 2026-09-02). (objectui `240b80f31`) +- **minor** — Relationship-target readers resolve a lookup's target from `reference` alone, dropping the `reference_to` fallback arm (objectui#6837, half 2). (objectui `045d20ba8`) +- **minor** — Converge the two named select-option types onto one spec-derived base (objectui#7014, Q1). (objectui `98d4108a2`) +- **minor** — Localize the server's built-in aggregate measure titles on dataset charts (objectui#7258 — consumer half of the objectstack#14492 contract; maintainer ruling B, 2026-09-02). (objectui `47547d01a`) +- **minor** — **BREAKING** — **Removes a published export.** Retire the `MobileComponentConfig` type (objectui#5942, ADR-0049 enforce-or-remove). The name is deleted from `@object-ui/types` and from `@object-… (objectui `90665e07a`) +- **minor** — A non-grid view's fetch now carries a platform row ceiling, and crossing it is never silent (objectui#7210, maintainer ruling a′, 2026-09-02). (objectui `7c3df8f0c`) +- **minor** — The two report data-source keys are retired on both faces (objectui#6121, maintainer ruling of 2026-08-30, decision batch #8 — option A's retirement half; ADR-0049 enforce-or-remo… (objectui `6414dfd45`) +- **minor** — `createObjectStackAdapter` declares the adapter it returns, not the shared `DataSource` interface (objectui#7323). (objectui `6a99bb209`) +- **minor** — Publish the parameter types of the entry's own exported functions, so a consumer can name what it must pass (objectui#7324). (objectui `2d3fe73f6`) +- **minor** — Consolidate the seven lucide icon-name resolvers into one seam (objectui#5935). (objectui `e17605309`) +- **minor** — **BREAKING** — Retire the `'created_at'` timeline date-axis floors at both plugin faces (objectui#7070 step ③, maintainer ruling 2026-09-01, 总监批 #28). (objectui `04a67b9dc`) +- **minor** — `compareTo` on a `scatter` chart is no longer supported — scatter joins pie / donut / funnel on the list of chart families that ignore it (objectui#7402, maintainer ruling 2026-09… (objectui `0dc2c9324`) +- **minor** — `ObjectTimeline` refuses an undeclared date axis instead of inventing one (objectui#7459). (objectui `20cb8db9b`) +- **minor** — **Retired: `DetailViewSection.hideEmpty`.** The `record:details` section key is gone from `@object-ui/types` and `RecordDetailsRenderer` no longer reads it. Emptiness on a detail… (objectui `1f31d3af6`) +- **minor** — **BREAKING** — Retire `useObjectLabel().viewDescription()` and the `_views..description` catalog convention it resolved (objectui#7219, maintainer ruling 2026-09-02, option B — enforce-or-… (objectui `a4514e840`) +- **minor** — The eight `on*` handler keys PR #7339's census could not see now refuse by name (objectui#7344 — the objectui#6182 ruling of 2026-08-25 that the handler-expression string dialect… (objectui `ed27d7c19`) +- **minor** — **BREAKING** — Removed the block schema family (objectui#4895, ADR-0049 enforce-or-remove, maintainer ruling 2026-09-02 — option C1, retire the family in one change, no transition window). (objectui `d88e20f55`) +- **minor** — `DataErrorState` accepts the icon props `DataEmptyState` already had, and `ListView`'s load-failure panel is now rendered by the error state instead of the empty state (objectui#7… (objectui `78ca23810`) +- **minor** — **Renamed:** the declared input carrying the action's execution type on `action:button` and `action:icon` is now `actionType`. It used to be `type`, which collides with the SDUI e… (objectui `f0bb9fa31`) +- **minor** — Size the gantt task list from its container, and give a row's dates ONE predicate (objectui#7204, objectui#7224; maintainer ruling 2026-09-02, option Y). (objectui `bf244f400`) +- **minor** — `objectui validate` now prints the failing union arm the document selected, instead of a bare "Invalid input" (objectui#7004, maintainer ruling 2026-09-02 — option B). (objectui `a5d55472b`) +- **minor** — **BREAKING** — Mixed id/object action arrays are refused; use all ids or all objects (objectui#7182, maintainer ruling 2026-09-02, option C). (objectui `b65251465`) +- **minor** — Studio workbench rails converge on an AI copilot apply without a page reload (objectui#7255) (objectui `1688986a3`) +- **minor** — A gantt timeline whose rows are malformed now refuses to draw, naming the row, instead of crashing the render (objectui#7164, maintainer ruling A+). (objectui `20c04b232`) +- **minor** — Studio workbench and AI tool cards speak the author's language (objectui#7254) (objectui `f1574235e`) +- **minor** — Two widget prop types anchor their `schema` to exported schema types that extend `BaseSchema`, instead of hand-rolled inline literals with no `BaseSchema` in their ancestry (objec… (objectui `4ca30d044`) +- **minor** — Fix the three breaks at the AI paywall moment (#7253), measured on a free plan's second build iteration when the cloud guardrail refuses "Confirm changes" with a 429 `AI_DESIGN_QU… (objectui `63b4e0e71`) +- **minor** — `@object-ui/types/zod`: the 58 `on*` handler keys declared `z.function()` now refuse BY NAME (objectui#6124) (objectui `a8d5c717e`) +- **minor** — `disabled` accepts a predicate string — `boolean | string`, the `BaseSchema` union — on the 18 concrete schemas that used to narrow it back to `boolean` (objectui#7087, maintainer… (objectui `c93b4d5f3`) +- **minor** — **BREAKING** — `record:details` section headings converge on the declared `label` slot; the `title` alias limb is gone (objectui#6190, maintainer ruling 2026-08-31 — option A, three producers pl… (objectui `1e7fe0a65`) +- **minor** — **BREAKING** — `ObjectFormSection` no longer declares `className` / `gridClassName` (objectui#7200 — the declared-but-inert remainder of objectstack#13626). (objectui `2e32ed475`) +- **minor** — feat(data-table): pass `pendingRow` to the host cell editor — the row with its staged edits merged over it (#7188) (objectui `adbda1bed`) +- **minor** — feat(types): `renderCellEditor`'s context gains `pendingRow` — the persisted row merged with its staged, unsaved edits (#7188) (objectui `adbda1bed`) +- **patch** — `button-group` honors per-button `disabled`, and the catalog stops authoring 29 keys nothing reads (objectui#7077, maintainer ruling 2026-09-04, decision batch #25). (objectui `00d3f09c5`) +- **patch** — Fix `record-alert` with `severity: 'success'` rendering a database glyph instead of a check mark (objectui#7593). (objectui `fe8f4515d`) +- **patch** — Correct two retired lucide spellings on component-registration `icon` meta (objectui#5936, the behaviour-neutral slice). (objectui `e30ed155c`) +- **patch** — fix(plugin-calendar): the all-day lane header reads the same string with or without an I18nProvider (objectui `b8fc1e2bf`) +- **patch** — `dashboard.noRows` and `dashboard.noDataAvailable` are retired — two rows removed from each of the ten locale packs, 20 entries, zero readers (objectui#7125). (objectui `14906917f`) +- **patch** — `ui:icon` and `ui:spinner` route their host spread through `toDomProps` (objectui#5632, the `BARE_SPREAD_ON_SVG` slice of objectui#5574). (objectui `e304a4ef7`) +- **patch** — Relay a per-view `rowColor` through the two object-view hosts (objectui#7218). (objectui `34ea56de7`) +- **patch** — Repair the `tree-view` mirror: `data` is optional, so the `nodes` spelling the renderer reads FIRST is a legal document on its own (objectui#6939, maintainer ruling recorded 2026-… (objectui `777e5c6f4`) +- **patch** — Field designer: clearing a picklist option's **Label** no longer produces metadata the API refuses (objectui#7014 Q2). (objectui `f0f774b0d`) +- **patch** — Delete the second, dead `SchemaRenderer` in `packages/components/src` (objectui#7319). (objectui `26e06d706`) +- **patch** — Correct three false `@objectstack/spec` alignment claims on field metadata, and pin the real boundary (objectui#7014). (objectui `0e3b3be09`) +- **patch** — The settled-schema convergence, and the gantt's duplicate query gated (objectui#7225, maintainer ruling B, 2026-09-02). (objectui `7c3df8f0c`) +- **patch** — A scatter handed more than one series now refuses instead of drawing a false picture. (objectui `e8c553bcb`) +- **patch** — Render a dataset measure over a date field as a date (objectui#7178, maintainer ruling 2026-09-02, director summon #8 — option A). (objectui `48c19bd48`) +- **patch** — Repair the `object-map` and `object-gantt` mirrors: `objectName` is optional, and a refinement requires that at least one of `data`, `staticData`, `objectName` is present (objectu… (objectui `77cb489b4`) +- **patch** — `DataTableSchema.rowActions` validates as the boolean it has always been declared to be (objectui#6940, maintainer ruling 2026-09-02, director seat summon #8, option A). (objectui `0c386dd7f`) +- **patch** — Repair the `tooltip` and `context-menu` mirrors: declare the keys their renderers actually read, and stop requiring the `children` neither of them reads (objectui#6939, maintainer… (objectui `bfaa1589c`) +- **patch** — Correct `BaseSchema.hidden`'s JSDoc: it hides by NOT RENDERING, exactly as `visible: false` does (objectui#7088, maintainer ruling 2026-09-01). (objectui `c1fe272ad`) +- **patch** — fix(plugin-calendar): a record with no date is no longer placed on today (objectui `bc5870c9f`) +- **patch** — `ui:text` now honours `TextSchema.variant` and `TextSchema.align` (objectui `57f9b077b`) +- **patch** — Implement `ListColumn.wrap` — a column that says it wraps now actually wraps (objectui#6650, maintainer ruling 2026-09-02, Option B). (objectui `d6ceb8d29`) +- **patch** — FLS-gate the `$expand` projection at the five remaining build sites (objectui#7230). (objectui `6411def25`) +- **patch** — Name the scatter legend's series, so its swatch stops reading as a stray data point (objectui#7248). (objectui `bb459ea9c`) +- **patch** — Draw every categorical x-axis label on short axes (objectui `d6fe1e1f2`) +- **patch** — **Bug — a `code`/`text` value whose text is JSON rendered as the literal `[Object]`.** `coerceToSafeValue` classified strings by SHAPE: any string starting `{`/`[` and ending `}`/… (objectui `b6e83be6a`) +- **patch** — fix(core): `ValueDataSource` applies the filters it is given instead of returning every row (objectui `7776fc268`) +- **patch** — Fix `AiUsageIndicator` to recognize the free plan's new `resetKind: 'weekly'` and its `resetsAt` (objectui#7371, consumer of cloud PR #1852's rolling 7-day AI quota window). (objectui `339970446`) +- **patch** — The console chrome's Home affordances follow the product's declared landing (objectui#7256). (objectui `d4c6a86a1`) +- **patch** — A master-detail form no longer ends on a screen asserting both a failure and a success (objectui#7345). (objectui `7dedec6f1`) +- **patch** — Grid: a malformed entry in `grouping.fields[]` no longer crashes the whole grid. (objectui `e21308ef2`) +- **patch** — A form no longer ends on a screen asserting both a failure and a success (objectui#7252). (objectui `4704aa4bb`) +- **patch** — `MetadataHmrReloader` stops flooding a production-posture deployment with `GET /api/v1/dev/metadata-events` 404s (objectui#7257). (objectui `ef1ffc283`) +- **patch** — Stop the record header title from collapsing when the action tail is wide (objectui `ab9294039`) +- **patch** — A synthesized default list view now always leads with the object's name field (objectui#7245). (objectui `19f16390d`) +- **patch** — `colorField` now means the same thing in the gantt, the calendar and the timeline (objectui#7243). (objectui `e75f4c986`) +- **patch** — `AiPendingActionsInbox` speaks the session locale — every string in it, not only its timestamps (objectui#7173). (objectui `01c90238e`) +- **patch** — Studio's package switcher reads the server's `writable` verdict instead of guessing from `manifest.scope` (objectui#7177, ADR-0130 Consequences row 6, server half in objectstack#1… (objectui `ebc05b4d6`) +- **patch** — fix(components): eight widgets now consume `SchemaRenderer`'s evaluated `disabled` verdict instead of re-reading the raw authored key (objectui `b9f5ff128`) +- **patch** — `RuntimeWidgetManifest` / `RuntimeWidgetSource` document the spec's retired `WidgetManifest` / `WidgetSource` as HISTORY, instead of describing them as a live schema (objectui#521… (objectui `64d624ded`) +- **patch** — FLS-gate the speculative half of `ListView`'s `$select` projection (objectui#7216). (objectui `ac257b31f`) +- **patch** — Fix: a `dependsOn` lookup edited inline follows a parent edited in the same row **before** it is saved (#7188, finishing #7165). (objectui `adbda1bed`) +- **patch** — `ObjectGantt` no longer blanks the chart when one reload supersedes another (objectui `92c65aab7`) + +⚠️ 8 of these carry a breaking change: 8 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 49 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(skills): retire the four root-devdep rows by unmarking their fences (#7557) (#7568) (objectui `24135aba1`) +- _(no changeset)_ docs(console): re-fence three design-token lists as tables, not `tsx` (#7583) (objectui `b80d40574`) +- _(no changeset)_ fix(scripts): read snippet imports from the AST in both gates (#7569) (objectui `78d592bb9`) +- _(no changeset)_ feat(scripts): bound snippet resolution at the repository root manifest (#7554) (objectui `28b3cc3ab`) +- _(no changeset)_ docs(ci-cd-pipeline): document the MARKED_FLOOR shrink-only ratchet (#7563) (objectui `98f51962b`) +- _(no changeset)_ feat(scripts): make the marked skill-example population shrink-only, per category (#7553) (objectui `403e3e555`) +- _(no changeset)_ docs(scripts): stop restating the eager-closure headroom in prose (#7529) (objectui `d04e79a80`) +- _(no changeset)_ fix(skills): teach the honest test-double idiom in testing.md, retiring its three bare-any rows (#7496) (objectui `a27d153c2`) +- _(no changeset)_ feat(scripts): assert no bare `any` in a marked skill example, and scan `.claude/skills` too (#7490) (objectui `ac8d5233d`) +- _(no changeset)_ fix(console,scripts): give the locale catalogue its own chunk, so the framework ceiling budgets the framework (#7489) (objectui `177afeba1`) +- _(no changeset)_ docs(plugin-dashboard): shrink UNGATED_DOCS by one — the dashboard README's 12 blocks now compile (#7485) (objectui `c4f541df9`) +- _(no changeset)_ docs(app-shell): shrink UNGATED_DOCS by one — app-shell README's 11 blocks compile honestly (#5174 batch 11) (#7484) (objectui `c39c825d3`) +- _(no changeset)_ feat(scripts): gate every eval must_contain token against the guides its bundle ships (#7475) (objectui `e307c9896`) +- _(no changeset)_ docs(plugin-report,docs): shrink UNGATED_DOCS by four — plugin-report README plus the last three .mdx entries (#7458) (objectui `0246d116e`) +- _(no changeset)_ docs(agents): record the search qualifier-token hazard beside the channel-control rule (#7452) (objectui `3804c222b`) +- _(no changeset)_ feat(gates): check the marked fenced examples in the skill guides (#7427) (objectui `c92dc4106`) +- _(no changeset)_ skills(objectui): two eval assertions stop grading accidental substrings, one re-points to the taught spelling (#7405) (#7422) (objectui `12bca5356`) +- _(no changeset)_ skills(objectui): page-builder teaches `section`, and stops claiming a closed set of five (#7416) (objectui `a37600b06`) +- _(no changeset)_ skills(objectui): evals grade what the guides teach — six assertions re-pointed or dropped, two substring accidents fixed, registerComponent taught (#7360) (#7408) (objectui `24d4a21ff`) +- _(no changeset)_ chore(deps): Bump mermaid from 11.17.0 to 11.17.1 (#7411) (objectui `b3a6531d8`) +- _(no changeset)_ chore(deps): Bump fumadocs-ui from 16.14.4 to 16.15.4 (#7060) (objectui `bde6483b1`) +- _(no changeset)_ chore(scripts): check-shell-escape-residue scans .claude/skills too — the 18 fenced blocks #7251 moved, back on its surface (#7403) (#7414) (objectui `9398a8155`) +- _(no changeset)_ docs(ci): skills-paths header names both scan roots and drops the file count (#7412) (objectui `5e9b18903`) +- _(no changeset)_ chore(scripts): check-skills-paths scans .claude/skills too — 27 to 88 stated paths under the gate, the #7251 pins restored (#7358) (#7407) (objectui `7c7729859`) +- _(no changeset)_ test(schema-catalog): pin the two unsealed authored-key pairs (objectui#6810) (#7395) (objectui `0614b6df1`) +- _(no changeset)_ chore(deps): Bump js-yaml from 5.2.3 to 5.4.1 (#7055) (objectui `d53e472f5`) +- _(no changeset)_ chore(deps): Bump i18next from 26.3.6 to 26.4.0 (#7056) (objectui `74f973a86`) +- _(no changeset)_ chore(deps): Bump mermaid from 11.16.1 to 11.17.0 (#7283) (objectui `90bc5d16a`) +- _(no changeset)_ docs(skills): verify — VFY-C-01, prescribe the stable Chromium alias (#7375) (objectui `d4bf7f741`) +- _(no changeset)_ skills(objectui): optimization flight — contributor-only content moved out, duplicates merged into rules/, router first, three evals corrected (net −20,344 tokens, −31.8%) (#7370) (objectui `0af240f05`) +- _(no changeset)_ docs(agents): record how GitHub mangles agent-written bodies, and the per-query search control (#7317) (objectui `2956d7af8`) +- _(no changeset)_ test(hooks): add the missing self-test matrix for guard-main-checkout.sh (#7264) (objectui `9650430f3`) +- _(no changeset)_ docs(agents): record that seats cannot delete remote branches (#7242) (objectui `1e30554f3`) +- _(no changeset)_ fix(test): point `test:integration` at projects that exist, and pin the agreement (#7327) (objectui `dfb60ae61`) +- _(no changeset)_ docs(data-objectstack,plugin-form,plugin-view): clear three package READMEs off the doc-snippet ledger (#5174 batch 8) (#7326) (objectui `c85b7aa24`) +- _(no changeset)_ docs(plugins,utilities,tooling): clear three more .mdx pages off the doc-snippet ledger (#5174 batch 7) (#7325) (objectui `a9b7bc742`) +- _(no changeset)_ docs(plugins,utilities): clear three more .mdx pages off the doc-snippet ledger (#5174 batch 6) (#7314) (objectui `0c20357ec`) +- _(no changeset)_ feat(scripts): pin documented `interface` blocks against the shipped type, both ways (#7306) (objectui `39c2c1285`) +- _(no changeset)_ test(infra): attribute and gate the ECONNREFUSED network-escape class repo-wide (#7304) (objectui `99614bb1f`) +- _(no changeset)_ test(config): state the unit project's real `isolate: false` invariant, and enforce it (#7309) (objectui `d717e8bc3`) +- _(no changeset)_ test(e2e): tell an open modal from a blank viewport in the boot-continuity rule (#7305) (objectui `4b2f9fa81`) +- _(no changeset)_ docs(guides,plugins,tooling): clear three .mdx pages off the doc-snippet ledger (#5174 batch 5) (#7294) (objectui `9bf0abfec`) +- _(no changeset)_ feat(scripts): derive retirement from the tombstone registry in the designer key-parity gate (#7290) (objectui `ec0a7b846`) +- _(no changeset)_ test(scripts): pin the prose attached to the eager-closure baselines to the values it explains (#7286) (objectui `5dbbde6d2`) +- _(no changeset)_ test(scripts): pin the published stylesheet banner per subject (#7044) (#7285) (objectui `5a053e841`) +- _(no changeset)_ docs(changeset): write the anti-collision filename convention into the README (#7280) (objectui `ad2e19341`) +- _(no changeset)_ fix(tooling): drop the derivation gate's export filter — rule 2 as a one-liner, rule 1 scoped (#7274) (objectui `9207c53e4`) +- _(no changeset)_ feat(gates): cover the permission authoring shapes in designer-field-key-parity (#7272) (objectui `a64bd9c37`) +- _(no changeset)_ ci: bound the seven remaining cache saves so bookkeeping cannot void a verdict (#7269) (objectui `1c4e2daac`) + + + +objectui range: `67dadd602a3a...00d3f09c500c` diff --git a/.objectui-sha b/.objectui-sha index 0d080b5c2ab..39cdb8179c6 100644 --- a/.objectui-sha +++ b/.objectui-sha @@ -1 +1 @@ -67dadd602a3a891666ea1513c5de677140784b6a +00d3f09c500c4a45b5f27aca8af80349412faaf1 diff --git a/packages/sdui-parser/objectui-lockstep.json b/packages/sdui-parser/objectui-lockstep.json index 5a7fe8b69f0..64f4194dee5 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": "67dadd602a3a891666ea1513c5de677140784b6a", - "revDate": "2026-09-01T16:00:05Z", + "rev": "00d3f09c500c4a45b5f27aca8af80349412faaf1", + "revDate": "2026-09-04T04:22:27Z", "source": "packages/sdui-parser/src", "files": [ "packages/sdui-parser/src/codegen.ts", @@ -20,7 +20,7 @@ "packages/sdui-parser/src/validate.ts" ] }, - "recordedAgainstPin": "67dadd602a3a891666ea1513c5de677140784b6a", + "recordedAgainstPin": "00d3f09c500c4a45b5f27aca8af80349412faaf1", "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 4b7621de7ff..40cd4316556 100644 --- a/packages/spec/src/data/api-methods-batch-conformance.test.ts +++ b/packages/spec/src/data/api-methods-batch-conformance.test.ts @@ -61,14 +61,14 @@ 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` = `67dadd602`, `packages/plugin-grid`; re-measured at - // that pin, 2026-09-02 — previously measured at `d8ec8d6d4`, before that at - // `9602dc820`, `190fbd01d`, `9a3daf8d3`, originally at `6314e87f2`. - // `ObjectGrid.tsx` DID change across the move off `d8ec8d6d4` (seven - // commits, 461 lines), so both claims below were re-derived rather than - // carried over: `ObjectGrid.tsx:3436-3451`, whose block is byte-identical - // to the one cited at `d8ec8d6d4:3187-3202` and shifted only by insertions - // above it, and + // (`.objectui-sha` = `00d3f09c5`, `packages/plugin-grid`; re-measured at + // that pin, 2026-09-04 — previously measured at `67dadd602`, before that at + // `d8ec8d6d4`, `9602dc820`, `190fbd01d`, `9a3daf8d3`, originally at + // `6314e87f2`. `ObjectGrid.tsx` DID change across the move off `67dadd602` + // (171 insertions, 81 deletions), so both claims below were re-derived + // rather than carried over: `ObjectGrid.tsx:3790-3805`, whose block is + // byte-identical to the one cited at `67dadd602:3436-3451` and shifted only + // by insertions above it, and // `hooks/useBulkExecutor.ts:284-289`, in a file byte-identical at both pins // and re-READ there rather than carried on that identity — it still ends on // `label = 'bulk delete'`, the line the `284-288` span cited three pins ago diff --git a/packages/spec/src/ui/component.test.ts b/packages/spec/src/ui/component.test.ts index e361ec0ffaa..96f8e2a39ce 100644 --- a/packages/spec/src/ui/component.test.ts +++ b/packages/spec/src/ui/component.test.ts @@ -274,19 +274,17 @@ describe('PageAccordionProps variant (#6776)', () => { // sweep once read as declared-but-unenforced. It has a live cross-repo consumer: // objectui's `PageAccordionRenderer` renders `{item.icon && }` inside the `AccordionTrigger` -// (`packages/components/src/renderers/layout/containers.tsx:918-924`), and the +// (`packages/components/src/renderers/layout/containers.tsx:919-925`), and the // same file's `ComponentRegistry.register('accordion', …)` publishes the key to -// the Studio block designer at `:965` (the `items` input, documented as +// the Studio block designer at `:966` (the `items` input, documented as // `[{ label, icon?, collapsed?, children }]`). Measured at the pin this repo -// builds against — `.objectui-sha` = `67dadd602`. Re-derived at that pin -// 2026-09-02: `containers.tsx` DID change across the move off `d8ec8d6d4` -// (164 lines), but that change lands from `:995` on, below both anchors (its -// only edit above them rewrites one import line in place), so neither moved — -// the icon block is still `918-924` and the registration input still `965`, -// each re-READ there with the cited text unchanged. The earlier hop off -// `9602dc820` is the one that moved them, `851-857` → `918-924` and `898` → -// `965`. Every anchor was re-READ at the new pin, never inferred, because -// identity preserves a wrong anchor as faithfully as a right one (#10274). +// builds against — `.objectui-sha` = `00d3f09c5`. Re-derived at that pin +// 2026-09-04: `containers.tsx` DID change across the move off `67dadd602` +// (117 insertions, 63 deletions), and this time both anchors moved by exactly +// one line — the icon block `918-924` to `919-925` and the registration input +// `965` to `966` — each re-READ there with the cited text unchanged. Every +// anchor was re-READ at the new pin, never inferred, because identity +// preserves a wrong anchor as faithfully as a right one (#10274). // // #9397 spent a full dispatch cycle re-deriving that read point from scratch // after the sweep proposed retiring the key. This block plus the `.describe()` @@ -365,18 +363,16 @@ describe('PageTabsProps items[].value / items[].count (#5775)', () => { // same bare declaration a liveness sweep reads as declared-but-unenforced. // objectui's `PageTabsRenderer` renders `{item.icon && }` inside the `TabsTrigger` -// (`packages/components/src/renderers/layout/containers.tsx:729-735`), and the +// (`packages/components/src/renderers/layout/containers.tsx:730-736`), and the // same file's `ComponentRegistry.register('tabs', …)` publishes the key to the -// Studio block designer at `:788` (the `items` input, documented as +// Studio block designer at `:789` (the `items` input, documented as // `[{ label, value?, icon?, count?, visibleWhen?, children }]`). Measured at -// the pin this repo builds against — `.objectui-sha` = `67dadd602`. Re-derived -// at that pin 2026-09-02: `containers.tsx` DID change across the move off -// `d8ec8d6d4` (164 lines), but that change lands from `:995` on, below both -// anchors, so neither moved — the icon block is still `729-735` and the -// registration input still `788`, each re-READ there with the cited text -// unchanged. The earlier hop off `9602dc820` is the one that moved them, -// `662-668` → `729-735` and `721` → `788`. Both were re-READ at the new pin, -// never inferred (#10274). +// the pin this repo builds against — `.objectui-sha` = `00d3f09c5`. Re-derived +// at that pin 2026-09-04: `containers.tsx` DID change across the move off +// `67dadd602` (117 insertions, 63 deletions), and both anchors moved by +// exactly one line — the icon block `729-735` to `730-736` and the +// registration input `788` to `789` — each re-READ there with the cited text +// unchanged. Both were re-READ at the new pin, never inferred (#10274). // // #9397 spent a full dispatch cycle re-deriving the accordion's read point // after the sweep proposed retiring it. This block plus the `.describe()` it @@ -2673,12 +2669,16 @@ describe('#7751 — object-* block props schemas', () => { // #9881 and #9972 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` = `67dadd602`, re-derived there 2026-09-02: `button.tsx` and -// `resolve-icon.ts` are both byte-identical to the ones at `d8ec8d6d4` (and at -// `9602dc820` before it), and every anchor below was still re-READ at the new -// pin rather than carried on that identity (#10274). Neither the move off -// `d8ec8d6d4` nor the one off `9602dc820` changed the read point or a single -// line number here. +// `.objectui-sha` = `00d3f09c5`, re-derived there 2026-09-04. This hop is the +// first that changed the record's SUBSTANCE and not merely its line numbers: +// `resolve-icon.ts` was restructured (110 insertions), so `resolveIcon` no +// longer PascalCases and maps inline — it delegates to the new +// `describeIconLookup` seam (`:117-120`), and the tokeniser now splits on +// hyphen, underscore AND whitespace (`/[-_\s]+/`), where this record used to +// say "splits on `-` only". That sentence was true when written and is false +// now, which is exactly why a citation refresh re-READS instead of moving +// numbers (#10274). `button.tsx` also changed (18 insertions): its anchors +// moved rather than died. // The one move that changed the button READ POINT and not merely its line // numbers was the one onto `9602dc820`: objectui#5993 deleted `button.tsx`'s // file-local `toPascalCase` + `iconNameMap` + `icons` index and routed the @@ -2694,11 +2694,13 @@ describe('ElementButtonPropsSchema icon liveness (#10053)', () => { const button = ComponentPropsMap['element:button']; it('accepts an icon on a button — the value objectui resolves through the lucide `icons` map', () => { - // objectui `packages/components/src/renderers/form/button.tsx:36` hands the + // objectui `packages/components/src/renderers/form/button.tsx:43` hands the // name to the shared `resolveIcon` - // (`packages/components/src/renderers/action/resolve-icon.ts:30-35`), which - // PascalCases it and applies the one-entry rename map at `:14-24` before - // looking it up in `icons` from `lucide-react`; `button.tsx:57` / `:59` + // (`packages/components/src/renderers/action/resolve-icon.ts:129-132`), + // which delegates to `describeIconLookup` (`:117-120`): that PascalCases + // through `toPascalCase` (`:100-105`, splitting on hyphen, underscore or + // whitespace) and applies the one-entry rename map (`:90-92`) before the + // lookup in `icons` from `lucide-react`; `button.tsx:72` / `:74` // draw it either side of the label per `iconPosition`. const result = button.safeParse({ label: 'Save', icon: 'arrow-right' }); expect(result.success).toBe(true); diff --git a/packages/spec/src/ui/component.zod.ts b/packages/spec/src/ui/component.zod.ts index 14d8bb446dc..0fb17a6c19e 100644 --- a/packages/spec/src/ui/component.zod.ts +++ b/packages/spec/src/ui/component.zod.ts @@ -675,18 +675,17 @@ export const PageTabsProps = strictObject({ * false candidate a component over). * * The key is LIVE at the objectui pin this repo builds against - * (`.objectui-sha` = `67dadd602`; re-derived at that pin 2026-09-02 — - * `containers.tsx` DID change across the move off `d8ec8d6d4`, but that - * change lands from `:995` on, below both anchors, so neither moved: the - * icon block is still `729-735` and the registration input still `788`, - * each re-READ there with the cited text unchanged, never inferred; the - * earlier hop off `9602dc820` is the one that moved them, `662-668` → - * `729-735` and `721` → `788`): `containers.tsx:729-735` + * (`.objectui-sha` = `00d3f09c5`; re-derived at that pin 2026-09-04 — + * `containers.tsx` DID change across the move off `67dadd602` (117 + * insertions, 63 deletions) and both anchors moved by exactly one line: + * the icon block from `729-735` and the registration input from `788`, + * each re-READ at the new pin with the cited text unchanged, never + * inferred): `containers.tsx:730-736` * renders * `{item.icon && }` inside the * `TabsTrigger`, left of the label span (`mr-1.5 h-3.5 w-3.5 shrink-0 * opacity-70`, `aria-hidden`), and the renderer's registration publishes - * the key to the Studio block designer at `:788` (the `items` input, + * the key to the Studio block designer at `:789` (the `items` input, * documented as `[{ label, value?, icon?, count?, visibleWhen?, children * }]`). * @@ -1735,18 +1734,17 @@ export const PageAccordionProps = strictObject({ * re-derive the same false candidate). * * The key is LIVE at the objectui pin this repo builds against - * (`.objectui-sha` = `67dadd602`; re-derived at that pin 2026-09-02 — - * `containers.tsx` DID change across the move off `d8ec8d6d4`, but that - * change lands from `:995` on, below both anchors, so neither moved: the - * icon block is still `918-924` and the registration input still `965`, - * each re-READ there with the cited text unchanged, never inferred; the - * earlier hop off `9602dc820` is the one that moved them, `851-857` → - * `918-924` and `898` → `965`): `containers.tsx:918-924` + * (`.objectui-sha` = `00d3f09c5`; re-derived at that pin 2026-09-04 — + * `containers.tsx` DID change across the move off `67dadd602` (117 + * insertions, 63 deletions) and both anchors moved by exactly one line: + * the icon block from `918-924` and the registration input from `965`, + * each re-READ at the new pin with the cited text unchanged, never + * inferred): `containers.tsx:919-925` * renders * `{item.icon && }` inside the * `AccordionTrigger`, grouped with the label in the trigger's one wrapping * span, and the renderer's registration publishes the key to the Studio - * block designer at `:965` (the `items` input, documented as + * block designer at `:966` (the `items` input, documented as * `[{ label, icon?, collapsed?, children }]`). * * Vocabulary is Lucide, resolved through objectui's `LazyIcon` @@ -1943,15 +1941,19 @@ export const ElementButtonPropsSchema = lazySchema(() => strictObject({ * the button. * * The key is LIVE at the objectui pin this repo builds against - * (`.objectui-sha` = `67dadd602`; re-derived at that pin 2026-09-02 — - * `button.tsx` and `resolve-icon.ts` are both byte-identical to the ones at - * `d8ec8d6d4` (and at `9602dc820` before it) and every anchor below is - * unmoved, each one re-READ at the new pin rather than carried on that - * identity (#10274). The read point MOVED - * rather than died on the earlier hop onto `9602dc820`, which is why the - * anchors below span a second file): `components/src/renderers/form/ - * button.tsx:36` resolves `schema.icon` through the shared `resolveIcon`, - * and `:57` / `:59` render it on either side of the label per + * (`.objectui-sha` = `00d3f09c5`; re-derived at that pin 2026-09-04 — BOTH + * files changed across the move off `67dadd602`, and this is the first hop + * that moved the record's SUBSTANCE rather than only its line numbers: + * `resolve-icon.ts` was restructured (110 insertions) so the resolution now + * runs through a named `describeIconLookup` seam, and its tokeniser accepts + * more spellings than this record used to claim — see the corrected + * breakdown below. `button.tsx` changed by 18 insertions and its anchors + * moved. Every anchor below was re-READ at the new pin, never carried + * (#10274); the read point first MOVED rather than died on the earlier hop + * onto `9602dc820`, which is why the anchors span a second file): + * `components/src/renderers/form/ + * button.tsx:43` resolves `schema.icon` through the shared `resolveIcon`, + * and `:72` / `:74` render it on either side of the label per * `iconPosition` (`mr-2 h-4 w-4` left, `ml-2 h-4 w-4` right), both * suppressed while `loading`. * @@ -1959,11 +1961,16 @@ export const ElementButtonPropsSchema = lazySchema(() => strictObject({ * this surface use — it is the `action:*` resolver, and the two accept * different spellings: * - here: `resolveIcon` - * (`components/src/renderers/action/resolve-icon.ts:30-35`) → - * `toPascalCase`, which splits on `-` only, then a one-entry rename map - * (`Home` → `House`), both at `:14-24` → `icons[name]` from - * `lucide-react`. An unknown name resolves to `null` and the button - * renders with NO icon and no diagnostic anywhere. + * (`components/src/renderers/action/resolve-icon.ts:129-132`) delegates + * to `describeIconLookup` (`:117-120`), which PascalCases through + * `toPascalCase` (`:100-105`) and then applies a one-entry rename map + * (`Home` becomes `House`, `:90-92`) before the `icons[key]` lookup from + * `lucide-react`. ⚠️ The tokeniser splits on hyphen, underscore OR + * whitespace (`/[-_\s]+/`) as of this pin; this record previously said + * "splits on `-` only", which was true when written and is not now — a + * re-READ caught it, a line-number refresh would not have. An unknown + * name still resolves to `null` and the button renders with NO icon and + * no diagnostic anywhere. * - `LazyIcon` / `getLazyIcon` (`components/src/lib/lazy-icon.tsx:66-92`): * normalises to kebab-case, checks the name against Lucide's own name * list, and degrades an unknown name to the `Database` glyph. @@ -2528,10 +2535,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` = `67dadd602`; re-derived at that pin 2026-09-02 — all + * (`.objectui-sha` = `00d3f09c5`; re-derived at that pin 2026-09-04 — all * five files in the chain below, `index.tsx`, `ObjectMetricWidget.tsx`, * `MetricWidget.tsx`, `MetricCard.tsx` and `lazy-icon.tsx`, are - * byte-identical to the ones at `d8ec8d6d4`, so NO anchor moved — the + * byte-identical to the ones at `67dadd602`, so NO anchor moved — the * `object-metric` registration still begins at `:194` and the icon input * still lands on `:204`. Every anchor below was re-READ at the new pin * rather than inferred from that identity), and the chain runs diff --git a/scripts/sdui-manifest.record.json b/scripts/sdui-manifest.record.json index f5fe4d79b9c..c5dfdd76e40 100644 --- a/scripts/sdui-manifest.record.json +++ b/scripts/sdui-manifest.record.json @@ -9,10 +9,10 @@ "a pin bump without regeneration goes RED there — that is the anti-rot half of the freshness gate.", "Regenerate + re-record: node scripts/gen-sdui-manifest-node.mjs (see its header for the offline mode)." ], - "objectuiSha": "67dadd602a3a891666ea1513c5de677140784b6a", + "objectuiSha": "00d3f09c500c4a45b5f27aca8af80349412faaf1", "objectuiPackagesVersion": "17.6.0", "generator": "scripts/gen-sdui-manifest-node.mjs", - "generatedAt": "2026-09-02", + "generatedAt": "2026-09-04", "sha256": "49211fee7792cf51174930dc2c1be2169d5175f77a83491f68f90b3f0c19e69d", "components": 57 }