feat(core): add Discord presence service and extract Jellyfin runtime composition

Introduce Discord presence runtime support and continue composition-root decomposition by moving Jellyfin wiring into dedicated composer modules. This keeps main runtime orchestration thinner while preserving behavior and test coverage across config, runtime, and docs updates.
This commit is contained in:
2026-02-22 14:53:10 -08:00
parent 43a8a37f5b
commit edfe6640ac
52 changed files with 2222 additions and 317 deletions

View File

@@ -1,10 +1,11 @@
---
id: TASK-103
title: Extract Jellyfin runtime wiring from main.ts composition root
status: To Do
assignee: []
status: Done
assignee:
- codex-task103-jellyfin-main-composer-20260222T220441Z-m8p1
created_date: '2026-02-22 07:13'
updated_date: '2026-02-22 07:13'
updated_date: '2026-02-22 22:48'
labels:
- refactor
- maintainability
@@ -36,16 +37,52 @@ Goal: finish extraction of Jellyfin-specific dependency construction and command
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 `src/main.ts` no longer contains the full Jellyfin deps-building block.
- [ ] #2 New Jellyfin composer modules have focused tests covering handler wiring.
- [ ] #3 `bun run check:main-fanin` stays green after extraction.
- [ ] #4 `bun run build` and `bun run test:core:src` pass.
- [x] #1 `src/main.ts` no longer contains the full Jellyfin deps-building block.
- [x] #2 New Jellyfin composer modules have focused tests covering handler wiring.
- [x] #3 `bun run check:main-fanin` stays green after extraction.
- [x] #4 `bun run build` and `bun run test:core:src` pass.
<!-- AC:END -->
## Implementation Plan
<!-- SECTION:PLAN:BEGIN -->
Plan artifact: `docs/plans/2026-02-22-task-103-jellyfin-runtime-wiring.md`.
Execution plan:
1) Add `composeJellyfinRuntimeHandlers` composer module + seam tests and composer barrel export.
2) Replace inline Jellyfin deps-building block in `src/main.ts` with one composer invocation while preserving existing callsites (`runJellyfinCommand`, `openJellyfinSetupWindow`, remote session lifecycle, playback).
3) Update architecture docs ownership bullets for Jellyfin composer boundary.
4) Run required gates: `bun run check:main-fanin`, `bun run build`, `bun run test:core:src`.
5) Record AC/DoD evidence and final summary in Backlog task (no commit).
<!-- SECTION:PLAN:END -->
## Implementation Notes
<!-- SECTION:NOTES:BEGIN -->
2026-02-22T22:04:41Z: Execution started via Backlog MCP workflow. Loading task context, creating written plan artifact, then implementing extraction and focused validations without commit.
2026-02-22T22:38:58Z: Added new Jellyfin composition entrypoint `src/main/runtime/composers/jellyfin-runtime-composer.ts` and seam test `src/main/runtime/composers/jellyfin-runtime-composer.test.ts`; exported via composer barrel.
2026-02-22T22:38:58Z: Replaced inline Jellyfin deps-building block in `src/main.ts` with a single `composeJellyfinRuntimeHandlers(...)` invocation returning config/client/playback/remote/session/command/setup handlers used by existing callsites.
2026-02-22T22:38:58Z: Validation: `bun test src/main/runtime/composers/jellyfin-runtime-composer.test.ts src/main/runtime/composers/jellyfin-remote-composer.test.ts` PASS (2/2), `bun run check:main-fanin` PASS (`15 import lines, 9 unique runtime paths`), `bun run test:core:src` PASS (241 pass, 6 skip).
2026-02-22T22:38:58Z: `bun run build` currently FAILS in current working tree due pre-existing duplicate/invalid `src/main.ts` imports unrelated to TASK-103 extraction (many TS2300/TS2724 import-surface errors already present in file).
2026-02-22T22:49:05Z: Re-ran required completion gates after user fix: `bun run build` PASS, `bun run test:core:src` PASS (241 pass, 6 skip), `bun run check:main-fanin` PASS (`14 import lines, 11 unique runtime paths`).
<!-- SECTION:NOTES:END -->
## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
Extracted Jellyfin composition-root wiring from `src/main.ts` into a dedicated runtime composer entrypoint (`composeJellyfinRuntimeHandlers`) so main now delegates Jellyfin config resolution, client-info wiring, playback orchestration, remote session handlers, command dispatch, and setup-window wiring through a single composer surface. Added focused seam coverage in `src/main/runtime/composers/jellyfin-runtime-composer.test.ts`, retained existing `jellyfin-remote-composer` coverage, and updated architecture ownership docs to declare Jellyfin composer boundaries.
Validation run: `bun test src/main/runtime/composers/jellyfin-runtime-composer.test.ts src/main/runtime/composers/jellyfin-remote-composer.test.ts` (pass), `bun run check:main-fanin` (pass), `bun run build` (pass), and `bun run test:core:src` (pass).
<!-- SECTION:FINAL_SUMMARY:END -->
## Definition of Done
<!-- DOD:BEGIN -->
- [ ] #1 `src/main.ts` LOC reduced materially from current baseline.
- [ ] #2 Jellyfin runtime wiring is centralized in named composer module(s) with clear ownership docs.
- [ ] #3 No behavior regressions in Jellyfin command/setup flows.
- [x] #1 `src/main.ts` LOC reduced materially from current baseline.
- [x] #2 Jellyfin runtime wiring is centralized in named composer module(s) with clear ownership docs.
- [x] #3 No behavior regressions in Jellyfin command/setup flows.
<!-- DOD:END -->

