Skip to content

test(app-shell): pin the already-honest studio-design consumers on an empty registry, plus the populated contrast - #8619

Merged
os-justin merged 1 commit into
mainfrom
claude/issue-6846-studio-design-empty-registry
Sep 8, 2026
Merged

test(app-shell): pin the already-honest studio-design consumers on an empty registry, plus the populated contrast#8619
os-justin merged 1 commit into
mainfrom
claude/issue-6846-studio-design-empty-registry

Conversation

@os-justin

Copy link
Copy Markdown
Collaborator

Fixes #6846

Premise check — the three repairs are already on main

objectui#6846 asks for three repairs plus pins. Re-driving the probes against origin/main (BASE 0544ae958) shows the three repairs landed on 2026-09-01 in #7120 (the part-C PR of objectui#6795, commit 994b73696), each with its own empty-registry pin — and that PR never referenced this card, which is why the card stayed open. This PR is the surviving half, the one the card calls "the cheap half and where this card's durability lives": pins for the two consumers #7120 measured as already honest and deliberately left unpinned, plus the populated-registry contrast.

Every row of the card's table, re-driven on this tree with the registries proven empty first (listMetadataPreviewTypes() and listMetadataInspectorTypes() both []; getMetadataDefaultInspector for object, hook, action all undefined; control getStudioCanvasPreview('object') defined):

consumer measured on origin/main today card's row
ObjectSettingsPanel prints "No default object inspector registered." once, in Basics; the sharing / roles / capabilities sections still render correct — unpinned until this PR
ObjectHooksPanel generic SchemaForm with one control per hook key (Name, Label, Object, Events, Handler); an edit enables Save and client.save receives it correct — unpinned until this PR
ObjectActionsPanel the label plus "No action editor is registered in this session, so this action's properties cannot be edited here." stale — repaired and pinned in #7120
Interfaces canvas "No metadata designers are registered in this session, so page cannot be previewed or designed here."; the "design support is in progress" sentence is gone stale — repaired and pinned in #7120
Data pillar field click the aside opens with "Field properties" and "No field inspector is registered in this session, so this field's properties cannot be edited here." stale — repaired and pinned in #7120

