Codex authored the adapter half of the phase-3 split; I reviewed it and applied one robustness fix (below). Additive/read-only — does not yet replace the existing audio.rs router (that migration is a later integration phase). adapter.rs: a dedicated libpipewire main-loop thread translating registry globals into RegEvents and publishing the latest Projection via RegistryObserverHandle::latest(). core.sync(0)/done is matched one-shot → ServerSynced; a 250 ms loop timer emits Tick for the fail-closed readiness timeout; pulse-PID candidates are probed from /proc/<pid>/comm only when the candidate changes; Links missing endpoint props are bound (LinkInfoRef, weak back-ref to avoid the listener cycle) and resolved via LinkEndpointsResolved. mod.rs: `pub mod adapter;`. audio.rs: parse_object_serial → pub(crate) so the adapter reuses the strict 64-bit parser. Review fix: record_global was called unconditionally per global (including unknown object types and dropped globals), which could desync the bound-link FIFO from the model's live_ids and leak a Link proxy on a recycled id. Now folded into `add()` so a slot is recorded only when an Added event is applied — the two id queues are provably lockstep. Exit gate complete: 5 pure rows + the live topology-diff row (row 6) — the #[ignore] adapter test PASSES on this host against the live daemon (module-null-sink + module-loopback observed appearing and disappearing). cargo test --bins 117 + 1 live green, clippy clean, no fmt sweep. Co-Authored-By: Codex (gpt-5.6-sol) <codex@openai.com> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>