On 2026-09-29, 41 serve-strict processes had outlived the gates that started them: 279 MB resident,
the oldest 5.3 days, spread across eight worktrees. A gate that crashes, is killed, or is refused by the
browser-slot guard's process.exit cannot run its own srv.kill(), and _serve-reaped's handlers cover
signals and normal exit but not a SIGKILLed parent.
serve-strict takes --exit-with-parent: it records the pid that started it and exits within 2 s once
that process is gone. Opt-in, so a server someone deliberately left running is never taken down.
Every internal/ gate and tool that spawns it now passes the flag (14 files, plus _serve-reaped, the
shared helper). Proven: a parent that spawns the server with the flag and exits abruptly (as the
guard does) leaves it alive for a moment and gone within 3 s.
The orphans already running belong to other worktrees' runs and are left to their owners; plugin-local
scripts that spawn serve-strict should pass the flag too.
Twelve gates here spawn serve-strict and eleven reap it only on the
happy path — srv.kill() at the end of the script. That holds until the
end is not reached. When the box ran low on memory it killed gate
processes mid-run, and every server those gates had spawned was
orphaned: ten in one worktree, four in another. Each orphan holds
memory, which makes the next kill likelier, which orphans more. The
leak feeds the condition that causes it.
Both halves measured rather than argued. A script using the old spawn
was sent SIGTERM and its server was still answering afterwards —
orphan reproduced on demand. The same script using this helper left
nothing behind.
The helper registers the child against SIGTERM, SIGINT, SIGHUP and
normal exit, and unregisters when stopped deliberately, so it is safe
in a finally block. Nothing survives SIGKILL and nothing can, which is
why the port is returned too — a sweep needs something to look for.
This gate adopts it; it still passes, and its negative control still
discriminates. The other ten are other agents' files, so they get the
one-line change offered rather than applied.