Merge origin/main (v1.64.0.0) into garrytan/time-attack-fork-review

Both waves fixed several of the same bugs; resolutions keep whichever
shape this branch's tests pin (#2018 jq bind, #1798 set-- pattern,
stop-ack, lock errors, polyfill windowsHide) and take main's richer
codex Step 2A (it absorbed the same mktemp fix). True unions: memory-
ingest keeps main's capability-probed --include-gitignored inside our
GIT_CEILING defense; setup wraps main's Playwright platform override in
our stale-healing install lock; package.json takes main's diff@^9 and
the combined test glob (design/test + ios-qa/daemon/test, 30s timeout).
Generated SKILL.md files regenerated from resolved templates, never
hand-picked. Ship goldens refreshed; parity/carve budgets re-measured
for the summed preamble growth of both waves (itemized per entry).
This commit is contained in:
Garry Tan
2026-08-15 09:57:34 -07:00
241 changed files with 7683 additions and 4716 deletions
+62 -5
View File
@@ -30,10 +30,11 @@ import { spawnSync } from 'child_process';
import { isPaidTestFile } from '../test/helpers/paid-test-set';
const ROOT = path.resolve(import.meta.dir, '..');
// ios-qa/daemon/test joined in fork port wave 2 (E2): its 5 files were
// invisible to every runner — the exact design/test-class hole TODOS tracks.
// All are hermetic (stub state-servers on ephemeral ports, no devices).
const TEST_ROOTS = ['browse/test', 'test', 'make-pdf/test', 'ios-qa/daemon/test'] as const;
// design/test and ios-qa/daemon/test were both silently absent from every
// runner (package.json glob + this list) — design tests (including a teardown
// bomb) and the 10 hermetic ios-qa daemon suites never ran in any CI or local
// free run. Keep the two lists in sync with package.json's test script.
const TEST_ROOTS = ['browse/test', 'test', 'make-pdf/test', 'design/test', 'ios-qa/daemon/test'] as const;
const TEST_FILE_REGEX = /\.test\.(?:[cm]?[jt]s|tsx|jsx)$/;
// POSIX-only patterns that indicate a test will fail on windows-latest no
@@ -101,6 +102,32 @@ const KNOWN_WINDOWS_INCOMPATIBLE: Array<{ file: string; reason: string }> = [
},
];
// Force-include overrides: files a WINDOWS_FRAGILE_PATTERNS regex excludes for
// a reason that does not actually apply to them. Each entry documents WHY the
// pattern hit is a false positive — the point of these files is Windows
// coverage, so auto-excluding them defeats the regression tests they carry.
const KNOWN_WINDOWS_SAFE: Array<{ file: string; reason: string }> = [
{
file: 'browse/test/file-permissions.test.ts',
// Trips the POSIX-mode-bitmask pattern, but every `mode & 0o777` assertion
// is platform-guarded (win32 returns early / takes the icacls branch).
// This file carries the win32-only icacls-by-SID regression tests, which
// can ONLY execute on windows-latest — excluding it here means the
// machine-account ACL lockout regression is never exercised on the one
// platform it bricks.
reason: 'mode-bitmask hits are POSIX-branch only; win32-only ACL regression tests must run on windows-latest',
},
{
file: 'browse/test/terminal-agent-owner-watchdog.test.ts',
// Trips the spawn(['bun','run',...]) pattern, whose reason is the
// Playwright-bound browse server. This test spawns terminal-agent.ts,
// which imports only fs/path/crypto + local helpers (no Playwright, no
// PTY at module scope) and boots under Bun on Windows — the owner-PID
// orphan leak it pins was reported on Windows (#2019).
reason: 'spawns terminal-agent (no Playwright), not the browse server; owner-orphan leak is a Windows defect',
},
];
export const DEFAULT_SHARD_COUNT = 20;
export const FREE_TEST_TIMEOUT_MS = 10_000;
@@ -170,12 +197,17 @@ export function curateWindowsSafe(files: string[], rootDir = ROOT): CurationResu
const safe: string[] = [];
const excluded: Array<{ file: string; reason: string }> = [];
const knownBad = new Map(KNOWN_WINDOWS_INCOMPATIBLE.map((e) => [e.file, e.reason]));
const knownSafe = new Set(KNOWN_WINDOWS_SAFE.map((e) => e.file));
for (const relativePath of files) {
const knownReason = knownBad.get(relativePath);
if (knownReason) {
excluded.push({ file: relativePath, reason: knownReason });
continue;
}
if (knownSafe.has(relativePath)) {
safe.push(relativePath);
continue;
}
const absolute = path.join(rootDir, relativePath);
const fragility = detectWindowsFragility(absolute);
if (fragility) {
@@ -264,14 +296,39 @@ function formatShardSummary(shards: string[][]): string[] {
});
}
/**
* True when a shard's output shows the run ended WITHOUT bun's final summary
* ("Ran N tests across ..."). A process.exit() fired mid-suite skips the
* summary AND hands back whatever code the caller passed — historically 0,
* which made a truncated shard indistinguishable from a green one. Exit code
* alone is therefore not evidence of completion; the summary line is.
* (Fault-injection coverage: test/exit-propagation.test.ts.)
*/
export function shardRunLooksTruncated(status: number | null, output: string): boolean {
if (status !== 0) return false; // already failing — not the silent case
return !/Ran \d+ tests? across \d+ files?/.test(output);
}
function runShard(files: string[], shardNumber: number, totalShards: number): number {
const header = `[test:free] shard ${shardNumber}/${totalShards} (${files.length} files)`;
console.log(header);
const result = spawnSync(process.execPath, buildShardArgs(files), {
cwd: ROOT,
stdio: 'inherit',
stdio: ['ignore', 'pipe', 'pipe'],
encoding: 'utf8',
env: process.env,
});
// Preserve the inherit-style UX: replay the shard's output.
if (result.stdout) process.stdout.write(result.stdout);
if (result.stderr) process.stderr.write(result.stderr);
const combined = `${result.stdout ?? ''}${result.stderr ?? ''}`;
if (shardRunLooksTruncated(result.status, combined)) {
console.error(
`${header} exited 0 WITHOUT bun's final summary — the run was truncated ` +
'(a process.exit fired mid-suite). Treating as FAILED.',
);
return 1;
}
if (result.status !== 0) {
console.error(`${header} failed with exit code ${result.status ?? 1}`);
}