Skip to content

test(plugin-detail): gate RelatedList's client-mode sort-button case on the object schema (objectui#10895) - #10923

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-10895-relatedlist-client-sort-gate
Sep 28, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-10895-relatedlist-client-sort-gate

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #10895
Clause-②: no

Test-only. Branch claude/issue-10895-relatedlist-client-sort-gate, base objectui origin/main 733fd5ac6, head 3abab7ce5. Implemented for the PM claim 5865039628 in session https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN.

What changed

  • packages/plugin-detail/src/__tests__/RelatedList.unmaterializedSort.test.tsx, case "keeps that button in client mode": renderList(…) now returns into const dataSource, and after the existing data-list waitFor the case awaits settleObjectSchema(dataSource), with the one-line reason: since objectui#10728 the sort-button row reads the masked stamp, which covers every column until the object schema lands (finding(plugin-detail): RelatedList.unmaterializedSort.test.tsx:153 rides a SECOND, ungated settle — its gate covers a different promise chain, and it is green only by effect-declaration order #7007). The existing data-list gate is kept, as the file's docblock asks (the two gates prove different facts).
  • .changeset/10895-plugin-detail-relatedlist-client-sort-gate.md: empty frontmatter, releasing nothing. check-changeset-presence asked for it: it counts a test file under a released package's src/ (verdict quoted under Gates).
  • No source change, no retry, no raised timeout, no waitFor around the assertion.

Mechanism, confirmed on this base. The sort-button row skips every field that is not in unmaskedColumnKeys. While objectTypesPending holds (an api, a getObjectSchema, and no fields in hand), tableColumns stamps every column masked, so the key list is empty. In client mode (data passed) the rows and the data-list view exist on the first commit, before getObjectSchema resolves. So the case's only gate passed while the Total button could still be absent. On the auto-fetch path this window does not exist: the row fetch waits on the settled schema (objectui#10690), and the view mounts only after the rows land.

Census

Every plugin-detail test that reaches RelatedList was read: 51 files name it, plus DetailView.test.tsx (retired related: entry, empty rows). unmaskedColumnKeys and objectTypesPending live in RelatedList.tsx only, within this package. Only a render that passes data together with an api and a data source carrying getObjectSchema has a window where the stamp still covers every column after the rows are in hand.

