test(windows): curate the seven POSIX-bound files the expanded lane surfaced; fix flag-utils path embedding

First full run of the expanded Windows lane (13 -> ~258 files, PR #2593
run 31918591602) failed in exactly 8 files. One was a real test bug,
fixed: design-flag-utils embedded a raw Windows ROOT into a bun -e
string where backslashes act as escapes (D:\a\gstack imported as
D:agstack) — forward slashes work on every platform. The other seven
are POSIX-bound in ways the content patterns cannot see (sed/ln/bash
ARE their subject, a shebang shim arrives via variable, wall-clock
retry bounds on the slowest runner) — each gets a receipted
KNOWN_WINDOWS_INCOMPATIBLE entry, and the census pin now covers that
list so a renamed file fails the suite instead of silently keeping a
stale exclusion.
This commit is contained in:
Garry Tan 2026-08-15 18:17:15 -07:00
parent 9a9ead29e4
commit f7f402106d
No known key found for this signature in database
GPG Key ID: C1F69E85C74EFE1D
3 changed files with 45 additions and 2 deletions

View File

@ -156,7 +156,7 @@ const WINDOWS_FRAGILE_PATTERNS: Array<{ pattern: RegExp; reason: string }> = [
// pattern. Listed here with the precise reason. Prefer adding a pattern above
// when possible; this list is for environment-/runtime-specific tests where
// the failure mode is structural rather than detectable via source-file scan.
const KNOWN_WINDOWS_INCOMPATIBLE: Array<{ file: string; reason: string }> = [
export const KNOWN_WINDOWS_INCOMPATIBLE: Array<{ file: string; reason: string }> = [
{
file: 'test/host-config.test.ts',
reason: 'asserts "claude" binary on PATH (only true when running inside Claude Code, not on bare CI runner)',
@ -165,6 +165,38 @@ const KNOWN_WINDOWS_INCOMPATIBLE: Array<{ file: string; reason: string }> = [
file: 'browse/test/findport.test.ts',
reason: 'asserts Bun.serve.stop() is fire-and-forget — Bun behavior differs on Windows for this polyfill',
},
// First full run of the expanded lane (v1.66, 13 → ~258 files) surfaced
// seven POSIX-bound files the content patterns cannot see (their
// POSIX-ness is what they TEST, or arrives via a variable). Receipts:
// PR #2593 windows-free-tests run 31918591602.
{
file: 'test/regression-pr1169-build-app-sed.test.ts',
reason: 'tests sed escape sequences in build-app.sh — sed/bash are the subject under test',
},
{
file: 'test/setup-conductor-worktree.test.ts',
reason: 'tests ln -snf symlink semantics in the setup script — POSIX ln is the subject under test',
},
{
file: 'test/artifacts-init-migration.test.ts',
reason: 'runs a bash migration script + jq against a scaffolded git state — POSIX toolchain paths break under cmd spawn',
},
{
file: 'test/gstack-decision-semantic.test.ts',
reason: 'installs a fake gbrain SHEBANG SHIM on PATH; Windows spawn cannot exec shebang scripts',
},
{
file: 'test/question-log-hook.test.ts',
reason: 'spawns the PostToolUse hook script (bash shebang) directly; Windows spawn cannot exec it',
},
{
file: 'browse/test/browser-skills-e2e.test.ts',
reason: 'asserts forward-slash tier paths (<repo>/browser-skills/) that resolve with backslashes on Windows',
},
{
file: 'design/test/variants-retry-after.test.ts',
reason: 'wall-clock retry-timing assertions — flaky on the slow windows-latest runner even with widened bounds',
},
];
// Force-include overrides: files a WINDOWS_FRAGILE_PATTERNS regex excludes for

View File

@ -90,8 +90,12 @@ describe("parseIntFlag contract (#2032, codex 17a-c)", () => {
describe("normalizeIntFlag CLI wrapper (exit-1 semantics)", () => {
function runWrapper(rawExpr: string, specExpr: string): { status: number; stderr: string } {
// Forward slashes: a raw Windows ROOT embeds backslashes into the eval
// string where they act as ESCAPES ("D:\\a\\gstack" imports as
// "D:agstack" — first Windows lane run). Import specifiers accept
// forward slashes on every platform.
const script = `
import { normalizeIntFlag } from "${ROOT}/design/src/flag-utils";
import { normalizeIntFlag } from "${ROOT.replaceAll('\\', '/')}/design/src/flag-utils";
const v = normalizeIntFlag(${rawExpr}, ${specExpr});
console.log("VALUE:" + v);
`;

View File

@ -18,6 +18,7 @@ import {
DEFAULT_WALL_TIMEOUT_MS,
PER_FILE_WALL_MS,
wallTimeoutForShard,
KNOWN_WINDOWS_INCOMPATIBLE,
TEST_ROOTS,
TREE_MUTATING,
WORKER_HOSTILE,
@ -535,6 +536,12 @@ describe('test-free-shards: curated-list census pins', () => {
expect(stale).toEqual([]);
});
test('every KNOWN_WINDOWS_INCOMPATIBLE entry names a real free test file', () => {
const census = new Set(collectFreeTestFiles(ROOT));
const stale = KNOWN_WINDOWS_INCOMPATIBLE.map((e) => e.file).filter((f) => !census.has(f));
expect(stale).toEqual([]);
});
test('every TEST_ROOTS entry exists on disk and contributes at least one test file', () => {
const files = collectFreeTestFiles(ROOT);
for (const root of TEST_ROOTS) {