Skip to content

fix(plugin-view): forward the canonical table.columns on the non-grid paths - #5319

Merged
os-support-ai merged 2 commits into
mainfrom
claude/issue-5269-objectview-table-columns-forwarding
Aug 19, 2026
Merged

fix(plugin-view): forward the canonical table.columns on the non-grid paths#5319
os-support-ai merged 2 commits into
mainfrom
claude/issue-5269-objectview-table-columns-forwarding

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes#5269

ObjectViewSchema.table is Partial< Omit< ObjectGridSchema, 'type' | 'objectName' > >, where columns is the canonical spelling and fields carries @deprecated Use columns instead. ObjectView does not spread table; it forwards a hand-written whitelist, and that whitelist had exactly one read of table.columns in the file — the grid one. The other two field-list read points took the deprecated key alone, so table: { columns: [...] } — the shape the type recommends — produced an empty field list off the grid path from a schema that compiled and read correctly. Same silent-success shape as #5102, different mechanism: not a whitelist that knows only legacy spellings, but one that disagreed with itself between two rendering paths.

Both sites now read the canonical key first and keep the deprecated one as a working alias, the shape #5102 settled for its four pairs. Precedence is unchanged: a named view's columns, then the active view's, then the table segment. schema.table?.columns also joins the generateViewSchema dependency list alongside the new read.

Re-derived against current origin/main (3fbbea1f3), because the card is stale

The region was reworked twice today (#5102, then #5270 / PR #5294). Card vs. tree, measured:

the card sayson 3fbbea1f3
:842basePropsstill :842, and still table?.fields only — confirmed
:1056 / :1057 gridmoved to :1085 / :1086, unchanged in substance
:1247 delegatedmoved to :1284, still table?.fields only — confirmed
three read pointsfour — the useCallback dependency list at :1021 reads schema.table?.fields too, and a memo that reads a key without depending on it keeps serving a field list the author has already replaced

The defect stands. Its reach does not, in either direction — the affected surfaces were measured rather than taken from the card:

  • kanban — real. baseProps.fields becomes cardFields, which ObjectKanban reads.
  • tree — real, and not named on the card. ObjectTree reads schema.fields, fed from the same baseProps.
  • delegated renderListView — real. ListView reads schema.columns as its whole column set.
  • gallery / calendar — named on the card, but not reachable this way, and the same holds for timeline / gantt / map. None of those five reads a field list off its schema at all: every .fields in them is objectDef.fields (object metadata) or gallery's schema.grouping.fields. The forwarded value is inert there, before this change and after it. No ceremonial tests were added for them; the measurement is recorded in the test file header instead. (Each zero was counter-probed with .titleField in the same file — the first counter-probe caught a regex of mine that read zero on ObjectCalendar for the wrong reason.)

One shape question the fix raised, answered at the boundary

table.columns is string[] | ListColumn[], and the two slots disagree about which half they can hold:

  • the delegated list-viewcolumns slot declares the same union and ListView reads both, so it takes the value raw — flattening there would throw away the label / width the author wrote;
  • the non-grid baseProps slot is a names slot: both segments ahead of table declare string[], and ObjectKanban indexes the record by each entry (resolveKanbanCardFields casts straight to string[]).

Raw forwarding into the second one would have handed kanban a non-empty card field list naming nothing — which renders emptier than the bug being fixed, because a non-empty list suppresses ObjectKanban's highlightFields fallback. That is #5270's failure again (a value in a slot whose declared shape it lacks), so it is answered the same way: columnIdentity from @object-ui/core, the repo's converged identity reader (#3104) and the very fold ObjectGrid applies to this same value when deriving $select. One authored table.columns now resolves identically on both paths. It returns undefined, never [], when nothing resolves — a truthy empty array would stop the || chain short of table.fields.

No new spelling becomes acceptable: the accepted set is what columnIdentity already accepts everywhere else in the repo, and the canonical key being honoured here was already declared.

Verification

Run from the repository root (plugin-view owns a standalone vitest.config.ts, so the invocation guard does not cover a package-cwd run here).

No build artifact sits between the edit and the thing under test: the suite imports the subject as ../ObjectView (source), and the root Vitest config aliases every @object-ui/* specifier — @object-ui/core, where columnIdentity comes from — to packages/*/src. The dist/ built for type-check is not on the test's resolution path.

Reverse-verification (fix reverted with the tests kept, prediction written before the run): predicted 7 red and 7 green-on-both-legs; observed exactly that, with the predicted values.

Red, all seven pinning the defect: kanban forwards table.columns as the kanban card fields ([]), kanban prefers the canonical … over the deprecated (['owner']), kanban resolves the ListColumn[] form … to field NAMES ([]), tree forwards table.columns as the tree view fields (undefined), delegated hands over a canonical table.columns (undefined), delegated hands over the ListColumn[] form … unchanged (undefined), delegated prefers the canonical … over the deprecated (['owner']).

Green on both legs, so stated rather than counted — they pin the halves that must not change, not the defect: the three still forwards the deprecated table.fields aliases (kanban / tree / delegated), the two keeps a named view outranking the table segment precedence tests, the grid-path control, and falls through to table.fields when no column entry names a field (green before for a different reason — the canonical key was ignored entirely).

Generated by Claude Code


Generated by Claude Code

…id paths (#5269)
`ObjectViewSchema.table` inherits from `ObjectGridSchema`, where `columns` is
canonical and `fields` is `@deprecated Use columns instead`. Only one of the
file's three field-list read points consulted `table.columns` — the grid one.
`generateViewSchema`'s shared `baseProps` and the delegated `renderListView`
schema read `table.fields` alone, so `table: { columns: [...] }` produced an
empty field list off the grid path from a schema that compiled and read
correctly.
Both sites now read the canonical key first, keeping the deprecated one as a
working alias (the shape objectui#5102 settled for its four pairs). Forwarding,
not translation; precedence unchanged. `schema.table?.columns` joins the
`generateViewSchema` dependency list alongside the read.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RV6yuVCxymHYE16PL9vQkE
…e non-grid slot (#5269)
The non-grid `baseProps` slot is a names slot — both segments ahead of the
`table` one declare `string[]`, and `ObjectKanban` indexes the record by each
entry — while `table.columns` is `string[] | ListColumn[]`. Forwarding the
object form raw would have handed kanban a non-empty card field list naming
nothing, which renders emptier than the bug this card fixes: a non-empty list
suppresses ObjectKanban's `highlightFields` fallback. Same failure mode as
objectui#5270 (a value in a slot whose declared shape it lacks), answered the
same way, at the boundary.
`columnIdentity` (@object-ui/core) is the fold ObjectGrid already applies to
this very value on the grid path, so the two paths now resolve one authored
`table.columns` identically. `undefined`, never `[]`, when nothing resolves —
otherwise a truthy empty array would stop the `||` chain short of the
deprecated `table.fields`. The delegated `list-view` slot declares the same
union and keeps taking the value raw.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RV6yuVCxymHYE16PL9vQkE
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)25.3 KB350 KB
Entry fileindex-BtWutwIL.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.83KB3.70KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)29.33KB7.05KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.79KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.71KB1.22KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)506.81KB113.40KB
core (index.js)4.11KB1.62KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)159.80KB44.34KB
fields (index.js)237.07KB59.46KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.42KB1.39KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)29.43KB7.15KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)39.16KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.35KB3.31KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.42KB1.42KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.81KB0.83KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.75KB18.37KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)127.92KB32.80KB
plugin-designer (index.js)212.39KB42.83KB
plugin-detail (index.js)241.46KB60.56KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)124.19KB30.20KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)198.22KB53.28KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.66KB27.13KB
plugin-map (index.js)20.08KB6.62KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.49KB11.93KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.55KB20.67KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)36.10KB12.26KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (index.js)4.77KB2.16KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)10.76KB3.17KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)6.92KB2.40KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.08KB1.53KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@os-support-ai
os-support-ai marked this pull request as ready for review August 19, 2026 14:34
@os-support-ai
os-support-ai added this pull request to the merge queueAug 19, 2026
Merged via the queue into main with commit 2426608Aug 19, 2026
22 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-5269-objectview-table-columns-forwarding branch August 19, 2026 14:35
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants

@os-support-ai@claude