Skip to content

fix(core/app-shell): accept and resolve an inline I18nLabel on an action's resultDialog (objectui#9542) - #9826

Merged
os-sales merged 3 commits into
mainfrom
claude/issue-9542-result-dialog-i18nlabel
Sep 18, 2026
Merged

os-sales merged 3 commits into
mainfrom
claude/issue-9542-result-dialog-i18nlabel

Conversation

@os-sales

@os-sales os-sales commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #9542

Clause-②: no

@object-ui/core's ResultDialogSpec claimed in its own docblock to mirror Action.resultDialog in @objectstack/spec and did not. Four of its members — title, description, acknowledge and fields[].label — were hand-written string where the contract declares every one of them I18nLabel: a plain string or an inline per-locale map, both authorized by that type's own docblock and neither deprecated. So this repo refused what the platform accepts, which is check:spec-symbols' rule-2 failure class — an alignment CLAIM with a hand copy behind it.

The three steps: derive the members from the contract, do the resolution at the dialog, then delete the workaround objectui#8648 left behind.

The runtime severity: MEASURED, not restated

The card filed this reading as unverified and asked for confirmation. Confirmed — and it is a throw, not a mis-render. A rendering test with a locale-map title on the unfixed tree:

Error: Objects are not valid as a React child (found: object with keys {en, zh-CN}).
 ❯ throwOnInvalidObjectTypeImpl …/react-dom-client.development.js
 ❯ reconcileChildFibersImpl …
 ❯ renderRootSync …

Nothing upstream coerces or guards the value first. React 19.2.8 throws at the first such member reached, so the dialog never mounts — on an action that has already succeeded, and this dialog is the only place a one-shot reveal is ever shown. Three rendering legs failed this way before the change; the three plain-string legs in the same file passed unchanged, which is the control that makes this a reading about the map arm and nothing else.

⚠️ The card's 2FA / OAuth client_secret / backup-code examples are the contract's own illustrations of what resultDialog is for. They are not a measured population and are not restated as one here.

What changed

Derive, do not hand-copy. @object-ui/core already depends on @objectstack/spec and already imports Action from @objectstack/spec/ui, so the contract type is reachable — checked rather than assumed, and no hand-written fallback was needed. The four label members are now indexed-access derivations off the contract's own result-dialog block through two module-local aliases. ⛔ No new exported symbol: the two interfaces stay the only names this module publishes for the block, so the clause-② no stands on its terms.

Resolve at the dialog. Through @objectstack/spec/ui's resolveI18nLabel, imported under this package's established resolveInlineI18nLabel alias. ⛔ Not resolveKeyedI18nLabel — that takes the KEYED vocabulary and these members are the INLINE form. A plain-string label is unaffected: the resolver returns it unchanged and the existing fallback chain still answers for an absent label or a map with no usable entry (the || chain is kept over ?? for exactly that reason).

