Skip to content

Commit 278340d

Browse files
os-zhuangzhuangjianguoclaude
authored
fix(test-harness): one anchored rule for every @objectstack/spec subpath in nine vitest alias tables (#9703)
* fix(test-harness): one anchored rule for every `@objectstack/spec` subpath in the vitest alias tables (#9457) `packages/runtime`'s vitest alias table enumerated twelve `@objectstack/spec` subpaths by hand and had gone stale in three places — `cloud`, `integration` and `studio` are published subpath exports with no entry. A string `find` matches by PREFIX, so with a FILE replacement the bare `@objectstack/spec` entry swallowed each of them and resolved it to `…/spec/src/index.ts/<sub>`: `ENOTDIR`, at run time, from a config that reads as correct. The one-line alias is not the fix; the hand-maintained population is the defect. All nine enumerated configs are converted to the anchored-regex shape `packages/qa/downstream-contract` (PR #8129), `service-knowledge`, `service-settings` and `plugin-audit` already carry — one rule for every namespace, which cannot go stale as tests reach new subpaths. `packages/runtime/src/spec-subpath-alias-coverage.pin.test.ts` pins the RULE: it derives the subpath population from spec's published `exports` map, so a namespace this rule stops covering fails there rather than surfacing as an `ENOTDIR` inside whichever plugin performed the import. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012WKSnqAaoqtW3QX7SSf1Vk * test(runtime): give the subpath-coverage pin a timeout that outlives a cold Vite transform (#9457) Measured in both directions: the fifteen namespace imports take ~5.3s on a cold transform, against vitest's 5000ms default, so the case reported `Test timed out in 5000ms` instead of the resolution failure it exists to name. That is the points-at-the-wrong-thing diagnostic this card is about, reproduced inside its own pin. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012WKSnqAaoqtW3QX7SSf1Vk --------- Co-authored-by: os-zhuang <zhuangjianguo@steedos.com> Co-authored-by: Claude <noreply@anthropic.com>
1 parent 11ef32a commit 278340d

10 files changed

Lines changed: 488 additions & 159 deletions

File tree

packages/drivers/driver-memory/vitest.config.ts

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,37 @@ export default defineConfig({
99
environment: 'node',
1010
},
1111
resolve: {
12-
alias: {
13-
'@objectstack/core': path.resolve(__dirname, '../../core/src/index.ts'),
12+
alias: [
13+
{ find: '@objectstack/core', replacement: path.resolve(__dirname, '../../core/src/index.ts') },
1414
// [ADR-0105 D1] `resolveTenancyPosture()`, read by the #6915 tenancy guard.
15-
'@objectstack/types': path.resolve(__dirname, '../../types/src/index.ts'),
16-
'@objectstack/spec/api': path.resolve(__dirname, '../../spec/src/api/index.ts'),
17-
'@objectstack/spec/contracts': path.resolve(__dirname, '../../spec/src/contracts/index.ts'),
18-
'@objectstack/spec/data': path.resolve(__dirname, '../../spec/src/data/index.ts'),
19-
'@objectstack/spec/kernel': path.resolve(__dirname, '../../spec/src/kernel/index.ts'),
20-
'@objectstack/spec/system': path.resolve(__dirname, '../../spec/src/system/index.ts'),
21-
// [ADR-0105 D1] Reached transitively via `@objectstack/types` (tenancy posture).
22-
'@objectstack/spec/security': path.resolve(__dirname, '../../spec/src/security/index.ts'),
23-
// [#7378] Reached transitively: `@objectstack/core` (aliased to src above)
24-
// resolves the metadata register contract's plural→singular fold from this
25-
// subpath (`pluralToSingular`). An alias list matches by PREFIX, so without
26-
// this entry the bare `@objectstack/spec` alias below wins and yields the
27-
// nonsensical `spec/src/index.ts/shared` — ENOTDIR at import time for every
28-
// test file that transitively loads `@objectstack/core`.
29-
'@objectstack/spec/shared': path.resolve(__dirname, '../../spec/src/shared/index.ts'),
30-
'@objectstack/spec/qa': path.resolve(__dirname, '../../spec/src/qa/index.ts'),
31-
'@objectstack/spec': path.resolve(__dirname, '../../spec/src/index.ts'),
32-
},
15+
{ find: '@objectstack/types', replacement: path.resolve(__dirname, '../../types/src/index.ts') },
16+
// #9457: ONE anchored rule for every `@objectstack/spec` namespace, in place
17+
// of the hand-maintained list of the subpaths this package's tests happened
18+
// to reach. A string `find` matches by PREFIX, so with a FILE replacement the
19+
// bare `@objectstack/spec` entry also swallowed every published namespace the
20+
// list had not reached — `cloud`, `integration` and `studio` among them — and
21+
// resolved it to `…/spec/src/index.ts/<ns>`: `ENOTDIR`, at run time, from a
22+
// config that reads as correct, naming whichever module performed the import
23+
// rather than this table.
24+
//
25+
// spec's export map is UNIFORM — every published namespace is
26+
// `src/<ns>/index.ts`, with no FILE-shaped subpath of the kind
27+
// `@objectstack/platform-objects/plugin` is — so one rule covers all of them
28+
// and cannot go stale as tests reach new namespaces. Same shape as
29+
// `packages/qa/downstream-contract` (PR #8129), `service-knowledge`,
30+
// `service-settings` and `plugin-audit`; `packages/runtime` carries the pin
31+
// over the rule (`src/spec-subpath-alias-coverage.pin.test.ts`).
32+
//
33+
// Kept from the enumeration because the reasons outlive it: `security` is
34+
// reached transitively via `@objectstack/types` ([ADR-0105 D1] tenancy
35+
// posture) and `shared` via `@objectstack/core`'s plural→singular fold
36+
// (`pluralToSingular`, #7378). Neither is a reason to keep listing
37+
// namespaces by hand.
38+
{
39+
find: /^@objectstack\/spec\/([a-z-]+)$/,
40+
replacement: path.join(path.resolve(__dirname, '../..'), 'spec/src/$1/index.ts'),
41+
},
42+
{ find: /^@objectstack\/spec$/, replacement: path.resolve(__dirname, '../../spec/src/index.ts') },
43+
],
3344
},
3445
});

packages/drivers/driver-sql/vitest.config.ts

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,35 @@ export default defineConfig({
99
environment: 'node',
1010
},
1111
resolve: {
12-
alias: {
13-
'@objectstack/spec/contracts': path.resolve(__dirname, '../../spec/src/contracts/index.ts'),
14-
'@objectstack/spec/data': path.resolve(__dirname, '../../spec/src/data/index.ts'),
15-
'@objectstack/spec/shared': path.resolve(__dirname, '../../spec/src/shared/index.ts'),
16-
'@objectstack/spec/system': path.resolve(__dirname, '../../spec/src/system/index.ts'),
17-
// [ADR-0105 D1] Reached transitively via `@objectstack/types` (tenancy posture).
18-
'@objectstack/spec/security': path.resolve(__dirname, '../../spec/src/security/index.ts'),
19-
// Reached transitively via `@objectstack/core` (#3777's `nextUtcCalendarDay`
20-
// import pulls core's src barrel in, which fans out to these subpaths).
21-
'@objectstack/spec/api': path.resolve(__dirname, '../../spec/src/api/index.ts'),
22-
'@objectstack/spec/kernel': path.resolve(__dirname, '../../spec/src/kernel/index.ts'),
23-
'@objectstack/spec/qa': path.resolve(__dirname, '../../spec/src/qa/index.ts'),
24-
'@objectstack/spec': path.resolve(__dirname, '../../spec/src/index.ts'),
25-
'@objectstack/core': path.resolve(__dirname, '../../core/src/index.ts'),
26-
},
12+
alias: [
13+
// #9457: ONE anchored rule for every `@objectstack/spec` namespace, in place
14+
// of the hand-maintained list of the subpaths this package's tests happened
15+
// to reach. A string `find` matches by PREFIX, so with a FILE replacement the
16+
// bare `@objectstack/spec` entry also swallowed every published namespace the
17+
// list had not reached — `cloud`, `integration` and `studio` among them — and
18+
// resolved it to `…/spec/src/index.ts/<ns>`: `ENOTDIR`, at run time, from a
19+
// config that reads as correct, naming whichever module performed the import
20+
// rather than this table.
21+
//
22+
// spec's export map is UNIFORM — every published namespace is
23+
// `src/<ns>/index.ts`, with no FILE-shaped subpath of the kind
24+
// `@objectstack/platform-objects/plugin` is — so one rule covers all of them
25+
// and cannot go stale as tests reach new namespaces. Same shape as
26+
// `packages/qa/downstream-contract` (PR #8129), `service-knowledge`,
27+
// `service-settings` and `plugin-audit`; `packages/runtime` carries the pin
28+
// over the rule (`src/spec-subpath-alias-coverage.pin.test.ts`).
29+
//
30+
// Kept from the enumeration because the reasons outlive it: `security` is
31+
// reached transitively via `@objectstack/types` ([ADR-0105 D1] tenancy
32+
// posture), and `api` / `kernel` / `qa` through `@objectstack/core`'s src
33+
// barrel, pulled in by #3777's `nextUtcCalendarDay` import. Neither is a
34+
// reason to keep listing namespaces by hand.
35+
{
36+
find: /^@objectstack\/spec\/([a-z-]+)$/,
37+
replacement: path.join(path.resolve(__dirname, '../..'), 'spec/src/$1/index.ts'),
38+
},
39+
{ find: /^@objectstack\/spec$/, replacement: path.resolve(__dirname, '../../spec/src/index.ts') },
40+
{ find: '@objectstack/core', replacement: path.resolve(__dirname, '../../core/src/index.ts') },
41+
],
2742
},
2843
});

