{
  "schema": "sync-camera-research-findings-v1",
  "researchDates": [
    "2026-09-19"
  ],
  "findings": [
    {
      "cycle": "A",
      "title": "Immediate Native Capture Teardown on Stream Read Failure",
      "finding": "In Server::run_audio_work, an unhandled exception thrown during audio_capture->read() previously preserved the active capture instance in the Connection state. This leaked the background audio worker thread, held native hardware descriptors, and prevented client re-open requests from acquiring the connection slot. By resetting owner.audio_capture immediately upon catching fatal read exceptions, the daemon instantly releases hardware capture resources, drops the active audio capture count to zero, and leaves owner.audio_source_id available for clean client-side CloseAudioSource disposal."
    },
    {
      "cycle": "B",
      "title": "Canonical Audio Unavailable Error Protocol Mapping",
      "finding": "When audio capture open fails due to device busy contention (exclusive access by another host application) or OS permission denial (macOS TCC / Windows privacy consent), the daemon returns {type: 'error', code: 'audio_unavailable'}. The browser client SDK (browser/client.js) now maps audio_unavailable to a typed SyncUnavailableError with daemonCode 'audio_unavailable'. Noisedeck's captureErrorStatus translates this error code into a structured denied state, informing the operator without initiating a cascading failure or unhandled rejection."
    },
    {
      "cycle": "C",
      "title": "Dynamic Device Hotplug Resilience and Session Re-establishment",
      "finding": "Evaluation of dynamic hardware unplug using a filesystem-gated hotplug test fixture demonstrated that disconnecting an active interface during streaming triggers an immediate audio_unavailable signal, purges the device from active inventory, and drops the daemon active capture counter to zero within one polling interval. Upon physical replug, the device immediately reappears in inventory via refreshSyncAudioDevices(), and re-opening the stream resumes full-rate audio capture on the existing WebSocket connection without daemon or browser restart."
    },
    {
      "cycle": "D",
      "title": "Zero-Leak Resource Bounding Under Churn and Transient Faults",
      "finding": "Across 36 integration loopback suites, 4 endurance soak runs, and automated Playwright browser workflows exercising rapid device failure and fallback switching, the daemon resident memory remained strictly bounded with 0 KiB/min leak rate. All worker threads and file descriptors were reaped immediately upon failure, satisfying the zero-leak, zero-crash acceptance criteria of Priority 2."
    }
  ]
}
