Skip to content

chore(type-check): retire the narrow typetests projects in graduated packages (#4291) - #4345

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-4291-retire-narrow-typetests
Aug 11, 2026
Merged

chore(type-check): retire the narrow typetests projects in graduated packages (#4291)#4345
yinlianghui merged 1 commit into
mainfrom
claude/issue-4291-retire-narrow-typetests

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Closes#4291. Follow-up to #4040 tranche 1; refs #3032, objectstack-ai/objectstack#4118.

tsconfig.typetests.json is the #3181 rescue hatch: a package whose test tree was still in scripts/check-type-check-coverage.mjs's TEST_DEBT could compile the one file whose whole value is compile-time assertions — an Assert< Equal< Local, Spec > > is a tsc error or it is nothing — instead of waiting for its whole backlog to compile. As #4040's tranches landed full tsconfig.test.json projects, that hatch went redundant wherever the package graduated: the full project already compiles the same file, so the repo carried two spellings of what gets compiled, plus one extra tsc per type-check run.

Six packages had graduated. All six are retired here, with the narrow project deleted and its type-check chain entry removed.

Inventory

main carried 10 narrow projects. Classification, from TEST_DEBT at 78fa331:

PackageFull tsconfig.test.jsonIn TEST_DEBTVerdict
authyesnoretired
plugin-chatbotyesnoretired
plugin-detailyesnoretired
plugin-formyesnoretired
plugin-gridyesnoretired
plugin-listyesnoretired
app-shellnoyes (53 errors)kept
componentsnoyes (31 errors)kept
corenoyes (72 errors)kept
reactnoyes (27 errors)kept

The fifth TEST_DEBT entry, plugin-dashboard (6 errors), never had a narrow project. The four kept ones are untouched — no file, no script, no comment.

Coverage proof, per retired package

For each, tsc -p tsconfig.test.json --listFiles was written to a file and that file grepped for the absolute path of the file the narrow project named (never piped through head — SIGPIPE would truncate the compiler). All six: exactly one match.

PackageFile the narrow project namedRead by the full project
authsrc/__tests__/auth-spec-parity.test.tsyes (1 of 1096 files)
plugin-chatbotsrc/__tests__/spec-symbol-batch6.test.tsyes (1 of 1947)
plugin-detailsrc/__tests__/spec-symbol-batch7.test.tsyes (1 of 1718)
plugin-formsrc/__tests__/spec-symbol-batch7.test.tsxyes (1 of 1549)
plugin-gridsrc/__tests__/spec-symbol-batch7.test.tsyes (1 of 1684)
plugin-listsrc/__tests__/spec-symbol-batch6.test.tsxyes (1 of 1558)

Being in the program is not the same as being enforced, so each was also discriminated: append a provably-false assertion in the file's own vocabulary (type _Probe4291 = Assert< Equal< 1, 2 > >;), run the FULL project, revert. All six went red — coverage moved, it did not vanish.

auth src/__tests__/auth-spec-parity.test.ts(277,26): error TS2344 exit=2
plugin-chatbot src/__tests__/spec-symbol-batch6.test.ts(335,26): error TS2344 exit=2
plugin-detail src/__tests__/spec-symbol-batch7.test.ts(89,26): error TS2344 exit=2
plugin-form src/__tests__/spec-symbol-batch7.test.tsx(78,26): error TS2344 exit=2
plugin-grid src/__tests__/spec-symbol-batch7.test.ts(124,26): error TS2344 exit=2
plugin-list src/__tests__/spec-symbol-batch6.test.tsx(254,26):error TS2344 exit=2

Type 'false' does not satisfy the constraint 'true' in every case. The probes were appended and reverted one package at a time; git status was empty afterwards.

The environment the file is compiled in is equal or wider

Retiring a project is only sound if the surviving one does not check the file more weakly. Both projects extends the same root tsconfig.json, and neither overrides any strictness flag, so strict and friends are identical by construction. The only differing options are lib / types / jsx / paths, and in every case the full project is a superset or an exact match:

  • auth, plugin-chatbot, plugin-detail: narrow pinned lib: ["ES2020","DOM"]; the full project inherits the root's ["ES2020","DOM","DOM.Iterable"].
  • plugin-grid (["ES2022","DOM"]) and plugin-list (["ES2022","DOM","DOM.Iterable"]) sit one notch above the narrow project's ES2020.
  • types: four full projects add @testing-library/jest-dom on top of the narrow ["node"]; plugin-detail and plugin-list match it exactly.
  • jsx: plugin-detail / plugin-list inherit the root's react-jsx, which is what the narrow project set explicitly.
  • paths: {} on both sides everywhere except plugin-detail, whose full project adds one narrow @object-ui/fields/widgets/* alias (see @object-ui/fields deep subpaths resolve only through the repo vitest alias — its exports map publishes none of them #4325) — an addition the guard file does not use.

A wider lib cannot make a spec-parity assertion pass that previously failed; it only adds globals the guard file never references.

The ratchet — so the seventh cannot appear

The count in the gate's summary line is computed, not hardcoded, so it moved on its own from 10 with a narrow type-assertion project to 4. But nothing stopped a future graduating package from leaving its narrow project behind and re-creating this exact cleanup, so section 5½ gains the invariant its own header already stated in prose:

A package whose test tree is still in TEST_DEBT can rescue those specific files with a tsconfig.typetests.json [...]

A narrow project on a package where testsCovered is already true is now an error. testsCovered is true only when every test file the build program skips is read by the chained tsconfig.test.json — which necessarily includes whichever file the narrow project names, so the redundancy is proven rather than assumed. Declared is now enforced.

Reverse verification of the new rule — auth's narrow project and chain entry restored on top of this branch:

❌ type-check coverage regressed:
• @object-ui/auth (packages/auth) type-checks its whole test tree now, so its tsconfig.typetests.json
is redundant: every file it names is already compiled by the tsconfig.test.json chained
off "type-check". Delete the narrow project and its "type-check" chain entry — keeping
both is a second spelling of what gets compiled, and one extra tsc per run (objectui#4291).
It exists only as a rescue hatch for a package still in TEST_DEBT.
EXIT=1

Reverted; the gate is green on this branch.

Section 5½ had no tests at all

Grepping the gate's own suite for typetests returned nothing: the section that keeps the rescue hatch honest was itself unchecked — the same shape as the defect it exists to report. It now has three fixture tests (redundant-once-graduated; still-allowed-while-in-debt; the pre-existing never-runs case, pinned for the first time) and a real-repository block that holds every surviving narrow project to testsCovered === false and names the six retired here.

Verification

  • node scripts/check-type-check-coverage.mjs — green, before and after. Test-coverage line unchanged at 35/40 packages compile their tests, 5 declared debt (189 errors outstanding), narrow projects 10 to 4.
  • Both surviving tsc commands, per retired package, after the retirement — 12 invocations, all exit 0:
auth tsc --noEmit=0 tsc -p tsconfig.test.json=0
plugin-chatbot tsc --noEmit=0 tsc -p tsconfig.test.json=0
plugin-detail tsc --noEmit=0 tsc -p tsconfig.test.json=0
plugin-form tsc --noEmit=0 tsc -p tsconfig.test.json=0
plugin-grid tsc --noEmit=0 tsc -p tsconfig.test.json=0
plugin-list tsc --noEmit=0 tsc -p tsconfig.test.json=0
  • vitest run over the gate suite and all five touched guard files — Test Files 6 passed (6), Tests 70 passed (70).
  • eslint over every changed file — 0 errors (67 pre-existing warnings, all no-unused-vars on the compile-time pin aliases, which is what those aliases are).
  • Changeset: empty frontmatter. Only type-check scripts, checking-only tsconfig projects, test-file comments and a CI gate change; nothing published moves.

Note on comment edits inside five guard files

Five guard files carried a header naming the project this PR deletes (Compiled by this package's tsconfig.typetests.json), and three of those also claimed this package's test tree is still in TEST_DEBT — already false on main since #4040. Deleting the project without touching them would ship a comment pointing at a file that no longer exists, in the very PR that removes it. They are retargeted at tsconfig.test.json; the changes are comment-only, no assertion or fixture touched. plugin-list's historical note about the && short-circuit that hid #4163 is kept as history, with its tense corrected from present to past.


Generated by Claude Code

…packages (#4291)
`tsconfig.typetests.json` is the objectui#3181 rescue hatch: a package whose
test tree was still in `check-type-check-coverage.mjs`'s TEST_DEBT could
compile the one file whose whole value is compile-time assertions, instead of
waiting for its whole backlog. As #4040's tranches landed full
`tsconfig.test.json` projects, the hatch went redundant wherever the package
graduated — the full project already compiles the same file, so the repo
carried two spellings of what gets compiled plus one extra tsc per run.
Retired in auth, plugin-chatbot, plugin-detail, plugin-form, plugin-grid and
plugin-list, each with its `type-check` chain entry. Per package, the full
project's `--listFiles` was checked to contain the exact file the narrow
project named, and a provably-false `Assert` appended to that file turned the
FULL project red (TS2344, exit 2) — the coverage moved rather than vanished.
app-shell, components, core and react are still in TEST_DEBT and keep theirs.
The gate now makes this a ratchet rather than a one-time sweep: a narrow
project on a package whose full test project already compiles everything is
reported as redundant, so the seventh cannot reappear. Section 5½ had no test
coverage at all — the gate keeping the rescue hatch honest was itself
unchecked — so it gains a fixture suite plus a real-repository pin.
Refs #4040, #3032, objectstack-ai/objectstack#4118
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
@vercel

vercelBot commented Aug 11, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectuiIgnoredIgnoredAug 11, 2026 6:59pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)29.6 KB350 KB
Entry fileindex-B5AY1MND.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.56KB3.59KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)22.10KB4.37KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)35.76KB9.11KB
auth (createAuthenticatedFetch.js)4.37KB1.69KB
auth (index.js)2.35KB1.07KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)4.91KB0.87KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)489.12KB108.41KB
core (index.js)3.04KB1.15KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)150.04KB39.79KB
fields (index.js)228.37KB56.62KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.32KB1.77KB
i18n (index.js)3.35KB1.38KB
i18n (pickLocalized.js)1.70KB0.83KB
i18n (provider.js)23.12KB7.62KB
i18n (useDisplayLocale.js)2.33KB1.20KB
i18n (useObjectLabel.js)27.59KB6.63KB
i18n (useSafeTranslation.js)4.52KB1.96KB
layout (index.js)38.98KB10.85KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)8.75KB3.06KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)3.67KB1.12KB
permissions (evaluator.js)4.41KB1.44KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.55KB0.71KB
plugin-ai (index.js)15.71KB3.79KB
plugin-calendar (index.js)45.23KB12.45KB
plugin-charts (index.js)62.18KB17.67KB
plugin-chatbot (index.js)180.33KB42.79KB
plugin-dashboard (index.js)121.56KB31.56KB
plugin-designer (index.js)210.91KB42.67KB
plugin-detail (index.js)238.95KB59.76KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)114.58KB27.68KB
plugin-gantt (index.js)164.14KB39.98KB
plugin-grid (index.js)188.00KB49.94KB
plugin-kanban (index.js)48.60KB13.41KB
plugin-list (index.js)110.10KB26.74KB
plugin-map (index.js)18.05KB5.80KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)40.60KB10.58KB
plugin-timeline (index.js)26.21KB7.52KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.03KB20.55KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.71KB3.53KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.67KB2.37KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)23.71KB7.96KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.23KB0.66KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)4.09KB1.74KB
sdui-parser (index.js)4.47KB2.03KB
sdui-parser (parse.js)10.04KB2.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)4.69KB1.48KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.05KB1.52KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@yinlianghui
yinlianghui marked this pull request as ready for review August 11, 2026 19:12
@yinlianghui
yinlianghui added this pull request to the merge queueAug 11, 2026
Merged via the queue into main with commit ae6bb3aAug 11, 2026
21 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-4291-retire-narrow-typetests branch August 11, 2026 19:13
Sign up for freeto 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.

Retire the narrow per-file tsconfig.typetests.json projects in packages that have graduated out of TEST_DEBT

2 participants

@yinlianghui@claude