packages/metadata/vitest.config.ts

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,40 @@ import path from 'node:path';
55

66
export default defineConfig({
77
resolve: {
8-
alias: {
9-
'@objectstack/core': path.resolve(__dirname, '../core/src/index.ts'),
10-
'@objectstack/spec/api': path.resolve(__dirname, '../spec/src/api/index.ts'),
11-
'@objectstack/spec/cloud': path.resolve(__dirname, '../spec/src/cloud/index.ts'),
12-
'@objectstack/spec/contracts': path.resolve(__dirname, '../spec/src/contracts/index.ts'),
13-
'@objectstack/spec/data': path.resolve(__dirname, '../spec/src/data/index.ts'),
14-
'@objectstack/spec/kernel': path.resolve(__dirname, '../spec/src/kernel/index.ts'),
15-
'@objectstack/spec/system': path.resolve(__dirname, '../spec/src/system/index.ts'),
16-
'@objectstack/spec/shared': path.resolve(__dirname, '../spec/src/shared/index.ts'),
17-
// [ADR-0105 D1] Reached transitively via `@objectstack/types` (tenancy posture).
18-
'@objectstack/spec/security': path.resolve(__dirname, '../spec/src/security/index.ts'),
19-
'@objectstack/spec/qa': path.resolve(__dirname, '../spec/src/qa/index.ts'),
20-
'@objectstack/spec': path.resolve(__dirname, '../spec/src/index.ts'),
21-
'@objectstack/types': path.resolve(__dirname, '../types/src/index.ts'),
22-
},
8+
alias: [
9+
{ find: '@objectstack/core', replacement: path.resolve(__dirname, '../core/src/index.ts') },
10+
// #9457: ONE anchored rule for every `@objectstack/spec` namespace, in place
11+
// of the hand-maintained list of the subpaths this package's tests happened
12+
// to reach. A string `find` matches by PREFIX, so with a FILE replacement the
13+
// bare `@objectstack/spec` entry also swallowed every published namespace the
14+
// list had not reached — `cloud`, `integration` and `studio` among them — and
15+
// resolved it to `…/spec/src/index.ts/<ns>`: `ENOTDIR`, at run time, from a
16+
// config that reads as correct, naming whichever module performed the import
17+
// rather than this table.
18+
//
19+
// spec's export map is UNIFORM — every published namespace is
20+
// `src/<ns>/index.ts`, with no FILE-shaped subpath of the kind
21+
// `@objectstack/platform-objects/plugin` is — so one rule covers all of them
22+
// and cannot go stale as tests reach new namespaces. Same shape as
23+
// `packages/qa/downstream-contract` (PR #8129), `service-knowledge`,
24+
// `service-settings` and `plugin-audit`; `packages/runtime` carries the pin
25+
// over the rule (`src/spec-subpath-alias-coverage.pin.test.ts`).
26+
//
27+
// Kept from the enumeration because the reason outlives it: `security` is
28+
// reached transitively via `@objectstack/types` ([ADR-0105 D1] tenancy
29+
// posture). That is not a reason to keep listing namespaces by hand.
30+
//
31+
// This package is also where the missing-subpath cost was first measured:
32+
// `MetadataPlugin._parseAndRegisterArtifact` does `await import(
33+
// '@objectstack/spec/cloud')`, which is why `packages/runtime`'s tests died
34+
// with an `ENOTDIR` naming this plugin rather than their own alias table.
35+
{
36+
find: /^@objectstack\/spec\/([a-z-]+)$/,
37+
replacement: path.join(path.resolve(__dirname, '..'), 'spec/src/$1/index.ts'),
38+
},
39+
{ find: /^@objectstack\/spec$/, replacement: path.resolve(__dirname, '../spec/src/index.ts') },
40+
{ find: '@objectstack/types', replacement: path.resolve(__dirname, '../types/src/index.ts') },
41+
],
2342
},
2443
test: {
2544
globals: true,

packages/plugins/embedder-openai/vitest.config.ts

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,32 @@ export default defineConfig({
99
environment: 'node',
1010
},
1111
resolve: {
12-
alias: {
13-
'@objectstack/spec/contracts': path.resolve(__dirname, '../../spec/src/contracts/index.ts'),
14-
'@objectstack/spec/shared': path.resolve(__dirname, '../../spec/src/shared/index.ts'),
15-
// [ADR-0105 D1] Reached transitively via `@objectstack/types` (tenancy posture).
16-
'@objectstack/spec/security': path.resolve(__dirname, '../../spec/src/security/index.ts'),
17-
'@objectstack/spec': path.resolve(__dirname, '../../spec/src/index.ts'),
18-
},
12+
alias: [
13+
// #9457: ONE anchored rule for every `@objectstack/spec` namespace, in place
14+
// of the hand-maintained list of the subpaths this package's tests happened
15+
// to reach. A string `find` matches by PREFIX, so with a FILE replacement the
16+
// bare `@objectstack/spec` entry also swallowed every published namespace the
17+
// list had not reached — `cloud`, `integration` and `studio` among them — and
18+
// resolved it to `…/spec/src/index.ts/<ns>`: `ENOTDIR`, at run time, from a
19+
// config that reads as correct, naming whichever module performed the import
20+
// rather than this table.
21+
//
22+
// spec's export map is UNIFORM — every published namespace is
23+
// `src/<ns>/index.ts`, with no FILE-shaped subpath of the kind
24+
// `@objectstack/platform-objects/plugin` is — so one rule covers all of them
25+
// and cannot go stale as tests reach new namespaces. Same shape as
26+
// `packages/qa/downstream-contract` (PR #8129), `service-knowledge`,
27+
// `service-settings` and `plugin-audit`; `packages/runtime` carries the pin
28+
// over the rule (`src/spec-subpath-alias-coverage.pin.test.ts`).
29+
//
30+
// Kept from the enumeration because the reason outlives it: `security` is
31+
// reached transitively via `@objectstack/types` ([ADR-0105 D1] tenancy
32+
// posture). That is not a reason to keep listing namespaces by hand.
33+
{
34+
find: /^@objectstack\/spec\/([a-z-]+)$/,
35+
replacement: path.join(path.resolve(__dirname, '../..'), 'spec/src/$1/index.ts'),
36+
},
37+
{ find: /^@objectstack\/spec$/, replacement: path.resolve(__dirname, '../../spec/src/index.ts') },
38+
],
1939
},
2040
});

packages/plugins/knowledge-memory/vitest.config.ts

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,39 @@ export default defineConfig({
99
environment: 'node',
1010
},
1111
resolve: {
12-
alias: {
13-
'@objectstack/core': path.resolve(__dirname, '../../core/src/index.ts'),
14-
'@objectstack/service-knowledge': path.resolve(__dirname, '../../services/service-knowledge/src/index.ts'),
15-
'@objectstack/spec/ai': path.resolve(__dirname, '../../spec/src/ai/index.ts'),
16-
'@objectstack/spec/api': path.resolve(__dirname, '../../spec/src/api/index.ts'),
17-
'@objectstack/spec/contracts': path.resolve(__dirname, '../../spec/src/contracts/index.ts'),
18-
'@objectstack/spec/data': path.resolve(__dirname, '../../spec/src/data/index.ts'),
19-
'@objectstack/spec/kernel': path.resolve(__dirname, '../../spec/src/kernel/index.ts'),
20-
'@objectstack/spec/system': path.resolve(__dirname, '../../spec/src/system/index.ts'),
21-
// [ADR-0105 D1] Reached transitively via `@objectstack/types` (tenancy posture).
22-
'@objectstack/spec/security': path.resolve(__dirname, '../../spec/src/security/index.ts'),
23-
// [#7378] Reached transitively: `@objectstack/core` (aliased to src above)
24-
// resolves the metadata register contract's plural→singular fold from this
25-
// subpath (`pluralToSingular`). An alias list matches by PREFIX, so without
26-
// this entry the bare `@objectstack/spec` alias below wins and yields the
27-
// nonsensical `spec/src/index.ts/shared` — ENOTDIR at import time for every
28-
// test file that transitively loads `@objectstack/core`.
29-
'@objectstack/spec/shared': path.resolve(__dirname, '../../spec/src/shared/index.ts'),
30-
'@objectstack/spec/qa': path.resolve(__dirname, '../../spec/src/qa/index.ts'),
31-
'@objectstack/spec': path.resolve(__dirname, '../../spec/src/index.ts'),
32-
},
12+
alias: [
13+
{ find: '@objectstack/core', replacement: path.resolve(__dirname, '../../core/src/index.ts') },
14+
{
15+
find: '@objectstack/service-knowledge',
16+
replacement: path.resolve(__dirname, '../../services/service-knowledge/src/index.ts'),
17+
},
18+
// #9457: ONE anchored rule for every `@objectstack/spec` namespace, in place
19+
// of the hand-maintained list of the subpaths this package's tests happened
20+
// to reach. A string `find` matches by PREFIX, so with a FILE replacement the
21+
// bare `@objectstack/spec` entry also swallowed every published namespace the
22+
// list had not reached — `cloud`, `integration` and `studio` among them — and
23+
// resolved it to `…/spec/src/index.ts/<ns>`: `ENOTDIR`, at run time, from a
24+
// config that reads as correct, naming whichever module performed the import
25+
// rather than this table.
26+
//
27+
// spec's export map is UNIFORM — every published namespace is
28+
// `src/<ns>/index.ts`, with no FILE-shaped subpath of the kind
29+
// `@objectstack/platform-objects/plugin` is — so one rule covers all of them
30+
// and cannot go stale as tests reach new namespaces. Same shape as
31+
// `packages/qa/downstream-contract` (PR #8129), `service-knowledge`,
32+
// `service-settings` and `plugin-audit`; `packages/runtime` carries the pin
33+
// over the rule (`src/spec-subpath-alias-coverage.pin.test.ts`).
34+
//
35+
// Kept from the enumeration because the reasons outlive it: `security` is
36+
// reached transitively via `@objectstack/types` ([ADR-0105 D1] tenancy
37+
// posture) and `shared` via `@objectstack/core`'s plural→singular fold
38+
// (`pluralToSingular`, #7378). Neither is a reason to keep listing
39+
// namespaces by hand.
40+
{
41+
find: /^@objectstack\/spec\/([a-z-]+)$/,
42+
replacement: path.join(path.resolve(__dirname, '../..'), 'spec/src/$1/index.ts'),
43+
},
44+
{ find: /^@objectstack\/spec$/, replacement: path.resolve(__dirname, '../../spec/src/index.ts') },
45+
],
3346
},
3447
});

0 commit comments

Comments
 (0)