Skip to content

test(core,app-shell): type-check the whole test trees, retire both narrow typetests projects (#4040) - #4379

Merged
yinlianghui merged 2 commits into
mainfrom
claude/issue-4040-tranche5-core-app-shell
Aug 12, 2026
Merged

test(core,app-shell): type-check the whole test trees, retire both narrow typetests projects (#4040)#4379
yinlianghui merged 2 commits into
mainfrom
claude/issue-4040-tranche5-core-app-shell

Conversation

@yinlianghui

@yinlianghui yinlianghui commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Part of #4040 — tranche 5 (final). @object-ui/plugin-dashboard's 6 errors are deliberately out of scope (its surface belongs to the #4330 queue candidate's family), so its TEST_DEBT line stays and this PR does not close the card.

@object-ui/core and @object-ui/app-shell — the two largest debt packages, held back to last by the standing small-first ruling — each gain a tsconfig.test.json chained from type-check, so their 81 and 350 test files are compiled by something for the first time. Both TEST_DEBT lines are removed; per #4291's ratchet both packages' narrow tsconfig.typetests.json projects retire in this same PR.

After this, check-type-check-coverage.mjs reports 39/40 packages compile their tests and 0 narrow type-assertion projects remaining.

Measurement — red before, green after

Measured per the discipline adopted at tranche 2: every compiler stream written to a FILE and counted there, never piped through head/tail (SIGPIPE truncates mid-stream and fabricates a plausible count).

package raw errors config-tier code-tier (pre-fix) registry declared after
@object-ui/core 132 76 56 56 0
@object-ui/app-shell 221 159 62 62 0

Both registry numbers were exactly right — the first tranche where that is true. They are the tranche-4 remeasurement, and the note warning that the older #2911-era numbers were unreliable in both directions is what made them trustworthy; the note is folded into the table header now that the two entries it described are gone.

Raw runs use a temp config that lifts only the test exclusion from each package's own build config; code-tier is against the template config each package graduates with.

core, pre-fix (56): TS2322×17, TS7006×10, TS2345×7, TS2339×5, TS2304×5, TS2353×4, TS2532×3, TS2352×2, TS6133/TS2538/TS2348×1.

src/actions/__tests__/TransactionManager.test.ts(58,21): error TS2322: Type 'ActionSchema' (types/dist/crud) is not assignable to type 'ActionSchema' (types/dist/ui-action).
  Types of property 'name' are incompatible. Type 'string | undefined' is not assignable to type 'string'.
src/actions/__tests__/ActionRunner.resultDialog.test.ts(32,28): error TS2345: Argument of type 'Mock< Procedure | Constructable >' is not assignable to parameter of type 'ToastHandler'.
src/builder/__tests__/schema-builder.test.ts(92,19): error TS2353: Object literal may only specify known properties, and 'name' does not exist in type 'TableColumn'.

core, config-tier (76): TS6059×39 (source-tree paths pulling sibling src/ in as program inputs → paths: {}), TS2591×22 + TS2304×13 (node:fs / __dirname / globaltypes: ["node"]), TS7006×2 that fell out with them.

app-shell, pre-fix (62): TS2322×10, TS2698×8, TS2339×8, TS2739×7, TS2493×6, TS2345×6, TS2554×4, TS7006×3, TS2559×3, TS2769×2, TS2352×2, TS2578/TS2353/TS2307×1.

src/hooks/__tests__/useConsoleActionRuntime.test.tsx(504,25): error TS2339: Property 'onModal' does not exist on type '{ context; onConfirm; onToast; onNavigate; onParamCollection; onResultDialog; handlers }'.
src/hooks/__tests__/useConsoleActionRuntime.test.tsx(1044,9): error TS2554: Expected 1 arguments, but got 2.
src/views/metadata-admin/previews/AgentPreview.test.tsx(54,23): error TS2698: Spread types may only be created from object types.
src/console/ai/__tests__/AiChatPage.hydration.test.ts(25,16): error TS2339: Property 'toolInvocations' does not exist on type 'ChatMessage'.

app-shell, config-tier (159): TS6059×121 (same paths leak) and TS2550×38 — calls.at(-1) and friends against the package build's lib: ES2020. Raised to ES2022 in the TEST project only, so the package SOURCE keeps compiling against the baseline it ships to.

After (both green, and the source projects unchanged):

$ tsc -p packages/core/tsconfig.test.json         → exit 0, 0 errors
$ tsc --noEmit -p packages/core/tsconfig.json     → exit 0, 0 errors
$ tsc -p packages/app-shell/tsconfig.test.json    → exit 0, 0 errors
$ tsc --noEmit -p packages/app-shell/tsconfig.json → exit 0, 0 errors

Config-tier recipe

Both projects extend the repo root, set noEmit / composite: false / declaration: false, drop paths to {}, and include src/**/*.test.ts(x). The two differences:

  • coretypes: ["node"] (suites read fixtures through node:fs / node:url / __dirname, and the ActionRunner suites stub global.fetch); lib stays at the root's ES2020/DOM/DOM.Iterable.
  • app-shelllib: ["ES2022", "DOM", "DOM.Iterable"] and types: ["node", "vite/client", "@testing-library/jest-dom"], exactly the recipe recorded on the card at tranche 4. jsx: react-jsx for the 212 .tsx suites.

Notably NOT added: vitest/globals. No graduated package in this repo carries it, and the five core files that used vi without importing it are outliers — they got the import their siblings all have.

Source changes — three declarations narrower than their implementation

Only two source files move, both in app-shell, and each is a declaration the compile errors proved wrong rather than a behaviour change.

1. ConsoleActionRuntime.actionProviderProps — restatement → derivation (the item the dispatch flagged; it did surface). The interface hand-restated ActionProvider's props and had drifted twice: it omitted onModal, which the implementation has returned all along, and declared handlers values as one-parameter functions where ActionProvider passes (action, ctx). The neighbouring suite asserts typeof props.onModal === 'function' — it was reading a key the interface said did not exist. Now:

actionProviderProps: Required< Pick< ActionProviderProps,
  | 'context' | 'onConfirm' | 'onToast' | 'onModal'
  | 'onNavigate' | 'onParamCollection' | 'onResultDialog' | 'handlers' > >;

The key list stays explicit — it states which props this hook owns — but every type comes from the consumer, so the two cannot drift again.

2. ConsoleActionRuntime.apiHandler declares its second parameter. The implementation has always been (action, context?) (it reads context.pageVariables to resolve {{page.< var >}} tokens), and its three siblings in the same interface already spelled that. Two tests call it with two arguments.

3. AiChatPage imports the chat-message type it actually produces. @object-ui/plugin-chatbot exports TWO ChatMessage interfaces — the enhanced one (as ChatbotEnhancedMessage) and a minimal legacy one (id/role/content/…) from its own barrel module. This file imported the legacy one while producing and consuming the enhanced shape; the mismatch compiled only because every construction site spreads the extra keys conditionally (...(x ? { toolInvocations } : {})), which defeats excess-property checking. So hydratedMessagesToChatMessages returned a type narrower than every value flowing through it, and its own test could not read toolInvocations off it.

Test-side fixes worth naming

  • core / TransactionManager.test.ts (17 of 56). The suite imported ActionSchema from @object-ui/types, which resolves to the deprecated crud.ts one (type: 'action', optional name) — while executeTransaction takes a UIActionSchema executor. Every fixture was authored in a vocabulary the implementation never sees. Re-pointed at UIActionSchema; the TS2538 "undefined cannot be used as an index type" fell out with it, since name is required there.
  • core / schema-builder.test.ts. Column fixtures were { name, label } — a dialect TableColumn does not have (its keys are accessorKey / header). The builder stores whatever it is handed, so the assertion was checking that the builder returns its own input, on a shape no CRUD renderer reads. Re-spelled canonically. Separately, operations.< key > is boolean | CRUDOperation, so .enabled needed a narrowing helper that throws if the object form ever stops being written — not a cast.
  • core / ActionRunner.test.ts. The "does not read the retired execute alias" case had a comment claiming ActionDef is open-ended. It has since been CLOSED (objectstack#4075 step 3), so authoring execute is now a compile error too; marked @ts-expect-error rather than cast, which pins the refusal in both directions.
  • app-shell / eight preview suites. {...(props as never)} spread never (TS2698). All eight previews take MetadataPreviewProps — the cast was pure noise that had never been checked. Replaced with the real props; PagePreview's six render sites gained the required type / name.
  • The empty-tuple mock family (12 across both packages). ReturnType< typeof vi.fn > resolves to the un-instantiated Mock< Procedure | Constructable >, and a zero-arity vi.fn(async () => …) infers Mock< () => … > whose mock.calls is the EMPTY tuple — so a good number of calls[0][0] assertions were reading element 0 of an empty tuple as far as the compiler was concerned. Each is now typed with the signature the slot it feeds declares (the convention tranche 4 established).
  • app-shell / deriveBoundPackageId.test.ts. Fixtures were built as ChatMessage and cast — and the legacy ChatMessage has NO properties in common with the structural minimum the function declares, so the cast was asserting between unrelated shapes. Now derived: Parameters< typeof deriveBoundPackageId >[0][number].
  • app-shell / FavoritesProvider.test.tsx. TS2578 "unused @ts-expect-error": one null as any element collapsed the whole array literal's element type to any, so the directive documenting a malformed item suppressed nothing. Narrowed the escape hatch to as unknown as FavoriteItem; the suppression is load-bearing again.
  • app-shell / ContextSelectors.scopeKey.test.tsx. Imported @object-ui/layout/NavigationRenderer — a subpath that resolves through no exports entry (the package declares only .). resolveHref is re-exported from the barrel, so this is the same symbol by its public name.
  • Four fixtures spelled locale="en" where SupportedLocale is 'en-US' | 'zh-CN'.

Discrimination proof (both packages)

Per #4291's ratchet, retiring a narrow project requires showing the full project really covers it. --listFiles on each test project, written to a file:

  • core — reads both files the narrow project named (dataset-result-field-spec-parity.test.ts, actionDef-closed-surface.test.ts), 2 of 576.
  • app-shell — reads all five (spec-symbol-parity.test.ts, resolveActionParams.test.ts, InspectorComboField.naming.types.test.tsx, flow-designer-edge.types.test.ts, flow-sim-edge.types.test.ts), of 3624.

Then a provably-false Assert< Equal< 1, 2 > > appended to each package's parity test, and the FULL project turns red:

core:      src/utils/__tests__/dataset-result-field-spec-parity.test.ts(150,23): error TS2344: Type 'false' does not satisfy the constraint 'true'.
app-shell: src/__tests__/spec-symbol-parity.test.ts(384,23): error TS2344: Type 'false' does not satisfy the constraint 'true'.

Both probes removed afterwards (git diff on those two files is empty in this PR).

app-shell also carried a type-check:typetests script that nothing else in the repo referenced; it is removed with the project it ran.

For whoever resolves a merge conflict here

Two files in this PR are conflict-prone, and they resolve by different rules:

  • scripts/check-type-check-coverage.mjs (the TEST_DEBT registry) — take main's registry, then re-apply the deletion of @object-ui/core and @object-ui/app-shell. Drop BOTH conflict sides of those lines; do not keep either. Then run node scripts/check-type-check-coverage.mjs — it must be green with both lines gone. @object-ui/plugin-dashboard's line must SURVIVE.
  • scripts/__tests__/check-type-check-coverage.test.ts (the named retired list) — resolve by UNION: keep both sides' package names, @object-ui/core and @object-ui/app-shell included. Its neighbouring terminal-state case (toEqual([])) is NOT a union merge — take this side, since the set really is empty once this lands.

Reminder from tranches 1–4: GitHub silently drops auto-merge when a PR becomes conflicting, with no notification. Re-arm it after resolving.

Verification

All green. Local runs are repo-root vitest with paths relative to the repo root (never pnpm --filter, never a cd into the package — both of those silently run somebody else's suite), batched under one acquisition of the shared verification lock.

$ vitest run packages/core/          Test Files  81 passed (81)     Tests  1706 passed (1706)
$ vitest run packages/app-shell/     Test Files 350 passed (350)    Tests  3339 passed | 1 skipped
$ turbo run type-check               Tasks: 78 successful, 78 total
$ turbo run lint (core, app-shell)   Tasks:  2 successful,  2 total
$ node scripts/check-control-bytes.mjs      OK (4082 tracked text files)
$ node scripts/check-changeset-presence.mjs OK (empty frontmatter = declared as releasing nothing)
$ node scripts/check-type-check-coverage.mjs
  type-check coverage: 43/45 via `type-check`, 1 via their own build, 0 known-broken, 1 not compiled.
  test type-check coverage: 39/40 packages compile their tests, 1 declared debt (6 errors
  outstanding), 0 with a narrow type-assertion project.

CI on this head: all 20 checks completed, every one success or skipped — Type Check, Lint, Test (shard 1–4/4) and Build & E2E all success.

The gate's own self-test needed a second commit — its premise expired here

scripts/__tests__/check-type-check-coverage.test.ts asserted withNarrow.length > 0, under a comment saying survivors were guaranteed while #4040 burned down. Tranche 5 is the point where that stops being true: retiring these two narrow projects takes the last ones, so the assertion was false by construction and the local run caught it red.

Rewritten to the terminal statement, expect(withNarrow.map(p => p.name)).toEqual([]), which is not vacuous in the direction that matters — a tsconfig.typetests.json reappearing anywhere turns it red, i.e. #4291's ratchet stated as a test rather than only as a gate rule. @object-ui/core and @object-ui/app-shell join the named retired list, the case that keeps carrying real weight. The sibling "holds each survivor" case is vacuous today by design and says so; it re-arms the moment the set is non-empty.

Reverse verification of the registry deletion

Driven through the gate's exported auditPackages() rather than by editing the file, so it could not race the batched gate run:

probe expected got
control — registry as shipped green 0 errors
core + app-shell re-added to TEST_DEBT red 2 errors — "type-checks its tests now — delete its TEST_DEBT entry"
core keeps a narrow typetests project red 1 error — "type-checks its whole test tree now, so its tsconfig.typetests.json is redundant"
plugin-dashboard's surviving entry deleted red 1 error — "has 41 test files that no tsc invocation reads"

The last row matters: it shows the control's green is not vacuous — the one entry this PR leaves behind is still load-bearing.

And for the rewritten self-test assertion, the same treatment with a synthetic narrow project injected into collect()'s output:

CONTROL (tree as shipped)                  -> []                          GREEN (expected)
PROBE (app-shell regrows a narrow project) -> ["@object-ui/app-shell"]    RED (expected)

Changeset: .changeset/core-app-shell-type-check-their-tests.md, empty frontmatter (no published behaviour moves), never major.

Refs #4040, #4291, #3181, #3009, #3968.


Generated by Claude Code

…rrow typetests projects (#4040)

`@object-ui/core` and `@object-ui/app-shell` — the last two large TEST_DEBT
packages — each gain a `tsconfig.test.json` chained from `type-check`, so their
81 and 350 test files are compiled by something for the first time. Measured at
the branch point: core 132 raw / 56 code-tier, app-shell 221 raw / 62 code-tier,
against registry entries declaring exactly 56 and 62 — the first tranche where
the declared numbers held, because they were the tranche-4 remeasurement rather
than the unreliable #2911-era sweep.

Config tier: `paths: {}` kills 39 + 121 TS6059 source-leaks; core needs
`types: ["node"]` (22 TS2591 + 13 TS2304 for `node:fs` / `__dirname` / `global`);
app-shell needs `lib: ES2022` (38 TS2550 for `calls.at(-1)`) plus
`vite/client` + `@testing-library/jest-dom`, raised in the TEST project only so
the package source keeps compiling against the baseline it ships to.

Three source declarations were narrower than their implementation, and only the
tests could see it. `ConsoleActionRuntime.actionProviderProps` hand-restated
ActionProvider's props and had drifted twice — it omitted `onModal`, which the
implementation returns, and typed `handlers` values as one-parameter functions;
it is now `Required<Pick<ActionProviderProps, …>>`, an explicit key list with
derived types. `apiHandler` declares the `context` parameter it has always
taken. `AiChatPage` imported the plugin barrel's minimal legacy `ChatMessage`
while producing the enhanced shape — the mismatch survived only because the
extra keys are spread conditionally, which defeats excess-property checking.

Substantive test fixes: `TransactionManager.test.ts` authored its fixtures in
the deprecated `crud.ts` `ActionSchema` while the manager takes `UIActionSchema`
(17 of core's 56); `schema-builder.test.ts` spelled columns `{ name, label }`,
a dialect `TableColumn` does not have, so the assertion round-tripped its own
input; eight app-shell preview suites spread `props as never`, a cast that had
never been checked; twelve mocks across both packages carried
`ReturnType<typeof vi.fn>` / zero arity, whose `mock.calls` is the empty tuple.

Per #4291's ratchet both narrow `tsconfig.typetests.json` projects retire here:
`--listFiles` shows the full projects read all 2 + 5 files they named, and a
provably-false `Assert` appended to each parity test turns the full project red.
app-shell's orphan `type-check:typetests` script goes with it.

TEST_DEBT is down to `@object-ui/plugin-dashboard` alone; the gate now reports
39/40 packages compiling their tests and 0 narrow type-assertion projects.

Refs #4040, #4291, #3181, #3009, #3968.
@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectui Ignored Ignored Aug 11, 2026 11:45pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 24.8 KB 350 KB
Entry file index-Akz1reEa.js
Status PASS

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 9.56KB 3.59KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 8.92KB 3.41KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 22.10KB 4.37KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.13KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.64KB 2.21KB
auth (SocialSignInButtons.js) 9.60KB 3.89KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 35.76KB 9.11KB
auth (createAuthenticatedFetch.js) 4.37KB 1.69KB
auth (index.js) 2.35KB 1.07KB
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) 4.91KB 0.87KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 26.07KB 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.65KB 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) 489.12KB 108.41KB
core (index.js) 2.99KB 1.14KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 151.72KB 40.42KB
fields (index.js) 228.37KB 56.62KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.32KB 1.77KB
i18n (index.js) 3.35KB 1.38KB
i18n (pickLocalized.js) 3.69KB 1.73KB
i18n (provider.js) 23.12KB 7.62KB
i18n (useDisplayLocale.js) 2.33KB 1.20KB
i18n (useObjectLabel.js) 27.59KB 6.63KB
i18n (useSafeTranslation.js) 7.77KB 3.13KB
layout (index.js) 38.98KB 10.85KB
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.74KB
mobile (index.js) 1.50KB 0.62KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.71KB 0.42KB
mobile (useResponsiveConfig.js) 1.36KB 0.63KB
mobile (useSpecGesture.js) 4.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 8.75KB 3.06KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.67KB 1.12KB
permissions (evaluator.js) 4.41KB 1.44KB
permissions (index.js) 0.91KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 1.55KB 0.71KB
plugin-ai (index.js) 15.71KB 3.79KB
plugin-calendar (index.js) 45.23KB 12.45KB
plugin-charts (index.js) 62.18KB 17.67KB
plugin-chatbot (index.js) 180.33KB 42.79KB
plugin-dashboard (index.js) 121.60KB 31.63KB
plugin-designer (index.js) 210.91KB 42.67KB
plugin-detail (index.js) 239.00KB 59.76KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 114.58KB 27.68KB
plugin-gantt (index.js) 164.14KB 39.98KB
plugin-grid (index.js) 188.00KB 49.94KB
plugin-kanban (index.js) 48.60KB 13.41KB
plugin-list (index.js) 110.10KB 26.74KB
plugin-map (index.js) 18.05KB 5.80KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 40.60KB 10.58KB
plugin-timeline (index.js) 26.21KB 7.52KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 84.03KB 20.55KB
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.71KB 3.53KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.67KB 2.37KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 23.71KB 7.96KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.23KB 0.66KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 4.09KB 1.74KB
sdui-parser (index.js) 4.47KB 2.03KB
sdui-parser (parse.js) 10.04KB 2.82KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 4.69KB 1.48KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.87KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-retry.js) 4.32KB 2.02KB
types (index.js) 3.05KB 1.52KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (spec-report.js) 5.05KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 3.40KB 1.71KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

…ad of "some remain" (#4040)

`check-type-check-coverage.test.ts` asserted `withNarrow.length > 0` under a
comment saying survivors were guaranteed while #4040 burned down. Tranche 5 is
where that premise expires: retiring `core`'s and `app-shell`'s narrow projects
takes the last two, so the assertion is false by construction.

Rewritten to the terminal statement — `expect(withNarrow.map(p => p.name))
.toEqual([])` — which is NOT vacuous in the direction that matters: a
`tsconfig.typetests.json` reappearing anywhere turns it red, i.e. #4291's
ratchet stated as a test and not only as a gate rule. Proved by driving
`collect()` with a synthetic narrow project on `app-shell`: control `[]`,
probe `["@object-ui/app-shell"]`.

The sibling "holds each survivor" case is now vacuous by design, and says so;
it re-arms the moment the set is non-empty again. `@object-ui/core` and
`@object-ui/app-shell` join the named `retired` list, which is the case that
keeps carrying real weight.

Refs #4040, #4291.
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 24.8 KB 350 KB
Entry file index-Akz1reEa.js
Status PASS

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 9.56KB 3.59KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 8.92KB 3.41KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 22.10KB 4.37KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.13KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.64KB 2.21KB
auth (SocialSignInButtons.js) 9.60KB 3.89KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 35.76KB 9.11KB
auth (createAuthenticatedFetch.js) 4.37KB 1.69KB
auth (index.js) 2.35KB 1.07KB
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) 4.91KB 0.87KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 26.07KB 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.65KB 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) 489.12KB 108.41KB
core (index.js) 2.99KB 1.14KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 151.72KB 40.42KB
fields (index.js) 228.37KB 56.62KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.32KB 1.77KB
i18n (index.js) 3.35KB 1.38KB
i18n (pickLocalized.js) 3.69KB 1.73KB
i18n (provider.js) 23.12KB 7.62KB
i18n (useDisplayLocale.js) 2.33KB 1.20KB
i18n (useObjectLabel.js) 27.59KB 6.63KB
i18n (useSafeTranslation.js) 7.77KB 3.13KB
layout (index.js) 38.98KB 10.85KB
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.74KB
mobile (index.js) 1.50KB 0.62KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.71KB 0.42KB
mobile (useResponsiveConfig.js) 1.36KB 0.63KB
mobile (useSpecGesture.js) 4.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 8.75KB 3.06KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.67KB 1.12KB
permissions (evaluator.js) 4.41KB 1.44KB
permissions (index.js) 0.91KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 1.55KB 0.71KB
plugin-ai (index.js) 15.71KB 3.79KB
plugin-calendar (index.js) 45.23KB 12.45KB
plugin-charts (index.js) 62.18KB 17.67KB
plugin-chatbot (index.js) 180.33KB 42.79KB
plugin-dashboard (index.js) 121.60KB 31.63KB
plugin-designer (index.js) 210.91KB 42.67KB
plugin-detail (index.js) 239.00KB 59.76KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 114.58KB 27.68KB
plugin-gantt (index.js) 164.14KB 39.98KB
plugin-grid (index.js) 188.00KB 49.94KB
plugin-kanban (index.js) 48.60KB 13.41KB
plugin-list (index.js) 110.10KB 26.74KB
plugin-map (index.js) 18.05KB 5.80KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 40.60KB 10.58KB
plugin-timeline (index.js) 26.21KB 7.52KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 84.03KB 20.55KB
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.71KB 3.53KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.67KB 2.37KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 23.71KB 7.96KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.23KB 0.66KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 4.09KB 1.74KB
sdui-parser (index.js) 4.47KB 2.03KB
sdui-parser (parse.js) 10.04KB 2.82KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 4.69KB 1.48KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.87KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-retry.js) 4.32KB 2.02KB
types (index.js) 3.05KB 1.52KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (spec-report.js) 5.05KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 3.40KB 1.71KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

Copy link
Copy Markdown
Collaborator Author

ACCEPT — PM 复核 (session session_017Qqyix2QcnpUC9XeYVDzx3), tranche 5 of #4040 (Part of, not closing — plugin-dashboard's 6 remain by design).

  • Both packages graduate with the full ladder: pre-fix reds captured to files (raw 132/221, config-tier 76/159, file-tier 11/33), both source projects proven unchanged, repo-wide type-check 78/78, both narrow typetests projects retired per chore(type-check): retire the narrow typetests projects in graduated packages (#4291) #4345's ratchet, handlers item done as Required<Pick<ActionProviderProps, …>> — derivation over restatement, and the loud-break coupling it creates is the intended direction.
  • The self-test rewrite is the correct terminal-tranche shape: the withNarrow.length > 0 premise expired by construction here, and the replacement toEqual([]) was proved non-vacuous with a synthetic probe (control [], probe naming the package). Running reverse verification through the gate's exported auditPackages() rather than file mutation — because the lock-held batch would have raced — is accepted as the better method, not a shortcut.
  • For future conflict resolvers, this PR refines the standing rule and the refinement is now canonical: registry = drop both sides, re-apply deletion; retired-names list = union; the terminal toEqual([]) case = take THIS side (it is not a union). Written in the PR body; recorded here so it survives the body.
  • Sequencing note accepted: when plugin-dashboard's final tranche lands, the ratchet's debt-zero consequence must be handled in that PR, not this one.
  • The unfiled plugin-chatbot ChatMessage type collision is being filed by the PM as a finding — the report's reason for not filing (another agent's surface) no longer holds; no live task owns plugin-chatbot.

Flipping ready + arming auto-merge. Landing this opens #4373's gate (its other gate, #4374, already landed) and frees app-shell for #4377.


Generated by Claude Code

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