vitest.config.mts
Rama main · réplica de lectura del repositorio original.
import { defineConfig } from "vitest/config";
import path from "node:path";
import { fileURLToPath } from "node:url";
const root = path.dirname(fileURLToPath(import.meta.url));
export default defineConfig({
resolve: {
alias: {
// ORDER MATTERS: Vite tries these in insertion order, so the more specific
// prefix has to come first. With "@" first, `@/features/os-shell` resolved to
// <root>/features/os-shell — a path that does not exist — and any test whose
// module graph touched a slice barrel failed with "Cannot find package".
// tsconfig had it right; only the test runner disagreed.
"@/features": path.join(root, "frontend", "slices"),
"@": root,
},
},
test: {
// Shell/systemd lifecycle fixtures can exceed Vitest's 5s default under the full parallel gate.
testTimeout: 15_000,
// Cache transformed modules INSIDE THIS CHECKOUT, not in the shared
// `node_modules/.vitest-cache`.
//
// Agent worktrees symlink `node_modules` to this canonical checkout (so every
// worktree reuses one install). Vitest's default cache path resolves through that
// symlink, so two gates running at once — a worktree's pre-push and this repo's —
// share one cache directory and race on rmdir:
//
// Error: ENOTEMPTY: directory not empty, rmdir '.../node_modules/.vitest-cache'
//
// That failed a push three times with a message that looked like a code problem.
// Keying the cache by checkout root makes concurrent gates independent; the cache
// is still reused within one checkout.
fsModuleCachePath: path.join(root, "node_modules", ".vitest-cache", path.basename(root)),
// `zz-*` is the agreed scratch prefix: agent/debug harnesses that must never
// run in CI, never be committed, and never break a push. Also excluded from
// tsconfig and gitignored — three places, because a leftover has broken this
// repo three separate ways (a CI typecheck, a would-be commit, and a file that
// minted a real session cookie to disk).
exclude: ["**/node_modules/**", "**/.next/**", "**/zz-*"],
include: [
"app/**/*.test.{ts,tsx}",
"frontend/slices/**/*.test.{ts,tsx}",
"lib/**/*.test.{ts,tsx}",
"bin/**/*.test.{ts,tsx}",
"scripts/**/*.test.{ts,tsx}",
"instrumentation.test.ts",
// Root-level modules Next requires by name (middleware is `proxy.ts` in 16),
// so their tests are colocated at the root and named one by one. NAMED, not
// globbed — a root test file that is not listed here is silently never run,
// which is worse than having no test at all, because the suite still says green.
"proxy.test.ts",
"proxy-websocket.test.ts",
"proxy-machine-protocol.test.ts",
],
environment: "node",
// `bun run coverage`, and it IS in `verify`, so these are gates.
//
// The numbers are the CURRENT floor minus a hair, not a target. They used to
// read 50/40/50/50 with a comment calling them "real gates" while real coverage
// was 19% and nothing ran them — an aspiration written as a fact, which is the
// worse of the two failure modes: it reads as covered. Raise these when you add
// tests; never lower them to make a push go through.
coverage: {
provider: "v8",
reporter: ["text", "json-summary"],
include: ["lib/**/*.{ts,tsx}", "frontend/slices/**/*.{ts,tsx}"],
exclude: [
"**/*.test.{ts,tsx}",
"**/*.d.ts",
"**/node_modules/**",
"**/.next/**",
],
thresholds: {
// Ratcheted from the September audit baseline: 42.29 / 40.04 / 32.76 / 44.00.
statements: 42,
branches: 40,
functions: 32,
lines: 43.5,
},
},
},
});