From 8460e27aa153f591fcc37652f2631476114e938b Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 29 Oct 2026 01:36:41 +0000 Subject: [PATCH 1/8] wip(test): create-objectstack runs its scaffolds on a memory-backed TMPDIR Claude-Session: https://claude.ai/code/session_01Utp6CZiAsVSvj5E1XZbWrG Co-authored-by: Claude --- packages/create-objectstack/vitest.config.ts | 10 +++++ vitest.memory-tmp.mts | 45 ++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 vitest.memory-tmp.mts diff --git a/packages/create-objectstack/vitest.config.ts b/packages/create-objectstack/vitest.config.ts index d7ace906a70..0f2de4e1b60 100644 --- a/packages/create-objectstack/vitest.config.ts +++ b/packages/create-objectstack/vitest.config.ts @@ -1,6 +1,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { configDefaults, defineConfig } from 'vitest/config'; +import { memoryBackedTmpEnv } from '../../vitest.memory-tmp.mts'; const HERE = path.dirname(fileURLToPath(import.meta.url)); @@ -38,5 +39,14 @@ export default defineConfig({ // its `test` script. exclude: [...configDefaults.exclude, 'src/templates/**'], environment: 'node', + // Every scaffold these tests write lands under `os.tmpdir()`, children + // included. Under the disk load of a Test Core shard (#27306), measured + // beside four `dd … conv=fsync` writers: all 301 cases still passed, but + // the `afterAll` that removes the scaffolded trees in + // `created-summary.test.ts` and `scaffold-skills-single-copy.test.ts` ran + // past its 10 s hook budget, and a file-level failure with no failed + // case is the red main saw (runs 40713919581, 40718500281: `pnpm run + // test exited (1)`, no test named). Rationale: vitest.memory-tmp.mts. + env: memoryBackedTmpEnv(), }, }); diff --git a/vitest.memory-tmp.mts b/vitest.memory-tmp.mts new file mode 100644 index 00000000000..142deacd3fc --- /dev/null +++ b/vitest.memory-tmp.mts @@ -0,0 +1,45 @@ +// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. + +import { accessSync, constants } from 'node:fs'; + +// The `test.env` that moves a suite's temp directory onto a memory-backed +// filesystem. A package whose tests write real files under `os.tmpdir()` +// (SQLite databases, scaffolded projects) spreads it into its own config: +// +// test: { disableConsoleIntercept: true, env: memoryBackedTmpEnv() } +// +// Not a key of `vitest.preset.mts`: that preset carries one setting for every +// re-exporter, and this one belongs only to the suites whose wall time was +// measured against the disk. +// +// ## Why +// +// On a Test Core shard the runner's disk is shared by every suite running +// beside this one. A case that fsyncs a file, or a hook that unlinks a tree of +// them, waits for that disk's queue, so its wall time measures the +// neighbours' I/O, not the code. Measured with four `dd … conv=fsync` writers +// on the same disk (#27076, #27306): cases that take tens of milliseconds idle +// took seconds and timed out, while with TMPDIR on /dev/shm under the same +// writers they stayed at their idle times. The code under test runs unchanged +// on a tmpfs, `fsync` included; only the wait for unrelated I/O is gone. +// +// `os.tmpdir()` reads TMPDIR on every call, and a child process the suite +// spawns inherits it, so the one setting covers both. A path built from the +// package or the repository does not follow TMPDIR and is not moved by this. +// +// A host without a writable /dev/shm (macOS, Windows) keeps its own temp +// directory: the setting is absent there, not an error. +const MEMORY_BACKED_TMP = '/dev/shm'; + +function writableDir(dir: string): boolean { + try { + accessSync(dir, constants.W_OK); + return true; + } catch { + return false; + } +} + +export function memoryBackedTmpEnv(): Record { + return writableDir(MEMORY_BACKED_TMP) ? { TMPDIR: MEMORY_BACKED_TMP } : {}; +} From bbc7ba8b50fe377dbbba6778cef1bfadf15651ca Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 29 Oct 2026 02:12:46 +0000 Subject: [PATCH 2/8] wip(test): cli runs its SQLite fixtures on a memory-backed TMPDIR Claude-Session: https://claude.ai/code/session_01Utp6CZiAsVSvj5E1XZbWrG Co-authored-by: Claude --- packages/cli/vitest.config.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/cli/vitest.config.ts b/packages/cli/vitest.config.ts index 1dc74c5b2ac..601db263843 100644 --- a/packages/cli/vitest.config.ts +++ b/packages/cli/vitest.config.ts @@ -651,6 +651,7 @@ import { } from '../qa/vitest-filter-preflight/src/index.js'; import { integrationTestFiles, unitTestFiles } from './vitest-tiers.js'; import { readTierMode } from '../../scripts/nightly-tiers.mjs'; +import { memoryBackedTmpEnv } from '../../vitest.memory-tmp.mts'; // The two tiers, DERIVED from what the files DO — never written down — over // the population `OS_TEST_TIERS` selects. `vitest-tiers.ts` holds the @@ -989,6 +990,13 @@ export default defineConfig({ // `server.deps.external` entry above; each repeats the console-intercept // disarm — and, since #17647, the registry log level — because a // root-level value is inert under projects. + // + // Each project's `env` also moves `os.tmpdir()` onto /dev/shm when it is + // writable (#27306; vitest.memory-tmp.mts). Every SQLite database these + // tests migrate lives in an `mkdtemp` under it. Measured on the fifteen + // `organization-ownership-*` files beside four `dd … conv=fsync` + // writers on the same disk: 145 of 232 cases timed out and the run took + // 1,809 s, against 232 of 232 green in 68 s idle; READING_HEAD. projects: [ { extends: true, @@ -999,7 +1007,9 @@ export default defineConfig({ // #13517: quiet the registry's per-item registration chatter — the // engine's own `OS_REGISTRY_LOG` seam, not a change to its shipped // default. Enforced by scripts/check-registry-log-declared.mjs. - env: { OS_REGISTRY_LOG: 'warn' }, + // TMPDIR on a memory-backed directory (#27306): see the root `test` + // block's note above `projects`. + env: { OS_REGISTRY_LOG: 'warn', ...memoryBackedTmpEnv() }, include: UNIT_FILES, }, }, @@ -1012,7 +1022,9 @@ export default defineConfig({ // #13517: quiet the registry's per-item registration chatter — the // engine's own `OS_REGISTRY_LOG` seam, not a change to its shipped // default. Enforced by scripts/check-registry-log-declared.mjs. - env: { OS_REGISTRY_LOG: 'warn' }, + // TMPDIR on a memory-backed directory (#27306): see the root `test` + // block's note above `projects`. + env: { OS_REGISTRY_LOG: 'warn', ...memoryBackedTmpEnv() }, include: INTEGRATION_FILES, }, }, From a9aba7ca0e21f26d0f93f3e386547e07b67cc61b Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 29 Oct 2026 02:26:19 +0000 Subject: [PATCH 3/8] wip(test): runtime runs its SQLite fixtures on a memory-backed TMPDIR Claude-Session: https://claude.ai/code/session_01Utp6CZiAsVSvj5E1XZbWrG Co-authored-by: Claude --- packages/runtime/vitest.config.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/runtime/vitest.config.ts b/packages/runtime/vitest.config.ts index 85e39ce7a1d..604e8d7f16f 100644 --- a/packages/runtime/vitest.config.ts +++ b/packages/runtime/vitest.config.ts @@ -34,6 +34,7 @@ // author can see it. import { configDefaults, defineConfig } from 'vitest/config'; +import { memoryBackedTmpEnv } from '../../vitest.memory-tmp.mts'; import { readFileSync } from 'node:fs'; import path from 'node:path'; import { parseCLI } from 'vitest/node'; @@ -231,6 +232,14 @@ export default defineConfig({ // Each project re-declares the root block's test options: a ROOT-level // value is inert for a project run (measured on vitest 4.1.10, see // check-registry-log-declared / check-console-intercept-disarm). + // + // Each project's `env` also moves `os.tmpdir()` onto /dev/shm when it is + // writable (#27306; vitest.memory-tmp.mts): the package-lifecycle + // integration tests keep their SQLite databases in an `mkdtemp` under it. + // Measured on the 51 test files that do, beside four `dd … conv=fsync` + // writers on the same disk: 25 of 685 cases timed out across 7 files + // (package revert, uninstall, duplicate-adopt, list-commits) and the run + // took 501 s, against all green in 102 s idle; READING_HEAD. projects: [ { extends: true, @@ -242,7 +251,9 @@ export default defineConfig({ // #13517: quiet the registry's per-item registration chatter — the // engine's own `OS_REGISTRY_LOG` seam, not a change to its shipped // default. Enforced by scripts/check-registry-log-declared.mjs. - env: { OS_REGISTRY_LOG: 'warn' }, + // TMPDIR on a memory-backed directory (#27306): see the note above + // `projects`. + env: { OS_REGISTRY_LOG: 'warn', ...memoryBackedTmpEnv() }, // A late console.* must not redden a green suite (#10374); see the root // block. A ROOT-level value is inert for a project run, so it is // declared here as well (scripts/check-console-intercept-disarm.mjs). @@ -258,7 +269,9 @@ export default defineConfig({ // #13517: quiet the registry's per-item registration chatter — the // engine's own `OS_REGISTRY_LOG` seam, not a change to its shipped // default. Enforced by scripts/check-registry-log-declared.mjs. - env: { OS_REGISTRY_LOG: 'warn' }, + // TMPDIR on a memory-backed directory (#27306): see the note above + // `projects`. + env: { OS_REGISTRY_LOG: 'warn', ...memoryBackedTmpEnv() }, // A late console.* must not redden a green suite (#10374); see the root // block. A ROOT-level value is inert for a project run, so it is // declared here as well (scripts/check-console-intercept-disarm.mjs). From 7cc94855a4a0983a4c5b8578e40abae2a8c049d7 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 29 Oct 2026 02:33:59 +0000 Subject: [PATCH 4/8] wip(test): driver-turso runs its file: databases on a memory-backed TMPDIR Claude-Session: https://claude.ai/code/session_01Utp6CZiAsVSvj5E1XZbWrG Co-authored-by: Claude --- .../drivers/driver-turso/vitest.config.ts | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/drivers/driver-turso/vitest.config.ts b/packages/drivers/driver-turso/vitest.config.ts index 092f3349553..234dd868c28 100644 --- a/packages/drivers/driver-turso/vitest.config.ts +++ b/packages/drivers/driver-turso/vitest.config.ts @@ -1,4 +1,30 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. -// This package needs nothing beyond the shared preset; see its header. -export { default } from '../../../vitest.preset.mts'; +import { defineConfig } from 'vitest/config'; +import { memoryBackedTmpEnv } from '../../../vitest.memory-tmp.mts'; + +// This package re-exported the shared preset until #27306. It now carries one +// key of its own, `test.env`, so the preset's one setting is restated below (a +// merged or wrapped preset is not what scripts/check-console-intercept-disarm.mjs +// judges in a config's place). Every other key stays on vitest's defaults, as +// under the bare re-export. +// +// `test.env` moves `os.tmpdir()` onto /dev/shm when it is writable +// (vitest.memory-tmp.mts): the local and remote-face tests open `file:` +// databases in an `mkdtemp` under it. Measured on the 14 test files that do, +// beside four `dd … conv=fsync` writers on the same disk: 21 of 502 cases +// timed out across 4 files (inherited-members, external-object-parity, +// drift-detection, migration-entries) and the run took 211 s, against all +// green in 17 s idle; READING_HEAD. +export default defineConfig({ + test: { + // A late console.* must not redden a green suite (#10374): vitest's worker + // forwards console output over RPC and discards the promise, and a write + // landing after teardown's rpcDone() snapshot is rejected into an unhandled + // error — a fully green run that exits 1. Disarming removes the mechanism. + // Mechanism + measured costs: examples/app-showcase/vitest.config.ts. + // Enforced repo-wide by scripts/check-console-intercept-disarm.mjs. + disableConsoleIntercept: true, + env: memoryBackedTmpEnv(), + }, +}); From 21e43d26def6bdf55387a6c00cf199254ab25823 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 29 Oct 2026 02:37:22 +0000 Subject: [PATCH 5/8] wip(test): driver-sql runs its SQLite files on a memory-backed TMPDIR Claude-Session: https://claude.ai/code/session_01Utp6CZiAsVSvj5E1XZbWrG Co-authored-by: Claude --- packages/drivers/driver-sql/vitest.config.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/drivers/driver-sql/vitest.config.ts b/packages/drivers/driver-sql/vitest.config.ts index cfa7ef78c07..34bc4422d7d 100644 --- a/packages/drivers/driver-sql/vitest.config.ts +++ b/packages/drivers/driver-sql/vitest.config.ts @@ -2,6 +2,7 @@ import { defineConfig } from 'vitest/config'; import path from 'path'; +import { memoryBackedTmpEnv } from '../../../vitest.memory-tmp.mts'; export default defineConfig({ test: { @@ -14,6 +15,13 @@ export default defineConfig({ disableConsoleIntercept: true, globals: true, environment: 'node', + // TMPDIR on /dev/shm when it is writable (#27306; vitest.memory-tmp.mts): + // the SQLite file tests open their databases in an `mkdtemp` under it. + // Measured on the 23 test files that do, beside four `dd … conv=fsync` + // writers on the same disk: 3 of 192 cases timed out (posture + // conformance, reclaim-space, declared-index retired keys) and the run + // took 98 s, against all green in 28 s idle; READING_HEAD. + env: memoryBackedTmpEnv(), // #9350: the live-dialect files each own a schema (Postgres) / database // (MySQL), named in the connection so knex's `client.database()` and the // session cannot disagree. That naming has an ordering constraint — MySQL From d8bcc52c8dbc032aca64dbfcb32310ca38a1a80d Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 29 Oct 2026 02:39:54 +0000 Subject: [PATCH 6/8] wip(test): service-package and service-automation run their SQLite files on a memory-backed TMPDIR Claude-Session: https://claude.ai/code/session_01Utp6CZiAsVSvj5E1XZbWrG Co-authored-by: Claude --- packages/services/service-automation/vitest.config.ts | 8 +++++++- packages/services/service-package/vitest.config.ts | 10 ++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/services/service-automation/vitest.config.ts b/packages/services/service-automation/vitest.config.ts index 903ec636486..8f72939b3d2 100644 --- a/packages/services/service-automation/vitest.config.ts +++ b/packages/services/service-automation/vitest.config.ts @@ -1,5 +1,6 @@ import { defineConfig } from 'vitest/config'; import path from 'node:path'; +import { memoryBackedTmpEnv } from '../../../vitest.memory-tmp.mts'; /** * [#12157] `plugin.ts` registers the ADR-0126 §4 activation ledger's object, @@ -38,7 +39,12 @@ export default defineConfig({ // ride a bare `console.warn` this level never gates — measured green with // the declaration in place. Enforced by // scripts/check-registry-log-declared.mjs. - env: { OS_REGISTRY_LOG: 'warn' }, + // TMPDIR on /dev/shm when it is writable (#27306; vitest.memory-tmp.mts): + // the four tests that persist runs to a SQLite file do it in an `mkdtemp` + // under it. Measured beside four `dd … conv=fsync` writers on the same + // disk: green in that run, but the slowest case went from 0.31 s idle to + // 4.35 s, 87% of its 5 s budget, for no change in the code; READING_HEAD. + env: { OS_REGISTRY_LOG: 'warn', ...memoryBackedTmpEnv() }, }, resolve: { alias: [ diff --git a/packages/services/service-package/vitest.config.ts b/packages/services/service-package/vitest.config.ts index 0d74c903d67..c8a31403b14 100644 --- a/packages/services/service-package/vitest.config.ts +++ b/packages/services/service-package/vitest.config.ts @@ -1,11 +1,12 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. -// This config exists for three settings; everything else stays on vitest's +// This config exists for four settings; everything else stays on vitest's // defaults, deliberately — a key added here re-specifies behaviour for every // test file in the package (packages/cli/vitest.config.ts's header records the // incident that taught that). import { defineConfig } from 'vitest/config'; import path from 'node:path'; +import { memoryBackedTmpEnv } from '../../../vitest.memory-tmp.mts'; export default defineConfig({ test: { @@ -19,7 +20,12 @@ export default defineConfig({ // #13517: quiet the registry's per-item registration chatter — the // engine's own `OS_REGISTRY_LOG` seam, not a change to its shipped // default. Enforced by scripts/check-registry-log-declared.mjs. - env: { OS_REGISTRY_LOG: 'warn' }, + // TMPDIR on /dev/shm when it is writable (#27306; vitest.memory-tmp.mts): + // the two tests that open a SQLite file do it in an `mkdtemp` under it. + // Measured beside four `dd … conv=fsync` writers on the same disk: green + // in that run, but the slowest case went from 0.17 s idle to 3.04 s, 61% + // of its 5 s budget, for no change in the code; READING_HEAD. + env: { OS_REGISTRY_LOG: 'warn', ...memoryBackedTmpEnv() }, }, resolve: { // `hydration-convert-forward.test.ts` boots the REAL engine, protocol and From fb2d18d714e29a857f00aec995452168a1dc9aa9 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 29 Oct 2026 02:41:27 +0000 Subject: [PATCH 7/8] wip(test): driver-sqlite-wasm reads the shared memory-backed TMPDIR helper; readings in each config Claude-Session: https://claude.ai/code/session_01Utp6CZiAsVSvj5E1XZbWrG Co-authored-by: Claude --- packages/cli/vitest.config.ts | 4 +++- packages/create-objectstack/vitest.config.ts | 15 +++++++------ packages/drivers/driver-sql/vitest.config.ts | 3 ++- .../driver-sqlite-wasm/vitest.config.ts | 21 +++++-------------- .../drivers/driver-turso/vitest.config.ts | 3 ++- packages/runtime/vitest.config.ts | 3 ++- .../service-automation/vitest.config.ts | 7 ++++--- .../services/service-package/vitest.config.ts | 3 ++- 8 files changed, 29 insertions(+), 30 deletions(-) diff --git a/packages/cli/vitest.config.ts b/packages/cli/vitest.config.ts index 601db263843..7a5ab5c77e7 100644 --- a/packages/cli/vitest.config.ts +++ b/packages/cli/vitest.config.ts @@ -996,7 +996,9 @@ export default defineConfig({ // tests migrate lives in an `mkdtemp` under it. Measured on the fifteen // `organization-ownership-*` files beside four `dd … conv=fsync` // writers on the same disk: 145 of 232 cases timed out and the run took - // 1,809 s, against 232 of 232 green in 68 s idle; READING_HEAD. + // 1,809 s, against 232 of 232 green in 68 s idle; with TMPDIR there, under + // the same writers, 232 of 232 green in 59 s. Assertions and budgets are + // untouched. projects: [ { extends: true, diff --git a/packages/create-objectstack/vitest.config.ts b/packages/create-objectstack/vitest.config.ts index 0f2de4e1b60..0851d87aa34 100644 --- a/packages/create-objectstack/vitest.config.ts +++ b/packages/create-objectstack/vitest.config.ts @@ -40,13 +40,16 @@ export default defineConfig({ exclude: [...configDefaults.exclude, 'src/templates/**'], environment: 'node', // Every scaffold these tests write lands under `os.tmpdir()`, children - // included. Under the disk load of a Test Core shard (#27306), measured - // beside four `dd … conv=fsync` writers: all 301 cases still passed, but - // the `afterAll` that removes the scaffolded trees in + // included (#27306; vitest.memory-tmp.mts). The cost on a loaded disk is + // not fsync (four calls in the whole suite, by strace) but creating and + // removing those trees: ~4,000 unlinks and ~6,000 rmdirs. Measured beside + // four `dd … conv=fsync` writers on the same disk: all 301 cases passed, + // but the `afterAll` that removes the scaffolded tree in // `created-summary.test.ts` and `scaffold-skills-single-copy.test.ts` ran - // past its 10 s hook budget, and a file-level failure with no failed - // case is the red main saw (runs 40713919581, 40718500281: `pnpm run - // test exited (1)`, no test named). Rationale: vitest.memory-tmp.mts. + // past its 10 s hook budget, so two files failed with no failed case, and + // the run took 236 s against 21 s idle. With TMPDIR there, under the same + // writers, 19 of 19 files green in 20 s. Assertions and budgets are + // untouched. env: memoryBackedTmpEnv(), }, }); diff --git a/packages/drivers/driver-sql/vitest.config.ts b/packages/drivers/driver-sql/vitest.config.ts index 34bc4422d7d..858d895af56 100644 --- a/packages/drivers/driver-sql/vitest.config.ts +++ b/packages/drivers/driver-sql/vitest.config.ts @@ -20,7 +20,8 @@ export default defineConfig({ // Measured on the 23 test files that do, beside four `dd … conv=fsync` // writers on the same disk: 3 of 192 cases timed out (posture // conformance, reclaim-space, declared-index retired keys) and the run - // took 98 s, against all green in 28 s idle; READING_HEAD. + // took 98 s, against all green in 28 s idle; with TMPDIR there, under the + // same writers, all green in 28 s. Assertions and budgets are untouched. env: memoryBackedTmpEnv(), // #9350: the live-dialect files each own a schema (Postgres) / database // (MySQL), named in the connection so knex's `client.database()` and the diff --git a/packages/drivers/driver-sqlite-wasm/vitest.config.ts b/packages/drivers/driver-sqlite-wasm/vitest.config.ts index 08fbf987a6e..498b4024a3c 100644 --- a/packages/drivers/driver-sqlite-wasm/vitest.config.ts +++ b/packages/drivers/driver-sqlite-wasm/vitest.config.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. -import { accessSync, constants } from 'node:fs'; import { defineConfig } from 'vitest/config'; +import { memoryBackedTmpEnv } from '../../../vitest.memory-tmp.mts'; // This package re-exported the shared preset until #27076. It now carries one // key of its own, `test.env.TMPDIR`, so the preset's one setting is restated @@ -27,20 +27,9 @@ import { defineConfig } from 'vitest/config'; // tmpfs the same code still runs, `sync()` included: what each case asserts // (bytes on disk, atomic rename, the flush chain, the failure report) is // unchanged; only the wait for unrelated I/O is gone. Budgets, fixtures and -// cases are untouched. -// -// A host without a writable /dev/shm (macOS, Windows) keeps its own temp -// directory: the setting is absent there, not an error. -const MEMORY_BACKED_TMP = '/dev/shm'; - -function writableDir(dir: string): boolean { - try { - accessSync(dir, constants.W_OK); - return true; - } catch { - return false; - } -} +// cases are untouched. The setting itself, and the host without a writable +// /dev/shm, live in vitest.memory-tmp.mts, shared since #27306 with the other +// packages whose tests write SQLite files under `os.tmpdir()`. export default defineConfig({ test: { @@ -51,6 +40,6 @@ export default defineConfig({ // Mechanism + measured costs: examples/app-showcase/vitest.config.ts. // Enforced repo-wide by scripts/check-console-intercept-disarm.mjs. disableConsoleIntercept: true, - env: writableDir(MEMORY_BACKED_TMP) ? { TMPDIR: MEMORY_BACKED_TMP } : {}, + env: memoryBackedTmpEnv(), }, }); diff --git a/packages/drivers/driver-turso/vitest.config.ts b/packages/drivers/driver-turso/vitest.config.ts index 234dd868c28..080ac39f39e 100644 --- a/packages/drivers/driver-turso/vitest.config.ts +++ b/packages/drivers/driver-turso/vitest.config.ts @@ -15,7 +15,8 @@ import { memoryBackedTmpEnv } from '../../../vitest.memory-tmp.mts'; // beside four `dd … conv=fsync` writers on the same disk: 21 of 502 cases // timed out across 4 files (inherited-members, external-object-parity, // drift-detection, migration-entries) and the run took 211 s, against all -// green in 17 s idle; READING_HEAD. +// green in 17 s idle; with TMPDIR there, under the same writers, all green in +// 17 s. Assertions and budgets are untouched. export default defineConfig({ test: { // A late console.* must not redden a green suite (#10374): vitest's worker diff --git a/packages/runtime/vitest.config.ts b/packages/runtime/vitest.config.ts index 604e8d7f16f..28a0a7d4864 100644 --- a/packages/runtime/vitest.config.ts +++ b/packages/runtime/vitest.config.ts @@ -239,7 +239,8 @@ export default defineConfig({ // Measured on the 51 test files that do, beside four `dd … conv=fsync` // writers on the same disk: 25 of 685 cases timed out across 7 files // (package revert, uninstall, duplicate-adopt, list-commits) and the run - // took 501 s, against all green in 102 s idle; READING_HEAD. + // took 501 s, against all green in 102 s idle; with TMPDIR there, under the + // same writers, all green in 110 s. Assertions and budgets are untouched. projects: [ { extends: true, diff --git a/packages/services/service-automation/vitest.config.ts b/packages/services/service-automation/vitest.config.ts index 8f72939b3d2..fed159d4fc6 100644 --- a/packages/services/service-automation/vitest.config.ts +++ b/packages/services/service-automation/vitest.config.ts @@ -40,10 +40,11 @@ export default defineConfig({ // the declaration in place. Enforced by // scripts/check-registry-log-declared.mjs. // TMPDIR on /dev/shm when it is writable (#27306; vitest.memory-tmp.mts): - // the four tests that persist runs to a SQLite file do it in an `mkdtemp` - // under it. Measured beside four `dd … conv=fsync` writers on the same + // the three tests that persist runs to a SQLite file do it in an + // `mkdtemp` under it. Measured beside four `dd … conv=fsync` writers on the same // disk: green in that run, but the slowest case went from 0.31 s idle to - // 4.35 s, 87% of its 5 s budget, for no change in the code; READING_HEAD. + // 4.35 s, 87% of its 5 s budget, for no change in the code; with TMPDIR + // there, under the same writers, 0.34 s. env: { OS_REGISTRY_LOG: 'warn', ...memoryBackedTmpEnv() }, }, resolve: { diff --git a/packages/services/service-package/vitest.config.ts b/packages/services/service-package/vitest.config.ts index c8a31403b14..9ccb37f9c32 100644 --- a/packages/services/service-package/vitest.config.ts +++ b/packages/services/service-package/vitest.config.ts @@ -24,7 +24,8 @@ export default defineConfig({ // the two tests that open a SQLite file do it in an `mkdtemp` under it. // Measured beside four `dd … conv=fsync` writers on the same disk: green // in that run, but the slowest case went from 0.17 s idle to 3.04 s, 61% - // of its 5 s budget, for no change in the code; READING_HEAD. + // of its 5 s budget, for no change in the code; with TMPDIR there, under + // the same writers, 0.15 s. env: { OS_REGISTRY_LOG: 'warn', ...memoryBackedTmpEnv() }, }, resolve: { From 51e902259e987d5b89f4d339069fada235579e55 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 29 Oct 2026 04:40:03 +0000 Subject: [PATCH 8/8] fix(test): the memory-backed TMPDIR helper is scripts/vitest-memory-tmp.mjs with a declaration A package tsconfig.test.json type-checks its vitest.config.ts, where a .mts import path is TS5097. The helper follows the tsup-drop-sources-content.mjs shape: an .mjs module with a hand-written .d.mts that check:declaration-mirrors holds in step. Claude-Session: https://claude.ai/code/session_01Utp6CZiAsVSvj5E1XZbWrG Co-authored-by: Claude --- packages/cli/vitest.config.ts | 8 ++++---- packages/create-objectstack/vitest.config.ts | 12 ++++++------ packages/drivers/driver-sql/vitest.config.ts | 17 +++++++++-------- .../drivers/driver-sqlite-wasm/vitest.config.ts | 6 +++--- packages/drivers/driver-turso/vitest.config.ts | 4 ++-- packages/runtime/vitest.config.ts | 4 ++-- .../service-automation/vitest.config.ts | 14 +++++++------- .../services/service-package/vitest.config.ts | 14 +++++++------- scripts/vitest-memory-tmp.d.mts | 11 +++++++++++ .../vitest-memory-tmp.mjs | 12 +++++++++--- 10 files changed, 60 insertions(+), 42 deletions(-) create mode 100644 scripts/vitest-memory-tmp.d.mts rename vitest.memory-tmp.mts => scripts/vitest-memory-tmp.mjs (79%) diff --git a/packages/cli/vitest.config.ts b/packages/cli/vitest.config.ts index 7a5ab5c77e7..397ae9d490a 100644 --- a/packages/cli/vitest.config.ts +++ b/packages/cli/vitest.config.ts @@ -651,7 +651,7 @@ import { } from '../qa/vitest-filter-preflight/src/index.js'; import { integrationTestFiles, unitTestFiles } from './vitest-tiers.js'; import { readTierMode } from '../../scripts/nightly-tiers.mjs'; -import { memoryBackedTmpEnv } from '../../vitest.memory-tmp.mts'; +import { memoryBackedTmpEnv } from '../../scripts/vitest-memory-tmp.mjs'; // The two tiers, DERIVED from what the files DO — never written down — over // the population `OS_TEST_TIERS` selects. `vitest-tiers.ts` holds the @@ -992,9 +992,9 @@ export default defineConfig({ // root-level value is inert under projects. // // Each project's `env` also moves `os.tmpdir()` onto /dev/shm when it is - // writable (#27306; vitest.memory-tmp.mts). Every SQLite database these - // tests migrate lives in an `mkdtemp` under it. Measured on the fifteen - // `organization-ownership-*` files beside four `dd … conv=fsync` + // writable (#27306; scripts/vitest-memory-tmp.mjs). Every SQLite database + // these tests migrate lives in an `mkdtemp` under it. Measured on the + // fifteen `organization-ownership-*` files beside four `dd … conv=fsync` // writers on the same disk: 145 of 232 cases timed out and the run took // 1,809 s, against 232 of 232 green in 68 s idle; with TMPDIR there, under // the same writers, 232 of 232 green in 59 s. Assertions and budgets are diff --git a/packages/create-objectstack/vitest.config.ts b/packages/create-objectstack/vitest.config.ts index 0851d87aa34..7983fa08a77 100644 --- a/packages/create-objectstack/vitest.config.ts +++ b/packages/create-objectstack/vitest.config.ts @@ -1,7 +1,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { configDefaults, defineConfig } from 'vitest/config'; -import { memoryBackedTmpEnv } from '../../vitest.memory-tmp.mts'; +import { memoryBackedTmpEnv } from '../../scripts/vitest-memory-tmp.mjs'; const HERE = path.dirname(fileURLToPath(import.meta.url)); @@ -40,11 +40,11 @@ export default defineConfig({ exclude: [...configDefaults.exclude, 'src/templates/**'], environment: 'node', // Every scaffold these tests write lands under `os.tmpdir()`, children - // included (#27306; vitest.memory-tmp.mts). The cost on a loaded disk is - // not fsync (four calls in the whole suite, by strace) but creating and - // removing those trees: ~4,000 unlinks and ~6,000 rmdirs. Measured beside - // four `dd … conv=fsync` writers on the same disk: all 301 cases passed, - // but the `afterAll` that removes the scaffolded tree in + // included (#27306; scripts/vitest-memory-tmp.mjs). The cost on a loaded + // disk is not fsync (four calls in the whole suite, by strace) but creating + // and removing those trees: ~4,000 unlinks and ~6,000 rmdirs. Measured + // beside four `dd … conv=fsync` writers on the same disk: all 301 cases + // passed, but the `afterAll` that removes the scaffolded tree in // `created-summary.test.ts` and `scaffold-skills-single-copy.test.ts` ran // past its 10 s hook budget, so two files failed with no failed case, and // the run took 236 s against 21 s idle. With TMPDIR there, under the same diff --git a/packages/drivers/driver-sql/vitest.config.ts b/packages/drivers/driver-sql/vitest.config.ts index 858d895af56..872d77edefe 100644 --- a/packages/drivers/driver-sql/vitest.config.ts +++ b/packages/drivers/driver-sql/vitest.config.ts @@ -2,7 +2,7 @@ import { defineConfig } from 'vitest/config'; import path from 'path'; -import { memoryBackedTmpEnv } from '../../../vitest.memory-tmp.mts'; +import { memoryBackedTmpEnv } from '../../../scripts/vitest-memory-tmp.mjs'; export default defineConfig({ test: { @@ -15,13 +15,14 @@ export default defineConfig({ disableConsoleIntercept: true, globals: true, environment: 'node', - // TMPDIR on /dev/shm when it is writable (#27306; vitest.memory-tmp.mts): - // the SQLite file tests open their databases in an `mkdtemp` under it. - // Measured on the 23 test files that do, beside four `dd … conv=fsync` - // writers on the same disk: 3 of 192 cases timed out (posture - // conformance, reclaim-space, declared-index retired keys) and the run - // took 98 s, against all green in 28 s idle; with TMPDIR there, under the - // same writers, all green in 28 s. Assertions and budgets are untouched. + // TMPDIR on /dev/shm when it is writable (#27306; + // scripts/vitest-memory-tmp.mjs): the SQLite file tests open their + // databases in an `mkdtemp` under it. Measured on the 23 test files that + // do, beside four `dd … conv=fsync` writers on the same disk: 3 of 192 + // cases timed out (posture conformance, reclaim-space, declared-index + // retired keys) and the run took 98 s, against all green in 28 s idle; with + // TMPDIR there, under the same writers, all green in 28 s. Assertions and + // budgets are untouched. env: memoryBackedTmpEnv(), // #9350: the live-dialect files each own a schema (Postgres) / database // (MySQL), named in the connection so knex's `client.database()` and the diff --git a/packages/drivers/driver-sqlite-wasm/vitest.config.ts b/packages/drivers/driver-sqlite-wasm/vitest.config.ts index 498b4024a3c..a267a3b3f06 100644 --- a/packages/drivers/driver-sqlite-wasm/vitest.config.ts +++ b/packages/drivers/driver-sqlite-wasm/vitest.config.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. import { defineConfig } from 'vitest/config'; -import { memoryBackedTmpEnv } from '../../../vitest.memory-tmp.mts'; +import { memoryBackedTmpEnv } from '../../../scripts/vitest-memory-tmp.mjs'; // This package re-exported the shared preset until #27076. It now carries one // key of its own, `test.env.TMPDIR`, so the preset's one setting is restated @@ -28,8 +28,8 @@ import { memoryBackedTmpEnv } from '../../../vitest.memory-tmp.mts'; // (bytes on disk, atomic rename, the flush chain, the failure report) is // unchanged; only the wait for unrelated I/O is gone. Budgets, fixtures and // cases are untouched. The setting itself, and the host without a writable -// /dev/shm, live in vitest.memory-tmp.mts, shared since #27306 with the other -// packages whose tests write SQLite files under `os.tmpdir()`. +// /dev/shm, live in scripts/vitest-memory-tmp.mjs, shared since #27306 with the +// other packages whose tests write SQLite files under `os.tmpdir()`. export default defineConfig({ test: { diff --git a/packages/drivers/driver-turso/vitest.config.ts b/packages/drivers/driver-turso/vitest.config.ts index 080ac39f39e..cf628317c5e 100644 --- a/packages/drivers/driver-turso/vitest.config.ts +++ b/packages/drivers/driver-turso/vitest.config.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. import { defineConfig } from 'vitest/config'; -import { memoryBackedTmpEnv } from '../../../vitest.memory-tmp.mts'; +import { memoryBackedTmpEnv } from '../../../scripts/vitest-memory-tmp.mjs'; // This package re-exported the shared preset until #27306. It now carries one // key of its own, `test.env`, so the preset's one setting is restated below (a @@ -10,7 +10,7 @@ import { memoryBackedTmpEnv } from '../../../vitest.memory-tmp.mts'; // under the bare re-export. // // `test.env` moves `os.tmpdir()` onto /dev/shm when it is writable -// (vitest.memory-tmp.mts): the local and remote-face tests open `file:` +// (scripts/vitest-memory-tmp.mjs): the local and remote-face tests open `file:` // databases in an `mkdtemp` under it. Measured on the 14 test files that do, // beside four `dd … conv=fsync` writers on the same disk: 21 of 502 cases // timed out across 4 files (inherited-members, external-object-parity, diff --git a/packages/runtime/vitest.config.ts b/packages/runtime/vitest.config.ts index 28a0a7d4864..f48e8a2a312 100644 --- a/packages/runtime/vitest.config.ts +++ b/packages/runtime/vitest.config.ts @@ -34,7 +34,7 @@ // author can see it. import { configDefaults, defineConfig } from 'vitest/config'; -import { memoryBackedTmpEnv } from '../../vitest.memory-tmp.mts'; +import { memoryBackedTmpEnv } from '../../scripts/vitest-memory-tmp.mjs'; import { readFileSync } from 'node:fs'; import path from 'node:path'; import { parseCLI } from 'vitest/node'; @@ -234,7 +234,7 @@ export default defineConfig({ // check-registry-log-declared / check-console-intercept-disarm). // // Each project's `env` also moves `os.tmpdir()` onto /dev/shm when it is - // writable (#27306; vitest.memory-tmp.mts): the package-lifecycle + // writable (#27306; scripts/vitest-memory-tmp.mjs): the package-lifecycle // integration tests keep their SQLite databases in an `mkdtemp` under it. // Measured on the 51 test files that do, beside four `dd … conv=fsync` // writers on the same disk: 25 of 685 cases timed out across 7 files diff --git a/packages/services/service-automation/vitest.config.ts b/packages/services/service-automation/vitest.config.ts index fed159d4fc6..8827ab3306c 100644 --- a/packages/services/service-automation/vitest.config.ts +++ b/packages/services/service-automation/vitest.config.ts @@ -1,6 +1,6 @@ import { defineConfig } from 'vitest/config'; import path from 'node:path'; -import { memoryBackedTmpEnv } from '../../../vitest.memory-tmp.mts'; +import { memoryBackedTmpEnv } from '../../../scripts/vitest-memory-tmp.mjs'; /** * [#12157] `plugin.ts` registers the ADR-0126 §4 activation ledger's object, @@ -39,12 +39,12 @@ export default defineConfig({ // ride a bare `console.warn` this level never gates — measured green with // the declaration in place. Enforced by // scripts/check-registry-log-declared.mjs. - // TMPDIR on /dev/shm when it is writable (#27306; vitest.memory-tmp.mts): - // the three tests that persist runs to a SQLite file do it in an - // `mkdtemp` under it. Measured beside four `dd … conv=fsync` writers on the same - // disk: green in that run, but the slowest case went from 0.31 s idle to - // 4.35 s, 87% of its 5 s budget, for no change in the code; with TMPDIR - // there, under the same writers, 0.34 s. + // TMPDIR on /dev/shm when it is writable (#27306; + // scripts/vitest-memory-tmp.mjs): the three tests that persist runs to a + // SQLite file do it in an `mkdtemp` under it. Measured beside four + // `dd … conv=fsync` writers on the same disk: green in that run, but the + // slowest case went from 0.31 s idle to 4.35 s, 87% of its 5 s budget, for + // no change in the code; with TMPDIR there, under the same writers, 0.34 s. env: { OS_REGISTRY_LOG: 'warn', ...memoryBackedTmpEnv() }, }, resolve: { diff --git a/packages/services/service-package/vitest.config.ts b/packages/services/service-package/vitest.config.ts index 9ccb37f9c32..102d2036cc7 100644 --- a/packages/services/service-package/vitest.config.ts +++ b/packages/services/service-package/vitest.config.ts @@ -6,7 +6,7 @@ // incident that taught that). import { defineConfig } from 'vitest/config'; import path from 'node:path'; -import { memoryBackedTmpEnv } from '../../../vitest.memory-tmp.mts'; +import { memoryBackedTmpEnv } from '../../../scripts/vitest-memory-tmp.mjs'; export default defineConfig({ test: { @@ -20,12 +20,12 @@ export default defineConfig({ // #13517: quiet the registry's per-item registration chatter — the // engine's own `OS_REGISTRY_LOG` seam, not a change to its shipped // default. Enforced by scripts/check-registry-log-declared.mjs. - // TMPDIR on /dev/shm when it is writable (#27306; vitest.memory-tmp.mts): - // the two tests that open a SQLite file do it in an `mkdtemp` under it. - // Measured beside four `dd … conv=fsync` writers on the same disk: green - // in that run, but the slowest case went from 0.17 s idle to 3.04 s, 61% - // of its 5 s budget, for no change in the code; with TMPDIR there, under - // the same writers, 0.15 s. + // TMPDIR on /dev/shm when it is writable (#27306; + // scripts/vitest-memory-tmp.mjs): the two tests that open a SQLite file do + // it in an `mkdtemp` under it. Measured beside four `dd … conv=fsync` + // writers on the same disk: green in that run, but the slowest case went + // from 0.17 s idle to 3.04 s, 61% of its 5 s budget, for no change in the + // code; with TMPDIR there, under the same writers, 0.15 s. env: { OS_REGISTRY_LOG: 'warn', ...memoryBackedTmpEnv() }, }, resolve: { diff --git a/scripts/vitest-memory-tmp.d.mts b/scripts/vitest-memory-tmp.d.mts new file mode 100644 index 00000000000..8a67e1fcafe --- /dev/null +++ b/scripts/vitest-memory-tmp.d.mts @@ -0,0 +1,11 @@ +// Types for `vitest-memory-tmp.mjs`, published for the package vitest configs +// that import it. Several of those configs sit inside a package's +// `tsconfig.test.json` program, where an untyped `.mjs` import is TS7016. See +// `invoked-as.d.mts` for why this pairing exists; this file follows the same +// convention, and `check:declaration-mirrors` holds it in step with the module. + +/** + * The `test.env` that moves `os.tmpdir()` onto /dev/shm: + * `{ TMPDIR: '/dev/shm' }` when that directory is writable, `{}` otherwise. + */ +export function memoryBackedTmpEnv(): Record; diff --git a/vitest.memory-tmp.mts b/scripts/vitest-memory-tmp.mjs similarity index 79% rename from vitest.memory-tmp.mts rename to scripts/vitest-memory-tmp.mjs index 142deacd3fc..b64f3ac0804 100644 --- a/vitest.memory-tmp.mts +++ b/scripts/vitest-memory-tmp.mjs @@ -10,7 +10,11 @@ import { accessSync, constants } from 'node:fs'; // // Not a key of `vitest.preset.mts`: that preset carries one setting for every // re-exporter, and this one belongs only to the suites whose wall time was -// measured against the disk. +// measured against the disk. A `.mjs` with a hand-written `.d.mts` beside it, +// like `tsup-drop-sources-content.mjs`: a package's `tsconfig.test.json` +// type-checks its `vitest.config.ts`, where a `.mts` import path is TS5097 +// and an untyped `.mjs` one is TS7016 (`check:declaration-mirrors` holds the +// pair in step). // // ## Why // @@ -31,7 +35,8 @@ import { accessSync, constants } from 'node:fs'; // directory: the setting is absent there, not an error. const MEMORY_BACKED_TMP = '/dev/shm'; -function writableDir(dir: string): boolean { +/** @param {string} dir */ +function writableDir(dir) { try { accessSync(dir, constants.W_OK); return true; @@ -40,6 +45,7 @@ function writableDir(dir: string): boolean { } } -export function memoryBackedTmpEnv(): Record { +/** @returns {Record} */ +export function memoryBackedTmpEnv() { return writableDir(MEMORY_BACKED_TMP) ? { TMPDIR: MEMORY_BACKED_TMP } : {}; }