feat(types): arm the seven registered node types that pass the criterion — page kinds, app-schema-renderer, object-pivot, embeddable-form, detail-section (objectui#11440) - #11493
Conversation
…(objectui#11440) `safeValidateSchema`, and so `objectui validate`, accepts the spec page kinds `record` / `home` / `utility`, and `app-schema-renderer`, `object-pivot`, `embeddable-form` and `detail-section`, each refused at `type` before. `REFUSED_AT_TYPE` falls 8 -> 1; `spec-report` remains for the fold into `report`. - `PageKindNodeSchema`: the page node's members by reference under the spec's `PageTypeSchema` narrowed to the three registered kinds. - `AppSchemaRendererNodeSchema`: `basePath` and `mobileNavMode` from the registration inputs; `schema` is not declared (never delivered). - `ObjectPivotBlockSchema` / `EmbeddableFormBlockSchema`: required bags of the registration inputs, flat spelling refused by name. - `DetailSectionNodeSchema`: the ten registered section members, flat. - `object-pivot` publishes `drillDown` as a registration input. Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
…ill mirror's referencing declarations (objectui#11440) The end-to-end rows restate the plugin-detail example instead of reading its README, so the markdown-input ledger has nothing new to adjudicate. `.changeset/7352-drill-down-config-mirror.md` gains a pure-append dated note: the `object-pivot` arm is a third declaration extending the mirror. Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
…utSchema (objectui#11440) `LayoutSchema`'s enum-keyed arms are the two html-tag families that `@object-ui/core`'s html-tier roster pin finds by shape; a third enum-keyed arm there turned that pin red. The zod README stops naming the app document's arm by symbol, which the objectui#7469 census reads. Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
Brings in objectui#11473, objectui#11477 (objectui#11468) and objectui#11481. Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
…de types, their required bags closed (objectui#11440) objectui#11468 (landed on main) derives `ObjectQLPublicBlockNode` from the union's arms, so the two new arms joined it. `ClosedBag` closed only an optional bag; the two required bags are closed now too, so no `AuthoringNode` member carries an open bag. `ObjectPivotBlockNode` and `EmbeddableFormBlockNode` are named and exported beside the other eight, and the objectui#11468 pin lists them. Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
…ote the 11468 entry's member count (objectui#11440) Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
Brings in objectui#11485 (objectui#11465), objectui#11486 (objectui#11478) and objectui#11482 (objectui#11467). 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
|
Contract reviewServed-tier: PR objectui#11493, Check-runs on the head: 43, every one completed as of 2026-10-02T17:48Z (polled at 60 s intervals; the aggregate ① Derived judgmentsAccept set (
Public surface:
② Semver level
③ Boundary flagsDev
Dev deviations and flags:
Dev
Serial: Implemented-by: VERDICT: PASS |
Part of #11440
Clause-②: yes
The first of objectui#11440's two pull requests. It arms the seven registered node types that the seat ruling
5945530142on objectui#10859 (as amended by5945583855) passes: the spec page kindsrecord,homeandutility, andapp-schema-renderer,object-pivot,embeddable-formanddetail-section.safeValidateSchema, and soobjectui validate, refused each one withinvalid_unionattype.REFUSED_AT_TYPEfalls 8 to 1. The eighth key,spec-report, is the fold intoreport, which is the second pull request (see "What is left" below).Dispatched run: claim
5954845613(domain:uiseat 1), sessionhttps://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37. Draft, left for the seat.What changed
record,home,utilityPageKindNodeSchema(layout.zod.ts), its own arm ofAnyComponentSchemaPageNodeSchema's own, by reference (the spec'sPageSchemafields among them, throughSpecPageFields);typeis the spec'sPageTypeSchemanarrowed with.extractto the three kinds@object-ui/componentsregisters onPageRendererapp-schema-rendererAppSchemaRendererNodeSchema(app.zod.ts), its own armbasePathandmobileNavMode('drawer'or'bottom_nav'), from the registration's inputs;childrenandbodyrefused by nameobject-pivotObjectPivotBlockSchema(objectql.zod.ts), inObjectQLPublicBlockComponentSchemapropertiesbag of the registration's inputs (the cross-tab members are thepivotmirror's own, by reference;drillDownrefusesmode; the retireddataProvideris refused); flat props refused by name towardproperties.KEY;dataSourcebinding andresponsiveStyleson the node;RECORD_SOURCE_REQUIREDunlessdataSource.objectnames the objectembeddable-formEmbeddableFormBlockSchema(objectql.zod.ts), same unionformIdrequired), built as abovedetail-sectionDetailSectionNodeSchema(views.zod.ts), inViewComponentSchemaDetailViewSectionSchemamembers the registration publishes,.picked by reference, flat;fieldsrequiredAlso:
object-pivot's registration publishesdrillDownas an input (@object-ui/plugin-dashboard).ObjectPivotTablereads it, and thepivotnode's refusal ofdrillDownnames this block as where a pivot drill is authored.@object-ui/typesexportsObjectPivotBlockNodeandEmbeddableFormBlockNode. objectui#11468 (landed during this run) derivesObjectQLPublicBlockNodefrom the union's arms, so the two arms joined it. ItsClosedBagclosed only an optional bag, so it closes a required one too now, and noAuthoringNodemember carries an open bag.ObjectPivotDrillDownConfig,DrillDownConfigSchema,ObjectPivotTable'sdataProvidernote), and pure-append dated notes on three pending changesets (10685-drilldown-per-block.md,7352-drill-down-config-mirror.md,11468-bag-carrier-node-types.md)..changeset/11440-arm-passing-types.md(@object-ui/typesminor, each new authorable spelling listed, no BREAKING banner: a pure widening) and.changeset/11440-object-pivot-drilldown-input.md(@object-ui/plugin-dashboardminor).Contract notes
For the at-tier reviewer.
AnyComponentSchemaaccepts seventypeliterals it refused attype, on both faces, at the root and at every child slot.@object-ui/types/zodexports five schemas.@object-ui/typesexports two TypeScript node types andAuthoringNodegains their members. Theobject-pivotregistration publishes one more input (drillDown).mobileNavMode, a missingfields,drillDown.mode) replace a refusal attypewith a named one. TheClosedBagchange touches only the two new bags: the objectui#11468 pin shows the other members unchanged.type, both faces); the new pinpackages/types/src/__tests__/passing-keys-arms-11440.test.tsholds what each arm accepts and refuses on both faces with a lit control per refusal;packages/cli/src/__tests__/validate-passing-keys-11440.test.tsrunsobjectui validateend to end; each registration's inputs are pinned against its arm in the package that registers it (four new files); two ablations turn the ratchet and the pins red (below).Zone 2 readings — the mechanism assumptions, measured
appis registered onPageRenderertoo (withpage), not only the three kinds; its literal is the app document's (AppComponentSchema). Each declaration is built from the registration's inputs; where a renderer reads a key the inputs omit, it is named below.6007dd4e4the card's probe{ type: 'home', name, regions }and the spec's own page document were refused attypeon both faces, while{ type: 'page', pageType: 'home' }passed. After: all pass. The precedent followed isPageNodeSchemaitself (the spec fields by reference throughspecFieldsExcept); the strict face derives from the arm like every other. On objectstack's example pages (objectstack4e6dc233, read only, the elevendefinePagedocuments of kindhomeorrecordinapp-crmandapp-showcase, run through both faces by an uncommitted probe): base, 11 of 11 refused attypeon both faces; after, none is refused attype, and 10 of 11 parse on both faces. The eleventh (showcase_my_work) passes the tolerant face, and the strict face refuses a nested{ type: 'grid', properties: { … } }region component as an unrecognized key (properties): thegridarm takes its props flat. That is thegridarm's existing posture, unchanged here: the same component inside atype: 'page'document is refused the same way (measured).appandlisttoday, unchanged here: a spec page of kindappis judged by the app document's arm (the tolerant face passes it unjudged, the strict face refusesregions,template,kindas unrecognized keys); a spec page of kindlistmeets thelistcomponent's arm (refused for having noitems, and on the strict face forregionsand the other page keys). No new key is registered.AnyComponentSchemamadetscrefuse the union with TS7056 (inferred type too long to serialize);PageKindNodeSchemaTypenames the arm's type by reference, so declaration emit names it.spec-report: not in this pull request. Measured only: the strict face refuses{ type: 'report', report }as an unrecognized key (report), and the tolerant face passes it unjudged. The fold needs a file outside the claimed surface (below).detail-section: armed, not folded. The spec'srecord:detailssection names its headinglabeland takes field NAMES; this node names ittitleand takesDetailViewFieldobjects. The spec row refuses the README's section withunrecognized_keysontitleandinvalid_typeon each field object (pinned). After arming, the plugin-detail README'sdetail-viewdocument validates except for one issue, attabs.1.content.items: its second tab handsrecord:activitya host feed (items: activityData), which objectui#11321 refuses by name in a JSON document, and whose refusal text names this README as the TSX composition where it stays legal. Measured both ways byobjectui validate(the first tab alone: valid; the full document: that one issue). The README is not edited.app-schema-renderer: the guide's node validates; theschemainput is not declared. The governed guide teaches the node'smobileNavModekey, in prose, and{ type: 'app-schema-renderer', mobileNavMode: 'bottom_nav' }validates on both faces after. The registration declares three inputs. Measured through the realSchemaRendererand registry:SchemaRendererstrips theschemakey and hands the component the NODE as itsschemaprop, so a node with its navigation underschemadrew no navigation, and the same navigation written on the node drew. A node'schildrendrew nothing either. So the arm declaresbasePathandmobileNavModeand refuses both content channels; where the app document belongs on this node is an open question for the seat (below). Noskills/**edit.ui:home,ui:record,ui:utility,layout:app-schema-renderer,plugin-dashboard:object-pivot,plugin-form:embeddable-form,plugin-detail:detail-section. Each is its own literal, so the bare arm does not claim it; the ratchet row asserts each twin is still refused attype.Gates
Head
ccb1077bc(a merge ofmain401611b21into34d127803). Exit codes captured to a file before reading. Heavy runs through the shared verify lock; absolute times are shared-box readings.pnpm --filter @object-ui/types build && … type-check(three legs)tsconfig.test.json --listFilesOnlypnpm exec vitest run packages/types/ packages/cli/@object-ui/plugin-dashboard,plugin-form,plugin-detail,layout,cli(after their closure build)type-check: Donepackages/layout/plus the plugin-form / plugin-detail tests that read a zod face or name the keys, plus everyapps/console/packages/app-shelltest that reads a zod face or names a keyKNOWN_SCHEMA_TYPES, or names one of the eight keys (examples, scripts, components, core, react, plugin-report and others)packages/plugin-dashboard/whole suite, at30614b964(before the two merges; neither touched this package)node scripts/regenerate-known-schema-types.mjs --checkcheck:doc-snippets(after its--build-filterclosure build),check:doc-examples,check:readme-exportscheck:doc-types,check:doc-fences,markdown-test-inputs --auditcheck:control-bytes,check:new-line-citations(0 new),check-changeset-presence,check-changeset-no-major,check:pending-changeset-literalscheck:changeset-claims(report-only)check:handler-key-reads,check:element-data-source-declaration,check:registry-bare-names,check:spec-symbols,check:test-path-rootscheck-governed-queue-guard --test(the changed paths)pnpm check(the CLI sweep over the repository)main401611b21under a trapped restore, proven by blob hash and an emptygit diff HEAD) and after: identical, 287 validated, 146 recognised but not validated, 0 did not validate, 47 skipped. No tracked JSON or YAML document names one of the seven types, so the sweep has nothing new to validate. The expectation that more documents validate does not hold--no-inline-config --format jsonover the 24 changed lintable files: 1 error, 53 warnings, 0 of them on a line this branch adds (attributed bygit diff -U0against the merge base). The error is theno-restricted-importsreport on a@objectstack/spec/uire-export inpackages/types/src/index.tsthat aneslint-disablecomment covers, which--no-inline-configignores; that line predates this branch. Population: each touched package'slintscript;eslint.config.jssets no type-aware parser project (0 matches forparserOptions,project:,projectService), so no untouched file's verdict can move. Fullpnpm lintis CI'sReverse verification
6007dd4e4each of the seven was refused with oneinvalid_unionattypeon both faces, and the ratchet read 8.PageKindNodeSchemaremoved from the root union byablation-replace(anchor hit 1 to 0, blob moved), the pin files run, the file restored. Predicted: the ratchet goes red with the three kinds. Read: 3 files red, 14 rows; "objectui validaterefuses 4 registered bare key(s) attype; the pin is 1. Refused: home, record, spec-report, utility". Restore proven: blob equals HEAD,git diff HEADempty.ObjectPivotBlockSchemaremoved fromObjectQLPublicBlockComponentSchemathe same way. Read: 2 files red, 15 rows; "Refused: object-pivot, spec-report". Restore proven the same way.reportwrapper: belongs to the second pull request.What is left (the second pull request)
The
spec-reportfold, in the ruled step order (reportdeclares the wrapper shape,DrillDownDrawermoves toreport, then the alias goes), needs one file the claim does not name:apps/console/src/register-plugins.tsregisters a lazyspec-reportstub besidereport-viewer, and an unregistered key with a surviving console stub strands that stub. Per the brief, that waits for the seat to amend the claim; it is not started here.Acceptance notes
object-pivotandembeddable-formregistrations still declareobjectNamerequired: true, while both renderers are gate-wrapped and the arms acceptdataSource.objectinstead. The parser tier's verdict on a binding-only node was not measured here; objectui#10392 is the calendar instance of the same shape.EmbeddableFormreads config keys its registration does not publish (branding,thankYouPage, the anti-spam keys and others). The arm declares the registration's inputs only, so the strict face refuses them as unrecognized keys.PageRendererderives its layout frompageType, defaulting torecord, and not fromtype, so a kind node rendered outsidePageView(which writes both) would draw the record layout. Read from the source, not measured.plugin-dashboard.mdxdescribeobject-pivotas an "internal wrapper aroundObjectPivotTable"; it is a Tier A public block with an arm now.Generated by Claude Code