Skip to content

fix(examples): repair the class (i) keys the strict authoring face refuses (objectui#5250 slice C) - #12128

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-5250-class-i-repairs
Oct 11, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-5250-class-i-repairs

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #5250
Clause-②: no

Slice C of the objectui#5250 programme: the non-docs class (i) documents. These are authored documents that the shipped strict authoring face (StrictAnyComponentSchema, the face objectui validate judges with) refuses only because they carry a key that no schema declares. The slice table and its drop-list are in the park review (comment 5887006513): no deletion without runtime proof, and no declaration. Slice B is objectui#12127 (the JSON-fence gate plus the docs repairs). This card stays open until both have merged.

The set, re-derived on the dispatch base 5a65f7d

Instrument: a throwaway script. It reads every examples/schema-catalog/src/schemas/**/*.json, examples/hello-world/schema.json, and the exported nodes of packages/types/examples/*.ts. It judges each node document whole with the built StrictAnyComponentSchema and AnyComponentSchema, and names keys with the CLI's own findUndeclaredKeys.

Reading: 435 node documents. 26 are refused, 13 of them strict-only. 14 documents carry an undeclared key, and they hold 12 (component, key) pairs:

  • 11 catalog fixtures;
  • examples/hello-world/schema.json;
  • packages/types/examples/dashboard.ts;
  • packages/types/examples/login-form.ts.

The other 12 refusals (5 carousel, 6 resizable, 1 toaster stack) name no undeclared key. Both faces refuse them for value or shape reasons, so they are not class (i) and are not touched here.

The dispatch order's "25 files" is the whole class (i) set of the measurement report, docs included. The non-docs half is these 14.

Per-pair disposition and runtime proof

Instrument: a throwaway dom-project test, never committed. It renders each node through the real SchemaRenderer and the real registry (packages/components/src/renderers plus @object-ui/fields), once with the key and once without it. It compares the normalised document.body HTML. Combobox cases are compared with the popover OPEN, where a search placeholder or an empty text would show.

Controls: every declared key a pair is renamed to changes the output, so the instrument can see a read key: items[].children, className: "w-full", submitLabel, colSpan, label, children, and the combobox placeholder.

file pair runtime reading disposition
components-basic-navigation-menu/documentation-nav.json, site-navigation.json navigation-menu items[].items identical. The renderer reads item.children (control: it draws a submenu trigger) renamed to children
components-data-display-list/basic-list.json list items[].type (x3) identical. ui:list draws each item's content removed
components-form-button/full-width-button.json button fullWidth identical (control: className: "w-full" adds the class) replaced by className: "w-full", the declared key the fixture's name asks for
components-form-combobox/country-selector.json, searchable-combobox.json combobox searchPlaceholder, emptyText identical with the popover open, both with options and with none. The renderer passes only DOM keys on (toFormControlDomProps) removed
components-form-form/contact-form.json, login-form.json, registration-form.json form submitButton differs only by a stray submitbutton DOM attribute on the form element (control: submitLabel changes the button text) renamed to submitLabel
components-form-form/contact-form.json form field columnSpan differs only by a stray columnspan attribute on the textarea (control: colSpan adds the md:col-span-2 class) renamed to colSpan
components-form-label/required-label.json label required differs only by a required attribute on the label element, which draws no indicator removed
fields-object/structured-configuration.json object field schema identical removed
examples/hello-world/schema.json button content identical: the button rendered blank (control: label draws it) renamed to label (the park review's rename)
packages/types/examples/dashboard.ts card content differs only by a stray content DOM attribute. The data table never rendered (control: children renders it) renamed to children
packages/types/examples/login-form.ts form field defaultChecked READ: with true the checkbox renders checked. false is identical only because it is the default not touched: a class (ii) pair, reported, neither deleted nor declared

H6, checked: only the button node's content is undeclared in hello-world. Its two text nodes author content, which text declares and reads, so they stay.

After the change

The same instrument reads 435 documents, 0 strict-only refusals, and 14 refused:

  • the 12 shape and value refusals above;
  • login-form.ts: the class (ii) defaultChecked, plus the host-supplied onSubmit function that both faces refuse by name as a runtime slot;
  • dashboard.ts, which is NEW to the refused list for a non-class-(i) reason. With children in place, the data table is parsed (and rendered) for the first time, and it carries host-supplied onRowEdit / onRowDelete functions. That is the same runtime-slot refusal as login-form.ts's onSubmit. It was masked until now, because the misplaced content key kept the table out of every parse and every render.

Reverse leg: with the 13 repaired documents reverted to 5a65f7d5, the instrument reads 26 refused, 13 strict-only, and 14 carrying an undeclared key, which is the base reading. Restored with git checkout HEAD -- FILES; git diff HEAD is empty afterwards.

Pins

  • H7 does not hold as written. examples/schema-catalog/test/safe-validate-corpus-6318.test.ts pins seven named fixtures, none of them touched here, and by design it pins no corpus count. It is unchanged and green.
  • The count that moved is NODE_CENSUS in examples/schema-catalog/test/layout-dom-leak-5574.test.tsx. Its structural walk collected basic-list's three type: "text" items as bare text nodes, so text moves by exactly three: rendered 687 to 684, no-element 140 to 137. It is re-pinned with a dated comment in the file's own style.

Gates (HEAD 54a95e75)

command exit
locked vitest run over examples/schema-catalog/ (including the 6318 pin and the census) and every test outside it that names schema-catalog or hello-world (71 files, two runs) 0, "Test Files 68 passed (68)" / "Tests 2988 passed (2988)", and "Test Files 45 passed (45)" / "Tests 1274 passed, 16 skipped (1290)"
pnpm --filter @object-ui/types type-check (echoed tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json) 0
node scripts/check-changeset-presence.mjs 0, "no changeset is owed", so none is added (packages/types/examples/** is outside @object-ui/types' files, and the catalog and hello-world are private examples)
pnpm check:new-line-citations 0, "0 new citation(s)"
pnpm check:control-bytes 0
pnpm docs:check-links 0
pnpm check:doc-types 0
node scripts/check-governed-queue-guard.mjs --test over the 14 paths 0, NOT GOVERNED
pnpm check (the CLI self-check lint.yml runs) NOT MEASURED: it needs the CLI build. It exits non-zero only on unreadable JSON or an expression refusal, and every edited JSON file parses. Declared to CI

Acceptance notes

  • Class (ii), not repaired here. login-form.ts's defaultChecked is read through the checkbox field widget. Slice B measured the same channel for a text field's defaultValue. The strict face refuses both, so objectui validate tells an author to remove keys that work. Reported on the card for the declaration side; nothing is declared here.
  • Docs interface blocks still advertise three of the removed keys: content/docs/components/form/button.mdx (fullWidth), form.mdx (submitButton) and label.mdx (required, "Show required indicator"). The probes above show nothing reads them. Those pages are outside both slices' file surfaces, so this is reported on the card rather than changed here.

The session that produced this change is https://claude.ai/code/session_01DwLS3LzXyNmyTunMGbpc8W.


Generated by Claude Code

…fuses (objectui#5250)

Slice C of the objectui#5250 programme. Each catalog fixture, the
hello-world schema and packages/types/examples/dashboard.ts carried a key
no schema declares; each pair was rendered through the real
SchemaRenderer with and without the key before it changed:

- renamed to the declared key the renderer reads: navigation-menu
  `items[].items` -> `children`; form `submitButton.label` -> `submitLabel`;
  form field `columnSpan` -> `colSpan`; button `content` -> `label`
  (hello-world); card `content` -> `children` (dashboard.ts, whose data
  table never rendered); button `fullWidth` -> `className: "w-full"`;
- removed, with no runtime effect: list `items[].type`, combobox
  `searchPlaceholder` / `emptyText`, label `required`, object field
  `schema`.

`packages/types/examples/login-form.ts` keeps `defaultChecked`: the
checkbox field widget reads it (a `true` renders the box checked), so it
is a class (ii) pair, reported rather than deleted or declared.

The layout DOM-leak census moves by the three list items the structural
walk no longer collects as bare text nodes.

Claude-Session: https://claude.ai/code/session_01DwLS3LzXyNmyTunMGbpc8W
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 290 chunks) 3171.9 KB 3204.6 KB
Main entry chunk (gzip) 74.1 KB 350 KB
Entry file index-DdsIEOhh.js —
Status PASS —

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

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 19.75KB 7.29KB
app-shell (runtime-config.js) 22.59KB 7.89KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 41.19KB 11.12KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.11KB 7.97KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 586.97KB 141.32KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 240.39KB 67.09KB
fields (index.js) 274.56KB 69.81KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 40.26KB 11.71KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 15.35KB 5.51KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 54.31KB 15.86KB
plugin-charts (index.js) 84.72KB 23.27KB
plugin-chatbot (index.js) 201.52KB 47.99KB
plugin-dashboard (index.js) 144.20KB 38.95KB
plugin-designer (index.js) 233.53KB 49.80KB
plugin-detail (index.js) 249.33KB 65.74KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 177.59KB 46.00KB
plugin-gantt (index.js) 179.17KB 45.07KB
plugin-grid (index.js) 251.36KB 69.68KB
plugin-kanban (index.js) 53.23KB 16.71KB
plugin-list (index.js) 122.77KB 31.19KB
plugin-map (index.js) 27.24KB 9.03KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.12KB 12.29KB
plugin-timeline (index.js) 39.21KB 11.85KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 92.11KB 23.27KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants