Skip to content

fix: robust recovery from audio stream death, IBus boot race, and tray crashes#4

Merged
Hugo0 merged 1 commit into
mainfrom
fix/robustness-watchdog
Mar 14, 2026
Merged

fix: robust recovery from audio stream death, IBus boot race, and tray crashes#4
Hugo0 merged 1 commit into
mainfrom
fix/robustness-watchdog

Conversation

@Hugo0
Copy link
Copy Markdown
Owner

@Hugo0 Hugo0 commented Mar 14, 2026

Summary

  • IBus boot race: wait up to 15s for ibus-daemon at startup instead of falling back to broken clipboard typer on Wayland
  • Audio stream watchdog: detect 5 failure modes (closed/inactive/stopped/stale heartbeat) with exponential backoff recovery + pre-flight check before recording
  • Tray subprocess watchdog: auto-restart dead AppIndicator subprocess
  • IBus terminal auto-paste: query engine focus state, simulate Ctrl+V via ydotool for non-IBus apps (Ghostty, etc.)
  • Streaming resilience: catch typer errors in worker thread instead of crashing
  • Mic signal check: warn if pre-buffer is all zeros before recording

Test plan

  • All 404 tests pass
  • Ruff lint clean
  • Manual testing: streaming + commit works in Ghostty
  • Manual testing: service restart picks up IBus correctly

Summary by CodeRabbit

  • New Features

    • Audio stream health monitoring with automatic recovery capabilities.
    • Enhanced focus detection with fallback auto-paste functionality.
    • System tray process monitoring and automatic recovery.
  • Bug Fixes

    • Improved startup reliability and initialization stability.
    • Enhanced error resilience in audio streaming to prevent crashes.
  • Tests

    • Improved test coverage for app initialization.

…y crashes

Three recurring failures fixed:

1. IBus boot race: voiceio starts before ibus-daemon is ready, falls back to
   clipboard typer which fails on Wayland. Now waits up to 15s for IBus daemon
   and re-probes typers.

2. Audio stream silently dies (ALSA underrun, PipeWire restart, device disconnect)
   and all subsequent recordings capture only silence. Health watchdog now detects
   5 failure modes (closed/inactive/stopped/stale heartbeat) with exponential
   backoff recovery. Pre-flight check reopens dead stream before recording starts.

3. Tray indicator subprocess dies and loses D-Bus registration. Watchdog now
   detects and restarts it automatically.

Also:
- IBus typer auto-pastes via ydotool in non-IBus apps (terminals like Ghostty)
  by querying engine focus state over the Unix socket
- Streaming worker thread catches typer errors instead of crashing
- Pre-recording mic signal check warns if audio is all zeros (muted mic)
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 14, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

The changes introduce a comprehensive health monitoring and recovery system across multiple components. AudioRecorder gains heartbeat tracking and stream health diagnostics. The main app monitors audio stream and tray subprocess liveness with automatic recovery mechanisms. IBus integration is enhanced with focus detection and clipboard paste simulation on focus loss. Tray subprocess management adds liveness checks and restart capability. Streaming error handling is improved with wrapped transcription calls.

Changes

Cohort / File(s) Summary
Health Monitoring & Heartbeat
voiceio/recorder.py, tests/test_app_wiring.py
Introduces heartbeat timestamp tracking, stream health status checks, signal detection, and stream reopening capability. Test mocks enhanced with realistic initial stream state and heartbeat initialization.
Main App Health & Recovery
voiceio/app.py
Implements pre-recording stream health checks with reopen on failure, background health monitoring with backoff/retry logic, tray subprocess liveness checks with restart, and conditional IBus availability waiting with re-probing.
IBus Socket Communication
voiceio/ibus/engine.py
Adds handling for "focus?" socket messages with direct response based on engine focus state, bypassing GLib main loop for fast focus inquiries.
IBus Typing Resilience
voiceio/typers/ibus.py
Adds focus detection helper, paste simulation via ydotool/wtype when focus is lost, and tool lookups during initialization; auto-paste triggered after type/commit operations.
Tray Process Management
voiceio/tray/__init__.py
Adds is_alive() to check indicator subprocess liveness and restart() to respawn dead indicator backends with theme-aware icon setup and optional toggle callback handling.
Error Handling
voiceio/streaming.py
Wraps per-iteration and final transcription calls in try/except blocks to log errors without terminating the streaming worker.

Sequence Diagram

sequenceDiagram
    participant App
    participant Recorder
    participant Tray
    participant IBus

    Note over App,IBus: Startup Phase
    App->>Recorder: _check_health()
    Recorder-->>App: stream_health() → (ok, reason)
    alt Stream unhealthy
        App->>Recorder: reopen_stream()
        Recorder-->>App: stream reopened
    end
    
    App->>Tray: is_alive()
    Tray-->>App: subprocess status
    alt Tray dead
        App->>Tray: restart(toggle_callback)
        Tray-->>App: True/False
    end

    Note over App,IBus: Background Monitoring
    loop Health Check Interval
        App->>Recorder: stream_health()
        Recorder-->>App: (ok, reason)
        
        App->>IBus: _wait_for_ibus() if needed
        alt IBus not ready
            IBus-->>App: None (waiting)
        else IBus ready
            IBus-->>App: TyperBackend
        end
    end

    Note over App,IBus: Typing Operations
    App->>IBus: type_text()
    IBus->>IBus: _engine_has_focus()?
    alt Focus lost
        IBus->>IBus: _simulate_paste()
        IBus-->>App: paste executed
    else Focus present
        IBus-->>App: text typed
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 Hark! A heartbeat now doth flow,
Through streams and threads with healthful glow,
When systems falter, swift they mend,
Focus queries find their friend,
Resilience blooms—no task's too tough,
Our infrastructure's made of fluff! 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title precisely summarizes the three main recovery mechanisms introduced: audio stream health monitoring, IBus startup race handling, and tray subprocess restarts.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/robustness-watchdog
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Hugo0 Hugo0 merged commit b23c76f into main Mar 14, 2026
10 checks passed
@Hugo0 Hugo0 deleted the fix/robustness-watchdog branch March 14, 2026 20:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant