From 2d81f587c53cd893bda5bada95a7af1efc916eb4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 23 Sep 2026 02:40:39 +0000 Subject: [PATCH 1/2] test(plugin-dev): take the real module resolution out of the tenancy-posture clocked window `dev-plugin-tenancy-posture.test.ts` left `@objectstack/organizations` unmocked so the real resolution failure would be the signal for branch entry. Five of its six cases therefore performed a real, uncached `node_modules` walk inside the per-test clocked window, which is the only thing in that window whose cost is a function of concurrent machine load. Under a parallel shard one case exceeded the 5000ms budget. Measured, since the first reading was wrong: the failing resolution is not cached (200 consecutive attempts, p50 1.157ms, none free) and is not served by the vitest main process (with that process blocked by ~45s of transforms the cases still ran in 2-12ms), so it is the worker's own resolver; under filesystem contention the same 200 attempts keep p50 at 0.839ms but take max from 8.0ms to 28.2ms. The package now gets the same throwing factory the other twelve get, which is what this file's own `#3060` block always claimed to achieve ("zero module resolution on the hot path"). The absence itself keeps its faithful witness: `dev-plugin-tenancy-failfast.test.ts` still reads the real, unmocked failure, and `no-framework-dependents.pin.test.ts` pins the ADR-0132 entitlement boundary that makes the package unresolvable here. Claude-Session: https://claude.ai/code/session_01AhQASwqJr2Z7XfGWUdvnbF Co-authored-by: Claude --- .../src/dev-plugin-tenancy-posture.test.ts | 67 +++++++++++++++---- 1 file changed, 53 insertions(+), 14 deletions(-) diff --git a/packages/plugins/plugin-dev/src/dev-plugin-tenancy-posture.test.ts b/packages/plugins/plugin-dev/src/dev-plugin-tenancy-posture.test.ts index 12d71616b2e..f1bcb91a7b9 100644 --- a/packages/plugins/plugin-dev/src/dev-plugin-tenancy-posture.test.ts +++ b/packages/plugins/plugin-dev/src/dev-plugin-tenancy-posture.test.ts @@ -20,26 +20,64 @@ // service "is the wall up?" would be circular. // // ── What is observed, and why it is honest ────────────────────────────────── -// `@objectstack/organizations` is open core since ADR-0132 and IS a member of -// this workspace, but ADR-0132's entitlement boundary forbids any framework -// package declaring it (`no-framework-dependents.pin.test.ts`), so it is -// genuinely unresolvable from `plugin-dev`: the dynamic import genuinely fails -// and the real catch branch runs. That makes the emitted warning a faithful -// witness for "the multi-org branch was ENTERED": under the bug there is no -// warning at all, because the `if` was never taken. The assertions therefore -// key on branch ENTRY, not on a successfully mounted plugin — the latter is -// unobservable in open-source CI, and pretending otherwise would need a fake -// enterprise package, i.e. stubbing the very thing under test. +// The assertions key on branch ENTRY, read off the warning the absent-package +// path emits: under the bug there is no warning at all, because the `if` was +// never taken. They deliberately do NOT key on a successfully mounted plugin — +// that is unobservable in open-source CI, and pretending otherwise would need a +// fake enterprise package, i.e. stubbing the very thing under test. +// +// `@objectstack/organizations` is SIMULATED absent here, by the same throwing +// factory the twelve packages below get. That is a change: this file used to let +// the REAL dynamic import fail, which it does — ADR-0132's entitlement boundary +// forbids any framework package declaring the name +// (`no-framework-dependents.pin.test.ts`), so it is genuinely unresolvable from +// `plugin-dev`. What the real failure bought was honesty about the ABSENCE. +// What it cost was a real, uncached module resolution inside the CLOCKED WINDOW +// of five of the six cases below — and the absence is not this file's subject. +// Its subject is WHICH KNOB decides branch entry. +// +// Measured on this tree, three readings, because the first guess was wrong: +// • the failing resolution is NOT cached — 200 consecutive attempts from this +// file's own runner, p50 1.157ms, max 8.037ms, none of them free; +// • it is NOT served by the vitest main process, so it is not the transform +// queue the `#3060` note below names: with that process blocked by ~45s of +// real transforms these cases still ran in 2–12ms. The cost is the WORKER's +// own resolver walking `node_modules` and raising ERR_MODULE_NOT_FOUND; +// • that walk has a load-sensitive tail — the same 200 attempts under +// filesystem contention keep p50 at 0.839ms but take max from 8.0ms to +// 28.2ms. +// +// So each walled case drew from an unbounded, machine-load-dependent +// distribution, and a 5000ms per-test budget bounded the DRAW rather than any +// work this file is about. Under a parallel shard it timed out on a case that +// asserts a back-compat env-var reading. Scaled repro, same command before and +// after, timeout scaled down instead of load scaled up: with the per-test budget +// at 25ms under filesystem contention, 10 runs of this file failed 6 times +// before this change and 0 times after — and every one of those 10 timeouts +// landed on a WALLED case, never on the single-org case, which runs three +// `init()`s and resolves nothing. That control is what names the construct. +// +// ⛔ Nothing about the absence is given up by the SUITE, only by this file: the +// real, unmocked resolution failure is still the signal in +// `dev-plugin-tenancy-failfast.test.ts`, whose subject IS the absent-package +// path, and the boundary that makes the package absent is pinned mechanically +// by `no-framework-dependents.pin.test.ts`. A mock that stopped matching +// reality would therefore redden there, not go unnoticed here. import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -// #3060 — the same treatment the sibling suite uses: init() dynamically imports +// #3060 — the same treatment the sibling suites use: init() dynamically imports // ~10 real workspace packages, whose vite transforms alone can blow the test // timeout under a parallel `pnpm test`. Each factory throws the shape an absent // package produces, so the graceful-degradation branches run for real with zero -// module resolution on the hot path. `@objectstack/organizations` is -// deliberately NOT listed: it is really absent, and its real failure is the -// signal this file reads. +// module resolution on the hot path. +// +// `@objectstack/organizations` is listed HERE TOO, and the header above is the +// argument for why it may be: keeping it off this list left one real resolution +// per walled case in the clocked window, which is the only thing in that window +// whose cost is a function of what else the machine is doing. "Zero module +// resolution on the hot path" is what this block has always claimed; now it is +// true. vi.mock('@objectstack/objectql', () => { throw Object.assign(new Error("Cannot find package '@objectstack/objectql'"), { code: 'ERR_MODULE_NOT_FOUND' }); }); vi.mock('@objectstack/runtime', () => { throw Object.assign(new Error("Cannot find package '@objectstack/runtime'"), { code: 'ERR_MODULE_NOT_FOUND' }); }); vi.mock('@objectstack/driver-memory', () => { throw Object.assign(new Error("Cannot find package '@objectstack/driver-memory'"), { code: 'ERR_MODULE_NOT_FOUND' }); }); @@ -52,6 +90,7 @@ vi.mock('@objectstack/plugin-hono-server', () => { throw Object.assign(new Error vi.mock('@objectstack/rest', () => { throw Object.assign(new Error("Cannot find package '@objectstack/rest'"), { code: 'ERR_MODULE_NOT_FOUND' }); }); vi.mock('@objectstack/setup', () => { throw Object.assign(new Error("Cannot find package '@objectstack/setup'"), { code: 'ERR_MODULE_NOT_FOUND' }); }); vi.mock('@objectstack/account', () => { throw Object.assign(new Error("Cannot find package '@objectstack/account'"), { code: 'ERR_MODULE_NOT_FOUND' }); }); +vi.mock('@objectstack/organizations', () => { throw Object.assign(new Error("Cannot find package '@objectstack/organizations'"), { code: 'ERR_MODULE_NOT_FOUND' }); }); import { DevPlugin } from './dev-plugin'; From 62d3ec8a3f4ae81de103fe7afc461b177b34fc68 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 23 Sep 2026 03:09:23 +0000 Subject: [PATCH 2/2] test(plugin-dev): correct the header's measured after-figure and the mock count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scaled repro's after-side is 1 of 10, not 0 of 10, and the one residual timeout lands on the single-org case — which resolves nothing. That control is worth more than a clean zero, so it is recorded as measured. The block now also says "twelve OTHER packages", since organizations joined the list. Claude-Session: https://claude.ai/code/session_01AhQASwqJr2Z7XfGWUdvnbF Co-authored-by: Claude --- .../src/dev-plugin-tenancy-posture.test.ts | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/plugins/plugin-dev/src/dev-plugin-tenancy-posture.test.ts b/packages/plugins/plugin-dev/src/dev-plugin-tenancy-posture.test.ts index f1bcb91a7b9..c9bb19518f4 100644 --- a/packages/plugins/plugin-dev/src/dev-plugin-tenancy-posture.test.ts +++ b/packages/plugins/plugin-dev/src/dev-plugin-tenancy-posture.test.ts @@ -27,7 +27,7 @@ // fake enterprise package, i.e. stubbing the very thing under test. // // `@objectstack/organizations` is SIMULATED absent here, by the same throwing -// factory the twelve packages below get. That is a change: this file used to let +// factory the twelve OTHER packages in the block below get. That is a change: this file used to let // the REAL dynamic import fail, which it does — ADR-0132's entitlement boundary // forbids any framework package declaring the name // (`no-framework-dependents.pin.test.ts`), so it is genuinely unresolvable from @@ -50,12 +50,18 @@ // So each walled case drew from an unbounded, machine-load-dependent // distribution, and a 5000ms per-test budget bounded the DRAW rather than any // work this file is about. Under a parallel shard it timed out on a case that -// asserts a back-compat env-var reading. Scaled repro, same command before and -// after, timeout scaled down instead of load scaled up: with the per-test budget -// at 25ms under filesystem contention, 10 runs of this file failed 6 times -// before this change and 0 times after — and every one of those 10 timeouts -// landed on a WALLED case, never on the single-org case, which runs three -// `init()`s and resolves nothing. That control is what names the construct. +// asserts a back-compat env-var reading. +// +// Scaled repro — same command and same filesystem contention on both sides, +// with the per-test budget scaled DOWN to 25ms rather than the load scaled up, +// N=10 runs each side: 6 of 10 runs failed before this change, 1 of 10 after. +// The CASE-level reading is what names the construct: all 10 timeouts before +// landed on a WALLED case and none on the single-org case; after, the single +// remaining timeout WAS the single-org case — which resolves nothing and runs +// three `init()`s, i.e. the scaled harness's own CPU floor at a 25ms budget, +// not this construct. ⛔ Do not read that residual as a reason to reach for the +// budget: at the 5000ms CI actually uses, the whole window is now pure +// in-process CPU measured at 1–9ms. // // ⛔ Nothing about the absence is given up by the SUITE, only by this file: the // real, unmocked resolution failure is still the signal in