The workaround is out. Both action renderers drop as ActionDef OPEN-BRACKET 'resultDialog' CLOSE-BRACKET, so the whole forward is compiler-checked with nothing between it and ActionDef again. (Spelled in words: GitHub's body sanitizer eats tag-shaped fragments, and an index into a type is what this sentence is about.)

Zone-2 mechanism assumptions, each tested

The locale source — one source, no fork. All six in-package resolveInlineI18nLabel sites trace to the same value, useObjectTranslation().language from @object-ui/i18n: AppSidebar and UnifiedSidebar destructure language off that hook and pass it directly; resolveActionParams takes it threaded in and says so in its own docblock; the three metadata-admin sites take a locale prop fed by useMetadataLocale, which reads that same language and clamps it to that designer's two bundled catalogue locales. The clamp is about the designer's own copy catalogue, not a second source — so the un-clamped language is what a runtime surface like this dialog wants, matching the three runtime sites. The dialog already called that hook for t.

The sibling type carries the same drift, and repairing it is FORCED by ruling 5 — measured. ResultDialogFieldSpec.label is the contract's fourth I18nLabel member on this block. It is not a scope judgement: with label reverted to string and everything else in place, @object-ui/components' type-check goes red at BOTH forward sites with TS2322 … Types of property 'label' are incompatible, because the narrowing assertion that used to absorb it is gone. Deleting the assertions and leaving the sibling drifted do not compose. The ablation was run on disk and restored (git diff HEAD empty afterwards).

Tests

A case that is red before and green after, plus a converted pin that is red under ablation.

  • packages/app-shell/src/views/__tests__/ActionResultDialog.test.tsx — three new legs. Before: Tests 3 failed | 3 passed (6), all three failing with the React throw above. After: green. One leg varies only the display language and asserts the other locale's text is resolved AWAY, so the legs cannot pass by rendering both.
  • packages/components/src/renderers/action/__tests__/action-undeclared-keys-8648.test.ts — the objectui#8648 ledger leg is converted, not merely deleted. Its as any negative was never the workaround: castBefore only matches a cast between schema and the key, so a write-side as any walks straight past it and this is the only leg that refuses it. Ablation: re-injecting the narrowing assertion at both sites turns the converted legs red (Tests 2 failed | 14 passed); restored, git diff HEAD empty.

Commands and exit codes, each captured before any pipe, on 7321c6e3:

⚠️ Seat note (domain:ui seat 3, added after the fact — the dev writes this body once and does not PATCH it). The head has since moved to 23592bab, two commits on: one re-attaching the spec-alignment docblock to the interface it describes (the derived aliases had landed between them, detaching the claim and reddening check:spec-symbols), and one appending the supersession note to .changeset/8648-ui-action-four-undeclared-keys.md. The dev reports every ratchet family re-run green on that head. Independently measured by this seat on 23592bab at the time of this edit: 29 success · 3 expected skips · 0 non-success, with four Test shards still running. ⛔ The table below is left exactly as authored — it is the reading on 7321c6e3 and is not restated as a reading on the current head.

command exit
pnpm exec vitest run packages/core/ packages/components/ 0 — 436 passed (436) files, 6022 passed (6022) tests
pnpm exec turbo run build --filter=@object-ui/app-shell --filter=@object-ui/components --filter=@object-ui/core 0 — 29/29
pnpm exec turbo run type-check (same three filters) 0 — 32/32
pnpm check:spec-symbols 0
pnpm check:action-forward-parity 0
pnpm check:control-bytes 0
pnpm check:new-line-citations 0
pnpm check:phantom-deps · check:unused-deps · check:self-import · check:esm-specifiers 0
pnpm check:published-dist · check:published-tsconfig-exclude · check:readme-exports · check:unreferenced-sources 0
pnpm check:comment-mask-corpus · check:i18n-keys 0
node scripts/check-changeset-presence.mjs 0
pnpm exec turbo run lint (same three filters) 0 — 4/4, zero error-level findings
pnpm check:eager-closure 0 — ⚠️ see below

⚠️ check:eager-closure is a cached-artifact reading. The gauge needs apps/console/dist/eager-closure.json; the console build it comes from was a 100% turbo cache hit (35 cached / 35, 1s), and this checkout shares one turbo cache with every sibling worktree. So the gate's exit 0 does not prove anything about THIS tree's closure. It is reported as it is rather than greened over. The diff adds no new module edge into the console's eager graph — @objectstack/spec/ui is already imported eagerly by AppSidebar in this same package — so the expected movement is zero, but that is reasoning, not the measurement.

The build had to run before the type-checks: a package type-check ahead of its dependency closure produces TS6305 false reds. Both readings were taken in that order and both were green.

Deviations from the declared file surface — two, both declared

  1. packages/app-shell/src/views/__tests__/ActionResultDialog.test.tsx is not on the declared surface, and the dispatch also requires a case that fails before the change and passes after. The card's own example is a locale-map title reaching this dialog, and its existing sibling test file is where that lives. Extended rather than stopped, and named here.
  2. A second commit re-attaches the spec-alignment docblock to the interface it describes. The derived aliases had landed BETWEEN that docblock and the interface, which detached the claim — attachedDoc in scripts/check-spec-symbol-derivation.mjs reads only the LAST leading comment block — and pnpm check:spec-symbols went red asking for the ledger entry to be deleted. Moving the aliases above the docblock restores the attachment. ⛔ No gate script was edited.

Acceptance notes

  • check:spec-symbols' rule-2 ledger has no state for "claim now BACKED by derivation". Measured: with the claim re-attached and the members derived, deleting ResultDialogFieldSpec from CLAIM_DEBT makes the gate red — a spec-alignment claim has nothing behind it — so the entry must stay although the debt it records is paid. CLAIM_DEBT means unbacked and CLAIM_ALLOW means deliberate divergence; a repaired symbol fits neither, so it can never leave the ledger, and the ledger's own burn-down instruction cannot be followed for this class. Left as a finding; a gate change is a maintainer-floor item and ⛔ not this card's.
  • The card's "one package over from where that gate matches by name" is true of rule 1 only. Rule 2 already covers @object-ui/core and had this very symbol ledgered as CLAIM_DEBT the whole time. Extending rule 1 is therefore a smaller idea than the card implies — it was the CLAIM half, not the coverage half, that was missing.
  • Not filed, noted only: the dialog's fields fallback entry spells label: undefined explicitly where omission would read the same; nothing carries it.

What this PR does not touch

Out of scope: #9572 is not addressed here, and #8941 remains open — both are neighbours in the same directories on different files, and neither is touched. objectui#8648 is referenced only as the card that left the workaround behind.

This PR was drafted by an agent seat; the session reference is session_01Xm4WFhEe5mwcgyqHjxR2hn.


Generated by Claude Code


Generated by Claude Code

…ontract and resolve them (objectui#9542)

`@object-ui/core`'s `ResultDialogSpec` claimed to mirror `Action.resultDialog`
in `@objectstack/spec` and did not: `title`, `description`, `acknowledge` and
each `fields[].label` were hand-written `string` where the contract declares
every one of them `I18nLabel` — a plain string or an inline per-locale map,
both authorized and neither deprecated. All four now derive from the contract
type, so the alignment is re-checked by `tsc` instead of asserted in prose.

Measured consequence: the map arm reached `ActionResultDialog`'s JSX as a React
child, React refused the object, and the dialog threw rather than
mis-rendering — the one-shot reveal failed to render at all on an action that
had already succeeded. The dialog now resolves all four through
`resolveI18nLabel` from `@objectstack/spec/ui` (the producer's own resolver for
the inline form, aliased per this package's convention) against
`useObjectTranslation().language`.

Both action renderers drop the write-side narrowing assertion objectui#8648 left
behind, and its ledger leg is converted to pin the unasserted write — keeping
only the `as any` negative, which was never the workaround.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xm4WFhEe5mwcgyqHjxR2hn
…it describes

The derived local aliases had been inserted BETWEEN the "Mirrors
`Action.resultDialog` in @objectstack/spec" docblock and the interface it
describes, which detached the claim: `attachedDoc` in
`scripts/check-spec-symbol-derivation.mjs` reads only the LAST leading block,
so `pnpm check:spec-symbols` reported the claim as gone and asked for its
ledger entry to be deleted. Moving the aliases above the docblock puts the
claim back on the exported mirror, where the ledger already tracks it.

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

github-actions Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 3 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/6306-action-icon-type-resolution.md

  • names action-button.tsx → packages/components/src/renderers/action/action-button.tsx — edited by this change

    Scope is this one renderer. type: schema appears in exactly two files under renderers/action/ — action-button.tsx (already correct) and action-icon.tsx; action:group and action:menu compose their members differently and are untouched.

  • names action-icon.tsx → packages/components/src/renderers/action/action-icon.tsx — edited by this change

    Scope is this one renderer. type: schema appears in exactly two files under renderers/action/ — action-button.tsx (already correct) and action-icon.tsx; action:group and action:menu compose their members differently and are untouched.

.changeset/8318-jsdoc-default-tag-corrections.md

  • names core/src/actions/ActionRunner.ts → packages/core/src/actions/ActionRunner.ts — edited by this change

    • CRUDDialogSchema.size / .closeOnOutsideClick / .closeOnEscape / .showClose — there is no register('crud-dialog' anywhere, so no node of that type ever reaches a renderer. Recorded once on the interface. Per key, the name census differs: two spellings occur nowhere outside the declaration and its zod twin, and showClose's one other occurrence (renderers/overlay/drawer.tsx:38) belongs to DrawerSchema. - ActionSchema.level — type: 'action' is not a rendered node type, and core/src/actions/ActionRunner.ts, which is what makes method / chainMode / reload / close live, does not read level. - CardSchema.variant — card IS registered, twice, and neither registration reads it: the ui route forwards the key to ui/card.tsx, which spreads onto a div and mentions variant nowhere, and the page route forwards only its designer props. - PageNodeSchema.isDefault — page IS registered, and PageRenderer neither reads the key nor forwards it: the wrapper element gets toDomProps(props), an allow-list that does not carry it.

.changeset/action-keys-warning-text-5642.md

  • names ActionRunner.ts → packages/core/src/actions/ActionRunner.ts — edited by this change

    Both halves of the message's tail had outlived the change they described. It told the author the key was warned about rather than rejected because ActionDef "still carries [key: string]: any" — objectstack#4075 step 3 deleted that index signature, and actionKeys.pin.test.ts pins the deletion in the opposite direction ({ ActionDef: false, ActionContext: true }), while actionDef-closed-surface.test.ts pins that tsc now rejects exactly such a key at the construction site. And it prescribed promoting the key to an explicit field on ActionDef "(packages/core/src/actions/actionKeys.ts)" — that file holds the INVENTORY (ACTION_DEF_KEYS); the interface is in ActionRunner.ts. The wrong pointer had teeth: an author who followed it edited the inventory alone, which is precisely the half-change the pin test reddens on, since it re-derives the inventory from the interface's AST.

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 d2f19cba9 (merge-base with origin/main): 6 file(s) changed outside .changeset/, read against 1148 pending declaration(s) that publish a body (1680 pending in total). · run

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3049.5 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-Dn2i9bzi.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.69KB 6.21KB
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) 25.05KB 9.16KB
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.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
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) 26.08KB 7.56KB
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.99KB 130.71KB
core (index.js) 8.94KB 3.59KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 215.98KB 59.97KB
fields (index.js) 249.23KB 62.88KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.22KB 2.26KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 32.15KB 10.49KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.83KB 10.95KB
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) 2.53KB 0.85KB
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.39KB 3.10KB
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) 14.81KB 3.63KB
plugin-calendar (index.js) 49.92KB 14.22KB
plugin-charts (index.js) 71.61KB 20.05KB
plugin-chatbot (index.js) 195.34KB 46.51KB
plugin-dashboard (index.js) 131.44KB 34.65KB
plugin-designer (index.js) 215.94KB 44.33KB
plugin-detail (index.js) 253.28KB 65.87KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.71KB 34.16KB
plugin-gantt (index.js) 167.62KB 41.26KB
plugin-grid (index.js) 212.61KB 57.90KB
plugin-kanban (index.js) 48.10KB 14.94KB
plugin-list (index.js) 112.74KB 27.70KB
plugin-map (index.js) 21.48KB 6.99KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.41KB 11.93KB
plugin-timeline (index.js) 30.07KB 8.74KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 85.05KB 21.01KB
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) 104.82KB 34.67KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.66KB 2.50KB
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) 14.82KB 4.99KB
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) 4.73KB 2.28KB
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) 14.04KB 5.36KB
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

