Repository navigation
refactor(types,plugin-designer,i18n)!: retire the unread designer members objectui#11434's ruling settles as RETIRE, on both faces (PR 1 of 3) - #11451
Conversation
…the objectui#11434 ruling settles as RETIRE On both faces: DataModelDesignerSchema.autoLayout, ReportDesignerSchema.previewMode, DesignerComponent.parentId, DataModelRelationship.onUpdate, BPMNNode.serviceEndpoint, ObjectDefinition.relationships and DesignerFieldDefinition.validationRules become `?: never` tombstones on the TypeScript face and retirement tombstones refused by name on the zod face. ObjectDefinitionRelationship and DesignerValidationRule, and their zod mirrors, leave the exports. The mirror-parity ledger moves with them (two UnmirroredDeclared entries close; two pairs leave the registry), the dead component props and the autoLayout registration input go, and the two validation-rule labels leave the locale packs and the designer defaults map. Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
… DataModelRelationship.onUpdate tombstone Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
… objectui#11434 retirements make false Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
…Rules` as unrecognized keys, and `serviceEndpoint` prescribes deletion alone (objectui#11434 patch round 1) Measured through the installed @objectstack/spec 17.5.0: ObjectSchema and FieldSchema refuse the two keys with `unrecognized_keys` and no named guidance, so the prose this change publishes says that instead of "by name". The serviceEndpoint prescription no longer points at `properties`, which no renderer reads yet. Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: Inputs read: card objectui#11434 (its body and every comment — the claim Check-runs on the head, read at 2026-10-02T07:20Z, every run completed: ① Derived judgmentsAccept-set moves on the zod face (
Public-surface moves on the TypeScript face and the component face:
Wrong — the ② Semver level
③ Boundary flags
Shape: draft PR, head repo = base repo, 39 files / 1,137 changed lines, Implemented-by: VERDICT: FAIL Generated by Claude Code |
…an author (objectui#11434 patch round 2) The designer face writes a `lookup` field with `referenceTo` (DESIGNER_FIELD_TYPES has no `master_detail`); @objectstack/spec metadata writes a `lookup` / `master_detail` field with `reference`. The docblock's Instead line, the zod refusal message and the changeset migration line now say which is which. Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: Delta record on the fix-only head that answers the FAIL Nothing else moved. The new head's only parent is the reviewed head, so the net diff against Check-runs on this head, read at 2026-10-02T07:46Z, every run completed: ① Derived judgmentsThe FAIL finding, re-read at each carrier — each now pairs a key with a type the named face can author:
Accept set and public surface: no accept-set move and no public-surface move in the delta. The seven tombstones, the two removed types and mirrors, the plugin-designer props and input row, the i18n keys, the ledgers ( ② Semver levelUnchanged by the delta and right: PR body ③ Boundary flags
Shape: draft PR, head repo = base repo, 39 files / 1,138 changed lines, Implemented-by: VERDICT: PASS Generated by Claude Code |
…ashboard:metric / metric-card (objectui#10859 batch 8, phase 2b) (objectstack-ai#11453) Part of objectstack-ai#10859 Clause-②: yes Phase 2b of batch 8 on the family card. Twelve node type keys leave the registry: ten are unregistered, and the `metric` / `metric-card` node keys lose their bare fallback while both dashboard surfaces emit the namespaced keys. Fourteen keys the ruling also named fail the premise gate, so they stay registered and are reported as forks with the evidence. Implemented by `os-dev` for `domain:ui` seat 1, session `session_01YLg8XqWGJ785fwQ5v4pH37`. It follows the "Phase 2b" section of seat ruling `5945530142`, as amended by `5945583855`, and the coordinator's conditional premise gate. ## Premise gate: re-measured on `origin/main` 990a2d6 and later Each key was searched for producers in source, `examples/**`, the catalog, docs and the whole objectstack tree at `6c5bef5f`, and for runtime emission. | key | producers | runtime emission | disposition | |:--|:--|:--|:--| | `scatter-chart` | 0 | 0 | **retired** (unregistered) | | `dashboard-grid` | 0 (objectstack names it only as a host type in its own `sdui-parser` lint, which reads it) | 0 | **retired** (unregistered) | | `form-analytics`, `import-wizard`, `shared-view-link` | 0 | 0 | **retired** (unregistered) | | `app-creation-wizard`, `branding-editor`, `dashboard-editor`, `navigation-designer` | 0 | 0 | **retired** (unregistered) | | `related-list` | 0 | 0 | **retired** (unregistered) | | `metric`, `metric-card` | 0 standalone; the dashboard WIDGET vocabulary only | `DashboardRenderer`, `DashboardGridLayout` | **emitter moved** (M3 option A), `skipFallback: true` | | `pie-chart`, `donut-chart`, `radar-chart` | **1**: see fork 1 | 0 | **fork**, still registered | | `page-header` | **objectstack**: see fork 2 | 0 | **fork**, still registered | | the ten `sidebar-*` | only the four catalog documents the ruling orders rewritten | 0 | **fork**, still registered: see fork 3 | ### Fork 1: `pie-chart`, `donut-chart`, `radar-chart` have an in-repo producer `packages/plugin-charts/examples/chart-examples.ts` exports `pieChartExample`, `donutChartExample` and `radarChartExample`, which author `type: 'pie-chart'`, `'donut-chart'` and `'radar-chart'`. objectui#7401's describe block "the in-repo examples draw what they say" renders those three objects (ruling item 3 of that card). The file is not in the package's `files`, so it does not ship, but it is a producer pinned by a ruled test. `scatter-chart` has no example there, so it passed the gate on its own and is retired.⚠️ Phase 1 counted this file as source without classifying it as a producer. That miss is why the ruling listed all four chart aliases together. ### Fork 2: `page-header` is authored by objectstack On objectstack `origin/main` `6c5bef5f`, the spec conversions registry carries `PAGE_HEADER_COMPONENT_TYPES = new Set(['page:header', 'page-header'])` and the conversion `page-header-subtitle-alias` (toMajor 17, "Live window; retires at 18"). Its docblock says the key "is authorable here because PageComponentSchema.type is deliberately z.union([PageComponentType, z.string()])". It also says "The alias's entire reason to exist is out-of-repo consumer schemas" and "That registration is objectui's to retire, on its own schedule". Its fixtures author `{ type: 'page-header', properties: {...} }`.⚠️ Phase 1 did not search objectstack's `packages/spec`. It searched only examples, apps, content, skills and `packages/studio`. ### Fork 3: the `sidebar-*` family's teaching rewrite has no target No new producer or emitter turned up. But the ruling ties this retirement to rewriting the four `components-basic-sidebar` documents and `sidebar.mdx` "to what the armed `sidebar` both renders and accepts, measured by a render and a validate". The armed `sidebar` calls `useSidebar()`, which throws outside a `SidebarProvider`, and the only authored provider is the `sidebar-provider` primitive this retirement removes. The measurements below come from a temporary probe test, run through `SchemaRenderer` with both validator faces and deleted afterwards: | node | host | render | tolerant | strict | |:--|:--|:--|:--|:--| | bare `sidebar` with `text` children | no provider | throws "useSidebar must be used within a SidebarProvider." | ok | ok | | the same | the docs-site wrapper (`InteractiveDemo`: `SidebarProvider` with `defaultOpen={false}`) | mounts, but `data-state="collapsed"` `data-collapsible="offcanvas"`: shadcn's offcanvas collapse draws it off-screen | ok | ok | | `collapsible: true` | docs-site wrapper | `data-collapsible="true"`, which no CSS rule matches, so it shows only by accident | ok | ok | | `collapsible: 'none'` (the in-flow form) | docs-site wrapper | renders in flow | refused, `invalid_type` at `collapsible` | refused | | `side` / `variant` / `className` | docs-site wrapper | renders | ok | refused, `unrecognized_keys` `side` | | today's `basic-sidebar.json` (`sidebar-provider` root) | docs-site wrapper | renders expanded | refused at `type` | refused at `type` | Once `sidebar-provider` is gone, no `sidebar` document both draws visibly and validates, apart from the `collapsible: true` accident. The four catalog documents would have nothing honest to be rewritten to. They cannot keep their retired types either, because `check:doc-types` admits an exemption only where a retired value appears at a legitimate position. Forcing it through or quietly picking a fallback were both ruled out, so the ten stay registered and the teaching is unchanged. The options are in the report on the card: - **A.** The `sidebar` registration supplies its own `SidebarProvider`. Then a bare `sidebar` renders in any host and the teaching rewrite becomes possible. - **B.** Arm `sidebar-provider` (declare it) and retire the other nine. - **C.** Retire as ruled, and teach the bare node as host-provider-only (it draws collapsed and off-canvas in the docs host). ## What changed - **Unregistered, each with a tombstone docblock** at its old registration site (the objectui#10393 / objectui#8760 route). Each docblock says what was there, why it went, and that the React export stays where one exists: - `scatter-chart` (`plugin-charts`), along with its `CHART_TYPE_KEYWORD_FAMILIES` row; - `dashboard-grid` (`plugin-dashboard`); - `form-analytics` (`plugin-form`), `import-wizard` (`plugin-grid`) and `shared-view-link` (`plugin-view`); - `app-creation-wizard`, `branding-editor`, `dashboard-editor` and `navigation-designer` (`plugin-designer`), under one block; - `related-list` (`plugin-detail`). - **The metric emitter move (M3 option A).** - `widgetDispatch.ts` gains `DASHBOARD_NODE_TYPES` (`metric` maps to `plugin-dashboard:metric`, `metric-card` to `plugin-dashboard:metric-card`) and `toDashboardNodeType`. - Both surfaces emit through that table for: - the static metric tile; - the `metric-card` widget-slot passthrough; - a `metric` / `metric-card` node in the legacy `component` envelope. - The two registrations take `skipFallback: true`. The widget vocabulary and the 2026-08-14 `metric-card` slot ruling are untouched. - **`dashboardComponents`** loses `dashboard-grid`. Its metric pair is now keyed by the namespaced type each entry serves, so iterating the map cannot re-create the retired bare keys. - **Console.** - The `scatter-chart` and `dashboard-grid` lazy stubs are gone. - The `metric` / `metric-card` stubs, in `register-plugins.ts` and `preview-gallery.tsx`, pass `skipFallback: true`. - **Teaching corrected.** - The key tables in the `plugin-dashboard`, `plugin-form`, `plugin-grid` and `plugin-view` mdx pages and READMEs: the retired rows are gone, the metric rows read "none — `skipFallback: true`", and the call counts are updated. - The two standalone `metric-card` examples in the dashboard README now sit in a dashboard's `widgets[]`. - The mdx Metric Card block is introduced as that slot entry. - The `schema-reference.md` sentence about the editable grid no longer calls it `dashboard-grid`. - Present-tense comments about the `dashboard-grid` registration are updated. - **Doc gate.** Eight per-file `DOC_TYPE_EXEMPTIONS` rows, only at widget-vocabulary positions: - `metric` (a `ChartTypeSchema` widget kind) in four files; - `metric-card` (a `DASHBOARD_COMPONENT_WIDGET_TYPES` slot entry) in four files. - **Regenerated** `packages/cli/src/utils/known-schema-types.ts`: 22 deletions, 12 bare keys and 10 namespaced twins. ### Tests re-pointed (each named a retired key) - **7401 chart family:** the two `scatter-chart` render cases become `chart` with `chartType: 'scatter'`, plus an absence row for both spellings. - **DOM-leak sweep:** - the scatter arm is now swept through `plugin-charts:chart` with `chartType: 'scatter'`; - the `dashboard-grid` target is gone; - the counts table is now 8 / 7, and 181 targets in all. - **The `dashboard-grid` tests:** - Six `DashboardChart` / `seriesLabel` tests and one `invalidationRefetch` case mount `DashboardGridLayout` directly, as their `DashboardRenderer` twin already did. - `DashboardGridLayout.sduiDatasetPath` becomes the retirement pin: a stored `dashboard-grid` node draws the unknown-type refusal, and `dashboard` is the control. - **Metric tests:** - the `MetricWidget.domProps` standalone cases use the namespaced key; - the 11022 strict-face test reads the inputs in the `plugin-dashboard` namespace; - the README harness now strips a one-line type alias, so the moved Metric Card example is judged. - **cli recogniser:** its unmodelled-type fixture is now `plugin-dashboard:metric-card`. - **Console stubs test:** `scatter-chart` joins its `RETIRED` set, and the list length is 6. - **`dashboardComponents` parity:** 7 keys, plus a row asserting that the retired keys stay out of both the map and the registry. ## Ratchet | pin | before | after | what moved | |:--|:--|:--|:--| | `REFUSED_AT_TYPE` (bare) | 36 | **24** | the twelve keys above | | `NAMESPACED_REFUSED_AT_TYPE` | 389 | **379** | the ten namespaced twins of the unregistered keys | The ruling's target was 10. The difference is the 14 forks. The pin's comment names all 24 remaining keys: the ten the ruling kept (objectui#11440 and objectui#11441) and the fourteen forks, each with its reason. A new row pins the refused set to exactly that named list (`STILL_REFUSED_10859`), so the comment cannot drift. Another new row asserts that the twelve are out of the population and still refused at `type`, that the ten twins are gone, and that both namespaced metric keys are still present. ⛔ Neither pin rises. ## Changesets There is one `minor` changeset per released package whose code moved. Each carries a BREAKING (authoring) banner and a migration line per retired spelling: - `plugin-charts`, `plugin-dashboard`, `plugin-form`, `plugin-grid`, `plugin-view`, `plugin-designer` and `plugin-detail`; - `cli` (the regenerated list); - `console` (the stubs). The `plugin-dashboard` entry also covers: - the `dashboardComponents` re-key; - the `data-obj-type` change on KPI tiles (`plugin-dashboard:metric`). `app-shell` changed one test file only, so it has no entry (the objectui#10393 precedent). Four pending changesets described a retired key in the present tense: 7401, 10528, 7509 and 7997. Each gains a dated note, and each one's frontmatter is byte-identical. ## Local runs All runs are from the worktree root. Heavy runs went through `os-verify-lock`. **At the final head `f0d0abe29`:** - The union of 61 test files, run with `pnpm exec vitest run --maxWorkers=2` and the listed paths: - every test file this PR edits; - the ratchet, `known-schema-types-derivation-5115`, `check-known-types`, `registry-bare-name-collisions` and `check-doc-component-types.test.ts`; - `unit-registry-absence-collision`; - every dashboard / designer / app-shell test that authors a `metric` / `metric-card` type; - the two `@object-ui/types` designer tests that objectstack-ai#11451 touched. - Result: `Test Files 61 passed (61)`, `Tests 1072 passed (1072)`, VERDICT command-exit 0. - Type-check: `pnpm --filter @object-ui/plugin-designer type-check` and `pnpm --filter @object-ui/cli type-check` both exit 0, after rebuilding their closures (objectstack-ai#11451 changed `@object-ui/types`). - Exit 0 for each of: - `pnpm check:doc-types` (886 registered + 290 exempted type sites; 45 key-table keys judged, 45 registered); - `pnpm check:doc-snippets` (775 of 775 blocks judged, 0 failed, after its scoped build); - `pnpm check:doc-example-ids` and `pnpm check:doc-fences`; - `python3 scripts/regenerate-catalog-index.py --check`; - `node scripts/markdown-test-inputs.mjs --audit`; - `node scripts/check-doc-links.mjs`; - `node scripts/check-changeset-presence.mjs` (37 source files of 10 released packages, 9 changesets); - `node scripts/regenerate-known-schema-types.mjs --check`; - `check:registry-bare-names`, `check:prompt-keys`, `check:readme-exports`, `check:control-bytes`, `check:new-line-citations` (0 new); - `changeset:check`, `check:pending-changeset-literals`, `check:changeset-claims`. **At `9eb0f580e`** (after the first `main` merge; the code is the same as the final head apart from objectstack-ai#11451 and one test file): - Exit 0 for each of: - `check:doc-examples`, `check:handler-key-reads`, `check:spec-symbols`, `check:component-surface-parity`, `check:test-path-roots`; - `check:element-data-source-declaration`, `check:unreferenced-sources`, `check:doc-example-readers`, `check:self-import`; - `check:vi-mock-inherit`, `check:vi-mock-specifiers`, `check:side-effects-array`, `docs:check-links`; - `check:sdui-registration-pins` (17 of 17 present, after `pnpm --filter @object-ui/console build`). - Type-check: `pnpm --filter X type-check` exits 0 for `plugin-charts`, `plugin-dashboard`, `plugin-form`, `plugin-grid`, `plugin-view`, `plugin-designer`, `plugin-detail`, `cli`, `app-shell` and `console`. This ran after `pnpm --filter '@object-ui/console^...' --filter '@object-ui/cli^...' build`. - ESLint, narrowed: - `eslint --no-inline-config --format json` over the 38 changed ts/tsx/mjs files gives 0 errors. - Each file's error count equals its base blob's. Warnings are equal or lower: `plugin-form` index 23 to 22 and `plugin-grid` index 16 to 14, because the removed renderers carried the `any`. - The population is the root `eslint.config.js`. It sets no `projectService` / `parserOptions.project`, so no untouched file's verdict can move. Full `pnpm lint` is CI's. **Earlier wide runs**, before the fixes listed: - `packages/plugin-view/ packages/plugin-designer/ examples/schema-catalog/test/`: 137 files, 3074 tests, all passed. - The registry-touching tests of `plugin-form`, `plugin-grid` and `plugin-detail`: 27 files passed. - 64 dashboard-consumer tests in `app-shell` / `react` / `plugin-report` / `components` / `scripts`: all passed. - `packages/plugin-dashboard/`: 159 of 160 files passed. The README-harness file was red and was re-run green after its fix. - `packages/plugin-charts/ packages/cli/`: 109 of 110 files passed. The recogniser file was red and was re-run green. - `apps/console/src/__tests__/` plus the sweep plus the doc-types gate test: 45 of 47 files passed. The stubs test and the exemption-shape pin were red and were re-run green. ## Reverse verification The prediction was written to the scratchpad before either leg ran. **BASE leg.** The thirteen changed source files went back to BASE `990a2d616`, the new and edited tests stayed, and the five pin files ran. - **Predicted:** 13 red. That is 4 ratchet (count, namespaced, phase-2b row, exact set), 2 map parity, 2 `sduiDatasetPath`, 1 chart-family 7401 and 4 console stubs, with the controls and earlier batch rows green. - **Observed:** `Tests 13 failed | 49 passed (62)`. The red tests are exactly those 13, including "refuses 36 registered bare key(s) at `type`; the pin is 24" and "refuses 389 … the pin is 379". - **Restored:** 13 blobs equal HEAD, `git diff HEAD` is 0 lines, and status is 0 lines. **Ablation.** `skipFallback: true` was dropped from the `metric-card` registration with `scripts/ablation-replace.mjs`, run from `../objectstack`. The anchor went from 1 hit to 0, and the blob from `8a84c9f79e32` to `ea900ba0f0d1`. - **Leg 1** (source only): `known-schema-types-derivation-5115` went red ("expected [ 'metric-card' ] to deeply equal []", plus the byte-for-byte regen case), and the map-parity retired row went red (registry key `metric-card` was `MetricCard`). Result: `Tests 3 failed | 14 passed (17)`. - **Leg 2** (list regenerated from the mutated source): the ratchet went red with "refuses 25 registered bare key(s) at `type`; the pin is 24", with `metric-card` in the Refused list. The phase-2b row and the exact-set row were red too. Result: `Tests 3 failed | 21 passed (24)`. - **Restored:** the tool's restore reports blob equal to HEAD and an empty `git diff HEAD`. A second trap restored the known-types file, and its blob `fa94132ef625` equals HEAD. ## Acceptance notes - `DASHBOARD_WIDGET_HOST_TYPES` in `sdui-parser` still lists `dashboard-grid`, in both the objectui copy and the objectstack copy. It is now a reader of a retired key. It is left unchanged so the two copies stay in step. Carrier: none. - `ROADMAP.md` still lists the four designer keys under "Registered". It is a dated progress list, so it is left as is. - The `plugin-grid` README key-table rows carried line addresses that were already stale on `main`. The `import-wizard` row is gone, and the others are untouched. - The `MetricWidget.domProps` cases (a) to (c) kept passing once their bare key stopped resolving, because negative assertions over an "Unknown component type" panel stay green. Pointing them at the namespaced key makes them bite again. - `DashboardGridLayout` is no longer swept by the DOM-leak sweep, since it is not a registered widget any more. - A legacy report section with `chart.type: 'scatter-chart'` now reaches the generic `chart` with no derived family. The changeset states this. --- _Generated by [Claude Code](https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
Part of #11434
Clause-②: yes
PR 1 of at most 3 for objectui#11434: every retirement the seat ruling on that card settles (ruling comment
5946170549, option B). The members ruled READ are not touched here and ship in PR 2 and PR 3. So is theonDelete→deleteBehaviorrespelling. The final PR of the card says it completes the card; this one isPart of.The ruling this implements
The seat ruled member by member, by the maintainer's criterion for this family: "does the mainstream have it? Yes ⇒ give it a reader. No ⇒ retire it on both faces." Each member below was measured unread before ruling: a non-test grep, plus a runtime probe through the real
SchemaRendererand registry that drew the same markup with the member set and unset. Nothing in this repository or in ObjectStack authors any of them outside test fixtures. The phase-1 report on the card carries the measurement and the citations.On the TypeScript face each member becomes a
?: nevertombstone, sotscrefuses it by name. On the zod face it becomes a retirement tombstone, refused by name with the reason and what to write instead (RETIRED (objectui#11434, ADR-0049) — KEY on OWNER had no reader: … Instead: …). An element type that typed only a retired member leaves both faces and the exports.Members retired, each with its migration line
DataModelDesignerSchema.autoLayoutUnmirroredDeclared)ReportDesignerSchema.previewModeUnmirroredDeclared)readOnly: true,showToolbar: false,showPropertyPanel: falseDesignerComponent.parentIdchildrenarray, the tree's one spellingDataModelRelationship.onUpdate(seat override: retire)BPMNNode.serviceEndpointObjectDefinition.relationships(+ObjectDefinitionRelationship:relatedObject,type,label,foreignKey)lookupfield whosereferenceTonames the related object (in@objectstack/specmetadata, alookup/master_detailfield whosereferencenames it)DesignerFieldDefinition.validationRules(+DesignerValidationRule:type,value,message)min/max/minLength/maxLength, other rules in the object'svalidationsRemoved exports.
ObjectDefinitionRelationshipandDesignerValidationRuleleave the@object-ui/typesroot barrel.ObjectDefinitionRelationshipSchemaandDesignerValidationRuleSchemaleave@object-ui/types/zod.The component face agrees.
DataModelDesignerProps.autoLayoutandReportDesignerProps.previewModeare removed from@object-ui/plugin-designer; neither was read. Thedata-model-designerregistration no longer publishesautoLayoutamong itsinputs;check:component-surface-parityhad reported it as outside (spec ∪ renderer reads). The package README'sDataModelDesignerexample no longer passesautoLayout.Renderers are untouched. Every retired member was ignored at render before this change and still is. What moves is the verdict.
Ledger movement (
zod-mirror-parity.test.ts, same PR as its members)UnmirroredDeclaredDataModelDesignerSchema(autoLayout) andReportDesignerSchema(previewMode) entries close: each key is now a tombstone on both faces, and a tombstone is a mirrored memberUnmirroredDeclaredaloneEXPECTED_MIRROR_PAIRSObjectDefinitionRelationshipSchemaandDesignerValidationRuleSchemapairs left the registry with their typesProcessDesignerSchema'slanes/versionentry stays: they are ruled READ, and the reader PR mirrors them and closes it. Each move has its history sentence in the header, as the file's pins require.Other pins that move with the members:
designer-zod-arms-10859.test.ts: the full-document fixture no longer sets the retired members, and theautoLayout/previewModeomission rows become full key-set equality. The removed pairs' rows go.check-designer-field-key-parity.test.ts: therelationshipspin now asserts thatObjectDefinition.relationshipsis the?: nevertombstone.group/sortOrderstay on the UI model and all three stay off every object wire shape. The gate still listsrelationshipsas UI-only, because a tombstone is a property signature.ObjectManager.test.tsxandMetadataService.specKeyObjectPayload.test.ts: the fixtures stop settingrelationships. The wire-shape pins keep their strength through aLEGACYvalue cast from outside the type system, which still provestoObjectPayload's explicit field list keeps the key off the wire.component-docs-retired-handler-keys-7340.test.ts: that census is name-shaped (on*?: never), so it now countsDataModelRelationship.onUpdate, recorded the way objectui#7068'sonSuccess/onFailurewere (30 total,designer.ts1). It is a referential action, not a handler.designer-members-retired-11434.test.ts, covering both faces of all seven members, the two removed exports, and lit controls.i18n census and the decision on the dead editor strings
node scripts/check-i18n-dead-keys.mjslistsappDesigner.fieldDesigner.validationRulesandappDesigner.fieldDesigner.addRuleas NEEDS-REVIEW. No call site asks for either; their only other footprint is the plugin-designer defaults map. They labelled an editor for the member this PR retires, which was never built. The card that once owned confirming that namespace, objectui#4730, is closed.Decision: retire both. They are removed from the ten packs and from
DESIGNER_DEFAULT_TRANSLATIONS, with a pin,appDesigner-fieldDesigner-validation-rules-retired-11434.test.ts, that checks absence in all ten packs and has a lit neighbour control. The defaults-map half stays held bydefaults-maps-mirror-en-pack.test.tsx(objectui#4401). The other six NEEDS-REVIEW keys of that namespace are untouched.Changesets
@object-ui/typesminor, with a BREAKING (authoring) banner and one migration line per member (11434-designer-members-retired.md)@object-ui/plugin-designerminor: the removed props and registration input (11434-plugin-designer-retired-props.md)@object-ui/i18npatch: the two labels (11434-i18n-validation-rule-labels.md)@object-ui/app-shellpatch: comments only inMetadataService(11434-app-shell-relationships-note.md)10859-designer-zod-arms.md, whose "four unmirrored members … refused as unrecognized keys" sentence no longer holds for two of them, and10719-retire-phase35-validation-types.md, whose sentence that "DesignerValidationRulestay[s] exported" no longer holds for it. This follows the dated-note shape objectui#10859 batch 8 landed.check-changeset-overwritereports both edits, report-only by design.Evidence (head
91a824298; patch rounds 1 and 2 at6b5012446/97a16bccbbelow)Patch round 2 (
97a16bccb, prose only, contract review5947291305, seat order5947305312). TheObjectDefinition.relationshipsprescription paired a designer-face key with a spec-face type:referenceToon amaster_detailfield, which neither face can author.DESIGNER_FIELD_TYPEShas nomaster_detail, and the spec spells the keyreference. Fixed in thedesigner.tsInstead line, the zod refusal message, the changeset migration line and this table row: in the designer, alookupfield withreferenceTo; in@objectstack/specmetadata, alookup/master_detailfield withreference. A grep of this PR's diff for other face-mixing prescriptions found two@ts-expect-errordescriptions in the new pin, aligned the same way. The docblock's spec sentence and the changeset's TypeScript example are unchanged. Re-run throughos-verify-lock:designer-members-retired-11434.test.ts(18 passed) &&check:changeset-claims&&tsc --noEmit+tsc -p tsconfig.test.jsonfor@object-ui/types, chained, VERDICT command-exit 0.Patch round 1 (
6b5012446, prose only, REWORK5946901058). I measured through the installed@objectstack/spec17.5.0.ObjectSchema.safeParsewith an object-levelrelationships: []answersunrecognized_keys: "Unrecognized key(s) on this object:relationships. Until this shape was closed these were dropped silently on the PARSE path …".FieldSchema.safeParsewithvalidationRules: []answers "Unrecognized key(s) on this field:validationRules. Until this shape was closed these were dropped silently …". Neither carries named guidance. The controls do: object-levelvalidationRulesgets "Did you meanvalidationRules→validations?" and field-levelreferenceTogets "→reference". So every sentence this PR writes about the spec now says "refuses it as an unrecognized key", not "by name". Those sentences are in thedesigner.tsdocblocks, the twodesigner.zod.tsrefusal messages, theMetadataService.tscomments this PR rewrote (including itsgroup/sortOrdersentence, measured the same way), the new pin's header and the two changeset migration lines. TheserviceEndpointprescription is now "delete the key; there is nothing to configure in its place", in the TS docblock, the zod message and the changeset;BPMNNode.propertiesgets its reader in a later PR. Re-run throughos-verify-lock:vitest run packages/types/ packages/app-shell/src/services/MetadataService.specKeyObjectPayload.test.ts→Test Files 329 passed (329),Tests 8767 passed, VERDICT command-exit 0. Then the message pindesigner-members-retired-11434.test.ts(18 passed),check:changeset-claims, andtsc --noEmit+tsc -p tsconfig.test.jsonfor@object-ui/types, chained with&&: VERDICT command-exit 0.Test union, root form via
os-verify-lock. Ata5d1c2693:vitest run packages/types/ packages/plugin-designer/ packages/i18n/ packages/app-shell/src/services/plusdefaults-maps-mirror-en-pack.test.tsx,registered-types-validate-ratchet-10859.test.ts, and thescripts/__tests__files for designer-field-key-parity, doc-component-types, doc-links, doc-snippet-types, object-metadata-write-doors, readme-exports, doc-version-claims and unit-registry-absence-collision. Result:Test Files 459 passed (459),Tests 10965 passed | 13 skipped, VERDICT command-exit 0. The 13 skips are the pre-existingskipIfinformatting.dateOnlyZone-10866.test.ts.91a824298changes only two changeset files, so the ratchet family and every test that reads.changeset/was re-run on it:packages/types/+ the key-parity pin + those script tests gaveTest Files 353 passed (353),Tests 9741 passed, VERDICT command-exit 0.Type-check after a closure build.
turbo run build --filter=@object-ui/app-shell^... --filter=@object-ui/plugin-designer^... --filter=@object-ui/plugin-designerpassed, thentype-checkof@object-ui/types,@object-ui/i18n,@object-ui/plugin-designerand@object-ui/app-shell, joined with&&, plustype-check:scripts: VERDICT command-exit 0.tsc -p tsconfig.test.json --listFilesOnlylists the new and edited tests in their packages.Ablation (
ablation-replace.mjswith an absolute-path EXIT/INT/TERM trap). Deleting theautoLayoutretirement tombstone fromDataModelDesignerSchemamoved the anchor x1 → x0, blobff62eaf3→04d4fd87. Runtime result: 2 red, both naming the member: "autoLayoutis refused on the rendering face, at its own path, with the prescription" and "autoLayoutis refused on the strict authoring face, at its own path".tsc -p tsconfig.test.jsonwent red at three rows: the new pin's zod row (Property 'autoLayout' does not exist), the batch-7 arms key-set row (TS2344), and the parity ledger ('designer.zod.ts#DataModelDesignerSchema'not assignable tonever). Restored: blob equal to HEADff62eaf3,git diff HEADempty.Gates, each exit 0:
check-changeset-presence("29 source file(s) of 4 released package(s) changed, and this change declares 4 changeset(s)"),changeset:check,check:changeset-claims,census:changeset-polarity,check:pending-changeset-literals,check:designer-field-key-parity(OK),check:handler-key-reads,check:doc-types,check:doc-fences,check:doc-example-readers,docs:check-links,check:i18n-keys,check:i18n-drift,check:i18n-designer-parity,check:new-line-citations(0 new),check:control-bytes,check:test-path-roots,check:unreferenced-sources,check:registry-bare-names,check:prompt-keys,check:element-data-source-declaration,check:metadata-write-doors,check:spec-symbols,check:esm-specifiers,check:self-import,check:phantom-deps,markdown-test-inputs --audit.check:doc-snippets,check:doc-examplesandcheck:readme-exportspassed after the scoped build their own--build-filternames; packages that came in with the merge ofmainwere not rebuilt for them.check-governed-queue-guard --testover the diff: NOT GOVERNED.ESLint, narrowed.
eslint --no-inline-config --format jsonover the 30 changed.ts/.tsxfiles gives, per file, the same error and warning counts as each base blob linted through--stdin. That includes one pre-existingno-restricted-importserror inpackages/types/src/index.ts. The two new test files lint 0 / 0.eslint.config.jssets noprojectService/parserOptions.project, so the diff cannot move any untouched file's verdict. The fullpnpm lintis CI's.NOT MEASURED:
check:sdui-registration-pins. Reason: it needs anapps/consolebuild (exit 2, prerequisite not met). The diff adds or removes no registration; it drops oneinputsrow inside an existing one.NOT MEASURED:
type-check:coverage. Reason: it is the whole-repo test compile, which CI runs. Every touched package'stsconfig.test.jsonis compiled above.Overlap
packages/plugin-designer/src/index.tsxis shared with objectui#10859 phase 2b. This PR removes only theautoLayoutrow from thedata-model-designerregistration'sinputs.mainwas merged before opening (a5d1c2693, after objectui#11446 and objectui#11447 landed). Whichever lands second mergesmain.Acceptance notes
@object-ui/components'metadata-viewerreadsobj?.validations ?? obj?.validationRules, a consumer-side alias of a spelling the spec refuses on objects. It is unreachable through a public door, because the spec refusesvalidationRulesat save. Noted, not filed, and not in this PR.radial-gradientfrom serialized style), as the ruling records.Generated by Claude Code