(#7120 also found and repaired a fourth site the card did not list: the Automations pillar's two "click a node" instructions.)

What this PR adds

Three test files and one empty-frontmatter changeset. No source module changes.

  • ObjectSettingsPanel.designerRegistryMissing.test.tsx — empty registry (asserted first, with the control): the message appears exactly once (queryAllByText, since getByText throws on duplicates too), inside the Basics section, and the OWD section still renders; no recovery prose.
  • ObjectHooksPanel.designerRegistryMissing.test.tsx — empty registry: the generic form's Handler and Name controls carry the hook's values, the curated editor's hook-name test id is absent, and the form WORKS — editing Handler enables Save, and client.save('hook', 'guard_hook', …handler: 'guard_fn_v2'…, { mode: 'draft', packageId }) is observed.
  • DataPillar.designerRegistryPopulated.test.tsx — the non-regression axis for the plausible wrong fix on this card (an empty-state branch that fires whenever the lookup is falsy and swallows the populated path): with registerBuiltinInspectors() proven present, a field click opens the real ObjectFieldInspector (API-name control with value title), Actions mounts ActionDefaultInspector (Name control send_email), Hooks mounts the curated HookDefaultInspector (hook-name, hook-body-source; no synthesised Handler), Settings mounts ObjectDefaultInspector (object-name-input, object-access-posture) — and none of the four empty-state sentences appears. Each case asserts a real-editor control BEFORE the absence, so a blank screen reds on the positive. The Interfaces canvas already has its populated contrast in StudioDesignSurface.designerRegistryPartial.test.tsx.

Verification (all on HEAD 6453586e6)

  • pnpm exec vitest run packages/app-shell/src/views/studio-design/ (repo root): Test Files 57 passed (57), Tests 323 passed (323); JSON reporter: 0 failed suites, 0 non-passed assertions; 0 harness-death strings (Element type is invalid, No test suite found, Failed Suites). Narrowing declared: the diff vs BASE is three test files plus the changeset — no source module changed, so no test outside this directory can change outcome (the dom projects run with isolate: true).
  • pnpm --filter @object-ui/app-shell type-check (tsc --noEmit && tsc -p tsconfig.test.json): exit 0, 0 error TS, after building the 28-package dependency closure (turbo run build --filter='@object-ui/app-shell^...', 28 successful). The first attempt on the unbuilt worktree failed with Cannot find module '@object-ui/fields' — a precondition, not a reading. tsc -p tsconfig.test.json --listFiles lists all three new files.
  • pnpm --filter @object-ui/app-shell lint (eslint ., the same run CI's turbo run lint performs for this package): exit 0; --format json 1113 files, 0 errors, 2925 warnings — all pre-existing; the three new files contribute 0 warnings (the DropdownMenu passthroughs are typed, not any).
  • Gates, each printing its own green verdict line: check-changeset-presence (3 published source files, 1 changeset with EMPTY frontmatter — the explicit exemption), check-changeset-no-major, check:control-bytes, check:vi-mock-specifiers, check:vi-mock-inherit, check:unreferenced-sources, check:comment-mask-corpus, check:shell-escape-residue.

Red legs — every new pin observed to fail

Mutations were proven on disk by grep -c before each run; restore is git checkout HEAD -- ABS_PATH, proven by all four blob hashes equalling HEAD and an empty git diff HEAD (trap on EXIT/INT/TERM). No dist is on the path: the tests import the panels by relative path and workspace packages map to src through the root vitest alias, so there is no build leg to an ablation here.

  • Leg A (the silent class — the honest branches render nothing): Settings expected [] to have a length of 1 but got +0; Hooks Unable to find a label with the text of: Handler. 2 of 2 red.
  • Leg B (the caricature — every consumer answers one constant empty-state string regardless of registry or selection): all 4 populated pins red (Unable to find an element with the display value: title / send_email; hook-name; object-name-input), both new empty pins red (whole-panel constant: Basics / Guard not found), both designerRegistryPartial pins red. The fix(app-shell): say what is true when the studio-design designer registries are empty (#6795 part C) #7120 pins that assert the empty-state message itself stay green under this caricature — which is exactly the gap the populated file fills.

Notes for the reviewer

🤖 Generated with Claude Code

https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S


Generated by Claude Code

…n an empty registry, and the populated contrast

The three repairs objectui#6846 asks for — the Data pillar field rail that
swallowed a field click, the actions pane that rendered a bare label, and the
Interfaces canvas that blamed the roadmap — already landed on main in #7120
(#6795 part C), each with its own empty-registry pin. What #7120 deliberately
left unpinned are the two consumers its measurement found already honest:

- ObjectSettingsPanel prints "No default object inspector registered." in the
  Basics section and keeps rendering the sections that do not read the
  registry;
- ObjectHooksPanel falls back to the generic SchemaForm, and that form edits
  and saves the hook.

Both are pinned here with the same shape as the sibling pins: the registries
are asserted empty FIRST, with a control that must hit, and the assertion
names the specific visible controls rather than "something rendered".

The populated contrast pins the wrong fix on this axis — an empty-state
branch that fires whenever the lookup is falsy and swallows the populated
path: with the builtin inspectors registered, a field click opens the real
ObjectFieldInspector, Actions mounts the real ActionDefaultInspector, Hooks
mounts the curated HookDefaultInspector (not the generic form), Settings
mounts the real ObjectDefaultInspector, and none of the empty-state sentences
appears. Test only; the changeset declares no release.

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

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3477.0 KB 3512.7 KB
Main entry chunk (gzip) 143.9 KB 350 KB
Entry file index-BHWKPEWX.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) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 498.93KB 114.12KB
core (index.js) 7.48KB 2.96KB
create-plugin (index.js) 10.12KB 3.28KB
data-objectstack (index.js) 196.02KB 54.44KB
fields (index.js) 243.74KB 61.55KB
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) 49.00KB 13.91KB
plugin-charts (index.js) 71.39KB 19.92KB
plugin-chatbot (index.js) 194.53KB 46.34KB
plugin-dashboard (index.js) 131.43KB 34.44KB
plugin-designer (index.js) 213.21KB 43.63KB
plugin-detail (index.js) 250.75KB 64.81KB
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.30KB 56.63KB
plugin-kanban (index.js) 55.44KB 15.73KB
plugin-list (index.js) 112.74KB 27.70KB
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.54KB 20.84KB
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-justin
os-justin marked this pull request as ready for review September 8, 2026 17:10
@os-justin
os-justin enabled auto-merge September 8, 2026 17:11
@os-justin
os-justin added this pull request to the merge queue Sep 8, 2026
Merged via the queue into main with commit 86ef0c7 Sep 8, 2026
35 checks passed
@os-justin
os-justin deleted the claude/issue-6846-studio-design-empty-registry branch September 8, 2026 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

finding(app-shell): four studio-design consumers on an empty metadata registry — one renders NOTHING on a field click, one states a false reason

2 participants