Skip to content

fix(react,core): declare the spec dataSource binding at the gate-wrapping seam - #6767

Merged
os-sales merged 9 commits into
mainfrom
claude/issue-6678-datasource-input-declaration-injection
Aug 29, 2026
Merged

fix(react,core): declare the spec dataSource binding at the gate-wrapping seam#6767
os-sales merged 9 commits into
mainfrom
claude/issue-6678-datasource-input-declaration-injection

Conversation

@os-sales

@os-sales os-sales commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

Fixes #6678

The spec's dataSource element binding is now declared by the blocks that read
it
, emitted from one seam, so the html tier stops reporting the one working
saved-view spelling as unknown-prop.

Reproduced first, on the base commit

Base e321d5234, through the live path (registry-built manifest, the real
page.tsx html-kind construction, SchemaRenderer, the real list-view
registration and the real object-grid):

AssertionError: expected [ Array(1) ] to deeply equal []
+   "list-view has no prop \"dataSource\"",

(the real diagnostic wraps the tag name in angle brackets; they are dropped here
because this body is sanitized)

...while the same page's saved view resolved its columns and the assertion on
those columns passed. The working spelling and the two non-working ones
(viewName, view) were reported identically, and the tier's only signal
pointed away from the one that works.

What landed — option B in the injection form (ruling, 2026-08-29)

piece where
the single declaration ELEMENT_DATA_SOURCE_INPUT in @object-ui/core, beside the binding's own semantics
the seam elementDataSourceBlock() in @object-ui/core, re-exported by @object-ui/react next to ElementDataSourceGate
the emission Registry.registerwithElementDataSourceInput
the drift-catcher check:element-data-source-declaration

No block hand-writes the declaration. Seventeen renderers, in thirteen files
across twelve packages
, reach the seam; the key then flows to
sdui.manifest.json, the JSX authoring types (sdui-intrinsics.d.ts) and
sdui-blocks.md through the generators the repo already publishes with.

packages/sdui-parser/src/validate.ts is untouched — BASE_PROPS mirrors
BaseSchema, and silencing the key there would make the diagnostic lie in the
other direction.

Two things the work found that the card did not have

1. The population is seventeen renderers in twelve packages, not nine blocks.
The card named nine; the tree also has plugin-grid, plugin-timeline, two
further plugin-form blocks and element:record_picker. Nothing was
hand-listed, so the mechanism simply covered them.

element:record_picker was found by the render probe, not by reading sources: it
consumes the gate's hook and status panels without the ElementDataSourceGate
tag, because its object lives under properties. A check that only knew the tag
would have called that file compliant while it published exactly this defect. The
gate's rule was widened to the family the probe actually sees, with comments
masked via scripts/js-comment-mask.mjs.

2. The spec/registry parity gate had something to say — and it was measurably
wrong, so it was corrected rather than exempted.
The card predicted this. Five
blocks went red on declares no top-level input the spec does not accept.

Measured against the pinned spec:

PageComponentSchema.safeParse({ type: 'list-view', dataSource: {...} })
  -> success, and `dataSource` is KEPT
ComponentPropsMap['object-grid']  -> dataSource: false   (37 keys)

dataSource is a node-level spec key, a sibling of type and className.
ComponentPropsMap[type] is only the per-block props half of a node's
contract, and the gate treated that half as the whole thing — an assumption that
held only while no node-level key was declared per block. The forward direction's
accepted set now also reads PageComponentSchema's own keys, derived from the
spec, not listed
, and it still discriminates: dataSource and className are
accepted, objectName, viewName and an invented key are not. That calibration
is asserted in the same file. No exemption entry was added. The same widening was
carried to the record:related_list per-block pin.

⚠️ For the maintainer: the framework's own check:react-blocks-declaration-parity
in objectstack reads the same two declarations and will have the same false
complaint about these blocks. It cannot be fixed from this repo. Reported as an
open question rather than worked around.

Acceptance — both directions

pin result
gate-wrapped block: no diagnostic green
gate-wrapped block: saved view still resolves its columns (Opportunity Name, Amount, not Stage) green
non-wrapped flex / card: unknown-prop still fires green
viewName / view still reported green
codegen + manifest + block list carry the input green
every gate-rendering registration declares it, in any package green

Ablation — discriminating, against the committed implementation

Injection disabled at Registry.register on commit 6aa8de55a; mutation proven
on disk by counting both the removed and the injected text (1→0 and 1), not by an
editor exit code. No rebuild leg: the root vitest config aliases every
@object-ui/* specifier to packages/*/src, so the mutated source is what ran —
and the run did change, which is the assertion that would have caught a stale
build.

