Skip to content

test(app-shell,console): 29 @object-ui/i18n mock factories inherit the real surface, and the recogniser stops mis-reading a nested generic (objectui#7337) - #7889

Merged
os-sam merged 4 commits into
mainfrom
claude/issue-7337-vi-mock-i18n-inherit
Sep 6, 2026
Merged

test(app-shell,console): 29 @object-ui/i18n mock factories inherit the real surface, and the recogniser stops mis-reading a nested generic (objectui#7337)#7889
os-sam merged 4 commits into
mainfrom
claude/issue-7337-vi-mock-i18n-inherit

Conversation

@os-sam

@os-sam os-sam commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

Part of #7337

⚠️ Deliberately Part of, not a closing keyword. This PR delivers the sweep
and the recogniser repair; it does not add @object-ui/i18n to
COVERED_SPECIFIERS, which is that card's headline ask. One frozen factory
survives, in a file this seat was ordered not to edit, and flipping the ratchet
while it exists turns main red on merge. The remaining half is spelled out
under "What is left" below, so the card stays open to carry it.

The real frozen count is 31, and four of the reported 35 were the gate's own bug

Three figures were in circulation before this branch — 92 (a git grep upper
bound), 40/41 (the card, measured on PR #7330's merged head) and 34 (the gate
header's table, measured at 9ce20233f). None of them is what the gate's own
classifier reads today, and the discrepancy was not only drift.

Running this gate's classifier over origin/main with @object-ui/i18n as the
covered specifier: 93 judged call sites, 58 inheriting, 35 frozen. Four of
those 35 obtain the real module and spread it — they were false positives:

packages/app-shell/src/console/cloud-connection/__tests__/CloudConnectionPanel.bindError.test.tsx:62
packages/app-shell/src/console/cloud-connection/__tests__/CloudConnectionPanel.bindErrorLocale.test.tsx:62
packages/app-shell/src/layout/__tests__/AppSwitcher.publishState.test.tsx:64
packages/app-shell/src/preview/__tests__/UnpublishedAppBar.test.tsx:43

Each writes const actual = await vi.importActual with a nested generic
argument, Record of string to unknown. The recogniser's optional generic was
a character class that excludes the closing angle bracket, so it stopped at the
FIRST one: it consumed the opening bracket plus Record plus the inner
argument list plus that inner closing bracket, then failed against the outer
closing bracket that follows. The whole call went unmatched and the factory was
reported as one that "never obtains the real module" — on code that obtains it
and spreads it.

That is the failure this gate's own header rules out by name ("an exemption
means the recogniser called correct code broken; fix the recogniser"), and it
stayed invisible because the covered set is @object-ui/react, where nobody
writes that spelling.

importActualSpans() replaces the regular expression with a balanced scan
of the angle brackets. Measured across all 21 workspace specifiers, before and
after, on the same tree:

frozen inherits unreadable
before 349 280 0
after 344 285 0

Zero sites move the other way — the change only ever ADDS a way to recognise
the obtain, so nothing that read inherits can start reading frozen. A fifth
false positive outside this card's specifier is corrected as a side effect
(packages/app-shell/src/views/metadata-admin/WidgetContext.catalogUnion.test.tsx:74),
which is one fewer entry on #6892's worklist and no sweep of another specifier.

So the genuine frozen population for this specifier was 31, not 35 and not 40.

What this PR does

  • 29 factories converted to the obtain-and-spread form
    (async (importOriginal) => spreading await importOriginal of
    Record of string to unknown), across @object-ui/app-shell (22) and
    apps/console (7).
  • 1 deleted: apps/console/dev/__tests__/setup/common-mocks.ts. It exported
    applyCommon + ConsoleMocks behind a frozen @object-ui/i18n factory and
    had zero importers repo-wide — the card's and triage's instruction was
    delete-or-wire, and explicitly not convert-and-keep, which would be insuring
    dead code. check-vi-mock-specifiers.mjs's header cited that file as one of
    the two non-test-named files carrying a call site, so its prose is corrected
    in the same commit rather than left stale.
  • 1 left frozen: packages/app-shell/src/views/__tests__/DeclaredActionsBar.test.tsx:65
    — see below.
  • COVERED_SPECIFIERS untouched.

After the sweep: 92 judged call sites, 91 inherit, 1 frozen, 0 unreadable.

The pin reproduces the DEATH, not the spelling

THE DEATH builds a throwaway package in a temp directory whose "next export"
is the one added the day after the factory was written, and runs vitest for
real
against it. Every verdict is read from the child's JSON reporter, so
nothing depends on how vitest prints (see "Patch round" below for why that
sentence is load-bearing):

leg factory read site structured result
1 frozen module scope suite failed, total: 0, assertions: 0, collection error on the SUITE
2 inheriting module scope success: true, total: 1, passed: 1
3 frozen inside a function total: 1, assertions: 1, failed: 1, no suite message

Leg 1 is the signature objectui#6768 measured: a red run with zero failed
assertions
, which reads as flake and bills the wrong author. Leg 3 is the
non-vacuity control: same missing export, same frozen factory, and a completely
different shape because the read is no longer at module scope. Without it, a
fixture that failed for any reason at all would satisfy leg 1. The
ANSI-stripped human summary (Failed Suites 1 / Tests no tests / Tests 1 passed / Tests 1 failed) is asserted alongside, as belt to that brace.

A fourth case asserts the gate's verdict on those same two factories BEFORE
either is run, so the gate's classification is tied to the observed outcome.

Patch round — CI run 34003883330 was red on the death pin, and why

Three assertions failed on output that visibly contained the text they were
matching. Cause, read out of the job log rather than guessed: under GitHub
Actions the nested vitest colours its summary, so the real bytes are

ESC[2m      Tests ESC[22m ESC[1mESC[31m1 failed ESC[39mESC[22mESC[90m (1)ESC[39m

and \s+ matches no escape sequence. The box this was written on never colours
vitest under any env combination tried (CI, GITHUB_ACTIONS, FORCE_COLOR,
FORCE_TTY, --color, a pty — all measured, all uncoloured), so the shape was
unreachable locally. It is reproduced instead by replaying the exact bytes
from that job
in a new case: the old regex does not match them, the stripped
form does. That control is permanent and does not depend on CI colouring today.

Two repairs, both in the pin only:

  1. The verdict moved to the JSON reporter. Pinning a human-readable summary
    through a regex was the fragile part. The counts are structured now, and the
    discrimination got sharper, not looser — proved below.
  2. GITHUB_ACTIONS is dropped from the child's env. Legs 1 and 3 fail on
    purpose, and with it set the child switched on vitest's github-actions
    reporter and wrote ::error file=/tmp/vi-mock-collection-death-… annotations
    into the parent's own CI log, decorating this PR's run with failures from a
    fixture that was behaving correctly. Measured locally: with the variable, one
    ::error line; without it, zero.

NO_COLOR=1 is also set on the child, but nothing relies on it — the stripping
and the structured counts are what make the assertions true either way.

Ablation — five legs, each mutated on disk and restored by content

Every leg mutated a committed file, proved the bytes reached disk, ran, then
restored with git checkout HEAD -- and proved the restore by comparing the
on-disk hash against the HEAD blob (never by an exit code):

leg mutation result
A revert the recogniser to the first-angle-bracket generic 6 failed / 63 passed
B re-freeze one swept factory (PageView.test.tsx) 2 failed / 67 passed
C hand the death pin the INHERITING factory as its frozen one 3 failed / 66 passed
D give leg 3 a MODULE-SCOPE read (make it a copy of leg 1) 1 failed / 68 passed — only leg 3
E give leg 1 a LAZY read (make it a copy of leg 3) 1 failed / 68 passed — only leg 1

C is the trap #7861's fourth ablation warns about — a fixture self-consistent
with the thing it checks — and the pin does not stay green through it.
D and E are new this round and are the direct answer to "leg 3 must still
discriminate": swap the read site between the two legs and exactly the leg
whose premise was removed fails
. They are not interchangeable, so no assertion
here is satisfied by "a red run" in general.

What is left, and why

packages/app-shell/src/views/__tests__/DeclaredActionsBar.test.tsx:65 is still
frozen. The dispatch order locked that file and ruled that a correct partial
delivery beats a red main. PR #7846 has since landed (83fe6e7), so the lock's
premise is gone and the PM has lifted it — but not for this PR. The follow-up
is ruled to happen after this one merges:

  1. convert that factory to obtain-and-spread (it overrides four names, all of
    which stay as overrides on top of the spread);
  2. delete the the specifier is NOT in COVERED_SPECIFIERS yet case in
    scripts/__tests__/check-vi-mock-inherit.test.ts;
  3. add '@object-ui/i18n' to COVERED_SPECIFIERS.

Until then the ratchet lives in the pin file, one-directionally: it reddens when
a NEW frozen @object-ui/i18n factory appears — the defect — and stays green
when the held one is fixed, so nobody's unrelated PR pays for finishing this.

Verification

All at 52c43eb (branch head, merged up to origin/main with #7846 and #7880 in it).

scripts/__tests__/ (full)                        107 files, 3220 tests   PASS
scripts/__tests__/ + the 30 changed test files   120 files, 3585 tests   PASS   (at 2c10cbe)
packages/app-shell/ (full suite)                 623 files, 5964 tests   PASS   (at cf7f2af)
apps/console/ (full suite)                        89 files,  981 tests   PASS   (at cf7f2af)

Gates, each read from its own verdict line, exit code captured before any pipe:

node scripts/check-vi-mock-inherit.mjs        exit=0
node scripts/check-vi-mock-specifiers.mjs     exit=0
pnpm check:control-bytes                      exit=0
pnpm check:unreferenced-sources               exit=0
node scripts/check-changeset-presence.mjs     exit=0
pnpm changeset:check                          exit=0
pnpm type-check:scripts                       exit=0
pnpm type-check:coverage                      exit=0
pnpm lint:coverage                            exit=0
pnpm lint:root                                exit=0
turbo type-check --filter=@object-ui/app-shell --filter=@object-ui/console   37/37 tasks OK   (at 2c10cbe)
node scripts/check-governed-queue-guard.mjs --test (34 paths)   NOT GOVERNED

packages/app-shell/tsconfig.json excludes tests, so the converted files are
compiled by tsc -p tsconfig.test.json, the second half of that package's
type-check. Proved rather than assumed: --listFiles on that project lists
1043 app-shell source files and names each converted file exactly once.

Lint is a declared narrowing, not a full run: eslint over the 33 changed
files reports 0 errors, 268 warnings, every warning a pre-existing
no-explicit-any in a test body this PR did not add a line of any to (the
patch-round file itself: 0 errors, 0 warnings). The receiving population, read
from eslint's own config resolution rather than guessed, is 4319 files; the
flat config declares no parserOptions.project and no projectService, so
type-aware linting is off and this diff cannot move the verdict on any file it
does not touch. CI runs the full farm.

Changeset: .changeset/7337-vi-mock-i18n-inherit.md, empty frontmatter
check-changeset-presence.mjs has no carve-out for tests under src/, and its
own verdict names this as the complete answer. ⛔ The skip-changeset label is
dead in this repo (#4912) and was not applied.

In-flight collisions — both resolved

#7880 landed (b4c5d1b) and is merged in. Its edit to
scripts/__tests__/check-vi-mock-inherit.test.ts (+29/-18) auto-merged with
no conflict
, as predicted: this branch touches that file only at the import
line and in a pure append. The semantic half was re-checked too — #7880 moves
which sites the shared masker delimits, and its own commit message records that
it deliberately left this gate's local deJsxClosingTags workaround in place.
Counts re-derived on the merged head are unchanged: 92 judged / 91 inherit /
1 frozen / 0 unreadable.

#7846 landed (83fe6e7) and is merged in. Its diff does not touch the
frozen factory, so DeclaredActionsBar.test.tsx:65 reads the same before and
after. ⛔ scripts/js-comment-mask.mjs is not touched here.


Generated by Claude Code

…29 mock factories (objectui#7337)

A `vi.mock('@object-ui/i18n', () => ({ … }))` factory that hand-lists its
exports freezes the mock to the names that existed the day it was written.
The next module-scope read of a new export kills the importing file during
COLLECTION, so the suite reports zero failed assertions and the red lands on
an innocent test file.

- convert 29 frozen factories to the obtain-and-spread form;
- delete `apps/console/dev/__tests__/setup/common-mocks.ts`, a mock helper
  with zero importers repo-wide carrying the same shape;
- fix the recogniser's nested-generic blind spot: `<[^>]*>` stopped at the
  first `>`, so `vi.importActual<Record<string, unknown>>(…)` went unmatched
  and four factories that obtain AND spread the real module were reported as
  frozen. Repo-wide across all 21 workspace specifiers: 349 frozen -> 344,
  with no site moving the other way;
- pin the failure mode itself: three nested vitest runs over a throwaway
  package show the frozen factory dying at collection, the converted one
  passing, and a lazy read failing as an ordinary assertion.

`COVERED_SPECIFIERS` is deliberately NOT widened: one frozen factory remains
in `DeclaredActionsBar.test.tsx`, held by open PR #7846, and flipping the
ratchet while it exists turns `main` red on merge.

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

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3187.2 KB 3191.4 KB
Main entry chunk (gzip) 143.4 KB 350 KB
Entry file index-CAIR07xM.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) 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) 510.60KB 116.20KB
core (index.js) 6.96KB 2.79KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 182.08KB 50.62KB
fields (index.js) 242.44KB 61.25KB
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) 4.28KB 1.75KB
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.98KB 10.98KB
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.75KB 3.80KB
plugin-calendar (index.js) 47.87KB 13.31KB
plugin-charts (index.js) 70.92KB 19.75KB
plugin-chatbot (index.js) 196.19KB 46.37KB
plugin-dashboard (index.js) 132.88KB 34.69KB
plugin-designer (index.js) 212.86KB 43.19KB
plugin-detail (index.js) 250.55KB 64.06KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 132.87KB 32.66KB
plugin-gantt (index.js) 167.26KB 41.00KB
plugin-grid (index.js) 209.29KB 56.78KB
plugin-kanban (index.js) 52.71KB 14.55KB
plugin-list (index.js) 113.76KB 27.75KB
plugin-map (index.js) 20.44KB 6.78KB
plugin-markdown (index.js) 13.93KB 4.81KB
plugin-report (index.js) 43.59KB 11.97KB
plugin-timeline (index.js) 30.84KB 8.85KB
plugin-tree (index.js) 9.20KB 3.19KB
plugin-view (index.js) 85.24KB 20.94KB
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) 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 1.00KB
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 (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

…r, not from a coloured summary (objectui#7337)

CI run 34003883330 (job 101407488095) failed three assertions in the death
pin on output that visibly contained the text they were matching. Under
GitHub Actions the nested vitest colours its summary, so the real bytes are
`Tests ` + SGR + `1 failed` + SGR + ` (1)` and `\s+` matches no escape
sequence. The box this was written on never colours vitest under any env, so
the shape was unreachable locally.

- the three legs now decide on the JSON reporter's structured counts, so no
  verdict depends on how vitest PRINTS. Leg 1 asserts total=0 / assertions=0
  with the collection error on the SUITE; leg 3 asserts total=1 /
  assertions=1 with no suite message. That pair is the discrimination, and it
  is sharper than the prose was, not looser;
- the human-readable lines the card quotes are still asserted, on an
  ANSI-stripped copy;
- a new case replays the exact bytes from that CI job: the old regex does not
  match them, the stripped form does;
- `GITHUB_ACTIONS` is dropped from the child's env. Legs 1 and 3 fail on
  purpose, and with it set the child emitted `::error file=…` annotations
  into the parent's own CI log — visible in that same run.

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

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3187.3 KB 3191.4 KB
Main entry chunk (gzip) 143.5 KB 350 KB
Entry file index-ZK5RvsHJ.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) 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) 510.60KB 116.20KB
core (index.js) 6.96KB 2.79KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 182.08KB 50.62KB
fields (index.js) 242.44KB 61.25KB
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) 4.28KB 1.75KB
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.98KB 10.98KB
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.75KB 3.80KB
plugin-calendar (index.js) 47.87KB 13.31KB
plugin-charts (index.js) 70.92KB 19.75KB
plugin-chatbot (index.js) 196.19KB 46.37KB
plugin-dashboard (index.js) 132.88KB 34.69KB
plugin-designer (index.js) 212.86KB 43.19KB
plugin-detail (index.js) 250.55KB 64.06KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 132.87KB 32.66KB
plugin-gantt (index.js) 167.26KB 41.00KB
plugin-grid (index.js) 209.29KB 56.78KB
plugin-kanban (index.js) 52.71KB 14.55KB
plugin-list (index.js) 113.76KB 27.75KB
plugin-map (index.js) 20.44KB 6.78KB
plugin-markdown (index.js) 13.93KB 4.81KB
plugin-report (index.js) 43.59KB 11.97KB
plugin-timeline (index.js) 30.63KB 8.80KB
plugin-tree (index.js) 9.20KB 3.19KB
plugin-view (index.js) 85.24KB 20.94KB
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) 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 1.00KB
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 (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

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3187.3 KB 3191.4 KB
Main entry chunk (gzip) 143.5 KB 350 KB
Entry file index-ZK5RvsHJ.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) 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) 510.60KB 116.20KB
core (index.js) 6.96KB 2.79KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 182.08KB 50.62KB
fields (index.js) 242.44KB 61.25KB
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) 4.28KB 1.75KB
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.98KB 10.98KB
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.75KB 3.80KB
plugin-calendar (index.js) 47.87KB 13.31KB
plugin-charts (index.js) 70.92KB 19.75KB
plugin-chatbot (index.js) 196.19KB 46.37KB
plugin-dashboard (index.js) 132.88KB 34.69KB
plugin-designer (index.js) 212.86KB 43.19KB
plugin-detail (index.js) 250.55KB 64.06KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 132.87KB 32.66KB
plugin-gantt (index.js) 167.26KB 41.00KB
plugin-grid (index.js) 209.29KB 56.78KB
plugin-kanban (index.js) 52.71KB 14.55KB
plugin-list (index.js) 113.76KB 27.75KB
plugin-map (index.js) 20.44KB 6.78KB
plugin-markdown (index.js) 13.93KB 4.81KB
plugin-report (index.js) 43.59KB 11.97KB
plugin-timeline (index.js) 30.63KB 8.80KB
plugin-tree (index.js) 9.20KB 3.19KB
plugin-view (index.js) 85.24KB 20.94KB
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) 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 1.00KB
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 (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-sam
os-sam marked this pull request as ready for review September 6, 2026 02:14
@os-sam
os-sam added this pull request to the merge queue Sep 6, 2026
Merged via the queue into main with commit 6a9ee32 Sep 6, 2026
34 checks passed
@os-sam
os-sam deleted the claude/issue-7337-vi-mock-i18n-inherit branch September 6, 2026 02:30
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.

2 participants