Two follow-ups from hands-free testing:
- Audio cues had no off-switch: empty sound fields fall back to the freedesktop
system chime, so wakeword/recording always made noise. Add a [sounds] enabled
master flag (default true) exposed as "Play audio cues" in Settings → Input.
When off, _play_cue/_play_sound are no-ops — fully silent operation.
- The VAD level meter (sounddevice/PortAudio) leaked harmless thread-teardown
errors ("pthread_join ... failed", "PaUnixThread_Terminate ... failed") to the
terminal on every clip end. PortAudio writes these straight to fd 2, so wrap
the stream open/close in a fd-level stderr suppressor (_quiet_c_stderr).
Tests: cue gating respects the master switch (16 passed).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two reported bugs:
1) Notifications still appeared during hands-free use while away. A wakeword
hit arriving while the previous clip was still transcribing went through
toggle(), which popped a "Busy" notification — the away-from-keyboard
notification storm. Wakeword triggers now call start_dictation(silent=True)
directly, so a busy/not-ready state is ignored silently. Transcription and
rewrite failures during a silent session are now logged instead of raising
critical desktop notifications.
2) "Wakeword did not work" with the log line "muted via /tmp/wake_muted": a
stale mute flag silently disabled detection. The tray "Pause wakeword"
toggle (already added) clears it; the daemon now also logs a clear
"Starting PAUSED" warning when it boots with the flag present.
Adds tests/test_daemon_notify.py covering silent-session suppression and the
busy-while-wakeword no-notify path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Wayland support: text delivery using wtype or ydotool (paste.py)
- Testing: added Pytest coverage for routing, quality, and config logic
- CI/CD: added test-linux job to .github/workflows/ci.yml
- Feature: Hands-free dictation using an external wyoming-openwakeword
server, respecting the /tmp/wake_muted toggle.