7 red — the diagnostic pin, the cross-package mechanism pin, its
anti-vacuity floor, and all three consumer-reach pins.

5 green, and the right fiveflex and card still report; the two
non-working spellings still report; the block-does-not-declare-it control holds;
and the saved view still resolves, because this is a declaration change and not a
resolution change.

Restore proven: git diff HEAD empty and the restored blob hash equal to the
path's HEAD blob (4749cfc1a374049d24d43e48c1028cb2e5bf9eb1). Restored run:
12 passed (12).

Verification

The union in the table below was run on d3c62e07e; the reproduction was on the
base e321d5234 and the ablation on 6aa8de55a. Exit codes captured by
redirect-then-capture, never after a pipe.

what command result
the two new pin files + 73 derived readers vitest run over the derived list Test Files 75 passed (75) / Tests 1064 passed (1064), EXIT=0
types, affected packages pnpm run --filter core/react/components/plugin-*/console type-check EXIT=0
the new drift gate check:element-data-source-declaration OK — 13 gate-consuming file(s) checked, 3 definition file(s) excluded
spec/registry parity, repo-wide + per-block registry-inputs-spec-parity + recordRelatedListInputs.spec-parity + record-picker-inputs-spec-parity Test Files 3 passed (3) / Tests 127 passed (127)
check:control-bytes / changeset-presence / changeset-fixed / changeset-no-major / changeset-overwrite / side-effects-array / readme-exports / esm-specifiers / vi-mock-specifiers / phantom-deps / self-import / lint-coverage / type-check-coverage / doc-fences / doc-types / doc-snippets each run directly all EXIT=0

Declared narrowings

Two, both stated so a reader can tell a measurement from a gap.

Tests. The suite is the derived population rather than every package: the
files that read a registration's inputs / getMeta / getConfig /
manifestFromConfigs, taken by git grep, plus every *.elementDataSource and
registration test of the blocks whose renderers were wrapped, plus the gate's
own suite — 75 files. CI runs the whole farm regardless, and it found something
this narrowing could not
— see the CI section below, which is the honest cost of
the narrowing and is recorded rather than smoothed over.

ESLint. Ran over the 29 changed files (--format json, 0 errors, 325
warnings — this repo sets no --max-warnings and fails only on errors). The
narrowing is sound because eslint.config.js enables no type-aware linting (no
parserOptions.project, no projectService) and is not modified here, so a
file's verdict depends only on its own contents.


CI was red on all four shards — diagnosed, reproduced and fixed

The failure was this PR's. It was not an appended-input assertion break and
not a resolution failure; Type Check, Build & E2E and Lint were all green,
which is exactly right, because the fault was visible only to vitest.

Reproduced locally with the same partition CI uses, pnpm test --shard=2/4
on the red head fce8b57ca:

shard 2/4 EXIT=1
Test Files  3 failed | 546 passed (549)
Tests  6694 passed (6694)

Tests 6694 passed (6694) is the whole diagnosis: zero failed assertions.
The three files failed at COLLECTION:

Error: [vitest] No "elementDataSourceBlock" export is defined on the
"@object-ui/react" mock. Did you forget to return it from "vi.mock"?
  packages/components/src/renderers/basic/record-picker.tsx:312

Root cause

A registration runs at module scope, and 101 suites in this repo partially
mock @object-ui/react
by hand-listing the exports they return. A module-scope
read of a name absent from such a list throws while the file is being collected,
so the file dies before running one assertion.

Blast radius, measured over every suite that mocks the package without
importOriginal (36 candidates): 17 files. That is why all four shards were
red rather than a subset — and why there were no failed assertions anywhere.

The fix, and why it is not "add the export to 17 mocks"

Patching 17 fixtures would leave the hazard standing for the next module-scope
addition. The mocks were only incomplete because this PR made widely-imported
packages reach into a commonly-mocked one at module scope. So the seam moved to
the package nothing mocks:

  • @object-ui/core owns the one function under the one name (renamed from
    markElementDataSourceBlock). @object-ui/react re-exports it beside the
    gate for discoverability rather than wrapping it — still exactly one
    implementation, one name.
  • All 17 call sites import it from @object-ui/core. Every one already imported
    ComponentRegistry from there at module scope, so this removes a
    module-scope dependency rather than adding one.
  • check:element-data-source-declaration now enforces the import source, so this
    cannot recur. The new rule was proven able to fail: one file flipped back to
    the react import gave exit 1 naming that file; restored, and the restore proven
    by blob hash.

⛔ No test was skipped, quarantined, disabled or edited to get green. The 17 files
were never wrong — they could not load.

After the fix

what result
pnpm test --shard=2/4 — the partition that was red — on d019ee61a EXIT=0, Test Files 549 passed (549) / Tests 6727 passed (6727), seam-mock errors 0
the 36 mock candidates Test Files 36 passed (36) / Tests 330 passed (330), EXIT=0
the 75-file derived suite, on the pushed head 4f0bb02a2 Test Files 75 passed (75) / Tests 1064 passed (1064), EXIT=0
remaining elementDataSourceBlock mock errors 0
type-check, affected packages EXIT=0
check:element-data-source-declaration OK — 13 gate-consuming files, all reach the seam and take it from core
side-effects-array / control-bytes / phantom-deps / self-import / vi-mock-specifiers / esm-specifiers / changeset-presence / doc-fences / doc-types / readme-exports all EXIT=0

The test count RISING from 6694 to 6727 across the same 549 files is the
confirmation that matters: those 33 tests are the ones the three uncollectable
files could never run.

One honest note on shas: the shard reading was taken on d019ee61a. The three
commits after it change a changeset .md, comment lines in two source files
(proven comment-only — every changed line in that diff begins with *, /* or
//), and two stale failure-message strings that told the reader to import the
seam from the wrong package. The 75-file derived suite and every gate above were
re-run on the pushed head 4f0bb02a2 and are green there.

claude added 3 commits August 29, 2026 07:22
…apping seam

`PageComponentSchema.dataSource` is the one spelling that resolves a saved view
for an object-bound block. It works, and the html tier reported it with the same
`unknown-prop` warning it gives the spellings that do nothing (`viewName`,
`view`) — because `validateTree` looks a prop up in the block's declared
`inputs` and no registration declared this key. On the tier built to accept
AI-authored pages, where the diagnostic IS the contract, the only signal pointed
away from the key that works.

Adopting the maintainer ruling of 2026-08-29 — option B in the INJECTION form:

- `ELEMENT_DATA_SOURCE_INPUT` is the single declaration, in `@object-ui/core`
  beside the binding's semantics. `Registry.register` emits it for a
  registration whose renderer passed through `elementDataSourceBlock()`, the new
  seam exported from `@object-ui/react` next to `ElementDataSourceGate`. One
  mechanism, one copy — not a hand-written declaration per block.
- Thirteen renderers across eleven packages reach the seam.
- `dataSource` on a block that does NOT read it (`flex`, `card`) still reports
  `unknown-prop`; `BASE_PROPS` is untouched.
- New `check:element-data-source-declaration` fails any source that consumes the
  gate without reaching the seam, so a new block cannot forget.
- The forward spec/registry parity derivation now reads the whole node contract
  (`PageComponentSchema`, derived — not a listed exemption), because
  `ComponentPropsMap[type]` is only the per-block PROPS half and `dataSource` is
  a node-level spec key.

Part of #6678

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CRJge11jso9TpXRWFt1Z49
…ock pin, document the seam

Two follow-ons to the injection landing in the previous commit.

`recordRelatedListInputs.spec-parity.test.ts` is the per-block half of the same
forward-direction gate the repo-wide file carries, and it made the same
assumption: that `RecordRelatedListProps` — the block's PROPS contract — is the
whole contract of the node an `inputs` list describes. It is not.
`PageComponentSchema` carries its own top-level keys, and the html tier validates
an author's attributes against `BASE_PROPS` + `inputs`, with no third place for a
node-level key to live. Widened the same way: DERIVED from the spec, never
listed, and asserted to still discriminate (`dataSource` accepted,
`relationshipField` and an invented key refused).

`packages/react/README.md`'s worked example is what a new block author copies,
and it showed the wrapper without the seam — so it taught exactly the omission
`check:element-data-source-declaration` now fails the build for. The example
wraps the renderer, and the surrounding prose says what the seam is for and that
the hook/panel form (a renderer whose hooks must run before the panels) owes it
at its registration instead.

Part of #6678

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

Seventeen renderers in thirteen files across twelve packages, not thirteen across
eleven — counted from `check:element-data-source-declaration --list` rather than
from the card's nine. Also records that the two spec/registry parity gates were
corrected (derived from `PageComponentSchema`) rather than exempted.

Part of #6678

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 48 chunks) 3180.4 KB 3222.7 KB
Main entry chunk (gzip) 148.2 KB 350 KB
Entry file index-Dhws85rG.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) 11.89KB 4.50KB
app-shell (runtime-config.js) 20.61KB 7.35KB
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) 511.70KB 116.32KB
core (index.js) 5.30KB 2.13KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 173.10KB 47.96KB
fields (index.js) 240.41KB 60.56KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.44KB 1.39KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 33.40KB 8.71KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.95KB 10.97KB
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.55KB 0.62KB
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 (useResponsiveConfig.js) 1.37KB 0.63KB
mobile (useSpecGesture.js) 4.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 9.53KB 3.38KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 4.64KB 1.50KB
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) 1.93KB 0.88KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.92KB 12.93KB
plugin-charts (index.js) 64.69KB 18.34KB
plugin-chatbot (index.js) 190.33KB 45.10KB
plugin-dashboard (index.js) 133.49KB 34.50KB
plugin-designer (index.js) 212.87KB 43.19KB
plugin-detail (index.js) 245.46KB 62.46KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 133.03KB 32.65KB
plugin-gantt (index.js) 165.23KB 40.37KB
plugin-grid (index.js) 201.57KB 54.55KB
plugin-kanban (index.js) 53.14KB 14.64KB
plugin-list (index.js) 113.14KB 27.60KB
plugin-map (index.js) 20.20KB 6.67KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 43.51KB 11.94KB
plugin-timeline (index.js) 27.02KB 7.79KB
plugin-tree (index.js) 9.00KB 3.08KB
plugin-view (index.js) 85.87KB 21.12KB
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) 69.47KB 23.06KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 2.44KB 1.21KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 4.93KB 2.24KB
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) 10.35KB 3.60KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.74KB 1.41KB
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 (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.72KB 2.24KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
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 (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) 3.40KB 1.71KB
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

claude added 4 commits August 29, 2026 08:51
… from the mocked package

CI was red on all four shards. Reproduced locally with the same partition
(`pnpm test --shard=2/4`): three files failed, `Tests 6694 passed (6694)` — zero
failed assertions. They were COLLECTION failures:

  Error: [vitest] No "elementDataSourceBlock" export is defined on the
  "@object-ui/react" mock.

Cause, and it is this PR's: a registration runs at MODULE SCOPE, and 101 suites
in this repo partially mock `@object-ui/react` by hand-listing the exports they
return. A module-scope read of a name absent from such a list throws while the
test file is being collected, so the file dies before running one assertion.
Measured blast radius over every suite that mocks the package without
`importOriginal`: 17 files, which is why all four shards were red rather than a
subset — an appended input breaking exact-array assertions would have hit a
subset and produced failed ASSERTIONS, and there were none.

The fix is not to hand-list the export in 17 mocks. That leaves the hazard in
place for the next module-scope addition, and the mocks are only incomplete
because this PR made widely-imported packages reach into a commonly-mocked one at
module scope. So the seam moves to the package nothing mocks:

- `@object-ui/core` owns the one function under the one name (renamed from
  `markElementDataSourceBlock`); `@object-ui/react` re-exports it beside the gate
  for discoverability rather than wrapping it, so there is still exactly one
  implementation.
- All 17 call sites import it from `@object-ui/core`. Every one of them already
  imported `ComponentRegistry` from there at module scope, so this removes a
  module-scope dependency rather than adding one, and nothing in this repo mocks
  `@object-ui/core`.
- `check:element-data-source-declaration` now enforces the import source, so this
  cannot recur. The rule was proven able to fail (one file flipped back to the
  react import: exit 1, naming that file; restored and proven by blob hash).

No test was skipped, quarantined or edited to get green: the 17 files were never
wrong, they could not load.

Part of #6678

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CRJge11jso9TpXRWFt1Z49
Prose only, no code change: the seam lives in `@object-ui/core` and is
re-exported by `@object-ui/react` beside the gate, and call sites take the core
import because a registration runs at module scope while this repo's suites
partially mock `@object-ui/react`.

Part of #6678

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CRJge11jso9TpXRWFt1Z49
Comment-only (proven: every changed line in both files is a comment line). The
react-side re-export exists for discoverability; call sites import the seam from
`@object-ui/core`, and check:element-data-source-declaration enforces that — so
the docblocks should not read as a suggestion.

Part of #6678

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

Two diagnostics still told the reader to take the seam from `@object-ui/react` —
the console pin's assertion message and the gate script's own fix instruction.
Following either would reproduce the collection failure this PR just fixed, which
is the worst kind of stale message: it is read only by someone already stuck.

Part of #6678

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 48 chunks) 3180.6 KB 3222.7 KB
Main entry chunk (gzip) 148.2 KB 350 KB
Entry file index-EQTsU7c8.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) 11.89KB 4.50KB
app-shell (runtime-config.js) 20.61KB 7.35KB
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) 511.71KB 116.32KB
core (index.js) 5.30KB 2.13KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 173.10KB 47.96KB
fields (index.js) 240.93KB 60.76KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.44KB 1.39KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 33.40KB 8.71KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.95KB 10.97KB
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.55KB 0.62KB
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 (useResponsiveConfig.js) 1.37KB 0.63KB
mobile (useSpecGesture.js) 4.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 9.53KB 3.38KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 4.64KB 1.50KB
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) 1.93KB 0.88KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.92KB 12.93KB
plugin-charts (index.js) 64.68KB 18.35KB
plugin-chatbot (index.js) 190.33KB 45.10KB
plugin-dashboard (index.js) 133.48KB 34.51KB
plugin-designer (index.js) 212.87KB 43.19KB
plugin-detail (index.js) 245.46KB 62.46KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 133.03KB 32.64KB
plugin-gantt (index.js) 165.23KB 40.37KB
plugin-grid (index.js) 201.57KB 54.55KB
plugin-kanban (index.js) 53.14KB 14.64KB
plugin-list (index.js) 113.15KB 27.59KB
plugin-map (index.js) 20.20KB 6.66KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 43.51KB 11.94KB
plugin-timeline (index.js) 27.22KB 7.83KB
plugin-tree (index.js) 9.00KB 3.08KB
plugin-view (index.js) 85.87KB 21.12KB
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) 73.09KB 24.34KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 2.44KB 1.21KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 4.93KB 2.24KB
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) 10.35KB 3.60KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.74KB 1.41KB
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 (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.72KB 2.24KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
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 (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) 3.40KB 1.71KB
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

claude added 2 commits August 29, 2026 09:38
…-check row

`ci.yml`'s `type-check` job runs `pnpm check:element-data-source-declaration`
between `check:side-effects-array` and `check:esm-specifiers`, but the job
table's "What it runs" cell did not name it, so
`scripts/__tests__/ci-cd-pipeline-doc.test.ts` was red on this branch.

Add it to the cell in the order ci.yml runs it, with the one-sentence
explanation the page gives every other gate in that row.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CRJge11jso9TpXRWFt1Z49
…ssue-6678-datasource-input-declaration-injection
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 48 chunks) 3180.6 KB 3222.7 KB
Main entry chunk (gzip) 148.2 KB 350 KB
Entry file index-EQTsU7c8.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) 11.89KB 4.50KB
app-shell (runtime-config.js) 20.61KB 7.35KB
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) 511.71KB 116.32KB
core (index.js) 5.30KB 2.13KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 173.10KB 47.96KB
fields (index.js) 240.93KB 60.76KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.44KB 1.39KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 33.40KB 8.71KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.95KB 10.97KB
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.55KB 0.62KB
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 (useResponsiveConfig.js) 1.37KB 0.63KB
mobile (useSpecGesture.js) 4.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 9.53KB 3.38KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 4.64KB 1.50KB
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) 1.93KB 0.88KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.92KB 12.93KB
plugin-charts (index.js) 64.68KB 18.35KB
plugin-chatbot (index.js) 190.33KB 45.10KB
plugin-dashboard (index.js) 133.48KB 34.51KB
plugin-designer (index.js) 212.87KB 43.19KB
plugin-detail (index.js) 245.46KB 62.46KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 133.03KB 32.64KB
plugin-gantt (index.js) 165.23KB 40.37KB
plugin-grid (index.js) 201.57KB 54.55KB
plugin-kanban (index.js) 53.14KB 14.64KB
plugin-list (index.js) 113.15KB 27.59KB
plugin-map (index.js) 20.20KB 6.66KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 43.51KB 11.94KB
plugin-timeline (index.js) 27.22KB 7.83KB
plugin-tree (index.js) 9.00KB 3.08KB
plugin-view (index.js) 85.87KB 21.12KB
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) 73.09KB 24.34KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 2.44KB 1.21KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 4.93KB 2.24KB
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) 10.35KB 3.60KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.74KB 1.41KB
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 (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.72KB 2.24KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
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 (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) 3.40KB 1.71KB
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-sales
os-sales marked this pull request as ready for review August 29, 2026 09:57
@os-sales
os-sales added this pull request to the merge queue Aug 29, 2026
Merged via the queue into main with commit 3beef6d Aug 29, 2026
30 checks passed
@os-sales
os-sales deleted the claude/issue-6678-datasource-input-declaration-injection branch August 29, 2026 10:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants