A supervisor that kills its bridges when it restarts is not a supervisor anyone will run. Re-adoption had to be solved on day one — and it needed no new state file, because the previous phase already recorded a pid on every successful start, precisely so this one would have it.
A pid alone is not an identity. Pid reuse is real, and a naive pid check eventually signals something innocent. So adoption compares the kernel’s process start time, read at spawn and stored beside the pid. The wall-clock timestamp the supervisor already wrote could not be used: it differs from the kernel value by milliseconds, so equality would never match.
On boot, for each bridge with a recorded pid: if the pid is dead, clear the record. If the pid is alive but the start time disagrees, refuse to adopt and refuse to start, loudly. That second refusal is the important one — starting a replacement would put two processes on one chat channel, and a channel with two bridges answers everything twice. If both match, adopt it, with no output capture, because the pipe belonged to a supervisor that no longer exists.
Reading the start time is platform-specific, and the unsupported case is deliberately harsh: on a platform it cannot read, the supervisor refuses to start at all — not “adopt anyway”, not “spawn anyway”. An unverifiable identity must never be allowed to become a duplicate bridge.
The proof, and what it cost. A bridge was started under the new supervisor, the supervisor was interrupted — and the bridge survived, where the previous phase would have killed it. Restarting adopted the same pid, and the gate self-test count did not move: a supervisor bounce costs nothing, where a restart-everything approach would have spent real money per bridge. A tampered start-time token was then blocked and nothing was spawned; restoring it allowed adoption again, which proves the refusal was a guard rather than a dead end. Throughout, the two live production bridges were untouched.