From df57973e38de76a02f83a677d8ef2ef2291f562f Mon Sep 17 00:00:00 2001 From: Dotta Date: Sat, 7 Nov 2026 12:53:48 -0600 Subject: [PATCH] test(evals): accept node flags before the proxy script; record closed process facts The runner's provider chain is three processes deep and nothing qualified. Allow node runtime flags before the absolute proxy script (still last, still digest checked), and record each descendant's command name, argument count and script basenames so the next refusal shows why. Co-Authored-By: Claude Opus 5.5 --- .../chat-catalog-domains/runtime-provider-cleanup.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/runner-e2e/chat-catalog-domains/runtime-provider-cleanup.ts b/tests/runner-e2e/chat-catalog-domains/runtime-provider-cleanup.ts index 5392c865f94..1a63913a639 100644 --- a/tests/runner-e2e/chat-catalog-domains/runtime-provider-cleanup.ts +++ b/tests/runner-e2e/chat-catalog-domains/runtime-provider-cleanup.ts @@ -31,7 +31,9 @@ async function providerIdentity(pid: number): Promise { const [uid, parent, executable, command, startedAt] = await Promise.all([ps("uid"), ps("ppid"), ps("comm"), ps("args"), readProcessStartedAt(pid)]); const canonical = await realpath(ownedNativeExecutablePath(pid, executable)); const args = command.split(/\s+/); - const proxy = args.length === 2 && path.isAbsolute(args[1]!) && path.basename(args[1]!) === "opencode-app-server-proxy.cjs" ? await realpath(args[1]!) : undefined; + // node may carry runtime flags before the script; the absolute proxy script is the last argument. + const script = args.at(-1)!, flags = args.slice(1, -1); + const proxy = args.length >= 2 && path.isAbsolute(script) && path.basename(script) === "opencode-app-server-proxy.cjs" && flags.every(arg => /^--[a-z][a-z0-9-]*(?:=[^\s]*)?$/.test(arg)) ? await realpath(script) : undefined; const proxyDigest = proxy ? createHash("sha256").update(await readFile(proxy)).digest("hex") : undefined; if (!startedAt) throw new Error("missing start identity"); return { pid, parentPid: Number(parent), uid: Number(uid), startedAt, executable: canonical, @@ -45,14 +47,16 @@ async function providerIdentity(pid: number): Promise { async function soleProviderDescendant(ctx: ChatCatalogContext, runnerPid: number, kind: "codex" | "opencode"): Promise<{ pid: number; parentPid: number } | undefined> { const rows = (await promisify(execFile)("/bin/ps", ["-A", "-o", "pid=,ppid="], { timeout: 5_000, maxBuffer: 1_048_576 })).stdout .split("\n").map(line => line.trim().split(/\s+/).map(Number)).filter(([pid, parent]) => Number.isSafeInteger(pid) && Number.isSafeInteger(parent)); - const seen: Array<{ depth: number; executable: string | null; proxy: boolean; appServer: boolean; openCodeServe: boolean }> = []; + const seen: Array<{ depth: number; command: string | null; argCount: number | null; scripts: string[]; executable: string | null; proxy: boolean; appServer: boolean; openCodeServe: boolean }> = []; const providers: Array<{ pid: number; parentPid: number }> = []; let frontier = [runnerPid]; for (let depth = 1; depth <= 4 && frontier.length; depth += 1) { const next = rows.filter(([, parent]) => frontier.includes(parent!)).map(([pid, parent]) => ({ pid: pid!, parent: parent! })); for (const { pid, parent } of next) { const identity = await providerIdentity(pid).catch(() => undefined); - seen.push({ depth, executable: identity ? path.basename(identity.executable) : null, proxy: !!identity?.proxyScript, appServer: !!identity?.appServer, openCodeServe: !!identity?.openCodeServe }); + const args = await promisify(execFile)("/bin/ps", ["-p", String(pid), "-o", "args="], { timeout: 5_000, maxBuffer: 65_536 }).then(out => out.stdout.trim().split(/\s+/), () => null); + const command = await promisify(execFile)("/bin/ps", ["-p", String(pid), "-o", "comm="], { timeout: 5_000, maxBuffer: 65_536 }).then(out => path.basename(out.stdout.trim()) || null, () => null); + seen.push({ depth, command, argCount: args?.length ?? null, scripts: (args ?? []).filter(arg => /\.(?:c|m)?js$/.test(arg)).map(arg => path.basename(arg)), executable: identity ? path.basename(identity.executable) : null, proxy: !!identity?.proxyScript, appServer: !!identity?.appServer, openCodeServe: !!identity?.openCodeServe }); if (identity && (kind === "opencode" ? !!identity.proxyScript || identity.openCodeServe : identity.appServer)) providers.push({ pid, parentPid: parent }); } frontier = next.map(row => row.pid);