diff --git a/scripts/lib/windows-curation.ts b/scripts/lib/windows-curation.ts index 1694a0f2a..ae47103fb 100644 --- a/scripts/lib/windows-curation.ts +++ b/scripts/lib/windows-curation.ts @@ -240,6 +240,7 @@ export const KNOWN_WINDOWS_SAFE: Array<{ file: string; reason: string }> = [ { file: 'test/generator-eexist.test.ts', reason: 'E4: runs the generators through Bun argv with the Windows EEXIST emulation preload; no shebang execution' }, { file: 'test/gstack-config-gbrain-refresh.test.ts', reason: 'E6: runs bin/gstack-config through explicit bash; its gbrain/python3 shims are found by bash PATH lookup, never launched by CreateProcess' }, + { file: 'test/hook-scripts.test.ts', reason: '#3067 PowerShell and NotebookEdit hook coverage: every hook runs through spawnSync("bash", [script]) with the payload on stdin, scratch state lives under os.tmpdir(); its /tmp/ literals are payload strings, never opened; symlink, newline-path and POSIX-PATH cases are skipIf win32' }, { file: 'test/gstack-doctor.test.ts', reason: 'runs bin/gstack-doctor and setup --status through explicit bash argv in an os.tmpdir fixture; its bun/codex/claude/probe stubs are found by bash PATH lookup, and expected paths use bash spellings' }, { file: 'test/qa-evidence.test.ts', diff --git a/test/hook-scripts.test.ts b/test/hook-scripts.test.ts index 6e3a6c962..af9ee8a07 100644 --- a/test/hook-scripts.test.ts +++ b/test/hook-scripts.test.ts @@ -1209,7 +1209,8 @@ describe('check-freeze.sh', () => { // The old resolver followed the parent directory but NOT the final path // component, so an in-boundary symlink pointing outside the boundary was // allowed while the write landed outside. - test('an in-boundary symlink to an outside target denies', () => { + // Windows CI runners lack Developer Mode, so symlinkSync throws EPERM there. + test.skipIf(process.platform === 'win32')('an in-boundary symlink to an outside target denies', () => { const base = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-freeze-link-')); const boundary = path.join(base, 'boundary'); const outside = path.join(base, 'outside'); @@ -1453,7 +1454,8 @@ describe('gstack_hook_log_fire writes under the resolved state root', () => { }); }); - test('a GSTACK_HOME ending in a newline round-trips exactly (writer %q and reader sentinel agree)', () => { + // NTFS rejects a newline in a directory name. + test.skipIf(process.platform === 'win32')('a GSTACK_HOME ending in a newline round-trips exactly (writer %q and reader sentinel agree)', () => { const base = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-freeze-nl-')); const nlDir = path.join(base, 'root\n'); fs.mkdirSync(nlDir); @@ -1468,7 +1470,8 @@ describe('gstack_hook_log_fire writes under the resolved state root', () => { } }); - test('an unexpected set -e death inside the hook (a tool on PATH failing) DENIES via the EXIT backstop instead of exiting with no JSON', () => { + // The fake tool is prepended with a POSIX ':' PATH separator. + test.skipIf(process.platform === 'win32')('an unexpected set -e death inside the hook (a tool on PATH failing) DENIES via the EXIT backstop instead of exiting with no JSON', () => { const base = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-freeze-backstop-')); const fakeBin = path.join(base, 'bin'); fs.mkdirSync(fakeBin);