File Case(s) Mode Verdict Reason
RelatedList.unmaterializedSort "keeps that button in client mode" client (data + api + getObjectSchema) needs the gate: gated here sort-button presence reads unmaskedColumnKeys; the only gate was the view type
RelatedList.unmaterializedSort "offers no button for a formula field while windowed"; "withholds the header from a formula column while windowed" windowed gated already settleObjectSchema, and the row fetch waits on the settled schema
RelatedList.unmaterializedSort "leaves every stored column sortable — including the autonumber" windowed gated already (fetch chain) the table mounts only after the rows, which wait on the settled schema
RelatedList.unmaterializedSort "keeps the formula header live in client mode" client not schema-dependent reads the column sortable flag; client mode never withholds it and the masked stamp does not touch it
RelatedList.headerSort "keeps the button row for a list related list, which has no headers" client, no api not schema-dependent with no api nothing is read, so objectTypesPending is false from the first render
RelatedList.headerSort "keeps a relational header live in client mode" client, no api not schema-dependent reads sortable
RelatedList.headerSort the six windowed cases, and "renders no sort-button row for a table list" windowed gated already (fetch chain) / not schema-dependent a table list never renders the button row
RelatedList.sortabilitySignal surface 2, the five data-list sort-button cases windowed gated already (fetch chain) data-list mounts only after the rows, which wait on the settled schema
RelatedList.sortabilitySignal surface 1, the seven windowed header cases windowed gated already (fetch chain) as above
RelatedList.sortabilitySignal "leaves every header live in client mode" client not schema-dependent reads sortable
RelatedList.maskedFilterSort-10728 filter box (five cases), list sort buttons (five cases), the table-header sort case client gated already each waits on a fact only the landed schema produces (a drawn name, the Name sort button), or holds the schema on purpose (the two held cases)
RelatedList.maskedFilterSort-10728 the windowed $orderby case windowed gated already waits for a drawn name
RelatedList.maskedColumn-10657 masked-header sort click, copy, tooltip, width, export client gated already settledWithMask waits for a drawn name; the held and rejected cases read the withheld window on purpose, and it reads the same whether or not the read has settled
RelatedList.maskedFirstPaint-10657 held / rejected / settled client not in the class reads cells, not a sort or filter control, through an explicit hold
RelatedList.relationalSort "keeps it in client mode and orders by the resolved label, not the id" client gated already (implicitly) it waits for the sys_user label read, which only the render holding the schema issues (the target comes from the schema's reference); the order assertion sits inside waitFor
RelatedList.relationalSort the windowed case windowed gated already (fetch chain)
RelatedList.sortDroppedOutsideWindowed the filter-box cases windowed, then client once a term is typed not schema-dependent its data source has no getObjectSchema, so objectTypesPending is false throughout
RelatedList.serverpagination "keeps client-side slicing when the caller supplies data directly" client, no data source not schema-dependent pagination only
RelatedList.systemcolumns column order auto-fetch not in the class column headers, not a sort or filter control; gated by the fetch chain
RelatedList.columnIdentityAccessor.schema asserts onSortChange is a function client not schema-dependent the callback exists whatever the stamp says
columnHeaderLabel, columnIdentityAccessor, iconSeam-5935, parentscope, rowactions, userColumnNames-10112, DetailView.relatedEntryRetired-7997, RecordRelatedListRenderer.redactedDerivation-9053, RecordRelatedListRenderer.unresolvedIdentityFailClosed-8793, summaryChip.dateOnlyZone-10183 their client-mode renders client not in the class no sort button, filter box or sort call anywhere in the file; cell reads sit inside waitFor
every other file (the RecordRelatedListRenderer.* set and the remaining RelatedList.* files) all auto-fetch no client window record:related_list never passes data; the rows wait on the settled schema

Measured cross-check of the census. A throwaway delay between getObjectSchema resolving and useSettledSchema settling (in packages/react/src/hooks/useSettledSchema.ts, which vitest aliases to source), run over all 51 files at base: at 50 ms, and again at 400 ms, Tests 1 failed | 316 passed | 8 skipped (325), and the one failure is the target case. It was restored both times, blob equal to HEAD and git diff HEAD empty. That delay sits after the promise settleObjectSchema awaits, so it can find a race but cannot prove the gate. The green-after proof below uses the mock-level probe A.

Proof (probe A: getObjectSchema delayed 50 ms in the file's throwaway mock, never committed)

Every leg ran through ablation-replace.mjs (anchor hit 1 -> 0, blob moved, restored to the HEAD blob, git diff HEAD empty) under the verify lock.

  • Base 733fd5ac6, no probe: Tests 5 passed (5), VERDICT command-exit 0.
  • Base, probe A: red, the CI signature. Tests 1 failed | 4 passed (5): × keeps that button in client mode, TestingLibraryElementError: Unable to find an accessible element with the role "button" and name /Total/, and the only buttons present were Previous and Next. The four other cases stayed green under the probe. VERDICT command-exit 1.
  • Head b92ab92b3 (gate committed), probe A: green. Tests 5 passed (5), VERDICT command-exit 0.
  • Head, no probe (probe C): three runs back to back, each Tests 5 passed (5), VERDICT command-exit 0.

Gates (head 3abab7ce5 unless stated)

  • pnpm exec vitest run packages/plugin-detail/ at b92ab92b3: Test Files 216 passed | 1 skipped (217), Tests 2120 passed | 8 skipped (2128), VERDICT command-exit 0. The only later commit adds the .changeset file, which no plugin-detail test reads (check-pending-changeset-literals: No test source names a pending changeset). The changed file was re-run at 3abab7ce5: Tests 5 passed (5), VERDICT command-exit 0. This is a declared narrowing: the full suite held the lock for 9m05s, too close to the 10-minute foreground cap to repeat.
  • pnpm --filter @object-ui/plugin-detail run type-check (echoes tsc --noEmit && tsc -p tsconfig.test.json): exit 0, VERDICT command-exit 0. It ran after turbo run build --filter='@object-ui/plugin-detail^...' (Tasks: 11 successful, 11 total). tsc -p tsconfig.test.json --listFilesOnly lists the changed test file.
  • eslint on the changed test file, with the package's own config and --format json: 1 file, 0 errors, 5 warnings (@typescript-eslint/no-explicit-any), identical to its base blob linted via --stdin (1 file, 0 errors, 5 warnings, same rule). Population: --print-config resolves a config for the file (119 rules). The config has no parserOptions.project and no projectService, so there is no type-aware linting and this diff cannot move a verdict in an untouched file.
  • node scripts/check-changeset-presence.mjs: before the changeset, exit 1: 1 source file(s) of 1 released package(s) changed, and this change adds no changeset. After it, exit 0: this change declares 1 changeset(s) … Every one of them has an EMPTY frontmatter.
  • check-changeset-no-major, check-changeset-overwrite, check-changeset-fixed, check-changeset-claims, check-pending-changeset-literals: exit 0.
  • check:control-bytes, check:new-line-citations (0 new citation(s)), check:test-path-roots, check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape: exit 0.
  • check-governed-queue-guard.mjs --test on both paths: NOT GOVERNED.
  • Repo-wide pnpm lint and the rest of the lint farm are CI's.

Serial

PR objectui#10914 touches DetailView.tsx and renderers/record-details.tsx in this package. Neither is touched here. This branch changes exactly two paths, the test file above and the new .changeset file.

  • Against its head, fetched into a named ref (pull/10914/head, 2b3d2061a): git merge-tree --write-tree HEAD with that ref gives exit 0, clean tree 3f2b90a34. Its file list, taken against its merge-base with main, has no path in common with this branch.
  • Against a fresh origin/main (733fd5ac6, unchanged since the branch point): git merge-tree --write-tree gives exit 0, clean tree 6b2edc48c.

Acceptance notes

  • The two windowed cases in this file keep their settleObjectSchema gate. Since objectui#10690 the windowed row fetch already waits on the settled schema, so that gate is now a second guard there. Left as it is: nothing is flaky there, and removing it is not this card.
  • Withheld cells (the mask drawn while objectTypesPending holds) ride the same window as the stamp. The client-mode files that read cells do it inside waitFor or through an explicit hold, and the detector kept them green. They are outside the census class (no sort or filter control).

Generated by Claude Code

…on the object schema

The case "keeps that button in client mode" gated only on the view type
(`data-list`), which client mode satisfies on the first commit, then read
the `Total` sort button synchronously. Since the sort-button row reads
the masked stamp (objectui#10728), every column carries it until
`getObjectSchema` resolves, so the button existed only once the schema
commit had landed: a scheduling race (the #7007 trap described in the
file's own docblock). It now awaits `settleObjectSchema(dataSource)`,
the gate its windowed sibling already uses.

Test-only: no retry, no raised timeout, no source change.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN
…(empty frontmatter)

`check-changeset-presence` counts every file under a released package's
`src/`, test files included, so the test-only gate needs an explicit
no-release declaration.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3096.1 KB 3104.5 KB
Main entry chunk (gzip) 148.6 KB 350 KB
Entry file index-CXe0iCYr.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) 16.58KB 6.17KB
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) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
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.70KB 2.23KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
auth (index.js) 3.63KB 1.64KB
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) 27.13KB 7.95KB
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) 557.59KB 133.60KB
core (index.js) 9.93KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 226.44KB 63.00KB
fields (index.js) 261.01KB 66.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
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.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
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) 13.52KB 4.88KB
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) 8.33KB 3.07KB
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) 16.01KB 3.93KB
plugin-calendar (index.js) 51.96KB 14.83KB
plugin-charts (index.js) 83.99KB 22.86KB
plugin-chatbot (index.js) 197.67KB 46.90KB
plugin-dashboard (index.js) 136.93KB 36.48KB
plugin-designer (index.js) 215.03KB 44.21KB
plugin-detail (index.js) 233.48KB 61.79KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 161.21KB 41.41KB
plugin-gantt (index.js) 170.35KB 42.19KB
plugin-grid (index.js) 228.33KB 62.59KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.86KB 28.64KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.17KB 12.20KB
plugin-timeline (index.js) 31.00KB 9.09KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 88.55KB 22.21KB
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.81KB 3.58KB
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) 119.16KB 39.05KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 7.50KB 3.05KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.16KB 2.71KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.22KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
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.26KB
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 (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 (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 (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.27KB 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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 3abab7ce5ae95095f5bed4d0b055e3342e18e7e4

This is an in-seat review. The card is size S, test-only, Clause-②: no, and the diff is 4 lines of test plus an empty-frontmatter changeset. That is narrow enough for the seat, per the pm-dispatch shape.

① Derived judgments

  • The patch is the card's ready patch, exactly. In the case "keeps that button in client mode", renderList now returns its dataSource (the helper already returns it; its sibling cases capture it the same way). After the data-list waitFor, the case awaits settleObjectSchema(dataSource), the file's own helper that the two windowed cases already use, with the card's one-line reason.
    • ⛔ No retry, no raised timeout, no waitFor wrapped around the assertion, and no source change. Triage 5864346702 execution note 3 holds.
  • Proof, from the dev's quoted outputs.
    • Probe A (getObjectSchema delayed 50 ms, a throwaway that was never committed) at base gives 1 failed | 4 passed, with the exact CI signature: "Unable to find … /Total/", only Previous and Next present.
    • The same probe at the gated head gives 5 passed.
    • Without the probe: base 5 of 5, head 5 of 5, and three repeats 5 of 5.
    • The full plugin-detail suite gives 216 files and 2120 tests passed.
  • Census (execution note 2): the dev read all 51 plugin-detail test files that reach RelatedList, plus DetailView.test. Each candidate got a verdict.
    • Only the target case races.
    • The windowed cases are gated by the row fetch, which waits on the settled schema (objectui#10690).
    • The client-mode cases in maskedFilterSort-10728, maskedColumn-10657 and relationalSort each wait on a fact only the landed schema produces.
    • A delay detector, placed between getObjectSchema resolving and useSettledSchema settling, over all 51 files at 50 ms and at 400 ms, fails only the target case (1 failed of 325, both runs).
    • The dev's caveat is recorded: the detector finds races, it does not prove the gate. Probe A proves the gate.
  • The changeset has empty frontmatter, so it releases nothing, and check-changeset-presence asked for it (it counts test files under src/). Every sentence is true.
  • This PR is also the fix for the shard-7 failure that hit PR objectui#10912 at 5b2b8568bb (the same case, the same signature).

② Semver level

Nothing is released (empty frontmatter). Clause-②: no. ⛔ Not major.

③ Boundary flags

  • CI: the landing waits for every check-run on this head to be final and green, and re-runs git merge-tree against current main first. Spec Main Shape Gate is expected red until objectui#10916 lands. That failure is not this PR's (it touches no packages/types file), and the landing waits for it.
  • Merge: the dev's merge-tree is clean against origin/main 733fd5ac6 and against PR objectui#10914's head (no shared path).
  • NOT GOVERNED.
  • Draft, assigned to os-elon-musk.

Implemented-by: claude/issue-10895-relatedlist-client-sort-gate
Reviewed-by: session_014mXUNuFomfj24w7s1pZzhN

VERDICT: PASS

…0895-relatedlist-client-sort-gate

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3096.1 KB 3104.5 KB
Main entry chunk (gzip) 148.6 KB 350 KB
Entry file index-CXe0iCYr.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) 16.58KB 6.17KB
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) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
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.70KB 2.23KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
auth (index.js) 3.63KB 1.64KB
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) 27.13KB 7.95KB
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) 557.59KB 133.60KB
core (index.js) 9.93KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 226.44KB 63.00KB
fields (index.js) 261.01KB 66.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
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.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
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) 13.52KB 4.88KB
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) 8.33KB 3.07KB
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) 16.01KB 3.93KB
plugin-calendar (index.js) 51.96KB 14.83KB
plugin-charts (index.js) 83.99KB 22.86KB
plugin-chatbot (index.js) 197.67KB 46.90KB
plugin-dashboard (index.js) 136.93KB 36.48KB
plugin-designer (index.js) 215.03KB 44.21KB
plugin-detail (index.js) 233.48KB 61.79KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 161.21KB 41.41KB
plugin-gantt (index.js) 170.35KB 42.19KB
plugin-grid (index.js) 228.33KB 62.59KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.86KB 28.64KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.17KB 12.20KB
plugin-timeline (index.js) 31.00KB 9.09KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 88.55KB 22.21KB
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.81KB 3.58KB
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) 119.16KB 39.05KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 7.50KB 3.05KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.16KB 2.71KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.22KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
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.26KB
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 (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 (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 (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.27KB 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

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 28, 2026 09:05
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 28, 2026
Merged via the queue into main with commit d61ce42 Sep 28, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-10895-relatedlist-client-sort-gate branch September 28, 2026 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants