From 8f7d9beb0f7bce99d2245c483b6b1284140fbddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Sat, 22 Aug 2026 16:42:04 +0200 Subject: [PATCH] fix(mutation): move the repo size ratchet where the lane cannot reach it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stryker runs the suite from a sandbox copy under `.tmp/stryker/`, so a test that asserts about the repository checkout itself — its files on disk, or its git history — reads a repository that does not exist. `test-file-size-ratchet.test.ts` is such a gate, and it fails there for two independent reasons: `disableTypeChecks` (Stryker's default) prepends `// @ts-nocheck` to every copied file, so all 26 pinned files read one line longer than they are; and the sandbox has no `origin/main`, so the gate's history-backed half cannot resolve its merge-base. Fixing either leaves the other. Its own `.tmp` skip entry cannot help: that is matched relative to `REPO_ROOT`, which inside the sandbox *is* the sandbox. Move it to `scripts/__tests__/` and include it explicitly in `unit-core`, the address the repo already uses for maintained gates that are not `src` tests. `KERNEL_TEST_FILE_RE` admits only root/package `src` tests, and its comment already names `scripts/__tests__` as unreachable by construction — so the gate leaves every mutation lane by virtue of where it lives, with no classifier to recognise it and nothing to keep in sync. This replaces the source-text scanner of the previous revision, which was the wrong boundary: it sniffed for a single-quoted `walk-files` import or the string `origin/main`, so a behavioral test could match and be silently excluded while an equivalent repo gate using double quotes, another walker, or another base ref would be missed. The scanner, its test, and its justifying comment are all gone. `REPO_ROOT` and the walked roots are unchanged — both addresses are two levels below the repo root, and `TEST_ROOTS` already included `scripts`, so the gate measures exactly what it did before. The one new assertion pins the invariant this now depends on: `isKernelTestFile` accepts root/package `src` tests and rejects `scripts/__tests__`. Widening that pattern would silently pull the gate back into every lane. Verified with `pnpm mutation:run --modules kernel-errors`: scope 804 -> 803 test files, dry run clean, lane `pass` at stage complete, score 74.8% (187 killed / 63 survived / 250) — unchanged. `pnpm mutation:test` 39/39, `pnpm check:layering` 181/181, `typecheck`, `lint`, `format` clean. `stryker.config.json` is untouched, so scores stay comparable. Unblocks #1964, whose two mutation checks fail on main's tip without its code. --- .../__tests__/test-file-size-ratchet.test.ts | 4 ++-- scripts/mutation/modules.test.ts | 14 ++++++++++++++ .../android-settings-contract.ts | 2 +- vitest.config.ts | 7 +++++++ 4 files changed, 24 insertions(+), 3 deletions(-) rename {src => scripts}/__tests__/test-file-size-ratchet.test.ts (99%) diff --git a/src/__tests__/test-file-size-ratchet.test.ts b/scripts/__tests__/test-file-size-ratchet.test.ts similarity index 99% rename from src/__tests__/test-file-size-ratchet.test.ts rename to scripts/__tests__/test-file-size-ratchet.test.ts index ec134c7ab..c2dc784c3 100644 --- a/src/__tests__/test-file-size-ratchet.test.ts +++ b/scripts/__tests__/test-file-size-ratchet.test.ts @@ -1,8 +1,8 @@ import fs from 'node:fs'; import path from 'node:path'; import { expect, test } from 'vitest'; -import { walkFiles } from '../../scripts/lib/walk-files.ts'; -import { runCmdSync } from '../utils/exec.ts'; +import { walkFiles } from '../lib/walk-files.ts'; +import { runCmdSync } from '../../src/utils/exec.ts'; /** * Test-file size ratchet (AGENTS.md "Scope & shape": past 1,000 lines is architecture debt, diff --git a/scripts/mutation/modules.test.ts b/scripts/mutation/modules.test.ts index 898c74ddc..fd113ace3 100644 --- a/scripts/mutation/modules.test.ts +++ b/scripts/mutation/modules.test.ts @@ -6,6 +6,7 @@ import { fileURLToPath } from 'node:url'; import { affectedModules, ALL_MODULE_IDS, + isKernelTestFile, KERNEL_MODULES, moduleForFile, mutateGlobs, @@ -75,3 +76,16 @@ test('the shard matrix slices only the modules that declare shards', () => { ); } }); + +test('a kernel test is reachable only under root or package src', () => { + // Load-bearing for where `test-file-size-ratchet.test.ts` lives. It measures the + // repository's own files and git history, neither of which Stryker's sandbox copy can + // answer, so it sits in `scripts/__tests__/` (explicitly included by `unit-core`) and + // this predicate is what keeps it out of every mutation lane. Widening the pattern to + // scripts/ would silently pull it back in and fail every dry run. + assert.ok(isKernelTestFile('src/daemon/__tests__/ref-frame.test.ts')); + assert.ok(isKernelTestFile('packages/selectors/src/parse.test.ts')); + assert.ok(!isKernelTestFile('scripts/__tests__/test-file-size-ratchet.test.ts')); + assert.ok(!isKernelTestFile('test/integration/daemon.test.ts')); + assert.ok(!isKernelTestFile('src/daemon/ref-frame.ts')); +}); diff --git a/test/integration/provider-scenarios/android-settings-contract.ts b/test/integration/provider-scenarios/android-settings-contract.ts index c0f4b2004..ad7d0abc6 100644 --- a/test/integration/provider-scenarios/android-settings-contract.ts +++ b/test/integration/provider-scenarios/android-settings-contract.ts @@ -7,7 +7,7 @@ type AndroidSettingsWorld = Awaited