…ded by this change

`.changeset/8648-ui-action-four-undeclared-keys.md` is pending, so its body
publishes verbatim into the CHANGELOG at the next release. Its last paragraph
states in the present tense that the `resultDialog` WRITE carries a narrowing
assertion at both forward sites and that a ledger entry pins it — which this
change removes, in the same release. A supersession note is appended rather
than the original claims rewritten: every word the objectui#8648 author wrote
stands, and the final state is stated after it.

The other three pending changesets naming files this branch edits were checked
and are unmoved: 6306's `type: schema` population is byte-identical on the base
and this branch and no line of it is in this diff; 8318's "`ActionRunner.ts`
does not read `level`" still holds (every `level` in that file is prose);
5642's argument rests on `ActionDef` carrying no index signature and on the
interface living in `ActionRunner.ts`, neither of which this diff touches.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3049.5 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-Dn2i9bzi.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.69KB 6.21KB
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) 25.05KB 9.16KB
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.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
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) 26.08KB 7.56KB
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.99KB 130.71KB
core (index.js) 8.94KB 3.59KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 215.98KB 59.97KB
fields (index.js) 249.23KB 62.88KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.22KB 2.26KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 32.15KB 10.49KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.83KB 10.95KB
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) 2.53KB 0.85KB
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.39KB 3.10KB
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) 14.81KB 3.63KB
plugin-calendar (index.js) 49.92KB 14.22KB
plugin-charts (index.js) 71.61KB 20.05KB
plugin-chatbot (index.js) 195.34KB 46.51KB
plugin-dashboard (index.js) 131.44KB 34.65KB
plugin-designer (index.js) 215.94KB 44.33KB
plugin-detail (index.js) 253.28KB 65.87KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.71KB 34.16KB
plugin-gantt (index.js) 167.62KB 41.26KB
plugin-grid (index.js) 212.61KB 57.90KB
plugin-kanban (index.js) 48.10KB 14.94KB
plugin-list (index.js) 112.74KB 27.70KB
plugin-map (index.js) 21.48KB 6.99KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.41KB 11.93KB
plugin-timeline (index.js) 30.07KB 8.74KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 85.05KB 21.01KB
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) 104.82KB 34.67KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.66KB 2.50KB
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) 14.82KB 4.99KB
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) 4.73KB 2.28KB
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) 14.04KB 5.36KB
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

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