Denoise deep-review (CRITICAL): restart() read opts.audioContext, which LiveKit does NOT pass on restart — so reconnect (the A7 scenario) and mic device-switch threw after stopping the old track, leaving the mic SILENT (A7 reintroduced). Fix: - Processor owns a dedicated 48kHz AudioContext (sapphi worklets require 48kHz; H1), reused across restart, closed on destroy. - restart() never throws and never leaves a stopped track on the sender: builds the new graph first, then disposes the old; on failure degrades to RAW mic audio rather than silence. - Cache wasm per URL (no re-fetch each reconnect); gate threshold default -45 and accept an explicit 0 (M2); document the cross-repo asset contract. Protocol audit: - Non-silent warning when an unsupported denoise model (dtln/deepfilternet) is requested instead of silent rnnoise fallback (F3). - Correct the call_state enum comment (immediate error-reply, not 10s) (F2). Build/CI audit: - Stamp VITE_APP_VERSION in CI; document the vX.Y.Z-lotus.N version scheme. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>