Bounty eligibility
Stage
connect
Coding agent
OpenAI Codex
Coding agent version
Codex desktop; Monk plugin v0.1.47 (271cf17)
Repro steps
The POSIX launcher stops a recorded background companion and starts its replacement without waiting for the old process to exit:
if [ -f "$pid_file" ]; then
old_pid="$(cat "$pid_file" 2>/dev/null || true)"
if [ -n "$old_pid" ]; then
kill "$old_pid" >/dev/null 2>&1 || true
fi
fi
# replacement starts immediately
That creates a deterministic restart race when the old companion needs time to release its listener:
- Start an isolated old companion fixture whose health endpoint remains available for two seconds after SIGTERM.
- Put its PID in the launcher's normal
monk-agent.pid path.
- Make the managed-agent ensure step install a different executable so
agent_updated=1 and the healthy fast path is bypassed.
- Make the replacement fixture match
monk-agent's healthy-port-conflict behavior: if the old endpoint is still present, defer to it and exit 0.
- Run the unmodified v0.1.47
scripts/start-monk-agent.sh through its Linux background-process path, with health and process behavior isolated behind local filesystem stubs.
- After the launcher returns, wait for the old process's two-second shutdown to complete and check whether the replacement is alive.
Observed on repeated runs:
launcher_exit=0
old_companion_alive=no
replacement_companion_alive=no
replacement_start_attempts=1
launcher returned success before the replacement companion was running
The replacement starts while the old companion still owns the simulated endpoint and exits cleanly. The launcher's first readiness check then reaches the old companion and returns success. Once the delayed old shutdown finishes, no companion remains and the PID file points to the exited replacement.
This is distinct from existing reports:
Repository searches for restart handoff, replacement companion, old agent port, port conflict restart, start_with_background_process wait, and binary update launcher found no same-scope issue or PR.
Expected behavior
A managed POSIX restart should complete the old companion's shutdown before launching its replacement. Returning success must mean the replacement process—not the process being stopped—has passed readiness and remains running.
Actual behavior
The replacement can start before the old companion releases the port, defer to the old healthy process, and exit. The launcher then mistakes the stopping old process for successful replacement readiness and exits 0. Shortly afterward both processes are gone and Monk MCP is unavailable despite the successful SessionStart hook.
Severity (your guess)
major
OS
macOS 26.5.2, Apple Silicon, using the shipped POSIX launcher's Linux background-process path with deterministic process/health stubs
monkd version
Not involved; failure occurs in local companion restart handoff before any monkd operation
Target cloud
None; local companion only
Integration (if relevant)
Monk plugin POSIX SessionStart launcher for Codex and Claude Code
Bounty eligibility
Stage
connect
Coding agent
OpenAI Codex
Coding agent version
Codex desktop; Monk plugin v0.1.47 (271cf17)
Repro steps
The POSIX launcher stops a recorded background companion and starts its replacement without waiting for the old process to exit:
That creates a deterministic restart race when the old companion needs time to release its listener:
monk-agent.pidpath.agent_updated=1and the healthy fast path is bypassed.monk-agent's healthy-port-conflict behavior: if the old endpoint is still present, defer to it and exit 0.scripts/start-monk-agent.shthrough its Linux background-process path, with health and process behavior isolated behind local filesystem stubs.Observed on repeated runs:
The replacement starts while the old companion still owns the simulated endpoint and exits cleanly. The launcher's first readiness check then reaches the old companion and returns success. Once the delayed old shutdown finishes, no companion remains and the PID file points to the exited replacement.
This is distinct from existing reports:
Repository searches for
restart handoff,replacement companion,old agent port,port conflict restart,start_with_background_process wait, andbinary update launcherfound no same-scope issue or PR.Expected behavior
A managed POSIX restart should complete the old companion's shutdown before launching its replacement. Returning success must mean the replacement process—not the process being stopped—has passed readiness and remains running.
Actual behavior
The replacement can start before the old companion releases the port, defer to the old healthy process, and exit. The launcher then mistakes the stopping old process for successful replacement readiness and exits 0. Shortly afterward both processes are gone and Monk MCP is unavailable despite the successful SessionStart hook.
Severity (your guess)
major
OS
macOS 26.5.2, Apple Silicon, using the shipped POSIX launcher's Linux background-process path with deterministic process/health stubs
monkd version
Not involved; failure occurs in local companion restart handoff before any monkd operation
Target cloud
None; local companion only
Integration (if relevant)
Monk plugin POSIX SessionStart launcher for Codex and Claude Code