View File

@@ -0,0 +1,62 @@
---
id: TASK-109
title: Add Discord Rich Presence integration with polished activity card
status: In Progress
assignee: []
created_date: '2026-02-22 19:40'
updated_date: '2026-02-22 22:36'
labels:
- feature
- discord
- presence
dependencies: []
priority: medium
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Add optional Discord Rich Presence support so SubMiner can publish current activity (show/file context, study/mining status, elapsed session) with a polished, readable Discord activity card.
<!-- SECTION:DESCRIPTION:END -->
## Action Steps
<!-- SECTION:PLAN:BEGIN -->
1. Choose and add a Discord RPC client strategy compatible with Electron + launcher runtime.
2. Add config toggle and safe defaults so Discord presence is opt-in.
3. Define presence payload model (state/details/timestamps/assets/buttons) from existing runtime session metadata.
4. Wire lifecycle updates for start, pause/resume, episode/file changes, and stop/quit.
5. Design assets/text for a clean, branded activity box that is informative without noisy updates.
6. Add debounce/rate-limit handling and fallback behavior when Discord is unavailable.
7. Add focused tests for payload mapping and lifecycle transitions; document setup in user docs.
<!-- SECTION:PLAN:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 Discord Rich Presence can be enabled via config and remains disabled by default.
- [ ] #2 Activity card shows clear state/details and updates correctly across playback/session transitions.
- [ ] #3 Activity card visuals (assets/text) are polished and consistent with project branding.
- [ ] #4 Runtime handles Discord closed/not installed/disconnected without crashes or noisy logs.
- [ ] #5 Docs include setup steps (app/client id), config keys, and troubleshooting notes.
<!-- AC:END -->
## Implementation Notes
<!-- SECTION:NOTES:BEGIN -->
Implemented opt-in `discordPresence` config surface in types/defaults/resolver/option-registry/template sections with clamped timing fields and focused config tests.
Added `src/core/services/discord-presence.ts` with payload mapping, debounce+interval update throttling, duplicate suppression, and resilient login/set/clear error handling.
Wired MPV/runtime lifecycle hooks to refresh Discord presence on subtitle/media/path/time/pause/connection transitions and added cleanup stop hook in app lifecycle cleanup path + focused tests.
Updated docs and generated config examples with Discord Rich Presence setup/config/troubleshooting guidance.
Validation status: focused config/runtime/discord tests pass and docs build passes. Full `bun run build` currently blocked by pre-existing `src/main.ts` duplicate imports/symbol errors unrelated to TASK-109 scope (existing in working tree).
<!-- SECTION:NOTES:END -->
## Definition of Done
<!-- DOD:BEGIN -->
- [ ] #1 Focused tests cover presence payload mapping and lifecycle update behavior.
- [ ] #2 Manual validation confirms Discord card appearance/updates for at least one real playback session.
- [ ] #3 Build/test/docs gates pass with no regressions.
<!-- DOD:END -->