0560f52047
Ports #63768 forward onto current main per teknium1's review. On WSL2 without a PulseAudio bridge, ffplay and aplay have no audio device and TTS playback silently fails (issue #17608). When powershell.exe and ffmpeg are available, convert the audio to a uniquely-named WAV in the Windows %TEMP% directory and play it via Media.SoundPlayer. Per review, this fixes two gaps in the original port: 1. Exit-status masking: the cleanup subshell was '( ffmpeg && powershell ); rm -f wav' -- the shell's exit status is the LAST command's (rm -f, which is always 0), so a real ffmpeg/PowerShell failure could never be detected by the rc-checking fallback logic added to the player loop. Now captures the real status before cleanup and re-exits with it: '( ffmpeg && powershell ); rc=0; rm -f wav; exit '. 2. The no-Pulse WSL gate in detect_audio_environment() still hard-blocked voice mode entirely (input AND output) even when the PowerShell fallback made TTS output viable. Added _wsl_powershell_tts_available() and use it to downgrade the WSL-without-Pulse case from a hard 'warnings' block to a non-blocking 'notices' entry when the fallback is available -- the same PulseAudio-bridge recording guidance is still surfaced (mic capture genuinely still needs it), it just no longer blocks /voice on for TTS-only usage. cli.py's existing env_check['available'] gate needed no changes since it already respects this flag. Also fixed the flaky uniqueness test (the original asserted len(filenames) >= 2, which passed trivially on zero captured filenames) and added a real fallback-triggering regression test for the exit-status fix. 10 new/fixed tests pass in TestWSL2PowerShellFallback and the new TestWSLAudioEnvironmentGate; 80/80 in the full tests/tools/test_voice_mode.py file.