Skip to content

fix(components): header-bar root receives its BaseSchema DOM channels (ariaLabel, style, id, testId, data-obj-*) (#10496) - #10562

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-10496-header-bar-root-dom-props
Sep 25, 2026
Merged

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-10496-header-bar-root-dom-props

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #10496
Clause-②: no

What changed

The registered header-bar renderer was a function of schema alone, so the props SchemaRenderer hands every component beside it never reached the root header element: an authored ariaLabel never named the banner landmark, and style, id, testId and data-obj-* rendered byte-identical to their absence (objectui#10397 had made the root honour className, nothing else).

The root now takes the converged route, the same one grid.tsx, box.tsx, stack.tsx and flex.tsx take (objectui#4435's): the props go through toDomProps (the SDUI whitelist in @object-ui/core) and style is forwarded by name. No per-key spread and no second route.

  • packages/components/src/renderers/navigation/header-bar.tsx: the registration destructures schema, the className prop and style; spreads toDomProps(hostProps) onto the header element; sets className from schema.className exactly as objectui#10397 left it, and style by name. The className prop is taken off the spread by name and left unread, because className is on the whitelist and would otherwise ride the spread as a second copy of the one class channel. No declared key reaches the DOM twice: the pin asserts each declared value lands on exactly one element, the root.
  • header-bar-classname-10397.test.tsx: its control row moves, re-stated rather than deleted (below).
  • New pin header-bar-root-dom-props-10496.test.tsx, beside the other header-bar tests.
  • @object-ui/types prose (see "Beyond the claimed file surface").
  • .changeset/10496-header-bar-root-dom-props.md: patch on @object-ui/components and @object-ui/types.

The objectui#10397 control row: the new exact list and why

It asserted the root's attributes were exactly ['class']. It now asserts exactly ['class', 'data-obj-type'] (sorted, because the order React sets attributes in is not the contract), plus data-obj-type="header-bar". The class value is still byte-identical to the pre-repair string.

data-obj-type joins because SchemaRenderer hands every component data-obj-type unconditionally, and the whitelist forwards the open data-* family. Nothing else joins on an unauthored node: data-obj-id and id are undefined without an authored id (React omits them), aria-label only exists when ariaLabel is authored, data-testid is conditional on testId, and style is undefined. Measured: with the fix and the old row, the row failed with exactly expected [ 'data-obj-type', 'class' ] to deeply equal [ 'class' ].

The widget-dom-leak sweep: reading unchanged, file untouched

packages/app-shell/src/__tests__/widget-dom-leak-sweep.test.tsx, run with the root reverted to reading schema alone (ablation leg 1 below, i.e. the pre-fix renderer): 230 of 230 green, ui:header-bar green. On the fix: 230 of 230 green, ui:header-bar green. data-obj-type is an HTML-defined data-* attribute, so it does not register as a leak, and the target's selector is still met by the shared readiness class. No ledger row, count or docblock in that file moves, so it is not in this diff.

It does now guard this target against one more regression. Under ablation leg 2 (bare {...hostProps} spread) the sweep's ui:header-bar row goes red, which it could not do while the root read schema alone.

Ablation: the pin has teeth, both ways

Both legs ran on the committed fix, through objectstack's scripts/ablation-replace.mjs (literal anchor, must hit exactly once, blob hash checked on disk), wrapped in a driver with an absolute-path trap restore. Each restore was proven by blob: header-bar.tsx back to ce3850854aef == HEAD, and git diff HEAD empty.

  • Leg 1, revert the wiring: the header opening tag replaced by the pre-fix className-only one. Anchor x1 to x0, blob ce3850854aef to e99ee6354277. Red: ariaLabel, style, id, testId, data-obj-*, lands-once and exact-list rows, plus the objectui#10397 control row, which reverts to ['class']. Green: the harness row and the undeclared-key control. 8 failed of 246 across the three files.
  • Leg 2, widen to a bare spread: {...toDomProps(hostProps)} replaced by {...hostProps}. Anchor x1 to x0, blob ce3850854aef to bca6ae4bf89e. Red: the undeclared-key control, the exact-list row, and the sweep's ui:header-bar. Green: every positive-channel row. 3 failed of 246. This is what shows the control can fail: it tells the whitelist apart from a bare spread.

Before the fix, the new pin read 8 failed of 9. Only the harness row was green: every declared channel was absent from the root, one key per row, through the real SchemaRenderer and registry.

Tests (all on 0b607015d, the head of this PR)

  • pnpm exec vitest run packages/components/ packages/app-shell/src/__tests__/widget-dom-leak-sweep.test.tsx from the repo root: 302 test files passed, 1 skipped; 3196 tests passed, 17 skipped; exit 0.
  • pnpm exec vitest run packages/types/: 235 files, 5199 tests passed, exit 0.
  • pnpm --filter '@object-ui/components^...' build (8 projects), then pnpm --filter @object-ui/components --filter @object-ui/types type-check: both packages' type-check script names echoed, Done, exit 0. tsc -p tsconfig.test.json --listFiles in components does include both header-bar test files.
  • pnpm check:control-bytes exit 0 (OK). pnpm check:new-line-citations exit 0, 0 new citation(s). node scripts/check-changeset-presence.mjs exit 0, 1 changeset declared. node scripts/check-changeset-no-major.mjs exit 0.
  • pnpm check:changeset-claims exit 0 (report-only). It flags four pending changesets that name a touched file: 6645, 6646, 6349 and 7917. I read each paragraph and all four are still true. 6645 describes, in the past tense, header-bar.tsx before crumb icons existed; the other three describe BreadcrumbSchema / BreadcrumbItem and their zod exports, which this diff does not touch.
  • Hand-derived gates, since this repo has no dispatch-gates script: check:component-surface-parity, check:test-path-roots, check:pending-changeset-literals, check:handler-key-reads, check:icon-record-names and check:vi-mock-specifiers all exit 0.
  • eslint over the five touched lintable files (--no-inline-config --format json, 5 results, none ignored), per rule against the base fee1da595 (base content fed through --stdin --stdin-filename at the same path): identical. header-bar.tsx has 1 react-refresh/only-export-components warning at base and head, and every other file is 0/0. The config enables no type-aware linting, so this diff cannot change eslint's verdict on any untouched file. The repo-wide pnpm lint is left to CI.
  • NOT MEASURED: check:sdui-registration-pins, which exits 2 with "No console build to weigh at apps/console/dist/assets" (a prerequisite missing, not a red gate). Left to CI. The registration call, its file and the sideEffects shape are unchanged.

Beyond the claimed file surface: @object-ui/types prose this change made false

The retirement texts for the header-bar keys (title, logo, nav, left, center, right, sticky, height, variant) explained each refusal with "the renderer ... takes no spread props". That sentence is published, in nine zod refusal messages in packages/types/src/zod/navigation.zod.ts and four doc comments in packages/types/src/navigation.ts, and this change makes it false. All thirteen now say the renderer "forwards to its root only what the shared DOM whitelist admits plus style". None of those keys is on the whitelist, so every refusal and its conclusion still holds. The tests that pin those messages check the REFUSED (...) prefix and the four named read keys, and both still pass. A tree-wide git grep for the old phrase now answers 0 hits; the control phrase reads no `title` hits both files. The claim's file surface did not list these two files; the report says so.

Acceptance notes

  • content/docs/components/navigation/header-bar.mdx documents className under Styling and lists id / testId in its Schema block, but says nothing about ariaLabel or style. Nothing on it is false, so it is untouched here; a sentence saying the base DOM channels reach the root would help authors.
  • Now that data-* reaches the root, a node that the dev-only structural check marks invalid carries data-obj-schema-invalid on the header, as the other converged renderers already do. Not measured or pinned here.
  • The role, aria-describedby, tabIndex and handler keys on the whitelist reach the root by the same route. Only the channels the card names are pinned.

Session: https://claude.ai/code/session_01BA3nKVUwKQJf8DBxrSVtNC (domain:ui seat 1, dispatched by the PM claim on the card).


Generated by Claude Code

…10496)

Adds the objectui#10496 pin ahead of the fix. Through the real
SchemaRenderer and registry, `ariaLabel`, `style`, `id`, `testId` and
`data-obj-*` do not reach the `header` root today; an undeclared key and
the keys the renderer consumes stay off the DOM as the control.
…#10496)

The registered `header-bar` renderer read `schema` alone, so the props
SchemaRenderer hands every component never reached the `header` root: an
authored `ariaLabel` never named the banner landmark, and `style`, `id`,
`testId` and `data-obj-*` rendered byte-identical to their absence.

The root now takes the converged route: the props go through
`toDomProps` (the SDUI whitelist in @object-ui/core) and `style` is
forwarded by name, as the other converged renderers do. `schema.className`
stays the one class channel read (objectui#10397); the `className` prop is
taken off the pass-through by name so it cannot ride the spread as a
second copy.

objectui#10397's control row moves with it: an unauthored root now
carries `data-obj-type` beside `class`, because SchemaRenderer injects it
unconditionally and the whitelist forwards the open `data-*` family.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BA3nKVUwKQJf8DBxrSVtNC
…s no spread props (#10496)

The refusal messages and doc comments for the retired header-bar keys
explained each refusal with "takes no spread props". The renderer now
forwards what the shared DOM whitelist admits, plus `style`, so the
sentence says that instead. None of the retired keys is on the
whitelist, so every refusal and its conclusion stand.

Adds the changeset for @object-ui/components and @object-ui/types.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BA3nKVUwKQJf8DBxrSVtNC
@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 4 pending changeset(s) describe a file this change touches

Their bodies publish verbatim into the CHANGELOG at the next release, so this is a request to re-read them against your diff — addressed here because you are the one seat that can answer it without re-deriving anything.

⛔ Nothing here blocks, and nothing here is a verdict on your change. This gate exits 0, is not a required context, and judges name resolution, never meaning: it asked whether a pending body names a file you touched. "Is this sentence still true?" is the one question it will not answer, and the one you are being asked to answer.

.changeset/6349-types-internal-name-collisions-batch-1.md

  • names navigation.ts → packages/types/src/navigation.ts — edited by this change

    BreadcrumbItem / BreadcrumbSchema — re-pointed, because one copy was stale. Both were declared in data-display.ts and in navigation.ts. The data-display pair was not a second dialect but a strict SUBSET: no key declared differently on either side, and missing BreadcrumbItem.icon / onClick / siblings and BreadcrumbSchema.maxItems. Everything that reads a breadcrumb was already on the navigation declaration — registry.ts maps the 'breadcrumb' component type to it, src/index.ts re-exports it under the bare names, zod/navigation.zod.ts mirrors it (icon, onClick, siblings, maxItems included), the ui:breadcrumb renderer consumes it, and the component's own documentation page documents icon and maxItems. data-display.ts now re-exports the one authority.

  • names zod/navigation.zod.ts → packages/types/src/zod/navigation.zod.ts — edited by this change

    BreadcrumbItem / BreadcrumbSchema — re-pointed, because one copy was stale. Both were declared in data-display.ts and in navigation.ts. The data-display pair was not a second dialect but a strict SUBSET: no key declared differently on either side, and missing BreadcrumbItem.icon / onClick / siblings and BreadcrumbSchema.maxItems. Everything that reads a breadcrumb was already on the navigation declaration — registry.ts maps the 'breadcrumb' component type to it, src/index.ts re-exports it under the bare names, zod/navigation.zod.ts mirrors it (icon, onClick, siblings, maxItems included), the ui:breadcrumb renderer consumes it, and the component's own documentation page documents icon and maxItems. data-display.ts now re-exports the one authority.

.changeset/6645-header-bar-crumb-icon.md

  • names header-bar.tsx → packages/components/src/renderers/navigation/header-bar.tsx — edited by this change

    HeaderBarSchema.crumbs is typed BreadcrumbItem[] — the same declaration BreadcrumbSchema.items uses — and its Zod mirror does not merely declare icon, it describes it (.describe('Breadcrumb icon')), so any authoring surface that reads Zod describe can already offer the key to an author. header-bar.tsx contained zero occurrences of the substring icon.

.changeset/6646-breadcrumb-separator-max-items.md

  • names packages/types/src/navigation.ts → packages/types/src/navigation.ts — edited by this change

    BreadcrumbSchema has declared both since it shipped (packages/types/src/navigation.ts, mirrored in zod/navigation.zod.ts), and separator is additionally advertised to authors on the component's own documentation page. The renderer contained zero occurrences of either name: it always emitted the bare BreadcrumbSeparator and it never collapsed. That made separator the sharper of the two — an author who read the page, wrote "separator": "/" and saw a chevron got feedback identical to having misspelled the key, with nothing to tell the two apart.

  • names zod/navigation.zod.ts → packages/types/src/zod/navigation.zod.ts — edited by this change

    BreadcrumbSchema has declared both since it shipped (packages/types/src/navigation.ts, mirrored in zod/navigation.zod.ts), and separator is additionally advertised to authors on the component's own documentation page. The renderer contained zero occurrences of either name: it always emitted the bare BreadcrumbSeparator and it never collapsed. That made separator the sharper of the two — an author who read the page, wrote "separator": "/" and saw a chevron got feedback identical to having misspelled the key, with nothing to tell the two apart.

.changeset/7917-export-breadcrumb-object-tree-zod-schemas.md

  • names navigation.zod.ts → packages/types/src/zod/navigation.zod.ts — edited by this change

    AnyComponentSchema declares 107 node component types. 105 of them could be named on the ./zod barrel — ButtonSchema.safeParse(node), which is what a designer, a form builder or a targeted test needs. The arms declaring type: 'breadcrumb' (navigation.zod.ts) and type: 'object-tree' (objectql.zod.ts) could not: both were already export const in their own module, but index.zod.ts — the package's only zod entry point — did not re-export them, so the schemas existed, were maintained, and were applied by the union while no consumer could name them.

Read the paragraph, not the line: both false halves of the objectui#8617 claim sat in one paragraph, and correcting either alone would have left it asserting the same wrong thing.

If a claim did go false, correct the body. That is precedented and prose-only, frontmatter untouched; check-changeset-overwrite.mjs will report the correction as its own case 2 ("correcting a declaration on purpose … legitimate"), which is the intended shape — one gate asks for the read, the other records the write.

Not covered, stated so nobody reads this as more: a born-false claim that spells no line address at all (objectui#9495 coordinated one by ORDINAL — "a grep finds that member first" — and deciding that means reading what the sentence means), a claim spelled as a symbol or a package rather than a backticked file name, and a file named ambiguously.

Compared the checked-out tree with a50600166 (merge-base with origin/main): 5 file(s) changed outside .changeset/, read against 1459 pending declaration(s) that publish a body (2041 pending in total). · run

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3046.3 KB 3104.5 KB
Main entry chunk (gzip) 147.7 KB 350 KB
Entry file index-CZNKvplG.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) 16.68KB 6.20KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
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.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
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.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 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) 545.58KB 130.50KB
core (index.js) 9.22KB 3.71KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 223.91KB 62.28KB
fields (index.js) 257.41KB 65.16KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
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.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.28KB 11.09KB
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) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
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.01KB 3.93KB
plugin-calendar (index.js) 51.38KB 14.60KB
plugin-charts (index.js) 74.95KB 20.88KB
plugin-chatbot (index.js) 198.36KB 47.20KB
plugin-dashboard (index.js) 133.50KB 35.37KB
plugin-designer (index.js) 216.25KB 44.39KB
plugin-detail (index.js) 232.59KB 61.50KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 146.50KB 37.51KB
plugin-gantt (index.js) 169.64KB 41.92KB
plugin-grid (index.js) 215.37KB 58.92KB
plugin-kanban (index.js) 48.26KB 15.04KB
plugin-list (index.js) 114.43KB 28.26KB
plugin-map (index.js) 22.42KB 7.38KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.55KB 11.99KB
plugin-timeline (index.js) 30.64KB 8.94KB
plugin-tree (index.js) 10.52KB 3.69KB
plugin-view (index.js) 87.31KB 21.78KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
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) 114.58KB 37.60KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.78KB 2.56KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.20KB
types (ai.js) 4.11KB 2.06KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
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) 0.20KB 0.18KB
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) 4.74KB 2.25KB
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 (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
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) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

