fix(audio): #138 — reprobe escalates to a graph restart, never opens with one
All checks were successful
Check / eval (push) Successful in 3m53s
All checks were successful
Check / eval (push) Successful in 3m53s
Bernardo's Meet calls lost their microphone because our own dock-audio reprobe restarted PipeWire/Pulse/WirePlumber on every monitoradded (#100). Chromium's audio service does not reconnect when the server disappears under it, so it kept running and enumerated nothing; Zoom, started fresh into a settled graph, looked fine and made it read like a browser bug. reprobe now escalates cheapest-first — select → repair a parked card's profile → restart the graph — so an ordinary plug never touches the graph and no client loses its connection. wait_for_dock_sink polls for the sink the plug is about to publish, so "not yet" is not mistaken for "not ever" and cannot fall through to the restart. The restart stays as rung 3 for the codec that only publishes its route after a re-probe: the one claim the original comment made, and the only one it never demonstrated. Verified on the dev box against the live graph: rung 1 selects the same sink the restart-first path picked (HiFi__HDMI1__sink) in 2.0s instead of ~3.5s with pipewire/pulse/wireplumber MainPIDs unchanged; rung 3 reachable and restarts+retries. Diagnosis proof was ordering across four boots — restart-after-Chromium in both broken sessions, 24s before it in the healthy one — and Bernardo reproduced on demand with a dock/undock. Sweep: BACKLOG #138 deleted, ROADMAP gets the design record (incl. the stale restart-first sentence in the #100 entry), V3 queued on the dev box (relogin first — the watcher is exec-once), journal entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -736,9 +736,11 @@ Design/decision records and a running log of shipped work (items marked
|
||||
private process group on cleanup, and validates/cleans a stale runtime PID
|
||||
after an unclean exit. Normal undocked lid-close suspend resumes after
|
||||
release. Audio now uses `monitoradded` as the fresh-plug intent boundary:
|
||||
after a debounce and two-second hardware settle it restarts PipeWire,
|
||||
PipeWire Pulse, and WirePlumber, then explicitly selects the highest-priority
|
||||
available sink using the original WirePlumber regex data. Generic
|
||||
after a debounce and two-second hardware settle it restarted PipeWire,
|
||||
PipeWire Pulse, and WirePlumber, then explicitly selected the highest-priority
|
||||
available sink using the original WirePlumber regex data (the restart was
|
||||
demoted to a last resort by #138 below — the selection is the part that
|
||||
works). Generic
|
||||
`change:sink`/card events never select, so a manual speaker choice sticks;
|
||||
the subscription loop reconnects after graph restarts. Journal lines record
|
||||
the trigger and selected/no-candidate result. `checks.docking-ux` syntax- and
|
||||
@@ -779,6 +781,28 @@ Design/decision records and a running log of shipped work (items marked
|
||||
process lesson: both watchers are `exec-once`, so `nomarchy-home` leaves the
|
||||
*old* processes running and two of the four reports were never testing the
|
||||
fix — **relogin before testing a watcher**. V3 is queued as round 6.
|
||||
✓ **Dock audio round 7 — the graph restart was never the fix (#138,
|
||||
2026-07-16):** Bernardo's Meet calls kept losing their microphone; the cause
|
||||
was our own reprobe restarting PipeWire on **every** monitor plug. Chromium's
|
||||
audio service does not reconnect when the server goes away under it, so it
|
||||
runs on enumerating nothing — and Zoom, started fresh into a settled graph,
|
||||
looked fine and made it read like a browser bug. Ordering across four boots
|
||||
was the proof: restart-after-Chromium in both broken sessions, restart 24s
|
||||
*before* Chromium in the one healthy session; a dock/undock on demand then
|
||||
reproduced it live. `reprobe` now escalates cheapest-first — select → repair
|
||||
a parked card's profile → restart the graph — so the common plug never
|
||||
touches the graph and no client loses its connection. Measured on the dev
|
||||
box: selection alone picks the *same* sink the restart-first path picked, in
|
||||
2.0s instead of ~3.5s, with PipeWire/Pulse/WirePlumber PIDs unchanged. The
|
||||
restart survives as rung 3 for the codec that only publishes its route after
|
||||
a re-probe — the one claim the original comment made and never demonstrated.
|
||||
The lesson is the shape of the bug, not the audio: the restart was inherited
|
||||
from "the old working flake" as a recovery, ran first for a session-day, and
|
||||
its collateral was never priced. **A cure carried over from a working system
|
||||
is still an unproven cure** — and a sledgehammer's cost lands on whoever was
|
||||
already holding a connection, which is nobody at login and everybody at 11am.
|
||||
A slow-appearing sink is polled for (`wait_for_dock_sink`) rather than read
|
||||
as "nothing to select", so the ordinary plug cannot fall through to rung 3.
|
||||
✓ **Conditional layout indicator + swap parity (#109, 2026-07-14):** the
|
||||
indicator answers "which layout am I typing in?", so it earns bar space
|
||||
exactly when that has more than one answer — not when a device merely
|
||||
|
||||
Reference in New Issue
Block a user