pregate: count a module's full file name without a directory as a consumer

consumersOf anchored both the stem and the full basename on a path
separator, so run('install.sh') or bash install.sh without a directory
stopped counting for a multi-character old value. Only the bare stem
needs the separator; the full file name is specific on its own.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
garrytanandcapy-ai[bot] committed 2026-10-26 15:32:55 +00:00
1 parent 213ffe9d2e
commit e890d0d225
2 files changed
+7 -5

No files matched your search

+3 -3
View File
@@ -61,8 +61,8 @@ function unquote(v: string): string { return /^['"`]/.test(v) ? v.slice(1, -1) :
/**
* Test files that still carry the old literal beside the constant's name or
* its module. The module counts only as a path fragment (`/install.sh`,
* `/retry.js`, `/retry'`): a bare stem such as `install` or `retry` is an
* its module. The module counts as its full file name (`install.sh`) or as a
* path fragment (`/retry.js`, `/retry'`): a bare stem such as `install` or `retry` is an
* English word in half the test tree, and a one-character old value (`2`)
* sits in every test, so that value needs the constant's name (a wrapper
* version 2 → 3 flagged 575 consumers through the stem alone).
@@ -72,7 +72,7 @@ export function consumersOf(repoRoot: string, testFiles: readonly string[], chan
const valueRe = /^-?\d/.test(value) ? new RegExp(`(?<![\\w.])${escape(value)}(?![\\w.])`) : new RegExp(`['"\`]${escape(value)}['"\`]`);
const base = path.basename(change.file);
const stem = base.replace(/\.[^.]+$/, '');
const moduleRe = new RegExp(`(?:^|[/\\\\])(?:${escape(base)}|${escape(stem)})(?![\\w-])`, 'm');
const moduleRe = new RegExp(`(?:(?:^|[/\\\\])${escape(stem)}|(?<![\\w-])${escape(base)})(?![\\w-])`, 'm');
const nameRe = new RegExp(`\\b${escape(change.name)}\\b`);
const nameRequired = value.length < 2;
const hits: string[] = [];
+4 -2
View File
@@ -211,14 +211,16 @@ describe('literals (pure)', () => {
'test/other.test.ts': ['expect(install.steps.length).toBe(2);', ''].join(nl),
'test/retry.test.ts': ["expect(require('../lib/retry.js').TIMEOUT_MS).toBe(5000);", ''].join(nl),
'test/retry-path.test.ts': ["const mod = require('../lib/retry.js');", 'expect(mod.wait()).toBe(5000);', ''].join(nl),
'test/retry-bare.test.ts': ["const mod = load('retry.js');", 'expect(mod.wait()).toBe(5000);', ''].join(nl),
'test/reretry.test.ts': ["const mod = load('preretry.js');", 'expect(mod.wait()).toBe(5000);', ''].join(nl),
'test/retry-words.test.ts': ['// the retry budget was 5000 once', 'expect(elapsed).toBeLessThan(5000);', ''].join(nl),
};
for (const [rel, text] of Object.entries(files)) { fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); fs.writeFileSync(path.join(root, rel), text); }
const all = Object.keys(files);
// A one-character value: only the file that names the constant counts; the path fragment alone is not enough for "2".
expect(consumersOf(root, all, { name: 'GSTACK_CAPY_WRAPPER', old: '2', new: '3', file: 'capy/skill/gstack/scripts/install.sh' })).toEqual(['test/wrapper.test.ts:2']);
// A longer value: the constant's name or the module as a path fragment; the bare word "retry" in prose does not count.
expect(consumersOf(root, all, { name: 'TIMEOUT_MS', old: '5000', new: '9000', file: 'lib/retry.js' })).toEqual(['test/retry.test.ts:1', 'test/retry-path.test.ts:2']);
// A longer value: the constant's name, the module's full file name, or its stem as a path fragment; the bare word "retry" in prose and "preretry.js" do not count.
expect(consumersOf(root, all, { name: 'TIMEOUT_MS', old: '5000', new: '9000', file: 'lib/retry.js' })).toEqual(['test/retry.test.ts:1', 'test/retry-path.test.ts:2', 'test/retry-bare.test.ts:2']);
fs.rmSync(root, { recursive: true, force: true });
});
test('runner summaries: bun, node --test, vitest, jest, pytest, zero-run', () => {