- Stability: remove blocking TCP socket call from _collect() — was
freezing the GTK main thread on Save when wakeword server unreachable;
now checks async in background and logs result
- Thread safety: fix _ww_load() reading GTK widget from background thread;
capture URI on main thread before spawning
- WhisperX 404: _transcribe_remote now detects non-standard paths
(anything other than /v1) and uses the URL as the full endpoint,
so http://host/transcribe works without /audio/transcriptions appended
- Log levels: logbuffer stores (ts, level, msg) tuples; log() accepts
level= (DEBUG/INFO/WARNING/ERROR); Log tab gets a Level dropdown
(Verbose/Info/Warning/Error) that filters displayed entries live
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bug: a stale /tmp/wake_muted flag silently disabled wakeword detection
with no in-app way to clear it (the flag was read but never written by
any code or UI).
- wakeword.py: expose MUTE_FILE + is_muted()/set_muted() helpers
- tray.py: add a "Pause wakeword" CheckMenuItem (shown when wakeword is
enabled) that toggles the flag and reflects current state
- config.py: document the tray toggle instead of the bare /tmp file
- CHANGELOG: record the wakeword pause toggle and the existing notify
hygiene fixes (transient/single-bubble notifications, silent
hands-free sessions)
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.