Commit Graph
3 Commits
Author SHA1 Message Date
OmikronApexandClaude Fable 5 a142b0f3de fix(audio): gate the executor's chain-plan startAudio behind the user-stop latch
Second field finding: a user-stopped engine came back when a song load
ran a rig_builder chain plan with startAudio:true - the executor calls
native startAudio directly in the main process, bypassing the IPC latch
check entirely (plan 6.1's second writer).

Decision (strict 8.3): only the device screen's user start resumes.
lease-bridge gains gateNativeAudio(), a proxy over the native accessor
that suppresses startAudio while latched (log-once telemetry line);
audio-bridge hands the executor the gated accessor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 01:37:34 +02:00
OmikronApexandClaude Fable 5 bb0f79e0be fix(audio): user-stop latch - plugin keep-alives can no longer undo a user stop
Field finding (fix14 test build): nam_tone's 1.5s keep-alive watchdog
calls raw startAudio whenever the engine is not running, restarting it
seconds after the user pressed Stop - and the shim treated any raw start
as user authority, resuming all suspended demands with it.

Per plan 8.3 (user stop always wins) raw start/stop was supposed to be
device-screen-only; now enforced:
- audio:userStartAudio / audio:userStopAudio: explicit user authority.
  Stop sets a latch (+ suspends demands); start clears it (+ resumes).
- raw audio:startAudio is SUPPRESSED while latched (log-once telemetry
  'suppressed-by-user-stop') and no longer resumes demands.
- raw audio:stopAudio no longer suspends demands (it is the transient
  stop the device-apply flow and unmigrated plugins use).
- fresh capture demands born during the latch start suspended, so the
  user start resumes them like pre-existing ones; the demand glue also
  refuses to start the engine while latched.
- device screen (src/renderer/screen.js) toggle + apply flows use the
  user-authority calls.

Contract snapshots regenerated (2 IPC channels, 2 preload keys).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 01:08:52 +02:00
OmikronApexandClaude Fable 5 5ecf55cb0c feat(audio): wire lease registry into IPC — leases surface, demand glue, legacy telemetry
Phase A wiring (plan §6.8/§8/§9):
- lease-bridge.ts: holder identity derived from the IPC sender (compound
  identity — enforced wc id + attributed tag), webContents destroy →
  death invalidation, main-frame navigation → reload grace window,
  capture demand drives startAudio/stopAudio, detection demand drives
  setNoteDetectionEnabled.
- audio-bridge.ts: audio:leases:* channels; raw startAudio/stopAudio now
  resume/suspend demands (user authority, §8.3); raw detection disarm is
  ignored while a demand holder still needs it armed (fixes 6.3's
  last-disarmer-kills-concurrent-consumer); log-once legacy telemetry.
- preload: audio.leases.* (acquire/release/takeover/getHolder/
  acquireDemand/releaseDemand/snapshot/onEvent).
- contract snapshots regenerated deliberately (7 IPC channels, 1 preload key).
- tests: lease-bridge suite (9) incl. death matrix destroy/reload paths;
  _load-ts gains a .ts require hook for cross-module TS imports.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 22:13:16 +02:00