Skip to content
This repository was archived by the owner on Oct 26, 2026. It is now read-only.

feat(core,types)!: retire the module widget source and its runtime dynamic import (objectui#13450) - #13473

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-13450-retire-widget-module-source
Oct 25, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-13450-retire-widget-module-source

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #13450

Clause-②: no (narrowing)
Metadata-protocol: narrowed

Retires the module widget source. WidgetRegistry.load() resolved { type: 'module', url } with new Function('url', 'return import(url)'). That is the runtime dynamic import AGENTS.md commandment #6 forbids ("No eval() / runtime dynamic imports to load components"). The claim is the PM's comment 6386913269 on the card, for branch claude/issue-13450-retire-widget-module-source, session https://claude.ai/code/session_01432GBvPzfZ6CsLanp9xzkZ.

What changes

  • @object-ui/types: the module member and its WidgetSourceModule interface are removed. RuntimeWidgetSource is now WidgetSourceInline | WidgetSourceRegistry, and the barrel no longer exports WidgetSourceModule. The union's docblock records the retirement and the migration. The manifest's JSDoc @example now uses { type: 'inline', component } with a locally defined CustomChart component (the build-time import is named in a comment, so the block compiles in isolation under check-doc-example-types) instead of a URL.
  • @object-ui/core: the case 'module' arm and its Function-constructor sink are removed from WidgetRegistry.resolveComponent(). The default: arm is now exhaustive (const unhandled: never = source), so a union member added without an arm fails to compile.
    • An untyped manifest that still reaches load() with type: 'module' is refused by name before anything is fetched. Untyped means plain JS, a cast, or an older @object-ui/types. The error names the widget, the retired "module" source and both replacements.
    • Any other unknown type is refused with the supported types listed.
    • In both cases load() emits widget:error and loadAll() reports the error. The class docblock and its example no longer mention URL loading.
  • Changeset .changeset/13450-retire-widget-module-source.md: minor for core and types. objectui never declares major (check-changeset-no-major); the break is stated in the body as BREAKING. The changeset gives the FROM → TO migration and the one-line fix, and carries the Clause-②: / Metadata-protocol: lines.
  • page-nav-misc-spec-parity.test.ts: the reason string in one it.each row said "module/inline/registry loader union" and now says "inline/registry". It is a test title, not an assertion.

Migration (FROM → TO)

  • FROM source: { type: 'module', url: '/widgets/chart.js', exportName: 'Chart' }
  • TO import { Chart } from './widgets/chart' and source: { type: 'inline', component: Chart } (imported at build time, so the bundler sees it)
  • OR ComponentRegistry.register('chart', Chart) once, and source: { type: 'registry', registryKey: 'chart' }

Premise check: the card's "four emitting sites" are not widget sources

The card and the triage route name four type: 'module' producers. Each one was read in context at a3c0da9. All four are the generated package.json's ESM marker ("type": "module"), not a widget manifest source. Deleting them would make the scaffolded packages CommonJS and break their import syntax. None was changed:

Site (by symbol) What it builds Verdict
buildAppPackageJson in packages/cli/src/utils/app-generator.ts temp app package.json (name, private, type, deps) package.json ESM marker; kept
buildRoutedAppPackageJson in the same file routed temp app package.json package.json ESM marker; kept
buildInitPackageJson in packages/cli/src/commands/init.ts objectui init project package.json (scripts.dev: 'vite') package.json ESM marker; kept
buildPackageJson in packages/create-plugin/src/templates.ts generated plugin package.json (main, module, exports) package.json ESM marker; kept

So @object-ui/cli and @object-ui/create-plugin carry no change and no changeset, which narrows the route. No widget-manifest producer of a module source exists in this tree. A git grep for WidgetSourceModule before this change hit only its declaration and the barrel. apps/console/src and packages/app-shell/src construct no module source (triage's reading). objectstack and hotcrm reference neither WidgetRegistry nor RuntimeWidgetSource in code (the only objectstack hit is a doc paragraph that does not name the module source). Out-of-tree consumers are NOT MEASURED.

No user-facing doc names the module widget source. content/docs, the package READMEs and docs/ were checked with git grep; the control ComponentRegistry hits in content/docs. The two JSDoc examples were the only documentation of it, and both are rewritten.

Tests (head e15036c)

  • be01ada (patch round): check-doc-example-types exit 1 → 0 (34 → 35 compile; WidgetRegistry #1 back on its TS2304 ledger row). JSDoc text only.

New describe('the retired \module` source (objectui#13450)')inpackages/core/src/registry/tests/WidgetRegistry.test.ts`:

  1. A manifest with source: { type: 'module', url } is refused. The rejection is an Error that names "test-widget", "module", type: 'inline' and type: 'registry'; these are the named subjects, not the wording. The global Function constructor, proxied for construct and apply, records zero calls. Nothing is marked loaded or synced into the component registry. The literal carries @ts-expect-error, so the type-level refusal is pinned too: core's type-check runs tsconfig.test.json, which includes src/**/*.test.ts.
  2. loadAll() reports the refusal for that widget, a sibling still loads, and widget:error fires.
  3. An unknown type (remote) is refused with "inline" and "registry" named and no "retired" wording.
  • pnpm exec vitest run packages/core/ --maxWorkers=2: Test Files 211 passed (211), Tests 4089 passed | 27 skipped (4116)
  • pnpm exec vitest run packages/types/ --maxWorkers=2: Test Files 388 passed (388), Tests 10568 passed (10568)
  • pnpm --filter @object-ui/types --filter @object-ui/core run type-check: both Done, exit 0. This ran after both packages were rebuilt, so core's test program read the new dist/*.d.ts.

Ablation, runtime (one-shot, through ablation-replace.mjs, restored to the HEAD blob): a case 'module' arm with the Function-constructor import was re-planted ahead of default:. On-disk marker count was 1, sink count 1. Result: Tests 2 failed | 24 passed (26). Test 1 received "A dynamic import callback was not specified." instead of the refusal; test 2 failed the same way. Test 3 stayed green, which is the expected direction. After the restore, git diff HEAD was empty and the blob equalled HEAD. A first attempt used an anchor that the replacement re-contained; the tool refused it and nothing ran.

Reverse verification, types (cross-package): a { type: 'module'; url: string } member was re-added to RuntimeWidgetSource and @object-ui/types rebuilt; the dist marker count was 1. Core's tsc -p tsconfig.test.json then reported TS2578: Unused '@ts-expect-error' directive on the new test and TS2322 ... is not assignable to type 'never' on the exhaustive arm. After the restore and a rebuild, the dist marker count was 0 and the same tsc was green.

Gates (local, at e15036c)

Exit codes were captured to a file before reading:

  • lint (core + types): exit 0. 0 errors; the warnings are all pre-existing no-explicit-any, and none is on a changed line.
  • check:new-line-citations 0 · check:control-bytes 0 · check-changeset-presence 0 · changeset:check (fixed + no-major) 0 · check:changeset-claims 0 · check:pending-changeset-literals 0 · check:spec-symbols 0 · check:unreferenced-sources 0 · check:doc-example-readers 0 · check:shell-escape-residue 0 · check:test-path-roots 0
  • check:readme-exports: exit 1, NOT MEASURED for the repo as a whole. The only unjudged population is @object-ui/app-shell, which was unbuilt; every other package was judged with 0 fabricated, 0 wrong-path. No README names WidgetSourceModule.
  • check:published-dist: exit 1, NOT MEASURED. Its internal whole-workspace turbo run build hit a heap OOM in @object-ui/app-shell, so it judged nothing. That is environmental and not this diff. CI owns this gate.

origin/main was merged before opening; it had not moved from the branch base a3c0da9, so the merge was a no-op. objectui#13442 is in flight in the same batch on disjoint files (packages/core/src/actions/** and the DataSource type). The only shared surface is the @object-ui/types barrel, where this PR removes a single line in the widget block.

Acceptance notes

  • Remote widgets as a product capability (a signed manifest and an allow-listed origin, decided in spec) are the maintainer's call and are not part of this card, per the triage ruling.
  • register() still accepts a manifest with a retired or unknown source, and the refusal happens at load(). That matches the ruling's "refuse an old manifest loudly in default:" and how the registry already treats a missing registryKey.

Generated by Claude Code

…dynamic import

WidgetRegistry.load() resolved a `{ type: 'module', url }` source with
`new Function('url', 'return import(url)')`, the runtime dynamic import
AGENTS.md commandment #6 forbids. Remove the `module` member of
RuntimeWidgetSource, the WidgetSourceModule interface and the loader
arm. The `default:` arm is now exhaustive over the union and refuses an
untyped old manifest by name (naming both replacements) before anything
is fetched; any other unknown source type is refused with the supported
types listed.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 85 chunks) 3006.3 KB 3496.0 KB
Main entry chunk (gzip) 80.3 KB 350 KB
Entry file index-BrMiBfRo.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 (buildIdentity.js) 0.80KB 0.49KB
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 21.41KB 7.90KB
app-shell (runtime-config.js) 24.52KB 8.48KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 45.59KB 12.03KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 20.67KB 6.12KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.74KB 3.94KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.62KB 0.83KB
auth (authStyles.js) 5.27KB 1.86KB
auth (createAuthClient.js) 42.84KB 11.66KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 8.84KB 3.61KB
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.26KB 8.03KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (commentAuthorship.js) 1.39KB 0.78KB
collaboration (index.js) 1.93KB 0.85KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 614.94KB 150.52KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 253.04KB 70.68KB
fields (index.js) 295.90KB 75.88KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 41.17KB 11.96KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 15.35KB 5.51KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
permissions (ServerReadScope.js) 4.03KB 1.82KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.99KB 0.43KB
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.91KB
plugin-calendar (index.js) 55.41KB 16.19KB
plugin-charts (index.js) 88.30KB 24.33KB
plugin-chatbot (core.js) 5.22KB 2.18KB
plugin-chatbot (index.js) 237.93KB 56.26KB
plugin-dashboard (index.js) 147.15KB 39.95KB
plugin-designer (index.js) 232.83KB 50.01KB
plugin-detail (index.js) 267.21KB 71.14KB
plugin-editor (index.js) 2.21KB 1.04KB
plugin-form (index.js) 185.46KB 48.48KB
plugin-gantt (index.js) 178.19KB 45.06KB
plugin-grid (index.js) 278.30KB 77.57KB
plugin-kanban (index.js) 64.27KB 19.81KB
plugin-list (index.js) 149.60KB 39.26KB
plugin-map (index.js) 27.11KB 8.99KB
plugin-markdown (index.js) 13.79KB 4.79KB
plugin-report (index.js) 46.42KB 13.06KB
plugin-timeline (index.js) 39.30KB 11.87KB
plugin-tree (index.js) 15.25KB 5.38KB
plugin-view (index.js) 94.26KB 24.27KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 129.13KB 42.23KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.71KB 2.11KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.81KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (product-blocks.js) 0.20KB 0.19KB
types (record-approval-decision.js) 0.20KB 0.20KB
types (record-components.js) 0.20KB 0.19KB
types (record-panels.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

The retirement rewrote the RuntimeWidgetManifest and WidgetRegistry JSDoc
examples to import CustomChart from a relative './widgets/CustomChart'
path. The JSDoc example gate (check-doc-example-types.mjs) compiles each
block in isolation, where that module does not exist: TS2307 made the
types example an undeclared failure and drifted the core example's
ledger row (declared TS2304, produced TS2304 + TS2307).

Both examples now define a trivial local CustomChart component and name
the build-time import in a comment, so the types example compiles and the
core example fails exactly as its existing ledger row declares.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 85 chunks) 3033.6 KB 3496.0 KB
Main entry chunk (gzip) 80.3 KB 350 KB
Entry file index-DtLbgeX6.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 (buildIdentity.js) 0.80KB 0.49KB
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 21.41KB 7.90KB
app-shell (runtime-config.js) 24.52KB 8.48KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 45.59KB 12.03KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 20.67KB 6.12KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.74KB 3.94KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.62KB 0.83KB
auth (authStyles.js) 5.27KB 1.86KB
auth (createAuthClient.js) 42.84KB 11.66KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 8.84KB 3.61KB
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.26KB 8.03KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (commentAuthorship.js) 1.39KB 0.78KB
collaboration (index.js) 1.93KB 0.85KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 614.94KB 150.52KB
core (index.js) 10.51KB 4.16KB
create-plugin (index.js) 27.92KB 9.50KB
data-objectstack (index.js) 253.04KB 70.68KB
fields (index.js) 295.90KB 75.88KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 41.17KB 11.96KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 15.35KB 5.51KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
permissions (ServerReadScope.js) 4.03KB 1.82KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.99KB 0.43KB
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.91KB
plugin-calendar (index.js) 55.31KB 16.16KB
plugin-charts (index.js) 88.30KB 24.33KB
plugin-chatbot (core.js) 5.22KB 2.18KB
plugin-chatbot (index.js) 237.93KB 56.26KB
plugin-dashboard (index.js) 147.15KB 39.95KB
plugin-designer (index.js) 232.83KB 50.01KB
plugin-detail (index.js) 268.92KB 71.56KB
plugin-editor (index.js) 2.21KB 1.04KB
plugin-form (index.js) 185.46KB 48.48KB
plugin-gantt (index.js) 178.19KB 45.06KB
plugin-grid (index.js) 277.62KB 77.39KB
plugin-kanban (index.js) 64.27KB 19.81KB
plugin-list (index.js) 149.51KB 39.15KB
plugin-map (index.js) 27.54KB 9.10KB
plugin-markdown (index.js) 13.79KB 4.79KB
plugin-report (index.js) 46.42KB 13.06KB
plugin-timeline (index.js) 39.74KB 12.00KB
plugin-tree (index.js) 15.25KB 5.38KB
plugin-view (index.js) 93.37KB 24.00KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 129.13KB 42.23KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.71KB 2.11KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.81KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (product-blocks.js) 0.20KB 0.19KB
types (record-approval-decision.js) 0.20KB 0.20KB
types (record-components.js) 0.20KB 0.19KB
types (record-panels.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

The retirement removes the module member of a published union and an
export, so the clause line must name the narrowing arm; a bare no
declares no direction.

Claude-Session: https://claude.ai/code/session_01432GBvPzfZ6CsLanp9xzkZ
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 504c0ee96646bfc99d689fb98296673ae41c06a3
Local-runs: none
Scope: packages/core/src/registry/WidgetRegistry.ts, packages/core/src/registry/tests/WidgetRegistry.test.ts, packages/types/src/widget.ts, packages/types/src/index.ts, packages/types/src/tests/page-nav-misc-spec-parity.test.ts + packages/cli/src/utils/app-generator.ts, packages/cli/src/commands/init.ts, packages/create-plugin/src/templates.ts, packages/core/src/index.ts, scripts/check-doc-example-types.mjs, .changeset/config.json, scripts/check-changeset-no-major.mjs, AGENTS.md, packages/plugin-charts/src/index.tsx, packages/plugin-charts/src/normalizeChartSchema.ts, content/docs/guide/plugins.md, skills/objectui/guides/plugin-development.md, .changeset/13450-retire-widget-module-source.md (prose; read for ②)

Face: narrowing, declared Clause-②: no (narrowing) line-initial in the changeset (.changeset/13450-retire-widget-module-source.md:22), on the PR body (line 3) and on the amended claim 6386913269. Inputs: card #13450's body and its four comments (6385681238, 6386913269 as amended, 6387223880, 6393016217), PR #13473's body and file list, the net diff of 504c0ee against main (merge-base a3c0da9, three commits: e15036c, be01ada, 504c0ee), and the check-runs on be01ada and on 504c0ee. The head moved from be01ada to 504c0ee while this review was being written; the delta is one line in the changeset (Clause-②: no became Clause-②: no (narrowing)), so every code reading below holds byte-for-byte on this head. The cited code was read with git show and git grep on the fetched head objects in the shared clone; nothing was checked out, built, run or re-run.

① Derived judgments

  1. @object-ui/types accept set: RIGHT, narrowing only. RuntimeWidgetSource is WidgetSourceInline | WidgetSourceRegistry (widget.ts:178-180); the WidgetSourceModule interface is deleted and its barrel line (index.ts:1559 on main) removed. git grep WidgetSourceModule on the head tree hits only the changeset prose and the RETIRED paragraph at widget.ts:157-158; exportName and source.url hit comments only. No dangling export, alias, re-export or reader anywhere in the tree. packages/core/src/index.ts:15 re-exports the class, not the source types.

  2. @object-ui/core accept set: RIGHT, narrowing only. resolveComponent() keeps inline and registry, and the default: arm is exhaustive (const unhandled: never = source, WidgetRegistry.ts:297), so a union member added without an arm is a compile error, a tightening. The new Function('url', 'return import(url)') sink is gone: the head tree's only return import( hits are the static-specifier imports in apps/site/app/components/PluginLoader.tsx, which a bundler sees, and its new Function hits are console boot tests, the ExpressionCache and SafeExpressionParser comments, and the new test's spy. The old default: message Unknown widget source type for has no reader in the tree, so rewording it breaks nothing.

  3. The refusal is loud, named and pre-fetch: RIGHT. load() returns the cache, throws not-registered, resolves dependencies (pre-existing, no I/O), then resolveComponent() throws inside the switch before anything is fetched; the catch at WidgetRegistry.ts:205-209 emits widget:error and rethrows, and loadAll() collects the Error. The module message names the widget, the retired "module" source and both replacements; the unknown-type message names the offending type and both supported types. Test 1 pins zero Function constructions, isLoaded false and no sync into the component registry; test 3 pins that an unknown type is not mis-reported as retired.

  4. Silent acceptance left: register() still stores a manifest with a retired or unknown source, and getAllManifests() and getStats() count it until load() refuses it. That is the ruling's own shape ("refuse an old manifest loudly in default:") and the treatment a missing registryKey has always had. Not a defect; written down so the next reader meets a decision rather than an accident.

  5. The ruling's "four emitting sites": the dev's reading is RIGHT at source. app-generator.ts:304 (buildAppPackageJson) and :322 (buildRoutedAppPackageJson), init.ts:386 (buildInitPackageJson), templates.ts:152 (buildPackageJson): each type: 'module' sits in a generated package.json object literal beside name, private, version, main, exports or dependencies. They are Node ESM markers, not RuntimeWidgetSource values, and deleting them would flip the scaffolds to CommonJS. The card body's "still generate type: 'module' manifests" is false, so the triage route inherited a false premise. A whole-tree git grep for type: 'module' finds no widget-shaped producer beyond the two new test literals (one under @ts-expect-error, one cast through unknown); the app-shell hit is an ObjectStack package row and the cli test hits are package.json fixtures. Leaving cli and create-plugin untouched is correct.

  6. Documentation surface: RIGHT. No README, content/docs, docs/ or skills/ file names WidgetSourceModule, WidgetRegistry or RuntimeWidget* on the head (zero hits). The two "type": "module" hits in content/docs/guide/plugins.md:397 and skills/objectui/guides/plugin-development.md:367 are package.json JSON blocks. The two JSDoc examples were the only documentation of the URL source and both are rewritten to inline. The module/inline/registry rows in the package CHANGELOGs are release history and are correctly untouched. plugin-charts/src/index.tsx:158 and normalizeChartSchema.ts:164 name WidgetRegistry as the manifest-defaults consumer; that seam (load() lines 179-200) is unchanged.

  7. Doc-example ledger: RIGHT. scripts/check-doc-example-types.mjs:643 declares WidgetRegistry #1 as [2304] for the undeclared registry; the head's example still leaves registry undeclared and now defines CustomChart locally, so the row stands unedited. widget.ts has no row and its example is self-contained. Repo Gates, which runs this gate, is success at be01ada on the identical code tree, confirming the patch round; on this head it is in progress at the last read.

  8. The @ts-expect-error pin: RIGHT. core's type-check is tsc --noEmit && tsc -p tsconfig.test.json, and tsconfig.test.json compiles src/**/*.test.ts, so the pin is checked by the CI Type Check job (in progress at the last read).

  9. page-nav-misc-spec-parity.test.ts:792: a title string in an it.each row; the assertion (names does not contain RuntimeWidgetSource) is unchanged. RIGHT.

  10. Nit, not a verdict carrier: the RuntimeWidgetSource docblock still opens with "Describes how to load the widget's code at runtime." (widget.ts:142) and RuntimeWidgetManifest.source is still "Widget loading source configuration" (widget.ts:111); both outlive the retirement, since inline is already resolved and registry is a lookup. Harmless; a follow-up docs touch at most.

② Semver level

  • The changeset declares @object-ui/core: minor and @object-ui/types: minor with a BREAKING first line, the FROM → TO migration, the one-line fix, and Clause-②: no / Metadata-protocol: narrowed line-initial. That matches what the diff publishes: a union member, an exported interface, a barrel export and a runtime arm are removed from two published packages, and nothing else is published. RIGHT.
  • minor rather than major is the objectui rule, not a dodge: AGENTS.md:284 forbids major in changesets (the fixed group is pinned to objectstack's major; objectui's own breaking changes ship minor with the breaking semantics in the body), and scripts/check-changeset-no-major.mjs enforces it. Changeset Bump Policy, Changeset Fixed Group Check, Changeset Declaration and Changeset Claim Re-read are success on the head. The ! on the commit and PR titles is the conventional-commit spelling of the same fact.
  • The triage ruling's changesets for cli and create-plugin: their absence is RIGHT. Zero lines change under packages/cli or packages/create-plugin (PR file list), so check-changeset-presence owes none, and a changeset describing a removal that did not happen would be a false claim. All four packages also sit in the single fixed group in .changeset/config.json, so the minor on core and types carries cli and create-plugin to the same version regardless.
  • The Clause-②: line: no (narrowing) on both carriers and on the claim is RIGHT, and it is the only spelling that is. Every public-surface delta is a removal; the never arm and the descriptive refusal messages widen no accept set, and no new key, member, export or file format is introduced, so the direction is narrowing and the arm says so. The arm is load-bearing, not decoration: reviewFace in scripts/pm/record-recognisers.mjs reads the face off the changeset's line, and only the exact (narrowing) arm selects the narrowing face at CONTRACT_REVIEW_TIER; a bare no declares no direction and reads as the declaration face at TIER_DEFAULT, and a near-miss (narrowed, Narrowing) reads malformed. At be01ada both carriers spelled a bare no, which under that rule was a finding of the kind the sibling review on objectui#13475 (comment 6393057967) raised and which this record would have had to carry as a FAIL; 504c0ee closes it with the one token on the changeset, the PR body and the claim, in the spelling objectui's own packages/types/CHANGELOG.md precedents use. The changeset publishes verbatim into the CHANGELOGs, so the corrected line is what ships.

③ Boundary flags

Report 6387223880 (implementation round):

  • Ruling-vs-measurement conflict on the four sites: answered in ① item 5; the dev's H2 reading is verified at source and the card body's premise is wrong. Escalated to the PM as a card correction: the body's "Producers still alive" paragraph is false, and nothing on this PR depends on it.
  • File surface beyond the claim (packages/types/src/index.ts, page-nav-misc-spec-parity.test.ts): both are required by the removal (the barrel line must go for tsc to pass; the test title named the retired member) and both sit inside the claim's "docs naming the module widget source" reading. Answered.
  • check:published-dist run outside os-verify-lock: a process breach the dev disclosed; it changes no byte of the diff. Repo Gates is success at be01ada on the identical code tree, so CI has judged what that local run could not. Answered, left for the PM's process ledger.
  • ! shipped as minor: ② above. Answered.
  • Ablation and reverse-verification claims: consistent with the diff (the never arm and the @ts-expect-error are exactly what the reverse leg says went red). Not re-run here (Local-runs: none); CI Type Check is the gate that proves them.
  • Out-of-scope finding, register() accepting a retired source: ① item 4. Answered.

Report 6393016217 (patch round):

  • origin/main not merged (9 commits since a3c0da9): the PR reads mergeable: true and pull_request CI runs on the merge ref; per the report main touched neither the checker nor the two example files. Accepted.
  • PR body open question (the stale @example sentence and the missing be01ada test line): closed. The PR body at this head already carries the corrected wording ("with a locally defined CustomChart component (the build-time import is named in a comment, so the block compiles in isolation under check-doc-example-types)") and the "be01ada (patch round): check-doc-example-types exit 1 → 0" line under Tests, so the seat applied the first of the two edits the dev spelled out. One residual: the body's Gates section still says "origin/main was merged before opening; it had not moved", which was true at e15036c and is superseded by this report's 9-commit reading. Cosmetic; no code claim rests on it.
  • Worktree removed after the push: process only.

Head move be01ada to 504c0ee (commit "docs(changeset): declare Clause-② as no (narrowing)"): one changeset line, no code. The PR body's line 3 and the claim 6386913269 carry the same spelling, the claim with an amendment note naming its source. The three carriers agree, which is what the recogniser and the queue guard read. Answered; see ②.

CI on this head (504c0ee), last read 2026-10-25T03:45Z, about two minutes after the push: success = Changeset Bump Policy, Changeset Claim Re-read, Changeset Declaration, Changeset Fixed Group Check, Changeset Overwrite Report, Governed Surface Queue Guard, Line Citation Gate, Live E2E (informational), label. In progress = Build & E2E, Build Docs, Bundle Analysis, Lint, Repo Gates, Test (dist pins), Test shards 1 through 16, Type Check. Skipped = coverage and dependabot. No failure. On be01ada, whose code tree is identical, the last read 2026-10-25T03:42Z had Build & E2E, Build Docs, Bundle Analysis, Lint, Repo Gates, Test (dist pins) and Test shards 5, 9, 13 and 14 success, Type Check and the other twelve shards in progress, no failure. Type Check is the gate that proves the never arm and the @ts-expect-error pin compile against the rebuilt @object-ui/types, and it had not completed on either head at the last read; the seat re-reads CI on 504c0ee before landing, and an in-progress check does not by itself make this verdict FAIL.

Implemented-by: claude/issue-13450-retire-widget-module-source
Reviewed-by: session_01432GBvPzfZ6CsLanp9xzkZ

Self-review by session: the implementer was a subagent of this same session; this review was rendered in an isolated context from the card, the PR, the diff and the check-runs alone, not from the dispatch order or the seat's conclusions.

VERDICT: PASS


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 85 chunks) 3033.6 KB 3496.0 KB
Main entry chunk (gzip) 80.3 KB 350 KB
Entry file index-Qd0jsqJ0.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 (buildIdentity.js) 0.80KB 0.49KB
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 21.41KB 7.90KB
app-shell (runtime-config.js) 24.52KB 8.48KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 45.59KB 12.03KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 20.67KB 6.12KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.74KB 3.94KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.62KB 0.83KB
auth (authStyles.js) 5.27KB 1.86KB
auth (createAuthClient.js) 42.84KB 11.66KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 8.84KB 3.61KB
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.26KB 8.03KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (commentAuthorship.js) 1.39KB 0.78KB
collaboration (index.js) 1.93KB 0.85KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 614.94KB 150.52KB
core (index.js) 10.51KB 4.16KB
create-plugin (index.js) 27.92KB 9.50KB
data-objectstack (index.js) 253.04KB 70.68KB
fields (index.js) 295.90KB 75.88KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 41.17KB 11.96KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 15.35KB 5.51KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
permissions (ServerReadScope.js) 4.03KB 1.82KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.99KB 0.43KB
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.91KB
plugin-calendar (index.js) 55.31KB 16.16KB
plugin-charts (index.js) 88.30KB 24.33KB
plugin-chatbot (core.js) 5.22KB 2.18KB
plugin-chatbot (index.js) 237.93KB 56.26KB
plugin-dashboard (index.js) 147.15KB 39.95KB
plugin-designer (index.js) 232.83KB 50.01KB
plugin-detail (index.js) 268.92KB 71.56KB
plugin-editor (index.js) 2.21KB 1.04KB
plugin-form (index.js) 185.46KB 48.48KB
plugin-gantt (index.js) 178.19KB 45.06KB
plugin-grid (index.js) 277.62KB 77.39KB
plugin-kanban (index.js) 64.27KB 19.81KB
plugin-list (index.js) 149.51KB 39.15KB
plugin-map (index.js) 27.54KB 9.10KB
plugin-markdown (index.js) 13.79KB 4.79KB
plugin-report (index.js) 46.42KB 13.06KB
plugin-timeline (index.js) 39.74KB 12.00KB
plugin-tree (index.js) 15.25KB 5.38KB
plugin-view (index.js) 93.37KB 24.00KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 129.13KB 42.23KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.71KB 2.11KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.81KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (product-blocks.js) 0.20KB 0.19KB
types (record-approval-decision.js) 0.20KB 0.20KB
types (record-components.js) 0.20KB 0.19KB
types (record-panels.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对

ACCEPT — domain:ui seat 1 · session_01432GBvPzfZ6CsLanp9xzkZ · 2026-10-25T04:02Z · head 504c0ee96646bfc99d689fb98296673ae41c06a3

  • Shape: draft PR into main. Line 1 is Fixes #13450; no closing keyword sits beside any other open card. Clause-②: no (narrowing) and Metadata-protocol: narrowed are line-initial in the body, in the changeset, and on the amended claim 6386913269. The title carries !. Not governed (check-governed-merges --pr: 0 of 6 paths). +194 −52, under 3000.
  • Contract review of record: PASS at CONTRACT_REVIEW_TIER on this head, comment 6393108041.
  • Gates: check-runs on this head, read 2026-10-25T04:02Z: 33 success and 3 skipped (coverage lanes and dependabot), 0 red. That includes Type Check (which proves the exhaustive never arm and the @ts-expect-error pin), Lint, Repo Gates (the doc-snippet step that was red on e15036c), all 16 test shards and Build & E2E.
  • Patch rounds: be01ada fixed the red Doc Snippet Type Check. The cause was TS2307 on an unresolvable relative import in the rewritten @example blocks, not the undeclared name the seat guessed; the before/after exits were 1 → 0. 504c0ee added the (narrowing) arm, and it changes one changeset line.
  • Prose read sentence by sentence against the diff: the changeset's BREAKING line; the paragraph on the Function-constructor import and commandment Fix documentation deployment for www.objectui.org #6; the refusal paragraph ("rejected before anything is fetched", widget:error, loadAll() reports it, unknown types list the supported ones — WidgetRegistry.ts default: arm); the FROM → TO migration (both routes); and the one-line fix. All true to the code. The PR body's @example sentence was corrected by the seat to match be01ada.
  • Deviations accepted: H2 was falsified at source. The card's "four emitting sites" in cli / create-plugin are package.json ESM markers (type: 'module'), not widget sources, so those packages are untouched and carry no changeset. The fixed group bumps them anyway, and the review's ② judges this right. Also accepted: the barrel line and one test title beyond the claimed surface (required by the removal), and origin/main not merged (no conflict; CI builds the merge ref).
  • Out of scope: register() stores a retired or unknown source until load() refuses it. That is the ruling's own shape and how a missing registryKey has always been treated → Acceptance notes. A nit from the review (widget.ts comments still say "load the widget's code at runtime") → Acceptance notes, not filed. Nothing filed.
  • Landing: pr_ready + automerge_enable through the relay. Then follow to MERGED; the card closes through Fixes.

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 25, 2026 04:03
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 25, 2026 04:03
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 25, 2026
Merged via the queue into main with commit 899f381 Oct 25, 2026
37 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-13450-retire-widget-module-source branch October 25, 2026 04:17
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

2 participants