Build the Hub Fixes Directive 1 watchdog as a small standalone service on .13.
- Watch voice/audio_stream (paho); 15 min silence = 3 missed heartbeats.
- Attribute failures in order: broker -> voice_bridge -> ESP32/no-publisher.
The ESP32 is never blamed when the broker or the bridge broke.
- Alert via Apprise on .35:8210 (tag sam_ntfy; daily repeat escalates to sam).
- Persist state; repeat once a day while broken; recovery notice; alerts stop.
- No auto-heal of any kind. Notification only.
- Require publisher evidence (heartbeat or retained presence) before treating
silence as a failure, so the unflashed Directive 3 firmware cannot cause the
cry-wolf false alarms the spec warns about.
- Docker: host network, read-only Docker socket, state volume, unless-stopped.
- 23 unit tests; live evidence captured in watchdog/README.md.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
paho reconnects on its own but does not restore subscriptions. A client
without an on_connect re-subscribe holds a live socket with no subscription
and goes silently deaf -- no error, no log. That is how voice_bridge died on
2026-10-13.
All in-scope .13 clients already re-subscribe on every connect and log it
(voice_bridge, Jervis voice-agent, IUC control-service, IUC kids Android app).
The Hub has no MQTT client, n8n nodes are publish-only, Home Assistant
re-subscribes by design, and the ESP32 firmware is owned by Directive 3.
Add:
- docs/mqtt-reconnect-compliance.md: inventory with file:line evidence and the
live verification result.
- verify/mqtt_reconnect_check.sh: static source check plus an opt-in --live
check that restarts the .13 broker and asserts re-subscribe within 60s.
Live check 2026-10-14T00:01:18Z: .13 mosquitto restarted; voice_bridge and
control-service re-subscribed and ESP32 reconnected within 3s.
Co-Authored-By: Paperclip <noreply@paperclip.ing>