forked from unom/punktfunk
Phase 7's contained half. 7.1's writer split and 7.3's reservation are NOT here — see the plan; both need more than a local edit. **Lock-order inversion, gamescope.** `create_managed_session_steamos` held MANAGED_SESSION while taking STEAMOS_TOOK_OVER (and `persist_takeover`'s locks), while `do_restore_tv_session` takes STEAMOS_TOOK_OVER first and MANAGED_SESSION second — AB/BA between a connect and the restore worker, which genuinely run concurrently (`vd.create` runs off the registry lock; the worker is its own thread). The connect path now drops its guard before the pair and re-acquires after `poll_managed_node`, the shape `create_managed_session` already used. And `takeover_live` held all four statics at once — in a `||` chain every `.lock()` temporary lives to the end of the statement — for four reads; scoped bindings drop each guard before the next, taking it out of the ordering graph entirely. **`observe_session_instance` decided and acted under one lock.** It held LAST_INSTANCE across `invalidate_backend` (which drops keep-alive displays through the registry lock) and a `systemctl` shell-out on a 10 s budget, from three call sites including a per-second watcher. It decides under the lock and acts outside now; the baseline is advanced inside it, so a concurrent observer cannot run the action twice. **`admit` held the live-session table across the budget checks** — `manager::snapshot()` blocks on the manager `state` lock, which is itself held across DDC round trips and three 3 s activation ladders. Every connect, disconnect and mgmt read queued behind one slow display operation. The guard is scoped to `decide` alone. **GameStream never registered**, so its display was invisible to both Windows budgets (they gate on `!live.is_empty()`) and a native connect could be admitted past capacity the box had already spent. It registers now, anonymously, for the session's lifetime. **`ensure_exclusive_watch` panicked on a failed thread spawn** while holding BOTH `exclusive_watch` and (via its caller) `state` — poisoning the two locks the whole manager runs on, so every later acquire and mgmt read would panic on `.lock().unwrap()`. It logs and degrades instead: no re-assert watchdog is a degradation, a wedged manager is not. Also fixes two things only a Windows build shows, both mine: Phase 2.3 left `gamescope_route` unused there (every reader is Linux-gated), which `-D warnings` in Windows CI would have rejected — I had only run the host clippy on Linux. And Phase 5.4's helper-safening reaches a FOURTH crate, pf-inject, which xcheck does not lint. Verified on .173: `cargo clippy -p punktfunk-host -p pf-vdisplay --all-targets` clean across the whole tree; local fmt, both xcheck targets and 53 tests green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>