diff --git a/src/process/supervisor/adapters/child.test.ts b/src/process/supervisor/adapters/child.test.ts index 691c98d076..b2f7c59fb4 100644 --- a/src/process/supervisor/adapters/child.test.ts +++ b/src/process/supervisor/adapters/child.test.ts @@ -60,8 +60,15 @@ describe("createChildAdapter", () => { options?: { detached?: boolean }; fallbacks?: Array<{ options?: { detached?: boolean } }>; }; - expect(spawnArgs.options?.detached).toBe(true); - expect(spawnArgs.fallbacks?.[0]?.options?.detached).toBe(false); + // On Windows, detached defaults to false (headless Scheduled Task compat); + // on POSIX, detached is true with a no-detach fallback. + if (process.platform === "win32") { + expect(spawnArgs.options?.detached).toBe(false); + expect(spawnArgs.fallbacks).toEqual([]); + } else { + expect(spawnArgs.options?.detached).toBe(true); + expect(spawnArgs.fallbacks?.[0]?.options?.detached).toBe(false); + } adapter.kill(); diff --git a/src/process/supervisor/adapters/child.ts b/src/process/supervisor/adapters/child.ts index 4bd5be0e06..1db291e933 100644 --- a/src/process/supervisor/adapters/child.ts +++ b/src/process/supervisor/adapters/child.ts @@ -42,11 +42,17 @@ export async function createChildAdapter(params: { const stdinMode = params.stdinMode ?? (params.input !== undefined ? "pipe-closed" : "inherit"); + // On Windows, `detached: true` creates a new process group and can prevent + // stdout/stderr pipes from connecting when running under a Scheduled Task + // (headless, no console). Default to `detached: false` on Windows; on + // POSIX systems keep `detached: true` so the child survives parent exit. + const useDetached = process.platform !== "win32"; + const options: SpawnOptions = { cwd: params.cwd, env: params.env ? toStringEnv(params.env) : undefined, stdio: ["pipe", "pipe", "pipe"], - detached: true, + detached: useDetached, windowsHide: true, windowsVerbatimArguments: params.windowsVerbatimArguments, }; @@ -59,12 +65,14 @@ export async function createChildAdapter(params: { const spawned = await spawnWithFallback({ argv: resolvedArgv, options, - fallbacks: [ - { - label: "no-detach", - options: { detached: false }, - }, - ], + fallbacks: useDetached + ? [ + { + label: "no-detach", + options: { detached: false }, + }, + ] + : [], }); const child = spawned.child as ChildProcessWithoutNullStreams;