diff --git a/backlog/tasks/task-301 - Fix-launcher-managed-video-close-leaving-background-app-alive.md b/backlog/tasks/task-301 - Fix-launcher-managed-video-close-leaving-background-app-alive.md index 3d448157..8127275b 100644 --- a/backlog/tasks/task-301 - Fix-launcher-managed-video-close-leaving-background-app-alive.md +++ b/backlog/tasks/task-301 - Fix-launcher-managed-video-close-leaving-background-app-alive.md @@ -5,7 +5,7 @@ status: Done assignee: - Codex created_date: '2026-04-26 03:29' -updated_date: '2026-04-26 03:33' +updated_date: '2026-04-26 03:44' labels: - bug - launcher @@ -42,12 +42,14 @@ Launcher/plugin-managed video playback should not leave the SubMiner background Implemented managed playback shutdown by adding a `--managed-playback` app flag that the mpv plugin passes only for launcher-managed starts. The main mpv shutdown path now quits the app when initial args indicate managed playback, while explicit background/no-arg startup remains persistent. Added plugin start-gate and mpv protocol regression coverage. + +Implemented managed playback lifecycle: mpv plugin auto-start passes --background --managed-playback; app quits on mpv shutdown only when initial args include managedPlayback. Explicit --background and no-arg startup remain persistent. Installed updated mpv plugin to ~/.config/mpv/scripts/subminer via make install-plugin. + +Retest showed tray still remained. Root cause: relying on mpv's JSON IPC shutdown event was insufficient; the app may only see the socket close. Added managed-playback quit on MpvIpcClient onClose before reconnect scheduling, with regression coverage. ## Final Summary -Launcher-managed video playback now exits the SubMiner background app/tray when mpv shuts down, avoiding a leftover background process after closing a launcher-started video. Explicit `--background` and no-argument app startup remain persistent because the quit path is gated on the new `--managed-playback` flag. The mpv plugin passes that flag for auto-started playback, and mpv protocol shutdown requests app quit only in that managed mode. - -Verification: plugin start-gate regression coverage, mpv protocol shutdown regression coverage, CLI managed-playback parse coverage, plus broader local gates run before handoff. +Launcher-managed playback now starts SubMiner with an internal --managed-playback marker alongside --background. The app requests quit either when mpv sends shutdown or when the mpv IPC socket closes, but only for managed playback mode; explicit background/no-arg startup remains persistent. Added CLI, mpv protocol, mpv socket-close, and plugin regression coverage plus a launcher changelog fragment. Rebuilt the app/launcher and confirmed focused checks, typecheck, build, plugin tests, dist smoke, and formatting. diff --git a/src/core/services/mpv.test.ts b/src/core/services/mpv.test.ts index f4a388ec..e9b5b2a5 100644 --- a/src/core/services/mpv.test.ts +++ b/src/core/services/mpv.test.ts @@ -285,6 +285,25 @@ test('MpvIpcClient onClose resolves outstanding requests and schedules reconnect assert.equal(timers.length, 1); }); +test('MpvIpcClient onClose requests app quit for managed playback', () => { + let quitRequests = 0; + const client = new MpvIpcClient( + '/tmp/mpv.sock', + makeDeps({ + shouldQuitOnMpvShutdown: () => true, + requestAppQuit: () => { + quitRequests += 1; + }, + }), + ); + + (client as any).scheduleReconnect = () => {}; + + (client as any).transport.callbacks.onClose(); + + assert.equal(quitRequests, 1); +}); + test('MpvIpcClient reconnect replays property subscriptions and initial state requests', () => { const commands: unknown[] = []; const client = new MpvIpcClient('/tmp/mpv.sock', makeDeps()); diff --git a/src/core/services/mpv.ts b/src/core/services/mpv.ts index 3d55e198..7e5df317 100644 --- a/src/core/services/mpv.ts +++ b/src/core/services/mpv.ts @@ -219,6 +219,10 @@ export class MpvIpcClient implements MpvClient { this.playbackPaused = null; this.emit('connection-change', { connected: false }); this.failPendingRequests(); + if (this.deps.shouldQuitOnMpvShutdown?.() === true) { + this.deps.requestAppQuit?.(); + return; + } this.scheduleReconnect(); }, });