Replace a sidecar still running superseded code - #20
Merged
Conversation
The supervisor asked pgrep for the sidecar's match pattern and, finding anything alive, declared the sidecar reconciled. The pattern deliberately carries no store path, so a bridge launched from an older generation of bridge.py matches it exactly as well as the current one does. A rebuild therefore could never put new bridge code on a running agent: monster on chise has carried the same bridge process for two days across four system generations. The sidecar now records the command it was launched from beside its log, and a live process whose record no longer matches the desired command is terminated, waited for, and replaced. A sidecar with no record at all is replaced once and records itself, so the first reconcile after this change refreshes every bridge and later ones leave it alone. Terminating and waiting before spawning keeps the replacement from holding the bot token at the same moment as the process it supersedes, which is the same double-answer this module already guards against for duplicates. Agent-Machine: kira Agent-Resume: claude --resume efee1316-8d94-438e-951e-e9c978626531
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong
reconcile_one_sidecar_processaskedpgrepfor the sidecar's match pattern and, finding anything alive, returned without spawning. The pattern deliberately carries no store path, so a bridge launched from an older generation ofbridge.pymatches it exactly as well as the current one does.A rebuild could therefore never put new bridge code on a running agent. Live evidence on chise: monster's bridge (
pid 4193780,/nix/store/fx1wv2ds…-bridge.py) has run for two days across system generations 1618 to 1621. The media fix shipped in v0.12.5 would never have reached it.What changed
spawn_sidecar_processrecords the command it launched beside the sidecar log (<log>.spawned-command).reconcile_one_sidecar_processcompares that record to the desired command; on a mismatch it terminates every live process, waits for each to exit, then spawns the replacement.The command string covers everything that can change: the bridge script's store path, the python environment, the one-shot turn command, the workspace and state directories.
A sidecar with no record at all counts as superseded, so the first reconcile after this change refreshes every bridge once and later reconciles leave it alone. No respawn loop.
Terminating and waiting before spawning keeps the replacement from holding the bot token at the same moment as the process it supersedes.
Verification
nix build .#checks.aarch64-darwin.unit-testsgreenformattinganddiscord-transport-evalgreentest_clawde_service_sidecar_process_supersession.py, including the exactly-once replacement for a sidecar predating the record and both bounds of the termination wait