Skip to content

fix(types): declare the component-node arm of DashboardComponentSchema.widgets on the TypeScript face - #8296

Merged
os-zhuang merged 3 commits into
mainfrom
claude/issue-7952-dashboard-widgets-union-arm
Sep 7, 2026
Merged

fix(types): declare the component-node arm of DashboardComponentSchema.widgets on the TypeScript face#8296
os-zhuang merged 3 commits into
mainfrom
claude/issue-7952-dashboard-widgets-union-arm

Conversation

@os-zhuang

@os-zhuang os-zhuang commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Fixes #7952

What

DashboardComponentSchema.widgets (packages/types/src/complex.ts) becomes the two-arm union the zod twin has carried since the 2026-08-14 ruling (objectstack#8593): an array of DashboardWidgetSlotComponentSchema | DashboardWidgetSchema, component arm first as in zod/complex.zod.ts. DashboardWidgetSlotComponentSchema is new — extends BaseSchema with type: DashboardComponentWidgetType — and is exported from @object-ui/types (added to the barrel). packages/types/src/zod/complex.zod.ts is untouched. DashboardWidgetSchema is NOT widened with value / icon / trend / trendValue.

Ruling applied as written (director seat, decision batch #68, 2026-09-07, maintainer 「同意」; card comment 5565355483) — not re-opened here.

Spelling choice (the brief asked which and why)

An interface … extends BaseSchema rather than an intersection or a discriminated member:

  • it is the one-to-one twin of the zod arm's BaseSchema.extend({ type: z.enum(DASHBOARD_COMPONENT_WIDGET_TYPES) }), and the same shape DashboardComponentSchema itself uses (extends BaseSchema plus a literal type);
  • the export is a deliberate authoring-surface decision, not a compiler requirement — measured in this package's own build (declaration + composite, TypeScript 6.0.3): a non-exported arm referenced from the exported DashboardComponentSchema builds exit 0, emits into dist/complex.d.ts as a local interface, and a barrel consumer still writes the node with no name. It is exported so an author can annotate the node the platform accepts (the README teaches it), an intentional asymmetry with the zod twin's non-exported arm, whose docblock records why that const stays private. (Corrected in the patch round: the first version of this bullet claimed TS4033 forced the export — false, per the contract review.)
  • BaseSchema's [key: string]: any is the passthrough, so the component's own props reach the compiler through the index signature and never through DashboardWidgetSchema.

Measurements (re-driven before and after; both PM mechanism assumptions measured, not inherited)

Before, on fc32921. The six const schema = { type: 'dashboard', … } blocks of packages/plugin-dashboard/README.md, extracted from the page's own bytes, annotated DashboardComponentSchema and compiled --strict against the source declaration: 6 × TS2561 ('value' does not exist in type 'DashboardWidgetSchema'. Did you mean to write 'values'?) — the card's five across :47 / :177 / :274, plus one in the "Dashboard with Charts" block at :216, which PR #7951 rewrote after the card was measured. Runtime, same shape: DashboardComponentSchema.safeParse ACCEPT, all seven authored keys preserved.

After, on 297b014. Same six blocks, same annotation, same harness: 0 errors. The runtime verdict is unchanged (the zod face was not edited). The edited README "TypeScript Support" block also compiles against the BUILT packages/types/dist/index.d.ts — the check:doc-snippets question, narrowed to the one block this PR edits (exit 0).

Corners, measured on the source after the change (each is also pinned):

literal in widgets[] TypeScript face zod face
{ type: 'bar', title, bogus: 1 } refused, TS2353 — discriminated by type refused, unrecognized_keys [bogus]
{ type: 'metric-card', someProp: 1 } accepted — the passthrough arm, by ruling accepted, key kept
{ type: 'not-a-component', value } refused, TS2322 refused
{ id, component: {…}, layout } — legacy envelope, no type accepted accepted
{ id, component: {…}, bogus: 1 } — legacy envelope plus a stray key accepted — nothing to discriminate on, so the arm's index signature satisfies the union's excess-property check refused, unrecognized_keys [bogus]
const w: DashboardWidgetSchema = { type: 'metric-card', value } refused, TS2561 — the forbidden widening did not happen n/a

The stray-key envelope row is the one cost of a TypeScript union with a passthrough arm. It is recorded in the member's docblock and pinned two-faced (tsc accepts, zod refuses by name) so it reads as a measured limit rather than a hatch; the runtime is the strict face on that corner, as it already is for every BaseSchema slot.

Consumer cost, measured. The arm is assignable to DashboardWidgetSchema, so every (w: DashboardWidgetSchema) callback in plugin-dashboard compiled unchanged (pinned). An UNANNOTATED element read — schema.widgets.map with a bare w reading w.layout, at DashboardGridLayout.tsx:96 / :161, DashboardWithConfig.tsx:155, DashboardEditor.tsx:559 — now resolves through the index signature to any instead of the widget's declared type — it compiles and checks less. Stated in the changeset; not repaired here: it is BaseSchema's own any, the one every SchemaNode consumer already carries, and annotating those sites is a plugin-dashboard / plugin-designer change outside this card's surface.

Pin — packages/types/src/__tests__/dashboard-widget-slot-component-arm-7952.test.ts

Two-faced, enforced by tsconfig.test.json through type-check (objectui#3009): the README shape compiles AND parses with its keys kept; DashboardWidgetSchema still refuses value (an @ts-expect-error that becomes TS2578 if anyone widens it); the arm's type is closed by reference; the slot element IS the two-arm union; the arm is assignable to DashboardWidgetSchema; the discriminated refusals hold on both faces; the envelope corner is recorded as above.

Reverse verification — committed first; run on 297b014 inside the verify lock; script with a restore trap. widgets put back to DashboardWidgetSchema[] (on-disk proof: two-arm spelling 1 to 0, one-arm spelling 0 to 1), then tsc -p tsconfig.test.json: exit 2, 4 errors, all four in the new pin:82 TS2561 on value, :101 the two-arm Equal collapsing to false, :165 and :184 the two passthrough literals turning into TS2353. Predicted two, measured four: the direction is red as expected, and the extra two are the passthrough-arm literal and the envelope-corner literal, both excess-property errors once the arm is gone. Restore proved by blob hash — git hash-object after restore equals HEAD:packages/types/src/complex.ts (b7571577), git diff HEAD --stat empty. The ablation resolves through the tests' relative ../complex.js imports (source, not dist/), so no build leg was involved.

Gates — final head 297b014; every exit captured to disk before any output was read

gate reading
pnpm --filter @object-ui/types type-check (build project + examples + tests) exit 0
pnpm exec vitest run packages/types/ 138 files, 2633 tests passed, exit 0. The parity ledgers are unchanged: WiderThanDeclared['complex.zod.ts#DashboardComponentSchema'] still lists widgets, its remaining reason being the SCHEMA-NODE component slot of the second arm — the per-arm re-judgement is objectui#8252's
pnpm --filter @object-ui/plugin-dashboard type-check (13-package dependency closure built first) exit 0
pnpm --filter @object-ui/plugin-designer type-check (closure built first) exit 0
readme-dashboard-examples-spec-valid.test.ts (plugin-dashboard) 7 passed
check:spec-symbols · check:doc-types · check:doc-fences · check:control-bytes · check-changeset-presence all exit 0
lint, narrowed eslint --format json over the 3 changed .ts files: 3 files judged, 0 errors, 10 pre-existing no-explicit-any warnings on lines this PR does not touch. Population read from eslint.config.js (files: ['**/*.{ts,tsx}'] blocks). Invariance: no parserOptions.project / projectService (linting is not type-aware) and no custom rule under eslint-rules/ reads other files, so this diff cannot move any untouched file's verdict
check:doc-snippets NOT RUN locally — needs every package's dist/ (its own --build-filter lists 34 packages). The narrowed reading above (edited block against the built types .d.ts, exit 0) stands in; the whole-farm run is CI's
check:readme-exports NOT MEASURED locally — exits 1 with "could not be judged … dist/index.d.ts is not on disk" for 508 self-imports across unbuilt packages: a prerequisite not met, not a verdict. This PR's README edit imports from @object-ui/types, a cross-package import outside that gate's self-import rule
app-shell type-check declared to CI — its five widgets reads all go through (draft as any).widgets casts, so the element union cannot reach them

验收备注

  • noted, not filed: packages/plugin-dashboard/README.md:131 still declares widgets: DashboardWidgetSchema[] in the "Dashboard Schema" block — valid TS (the narrower array is assignable) and it teaches the spec-family usage; left as is.
  • noted, not filed: zod-mirror-parity.test.ts's WiderThanDeclared note "widgets is SCHEMA-NODE" is now true of the whole key (the first arm is aligned); rewording it per arm is objectui#8252's census, whose file surface it is.
  • filed as objectui#8290: content/docs/api/schema-reference.md's dashboard table teaches colSpan / rowSpan / body as widget keys (all three refused by name — reproducer in the card) and refreshInterval in milliseconds where the renderer multiplies by 1000; that row's widgets type column is also one arm short after this PR — one docs edit, out of this card's surface.

Route

Draft, needs:contract-review (clause ②: a published TypeScript accept set widens; @object-ui/types changeset, minor). Reviewed in-seat before any ready / queue / auto-merge step — none taken here. Related: objectui#8252 (the census ordered by this card's ruling, held behind this PR), objectui#7035 / PR #7951 (the README's docs half), objectui#6002 (the .strict() ruling the refusals rest on).

Implemented in Claude Code session session_01QtGhnU3WnnWyiWeYQhw2aX (PM loop round R1, domain:spec seat).

🤖 Generated with Claude Code

https://claude.ai/code/session_01QtGhnU3WnnWyiWeYQhw2aX


Generated by Claude Code

…a.widgets on the TypeScript face

`widgets` was `DashboardWidgetSchema[]` while the zod twin has carried a
two-arm union since the 2026-08-14 ruling (objectstack#8593): a component
node placed directly in the slot (`type: 'metric-card'`, passthrough
`BaseSchema` body) or a spec-family widget. Every `metric-card` block the
plugin-dashboard README teaches parsed green and `tsc --strict` refused it
(6 x TS2561 on `value` at fc32921). Ruled option (a), decision batch #68.

- `DashboardWidgetSlotComponentSchema` — `BaseSchema` with `type` narrowed to
  the closed `DASHBOARD_COMPONENT_WIDGET_TYPES`; exported (declaration emit
  needs a name, TS4033) and added to the barrel.
- `widgets: Array<DashboardWidgetSlotComponentSchema | DashboardWidgetSchema>`,
  component arm first, as in the zod twin. `DashboardWidgetSchema` is NOT
  widened with `value` / `icon` / `trend` / `trendValue`.
- Two-face pin `dashboard-widget-slot-component-arm-7952.test.ts`: README
  shape compiles and parses; forbidden widening still refused; discriminated
  refusals hold; the measured union corner (type-less envelope + stray key
  compiles, zod refuses by name) recorded, not contracted.
- README "TypeScript Support" table and prose corrected to the two-arm slot.
- Changeset: `@object-ui/types` minor (published TS accept set widens).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QtGhnU3WnnWyiWeYQhw2aX
@github-actions github-actions Bot added documentation Improvements or additions to documentation package: types plugin tests labels Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3472.1 KB 3512.7 KB
Main entry chunk (gzip) 143.9 KB 350 KB
Entry file index--2K1PeVY.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) 15.67KB 5.75KB
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) 5.13KB 2.35KB
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) 497.99KB 113.90KB
core (index.js) 7.20KB 2.88KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 189.15KB 52.56KB
fields (index.js) 243.14KB 61.38KB
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) 6.57KB 2.76KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
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.84KB 10.94KB
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) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
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) 5.12KB 1.74KB
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) 15.16KB 3.68KB
plugin-calendar (index.js) 48.03KB 13.29KB
plugin-charts (index.js) 71.39KB 19.92KB
plugin-chatbot (index.js) 193.54KB 46.04KB
plugin-dashboard (index.js) 131.43KB 34.43KB
plugin-designer (index.js) 213.21KB 43.63KB
plugin-detail (index.js) 248.56KB 63.89KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 131.01KB 32.32KB
plugin-gantt (index.js) 167.16KB 40.99KB
plugin-grid (index.js) 208.58KB 56.63KB
plugin-kanban (index.js) 52.83KB 14.63KB
plugin-list (index.js) 113.38KB 27.73KB
plugin-map (index.js) 20.49KB 6.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 30.10KB 8.74KB
plugin-tree (index.js) 9.33KB 3.25KB
plugin-view (index.js) 84.46KB 20.80KB
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) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
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.55KB 2.45KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 13.64KB 4.59KB
types (ai.js) 0.20KB 0.17KB
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.90KB 1.47KB
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 (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

…xported

Contract review on PR #8296 measured the docblock's claim that TS4033 forces
the export as false: in this package's own build (declaration + composite,
TypeScript 6.0.3) a non-exported arm referenced from the exported
DashboardComponentSchema emits into dist/complex.d.ts as a local interface,
exit 0, and a barrel consumer still writes the node with no name.

- arm docblock: the export is a deliberate authoring-surface decision — a
  name an author can annotate the node with — taken intentionally in the
  opposite direction to the zod twin's non-exported const.
- "the second arm" → the component arm, first in the declaration as in zod
  (complex.ts closed-set docblock, plugin-dashboard README).

Comment and prose only; no declaration, pin, changeset or barrel change.

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

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3472.2 KB 3512.7 KB
Main entry chunk (gzip) 143.9 KB 350 KB
Entry file index-rjCZWbsD.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) 15.67KB 5.75KB
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) 5.13KB 2.35KB
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) 497.99KB 113.90KB
core (index.js) 7.48KB 2.96KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 189.15KB 52.56KB
fields (index.js) 243.15KB 61.40KB
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) 6.57KB 2.76KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
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.84KB 10.94KB
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) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
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) 5.12KB 1.74KB
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) 15.16KB 3.68KB
plugin-calendar (index.js) 48.03KB 13.29KB
plugin-charts (index.js) 71.39KB 19.92KB
plugin-chatbot (index.js) 193.54KB 46.04KB
plugin-dashboard (index.js) 131.48KB 34.45KB
plugin-designer (index.js) 213.21KB 43.63KB
plugin-detail (index.js) 248.56KB 63.89KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 131.01KB 32.32KB
plugin-gantt (index.js) 167.16KB 40.99KB
plugin-grid (index.js) 208.58KB 56.63KB
plugin-kanban (index.js) 52.83KB 14.63KB
plugin-list (index.js) 113.38KB 27.73KB
plugin-map (index.js) 20.49KB 6.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 30.10KB 8.74KB
plugin-tree (index.js) 9.33KB 3.25KB
plugin-view (index.js) 84.46KB 20.80KB
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) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
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.55KB 2.45KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 13.64KB 4.59KB
types (ai.js) 0.20KB 0.17KB
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 (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

@os-zhuang
os-zhuang marked this pull request as ready for review September 7, 2026 11:09
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 7, 2026
Merged via the queue into main with commit c842594 Sep 7, 2026
34 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-7952-dashboard-widgets-union-arm branch September 7, 2026 11:32
os-zhuang pushed a commit that referenced this pull request Sep 7, 2026
…r key

objectui#8252. `WiderThanDeclared` recorded one prose class per ENTRY, and the
clause for `DashboardComponentSchema.widgets` was three words — "`widgets` is
SCHEMA-NODE" — true of its second arm and false of its first, a concrete
component node the TypeScript face was missing whole (objectui#7952, declared
by #8296 as c842594). A per-KEY verdict over a per-ARM fact.

`WIDER_ARMS` records one verdict per union arm of each ledgered key. The arm
ENUMERATION is measured from the mirror values (`measureMirrorArms`); the
verdicts are judged. Pinned: every ledgered key has exactly one row, every row
names one verdict per MEASURED arm, and objectui#7952's key cannot collapse to
a single verdict. The header gains this ledger's figures — the fifth ledger and
the only one objectui#7733 / objectui#8222 did not reach, which is how "27
SCHEMA-NODE keys" could be quoted while the re-derived figure is 25.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QtGhnU3WnnWyiWeYQhw2aX
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation package: types plugin tests

Projects

None yet

2 participants