test: load package barrels at module top so the collect phase pays for them - #21480
Merged
objectstack-fleet[bot] merged 2 commits intoOct 2, 2026
Merged
Conversation
…r them Five test cases loaded a package barrel with a dynamic import inside the case, which charges the whole index graph's load to vitest's per-case 5000ms budget; one of them was measured timing out on a loaded box. Each barrel is now loaded at module top, as the core precedent service-resolution-discriminator.contract.test.ts already does, so the load is charged to the collect phase and the cases assert behaviour only. - objectql system-write-organization: static namespace import of the barrel. - core security/platform-admin: static namespace import of the security entry. - lint validate-predicate-path-refs: static namespace import of the barrel. - plugin-sharing translations/serving-seam: the committed barrel is a static import; the moved-source barrel is evaluated at module top (resetModules, doMock, import, doUnmock), which replaces the per-case beforeEach. - lint lazy-deps keeps its in-case import (the load is its subject), now with a one-line note saying so. No timeout, retry, skip, config or source change. Claude-Session: https://claude.ai/code/session_01DDZNkDVwPQnevTFcYE47H3 Co-authored-by: Claude <noreply@anthropic.com>
…rrel-import-collect-phase
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
This was referenced Oct 2, 2026
objectstack-fleet
Bot
deleted the
claude/issue-21457-barrel-import-collect-phase
branch
October 2, 2026 23:14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #21457
Clause-②: no
What this changes
Five test files, test-only. Every case that loaded a package barrel with a dynamic import inside its body now gets that barrel from a module-top load, so the load is charged to vitest's collect phase instead of the case's 5000ms window (AGENTS.md: 「Clocked windows measure behaviour, never loading」). The shape and the reasoning are the core precedent's,
packages/core/src/service-resolution-discriminator.contract.test.ts; no helper was added. No timeout, retry, skip,vitest.config.ts, source or gate change.7e7e64b1)packages/objectql/src/system-write-organization.test.ts:506import * as barrel from './index.js'at module top; the case is now synchronous and still asserts, by identity, that both names come from the barrelpackages/core/src/security/platform-admin.test.ts:279import * as securityEntry from './index.js'at module top; the case still probes presence and absence on the security entrypackages/lint/src/validate-predicate-path-refs.test.ts:376import * as barrel from './index.js'at module toppackages/plugins/plugin-sharing/src/translations/serving-seam.test.ts:86and:100packages/lint/src/lazy-deps.test.ts:190The one site where the hoist was not mechanical:
serving-seam.test.tsHoisting changed what this file observes, so it was not a plain move. The
:86case evaluated the barrel against a MOVED source: abeforeEachranvi.resetModules(), then the case ranvi.doMock('./en.objects.generated.js', ...)and imported the barrel. A static import cannot be mocked per case. The resolution keeps each assertion's meaning::100("substitutes nothing while the source has not moved") reads a staticimport { SharingTranslations } from './index.js', which is the barrel as committed.:86("SERVES the current source when the source moves under the recorded leaf") readsservedAfterSourceMoved. That value is produced at module top by the same four steps thebeforeEachand the case used to perform:vi.resetModules(),vi.doMock(...),await import('./index.js'),vi.doUnmock(...). A top-level await in a test module runs during collection; the repo already uses that shape inpackages/cli/test/score-lint-crash.test.tsandpackages/mcp/src/__tests__/plugin-execution-context.test.ts.beforeEachis removed. It existed only to isolate the two in-case imports, and no case imports anything now.So one
await import('./index.js')remains in that file, at column 0 at module top and not inside a case. The triage pin is about loads inside a case.Ablation (one-time, on the committed tree,
scripts/ablation-replace.mjsin WRAP mode with its own restore proof): deleting the module-topvi.resetModules();turns exactly the:86case red,AssertionError: expected 'Token' to be 'Share token', with 1 failed and 4 passed. Without the reset, the import returns the copy the static import cached. The restore was proven: blob9d8e14d9fe22equals HEAD's, andgit diff HEADis empty.Measured
Every reading was taken on this container's shared box. Other agents' work ran alongside, and the verify lock excluded only other locked runs, so the absolute numbers are shared-box seconds. The signal is the per-case drop.
Per-case duration, run alone (one file plus
-t, vitest JSON reporter; the number in brackets is the same case in a whole-file run):7e7e64b1)8e8b3bb6):86:100In the package's whole suite. CI's Test Core runs each of these four packages whole on its shard; only
@objectstack/clitakes file-level slices. So the whole-suite run is their shard. The readings are on2d2204d764; for the before leg, the edited file(s) were restored tree-only from7e7e64b1.--project local):86/:100The load did not disappear. It moved into the collect phase, which vitest 4's summary calls "import". For example, objectql's single-case run went from import 7.84s and tests 1.67s to import 10.02s and tests 4ms.
Nobody had measured the other five sites before this. At these readings, only the objectql and core cases carried a load large enough to matter (1.5 to 1.8 s alone). The lazy-deps case is not under the default window at all: it already runs under
COLD_LOAD_TIMEOUT_MS = 30_000, and it measures 5.5 to 8.4 s.Verification
pnpm testper package on2d2204d764: core 76 files / 2156 tests, lint 119 / 5619, plugin-sharing 38 / 954, all passed. objectqlvitest run --project local, which is itstestscript: 366 / 7383 passed.pnpm typecheckfor all four packages: exit 0, andcheck:test-typecheckOK in each. All five files are in their package'stsconfig.test.jsonprogram (tsc --listFiles), and none of them carries an error.dispatch-gates --commandsderived 63 commands from this tree, the same list as the PM's derivation. All 63 were run and all exit 0.check:i18nandcheck:dual-build-cjs-loadsfirst answered PREREQUISITE NOT MET (exit 3); after a turbo cache replay of their build closure, both re-ran green. The--ranreconciliation: 63 derived, 63 run, 0 NOT-MEASURED, 0 UNRUN.eslint --no-inline-config --format jsonover the five files on2d2204d764linted 5 files (none reported as ignored), with 0 errors and 0 warnings.eslint.config.mjsenables no type-aware linting (noparserOptions.project, noprojectService), so this diff cannot change a verdict on any file it does not touch. The repo-widepnpm lintis CI's.git grep -n "await import('\./index" -- 'packages/**/*.test.ts' ':!packages/spec', gives 3 hits: the core precedent's own comment,lazy-deps.test.ts:191(the named exception) andserving-seam.test.ts:84(at module top). The spec side, as the control, gives 45 hits.check:test-source-aliasdoes not flag this shape. Per the triage ruling, that is recorded here and the gate is not widened. It is green on this tree.Acceptance notes
Same family, other spellings. These sites are outside this card's ruled pattern and outside its claimed files. Each is an in-case barrel load, measured alone on
2d2204d764:packages/services/service-analytics/src/__tests__/dataset-compare-kind-refusal.test.ts:220,../index.js: 568 ms;packages/plugins/plugin-email/src/send-template.test.ts:336and:342,./transports/index.js: 37 ms and 1 ms;packages/metadata/src/loaders/overlay-index-single-producer.test.ts:150,../migrations/index.js: 24 ms.None is near the window. They are noted here and not filed.
Base: the branch was cut at
7e7e64b1and merged withorigin/mainat49524f6906.Generated by Claude Code