Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

Commit 7c83e70

Browse files
test(cutover-prep F): ui tests pay the first load of the specifiers check:test-source-alias names at module scope (objectstack#25763) (#13513)
<!-- claude-projects-attribution: {"github_login":"os-tesla"} --> _Requested by **Tesla** · [project thread](https://claude.ai/code/project/chan_01AXsQkLFKRdQCqQ3RTr6Jao?thread=cmsg_01AXsQkLFKRdQCqQ3RTr6JaoHZM3TyZPr2yRmDU4cH4TJH)_ Part of objectstack#25763 (cutover prep F of the objectui → objectstack `ui/` merge). Part of objectstack#25677. Clause-②: no Metadata-protocol: none ## What changes In the merged tree every `@objectstack/*` import in a ui test resolves to a workspace package's `dist`, so a first load paid inside a test body, a `vi.mock` factory or after `vi.resetModules()` bills a cold transform to a clocked window (verify runs 8 and 11 reddened Test UI 3/16 on exactly this shape). objectstack's `check:test-source-alias` names these sites. Each of the 26 files below now also loads the same specifier with a module-scope side-effect import, so the transform is paid during collection, which vitest clocks against nothing. Every dynamic import stays where it was: this only decides where the first load is paid. No timeout is widened, nothing is skipped, and no production code changes. The changeset is empty-frontmatter (test-only, releases nothing). The 30 findings fall in three shapes, each with its own one-line comment in the file: - **in a test body or a helper a test awaits** (13 files): `@objectstack/spec`, `spec/ui`, `spec/data`, `spec/api`, `spec/kernel`, `spec/system`, `spec/security`, `spec/integration`, `@objectstack/formula`, `@object-ui/components`; - **inside a `vi.mock` factory** (10 files): `@object-ui/i18n/locales`, `@object-ui/react`, `@object-ui/components`; - **re-imported after each `vi.resetModules()`** (3 files, `@object-ui/core`): the reset re-evaluates, but the transform is cached, so warming it once moves the compile out of every clocked re-import. `DraftChangesPanel.securityProblems.test.tsx` is 2c round 2 (a)'s (objectstack#25727) and is not touched; the gate does not list it on this tree either. ## Gate reading on the merged layout Verify branch `claude/project-thread-dwhq6r-25697-verify` head `9e37acd126`, this diff applied with `git apply --directory=ui` (applies clean: all 33 named files are byte-identical between that tree's `ui/` and objectui `main` `0063f22ce`). `node scripts/check-test-source-alias.mjs`: | | before | after | |---|---|---| | function-body lines printed under `ui/` | 57 | 12 | | unique (file, specifier) findings | 37 | 7 | | real findings (a runtime load) | 30 | **0** | | every other line of the gate's output | — | byte-identical to before | ### Gate false positives, left untouched (see objectstack#25766) These 7 never load anything at run time, so there is no cost to warm; adding a side-effect import would add a load these files do not pay today. The gate reads them because its type-query check knows only `typeof`, and its import pattern runs over a projection that still holds string content. - `packages/plugin-calendar/src/__tests__/spec-symbol-4650.test.ts`, type alias under a `@ts-expect-error` tripwire - `packages/plugin-form/src/__tests__/spec-symbol-4650.test.ts`, same - `packages/plugin-grid/src/__tests__/spec-symbol-4650.test.ts`, same - `packages/plugin-kanban/src/__tests__/spec-symbol-4650.test.ts`, same (the four headers explain why the inline type-level form is deliberate) - `packages/types/src/__tests__/dashboard-global-filters-spec-binding.test.ts`, type alias - `packages/components/src/renderers/complex/__tests__/data-table.test.ts`, type annotation - `scripts/__tests__/check-spec-range-floors.test.ts`, text inside a template-literal fixture ## Timing, before and after The 26 touched files, run as one set (`vitest run` on those paths, json reporter), once per cell on a 4-vCPU box under the shared verify lock. Merged layout = the tree above after the CI build of the seven `@objectstack` packages, run from `ui/` with `--root .`; standalone = this branch after `pnpm run setup`. Both before and after: 26 files, 342 tests, all passed. | | merged before | merged after | standalone before | standalone after | |---|---|---|---|---| | vitest "tests" (summed across files, s) | 173.88 | 164.70 | 161.17 | 151.87 | | vitest "import" (collection, s) | 175.03 | 190.95 | 133.82 | 138.96 | | wall duration (s) | 135.99 | 138.08 | 117.33 | 114.44 | The cost moved from the clocked "tests" phase into the unclocked import phase, which is the point. Single runs on a shared box, so differences of a few hundred ms on one file are noise. The clear per-file moves are in the slowest-test column: | file | findings before → after | slowest test, merged before → after (ms) | file test time, merged before → after (ms) | file test time, standalone before → after (ms) | |---|---|---|---|---| | `apps/console/src/__tests__/masterDetailFormTypeManifest.test.ts` | 1 → 0 | 3 → 3 | 9 → 11 | 11 → 16 | | `packages/app-shell/src/__tests__/spec-symbol-parity.test.ts` | 1 → 0 | 3 → 4 | 10 → 14 | 24 → 15 | | `packages/app-shell/src/console/__tests__/AppContent.deniedVsUnpublished.test.tsx` | 1 → 0 | 113 → 96 | 720 → 767 | 608 → 653 | | `packages/app-shell/src/hooks/__tests__/useConsoleActionRuntime.flowRowGuard-13397.test.tsx` | 1 → 0 | 31 → 32 | 105 → 102 | 111 → 140 | | `packages/app-shell/src/views/ObjectView.listLinksPlural-11733.test.tsx` | 1 → 0 | 204 → 184 | 697 → 545 | 500 → 665 | | `packages/app-shell/src/views/RecordDetailView.paramRuntimeParity-6431.test.tsx` | 1 → 0 | 97 → 100 | 566 → 600 | 532 → 644 | | `packages/app-shell/src/views/metadata-admin/MetadataTypeActions.paramDialogClose-6473.test.tsx` | 1 → 0 | 357 → 364 | 715 → 760 | 656 → 670 | | `packages/app-shell/src/views/metadata-admin/ResourceEditPage.requiredInGatedSection-6900.test.tsx` | 1 → 0 | 994 → 912 | 4749 → 4493 | 4229 → 3975 | | `packages/app-shell/src/views/metadata-admin/clientValidation.optOuts.test.ts` | 5 → 0 | 848 → 11 | 1251 → 56 | 555 → 44 | | `packages/app-shell/src/views/metadata-admin/clientValidation.retiredFormulaKey.test.ts` | 1 → 0 | 7161 → 1948 | 8077 → 2008 | 1170 → 1347 | | `packages/app-shell/src/views/metadata-admin/inspectors/ViewVariantInspector.requiredInGatedSection-6900.test.tsx` | 1 → 0 | 536 → 638 | 2177 → 2461 | 2389 → 1824 | | `packages/app-shell/src/views/studio-design/DataPillar.addFieldPopover-12516.test.tsx` | 1 → 0 | 2127 → 2086 | 6589 → 6457 | 6521 → 6650 | | `packages/app-shell/src/views/studio-design/DataPillar.formToolbar-12451.test.tsx` | 1 → 0 | 530 → 578 | 1119 → 1067 | 1205 → 1093 | | `packages/app-shell/src/views/studio-design/DataPillar.gridProjection.test.tsx` | 1 → 0 | 481 → 768 | 595 → 917 | 755 → 565 | | `packages/app-shell/src/views/studio-design/DataPillar.picklistServedOptions-10202.test.tsx` | 1 → 0 | 2666 → 2850 | 2804 → 3022 | 2866 → 2835 | | `packages/app-shell/src/views/studio-design/StudioDesignSurface.autosaveInFlight-11204.test.tsx` | 1 → 0 | 6006 → 6112 | 30663 → 30220 | 30119 → 30270 | | `packages/app-shell/src/views/studio-design/StudioDesignSurface.autosaveSwitch-11232.test.tsx` | 1 → 0 | 6723 → 6860 | 70743 → 70922 | 70562 → 70445 | | `packages/app-shell/src/views/studio-design/StudioDesignSurface.draftVersionConflict-11773.test.tsx` | 1 → 0 | 5311 → 5355 | 27022 → 27192 | 26673 → 26866 | | `packages/auth/src/__tests__/auth-spec-parity.test.ts` | 1 → 0 | 359 → 94 | 478 → 96 | 188 → 108 | | `packages/plugin-calendar/src/__tests__/ObjectCalendar.dataObjectArmRefused-8348.test.tsx` | 1 → 0 | 79 → 65 | 163 → 113 | 130 → 114 | | `packages/plugin-dashboard/src/__tests__/ObjectMetricWidget.i18nLabel.test.tsx` | 1 → 0 | 111 → 85 | 355 → 292 | 274 → 379 | | `packages/plugin-grid/src/__tests__/gridBareArrayDataRefused-8348.test.tsx` | 1 → 0 | 137 → 107 | 441 → 380 | 398 → 410 | | `packages/react/src/__tests__/SchemaRenderer.concealmentGateFaultDiagnostic.test.tsx` | 1 → 0 | 1045 → 369 | 3787 → 2973 | 1065 → 512 | | `packages/react/src/__tests__/SchemaRenderer.disabledGateFaultDiagnostic.test.tsx` | 1 → 0 | 1066 → 423 | 5952 → 5784 | 8207 → 838 | | `packages/react/src/__tests__/SchemaRenderer.productionPredicateFaultWarning.test.tsx` | 1 → 0 | 1103 → 426 | 3792 → 3112 | 1038 → 490 | | `packages/types/src/__tests__/registry-meta-carry-9102.test.ts` | 1 → 0 | 54 → 58 | 191 → 220 | 273 → 206 | | **total (26 files)** | 30 → 0 | | 173770 → 164584 | 161059 → 151774 | `clientValidation.retiredFormulaKey` on the merged layout shows the bill-24 shape at small scale. Its first test went from 903 to 41 ms, and its `expression`-draft test from 7161 to 1948 ms. The remaining 1.9 s is not a load the gate attributes to this file, so this card leaves it alone (not investigated further). ## Verification record (exit codes) objectui standalone, this branch after `pnpm run setup`: | gate | exit | |---|---| | `pnpm exec vitest run` on the 26 touched files (342 tests) | 0 | | `pnpm exec turbo run type-check` for the 8 touched packages (app-shell, auth, console, plugin-calendar, plugin-dashboard, plugin-grid, react, types; 43 tasks incl. each package's `tsconfig.test.json` and `type-check:e2e`) | 0 | | `pnpm exec eslint` on the changed files | 0 errors; 72 warnings, the same 72 as the base versions of those files | | `node scripts/check-changeset-presence.mjs` | 0 | | `node scripts/check-changeset-overwrite.mjs` | 0 | | `node scripts/check-changeset-no-major.mjs` | 0 | | `pnpm check:changeset-claims` | 0 | | `pnpm check:new-line-citations` | 0 | | `pnpm check:control-bytes` | 0 | | `pnpm check:test-path-roots` | 0 | Merged layout (verify head `9e37acd126` plus this diff): | step | exit | |---|---| | `git apply --check --directory=ui` | 0 | | `pnpm install --frozen-lockfile` | 0 | | CI build of the seven `@objectstack` packages (36 tasks) | 0 | | `vitest run --root .` from `ui/` on the 26 touched files (342 tests) | 0 | | `node scripts/check-test-source-alias.mjs` | 1, as on the base: the 7 false positives above plus the alias-half findings, which belong to the cutover adaptation commit; no real function-body finding left | - [x] Adds no product-specific widget, dialog, hook or string (see AGENTS.md › Product-neutral renderer) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Session: `https://claude.ai/code/session_01N1dH2ywuFXe38A89awucwV` Co-authored-by: Claude <noreply@anthropic.com>
1 parent d12c615 commit 7c83e70

27 files changed

Lines changed: 89 additions & 0 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
---
3+
4+
Test-only change: the test files that `check:test-source-alias` named now load, at module scope, the `@objectstack/*` / `@object-ui/*` specifiers they otherwise first load inside a test body, a `vi.mock` factory or after `vi.resetModules()`, so the cold transform is paid during collection instead of inside a clocked window (objectstack#25763). No published behaviour changes.

‎apps/console/src/__tests__/masterDetailFormTypeManifest.test.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
* papering over it, so this file cannot be read as "the hole is closed".
2525
*/
2626
import { describe, it, expect } from 'vitest';
27+
// Module scope as well as where a test awaits it below: the cold transform is paid
28+
// during collection, which no test or hook timeout clocks (AGENTS.md, flaky-test discipline).
29+
import '@objectstack/spec/ui';
2730
import { ComponentRegistry } from '@object-ui/core';
2831
import { manifestFromConfigs, validateTree } from '@object-ui/sdui-parser';
2932
import type { Diagnostic, SchemaElement } from '@object-ui/sdui-parser';

‎packages/app-shell/src/__tests__/spec-symbol-parity.test.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@
7474
*/
7575

7676
import { describe, it, expect } from 'vitest';
77+
// Module scope as well as where a test awaits it below: the cold transform is paid
78+
// during collection, which no test or hook timeout clocks (AGENTS.md, flaky-test discipline).
79+
import '@objectstack/spec';
7780
import ts from 'typescript';
7881
import { createRequire } from 'node:module';
7982
import { readFileSync } from 'node:fs';

‎packages/app-shell/src/console/__tests__/AppContent.deniedVsUnpublished.test.tsx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@
7979

8080
import '@testing-library/jest-dom/vitest';
8181
import { describe, it, expect, vi, beforeEach } from 'vitest';
82+
// Module scope as well as in the `vi.mock` factory below: the cold transform is paid
83+
// during collection, which no test or hook timeout clocks (AGENTS.md, flaky-test discipline).
84+
import '@object-ui/i18n/locales';
8285
import React from 'react';
8386
import { render, screen, waitFor } from '@testing-library/react';
8487
import { MemoryRouter, Routes, Route, useLocation, useNavigate } from 'react-router-dom';

‎packages/app-shell/src/hooks/__tests__/useConsoleActionRuntime.flowRowGuard-13397.test.tsx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
*/
2121

2222
import { describe, it, expect, beforeEach, vi } from 'vitest';
23+
// Module scope as well as in the `vi.mock` factory below: the cold transform is paid
24+
// during collection, which no test or hook timeout clocks (AGENTS.md, flaky-test discipline).
25+
import '@object-ui/i18n/locales';
2326
import { render, screen, fireEvent, waitFor, renderHook, act } from '@testing-library/react';
2427
import React from 'react';
2528

‎packages/app-shell/src/views/ObjectView.listLinksPlural-11733.test.tsx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535

3636
import * as React from 'react';
3737
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
38+
// Module scope as well as in the `vi.mock` factory below: the cold transform is paid
39+
// during collection, which no test or hook timeout clocks (AGENTS.md, flaky-test discipline).
40+
import '@object-ui/react';
3841
import { render, cleanup, screen, fireEvent } from '@testing-library/react';
3942
import { MemoryRouter, Routes, Route, useLocation } from 'react-router-dom';
4043
import { createI18n, I18nProvider } from '@object-ui/i18n';

‎packages/app-shell/src/views/RecordDetailView.paramRuntimeParity-6431.test.tsx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@
8080

8181
import * as React from 'react';
8282
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
83+
// Module scope as well as where a test awaits it below: the cold transform is paid
84+
// during collection, which no test or hook timeout clocks (AGENTS.md, flaky-test discipline).
85+
import '@object-ui/components';
8386
import { render, screen, waitFor, act, cleanup, fireEvent } from '@testing-library/react';
8487
import { MemoryRouter } from 'react-router-dom';
8588

‎packages/app-shell/src/views/metadata-admin/MetadataTypeActions.paramDialogClose-6473.test.tsx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ import path from 'node:path';
6767
import { readFileSync } from 'node:fs';
6868
import { fileURLToPath } from 'node:url';
6969
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
70+
// Module scope as well as where a test awaits it below: the cold transform is paid
71+
// during collection, which no test or hook timeout clocks (AGENTS.md, flaky-test discipline).
72+
import '@object-ui/components';
7073
import { render, screen, act, cleanup, fireEvent } from '@testing-library/react';
7174

7275
vi.mock('@object-ui/auth', async (importOriginal) => ({

‎packages/app-shell/src/views/metadata-admin/ResourceEditPage.requiredInGatedSection-6900.test.tsx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838
import '@testing-library/jest-dom/vitest';
3939
import * as React from 'react';
4040
import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
41+
// Module scope as well as where a test awaits it below: the cold transform is paid
42+
// during collection, which no test or hook timeout clocks (AGENTS.md, flaky-test discipline).
43+
import '@objectstack/formula';
4144
import { render, screen, fireEvent, cleanup, waitFor, act } from '@testing-library/react';
4245
import { MemoryRouter } from 'react-router-dom';
4346

‎packages/app-shell/src/views/metadata-admin/clientValidation.optOuts.test.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@
3636
*/
3737

3838
import { describe, it, expect } from 'vitest';
39+
// Module scope as well as where a test awaits it below: the cold transform is paid
40+
// during collection, which no test or hook timeout clocks (AGENTS.md, flaky-test discipline).
41+
import '@objectstack/spec';
42+
import '@objectstack/spec/integration';
43+
import '@objectstack/spec/kernel';
44+
import '@objectstack/spec/security';
45+
import '@objectstack/spec/system';
3946
import { arrayElementSchema } from '@object-ui/test-support';
4047
import { validateMetadataDraft, hasClientValidator } from './clientValidation';
4148

0 commit comments

Comments
 (0)