From 7e007c0aded115a694d85011bf9b6329726742bb Mon Sep 17 00:00:00 2001 From: RSI smoke Date: Tue, 13 Oct 2026 06:41:30 -0600 Subject: [PATCH] Kill watcher fixtures directly instead of via denied group signals The headlesscode-job tests cleaned up exec'd sleep fixtures with process.kill(-pid), which is EPERM in the eval sandbox. The kill was swallowed, the fixture survived, and the watcher (correctly, via procfs) still saw a live group, failing the baseline gate. The fixtures are single-process groups, so direct child kill is exactly equivalent and policy-immune. --- src/watcher/__tests__/headlesscode-job.test.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/watcher/__tests__/headlesscode-job.test.ts b/src/watcher/__tests__/headlesscode-job.test.ts index b9a801b..344311d 100644 --- a/src/watcher/__tests__/headlesscode-job.test.ts +++ b/src/watcher/__tests__/headlesscode-job.test.ts @@ -138,7 +138,9 @@ async function testForgedWorktreeMarkersCannotFinishLiveWorker(): Promise assert.equal(h.closed, false, "worker-controlled markers cannot close an issue while its process group is live") } finally { if (child.pid) { - try { process.kill(-child.pid, "SIGKILL") } catch { /* fixture already exited */ } + // Direct kill: the exec'd fixture is a single-process group, + // and group signals are denied in the eval sandbox. + try { child.kill("SIGKILL") } catch { /* fixture already exited */ } } } await run(h) @@ -198,7 +200,9 @@ async function testStaleAttemptAndUnknownIdentityStayRunning(): Promise { assert.equal((await loadWatcherState(h.stateFile)).processed[String(h.issue.number)]?.status, "spawned", "a reused PID does not prove the captured process group is gone") } finally { if (reused.pid) { - try { process.kill(-reused.pid, "SIGKILL") } catch { /* fixture already exited */ } + // Direct kill: the exec'd fixture is a single-process group, + // and group signals are denied in the eval sandbox. + try { reused.kill("SIGKILL") } catch { /* fixture already exited */ } } } }