hermes-agent/apps
Teknium a562757717
fix(wake): reconcile the listener back to config after a voice turn ends
Ending a voice conversation left the wake word silently off even with
wake_word.enabled: true — the desktop fired one wake.resume and hoped;
if the mic was still held by the just-released WebRTC capture (or the
resume raced teardown), the listener stayed dead until the user
re-toggled it. The wake word is a persistent setting: on is on until
the user explicitly turns it off.

- Desktop: resumeWakeAfterVoice() replaces the fire-and-forget resume —
  resume, then verify against wake.status (config 'enabled' is the
  authority) and re-arm via wake.start, with spaced retries to ride out
  mic-release latency. Passive path: never passes persist, never writes
  config; respects an explicit off and another surface's mic lease.
- Backend: wake.status now reports 'enabled' (config truth) so clients
  reconcile against the setting, not runtime listener state.
- Backend: _wake_resume_if_owner self-heals — a resume that throws
  (mic still busy) retries in a background thread for up to 15s. A
  False return (lease gone/moved) is final, never retried, so the
  retry can't steal another surface's mic. Covers the TUI/gateway
  voice.record path which had no recovery at all (CLI has its idle
  watchdog; the gateway had nothing).
- 6 new vitest cases: re-arm on enabled+down, no persist on the passive
  path, resume-alone success, disabled stays off, owned lease yields,
  older-backend no-op.
2026-07-28 07:59:34 -07:00
..
bootstrap-installer fix(installer): stamp the bootstrap-complete marker from the Rust installer 2026-07-26 16:02:13 -05:00
desktop fix(wake): reconcile the listener back to config after a voice turn ends 2026-07-28 07:59:34 -07:00
shared refactor: drop the shared subpath export, keeping package.json untouched 2026-07-28 03:54:49 -05:00