Found while implementing #9457 (the @objectstack/spec half of the same class). Not fixed there: that card's dispatch declared its file surface as "the @objectstack/spec alias table only", and the correct shape here is a different one — see below. Filing unassigned.
The gap
#9457 converted the enumerated @objectstack/spec subpath lists in nine vitest.config.ts files to one anchored regex per config. The two other workspace packages those same configs alias with a bare stringfind and a FILE replacement still publish subpaths of their own:
| package | published subpath | source shape |
|---|
@objectstack/core | ./logger | src/logger.ts — a FILE |
@objectstack/types | ./node | src/node.ts — a FILE |
A string find matches by PREFIX, so @objectstack/core/logger resolves to …/core/src/index.ts/logger — the same ENOTDIR-at-run-time shape those configs' own comments already document twice.
Measured (config shapes and export maps, on main)
Configs that alias bare @objectstack/core with no@objectstack/core/logger entry ahead of it — 7:
packages/drivers/driver-memory packages/plugins/knowledge-ragflow
packages/drivers/driver-sql packages/plugins/plugin-dev
packages/metadata packages/plugins/plugin-hono-server
packages/plugins/knowledge-memory
Configs that alias bare @objectstack/types, none of which has a @objectstack/types/node entry — 4: packages/runtime, packages/metadata, packages/drivers/driver-memory, packages/plugins/plugin-dev.
packages/runtime is the only config with an explicit @objectstack/core/logger entry, added when exactly this bit somebody once.
Real consumers of the two subpaths exist today — packages/cli/src/commands/serve.ts, packages/client/src/index.ts, packages/verify/src/harness.ts, packages/qa/dogfood/test/enterprise-organizations.ts, packages/types/src/node-isolation.test.ts — so this is reachable rather than theoretical; it just has not been reached from those seven packages' test graphs yet.
Why the #9457 shape does NOT transfer, which is why this is its own card
@objectstack/spec's export map is uniform (every published namespace is src/(namespace)/index.ts), so one anchored regex covers all of it. @objectstack/core and @objectstack/types are not uniform: their only published subpaths are FILES, so a ([a-z-]+) namespace rule would send @objectstack/core/logger to src/logger/index.ts — a path nobody wrote, and one pnpm check:test-source-alias cannot catch because it still reads as pointing at source. This is the same asymmetry packages/services/service-settings/vitest.config.ts records for @objectstack/platform-objects/plugin.
The shape that fits is the other one those configs already use: an explicit anchored subpath entry ahead of an anchored bare entry. Whether it should be applied at all is a real decision rather than a mechanical edit — an anchored bare entry alone leaves the subpath resolving through exports to dist, which is what check:test-source-alias and its KNOWN_UNALIASED_TEST_IMPORTS registry adjudicate, so a sweep here has to move that registry with it.
Why it is a finding
No product path is affected: published packages resolve both subpaths through their exports maps correctly. This is unexercised drift in test configs, and its cost is the same diagnostic one #9457 records — the failure lands on whoever adds the import, naming a path nobody wrote, one package away from the table that is actually wrong.
Backlink: #9457.
Found while implementing #9457 (the
@objectstack/spechalf of the same class). Not fixed there: that card's dispatch declared its file surface as "the@objectstack/specalias table only", and the correct shape here is a different one — see below. Filing unassigned.The gap
#9457 converted the enumerated
@objectstack/specsubpath lists in ninevitest.config.tsfiles to one anchored regex per config. The two other workspace packages those same configs alias with a bare stringfindand a FILE replacement still publish subpaths of their own:@objectstack/core./loggersrc/logger.ts— a FILE@objectstack/types./nodesrc/node.ts— a FILEA string
findmatches by PREFIX, so@objectstack/core/loggerresolves to…/core/src/index.ts/logger— the sameENOTDIR-at-run-time shape those configs' own comments already document twice.Measured (config shapes and export maps, on
main)Configs that alias bare
@objectstack/corewith no@objectstack/core/loggerentry ahead of it — 7:Configs that alias bare
@objectstack/types, none of which has a@objectstack/types/nodeentry — 4:packages/runtime,packages/metadata,packages/drivers/driver-memory,packages/plugins/plugin-dev.packages/runtimeis the only config with an explicit@objectstack/core/loggerentry, added when exactly this bit somebody once.Real consumers of the two subpaths exist today —
packages/cli/src/commands/serve.ts,packages/client/src/index.ts,packages/verify/src/harness.ts,packages/qa/dogfood/test/enterprise-organizations.ts,packages/types/src/node-isolation.test.ts— so this is reachable rather than theoretical; it just has not been reached from those seven packages' test graphs yet.Why the #9457 shape does NOT transfer, which is why this is its own card
@objectstack/spec's export map is uniform (every published namespace issrc/(namespace)/index.ts), so one anchored regex covers all of it.@objectstack/coreand@objectstack/typesare not uniform: their only published subpaths are FILES, so a([a-z-]+)namespace rule would send@objectstack/core/loggertosrc/logger/index.ts— a path nobody wrote, and onepnpm check:test-source-aliascannot catch because it still reads as pointing at source. This is the same asymmetrypackages/services/service-settings/vitest.config.tsrecords for@objectstack/platform-objects/plugin.The shape that fits is the other one those configs already use: an explicit anchored subpath entry ahead of an anchored bare entry. Whether it should be applied at all is a real decision rather than a mechanical edit — an anchored bare entry alone leaves the subpath resolving through
exportstodist, which is whatcheck:test-source-aliasand itsKNOWN_UNALIASED_TEST_IMPORTSregistry adjudicate, so a sweep here has to move that registry with it.Why it is a
findingNo product path is affected: published packages resolve both subpaths through their
exportsmaps correctly. This is unexercised drift in test configs, and its cost is the same diagnostic one #9457 records — the failure lands on whoever adds the import, naming a path nobody wrote, one package away from the table that is actually wrong.Backlink: #9457.