Choose audio devices during preflight
Candidates with multiple audio devices otherwise have to change system defaults before an interview. Add microphone and output selectors to preflight. Candidates without a saved output preference start at System default, while existing output preferences survive reloads. The selected microphone supplies both the activity check and the track published to LiveKit. The test tone, test voice, and Jim share one effective output selection, including outside Meet mode. Changing devices requires fresh microphone activity or output confirmation.
A saved output that cannot yet be listed appears as the selected "Saved output device" option in both menus, so the candidate can explicitly choose System default before granting microphone access. Empty, placeholder, or failed pre-grant listings retain the preference. A granted listing replaces the temporary label with the device name or confirms that the hardware is missing and restores System default. Choosing System default clears the saved preference. The original manual reload check is unchanged.
Jim uses the existing volume controller with candidate mute and pending routing as independent mute reasons. A fresh element stays muted after LiveKit attaches it until the latest routing chain settles. Releasing the hold retries audible playback, and a later native pause rechecks permission through the existing resume control. A stalled sink request displays a device-check/reload notice after five seconds and remains serialized; recovery can require a reload rather than playing on an unverified sink.
Before
Preflight provides sound and microphone checks without device selectors.
After
Preflight provides separate output and microphone selectors, both showing System default when no output preference is saved.
Both screenshots use a local test session with the camera declined and contain no personal media or credentials.
Validation
The branch is rebased onto 48d7505; the current commit is b4fe940. The focused audio, volume, camera-preview, and DOM-contract suite passed all 144 tests without skips. Six delayed-grant checks failed before the saved-option correction and passed afterward; they cover empty, placeholder, and failed listings, retained preferences, and returning to System default before permission. ESLint, Prettier, whitespace checks, and the push hook passed. The updated hook installer reports all four hooks in effect.
GitHub Actions run 39941183499 passed the Rust, portable, browser, mutation-planning, and aggregate check jobs at the preceding head 1ee77c2. The new run for b4fe940 is awaiting maintainer approval; its result is not yet known.
The required full ./scripts/test.sh run at b4fe940 completed with exit 1. Its browser suite reported 1,546 passed, four failed, and 48 skipped (36 without cc and 12 without javac/java). Failures were two Windows subprocess-interruption checks, the lobby-height check (802px against 800px), and the standalone WebRTC probe reporting receiver-stats-unavailable. The probe also failed in isolation and loads unchanged test/probe code; its local cause remains unresolved. Clippy rejected dead code with Unix-only readers in unchanged main files, Cargo could not replace the running Windows executable, and fixture generation rejected a Windows drive path as an ESM URL. The server check and shell/Python harnesses also failed, including Windows process/path handling and missing tool/privilege cases. The updated hook self-tests failed while installing hooks in temporary repositories, including a Windows path permission error; this is separate from the successful installer check in this checkout.
The failed gates were clippy, cargo-test, browser-server-tests, wire-fixtures, recording-provision-check-tests, recording-integration-harness-tests, test-gate-tests, mutants-plan-tests, mutants-install-tests, interview-behavior-script-tests, skill-scripts-tests, browser-tests, and git-hooks. The run additionally skipped two server checks, Python skill checks without jq, and checks requiring commentflow, ruff, shfmt, cargo-audit, actionlint, or shellcheck. The full local gate is not claimed to pass.
Before the review refinements, manual testing on Windows 10 confirmed operation with two physical input devices and two physical output devices. Earlier tests covered tone and test-voice playback, Jim and microphone input during interviews, rapid output switching, unplug/reconnect, and returning to the lobby. These physical tests do not validate the latest review refinements. The specific silent-tone driver conditions in #44 and #197 were not reproduced and are not claimed fixed.
Closes #206