fix: claude CLI version resolves in the runner parent, never on a test thread

Eng-review finding: getClaudeCliVersion's fallback is a SYNCHRONOUS
spawnSync on the same thread that polls concurrent PTY/session tests — the
judgePtyState blocking class this overhaul kills elsewhere. The paid runner
parent now resolves it once (cached) and stamps GSTACK_CLAUDE_CLI_VERSION
into every shard's env; eval-store short-circuits on the env var, and the
fallback spawn's budget tightens 10s -> 3s (bounded one-time stall, records
'unknown' on a slow CLI).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-08-31 04:34:57 +00:00
co-authored by Claude Fable 5
parent cfcc9ecc6f
commit 31bb69f9b4
2 changed files with 20 additions and 2 deletions
+13 -1
View File
@@ -786,11 +786,23 @@ function getVersion(): string {
// claude-CLI TUI drift only after long flake hunts — stamping the version
// into every run record makes that correlation a grep instead of an
// archaeology dig.
//
// GSTACK_CLAUDE_CLI_VERSION short-circuits the spawn entirely: the paid
// runner's parent resolves the version once and passes it to every shard,
// so test processes never block on it. The fallback spawn is SYNCHRONOUS on
// the same thread that polls PTY sessions — the judgePtyState blocking
// class — so its budget is a tight 3s, not a generous one: a slow/hung CLI
// costs one bounded stall per process and records 'unknown'.
let claudeCliVersionCache: string | null = null;
export function getClaudeCliVersion(): string {
if (claudeCliVersionCache !== null) return claudeCliVersionCache;
const fromEnv = process.env.GSTACK_CLAUDE_CLI_VERSION;
if (fromEnv) {
claudeCliVersionCache = fromEnv;
return claudeCliVersionCache;
}
try {
const result = spawnSync('claude', ['--version'], { stdio: 'pipe', timeout: 10_000 });
const result = spawnSync('claude', ['--version'], { stdio: 'pipe', timeout: 3_000 });
claudeCliVersionCache = result.stdout?.toString().split('\n')[0].trim() || 'unknown';
} catch {
claudeCliVersionCache = 'unknown';