Before: ps -ax | grep bobit was the only record of what a bridge was. The willartley bridge had already proved the failure mode — had it died, the launch line was unrecoverable.
After: each bridge is an AgentConfigRevision whose config_json states site, channel, user and gate port — versioned, attributed to a user, with an active pointer.
This phase is bookkeeping, and it says so out loud. Nothing reads these rows. No supervisor exists; no process starts, stops, or changes behaviour because of anything here. desired_state is a column with no reader and no screen. That is not a gap to apologise for — it is the phase. Phase 3 needs something to reconcile against, and inventing a consumer now, to make this feel like a working increment, would have been the wrong trade.
One honest correction to “nothing reads these rows”: the worker’s processor does query the active revision and pass config_json straight into an adapter. A bridge never reaches it, behind four independent guards — the dispatcher’s worker-type filter, the push-mode adapter set (a bridge is api), and Phase 1’s two assignment predicates. The reader exists; a bridge is excluded from it four times over. Better to name that than to claim a clean zero.
The default is stopped, and that choice is load-bearing: declaring a bridge must not arm it. With running as the default, this phase — which only writes rows — would have auto-started every declared bridge the instant a supervisor first appeared.