Follow-up from PR #1112 code review (open). The orphan reaper is the right direction, but the current startup path is too aggressive for production use.
Problem
On every daemon start, cleanupWebBrowserOrphans() SIGTERM/SIGKILLs all Chrome processes matching the managed install (launch marker or managed home path), with no check against:
- active daemon web sessions,
- agent-browser control socket / PID ownership, or
- recent browser activity.
After a quick daemon restart while a user still has a page open (or a long-running web workflow outside formal close), the new daemon kills the browser before accepting requests.
Additional gaps in the same PR:
provider-startup cleanup reason is declared but never wired — orphans from a crashed web provider while the daemon stays alive are not reaped until the next full daemon restart.
stopMatchedProcesses signals only top-level PIDs, not the Chrome process tree (renderer/GPU children can survive).
- Home-path matching may be over-broad (bare
homeDir / runtimeHomeDir vs .agent-browser/browsers subtree).
- No tests for actual reap behavior (signal escalation, TERM→KILL, leave-unmatched-alone).
Suggested direction
- Reap only provably orphaned processes: no matching agent-browser socket/PID lock, idle beyond
AGENT_BROWSER_IDLE_TIMEOUT_MS, or start time before last daemon shutdown marker. Skip reaping when session store reports an open web session for that stateDir.
- Wire
provider-startup from the web provider factory on first resolve (with debounce).
- Walk process tree or kill process group for matched Chrome processes.
- Add unit tests with mocked
ps / process.kill.
Acceptance
- Daemon restart does not kill a managed browser that an active session still owns.
- Crashed-provider orphans are reaped without requiring a full daemon restart.
- Tests cover reap signal order and process-tree coverage.
Context
Follow-up from PR #1112 code review (open). The orphan reaper is the right direction, but the current startup path is too aggressive for production use.
Problem
On every daemon start,
cleanupWebBrowserOrphans()SIGTERM/SIGKILLs all Chrome processes matching the managed install (launch marker or managed home path), with no check against:After a quick daemon restart while a user still has a page open (or a long-running web workflow outside formal
close), the new daemon kills the browser before accepting requests.Additional gaps in the same PR:
provider-startupcleanup reason is declared but never wired — orphans from a crashed web provider while the daemon stays alive are not reaped until the next full daemon restart.stopMatchedProcessessignals only top-level PIDs, not the Chrome process tree (renderer/GPU children can survive).homeDir/runtimeHomeDirvs.agent-browser/browserssubtree).Suggested direction
AGENT_BROWSER_IDLE_TIMEOUT_MS, or start time before last daemon shutdown marker. Skip reaping when session store reports an open web session for thatstateDir.provider-startupfrom the web provider factory on first resolve (with debounce).ps/process.kill.Acceptance
Context