fix(#3308): compare guard-produced file fields against POSIX-normalized paths in Windows CI

PR #3402's real Windows CI (windows-latest node22/24) caught what gsd-test's
Linux-only lanes structurally cannot: tests/planning-snapshot-bypass-drift.test.cjs
compared the guard's own POSIX-normalized output (findSnapshotBypassDrift's
`file` field, dedupeViolationsForBaseline/sortEntries entries, a written
baseline read back from disk) against REGISTERED_FILE, which is built via
path.join('src', 'verify.cts') and is therefore backslash-separated on
Windows. The guard always normalizes its OUTPUT to POSIX via toPosixRel
regardless of the input separator form, so the comparison only ever
coincidentally passed on POSIX.

Adds REGISTERED_FILE_POSIX for every assertion against a guard-PRODUCED
value (including baseline fixtures fed into diffAgainstBaseline, which are
matched by exact string key against the guard's normalized output).
REGISTERED_FILE itself is unchanged and still used, correctly, everywhere it
is the relPath INPUT to findSnapshotBypassDrift or a DIAGNOSTIC_RULE_FUNCTIONS
Map-key lookup — both need the platform-native form to match the guard's own
Map key, which is also path.join-constructed.

No behavior change on POSIX (both constants are byte-identical there).
This commit is contained in:
sim
2026-08-12 22:54:30 -04:00
parent 1f5fc24610
commit 2bd1d12369

View File

@@ -40,6 +40,14 @@ const fs = require('node:fs');
const path = require('node:path');
const REGISTERED_FILE = path.join('src', 'verify.cts');
// The guard's OWN output (found/file fields, baseline entries) is always
// POSIX-normalized via toPosixRel, regardless of the separator form its
// `relPath` input used — comparing against the platform-native
// REGISTERED_FILE is correct for the guard's INPUT (the DIAGNOSTIC_RULE_FUNCTIONS
// Map key is also path.join-constructed, so an exact Map.has() lookup needs
// this form) but wrong for anything the guard PRODUCED, which this constant
// is for.
const REGISTERED_FILE_POSIX = REGISTERED_FILE.replace(/\\/g, '/');
const REGISTERED_FN = 'cmdValidateHealth';
// A minimal fixture carrying one registered diagnostic-rule-shaped function
@@ -72,12 +80,12 @@ describe('findSnapshotBypassDrift — G1/G3: registered function raw-read detect
assert.strictEqual(out[0].line, 2);
assert.strictEqual(out[0].found, 'platformReadSync(');
assert.strictEqual(out[0].text, 'const raw = platformReadSync(x);');
assert.strictEqual(out[0].file, REGISTERED_FILE);
assert.strictEqual(out[0].file, REGISTERED_FILE_POSIX);
});
test('G1: a registered-function violation present in the baseline is KNOWN — neither fresh nor stale', () => {
const violations = findSnapshotBypassDrift(fixtureSource(), REGISTERED_FILE);
const baseline = [{ file: REGISTERED_FILE, text: 'const raw = platformReadSync(x);' }];
const baseline = [{ file: REGISTERED_FILE_POSIX, text: 'const raw = platformReadSync(x);' }];
const { fresh, stale } = diffAgainstBaseline(violations, baseline);
assert.deepStrictEqual(fresh, []);
assert.deepStrictEqual(stale, []);
@@ -116,7 +124,7 @@ describe('findSnapshotBypassDrift — G2: function-scoped detection (not whole-f
describe('diffAgainstBaseline — G4: stale entries', () => {
test('a baseline entry whose (file, text) pair no longer appears in a fresh scan is reported under stale', () => {
const baseline = [{ file: REGISTERED_FILE, text: 'const raw = platformReadSync(oldSite);' }];
const baseline = [{ file: REGISTERED_FILE_POSIX, text: 'const raw = platformReadSync(oldSite);' }];
const violations = findSnapshotBypassDrift(fixtureSource(), REGISTERED_FILE);
const { fresh, stale } = diffAgainstBaseline(violations, baseline);
// The baseline's own (unmatched) entry is stale...
@@ -136,7 +144,7 @@ describe('writeBaseline / dedupeViolationsForBaseline — G5: regeneration match
const deduped = dedupeViolationsForBaseline(violations);
const sorted = sortEntries(deduped);
assert.strictEqual(sorted.length, 1);
assert.strictEqual(sorted[0].file, REGISTERED_FILE);
assert.strictEqual(sorted[0].file, REGISTERED_FILE_POSIX);
assert.strictEqual(sorted[0].text, 'const raw = platformReadSync(x);');
assert.strictEqual(sorted[0].count, 1);
// A freshly-written baseline must itself be immediately KNOWN (not
@@ -155,7 +163,7 @@ describe('writeBaseline / dedupeViolationsForBaseline — G5: regeneration match
const writtenPath = path.join(root, 'scripts', 'baselines', 'planning-snapshot-bypass-baseline.json');
const written = JSON.parse(fs.readFileSync(writtenPath, 'utf8'));
assert.strictEqual(written.entries.length, 1);
assert.strictEqual(written.entries[0].file, REGISTERED_FILE);
assert.strictEqual(written.entries[0].file, REGISTERED_FILE_POSIX);
assert.strictEqual(written.entries[0].text, 'const raw = platformReadSync(x);');
assert.strictEqual(written.entries[0].count, 1);
// The written baseline immediately reconciles with the pass that produced