Bounty eligibility
Stage
connect
Coding agent
OpenAI Codex
Coding agent version
Codex CLI 0.146.0-alpha.9.2; Monk plugin v0.1.54 (2a4f9cf)
Repro steps
The v0.1.54 background launcher correctly notices when MONK_AGENT_PATH changes from custom executable A to B, but its stop step validates the recorded PID against B instead of the executable that actually owns the PID (A).
I reproduced the complete false-success handoff with a deterministic, network-free launcher test:
- Start a long-running custom executable A and write its PID plus
agent_path=A to the launcher's normal PID/state files.
- Make the normal protected-resource probe return the expected healthy Monk MCP resource for A.
- Set
MONK_AGENT_PATH=B. B models the companion's healthy-port-conflict behavior: it briefly waits for A to release the endpoint, then exits 0 when A is still alive.
- Run the unmodified
scripts/start-monk-agent.sh through its Linux/background-process path.
- After the launcher returns, inspect both processes and the launcher's PID/state files.
Observed on v0.1.54:
launcher_exit=0
old_companion_A_alive=yes
replacement_B_alive=no
pid_file_points_to=B
state_file_agent_path=B
The focused regression reports:
launcher returned success against the old custom companion while the replacement exited
The root cause is in start_with_background_process():
old_pid="$(cat "$pid_file" ...)"
if pid_matches_executable "$old_pid" "$agent_path" && kill -0 "$old_pid"; then
kill "$old_pid"
fi
At this point $agent_path is B, while $old_pid belongs to A. The ownership check therefore rejects the correct old process and never signals it. The launcher starts B, B defers to the healthy A and exits, then readiness succeeds against A before liveness can reject B.
The native Windows path has the same ownership mismatch: Stop-ManagedAgent compares the old process path with the newly selected $AgentPath, even though the state file records the prior path.
This is distinct from #10/#36. Those reports fixed repeated restarts when the same custom path is reused. #10 explicitly expected a one-time restart when switching to a different custom executable, but the shipped handoff cannot complete that switch. It is also distinct from #154/#180, which cover restart races without changing executable paths.
Fresh issue and PR searches for MONK_AGENT_PATH, custom agent/companion, path switch/drift, replacement, handoff, old PID, and restart found no report or implementation for this A-to-B ownership mismatch.
Expected behavior
When MONK_AGENT_PATH changes from A to B, the launcher should authenticate the recorded PID against the previously recorded A path, stop A, start B, and return success only after B owns the healthy endpoint. The PID and state files should both describe the running B process.
Actual behavior
The launcher authenticates A's PID against B, refuses to stop A, starts B into A's occupied endpoint, and can return success against A after B exits. It then leaves PID/state metadata pointing to the dead replacement even though the old custom companion is still serving.
Severity (your guess)
major
The launcher reports a successful configuration switch that did not occur, and later lifecycle/uninstall operations lose ownership of the process still serving the MCP endpoint. Manually stopping A before switching paths is a workaround.
OS
macOS 26.6 arm64 host using the repository's deterministic fixture to execute the exact Linux/background-process branch; equivalent ownership mismatch confirmed in the shipped Windows PowerShell path
monkd version
Not involved; the failure is in the local companion handoff before any monkd operation
Target cloud
None
Integration (if relevant)
Monk plugin custom-agent launcher used by OpenAI Codex and Google Antigravity on Linux; equivalent native Windows launcher logic
Bounty eligibility
Stage
connect
Coding agent
OpenAI Codex
Coding agent version
Codex CLI 0.146.0-alpha.9.2; Monk plugin v0.1.54 (
2a4f9cf)Repro steps
The v0.1.54 background launcher correctly notices when
MONK_AGENT_PATHchanges from custom executable A to B, but its stop step validates the recorded PID against B instead of the executable that actually owns the PID (A).I reproduced the complete false-success handoff with a deterministic, network-free launcher test:
agent_path=Ato the launcher's normal PID/state files.MONK_AGENT_PATH=B. B models the companion's healthy-port-conflict behavior: it briefly waits for A to release the endpoint, then exits 0 when A is still alive.scripts/start-monk-agent.shthrough its Linux/background-process path.Observed on v0.1.54:
The focused regression reports:
The root cause is in
start_with_background_process():At this point
$agent_pathis B, while$old_pidbelongs to A. The ownership check therefore rejects the correct old process and never signals it. The launcher starts B, B defers to the healthy A and exits, then readiness succeeds against A before liveness can reject B.The native Windows path has the same ownership mismatch:
Stop-ManagedAgentcompares the old process path with the newly selected$AgentPath, even though the state file records the prior path.This is distinct from #10/#36. Those reports fixed repeated restarts when the same custom path is reused. #10 explicitly expected a one-time restart when switching to a different custom executable, but the shipped handoff cannot complete that switch. It is also distinct from #154/#180, which cover restart races without changing executable paths.
Fresh issue and PR searches for
MONK_AGENT_PATH, custom agent/companion, path switch/drift, replacement, handoff, old PID, and restart found no report or implementation for this A-to-B ownership mismatch.Expected behavior
When
MONK_AGENT_PATHchanges from A to B, the launcher should authenticate the recorded PID against the previously recorded A path, stop A, start B, and return success only after B owns the healthy endpoint. The PID and state files should both describe the running B process.Actual behavior
The launcher authenticates A's PID against B, refuses to stop A, starts B into A's occupied endpoint, and can return success against A after B exits. It then leaves PID/state metadata pointing to the dead replacement even though the old custom companion is still serving.
Severity (your guess)
major
The launcher reports a successful configuration switch that did not occur, and later lifecycle/uninstall operations lose ownership of the process still serving the MCP endpoint. Manually stopping A before switching paths is a workaround.
OS
macOS 26.6 arm64 host using the repository's deterministic fixture to execute the exact Linux/background-process branch; equivalent ownership mismatch confirmed in the shipped Windows PowerShell path
monkd version
Not involved; the failure is in the local companion handoff before any monkd operation
Target cloud
None
Integration (if relevant)
Monk plugin custom-agent launcher used by OpenAI Codex and Google Antigravity on Linux; equivalent native Windows launcher logic