From 6841d82a98916b9c39b126cee9f452dd39ac90c1 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Tue, 28 Apr 2026 00:15:50 -0700 Subject: [PATCH] fix(windows-ci): gen:skill-docs in workflow + known-bad list for env-specific tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Round 9 of windows-free-tests fixes. Round 8 cleared shard 7; shard 8 surfaced 4 fails: 1+2. test/gen-skill-docs.test.ts golden-file regression for Codex + Factory ship skills failed with ENOENT on `.agents/skills/gstack-ship/SKILL.md` and `.factory/skills/gstack-ship/SKILL.md`. These are gitignored gen-skill-docs outputs that the Mac/Linux CI workflows already regenerate elsewhere — the windows-free-tests lane never did. Fix: add `bun run gen:skill-docs --host all` step to windows-free-tests.yml after `bun install`. 3. test/host-config.test.ts:377 "detect finds claude" asserts the `claude` binary is on PATH. True when running inside Claude Code; false on a bare CI runner. 4. browse/test/findport.test.ts:117 asserts Bun.serve.stop() is fire-and-forget (returns undefined). Bun's Windows behavior for this polyfill differs; the assertion is Bun-on-non-Windows-specific. Both 3 and 4 are environment/runtime-specific failures that don't fit a regex pattern. Added a KNOWN_WINDOWS_INCOMPATIBLE explicit list to scripts/test-free-shards.ts so they're curated by exact path, with a reason string. The list is for cases where pattern matching can't infer the failure shape from the source file alone. Curated subset: 66 → 64 tests (~50% of free suite). 14 unit tests in test/test-free-shards.test.ts still pass. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/windows-free-tests.yml | 10 ++++++++++ scripts/test-free-shards.ts | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/.github/workflows/windows-free-tests.yml b/.github/workflows/windows-free-tests.yml index 0c7e69e2..037f1344 100644 --- a/.github/workflows/windows-free-tests.yml +++ b/.github/workflows/windows-free-tests.yml @@ -57,6 +57,16 @@ jobs: run: bash browse/scripts/build-node-server.sh shell: bash + - name: Generate host SKILL.md outputs (.agents, .factory) + # The golden-file regression tests in test/gen-skill-docs.test.ts read + # .agents/skills/gstack-ship/SKILL.md and .factory/skills/gstack-ship/ + # SKILL.md. Both are gitignored — generated on demand by gen:skill-docs. + # On Mac/Linux CI the existing eval workflow regenerates these as part + # of its own pipeline; the windows-free-tests lane doesn't share that + # so it must regenerate explicitly. + run: bun run gen:skill-docs --host all + shell: bash + - name: Show curated subset (for build log audit trail) run: bun run scripts/test-free-shards.ts --windows-only --list shell: bash diff --git a/scripts/test-free-shards.ts b/scripts/test-free-shards.ts index 94b4d53f..9407c83d 100755 --- a/scripts/test-free-shards.ts +++ b/scripts/test-free-shards.ts @@ -86,6 +86,21 @@ const WINDOWS_FRAGILE_PATTERNS: Array<{ pattern: RegExp; reason: string }> = [ { pattern: /BROWSE_HEADLESS_SKIP|spawn\(\[['"]bun['"],\s*['"]run['"]/, reason: 'spawns the browse server subprocess (Bun-driven path is Windows-broken)' }, ]; +// Explicit known-Windows-incompatible test files that don't fit a regex +// 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 }> = [ + { + file: 'test/host-config.test.ts', + reason: 'asserts "claude" binary on PATH (only true when running inside Claude Code, not on bare CI runner)', + }, + { + file: 'browse/test/findport.test.ts', + reason: 'asserts Bun.serve.stop() is fire-and-forget — Bun behavior differs on Windows for this polyfill', + }, +]; + export const DEFAULT_SHARD_COUNT = 20; export const FREE_TEST_TIMEOUT_MS = 10_000; @@ -154,7 +169,13 @@ export interface CurationResult { export function curateWindowsSafe(files: string[], rootDir = ROOT): CurationResult { const safe: string[] = []; const excluded: Array<{ file: string; reason: string }> = []; + const knownBad = new Map(KNOWN_WINDOWS_INCOMPATIBLE.map((e) => [e.file, e.reason])); for (const relativePath of files) { + const knownReason = knownBad.get(relativePath); + if (knownReason) { + excluded.push({ file: relativePath, reason: knownReason }); + continue; + } const absolute = path.join(rootDir, relativePath); const fragility = detectWindowsFragility(absolute); if (fragility) {