CI red on 0b607015d: Test (shard 4/8 exceeded the job time limit), judged not this PR's

domain:ui seat #1, session_01BA3nKVUwKQJf8DBxrSVtNC, driving this PR for objectui#10496.

The failing check: Test (run 36116517852) failed only because Test (shard 4/8) (job 108011798285) was cancelled. Its step "Run tests (shard 4/8)" started at 2026-09-25T09:06Z and never recorded a completion, and the job hit "The job has exceeded the maximum execution time of 20m0s". The other seven shards of the same run took 454–626s, and shard 4 took 675–696s on every recent run the seat read.

Why it is judged not this PR's (the dev's measurements, objectui#10496 comment 5830579474): shard 4/8 run locally with CI's invocation (vitest run --shard=4/8, pool: 'threads', a 4-CPU box), with a per-module start/end reporter:

tree modules time stuck modules
this PR's head 0b607015d 448 527s none
origin/main d22b37bd8 (control) 449 512s none
CI's own merge rebuilt (main at fde4cafbb + 0b607015d) 449 512s none

The suite's testTimeout is 15s, so a slow test would fail rather than stall. No shard-4 file and no vitest.config.mts branch reads CI / GITHUB_ACTIONS. The step's own log is not retrievable from this container (its blob redirect is refused by the egress proxy). No fix exists, because nothing in this diff reproduces the stall.

