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

Commit bba96ce

Browse files
tooling(objectui-readiness 5): the workspace's own files come from workspace-root.mjs, so tests and the CLI generator read the same layout under the monorepo's ui/ (objectstack#25733) (#13498)
<!-- claude-projects-attribution: {"github_login":"os-tesla"} --> _Requested by **Tesla** · [project thread](https://claude.ai/code/project/chan_01AXsQkLFKRdQCqQ3RTr6Jao?thread=cmsg_01AXsQkLFKRdQCqQ3RTr6JaoKJXi9asZgeRJUKMTK6ywWF)_ Part of objectstack#25733 (child 2e of the epic). Part of objectstack#25677. Clause-②: no Metadata-protocol: none - [x] Adds no product-specific widget, dialog, hook or string (see AGENTS.md › Product-neutral renderer) ## Why Standalone, the objectui tree is the pnpm workspace root. Under the objectstack monorepo it is `ui/`, and the workspace root (`pnpm-workspace.yaml`, `node_modules/.pnpm`) is one level up. `ui/node_modules` then holds only the ui root package's own links. There is no `ui/node_modules/.pnpm` and no `ui/pnpm-workspace.yaml`. Measured on a scratch worktree of the objectstack verification head `cfa1676afc`, with this tree applied under `ui/`: 12 tests went red across 5 files, before this change. - `check-doc-snippet-types.test.ts`, 2 reds. The UNDECLARED and ROOT-DECLARED controls looked for `TREE/node_modules/.pnpm`, so both read "NOT INSTALLED", and `check:doc-snippets` exited 2. - `vite-objectstack-client-dist.test.ts`, 5 reds. The installed client is a workspace link to `packages/client`, not a store symlink, and that link carries its own `node_modules`. - `vite-objectstack-spec-dist.test.ts`, 2 reds, and `vite-objectstack-workspace.test.ts`, 2 reds. The checkout's own console has the framework's `packages/` three levels up, so its tests are the merged arm and not the baseline literals. - `packages/cli` `app-generator.test.ts`, 1 red. The in-workspace case used the checkout root as "a workspace root", and under `ui/` it is a member. ## What changes - **`scripts/workspace-root.mjs`** gains `virtualStorePath(root = uiRoot())`, which is the workspace root's `node_modules/.pnpm`. It throws, like `workspaceRoot()`, when no workspace governs the tree. `findInstalledCopy` in `check-doc-snippet-types.mjs` reads it, and returns null with no workspace. The relative path it reports reads `../node_modules/.pnpm/…` under `ui/`. - **`@object-ui/cli` `currentContext()`** returns `isMonorepo: isWorkspaceRoot(cwd)`. That is the predicate `dev`, `serve` and `build` already use (`utils/workspace-vite.ts`, objectui#3890), and it is the same expression the function used to spell inline, `existsSync(join(cwd, 'pnpm-workspace.yaml'))`. See the proposal below. - **Console vendor-chunk tests.** The standalone arm is read off a tmp fixture (`TMP/objectui/apps/console`, nothing beside it), and the merged arm off the existing monorepo-shaped fixture. The checkout itself is asked only which arm its own layout names, with `isNestedWorkspace()` as the independent witness. `vite-objectstack-spec-dist.test.ts` compares the config's vendor test with the arm the layout selects, and pins the baseline literal separately. **The regexes in `scripts/vite-objectstack-workspace.ts` are unchanged.** - **Client-dist test.** The dependency walk through a pnpm symlink is held on a fixture store (`node_modules/.pnpm/@objectstack+client@1.0.0/node_modules/{client,core}` and a console symlink). The out-of-tree copy leaves the package's own `node_modules` behind. - **`check:ui-root-lookups`** gains the `workspace-file-at-ui-root` shape. It fires on a `join`/`resolve` (or a template led by a substitution) that names `pnpm-workspace.yaml` or `node_modules/.pnpm` and whose base resolves to the objectui tree. The base can be `uiRoot()`, `UI_ROOT`, `__dirname` / `import.meta.dirname` / `fileURLToPath(import.meta.url)` climbed to the tree, or a `const` or parameter default bound to one of those. It fires once, where the path first names the file. It adds 14 self-test cases, 51 in total. The allowlist entry for `app-generator.ts` is removed, because it would read stale. ## Proposal: what "runs at a workspace root" means for `currentContext()` `currentContext()` is product code, so its meaning is written in its doc comment and proposed here. "Runs at a workspace root" means **cwd itself holds `pnpm-workspace.yaml`**, the same predicate `dev`, `serve` and `build` use to skip install and to alias. A workspace **member** gets the standalone map. That covers a user's package inside their own monorepo, and objectui under `ui/`. The generator does not walk up, because walking up would hand a member the empty in-workspace maps, and no alias table backs those maps at a member's cwd. **A user's project behaves exactly as before.** With the file in cwd it gets the in-workspace map, and without it the standalone map, because the expression is the same. Two tests pin it, both from fixtures: the in-workspace case runs from a fixture workspace root, and a new case runs from a fixture member and expects the standalone map. ## Reverse check The new gate shape, run on the pristine #13491 head (`f8fa141`), fires at exactly the two sites this PR changes, and nowhere else outside the allowlist: - `scripts/check-doc-snippet-types.mjs` `findInstalledCopy`, `workspace-file-at-ui-root`, `join(root, 'node_modules', '.pnpm')` - `packages/cli/src/utils/app-generator.ts` `currentContext`, `marker-probe`, `existsSync(join(cwd, 'pnpm-workspace.yaml'))` ## Verification **objectui standalone**, on this branch (main `6c3340c` plus this commit, after `pnpm run setup`). Every command exited 0: `pnpm check:ui-root-lookups` · `node scripts/check-ui-root-lookups.mjs --self-test` (51 cases) · `pnpm check:new-line-citations` · `node scripts/check-changeset-presence.mjs` · `node scripts/check-changeset-overwrite.mjs` · `pnpm check:changeset-claims` · `pnpm type-check:scripts` · `pnpm check:test-path-roots` · `pnpm check:pre-install-import-graph` · `pnpm check:control-bytes` · `pnpm exec eslint` over the changed files (0 errors) · `pnpm --filter @object-ui/cli test` (30 files, 416 tests). `pnpm exec vitest run scripts/__tests__` was run whole in three shards (`--shard=K/3`, under the verify lock): 196 files passed, 5787 tests. Two files were skipped by their own `IS_CHILD` conditions. **Merged layout.** I used a scratch worktree of the objectstack verification head `cfa1676afc`. I installed it and ran the CI build of the seven `@objectstack` packages, plus the `@object-ui` closure `check:doc-snippets` builds. Then I applied #13491's diff and this diff under `ui/` with `git apply --directory=ui`. This diff applies to the landed main unchanged; it is byte-identical apart from blob ids. - The 7 touched script test files: 293/293 passed. - `vitest run --root . packages/cli/src/__tests__/app-generator.test.ts`: 48/48 passed. - `pnpm --dir ui run check:ui-root-lookups`: OK, 6 allowlist entries live. - `pnpm --dir ui run check:doc-snippets`: exit 0, 811 blocks compiled. Both controls are live and installed at `../node_modules/.pnpm/…`. - Control, before this diff: the same 7 files plus the CLI test showed the 12 reds above, and `check:doc-snippets` exited 2 with both controls "NOT INSTALLED". ## Bound of the new gate shape Two of the three classes this card fixes are not syntactic joins: the CLI test treating the checkout root as a workspace root, and the vite sibling-directory probe. They are out of the gate's reach, and so are a path assembled through `let` or across files. The gate header states this bound. ## Out of scope Pin scripts (objectstack#25711), spec drift (objectstack#25727), QUICK_REFERENCE (objectstack#25697), dependency versions (objectstack#25726), `.github/**`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_018KHW3U8PmJue4aVvtXutRb Co-authored-by: Claude <noreply@anthropic.com>
1 parent 899f381 commit bba96ce

14 files changed

Lines changed: 436 additions & 52 deletions
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
---
3+
4+
Tooling-only change (objectstack#25733): three tests no longer assume this tree is the pnpm workspace root. `check-doc-snippet-types` finds installed copies in the workspace root's `node_modules/.pnpm` (`virtualStorePath()` in `scripts/workspace-root.mjs`), the Console vendor-chunk tests read their standalone and merged arms off fixture layouts, and the CLI generator test runs its in-workspace case from a fixture workspace. `@object-ui/cli`'s `currentContext()` now asks `isWorkspaceRoot(cwd)`, the predicate `dev`, `serve` and `build` already use: the same expression, so no published behaviour changes.

‎packages/cli/src/__tests__/app-generator.test.ts‎

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,15 +1380,46 @@ describe('generation onto disk', () => {
13801380
}
13811381
}
13821382

1383+
/**
1384+
* A workspace root this file builds itself: a directory holding its own
1385+
* `pnpm-workspace.yaml`, with one member below it. Not `REPO_ROOT`: the
1386+
* objectui tree is a workspace root only standalone, and under the
1387+
* objectstack monorepo it is `ui/`, a member whose workspace file is one
1388+
* level up (objectstack#25733). A fixture names the branch in both layouts.
1389+
*/
1390+
function withWorkspace(run: (root: string, member: string) => void): void {
1391+
withTempDir((root) => {
1392+
writeFileSync(join(root, 'pnpm-workspace.yaml'), "packages:\n - 'packages/*'\n");
1393+
const member = join(root, 'packages', 'app');
1394+
mkdirSync(member, { recursive: true });
1395+
run(root, member);
1396+
});
1397+
}
1398+
13831399
it('writes the IN-WORKSPACE map when the generator runs at a workspace root', () => {
1384-
// `REPO_ROOT` walks up from `import.meta.url`, so this pins the same branch
1385-
// whatever directory the run was launched from — and `IN_WORKSPACE` is that
1386-
// same file-derived root, which is what keeps the expectation independent
1387-
// too. Put either side back on `process.cwd()` and this case silently
1388-
// becomes a third copy of the ambient mirror.
1389-
withTempDir((dir) => {
1390-
writingFrom(REPO_ROOT, () => createTempApp(dir, SCHEMA));
1391-
expect(filesOnDisk(dir)).toEqual(buildAppFiles(SCHEMA, IN_WORKSPACE));
1400+
// The fixture root is derived here, not from `process.cwd()`, so this pins
1401+
// the same branch whatever directory the run was launched from, and the
1402+
// expectation names that same root. Put either side back on
1403+
// `process.cwd()` and this case silently becomes a third copy of the
1404+
// ambient mirror.
1405+
withWorkspace((root) => {
1406+
withTempDir((dir) => {
1407+
writingFrom(root, () => createTempApp(dir, SCHEMA));
1408+
expect(filesOnDisk(dir)).toEqual(buildAppFiles(SCHEMA, { cwd: root, isMonorepo: true }));
1409+
});
1410+
});
1411+
});
1412+
1413+
it('writes the STANDALONE map from a workspace MEMBER — the generator does not walk up', () => {
1414+
// `currentContext()` asks `isWorkspaceRoot(cwd)`, the predicate `dev` and
1415+
// `serve` alias by: a `pnpm-workspace.yaml` ABOVE cwd makes no alias table,
1416+
// so it must not make empty dependency maps either. This is a user's
1417+
// package inside their own monorepo, and the objectui tree under `ui/`.
1418+
withWorkspace((_root, member) => {
1419+
withTempDir((dir) => {
1420+
writingFrom(member, () => createTempApp(dir, SCHEMA));
1421+
expect(filesOnDisk(dir)).toEqual(buildAppFiles(SCHEMA, { cwd: member, isMonorepo: false }));
1422+
});
13921423
});
13931424
});
13941425

‎packages/cli/src/utils/app-generator.ts‎

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
import { readFileSync, writeFileSync, mkdirSync, readdirSync, statSync, existsSync } from 'fs';
9+
import { readFileSync, writeFileSync, mkdirSync, readdirSync, statSync } from 'fs';
1010
import { dirname, join } from 'path';
1111
import chalk from 'chalk';
1212
import * as yaml from 'js-yaml';
@@ -16,6 +16,7 @@ import {
1616
REACT_RANGE,
1717
SCAFFOLD_DEV_DEPENDENCIES
1818
} from './scaffold-dependencies.js';
19+
import { isWorkspaceRoot } from './workspace-vite.js';
1920

2021
export interface RouteInfo {
2122
path: string;
@@ -281,10 +282,25 @@ export interface AppGeneratorContext {
281282
isMonorepo: boolean;
282283
}
283284

284-
/** The context the CLI commands themselves generate under. */
285+
/**
286+
* The context the CLI commands themselves generate under.
287+
*
288+
* "Runs at a workspace root" means `cwd` ITSELF holds a `pnpm-workspace.yaml`,
289+
* and nothing wider: the answer is `isWorkspaceRoot(cwd)`, the same predicate
290+
* `dev`, `serve` and `build` use to skip `npm install` and to build the alias
291+
* table from that file's globs (`utils/workspace-vite.ts`). The two must agree,
292+
* because this branch writes both dependency maps EMPTY on the promise that the
293+
* command will alias the platform packages instead. So a directory that is only
294+
* a workspace MEMBER is not a workspace root, whatever lies above it: a user's
295+
* package inside their own monorepo, and equally the objectui tree when it is
296+
* `ui/` of the objectstack monorepo (objectstack#25733), get the standalone map.
297+
* Walking up to the nearest `pnpm-workspace.yaml` would hand them empty maps
298+
* that no alias table backs. A user's project behaves as it always has: the
299+
* file in `cwd` means in-workspace, no file means standalone.
300+
*/
285301
function currentContext(): AppGeneratorContext {
286302
const cwd = process.cwd();
287-
return { cwd, isMonorepo: existsSync(join(cwd, 'pnpm-workspace.yaml')) };
303+
return { cwd, isMonorepo: isWorkspaceRoot(cwd) };
288304
}
289305

290306
/**

‎scripts/__tests__/check-doc-snippet-emitted-census.test.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,9 @@ describe("objectui#8397 — the manifest the emitted file's reader installs", ()
503503
[`node_modules/${ROOT_DECLARED_CONTROL}/index.d.ts`]: 'export declare const control: number;\n',
504504
// The gate reads "is it installed?" from pnpm's virtual store, so the
505505
// fixture lays one out: an UNINSTALLED control produces TS2307 whether the
506-
// bound ran or not, and would pin nothing.
506+
// bound ran or not, and would pin nothing. The store is the WORKSPACE
507+
// root's (objectstack#25733), so the fixture is one.
508+
'pnpm-workspace.yaml': "packages:\n - 'packages/*'\n",
507509
[`node_modules/.pnpm/${ROOT_DECLARED_CONTROL}@4.0.0/node_modules/${ROOT_DECLARED_CONTROL}/package.json`]:
508510
JSON.stringify({ name: ROOT_DECLARED_CONTROL, version: '4.0.0', types: './index.d.ts' }),
509511
[`node_modules/.pnpm/${ROOT_DECLARED_CONTROL}@4.0.0/node_modules/${ROOT_DECLARED_CONTROL}/index.d.ts`]:

‎scripts/__tests__/check-doc-snippet-types.test.ts‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,34 @@ describe('third-party resolution reaches exactly as far as the imported packages
13761376
).toBeTruthy();
13771377
});
13781378

1379+
it('finds an installed copy in the WORKSPACE root store, in both layouts (objectstack#25733)', () => {
1380+
// Standalone the tree is the workspace root; under the monorepo it is
1381+
// `ui/`, whose node_modules has no `.pnpm`, and the store is one level up.
1382+
// A tree no workspace governs has nothing installed in it.
1383+
const store = 'node_modules/.pnpm/@scope+pkg@1.0.0/node_modules/@scope/pkg/package.json';
1384+
const workspace = "packages:\n - 'packages/*'\n";
1385+
const root = tempTree({
1386+
'ws/pnpm-workspace.yaml': workspace,
1387+
[`ws/${store}`]: '{}',
1388+
'mono/pnpm-workspace.yaml': workspace,
1389+
[`mono/${store}`]: '{}',
1390+
'mono/ui/node_modules/other/package.json': '{}',
1391+
[`loose/${store}`]: '{}',
1392+
});
1393+
try {
1394+
expect(findInstalledCopy(path.join(root, 'ws'), '@scope/pkg')).toBe(
1395+
'node_modules/.pnpm/@scope+pkg@1.0.0/node_modules/@scope/pkg',
1396+
);
1397+
expect(findInstalledCopy(path.join(root, 'mono/ui'), '@scope/pkg')).toBe(
1398+
'../node_modules/.pnpm/@scope+pkg@1.0.0/node_modules/@scope/pkg',
1399+
);
1400+
expect(findInstalledCopy(path.join(root, 'mono/ui'), 'absent')).toBeNull();
1401+
expect(findInstalledCopy(path.join(root, 'loose'), '@scope/pkg')).toBeNull();
1402+
} finally {
1403+
fs.rmSync(root, { recursive: true, force: true });
1404+
}
1405+
});
1406+
13791407
it('neither control specifier is declared by any workspace package, in EITHER field the map reads', () => {
13801408
// Widened with the map (objectui#8919). A control that stays green only
13811409
// because the suite asks about one of two fields is a control that can be

‎scripts/__tests__/check-ui-root-lookups.test.ts‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ describe('check-ui-root-lookups (objectstack ruling D1)', () => {
3939
expect(data).toEqual([]);
4040
});
4141

42+
it('reads the store joined to the tree once, where the path first names it, and the root from the file it is in (objectstack#25733)', () => {
43+
const head = "import { join, resolve } from 'node:path';\nimport { uiRoot } from './ui-root.mjs';\n";
44+
const nested = lookupsIn('scripts/x.mjs', `${head}const store = join(uiRoot(), 'node_modules', '.pnpm');\nconst entry = join(store, 'x@1.0.0', 'node_modules');`);
45+
expect(nested.map((h) => [h.shape, h.text])).toEqual([['workspace-file-at-ui-root', "join(uiRoot(), 'node_modules', '.pnpm')"]]);
46+
// The same climb lands on the tree from one file and on `scripts/` from another.
47+
const climb = "const root = resolve(__dirname, '../..');\nconst store = join(root, 'node_modules', '.pnpm');";
48+
expect(lookupsIn('scripts/__tests__/x.test.ts', `${head}${climb}`).map((h) => h.shape)).toEqual(['workspace-file-at-ui-root']);
49+
expect(lookupsIn('scripts/__tests__/deeper/x.test.ts', `${head}${climb}`)).toEqual([]);
50+
});
51+
4252
it('finds no lookup outside the helper in this tree, and every allowlist entry is live', () => {
4353
const result = scan(repoRoot);
4454
expect(result.scanned).toBeGreaterThan(100);

‎scripts/__tests__/vite-objectstack-client-dist.test.ts‎

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,46 @@ function makeFixtureRoot(): string {
9595
* A copy of the installed client placed outside the workspace — manifest and
9696
* `dist/` intact, no reachable `node_modules` for its two dependencies.
9797
*
98-
* This is the card's reproduction, reduced to a fixture.
98+
* This is the card's reproduction, reduced to a fixture. The package's OWN
99+
* `node_modules` stays behind: a store copy has none (its dependencies are its
100+
* siblings in the store), but under the objectstack monorepo the installed
101+
* client is a workspace link to a package that carries one, and copying that
102+
* would carry the dependencies along (objectstack#25733).
99103
*/
100104
function outOfTreeClientCopy(): string {
101105
const dest = path.join(makeFixtureRoot(), 'client');
102-
fs.cpSync(fs.realpathSync(installedClientDir), dest, { recursive: true, dereference: true });
106+
const source = fs.realpathSync(installedClientDir);
107+
const ownNodeModules = path.join(source, 'node_modules');
108+
fs.cpSync(source, dest, { recursive: true, dereference: true, filter: (src) => src !== ownNodeModules });
103109
return dest;
104110
}
105111

112+
/**
113+
* pnpm's store layout, on disk: the client in
114+
* `.pnpm/@objectstack+client@1.0.0/node_modules/@objectstack/client` with its
115+
* dependency as a sibling there, and a console whose `node_modules` holds only
116+
* a SYMLINK to it. That is how a standalone checkout installs the client; under
117+
* the objectstack monorepo it is a workspace link instead, so the realpath
118+
* measurement below builds this layout rather than reading the checkout's
119+
* (objectstack#25733).
120+
*/
121+
function storeLayoutClient(): { linked: string; real: string } {
122+
const root = makeFixtureRoot();
123+
const storeModules = path.join(root, 'node_modules/.pnpm/@objectstack+client@1.0.0/node_modules');
124+
const real = path.join(storeModules, '@objectstack/client');
125+
fs.mkdirSync(real, { recursive: true });
126+
fs.writeFileSync(
127+
path.join(real, 'package.json'),
128+
JSON.stringify({ name: CLIENT_PACKAGE_NAME, dependencies: { '@objectstack/core': '1.0.0' } })
129+
);
130+
fs.mkdirSync(path.join(storeModules, '@objectstack/core'), { recursive: true });
131+
fs.writeFileSync(path.join(storeModules, '@objectstack/core/package.json'), '{"name":"@objectstack/core"}');
132+
const linked = path.join(root, 'console/node_modules/@objectstack/client');
133+
fs.mkdirSync(path.dirname(linked), { recursive: true });
134+
fs.symlinkSync(real, linked, 'dir');
135+
return { linked, real: fs.realpathSync(real) };
136+
}
137+
106138
/**
107139
* The walk `packageResolvesFrom` performs, re-stated here as a MEASUREMENT
108140
* rather than an import: these cases exist to show what the production walk
@@ -190,22 +222,23 @@ describe('objectui#6094: a VALID override is still injected — all three spelli
190222
});
191223

192224
it('resolves the dependency walk through the pnpm symlink, not around it', () => {
193-
// Skipped only where the installed client is NOT a symlink (a hoisted,
194-
// non-pnpm install), because then there is no symlink for the realpath to
195-
// make a difference to and the counter-probe would be measuring nothing.
196-
if (fs.realpathSync(installedClientDir) === installedClientDir) return;
197-
198225
// The measurement that makes `realpathSync` load-bearing rather than
199-
// tidy: from the symlink path, the client's own dependency is NOT found —
200-
// the walk climbs `apps/console/node_modules` → `apps/console` → the repo
201-
// root, none of which carry `node_modules/@objectstack/core`. From the
202-
// store path it is found, beside the store copy of the client.
203-
expect(walkResolves(installedClientDir, '@objectstack/core')).toBe(false);
204-
expect(walkResolves(fs.realpathSync(installedClientDir), '@objectstack/core')).toBe(true);
226+
// tidy, on the store layout: from the symlink path, the client's own
227+
// dependency is NOT found — the walk climbs `console/node_modules` →
228+
// `console` → the fixture root, none of which carry
229+
// `node_modules/@objectstack/core`. From the store path it is found,
230+
// beside the store copy of the client.
231+
const { linked, real } = storeLayoutClient();
232+
expect(real).not.toBe(linked);
233+
expect(walkResolves(linked, '@objectstack/core')).toBe(false);
234+
expect(walkResolves(real, '@objectstack/core')).toBe(true);
205235
// …so the injection, which walks from `packageDir`, must be reading the
206236
// store path. Without this the check would reject the installed client —
207237
// the one input it must accept.
208-
expect(resolveClientDistInjection(installedClientDir)!.packageDir).not.toBe(installedClientDir);
238+
expect(resolveClientDistInjection(linked)!.packageDir).toBe(real);
239+
// And this checkout's own installed client, store copy or workspace link,
240+
// is judged at its real path too.
241+
expect(resolveClientDistInjection(installedClientDir)!.packageDir).toBe(realClientDir());
209242
});
210243

211244
it('does not demand `peerDependencies` — they come from the consuming app', () => {

‎scripts/__tests__/vite-objectstack-spec-dist.test.ts‎

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
versionSatisfiesRange,
2222
zodPackageDirOf,
2323
} from '../vite-objectstack-spec-dist';
24+
import { BASELINE_CHUNK_TESTS, frameworkPackagesDir, workspaceChunkTests } from '../vite-objectstack-workspace.ts';
2425

2526
/**
2627
* objectui#4854 — `apps/console/vite.config.ts` honours `OBJECTSTACK_SPEC_DIST`,
@@ -93,6 +94,16 @@ const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../
9394
const BASE_VENDOR_TEST =
9495
/([\\/]node_modules[\\/]@objectstack[\\/](?!lint[\\/])|[\\/]@objectstack\+(?!lint@))/;
9596

97+
/**
98+
* The vendor test the console config builds in THIS checkout's layout with no
99+
* override set: `BASE_VENDOR_TEST` standalone, the same arms plus the
100+
* framework's `packages/` when the tree is `ui/` of the objectstack monorepo
101+
* (objectstack#25733). "Inert" means "unmoved from this", in either layout;
102+
* that the standalone arm IS the baseline literal, byte for byte, is pinned on
103+
* a fixture layout in `vite-objectstack-workspace.test.ts`.
104+
*/
105+
const LAYOUT_VENDOR_TEST = workspaceChunkTests(frameworkPackagesDir(path.join(repoRoot, 'apps/console'))).vendor;
106+
96107
/**
97108
* The baseline "this module id is the spec" test, as the console config spells it.
98109
*
@@ -930,11 +941,13 @@ describe('objectui#4854: the four flagged surfaces in the console config', () =>
930941
'react-map-gl/maplibre',
931942
]);
932943

933-
// 3. the vendor-objectstack chunk test — the literal, unwidened.
944+
// 3. the vendor-objectstack chunk test — the layout's own, unwidened. The
945+
// mirror above is still the helper's baseline, so it cannot drift alone.
934946
const groups = config.build.rollupOptions.output.advancedChunks.groups as { name: string; test: RegExp }[];
935947
const vendor = groups.find((g) => g.name === 'vendor-objectstack');
936948
expect(vendor).toBeDefined();
937-
expect(vendor!.test.source).toBe(BASE_VENDOR_TEST.source);
949+
expect(BASE_VENDOR_TEST.source).toBe(BASELINE_CHUNK_TESTS.vendor.source);
950+
expect(vendor!.test.source).toBe(LAYOUT_VENDOR_TEST.source);
938951
// …and what that literal MEANS, so a future rewrite that keeps the shape
939952
// but changes the membership cannot pass by pasting a new string in.
940953
// Reads off the live config's own regex, never the mirror above.
@@ -990,7 +1003,7 @@ describe('objectui#4854: the four flagged surfaces in the console config', () =>
9901003
(config.build.rollupOptions.output.advancedChunks.groups as { name: string; test: RegExp }[]).find(
9911004
(g) => g.name === 'vendor-objectstack'
9921005
)!.test;
993-
expect(vendorOf(injected).source.startsWith(BASE_VENDOR_TEST.source)).toBe(true);
1006+
expect(vendorOf(injected).source.startsWith(LAYOUT_VENDOR_TEST.source)).toBe(true);
9941007
expect(vendorOf(injected).test(`${fs.realpathSync(installedSpecDir)}/dist/ui/index.mjs`)).toBe(true);
9951008
// Widening appends an arm; it must not resurrect the lint exclusion the
9961009
// baseline arms carry, or a spec-dist build would silently re-eagerize the

0 commit comments

Comments
 (0)