Surfaced in the 2026-07-16 whole-repo audit. Windows-only; not verifiable on the macOS dev host, so filed rather than fixed blind.
Problem
agent/exec.go calls cmd.Start() then procCtl.AfterStart(cmd) → AssignProcessToJobObject (agent/sysproc_windows.go). exec.Cmd.Start() creates the child running immediately — no CREATE_SUSPENDED — so between Start() returning and the Job Object assignment completing, the child can spawn a grandchild that never becomes a job member. That grandchild then survives JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE when the session ends via windowsProcessController.close().
This is the Windows analogue of the guarantee Linux gets from Setpgid + process-group kill (covered by TestServerExecBackgroundChildDoesNotPinSession), which has no Windows equivalent test.
Fix direction
Create the process with CREATE_SUSPENDED via a raw windows.CreateProcess (os/exec doesn't expose the primary thread handle needed to resume), assign to the Job Object, then ResumeThread. Alternatively, document the narrow race as accepted.
Acceptance
- A Windows exec whose child immediately spawns a grandchild: ending the session kills both (Job Object membership established at creation, pre-resume).
- A Windows-target test mirroring
TestServerExecBackgroundChildDoesNotPinSession.
- Verified on a Windows runner, not a mac-only green.
Surfaced in the 2026-07-16 whole-repo audit. Windows-only; not verifiable on the macOS dev host, so filed rather than fixed blind.
Problem
agent/exec.gocallscmd.Start()thenprocCtl.AfterStart(cmd)→AssignProcessToJobObject(agent/sysproc_windows.go).exec.Cmd.Start()creates the child running immediately — noCREATE_SUSPENDED— so betweenStart()returning and the Job Object assignment completing, the child can spawn a grandchild that never becomes a job member. That grandchild then survivesJOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSEwhen the session ends viawindowsProcessController.close().This is the Windows analogue of the guarantee Linux gets from
Setpgid+ process-group kill (covered byTestServerExecBackgroundChildDoesNotPinSession), which has no Windows equivalent test.Fix direction
Create the process with
CREATE_SUSPENDEDvia a rawwindows.CreateProcess(os/exec doesn't expose the primary thread handle needed to resume), assign to the Job Object, thenResumeThread. Alternatively, document the narrow race as accepted.Acceptance
TestServerExecBackgroundChildDoesNotPinSession.