From 5265b3002cdb7b245b1e20bc59fde4f414c72c08 Mon Sep 17 00:00:00 2001 From: ethernet Date: Wed, 8 Jul 2026 09:59:20 -0400 Subject: [PATCH] feat(agent): ban regex-scanning source code in tests Add a new AGENTS.md antipattern section: tests should NEVER read source code and regex against it! --- AGENTS.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index a3d5e5be8413..78a150ab0c35 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1354,3 +1354,58 @@ not the specific names. Reviewers should reject new change-detector tests; authors should convert them into invariants before re-requesting review. + +### Never read source code in tests + +A test that reads a source file's text is testing *the shape of the +source code*, not its behavior. This is a hard antipattern, banned outright. +Any test that reads a .py, .ts, .tsx, etc., file is suspect. + +**Why it's actively harmful, not just weak:** + +- It passes when the implementation is subtly broken (the regex matches a + call site that exists but is wired wrong) and fails when a correct + refactor changes formatting, variable names, or control flow with + identical runtime behavior. Both directions of failure are wrong. +- It can't be run against a built/bundled/minified artifact, so it silently + stops testing anything the moment code moves, gets renamed, or a + dependency reformats it. +- It actively blocks refactors: reviewers see "keeps a pattern intact" tests + fail during pure structural cleanup with no behavior change, and either + hand-wave the failure (dangerous) or waste time updating regexes that add + nothing (waste). +- It gives false confidence. a green suite full of source-regex tests + looks like coverage but has never once executed the code path it claims + to guard. + +**Do not write:** + +```ts +const source = fs.readFileSync(path.join(__dirname, 'main.ts'), 'utf8') + +test('backend spawn hides the Windows console', () => { + assert.match(source, /spawn\(\s*backend\.command,\s*backend\.args[\s\S]{0,300}hiddenWindowsChildOptions/) +}) +``` + +**Do write — extract the logic into a small pure/DI-testable function and +call it for real:** + +```ts +// backend-spawn.ts +export function hiddenWindowsChildOptions(options: SpawnOptionsLike = {}, isWindows = process.platform === 'win32') { + if (!isWindows || 'windowsHide' in options) return options + return { ...options, windowsHide: true } +} + +// backend-spawn.test.ts +test('windowsHide defaults to true on Windows, is left alone elsewhere', () => { + assert.equal(hiddenWindowsChildOptions({}, true).windowsHide, true) + assert.equal(hiddenWindowsChildOptions({}, false).windowsHide, undefined) + assert.equal(hiddenWindowsChildOptions({ windowsHide: false }, true).windowsHide, false) +}) +``` + +If the logic lives inline in a god-file (`main.ts`, `cli.py`, +`gateway/run.py`) and extracting it feels disruptive: that's the actual +signal to do the extraction, not to regex around it.