Re-run: this seat has no job re-run op. The branch is behind main, so it gets one base merge (a merge commit carrying main, with no change of its own), and CI runs on the new head. If shard 4 stalls again on that head, it is treated as real and root-caused, ⛔ not re-run again.


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3047.2 KB 3104.5 KB
Main entry chunk (gzip) 147.8 KB 350 KB
Entry file index-C7E8SqT-.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) 16.68KB 6.20KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
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.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
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.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 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) 545.35KB 130.42KB
core (index.js) 9.22KB 3.71KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 223.91KB 62.28KB
fields (index.js) 258.75KB 65.60KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
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.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.28KB 11.09KB
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) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
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.01KB 3.93KB
plugin-calendar (index.js) 51.40KB 14.61KB
plugin-charts (index.js) 74.94KB 20.89KB
plugin-chatbot (index.js) 198.36KB 47.20KB
plugin-dashboard (index.js) 133.50KB 35.37KB
plugin-designer (index.js) 216.25KB 44.39KB
plugin-detail (index.js) 232.59KB 61.50KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 147.92KB 37.83KB
plugin-gantt (index.js) 169.62KB 41.91KB
plugin-grid (index.js) 215.37KB 58.92KB
plugin-kanban (index.js) 48.26KB 15.04KB
plugin-list (index.js) 114.43KB 28.26KB
plugin-map (index.js) 22.42KB 7.38KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.55KB 11.99KB
plugin-timeline (index.js) 30.64KB 8.94KB
plugin-tree (index.js) 10.52KB 3.69KB
plugin-view (index.js) 87.31KB 21.78KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
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) 114.58KB 37.60KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.78KB 2.56KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.20KB
types (ai.js) 4.11KB 2.06KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
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) 0.20KB 0.18KB
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) 4.74KB 2.25KB
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 (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
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) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
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

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 25, 2026 10:36
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 25, 2026
Merged via the queue into main with commit 1daf477 Sep 25, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-10496-header-bar-root-dom-props branch September 25, 2026 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

1 participant