This commit is contained in:
2026-02-17 22:50:57 -08:00
parent ffeef9c136
commit f20d019c11
315 changed files with 9876 additions and 12537 deletions

View File

@@ -47,4 +47,3 @@ jobs:
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options # or https://code.claude.com/docs/en/cli-reference for available options
# claude_args: '--allowed-tools Bash(gh pr:*)' # claude_args: '--allowed-tools Bash(gh pr:*)'

6
.prettierignore Normal file
View File

@@ -0,0 +1,6 @@
node_modules
dist
release
coverage
vendor
*.log

5
.prettierrc.json Normal file
View File

@@ -0,0 +1,5 @@
{
"printWidth": 100,
"singleQuote": true,
"trailingComma": "all"
}

View File

@@ -97,8 +97,8 @@ deps:
ensure-bun: ensure-bun:
@command -v bun >/dev/null 2>&1 || { printf '%s\n' "[ERROR] bun not found"; exit 1; } @command -v bun >/dev/null 2>&1 || { printf '%s\n' "[ERROR] bun not found"; exit 1; }
pretty: pretty: ensure-bun
@bunx prettier --write 'src/**/*.ts' @bun run format
build: build:
@printf '%s\n' "[INFO] Detected platform: $(PLATFORM)" @printf '%s\n' "[INFO] Detected platform: $(PLATFORM)"

View File

@@ -1,6 +1,6 @@
--- ---
id: m-0 id: m-0
title: "Codebase Clarity & Composability" title: 'Codebase Clarity & Composability'
--- ---
## Description ## Description

View File

@@ -13,12 +13,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Restored task after accidental cleanup. Ensure keybindings are available whenever the Electron runtime is active, while respecting focused overlay/input contexts that require local key handling. Restored task after accidental cleanup. Ensure keybindings are available whenever the Electron runtime is active, while respecting focused overlay/input contexts that require local key handling.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Started implementation: tracing overlay shortcut registration lifecycle and runtime activation gating. Started implementation: tracing overlay shortcut registration lifecycle and runtime activation gating.
Root cause: overlay shortcut sync executes during overlay runtime initialization before overlayRuntimeInitialized is set true, so registration could be skipped until a later visibility toggle. Root cause: overlay shortcut sync executes during overlay runtime initialization before overlayRuntimeInitialized is set true, so registration could be skipped until a later visibility toggle.
@@ -32,12 +35,15 @@ Updated CLI runtime gating so --start initializes overlay runtime, which activat
User clarified MPV-only workflow requirement. Added MPV plugin keybindings and script messages for mining/runtime actions (copy/mine/multi/mode/field-grouping/subsync/audio-card/runtime-options) so these actions are available from mpv chord bindings without relying on overlay global shortcuts. User clarified MPV-only workflow requirement. Added MPV plugin keybindings and script messages for mining/runtime actions (copy/mine/multi/mode/field-grouping/subsync/audio-card/runtime-options) so these actions are available from mpv chord bindings without relying on overlay global shortcuts.
Per user direction, reverted all shortcut/runtime/plugin changes from this implementation cycle. Desired behavior is to keep keybindings working only when overlay is active. Per user direction, reverted all shortcut/runtime/plugin changes from this implementation cycle. Desired behavior is to keep keybindings working only when overlay is active.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Ensured overlay shortcuts are available as soon as overlay runtime becomes active by resyncing after activation flag is set. This prevents startup states where shortcuts remained inactive until a later overlay visibility change. Ensured overlay shortcuts are available as soon as overlay runtime becomes active by resyncing after activation flag is set. This prevents startup states where shortcuts remained inactive until a later overlay visibility change.
Follow-up fix: included --start in overlay-runtime-required commands so keybinds are active right after startup, even before toggling visible/invisible overlays. Follow-up fix: included --start in overlay-runtime-required commands so keybinds are active right after startup, even before toggling visible/invisible overlays.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -13,11 +13,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Implement the overlay sizing redesign documented in `overlay_window.md`: move visible/invisible overlays from fullscreen bounds to content-bounded sizing, and decouple secondary subtitle rendering into an independent top bar window/lifecycle. Implement the overlay sizing redesign documented in `overlay_window.md`: move visible/invisible overlays from fullscreen bounds to content-bounded sizing, and decouple secondary subtitle rendering into an independent top bar window/lifecycle.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Per-layer bounds ownership is implemented for overlay windows (no shared full-bounds setter for all layers). - [ ] #1 Per-layer bounds ownership is implemented for overlay windows (no shared full-bounds setter for all layers).
- [ ] #2 Renderer-to-main IPC contract exists for measured overlay content bounds with layer identity and safe validation. - [ ] #2 Renderer-to-main IPC contract exists for measured overlay content bounds with layer identity and safe validation.
- [ ] #3 Visible and invisible overlays use content-bounded sizing with padding/clamp/jitter protections and full-bounds fallback when measurements are unavailable. - [ ] #3 Visible and invisible overlays use content-bounded sizing with padding/clamp/jitter protections and full-bounds fallback when measurements are unavailable.

View File

@@ -16,11 +16,15 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Implement content-bounded sizing for visible/invisible windows using measured rects plus tracker origin, with robust clamping and jitter resistance. Implement content-bounded sizing for visible/invisible windows using measured rects plus tracker origin, with robust clamping and jitter resistance.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Bounds algorithm applies configurable padding, minimum size, display-workarea clamp, and integer snap. - [ ] #1 Bounds algorithm applies configurable padding, minimum size, display-workarea clamp, and integer snap.
- [ ] #2 Main-process bounds updates are thresholded/debounced to reduce jitter and unnecessary `setBounds` churn. - [ ] #2 Main-process bounds updates are thresholded/debounced to reduce jitter and unnecessary `setBounds` churn.
- [ ] #3 When no valid measurement exists, layer falls back to safe tracker/display bounds without breaking interaction. - [ ] #3 When no valid measurement exists, layer falls back to safe tracker/display bounds without breaking interaction.

View File

@@ -13,11 +13,15 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Create and integrate a dedicated secondary subtitle overlay window with independent lifecycle, z-order, bounds, and pointer policy, decoupled from primary visible/invisible overlay windows. Create and integrate a dedicated secondary subtitle overlay window with independent lifecycle, z-order, bounds, and pointer policy, decoupled from primary visible/invisible overlay windows.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 A third overlay window dedicated to secondary subtitles is created and managed alongside existing visible/invisible windows. - [ ] #1 A third overlay window dedicated to secondary subtitles is created and managed alongside existing visible/invisible windows.
- [ ] #2 Secondary window visibility follows secondary mode semantics (`hidden`/`visible`/`hover`) independent of primary overlay visibility. - [ ] #2 Secondary window visibility follows secondary mode semantics (`hidden`/`visible`/`hover`) independent of primary overlay visibility.
- [ ] #3 Secondary subtitle text/mode/style updates are routed directly to the secondary window renderer path. - [ ] #3 Secondary subtitle text/mode/style updates are routed directly to the secondary window renderer path.

View File

@@ -13,11 +13,15 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add safety controls and verification coverage for the new content-bounded overlay architecture and secondary top-bar window. Add safety controls and verification coverage for the new content-bounded overlay architecture and secondary top-bar window.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Feature flag or equivalent rollout guard exists for switching to new sizing/window behavior. - [ ] #1 Feature flag or equivalent rollout guard exists for switching to new sizing/window behavior.
- [ ] #2 Service-level/unit tests cover bounds clamping, jitter thresholding, invalid measurement fallback, and per-layer updates. - [ ] #2 Service-level/unit tests cover bounds clamping, jitter thresholding, invalid measurement fallback, and per-layer updates.
- [ ] #3 Manual validation checklist documents and verifies wrap/no-wrap, style changes, monitor moves, tracker churn, modal interactions, and simultaneous overlay states. - [ ] #3 Manual validation checklist documents and verifies wrap/no-wrap, style changes, monitor moves, tracker churn, modal interactions, and simultaneous overlay states.

View File

@@ -12,11 +12,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Investigate and implement a UX where secondary subtitles (e.g., English text in our current sessions) become visible when hovered, while explicitly preventing user interactions that allow text lookup (including Yomitan integration) on those subtitles. This should allow readability-on-hover without exposing the secondary overlay text to selection/lookup workflows. Investigate and implement a UX where secondary subtitles (e.g., English text in our current sessions) become visible when hovered, while explicitly preventing user interactions that allow text lookup (including Yomitan integration) on those subtitles. This should allow readability-on-hover without exposing the secondary overlay text to selection/lookup workflows.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Secondary subtitles become visible only while hovered (or via equivalent hover-triggered mechanism), and return to default hidden/low-visibility state when not hovered. - [ ] #1 Secondary subtitles become visible only while hovered (or via equivalent hover-triggered mechanism), and return to default hidden/low-visibility state when not hovered.
- [ ] #2 When hovered, secondary subtitles do not trigger Yomitan lookup behavior in sessions where Yomitan is enabled. - [ ] #2 When hovered, secondary subtitles do not trigger Yomitan lookup behavior in sessions where Yomitan is enabled.
- [ ] #3 Secondary subtitles remain non-interactive for lookup paths (for example, text selection or lookup event propagation) while hover-visibility still works as intended. - [ ] #3 Secondary subtitles remain non-interactive for lookup paths (for example, text selection or lookup event propagation) while hover-visibility still works as intended.
@@ -25,6 +29,8 @@ Investigate and implement a UX where secondary subtitles (e.g., English text in
<!-- AC:END --> <!-- AC:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 Acceptance criteria are reviewed and covered by explicit manual/automated test coverage for hover reveal and lookup suppression behavior. - [ ] #1 Acceptance criteria are reviewed and covered by explicit manual/automated test coverage for hover reveal and lookup suppression behavior.
<!-- DOD:END --> <!-- DOD:END -->

View File

@@ -13,13 +13,17 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add a feature to query configured extension repositories for anime titles/episodes from SubMiner, let users select a streamable source, and play it through mpv with minimal friction. The result should be interactive from Electron (and triggered from mpv via existing command bridge), and fully configurable in app config. Add a feature to query configured extension repositories for anime titles/episodes from SubMiner, let users select a streamable source, and play it through mpv with minimal friction. The result should be interactive from Electron (and triggered from mpv via existing command bridge), and fully configurable in app config.
The implementation should provide a modular backend resolver and a clear UI flow that mirrors existing modal interaction patterns, while keeping mpv playback unchanged (use loadfile with resolved URL and optional headers/referrer metadata). The implementation should provide a modular backend resolver and a clear UI flow that mirrors existing modal interaction patterns, while keeping mpv playback unchanged (use loadfile with resolved URL and optional headers/referrer metadata).
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Create a stable config schema for one or more extension source backends (repos/endpoints/flags) and persist in user config + default template. - [ ] #1 Create a stable config schema for one or more extension source backends (repos/endpoints/flags) and persist in user config + default template.
- [ ] #2 Resolve an anime search term to candidate series from configured sources. - [ ] #2 Resolve an anime search term to candidate series from configured sources.
- [ ] #3 Resolve an episode selection to at least one playable stream URL candidate with playback metadata when available. - [ ] #3 Resolve an episode selection to at least one playable stream URL candidate with playback metadata when available.
@@ -32,13 +36,17 @@ The implementation should provide a modular backend resolver and a clear UI flow
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Execution sequence for implementation: 1) TASK-30.1 (config/model), 2) TASK-30.2 (resolver), 3) TASK-30.3 (IPC), 4) TASK-30.4 (UI modal), 5) TASK-30.5 (mpv trigger), 6) TASK-30.6 (validation/rollout checklist). Execution sequence for implementation: 1) TASK-30.1 (config/model), 2) TASK-30.2 (resolver), 3) TASK-30.3 (IPC), 4) TASK-30.4 (UI modal), 5) TASK-30.5 (mpv trigger), 6) TASK-30.6 (validation/rollout checklist).
Rollout recommendation: complete TASK-30.6 only after TASK-30.1-30.5 are done and can be verified in combination. Rollout recommendation: complete TASK-30.6 only after TASK-30.1-30.5 are done and can be verified in combination.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 Config schema validated in app startup (bad config surfaces clear error). - [ ] #1 Config schema validated in app startup (bad config surfaces clear error).
- [ ] #2 No hardcoded source/resolver URLs in UI layer; resolver details are backend-driven. - [ ] #2 No hardcoded source/resolver URLs in UI layer; resolver details are backend-driven.
- [ ] #3 Play command path uses existing mpv IPC/runtime helpers. - [ ] #3 Play command path uses existing mpv IPC/runtime helpers.

View File

@@ -14,11 +14,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Define a backend-agnostic configuration contract for extension repository streaming, including resolver endpoints/process mode, query/auth headers, timeouts, enable flags, and source preference. Wire schema through Config/ResolvedConfig and generated template/defaults so users can manage repos entirely through config. Define a backend-agnostic configuration contract for extension repository streaming, including resolver endpoints/process mode, query/auth headers, timeouts, enable flags, and source preference. Wire schema through Config/ResolvedConfig and generated template/defaults so users can manage repos entirely through config.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Add new config sections for extension source providers in Config and ResolvedConfig types. - [ ] #1 Add new config sections for extension source providers in Config and ResolvedConfig types.
- [ ] #2 Add validation defaults and env-compatible parsing for provider list, auth, header overrides, and feature flags. - [ ] #2 Add validation defaults and env-compatible parsing for provider list, auth, header overrides, and feature flags.
- [ ] #3 Update config template and docs text so defaults are discoverable and editable. - [ ] #3 Update config template and docs text so defaults are discoverable and editable.
@@ -29,11 +33,15 @@ Define a backend-agnostic configuration contract for extension repository stream
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Phase 1 — Foundation: config contract + validation + defaults Phase 1 — Foundation: config contract + validation + defaults
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 Config examples in template/docs include at least one provider entry shape. - [ ] #1 Config examples in template/docs include at least one provider entry shape.
- [ ] #2 Defaults remain backward-compatible when key is absent. - [ ] #2 Defaults remain backward-compatible when key is absent.
- [ ] #3 Feature can be disabled without touching unrelated settings. - [ ] #3 Feature can be disabled without touching unrelated settings.

View File

@@ -15,11 +15,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Build a dedicated service in main process that queries configured extension repos and normalizes results into a unified internal model, including optional playback metadata. Keep transport abstracted so future backends (local process, remote API, Manatán-compatible source) can be swapped without changing renderer contracts. Build a dedicated service in main process that queries configured extension repos and normalizes results into a unified internal model, including optional playback metadata. Keep transport abstracted so future backends (local process, remote API, Manatán-compatible source) can be swapped without changing renderer contracts.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Create a typed internal model for source, series, episode, and playable candidate with fields for quality/audio/headers/referrer/userAgent. - [ ] #1 Create a typed internal model for source, series, episode, and playable candidate with fields for quality/audio/headers/referrer/userAgent.
- [ ] #2 Implement provider abstraction with pluggable fetch/execution strategy from config. - [ ] #2 Implement provider abstraction with pluggable fetch/execution strategy from config.
- [ ] #3 Add services for searchAnime, listEpisodes, resolveStream (or equivalent) with cancellation/error boundaries. - [ ] #3 Add services for searchAnime, listEpisodes, resolveStream (or equivalent) with cancellation/error boundaries.
@@ -30,11 +34,15 @@ Build a dedicated service in main process that queries configured extension repo
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Phase 2 — Core service: provider integration and stream resolution Phase 2 — Core service: provider integration and stream resolution
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 Resolver never leaks raw provider payload to renderer. - [ ] #1 Resolver never leaks raw provider payload to renderer.
- [ ] #2 Streaming URL output includes reason for failure when unavailable. - [ ] #2 Streaming URL output includes reason for failure when unavailable.
- [ ] #3 Service boundaries allow unit-level validation of request/response mapping logic. - [ ] #3 Service boundaries allow unit-level validation of request/response mapping logic.

View File

@@ -15,11 +15,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add a typed preload and main-IPC contract for streaming queries and playback resolution so the renderer can initiate search/list/resolve without embedding network/provider logic in UI code. Add a typed preload and main-IPC contract for streaming queries and playback resolution so the renderer can initiate search/list/resolve without embedding network/provider logic in UI code.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Define IPC handlers in main with input/output schema validation and timeouts. - [ ] #1 Define IPC handlers in main with input/output schema validation and timeouts.
- [ ] #2 Expose corresponding functions in preload `window.electronAPI` and ElectronAPI types. - [ ] #2 Expose corresponding functions in preload `window.electronAPI` and ElectronAPI types.
- [ ] #3 Reuse existing mpv command channel for playback and add a dedicated request/response flow for resolver actions. - [ ] #3 Reuse existing mpv command channel for playback and add a dedicated request/response flow for resolver actions.
@@ -31,11 +35,15 @@ Add a typed preload and main-IPC contract for streaming queries and playback res
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Phase 3 — API surface: IPC/preload contract for resolver operations Phase 3 — API surface: IPC/preload contract for resolver operations
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 Renderer code can query providers without importing Node-only modules. - [ ] #1 Renderer code can query providers without importing Node-only modules.
- [ ] #2 IPC paths have clear names and consistent response shapes across all calls. - [ ] #2 IPC paths have clear names and consistent response shapes across all calls.
- [ ] #3 Error paths return explicit machine-readable codes mapped to user-visible messages. - [ ] #3 Error paths return explicit machine-readable codes mapped to user-visible messages.

View File

@@ -15,11 +15,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Implement a renderer flow to query configured providers, display results, let user choose series and episode, and trigger playback for a selected stream. The UI should support keyboard interactions and surface backend errors clearly. Implement a renderer flow to query configured providers, display results, let user choose series and episode, and trigger playback for a selected stream. The UI should support keyboard interactions and surface backend errors clearly.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Create modal UI/state model for query, results list, selected item, episode list, candidate qualities, and loading/error status. - [ ] #1 Create modal UI/state model for query, results list, selected item, episode list, candidate qualities, and loading/error status.
- [ ] #2 Wire renderer actions to new IPC methods for search/episode/resolve. - [ ] #2 Wire renderer actions to new IPC methods for search/episode/resolve.
- [ ] #3 Render one-click or enter-to-play action that calls existing mpv playback pathway. - [ ] #3 Render one-click or enter-to-play action that calls existing mpv playback pathway.
@@ -31,11 +35,15 @@ Implement a renderer flow to query configured providers, display results, let us
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Phase 4 — UX: interactive modal flow and playback callout Phase 4 — UX: interactive modal flow and playback callout
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 Modal state is isolated and unsubscribes listeners on close. - [ ] #1 Modal state is isolated and unsubscribes listeners on close.
- [ ] #2 No direct network logic in renderer beyond IPC calls. - [ ] #2 No direct network logic in renderer beyond IPC calls.
- [ ] #3 Visual style and behavior are consistent with existing modal patterns. - [ ] #3 Visual style and behavior are consistent with existing modal patterns.

View File

@@ -18,11 +18,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Allow users to open streaming selection from within mpv via keybind/menu and route that intent into renderer modal and playback flow without requiring separate window focus changes. Allow users to open streaming selection from within mpv via keybind/menu and route that intent into renderer modal and playback flow without requiring separate window focus changes.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Add/extend mpv Lua plugin or existing command registry to emit a custom action for opening the streaming picker. - [ ] #1 Add/extend mpv Lua plugin or existing command registry to emit a custom action for opening the streaming picker.
- [ ] #2 Handle this action in main IPC/mpv-command pipeline and forward to renderer modal state. - [ ] #2 Handle this action in main IPC/mpv-command pipeline and forward to renderer modal state.
- [ ] #3 Add at least one default keybinding/menu entry documented in config/plugin notes. - [ ] #3 Add at least one default keybinding/menu entry documented in config/plugin notes.
@@ -33,11 +37,15 @@ Allow users to open streaming selection from within mpv via keybind/menu and rou
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Phase 5 — In-player entry: mpv trigger/menu integration Phase 5 — In-player entry: mpv trigger/menu integration
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 No duplicate mpv command parsing between picker and legacy commands. - [ ] #1 No duplicate mpv command parsing between picker and legacy commands.
- [ ] #2 Feature can be used in overlay and mpv-only mode where applicable. - [ ] #2 Feature can be used in overlay and mpv-only mode where applicable.
- [ ] #3 No dependency on modal open state when launched by mpv trigger. - [ ] #3 No dependency on modal open state when launched by mpv trigger.

View File

@@ -16,11 +16,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Create a concrete validation task that defines end-to-end acceptance checks for config loading, resolver behavior, IPC contract correctness, UI flow, and mpv-triggered launch. The checklist should be actionable and align with existing project conventions so completion can be verified without guesswork. Create a concrete validation task that defines end-to-end acceptance checks for config loading, resolver behavior, IPC contract correctness, UI flow, and mpv-triggered launch. The checklist should be actionable and align with existing project conventions so completion can be verified without guesswork.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Define test scenarios for config success/failure cases, including invalid provider config and feature disabled mode. - [ ] #1 Define test scenarios for config success/failure cases, including invalid provider config and feature disabled mode.
- [ ] #2 Define search/list/resolve API contract tests and error-code assertions (empty, timeout, auth error, no playable URL). - [ ] #2 Define search/list/resolve API contract tests and error-code assertions (empty, timeout, auth error, no playable URL).
- [ ] #3 Define renderer UX checks for modal state transitions, loading indicators, empty results, selection, and play invocation. - [ ] #3 Define renderer UX checks for modal state transitions, loading indicators, empty results, selection, and play invocation.
@@ -33,11 +37,15 @@ Create a concrete validation task that defines end-to-end acceptance checks for
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Phase 6 — Validation: rollout, smoke tests, and release readiness checklist Phase 6 — Validation: rollout, smoke tests, and release readiness checklist
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 Checklist covers happy-path and failure-path for each task dependency. - [ ] #1 Checklist covers happy-path and failure-path for each task dependency.
- [ ] #2 Verification steps are executable without external tooling assumptions. - [ ] #2 Verification steps are executable without external tooling assumptions.
- [ ] #3 No task can be marked done without explicit evidence fields filled in. - [ ] #3 No task can be marked done without explicit evidence fields filled in.

View File

@@ -17,11 +17,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Improve the Aniyomi/anime extension streaming flow to prefer English-capable sources with soft subtitles, and automatically recover when only hard-subbed streams are available by stripping embedded subtitles with ffmpeg and attaching external Jimaku subtitle files into mpv. Improve the Aniyomi/anime extension streaming flow to prefer English-capable sources with soft subtitles, and automatically recover when only hard-subbed streams are available by stripping embedded subtitles with ffmpeg and attaching external Jimaku subtitle files into mpv.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 During source scoring/selection, prefer providers/sources that declare or expose soft subtitles for English audio or subtitle tracks over hard-subbed alternatives. - [ ] #1 During source scoring/selection, prefer providers/sources that declare or expose soft subtitles for English audio or subtitle tracks over hard-subbed alternatives.
- [ ] #2 Add a config option for preferred language targets (default English) and fallback policy (favor soft subtitles, then hard-sub fallback). - [ ] #2 Add a config option for preferred language targets (default English) and fallback policy (favor soft subtitles, then hard-sub fallback).
- [ ] #3 Detect when a resolved stream is hard-sub-only and a soft-sub source is unavailable for the same episode. - [ ] #3 Detect when a resolved stream is hard-sub-only and a soft-sub source is unavailable for the same episode.

View File

@@ -16,11 +16,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add lightweight telemetry/analytics hooks (local logs + optional structured counters) to measure how Aniyomi/anime streaming source selection behaves, including soft-sub preference, hard-sub fallback usage, and ffmpeg+Jimaku post-processing outcomes, to support source ranking tuning. Add lightweight telemetry/analytics hooks (local logs + optional structured counters) to measure how Aniyomi/anime streaming source selection behaves, including soft-sub preference, hard-sub fallback usage, and ffmpeg+Jimaku post-processing outcomes, to support source ranking tuning.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Track per-playback decision metadata including chosen source, language match score, subtitle mode (soft/hard), and reason for source preference ordering. - [ ] #1 Track per-playback decision metadata including chosen source, language match score, subtitle mode (soft/hard), and reason for source preference ordering.
- [ ] #2 Emit success/failure counters for hard-sub stripping attempts (started/succeeded/failed/unsupported codec) with reason codes. - [ ] #2 Emit success/failure counters for hard-sub stripping attempts (started/succeeded/failed/unsupported codec) with reason codes.
- [ ] #3 Log whether Jimaku subtitle attachment was available and successfully loaded for ffmpeg-assisted flows. - [ ] #3 Log whether Jimaku subtitle attachment was available and successfully loaded for ffmpeg-assisted flows.

View File

@@ -15,11 +15,15 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add user-configurable controls for Aniyomi streaming subtitle behavior, including preferred language profile, soft-vs-hard source preference, ffmpeg-assisted hard-sub removal behavior, and policy toggles so quality and fallback behavior can be tuned without code changes. Add user-configurable controls for Aniyomi streaming subtitle behavior, including preferred language profile, soft-vs-hard source preference, ffmpeg-assisted hard-sub removal behavior, and policy toggles so quality and fallback behavior can be tuned without code changes.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Add settings UI fields to define preferred subtitle/audiotrack language order (e.g., en, ja) and enable/disable hard-sub fallback mode. - [ ] #1 Add settings UI fields to define preferred subtitle/audiotrack language order (e.g., en, ja) and enable/disable hard-sub fallback mode.
- [ ] #2 Add explicit toggle for enabling hard-sub stripping via ffmpeg and configurable timeout/quality limits to avoid long waits. - [ ] #2 Add explicit toggle for enabling hard-sub stripping via ffmpeg and configurable timeout/quality limits to avoid long waits.
- [ ] #3 Expose source ranking preferences for soft-sub vs hard-sub sources and optional fallback to native/transcoded source when preferred modes are unavailable. - [ ] #3 Expose source ranking preferences for soft-sub vs hard-sub sources and optional fallback to native/transcoded source when preferred modes are unavailable.

View File

@@ -16,12 +16,15 @@ priority: low
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Allow users to share their subtitle timing corrections to a community database, so other users watching the same video file get pre-synced subtitles automatically. Allow users to share their subtitle timing corrections to a community database, so other users watching the same video file get pre-synced subtitles automatically.
## Motivation ## Motivation
Subtitle synchronization (alass/ffsubsync) is one of the most friction-heavy steps in the mining workflow. Users spend time syncing subtitles that someone else has already synced for the exact same video. A shared database of timing corrections keyed by video file hash would eliminate redundant work. Subtitle synchronization (alass/ffsubsync) is one of the most friction-heavy steps in the mining workflow. Users spend time syncing subtitles that someone else has already synced for the exact same video. A shared database of timing corrections keyed by video file hash would eliminate redundant work.
## Design ## Design
1. **Video identification**: Use a partial file hash (first + last N bytes, or a media fingerprint) to identify video files without uploading content 1. **Video identification**: Use a partial file hash (first + last N bytes, or a media fingerprint) to identify video files without uploading content
2. **Timing data**: Store the timing offset/warp parameters produced by alass/ffsubsync, not the full subtitle file 2. **Timing data**: Store the timing offset/warp parameters produced by alass/ffsubsync, not the full subtitle file
3. **Upload flow**: After a successful sync, offer to share the timing correction (opt-in) 3. **Upload flow**: After a successful sync, offer to share the timing correction (opt-in)
@@ -29,6 +32,7 @@ Subtitle synchronization (alass/ffsubsync) is one of the most friction-heavy ste
5. **Trust model**: Simple upvote/downvote on corrections; show number of users who confirmed a correction works 5. **Trust model**: Simple upvote/downvote on corrections; show number of users who confirmed a correction works
## Technical considerations ## Technical considerations
- Backend could be a simple REST API with a lightweight database (or even a GitHub-hosted JSON/SQLite file for v1) - Backend could be a simple REST API with a lightweight database (or even a GitHub-hosted JSON/SQLite file for v1)
- Privacy: only file hashes and timing parameters are shared, never video content or personal data - Privacy: only file hashes and timing parameters are shared, never video content or personal data
- Subtitle source (jimaku entry ID) can serve as an additional matching key - Subtitle source (jimaku entry ID) can serve as an additional matching key
@@ -36,12 +40,15 @@ Subtitle synchronization (alass/ffsubsync) is one of the most friction-heavy ste
- Could integrate with existing jimaku modal flow - Could integrate with existing jimaku modal flow
## Phasing ## Phasing
- v1: Local export/import of timing corrections (share as files) - v1: Local export/import of timing corrections (share as files)
- v2: Optional cloud sync with community database - v2: Optional cloud sync with community database
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Video files are identified by content hash without uploading video data. - [ ] #1 Video files are identified by content hash without uploading video data.
- [ ] #2 Timing corrections (offset/warp parameters) can be exported and shared. - [ ] #2 Timing corrections (offset/warp parameters) can be exported and shared.
- [ ] #3 Before syncing, the app checks for existing community corrections for the current video. - [ ] #3 Before syncing, the app checks for existing community corrections for the current video.

View File

@@ -16,11 +16,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Implement a new streaming mode so SubMiner can resolve and play episodes via ani-cli stream sources instead of existing file/download flow. The mode is enabled with a CLI flag (`-s` / `--stream`) and, when active, should prefer streamed playback and subtitle handling that keeps Japanese (or configured primary) subtitles as the main track. If a stream lacks Japanese subtitle tracks, fetch and inject subtitles from Jimaku and set them as primary subtitles according to SubMiner config. Implement a new streaming mode so SubMiner can resolve and play episodes via ani-cli stream sources instead of existing file/download flow. The mode is enabled with a CLI flag (`-s` / `--stream`) and, when active, should prefer streamed playback and subtitle handling that keeps Japanese (or configured primary) subtitles as the main track. If a stream lacks Japanese subtitle tracks, fetch and inject subtitles from Jimaku and set them as primary subtitles according to SubMiner config.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Add a command-line option `-s`/`--stream` that enables streaming mode and is documented in help/config UX. - [ ] #1 Add a command-line option `-s`/`--stream` that enables streaming mode and is documented in help/config UX.
- [ ] #2 When streaming mode is enabled, resolve episode/video URLs using existing ani-cli stream selection logic (ported into SubMiner) and route playback to the resolved stream source. - [ ] #2 When streaming mode is enabled, resolve episode/video URLs using existing ani-cli stream selection logic (ported into SubMiner) and route playback to the resolved stream source.
- [ ] #3 If stream metadata contains a Japanese subtitle track, preserve that track as the primary subtitle stream path per current primary-subtitle selection behavior. - [ ] #3 If stream metadata contains a Japanese subtitle track, preserve that track as the primary subtitle stream path per current primary-subtitle selection behavior.
@@ -32,11 +36,15 @@ Implement a new streaming mode so SubMiner can resolve and play episodes via ani
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Superseded by TASK-51. Streaming via ani-cli in subminer was removed due Cloudflare 403/unreliable source metadata; re-evaluate later if reintroduced behind a feature flag and redesigned resolver/metadata pipeline. Superseded by TASK-51. Streaming via ani-cli in subminer was removed due Cloudflare 403/unreliable source metadata; re-evaluate later if reintroduced behind a feature flag and redesigned resolver/metadata pipeline.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 CLI accepts both `-s` and `--stream` and enables streaming-specific behavior. - [ ] #1 CLI accepts both `-s` and `--stream` and enables streaming-specific behavior.
- [ ] #2 Streaming mode resolves streams through migrated ani-cli logic. - [ ] #2 Streaming mode resolves streams through migrated ani-cli logic.
- [ ] #3 Japanese subs are preferred from stream metadata when available; Jimaku fallback is used only when absent. - [ ] #3 Japanese subs are preferred from stream metadata when available; Jimaku fallback is used only when absent.

View File

@@ -16,11 +16,15 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add the `-s`/`--stream` option end-to-end in SubMiner CLI and configuration handling, including defaults, help text, parsing/validation, and explicit routing so streaming mode is only enabled when requested. Add the `-s`/`--stream` option end-to-end in SubMiner CLI and configuration handling, including defaults, help text, parsing/validation, and explicit routing so streaming mode is only enabled when requested.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Introduce `-s` short option and `--stream` long option in CLI parsing without breaking existing flags. - [ ] #1 Introduce `-s` short option and `--stream` long option in CLI parsing without breaking existing flags.
- [ ] #2 When set, the resulting config state reflects streaming mode enabled and is propagated to playback/session startup. - [ ] #2 When set, the resulting config state reflects streaming mode enabled and is propagated to playback/session startup.
- [ ] #3 When unset, behavior remains identical to current non-streaming flows. - [ ] #3 When unset, behavior remains identical to current non-streaming flows.
@@ -29,5 +33,7 @@ Add the `-s`/`--stream` option end-to-end in SubMiner CLI and configuration hand
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Superseded by TASK-51. CLI stream mode work deferred until streaming architecture is revisited. Superseded by TASK-51. CLI stream mode work deferred until streaming architecture is revisited.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -16,11 +16,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Implement stream URL resolution by porting ani-cli logic for selecting providers/episodes and obtaining playable stream URLs so SubMiner can consume stream sources directly. Implement stream URL resolution by porting ani-cli logic for selecting providers/episodes and obtaining playable stream URLs so SubMiner can consume stream sources directly.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Encapsulate stream search/provider selection logic in a dedicated module in SubMiner. - [ ] #1 Encapsulate stream search/provider selection logic in a dedicated module in SubMiner.
- [ ] #2 Resolve episode query input into a canonical playable stream URL in streaming mode. - [ ] #2 Resolve episode query input into a canonical playable stream URL in streaming mode.
- [ ] #3 Preserve existing behavior for non-streaming flow and expose errors when stream resolution fails. - [ ] #3 Preserve existing behavior for non-streaming flow and expose errors when stream resolution fails.
@@ -29,5 +33,7 @@ Implement stream URL resolution by porting ani-cli logic for selecting providers
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Superseded by TASK-51. Stream URL resolution via ani-cli postponed; previous attempt exposed anti-bot/403 fragility and poor title-source reliability. Superseded by TASK-51. Stream URL resolution via ani-cli postponed; previous attempt exposed anti-bot/403 fragility and poor title-source reliability.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -16,11 +16,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Handle subtitle track selection for stream playback so Japanese (or configured primary language) subtitle behavior is correctly applied when stream metadata includes or omits JP tracks. Handle subtitle track selection for stream playback so Japanese (or configured primary language) subtitle behavior is correctly applied when stream metadata includes or omits JP tracks.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Use stream metadata to choose and mark the configured primary language subtitle as active when available. - [ ] #1 Use stream metadata to choose and mark the configured primary language subtitle as active when available.
- [ ] #2 If no matching primary language track exists in stream metadata, keep previous fallback behavior only for non-streaming mode. - [ ] #2 If no matching primary language track exists in stream metadata, keep previous fallback behavior only for non-streaming mode.
- [ ] #3 When no Japanese track exists and config primary is different, explicitly set configured primary as primary track for streaming flow. - [ ] #3 When no Japanese track exists and config primary is different, explicitly set configured primary as primary track for streaming flow.
@@ -29,5 +33,7 @@ Handle subtitle track selection for stream playback so Japanese (or configured p
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Superseded by TASK-51. Stream subtitle language precedence in streaming mode deferred with full design revisit. Superseded by TASK-51. Stream subtitle language precedence in streaming mode deferred with full design revisit.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -17,11 +17,15 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
When a resolved stream lacks JP/primary-language tracks, fetch subtitles from Jimaku and inject them for playback, overriding non-primary subtitle defaults in streaming mode according to config. When a resolved stream lacks JP/primary-language tracks, fetch subtitles from Jimaku and inject them for playback, overriding non-primary subtitle defaults in streaming mode according to config.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Detect missing primary subtitle from stream metadata and trigger Jimaku lookup for matching episode. - [ ] #1 Detect missing primary subtitle from stream metadata and trigger Jimaku lookup for matching episode.
- [ ] #2 Load fetched Jimaku subtitles into playback pipeline and mark them as the primary subtitle track. - [ ] #2 Load fetched Jimaku subtitles into playback pipeline and mark them as the primary subtitle track.
- [ ] #3 Fallback is only used in streaming mode and should not alter subtitle behavior outside streaming. - [ ] #3 Fallback is only used in streaming mode and should not alter subtitle behavior outside streaming.
@@ -30,5 +34,7 @@ When a resolved stream lacks JP/primary-language tracks, fetch subtitles from Ji
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Superseded by TASK-51. Jimaku fallback for streams deferred along with entire streaming flow. Superseded by TASK-51. Jimaku fallback for streams deferred along with entire streaming flow.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -16,11 +16,15 @@ priority: low
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Create a validation plan or tests for CLI flag behavior, stream resolution, and subtitle precedence/fallback rules so streaming mode changes are measurable and regressions are caught. Create a validation plan or tests for CLI flag behavior, stream resolution, and subtitle precedence/fallback rules so streaming mode changes are measurable and regressions are caught.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Document/manual checklist covers `-s` and `--stream` invocation and streaming-only behavior. - [ ] #1 Document/manual checklist covers `-s` and `--stream` invocation and streaming-only behavior.
- [ ] #2 Include cases for (a) stream with JP subtitles, (b) no JP subtitles with Jimaku fallback, (c) primary-language not Japanese. - [ ] #2 Include cases for (a) stream with JP subtitles, (b) no JP subtitles with Jimaku fallback, (c) primary-language not Japanese.
- [ ] #3 Run or provide reproducible checks to confirm non-streaming behavior unchanged. - [ ] #3 Run or provide reproducible checks to confirm non-streaming behavior unchanged.
@@ -29,5 +33,7 @@ Create a validation plan or tests for CLI flag behavior, stream resolution, and
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Superseded by TASK-51. Verification plan moved to deferred reimplementation context. Superseded by TASK-51. Verification plan moved to deferred reimplementation context.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -22,11 +22,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Implement SubMiner streaming mode end-to-end behind a `-s`/`--stream` flag. In stream mode, use the vendored ani-cli resolution flow to get playable stream URLs instead of local file/YouTube URL handling. If resolved streams do not expose Japanese subtitles, fetch matching subtitles from Jimaku and load them into mpv as the active primary subtitle track, overwriting the current non-primary/non-Japanese default according to subminer primary-subtitle configuration. Implement SubMiner streaming mode end-to-end behind a `-s`/`--stream` flag. In stream mode, use the vendored ani-cli resolution flow to get playable stream URLs instead of local file/YouTube URL handling. If resolved streams do not expose Japanese subtitles, fetch matching subtitles from Jimaku and load them into mpv as the active primary subtitle track, overwriting the current non-primary/non-Japanese default according to subminer primary-subtitle configuration.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 When `subminer -s` is used, resolution should pass a search/query through ani-cli stream logic and play the resolved stream source. - [ ] #1 When `subminer -s` is used, resolution should pass a search/query through ani-cli stream logic and play the resolved stream source.
- [ ] #2 If the stream includes a Japanese subtitle track, preserve and select the configured primary subtitle language behavior without Jimaku injection. - [ ] #2 If the stream includes a Japanese subtitle track, preserve and select the configured primary subtitle language behavior without Jimaku injection.
- [ ] #3 If no Japanese (or configured primary language) subtitle exists in stream metadata, fetch and inject Jimaku subtitles before playback starts. - [ ] #3 If no Japanese (or configured primary language) subtitle exists in stream metadata, fetch and inject Jimaku subtitles before playback starts.
@@ -37,11 +41,15 @@ Implement SubMiner streaming mode end-to-end behind a `-s`/`--stream` flag. In s
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Superseded by TASK-51. End-to-end stream wiring to ani-cli is deferred. Superseded by TASK-51. End-to-end stream wiring to ani-cli is deferred.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 CLI exposes both `-s` and `--stream` in help/config and validation. - [ ] #1 CLI exposes both `-s` and `--stream` in help/config and validation.
- [ ] #2 Implementation includes a clear fallback path when stream subtitles are absent and Jimaku search/download fails gracefully. - [ ] #2 Implementation includes a clear fallback path when stream subtitles are absent and Jimaku search/download fails gracefully.
- [ ] #3 Subtitles loading path avoids temp-file leaks; temporary media/subtitle artifacts are cleaned up on exit. - [ ] #3 Subtitles loading path avoids temp-file leaks; temporary media/subtitle artifacts are cleaned up on exit.

View File

@@ -15,9 +15,11 @@ dependencies: []
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Current codebase has removed ani-cli integration and stream-mode from subminer temporarily. Keep a deferred design task to reintroduce streaming mode in a future cycle. Current codebase has removed ani-cli integration and stream-mode from subminer temporarily. Keep a deferred design task to reintroduce streaming mode in a future cycle.
Findings from prior attempts: Findings from prior attempts:
- `subminer -s <query>` path relied on `ani-cli` resolving stream URLs, but returned stream URLs that are Cloudflare-protected (`tools.fast4speed.rsvp`) and often returned 403 from mpv/ytdl-hook (generic anti-bot/Forbidden). - `subminer -s <query>` path relied on `ani-cli` resolving stream URLs, but returned stream URLs that are Cloudflare-protected (`tools.fast4speed.rsvp`) and often returned 403 from mpv/ytdl-hook (generic anti-bot/Forbidden).
- Even after passing `ytdl` extractor args, stream playback via subminer still failed because URL/anti-bot handling differed from direct ani-cli execution context. - Even after passing `ytdl` extractor args, stream playback via subminer still failed because URL/anti-bot handling differed from direct ani-cli execution context.
- We also observed stream title resolution issues: selected titles from ani-cli menu were unreliable/random and broke downstream Jimaku matching behavior. - We also observed stream title resolution issues: selected titles from ani-cli menu were unreliable/random and broke downstream Jimaku matching behavior.
@@ -25,6 +27,7 @@ Findings from prior attempts:
- Based on these findings and instability, stream mode should be explicitly deferred rather than partially reintroduced. - Based on these findings and instability, stream mode should be explicitly deferred rather than partially reintroduced.
Proposal: Proposal:
- Reintroduce behind a feature flag / future milestone only. - Reintroduce behind a feature flag / future milestone only.
- Re-design around a dedicated stream source resolver with robust URL acquisition and source metadata preservation (query/episode/title) before subtitle sync flows. - Re-design around a dedicated stream source resolver with robust URL acquisition and source metadata preservation (query/episode/title) before subtitle sync flows.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->

View File

@@ -19,7 +19,9 @@ priority: low
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
The service layer has inconsistent naming: The service layer has inconsistent naming:
- Some functions end in `Service`: `handleCliCommandService`, `loadSubtitlePositionService` - Some functions end in `Service`: `handleCliCommandService`, `loadSubtitlePositionService`
- Some end in `RuntimeService`: `replayCurrentSubtitleRuntimeService`, `sendMpvCommandRuntimeService` - Some end in `RuntimeService`: `replayCurrentSubtitleRuntimeService`, `sendMpvCommandRuntimeService`
- Some are plain: `shortcutMatchesInputForLocalFallback` - Some are plain: `shortcutMatchesInputForLocalFallback`
@@ -28,13 +30,16 @@ The service layer has inconsistent naming:
The barrel export (src/core/services/index.ts) re-exports 79 symbols from 28 files through a single surface, which obscures dependency boundaries. Consumers import everything from `./core/services` and can't tell which service file they actually depend on. The barrel export (src/core/services/index.ts) re-exports 79 symbols from 28 files through a single surface, which obscures dependency boundaries. Consumers import everything from `./core/services` and can't tell which service file they actually depend on.
Establish consistent naming: Establish consistent naming:
- Exported service functions: `verbNounService` (e.g., `handleCliCommand`) - Exported service functions: `verbNounService` (e.g., `handleCliCommand`)
- Deps factory functions: `create*Deps` - Deps factory functions: `create*Deps`
- Consider whether the barrel re-export is still the right pattern vs direct imports from individual files. - Consider whether the barrel re-export is still the right pattern vs direct imports from individual files.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 All service functions follow a consistent naming convention - [ ] #1 All service functions follow a consistent naming convention
- [ ] #2 Decision documented on barrel export vs direct imports - [ ] #2 Decision documented on barrel export vs direct imports
- [ ] #3 No functional changes - [ ] #3 No functional changes
@@ -43,11 +48,15 @@ Establish consistent naming:
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Naming convention consolidation should be addressed as part of TASK-27.2 (split main.ts) and TASK-27.3 (anki-integration split). As modules are extracted and given clear boundaries, naming will be standardized at each boundary. No need to do a standalone naming pass — it's wasted effort if the module structure is about to change. Naming convention consolidation should be addressed as part of TASK-27.2 (split main.ts) and TASK-27.3 (anki-integration split). As modules are extracted and given clear boundaries, naming will be standardized at each boundary. No need to do a standalone naming pass — it's wasted effort if the module structure is about to change.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Subsumed by TASK-27.2 and TASK-27.3. Naming conventions were standardized at module boundaries during extraction. A standalone global naming pass would be churn with no structural benefit now that modules have clear ownership boundaries. Subsumed by TASK-27.2 and TASK-27.3. Naming conventions were standardized at module boundaries during extraction. A standalone global naming pass would be churn with no structural benefit now that modules have clear ownership boundaries.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -20,19 +20,24 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
In renderer.ts (around lines 865-1075), `applyInvisibleSubtitleLayoutFromMpvMetrics` is a 211-line function with up to 5 levels of nesting. It handles OSD scaling calculations, platform-specific font compensation (macOS vs Linux), DPR calculations, ASS alignment tag interpretation (\an tags), baseline compensation, line-height fixes, font property application, and transform origin — all interleaved. In renderer.ts (around lines 865-1075), `applyInvisibleSubtitleLayoutFromMpvMetrics` is a 211-line function with up to 5 levels of nesting. It handles OSD scaling calculations, platform-specific font compensation (macOS vs Linux), DPR calculations, ASS alignment tag interpretation (\an tags), baseline compensation, line-height fixes, font property application, and transform origin — all interleaved.
Extract into focused helpers: Extract into focused helpers:
- `calculateOsdScale(metrics, renderAreaHeight)` — pure scaling math - `calculateOsdScale(metrics, renderAreaHeight)` — pure scaling math
- `calculateSubtitlePosition(metrics, scale, alignment)` — ASS \an tag interpretation + positioning - `calculateSubtitlePosition(metrics, scale, alignment)` — ASS \an tag interpretation + positioning
- `applyPlatformFontCompensation(style, platform)` — macOS kerning/size adjustments - `applyPlatformFontCompensation(style, platform)` — macOS kerning/size adjustments
- `applySubtitleStyle(element, computedStyle)` — DOM style application - `applySubtitleStyle(element, computedStyle)` — DOM style application
This can be done independently of or as part of TASK-6 (renderer split). This can be done independently of or as part of TASK-6 (renderer split).
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 No single function exceeds ~50 lines in the positioning logic - [x] #1 No single function exceeds ~50 lines in the positioning logic
- [x] #2 Helper functions are pure where possible (take inputs, return outputs) - [x] #2 Helper functions are pure where possible (take inputs, return outputs)
- [x] #3 Platform-specific branches isolated into dedicated helpers - [x] #3 Platform-specific branches isolated into dedicated helpers
@@ -42,13 +47,17 @@ This can be done independently of or as part of TASK-6 (renderer split).
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Helpers were split so positioning math, base layout, and typography/vertical handling are no longer in one monolith; see `src/renderer/positioning/invisible-layout.ts` and peer files. Helpers were split so positioning math, base layout, and typography/vertical handling are no longer in one monolith; see `src/renderer/positioning/invisible-layout.ts` and peer files.
Applied as part of TASK-27.5 with helper extraction: moved mpv subtitle layout orchestration to `invisible-layout.ts` and extracted metric/base/style helpers into `invisible-layout-metrics.ts` and `invisible-layout-helpers.ts`. Applied as part of TASK-27.5 with helper extraction: moved mpv subtitle layout orchestration to `invisible-layout.ts` and extracted metric/base/style helpers into `invisible-layout-metrics.ts` and `invisible-layout-helpers.ts`.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Decomposition of `applyInvisibleSubtitleLayoutFromMpvMetrics` completed as part of TASK-27.5: function body split into metric/layout/typography helpers and small coordinator preserved. Manual validation completed by user; behavior remains stable. Decomposition of `applyInvisibleSubtitleLayoutFromMpvMetrics` completed as part of TASK-27.5: function body split into metric/layout/typography helpers and small coordinator preserved. Manual validation completed by user; behavior remains stable.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -23,18 +23,23 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Currently renderer.ts is a single file loaded directly by Electron's renderer process via a script tag in index.html. To split it into modules (TASK-6), we need a bundling step since Electron renderer's default context doesn't support bare ES module imports without additional configuration. Currently renderer.ts is a single file loaded directly by Electron's renderer process via a script tag in index.html. To split it into modules (TASK-6), we need a bundling step since Electron renderer's default context doesn't support bare ES module imports without additional configuration.
Options: Options:
1. **esbuild** — fast, minimal config, already used in many Electron projects 1. **esbuild** — fast, minimal config, already used in many Electron projects
2. **Electron's native ESM support** — requires `"type": "module"` and sandbox configuration 2. **Electron's native ESM support** — requires `"type": "module"` and sandbox configuration
3. **TypeScript compiler output** — if targeting a single concatenated bundle 3. **TypeScript compiler output** — if targeting a single concatenated bundle
The build pipeline already compiles TypeScript and copies renderer assets. Adding a bundling step for the renderer would slot into the existing `npm run build` script. The build pipeline already compiles TypeScript and copies renderer assets. Adding a bundling step for the renderer would slot into the existing `npm run build` script.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Renderer code can be split across multiple .ts files with imports - [x] #1 Renderer code can be split across multiple .ts files with imports
- [x] #2 Build pipeline bundles renderer modules into a single output for Electron - [x] #2 Build pipeline bundles renderer modules into a single output for Electron
- [x] #3 Existing `make build` still works end-to-end - [x] #3 Existing `make build` still works end-to-end
@@ -44,13 +49,17 @@ The build pipeline already compiles TypeScript and copies renderer assets. Addin
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Updated root npm build pipeline to use an explicit renderer bundle step via esbuild. Added `build:renderer` script to emit a single `dist/renderer/renderer.js` from `src/renderer/renderer.ts`; `build` now runs `pnpm run build:renderer` and preserves existing index/style copy and macOS helper step. Added `esbuild` to devDependencies. Updated root npm build pipeline to use an explicit renderer bundle step via esbuild. Added `build:renderer` script to emit a single `dist/renderer/renderer.js` from `src/renderer/renderer.ts`; `build` now runs `pnpm run build:renderer` and preserves existing index/style copy and macOS helper step. Added `esbuild` to devDependencies.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Implemented renderer bundling step and wired `build` to use it. This adds `pnpm run build:renderer` which bundles `src/renderer/renderer.ts` into a single `dist/renderer/renderer.js` for Electron to load. Also added `esbuild` as a dev dependency and aligned `pnpm-lock.yaml` importer metadata for dependency consistency. Kept `index.html`/`style.css` copy path unchanged, so renderer asset layout remains stable. Implemented renderer bundling step and wired `build` to use it. This adds `pnpm run build:renderer` which bundles `src/renderer/renderer.ts` into a single `dist/renderer/renderer.js` for Electron to load. Also added `esbuild` as a dev dependency and aligned `pnpm-lock.yaml` importer metadata for dependency consistency. Kept `index.html`/`style.css` copy path unchanged, so renderer asset layout remains stable.
Implemented additional test-layer type fix after build breakage by correcting `makeDepsFromMecabTokenizer` and related `tokenizeWithMecab` mocks to match expected `Token` vs `MergedToken` shapes, keeping runtime behavior unchanged while satisfying TS checks. Implemented additional test-layer type fix after build breakage by correcting `makeDepsFromMecabTokenizer` and related `tokenizeWithMecab` mocks to match expected `Token` vs `MergedToken` shapes, keeping runtime behavior unchanged while satisfying TS checks.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -14,11 +14,15 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Refactor overlay runtime so each overlay layer owns and applies its bounds independently. Keep tracker geometry as shared origin input only. Refactor overlay runtime so each overlay layer owns and applies its bounds independently. Keep tracker geometry as shared origin input only.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 `updateOverlayBoundsService` no longer applies the same bounds to every overlay window by default. - [x] #1 `updateOverlayBoundsService` no longer applies the same bounds to every overlay window by default.
- [x] #2 Main runtime/manager exposes per-layer bounds update paths for visible and invisible overlays. - [x] #2 Main runtime/manager exposes per-layer bounds update paths for visible and invisible overlays.
- [x] #3 Window tracker updates feed shared origin data; each layer applies its own computed bounds. - [x] #3 Window tracker updates feed shared origin data; each layer applies its own computed bounds.
@@ -28,6 +32,7 @@ Refactor overlay runtime so each overlay layer owns and applies its bounds indep
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Started implementation for per-layer overlay bounds ownership refactor. Started implementation for per-layer overlay bounds ownership refactor.
Implemented per-layer bounds ownership path: visible and invisible layers now update bounds independently through overlay manager/runtime plumbing, while preserving existing geometry source behavior. Implemented per-layer bounds ownership path: visible and invisible layers now update bounds independently through overlay manager/runtime plumbing, while preserving existing geometry source behavior.
@@ -35,10 +40,13 @@ Implemented per-layer bounds ownership path: visible and invisible layers now up
Replaced shared all-window bounds application with per-window bound application service and layer-specific runtime calls from visibility/tracker flows. Replaced shared all-window bounds application with per-window bound application service and layer-specific runtime calls from visibility/tracker flows.
Archiving requested by user. Archiving requested by user.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Refactored overlay bounds ownership to per-layer update paths. Tracker geometry remains shared input, but visible/invisible windows apply bounds independently via explicit layer routes. Existing single-layer UX behavior is preserved. Refactored overlay bounds ownership to per-layer update paths. Tracker geometry remains shared input, but visible/invisible windows apply bounds independently via explicit layer routes. Existing single-layer UX behavior is preserved.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -18,14 +18,18 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Create a phased backlog-backed restructuring plan that keeps current service-oriented architecture while reducing cognitive load from oversized modules and tightening module ownership boundaries. Create a phased backlog-backed restructuring plan that keeps current service-oriented architecture while reducing cognitive load from oversized modules and tightening module ownership boundaries.
This initiative should make future feature work easier by splitting high-complexity files, reducing tightly-coupled orchestration, and introducing measurable structural guardrails. This initiative should make future feature work easier by splitting high-complexity files, reducing tightly-coupled orchestration, and introducing measurable structural guardrails.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 A phased decomposition plan is defined in task links and references the following target files: src/main.ts, src/anki-integration.ts, src/core/services/mpv-service.ts, src/renderer/*, src/config/*, and src/core/services/*.
- [ ] #1 A phased decomposition plan is defined in task links and references the following target files: src/main.ts, src/anki-integration.ts, src/core/services/mpv-service.ts, src/renderer/_, src/config/_, and src/core/services/\*.
- [ ] #2 Tasks are assigned with clear owners and include explicit dependencies so execution can proceed in parallel where safe. - [ ] #2 Tasks are assigned with clear owners and include explicit dependencies so execution can proceed in parallel where safe.
- [ ] #3 Changes are constrained to structural refactors first (no behavior changes until foundational splits are in place). - [ ] #3 Changes are constrained to structural refactors first (no behavior changes until foundational splits are in place).
- [ ] #4 Each subtask includes test/verification expectations (manual or automated) and a rollback-safe checkpoint. - [ ] #4 Each subtask includes test/verification expectations (manual or automated) and a rollback-safe checkpoint.
@@ -34,27 +38,35 @@ This initiative should make future feature work easier by splitting high-complex
## Implementation Plan ## Implementation Plan
<!-- SECTION:PLAN:BEGIN --> <!-- SECTION:PLAN:BEGIN -->
## Revised Execution Sequence ## Revised Execution Sequence
### Phase 0 — Prerequisites (outside TASK-27 tree) ### Phase 0 — Prerequisites (outside TASK-27 tree)
- **TASK-7** — Extract main.ts global state into AppState container (required before TASK-27.2) - **TASK-7** — Extract main.ts global state into AppState container (required before TASK-27.2)
- **TASK-9** — Remove trivial wrapper functions from main.ts (depends on TASK-7; recommended before TASK-27.2 but not blocking) - **TASK-9** — Remove trivial wrapper functions from main.ts (depends on TASK-7; recommended before TASK-27.2 but not blocking)
### Phase 1 — Lightweight Inventory ### Phase 1 — Lightweight Inventory
- **TASK-27.1** — Inventory files >400 LOC, document contracts, define smoke test checklist - **TASK-27.1** — Inventory files >400 LOC, document contracts, define smoke test checklist
### Phase 2 — Sequential Split Wave ### Phase 2 — Sequential Split Wave
Order matters to avoid merge conflicts: Order matters to avoid merge conflicts:
1. **TASK-27.3** — anki-integration.ts split (self-contained, doesn't affect main.ts wiring until facade is stable) 1. **TASK-27.3** — anki-integration.ts split (self-contained, doesn't affect main.ts wiring until facade is stable)
2. **TASK-27.2** — main.ts split (after TASK-7 provides AppState container and 27.3 stabilizes the Anki facade) 2. **TASK-27.2** — main.ts split (after TASK-7 provides AppState container and 27.3 stabilizes the Anki facade)
3. **TASK-27.4** — mpv-service.ts split (absorbs TASK-8 scope; blocked until 27.1 is done) 3. **TASK-27.4** — mpv-service.ts split (absorbs TASK-8 scope; blocked until 27.1 is done)
4. **TASK-27.5** — renderer positioning.ts split (downscoped; after 27.2 to avoid import-path conflicts) 4. **TASK-27.5** — renderer positioning.ts split (downscoped; after 27.2 to avoid import-path conflicts)
### Phase 3 — Stabilization ### Phase 3 — Stabilization
- **TASK-27.7** — Finalization and validation cleanup - **TASK-27.7** — Finalization and validation cleanup
## Smoke Test Checklist (applies to all subtasks) ## Smoke Test Checklist (applies to all subtasks)
Every subtask must verify before merging: Every subtask must verify before merging:
- [ ] App starts and connects to MPV - [ ] App starts and connects to MPV
- [ ] Subtitle text appears in overlay - [ ] Subtitle text appears in overlay
- [ ] Card mining creates a note in Anki - [ ] Card mining creates a note in Anki
@@ -68,9 +80,11 @@ Every subtask must verify before merging:
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
## Review Findings (2026-02-13) ## Review Findings (2026-02-13)
### Key changes from original plan: ### Key changes from original plan:
1. **Dropped parallel execution of Phase 2** — TASK-27.2 and 27.5 share import paths; 27.2 and 27.3 share main.ts wiring. Sequential order prevents merge conflicts. 1. **Dropped parallel execution of Phase 2** — TASK-27.2 and 27.5 share import paths; 27.2 and 27.3 share main.ts wiring. Sequential order prevents merge conflicts.
2. **Added TASK-7 as external prerequisite** — main.ts has 30+ module-level `let` declarations. Splitting files without a state container first just scatters mutable state. 2. **Added TASK-7 as external prerequisite** — main.ts has 30+ module-level `let` declarations. Splitting files without a state container first just scatters mutable state.
3. **TASK-8 absorbed into TASK-27.4** — TASK-8 (separate protocol from app logic) and TASK-27.4 (physical file split) overlap significantly. TASK-27.4 now covers both. 3. **TASK-8 absorbed into TASK-27.4** — TASK-8 (separate protocol from app logic) and TASK-27.4 (physical file split) overlap significantly. TASK-27.4 now covers both.
@@ -82,11 +96,15 @@ Every subtask must verify before merging:
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
TASK-27 completed: plan execution sequence completed through all major refactor subtasks. Done status now confirmed for 27.1 (ownership mapping), 27.2 (main.ts split), 27.3 (anki-integration service-domain extraction), 27.4 (mpv-service split), 27.5 (renderer positioning split), and 27.7 (final validation summary, build + tests). Remaining work is now outside TASK-27 scope. TASK-27 completed: plan execution sequence completed through all major refactor subtasks. Done status now confirmed for 27.1 (ownership mapping), 27.2 (main.ts split), 27.3 (anki-integration service-domain extraction), 27.4 (mpv-service split), 27.5 (renderer positioning split), and 27.7 (final validation summary, build + tests). Remaining work is now outside TASK-27 scope.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 Plan task links and ordering are recorded in backlog descriptions. - [ ] #1 Plan task links and ordering are recorded in backlog descriptions.
- [ ] #2 At least 2 independent owners are assigned with explicit labels in subtasks. - [ ] #2 At least 2 independent owners are assigned with explicit labels in subtasks.
<!-- DOD:END --> <!-- DOD:END -->

View File

@@ -25,21 +25,26 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
TASK-27.3 extracted leaf clusters (duplicate-detection 102 LOC, ai-translation 158 LOC, ui-feedback 107 LOC) but the core class remains at 2935 LOC. The heavy decomposition from the original TASK-27.3 plan was never executed. TASK-27.3 extracted leaf clusters (duplicate-detection 102 LOC, ai-translation 158 LOC, ui-feedback 107 LOC) but the core class remains at 2935 LOC. The heavy decomposition from the original TASK-27.3 plan was never executed.
Remaining extractions from the original plan: Remaining extractions from the original plan:
1. **field-grouping** (~900 LOC) — `triggerFieldGroupingForLastAddedCard`, `applyFieldGrouping`, `computeFieldGroupingMergedFields`, `buildFieldGroupingPreview`, `performFieldGroupingMerge`, `handleFieldGroupingAuto`, `handleFieldGroupingManual`, plus ~15 span/parse/normalize helpers 1. **field-grouping** (~900 LOC) — `triggerFieldGroupingForLastAddedCard`, `applyFieldGrouping`, `computeFieldGroupingMergedFields`, `buildFieldGroupingPreview`, `performFieldGroupingMerge`, `handleFieldGroupingAuto`, `handleFieldGroupingManual`, plus ~15 span/parse/normalize helpers
2. **card-creation** (~350 LOC) — `createSentenceCard`, `setCardTypeFields`, `extractFields`, `processSentence`, field resolution helpers 2. **card-creation** (~350 LOC) — `createSentenceCard`, `setCardTypeFields`, `extractFields`, `processSentence`, field resolution helpers
3. **polling/lifecycle** (~250 LOC) — `start`, `stop`, `poll`, `pollOnce`, `processNewCard` 3. **polling/lifecycle** (~250 LOC) — `start`, `stop`, `poll`, `pollOnce`, `processNewCard`
Also consolidate the scattered extraction files into `src/anki-integration/`: Also consolidate the scattered extraction files into `src/anki-integration/`:
- `src/anki-integration-duplicate.ts``src/anki-integration/duplicate.ts` - `src/anki-integration-duplicate.ts``src/anki-integration/duplicate.ts`
- `src/anki-integration-ui-feedback.ts``src/anki-integration/ui-feedback.ts` - `src/anki-integration-ui-feedback.ts``src/anki-integration/ui-feedback.ts`
- `src/anki-integration/ai.ts` (already there) - `src/anki-integration/ai.ts` (already there)
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 anki-integration.ts reduced below 800 LOC (facade + private state wiring only) - [ ] #1 anki-integration.ts reduced below 800 LOC (facade + private state wiring only)
- [ ] #2 Field-grouping cluster (~900 LOC) extracted as its own module under src/anki-integration/ - [ ] #2 Field-grouping cluster (~900 LOC) extracted as its own module under src/anki-integration/
- [ ] #3 Card-creation and polling/lifecycle extracted as separate modules - [ ] #3 Card-creation and polling/lifecycle extracted as separate modules
@@ -51,5 +56,7 @@ Also consolidate the scattered extraction files into `src/anki-integration/`:
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Implemented and stabilized the anki-integration refactor + transport/protocol fixes needed to keep 27.7 moving: fixed MPV protocol sub-end timing behavior, corrected split-buffer test fixtures, added injectable mpv transport socket factory to eliminate readonly Socket monkey-patching, and resolved TypeScript strictness issues in card-creation path (typed notesInfo cast, option signature/field guards/audio stream index). Updated related tests and build outputs accordingly. Validation results: `bun run build` passes and targeted suites pass: `src/core/services/mpv-protocol.test.ts`, `src/core/services/mpv-transport.test.ts`, `src/anki-integration.test.ts` (16/16). Implemented and stabilized the anki-integration refactor + transport/protocol fixes needed to keep 27.7 moving: fixed MPV protocol sub-end timing behavior, corrected split-buffer test fixtures, added injectable mpv transport socket factory to eliminate readonly Socket monkey-patching, and resolved TypeScript strictness issues in card-creation path (typed notesInfo cast, option signature/field guards/audio stream index). Updated related tests and build outputs accordingly. Validation results: `bun run build` passes and targeted suites pass: `src/core/services/mpv-protocol.test.ts`, `src/core/services/mpv-transport.test.ts`, `src/anki-integration.test.ts` (16/16).
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -15,7 +15,9 @@ priority: low
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
The core/services directory has inconsistent naming patterns that create confusion: The core/services directory has inconsistent naming patterns that create confusion:
- Some files use `*Service.ts` suffix (e.g., `mpv-service.ts`, `tokenizer-service.ts`) - Some files use `*Service.ts` suffix (e.g., `mpv-service.ts`, `tokenizer-service.ts`)
- Others use `*RuntimeService.ts` or just descriptive names (e.g., `overlay-visibility-service.ts` exports functions with 'Service' in name) - Others use `*RuntimeService.ts` or just descriptive names (e.g., `overlay-visibility-service.ts` exports functions with 'Service' in name)
- Some functions in files have 'Service' suffix, others don't - Some functions in files have 'Service' suffix, others don't
@@ -23,18 +25,23 @@ The core/services directory has inconsistent naming patterns that create confusi
This inconsistency makes it hard to predict file/function names and creates cognitive overhead. This inconsistency makes it hard to predict file/function names and creates cognitive overhead.
Standardize on: Standardize on:
- File names: `kebab-case.ts` without 'service' suffix (e.g., `mpv.ts`, `tokenizer.ts`) - File names: `kebab-case.ts` without 'service' suffix (e.g., `mpv.ts`, `tokenizer.ts`)
- Function names: descriptive verbs without 'Service' suffix (e.g., `createMpvClient()`, `tokenizeSubtitle()`) - Function names: descriptive verbs without 'Service' suffix (e.g., `createMpvClient()`, `tokenizeSubtitle()`)
- Barrel exports: clean, predictable names - Barrel exports: clean, predictable names
Files needing audit (47 services): Files needing audit (47 services):
- All files in src/core/services/ need review - All files in src/core/services/ need review
Note: This is a large-scale refactor that should be done carefully to avoid breaking changes. Note: This is a large-scale refactor that should be done carefully to avoid breaking changes.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Establish naming convention rules (document in code or docs) - [x] #1 Establish naming convention rules (document in code or docs)
- [x] #2 Audit all service files for naming inconsistencies - [x] #2 Audit all service files for naming inconsistencies
- [x] #3 Rename files to follow convention (kebab-case, no 'service' suffix) - [x] #3 Rename files to follow convention (kebab-case, no 'service' suffix)
@@ -48,6 +55,7 @@ Note: This is a large-scale refactor that should be done carefully to avoid brea
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Starting implementation. Planning and executing a mechanical refactor: file names and exported symbols with Service suffix in `src/core/services`, then cascading import updates across `src/`. Starting implementation. Planning and executing a mechanical refactor: file names and exported symbols with Service suffix in `src/core/services`, then cascading import updates across `src/`.
Implemented naming convention refactor across `src/core/services`: removed `-service` from service file names, renamed Service-suffixed exported symbols to non-Service names, and updated barrel exports in `src/core/services/index.ts`. Implemented naming convention refactor across `src/core/services`: removed `-service` from service file names, renamed Service-suffixed exported symbols to non-Service names, and updated barrel exports in `src/core/services/index.ts`.
@@ -55,10 +63,13 @@ Implemented naming convention refactor across `src/core/services`: removed `-ser
Updated call sites across `src/main/**`, `src/core/services/**` tests, `scripts/**`, `package.json` test paths, and docs references (`docs/development.md`, `docs/architecture.md`, `docs/structure-roadmap.md`). Updated call sites across `src/main/**`, `src/core/services/**` tests, `scripts/**`, `package.json` test paths, and docs references (`docs/development.md`, `docs/architecture.md`, `docs/structure-roadmap.md`).
Validation completed: `pnpm run build` and `pnpm run test:fast` both pass after refactor. Validation completed: `pnpm run build` and `pnpm run test:fast` both pass after refactor.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Normalized `src/core/services` naming by removing `-service` from module filenames, dropping `Service` suffixes from exported service functions, and updating `src/core/services/index.ts` barrel exports to the new names. Updated all import/call sites across `src/main/**`, service tests, scripts, and docs/package test paths to match the new module and symbol names. Verified no behavior regressions with `pnpm run build` and `pnpm run test:fast` (all passing). Normalized `src/core/services` naming by removing `-service` from module filenames, dropping `Service` suffixes from exported service functions, and updating `src/core/services/index.ts` barrel exports to the new names. Updated all import/call sites across `src/main/**`, service tests, scripts, and docs/package test paths to match the new module and symbol names. Verified no behavior regressions with `pnpm run build` and `pnpm run test:fast` (all passing).
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -15,14 +15,17 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
main.ts is still 1481 lines after previous refactoring efforts. While significant progress has been made, there are still opportunities to extract runtime functions into dedicated modules to further reduce its size and improve maintainability. main.ts is still 1481 lines after previous refactoring efforts. While significant progress has been made, there are still opportunities to extract runtime functions into dedicated modules to further reduce its size and improve maintainability.
Current opportunities: Current opportunities:
1. **JLPT dictionary lookup functions** (lines 470-535) - initializeJlptDictionaryLookup, ensureJlptDictionaryLookup, getJlptDictionarySearchPaths 1. **JLPT dictionary lookup functions** (lines 470-535) - initializeJlptDictionaryLookup, ensureJlptDictionaryLookup, getJlptDictionarySearchPaths
2. **Media path utilities** (lines 552-590) - updateCurrentMediaPath, updateCurrentMediaTitle, resolveMediaPathForJimaku 2. **Media path utilities** (lines 552-590) - updateCurrentMediaPath, updateCurrentMediaTitle, resolveMediaPathForJimaku
3. **Overlay visibility helpers** (lines 1273-1360) - updateVisibleOverlayVisibility, updateInvisibleOverlayVisibility, syncInvisibleOverlayMousePassthrough 3. **Overlay visibility helpers** (lines 1273-1360) - updateVisibleOverlayVisibility, updateInvisibleOverlayVisibility, syncInvisibleOverlayMousePassthrough
These functions are largely self-contained and could be moved to: These functions are largely self-contained and could be moved to:
- `src/main/jlpt-runtime.ts` - `src/main/jlpt-runtime.ts`
- `src/main/media-runtime.ts` - `src/main/media-runtime.ts`
- `src/main/overlay-visibility-runtime.ts` - `src/main/overlay-visibility-runtime.ts`
@@ -30,13 +33,16 @@ These functions are largely self-contained and could be moved to:
Goal: Reduce main.ts complexity by extracting focused runtime helpers into dedicated modules Goal: Reduce main.ts complexity by extracting focused runtime helpers into dedicated modules
Benefits: Benefits:
- Faster navigation and comprehension of main.ts - Faster navigation and comprehension of main.ts
- Easier to test extracted modules independently - Easier to test extracted modules independently
- Clearer separation of concerns - Clearer separation of concerns
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Extract JLPT dictionary lookup functions to dedicated module - [x] #1 Extract JLPT dictionary lookup functions to dedicated module
- [x] #2 Extract media path utilities to dedicated module - [x] #2 Extract media path utilities to dedicated module
- [x] #3 Extract overlay visibility helpers to dedicated module - [x] #3 Extract overlay visibility helpers to dedicated module
@@ -49,7 +55,9 @@ Benefits:
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Refactor complete for targeted runtime extraction: JLPT lookup, media utilities, and overlay visibility helpers were moved into dedicated main-runtime modules and wired from main.ts. Existing behavior preserved and full typecheck + test suite passed. Refactor complete for targeted runtime extraction: JLPT lookup, media utilities, and overlay visibility helpers were moved into dedicated main-runtime modules and wired from main.ts. Existing behavior preserved and full typecheck + test suite passed.
Task intent updated to prioritize readability over strict line-count target. Task intent updated to prioritize readability over strict line-count target.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -21,17 +21,22 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
MpvIpcClient (761 lines) in src/core/services/mpv-service.ts has a 22-property `MpvIpcClientDeps` interface that reaches back into main.ts state for application-level concerns (overlay visibility, subtitle timing, media path updates, OSD display). MpvIpcClient (761 lines) in src/core/services/mpv-service.ts has a 22-property `MpvIpcClientDeps` interface that reaches back into main.ts state for application-level concerns (overlay visibility, subtitle timing, media path updates, OSD display).
The class mixes two responsibilities: The class mixes two responsibilities:
1. **IPC Protocol**: Socket connection, JSON message framing, reconnection, property observation 1. **IPC Protocol**: Socket connection, JSON message framing, reconnection, property observation
2. **Application Integration**: Subtitle text broadcasting, overlay visibility sync, timing tracking 2. **Application Integration**: Subtitle text broadcasting, overlay visibility sync, timing tracking
Separating these would let the protocol layer be simpler and testable, while application-level reactions to mpv events could be handled by listeners/callbacks registered externally. Separating these would let the protocol layer be simpler and testable, while application-level reactions to mpv events could be handled by listeners/callbacks registered externally.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 MpvIpcClient deps interface reduced to protocol-level concerns only - [ ] #1 MpvIpcClient deps interface reduced to protocol-level concerns only
- [ ] #2 Application-level reactions (subtitle broadcast, overlay sync, timing) handled via event emitter or external listeners - [ ] #2 Application-level reactions (subtitle broadcast, overlay sync, timing) handled via event emitter or external listeners
- [ ] #3 MpvIpcClient is testable without mocking 22 callbacks - [ ] #3 MpvIpcClient is testable without mocking 22 callbacks
@@ -41,5 +46,7 @@ Separating these would let the protocol layer be simpler and testable, while app
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Superseded by TASK-27.4 which absorbed this task's full scope (protocol/application separation, deps interface reduction from 22 properties to protocol-level concerns, event-based app reactions). All acceptance criteria met by TASK-27.4. Superseded by TASK-27.4 which absorbed this task's full scope (protocol/application separation, deps interface reduction from 22 properties to protocol-level concerns, event-based app reactions). All acceptance criteria met by TASK-27.4.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -20,6 +20,7 @@ priority: low
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
main.ts contains many trivial single-line wrapper functions that add indirection without value: main.ts contains many trivial single-line wrapper functions that add indirection without value:
```typescript ```typescript
@@ -37,10 +38,13 @@ function ensureOverlayWindowLevel(window: BrowserWindow): void {
Similarly, config accessor wrappers like `getJimakuLanguagePreference()`, `getJimakuMaxEntryResults()`, `resolveJimakuApiKey()` are pure boilerplate. Similarly, config accessor wrappers like `getJimakuLanguagePreference()`, `getJimakuMaxEntryResults()`, `resolveJimakuApiKey()` are pure boilerplate.
After TASK-7 (AppState container), many of these can be eliminated by having services access the state container directly, or by using the service functions directly at call sites without local wrappers. After TASK-7 (AppState container), many of these can be eliminated by having services access the state container directly, or by using the service functions directly at call sites without local wrappers.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Trivial pass-through wrappers eliminated (call service/manager directly) - [ ] #1 Trivial pass-through wrappers eliminated (call service/manager directly)
- [ ] #2 Config accessor wrappers replaced with direct calls or a config accessor helper - [ ] #2 Config accessor wrappers replaced with direct calls or a config accessor helper
- [ ] #3 main.ts line count reduced - [ ] #3 main.ts line count reduced
@@ -50,11 +54,15 @@ After TASK-7 (AppState container), many of these can be eliminated by having ser
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Priority changed from medium to low: this work is largely subsumed by TASK-27.2 (split main.ts). When main.ts is decomposed into composition-root modules, trivial wrappers will naturally be eliminated or inlined. Recommend folding remaining wrapper cleanup into TASK-27.2 rather than tracking separately. Keep this ticket as a checklist reference but don't execute independently. Priority changed from medium to low: this work is largely subsumed by TASK-27.2 (split main.ts). When main.ts is decomposed into composition-root modules, trivial wrappers will naturally be eliminated or inlined. Recommend folding remaining wrapper cleanup into TASK-27.2 rather than tracking separately. Keep this ticket as a checklist reference but don't execute independently.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Subsumed by TASK-27.2 (main.ts split). Trivial wrappers were eliminated or inlined as composition-root modules were extracted. main.ts reduced from ~2000+ LOC to 1384 with state routed through appState container. Standalone wrapper removal pass no longer needed. Subsumed by TASK-27.2 (main.ts split). Trivial wrappers were eliminated or inlined as composition-root modules were extracted. main.ts reduced from ~2000+ LOC to 1384 with state routed through appState container. Standalone wrapper removal pass no longer needed.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -1,11 +1,11 @@
project_name: "SubMiner" project_name: 'SubMiner'
default_status: "To Do" default_status: 'To Do'
statuses: ["To Do", "In Progress", "Done"] statuses: ['To Do', 'In Progress', 'Done']
labels: [] labels: []
milestones: [] milestones: []
date_format: yyyy-mm-dd date_format: yyyy-mm-dd
max_column_width: 20 max_column_width: 20
default_editor: "nvim" default_editor: 'nvim'
auto_open_browser: false auto_open_browser: false
default_port: 6420 default_port: 6420
remote_operations: true remote_operations: true
@@ -13,4 +13,4 @@ auto_commit: false
bypass_git_hooks: false bypass_git_hooks: false
check_active_branches: true check_active_branches: true
active_branch_days: 30 active_branch_days: 30
task_prefix: "task" task_prefix: 'task'

View File

@@ -1,6 +1,6 @@
--- ---
id: m-0 id: m-0
title: "Release v0.1.0" title: 'Release v0.1.0'
--- ---
## Description ## Description

View File

@@ -15,11 +15,15 @@ ordinal: 2000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Execute the SubMiner refactoring initiative documented in plan.md to reduce thin abstractions, consolidate service boundaries, fix known quality issues, and increase test coverage while preserving current behavior. Execute the SubMiner refactoring initiative documented in plan.md to reduce thin abstractions, consolidate service boundaries, fix known quality issues, and increase test coverage while preserving current behavior.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Phase-based execution tasks are created and linked under this initiative. - [x] #1 Phase-based execution tasks are created and linked under this initiative.
- [x] #2 Each phase task includes clear, testable outcomes aligned with plan.md. - [x] #2 Each phase task includes clear, testable outcomes aligned with plan.md.
- [x] #3 Implementation proceeds with build/test verification checkpoints after each completed phase. - [x] #3 Implementation proceeds with build/test verification checkpoints after each completed phase.
@@ -29,6 +33,7 @@ Execute the SubMiner refactoring initiative documented in plan.md to reduce thin
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Created initiative subtasks TASK-1.1 through TASK-1.6 with phase-aligned acceptance criteria and sequential dependencies. Created initiative subtasks TASK-1.1 through TASK-1.6 with phase-aligned acceptance criteria and sequential dependencies.
Completed TASK-1.1 (Phase 1 thin-wrapper removal) with green build/core tests. Completed TASK-1.1 (Phase 1 thin-wrapper removal) with green build/core tests.
@@ -40,10 +45,13 @@ Completed TASK-1.5 (critical behavior tests) with expanded tokenizer/mpv/subsync
Completed TASK-1.6 with documented no-go decision for optional domain-directory reorganization (kept current structure; tests remain green). Completed TASK-1.6 with documented no-go decision for optional domain-directory reorganization (kept current structure; tests remain green).
TASK-1.4 remains the only open phase, blocked on interactive desktop smoke checks that cannot be fully validated in this headless environment. TASK-1.4 remains the only open phase, blocked on interactive desktop smoke checks that cannot be fully validated in this headless environment.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Completed the plan.md refactor initiative across Phases 1-5 and optional Phase 6 decisioning: removed thin wrappers, consolidated DI adapters and related services, fixed targeted runtime correctness issues, expanded critical behavior test coverage, and kept build/core tests green throughout. Final runtime smoke checks (start/toggle/trigger-field-grouping/stop) passed in this headless environment, with known limitation that visual overlay rendering itself was not directly inspectable. Completed the plan.md refactor initiative across Phases 1-5 and optional Phase 6 decisioning: removed thin wrappers, consolidated DI adapters and related services, fixed targeted runtime correctness issues, expanded critical behavior test coverage, and kept build/core tests green throughout. Final runtime smoke checks (start/toggle/trigger-field-grouping/stop) passed in this headless environment, with known limitation that visual overlay rendering itself was not directly inspectable.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -19,11 +19,15 @@ ordinal: 12000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Inline trivial wrapper services into their call sites and delete redundant service/test files listed in Phase 1 of plan.md. Inline trivial wrapper services into their call sites and delete redundant service/test files listed in Phase 1 of plan.md.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Wrapper logic from the Phase 1 file list is inlined at call sites without behavior changes. - [x] #1 Wrapper logic from the Phase 1 file list is inlined at call sites without behavior changes.
- [x] #2 Phase 1 wrapper service files and corresponding trivial tests are removed from the codebase. - [x] #2 Phase 1 wrapper service files and corresponding trivial tests are removed from the codebase.
- [x] #3 `src/core/services/index.ts` exports are updated to remove deleted modules. - [x] #3 `src/core/services/index.ts` exports are updated to remove deleted modules.
@@ -33,6 +37,7 @@ Inline trivial wrapper services into their call sites and delete redundant servi
## Implementation Plan ## Implementation Plan
<!-- SECTION:PLAN:BEGIN --> <!-- SECTION:PLAN:BEGIN -->
1. Locate all Phase 1 wrapper service call sites and classify direct-inline substitutions vs orchestration-flow inlines. 1. Locate all Phase 1 wrapper service call sites and classify direct-inline substitutions vs orchestration-flow inlines.
2. Remove the lowest-risk wrappers first (`config-warning-runtime-service`, `app-logging-runtime-service`, `runtime-options-manager-runtime-service`, `overlay-modal-restore-service`, `overlay-send-service`) and update imports/exports. 2. Remove the lowest-risk wrappers first (`config-warning-runtime-service`, `app-logging-runtime-service`, `runtime-options-manager-runtime-service`, `overlay-modal-restore-service`, `overlay-send-service`) and update imports/exports.
3. Continue with startup and shutdown wrappers (`startup-resource-runtime-service`, `config-generation-runtime-service`, `app-shutdown-runtime-service`, `shortcut-ui-deps-runtime-service`) by inlining behavior into `main.ts` or direct callers. 3. Continue with startup and shutdown wrappers (`startup-resource-runtime-service`, `config-generation-runtime-service`, `app-shutdown-runtime-service`, `shortcut-ui-deps-runtime-service`) by inlining behavior into `main.ts` or direct callers.
@@ -43,6 +48,7 @@ Inline trivial wrapper services into their call sites and delete redundant servi
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Inlined wrapper behaviors into direct call sites in `main.ts` and `overlay-bridge-runtime-service.ts` for config warning/app logging, runtime options manager construction, generate-config bootstrap path, startup resource initialization, app shutdown sequence, overlay modal restore handling, overlay send behavior, and overlay shortcut local fallback invocation. Inlined wrapper behaviors into direct call sites in `main.ts` and `overlay-bridge-runtime-service.ts` for config warning/app logging, runtime options manager construction, generate-config bootstrap path, startup resource initialization, app shutdown sequence, overlay modal restore handling, overlay send behavior, and overlay shortcut local fallback invocation.
Deleted 16 Phase 1 files (9 wrapper services + 7 wrapper tests) and removed corresponding barrel exports from `src/core/services/index.ts`. Deleted 16 Phase 1 files (9 wrapper services + 7 wrapper tests) and removed corresponding barrel exports from `src/core/services/index.ts`.
@@ -50,4 +56,5 @@ Deleted 16 Phase 1 files (9 wrapper services + 7 wrapper tests) and removed corr
Updated `package.json` `test:core` list to remove deleted test entries so the script tracks current sources accurately. Updated `package.json` `test:core` list to remove deleted test entries so the script tracks current sources accurately.
Verification: `pnpm run build && pnpm run test:core` passes after refactor. Verification: `pnpm run build && pnpm run test:core` passes after refactor.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -22,11 +22,15 @@ ordinal: 10000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Absorb dependency adapter runtime services into core service modules and remove adapter files/tests while preserving runtime behavior. Absorb dependency adapter runtime services into core service modules and remove adapter files/tests while preserving runtime behavior.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 CLI, IPC, tokenizer, and app lifecycle adapter logic is merged into their target service modules. - [x] #1 CLI, IPC, tokenizer, and app lifecycle adapter logic is merged into their target service modules.
- [x] #2 Adapter service and adapter test files listed in Phase 2 are removed. - [x] #2 Adapter service and adapter test files listed in Phase 2 are removed.
- [x] #3 Callers pass dependency shapes expected by updated services without redundant mapping layers. - [x] #3 Callers pass dependency shapes expected by updated services without redundant mapping layers.
@@ -36,6 +40,7 @@ Absorb dependency adapter runtime services into core service modules and remove
## Implementation Plan ## Implementation Plan
<!-- SECTION:PLAN:BEGIN --> <!-- SECTION:PLAN:BEGIN -->
1. Audit `cli-command-deps-runtime-service.ts`, `ipc-deps-runtime-service.ts`, `tokenizer-deps-runtime-service.ts`, and `app-lifecycle-deps-runtime-service.ts` usage sites in `main.ts` and corresponding services. 1. Audit `cli-command-deps-runtime-service.ts`, `ipc-deps-runtime-service.ts`, `tokenizer-deps-runtime-service.ts`, and `app-lifecycle-deps-runtime-service.ts` usage sites in `main.ts` and corresponding services.
2. For each adapter, move null-guarding and shape-normalization logic into its target service (`cli-command-service.ts`, `ipc-service.ts`, `tokenizer-service.ts`, `app-lifecycle-service.ts`) and simplify caller dependency objects. 2. For each adapter, move null-guarding and shape-normalization logic into its target service (`cli-command-service.ts`, `ipc-service.ts`, `tokenizer-service.ts`, `app-lifecycle-service.ts`) and simplify caller dependency objects.
3. Remove adapter service files/tests and update `src/core/services/index.ts` exports/import sites. 3. Remove adapter service files/tests and update `src/core/services/index.ts` exports/import sites.
@@ -46,6 +51,7 @@ Absorb dependency adapter runtime services into core service modules and remove
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Merged adapter-constructor logic into target services: `createCliCommandDepsRuntimeService` moved into `cli-command-service.ts`, `createIpcDepsRuntimeService` moved into `ipc-service.ts`, `createTokenizerDepsRuntimeService` moved into `tokenizer-service.ts`, and `createAppLifecycleDepsRuntimeService` moved into `app-lifecycle-service.ts`. Merged adapter-constructor logic into target services: `createCliCommandDepsRuntimeService` moved into `cli-command-service.ts`, `createIpcDepsRuntimeService` moved into `ipc-service.ts`, `createTokenizerDepsRuntimeService` moved into `tokenizer-service.ts`, and `createAppLifecycleDepsRuntimeService` moved into `app-lifecycle-service.ts`.
Deleted adapter service files and tests for cli-command deps, ipc deps, tokenizer deps, and app lifecycle deps. Deleted adapter service files and tests for cli-command deps, ipc deps, tokenizer deps, and app lifecycle deps.
@@ -53,4 +59,5 @@ Deleted adapter service files and tests for cli-command deps, ipc deps, tokenize
Updated `src/core/services/index.ts` exports and `package.json` `test:core` entries to remove deleted adapter test modules. Updated `src/core/services/index.ts` exports and `package.json` `test:core` entries to remove deleted adapter test modules.
Verification: `pnpm run build && pnpm run test:core` passes after consolidation. Verification: `pnpm run build && pnpm run test:core` passes after consolidation.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -23,11 +23,15 @@ ordinal: 6000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Merge split modules for overlay visibility, broadcast, shortcuts, numeric shortcuts, and startup orchestration into cohesive service files. Merge split modules for overlay visibility, broadcast, shortcuts, numeric shortcuts, and startup orchestration into cohesive service files.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Overlay visibility/runtime split is consolidated into a single service module. - [x] #1 Overlay visibility/runtime split is consolidated into a single service module.
- [x] #2 Overlay broadcast functions are merged with overlay manager responsibilities. - [x] #2 Overlay broadcast functions are merged with overlay manager responsibilities.
- [x] #3 Shortcut and numeric shortcut runtime/lifecycle splits are consolidated as described in plan.md. - [x] #3 Shortcut and numeric shortcut runtime/lifecycle splits are consolidated as described in plan.md.
@@ -38,6 +42,7 @@ Merge split modules for overlay visibility, broadcast, shortcuts, numeric shortc
## Implementation Plan ## Implementation Plan
<!-- SECTION:PLAN:BEGIN --> <!-- SECTION:PLAN:BEGIN -->
1. Merge `overlay-visibility-runtime-service.ts` exports into `overlay-visibility-service.ts` and update imports/exports. 1. Merge `overlay-visibility-runtime-service.ts` exports into `overlay-visibility-service.ts` and update imports/exports.
2. Merge overlay broadcast responsibilities from `overlay-broadcast-runtime-service.ts` into `overlay-manager-service.ts` while preserving current APIs used by `main.ts`. 2. Merge overlay broadcast responsibilities from `overlay-broadcast-runtime-service.ts` into `overlay-manager-service.ts` while preserving current APIs used by `main.ts`.
3. Consolidate shortcut modules by absorbing lifecycle utilities into `overlay-shortcut-service.ts` and fallback-runner logic into `overlay-shortcut-runtime-service.ts` (or successor handler module), then remove obsolete files. 3. Consolidate shortcut modules by absorbing lifecycle utilities into `overlay-shortcut-service.ts` and fallback-runner logic into `overlay-shortcut-runtime-service.ts` (or successor handler module), then remove obsolete files.
@@ -48,6 +53,7 @@ Merge split modules for overlay visibility, broadcast, shortcuts, numeric shortc
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Merged overlay visibility runtime API into `overlay-visibility-service.ts` and removed `overlay-visibility-runtime-service.ts`. Merged overlay visibility runtime API into `overlay-visibility-service.ts` and removed `overlay-visibility-runtime-service.ts`.
Merged overlay broadcast behavior into `overlay-manager-service.ts` (including manager-level broadcasting) and removed `overlay-broadcast-runtime-service.ts` + test, with equivalent coverage moved into `overlay-manager-service.test.ts`. Merged overlay broadcast behavior into `overlay-manager-service.ts` (including manager-level broadcasting) and removed `overlay-broadcast-runtime-service.ts` + test, with equivalent coverage moved into `overlay-manager-service.test.ts`.
@@ -59,4 +65,5 @@ Merged numeric shortcut runtime/session split into `numeric-shortcut-service.ts`
Merged startup bootstrap + app-ready orchestration into `startup-service.ts`; removed `startup-bootstrap-runtime-service.ts` and `app-ready-runtime-service.ts` with tests updated to new module path. Merged startup bootstrap + app-ready orchestration into `startup-service.ts`; removed `startup-bootstrap-runtime-service.ts` and `app-ready-runtime-service.ts` with tests updated to new module path.
Verification: `pnpm run build && pnpm run test:core` passes after consolidation. Verification: `pnpm run build && pnpm run test:core` passes after consolidation.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -21,11 +21,15 @@ ordinal: 3000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Address identified correctness and code-quality issues from plan.md, including race conditions, unsafe typing, callback rejection handling, and runtime naming cleanup. Address identified correctness and code-quality issues from plan.md, including race conditions, unsafe typing, callback rejection handling, and runtime naming cleanup.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Debug `console.log`/`console.warn` usage in overlay visibility logic is removed or replaced with structured logging where needed. - [x] #1 Debug `console.log`/`console.warn` usage in overlay visibility logic is removed or replaced with structured logging where needed.
- [x] #2 Tokenizer type mismatch is fixed without unsafe `as never` casting. - [x] #2 Tokenizer type mismatch is fixed without unsafe `as never` casting.
- [x] #3 Field grouping resolver handling is made concurrency-safe against overlapping requests. - [x] #3 Field grouping resolver handling is made concurrency-safe against overlapping requests.
@@ -37,6 +41,7 @@ Address identified correctness and code-quality issues from plan.md, including r
## Implementation Plan ## Implementation Plan
<!-- SECTION:PLAN:BEGIN --> <!-- SECTION:PLAN:BEGIN -->
1. Remove or replace debug `console.log`/`console.warn` usage in `overlay-visibility-service.ts` while preserving useful operational logging semantics. 1. Remove or replace debug `console.log`/`console.warn` usage in `overlay-visibility-service.ts` while preserving useful operational logging semantics.
2. Confirm and fix unsafe tokenizer casting paths (already partially addressed during Phase 2) and ensure no remaining `as never` escape hatches in tokenizer dependency flows. 2. Confirm and fix unsafe tokenizer casting paths (already partially addressed during Phase 2) and ensure no remaining `as never` escape hatches in tokenizer dependency flows.
3. Make field grouping resolver handling in `main.ts` concurrency-safe by adding request sequencing and stale-resolution guards. 3. Make field grouping resolver handling in `main.ts` concurrency-safe by adding request sequencing and stale-resolution guards.
@@ -47,6 +52,7 @@ Address identified correctness and code-quality issues from plan.md, including r
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Removed debug overlay-visibility `console.log`/`console.warn` statements from `overlay-visibility-service.ts`. Removed debug overlay-visibility `console.log`/`console.warn` statements from `overlay-visibility-service.ts`.
Eliminated unsafe tokenizer cast path during prior consolidation (`createTokenizerDepsRuntimeService` now uses typed `Token[]` and `mergeTokens(rawTokens)` without `as never`). Eliminated unsafe tokenizer cast path during prior consolidation (`createTokenizerDepsRuntimeService` now uses typed `Token[]` and `mergeTokens(rawTokens)` without `as never`).
@@ -80,10 +86,13 @@ Automated interactive-smoke surrogate 2 (outside sandbox): started app, sent `--
Observed expected reconnect behavior when MPV socket was absent (`ENOENT /tmp/subminer-socket`), with no regressions in startup/bootstrap flow. Observed expected reconnect behavior when MPV socket was absent (`ENOENT /tmp/subminer-socket`), with no regressions in startup/bootstrap flow.
Note: this environment is headless, so visual overlay rendering cannot be directly confirmed; command-path and process-lifecycle smoke checks passed. Note: this environment is headless, so visual overlay rendering cannot be directly confirmed; command-path and process-lifecycle smoke checks passed.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Completed Phase 4 by removing debug logging noise, fixing unsafe typing and concurrency risks, adding async rejection handling, completing naming cleanup, and validating startup/command-path behavior through repeated build/test and live Electron smoke runs. Completed Phase 4 by removing debug logging noise, fixing unsafe typing and concurrency risks, adding async rejection handling, completing naming cleanup, and validating startup/command-path behavior through repeated build/test and live Electron smoke runs.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -22,11 +22,15 @@ ordinal: 5000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add meaningful behavior tests for high-risk services called out in plan.md: mpv, subsync, tokenizer, and expanded CLI command coverage. Add meaningful behavior tests for high-risk services called out in plan.md: mpv, subsync, tokenizer, and expanded CLI command coverage.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 `mpv` service has focused tests for protocol parsing, event dispatch, request/response matching, reconnection, and subtitle extraction behavior. - [x] #1 `mpv` service has focused tests for protocol parsing, event dispatch, request/response matching, reconnection, and subtitle extraction behavior.
- [x] #2 `subsync` service has focused tests for engine path resolution, command construction, timeout/error handling, and result parsing. - [x] #2 `subsync` service has focused tests for engine path resolution, command construction, timeout/error handling, and result parsing.
- [x] #3 `tokenizer` service has focused tests for parser readiness, token extraction, fallback behavior, and edge-case inputs. - [x] #3 `tokenizer` service has focused tests for parser readiness, token extraction, fallback behavior, and edge-case inputs.
@@ -37,6 +41,7 @@ Add meaningful behavior tests for high-risk services called out in plan.md: mpv,
## Implementation Plan ## Implementation Plan
<!-- SECTION:PLAN:BEGIN --> <!-- SECTION:PLAN:BEGIN -->
1. Add focused tests for `tokenizer-service.ts` behavior (normalization, Yomitan-unavailable fallback, mecab fallback success/error paths, empty input handling). 1. Add focused tests for `tokenizer-service.ts` behavior (normalization, Yomitan-unavailable fallback, mecab fallback success/error paths, empty input handling).
2. Add focused tests for `subsync-service.ts` command/engine selection and failure handling using mocked command utilities where feasible. 2. Add focused tests for `subsync-service.ts` command/engine selection and failure handling using mocked command utilities where feasible.
3. Add focused tests for `mpv-service.ts` protocol handling (line parsing, request-response routing, property-change dispatch) with lightweight socket stubs. 3. Add focused tests for `mpv-service.ts` protocol handling (line parsing, request-response routing, property-change dispatch) with lightweight socket stubs.
@@ -47,6 +52,7 @@ Add meaningful behavior tests for high-risk services called out in plan.md: mpv,
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Added new tokenizer behavior tests in `src/core/services/tokenizer-service.test.ts` covering empty normalized input, newline normalization, mecab fallback success, and mecab error fallback-to-null. Added new tokenizer behavior tests in `src/core/services/tokenizer-service.test.ts` covering empty normalized input, newline normalization, mecab fallback success, and mecab error fallback-to-null.
Added new mpv protocol tests in `src/core/services/mpv-service.test.ts` covering JSON line-buffer parsing, property-change subtitle dispatch behavior, and request/response resolution by `request_id`. Added new mpv protocol tests in `src/core/services/mpv-service.test.ts` covering JSON line-buffer parsing, property-change subtitle dispatch behavior, and request/response resolution by `request_id`.
@@ -72,4 +78,5 @@ Added subsync command-construction tests using executable stubs for both engines
Expanded CLI dispatch tests with broad branch coverage for visibility/settings/copy/multi-copy/mining/open-runtime-options/stop/help/second-instance behaviors and async error propagation. Expanded CLI dispatch tests with broad branch coverage for visibility/settings/copy/multi-copy/mining/open-runtime-options/stop/help/second-instance behaviors and async error propagation.
Verification: `pnpm run test:core` passes with 18 green tests including newly added `dist/subsync/utils.test.js`. Verification: `pnpm run test:core` passes with 18 green tests including newly added `dist/subsync/utils.test.js`.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -17,11 +17,15 @@ ordinal: 4000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
If service flattening remains hard to navigate after Phases 1-5, optionally move modules into domain-based folders and update imports. If service flattening remains hard to navigate after Phases 1-5, optionally move modules into domain-based folders and update imports.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 A clear go/no-go decision for domain restructuring is documented based on post-phase-5 codebase state. - [x] #1 A clear go/no-go decision for domain restructuring is documented based on post-phase-5 codebase state.
- [ ] #2 If executed, service modules are reorganized into domain folders with no import or runtime breakage. - [ ] #2 If executed, service modules are reorganized into domain folders with no import or runtime breakage.
- [x] #3 Build and core test commands pass after any directory reorganization. - [x] #3 Build and core test commands pass after any directory reorganization.
@@ -30,6 +34,7 @@ If service flattening remains hard to navigate after Phases 1-5, optionally move
## Implementation Plan ## Implementation Plan
<!-- SECTION:PLAN:BEGIN --> <!-- SECTION:PLAN:BEGIN -->
1. Assess post-phase-5 directory complexity and determine whether domain reorganization is still justified. 1. Assess post-phase-5 directory complexity and determine whether domain reorganization is still justified.
2. If complexity remains acceptable, record a no-go decision and keep current structure stable. 2. If complexity remains acceptable, record a no-go decision and keep current structure stable.
3. If complexity is still problematic, perform import-safe domain reorganization and re-run build/tests. 3. If complexity is still problematic, perform import-safe domain reorganization and re-run build/tests.
@@ -38,9 +43,11 @@ If service flattening remains hard to navigate after Phases 1-5, optionally move
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Decision: no-go on Phase 6 directory reorganization for now. After Phases 1-5, service/module consolidation and test expansion have improved maintainability without introducing a high-risk import churn. Decision: no-go on Phase 6 directory reorganization for now. After Phases 1-5, service/module consolidation and test expansion have improved maintainability without introducing a high-risk import churn.
Rationale: preserving path stability now reduces regression risk while Phase 4 smoke validation remains open and large refactor commits are still stabilizing. Rationale: preserving path stability now reduces regression risk while Phase 4 smoke validation remains open and large refactor commits are still stabilizing.
Verification baseline remains green (`pnpm run test:core`) with current structure. Verification baseline remains green (`pnpm run test:core`) with current structure.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -0,0 +1,51 @@
---
id: TASK-13
title: Fix macOS native window bounds for overlay binding
status: Done
assignee:
- codex
created_date: '2026-02-11 15:45'
updated_date: '2026-02-11 16:36'
labels:
- bug
- macos
- overlay
dependencies: []
references:
- src/window-trackers/macos-tracker.ts
- scripts/get-mpv-window-macos.swift
priority: high
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Overlay windows on macOS are not properly aligned to the mpv window after switching from AppleScript window discovery to native Swift/CoreGraphics bounds retrieval.
Implement a robust native bounds strategy that prefers Accessibility window geometry (matching app-window coordinates used previously) and falls back to filtered CoreGraphics windows when Accessibility data is unavailable.
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [x] #1 Overlay bounds track the active mpv window with correct position and size on macOS.
- [x] #2 Helper avoids selecting off-screen/non-primary mpv-related windows.
- [x] #3 Build succeeds with the updated macOS helper.
<!-- AC:END -->
## Implementation Notes
<!-- SECTION:NOTES:BEGIN -->
Follow-up in progress after packaged app runtime showed fullscreen fallback behavior:
- Added packaged-app helper path resolution in tracker (`process.resourcesPath/scripts/get-mpv-window-macos`).
- Added `.asar` helper materialization to temp path so child process execution is possible if candidate path resolves inside asar.
- Added throttled tracker logging for helper execution failures to expose runtime errors without log spam.
- Updated Electron builder `extraResources` to ship `dist/scripts/get-mpv-window-macos` outside asar at `resources/scripts/get-mpv-window-macos`.
- Added macOS-only invisible subtitle vertical nudge (`+5px`) in renderer layout to align interactive subtitles with mpv glyph baseline after bounds fix.
- Increased macOS-only invisible subtitle line-height for multi-line text to improve separation as line count grows.
<!-- SECTION:NOTES:END -->

View File

@@ -17,11 +17,15 @@ ordinal: 51000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
When SubMiner is already running in texthooker-only mode, a subsequent `--start` command from a second instance is currently ignored. This can leave users without an initialized overlay runtime even though startup commands were issued. Adjust CLI command handling so `--start` on second-instance initializes overlay runtime when it is not yet initialized, while preserving current ignore behavior when overlay runtime is already active. When SubMiner is already running in texthooker-only mode, a subsequent `--start` command from a second instance is currently ignored. This can leave users without an initialized overlay runtime even though startup commands were issued. Adjust CLI command handling so `--start` on second-instance initializes overlay runtime when it is not yet initialized, while preserving current ignore behavior when overlay runtime is already active.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Second-instance `--start` initializes overlay runtime when current instance has deferred/not-initialized overlay runtime. - [x] #1 Second-instance `--start` initializes overlay runtime when current instance has deferred/not-initialized overlay runtime.
- [x] #2 Second-instance `--start` remains ignored (existing behavior) when overlay runtime is already initialized. - [x] #2 Second-instance `--start` remains ignored (existing behavior) when overlay runtime is already initialized.
- [x] #3 CLI command service tests cover both behaviors and pass. - [x] #3 CLI command service tests cover both behaviors and pass.
@@ -30,23 +34,28 @@ When SubMiner is already running in texthooker-only mode, a subsequent `--start`
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Patched CLI second-instance `--start` handling in `src/core/services/cli-command-service.ts` to initialize overlay runtime when deferred. Patched CLI second-instance `--start` handling in `src/core/services/cli-command-service.ts` to initialize overlay runtime when deferred.
Added regression test for deferred-runtime start path and updated initialized-runtime second-instance tests in `src/core/services/cli-command-service.test.ts`. Added regression test for deferred-runtime start path and updated initialized-runtime second-instance tests in `src/core/services/cli-command-service.test.ts`.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Fixed overlay startup regression path where a second-instance `--start` could be ignored even when the primary instance was running in texthooker-only/deferred overlay mode. Fixed overlay startup regression path where a second-instance `--start` could be ignored even when the primary instance was running in texthooker-only/deferred overlay mode.
Changes: Changes:
- Updated `handleCliCommandService` logic so `ignoreStart` applies only when source is second-instance, `--start` is present, and overlay runtime is already initialized. - Updated `handleCliCommandService` logic so `ignoreStart` applies only when source is second-instance, `--start` is present, and overlay runtime is already initialized.
- Added explicit overlay-runtime initialization path for second-instance `--start` when runtime is not initialized. - Added explicit overlay-runtime initialization path for second-instance `--start` when runtime is not initialized.
- Kept existing behavior for already-initialized runtime (still logs and ignores redundant `--start`). - Kept existing behavior for already-initialized runtime (still logs and ignores redundant `--start`).
- Added and updated tests in `cli-command-service.test.ts` to validate both deferred and initialized second-instance startup behaviors. - Added and updated tests in `cli-command-service.test.ts` to validate both deferred and initialized second-instance startup behaviors.
Validation: Validation:
- `pnpm run build` succeeded. - `pnpm run build` succeeded.
- `node dist/core/services/cli-command-service.test.js` passed (11/11). - `node dist/core/services/cli-command-service.test.js` passed (11/11).
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -17,11 +17,15 @@ ordinal: 50000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
The `subminer` launcher starts SubMiner with `--start` but can leave the visible overlay hidden when runtime config defers auto-show (`auto_start_overlay=false`). Update launcher command args to explicitly request visible overlay at startup so script-mode behavior matches user expectations. The `subminer` launcher starts SubMiner with `--start` but can leave the visible overlay hidden when runtime config defers auto-show (`auto_start_overlay=false`). Update launcher command args to explicitly request visible overlay at startup so script-mode behavior matches user expectations.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Running `subminer <video>` starts SubMiner with startup args that include visible-overlay show intent. - [x] #1 Running `subminer <video>` starts SubMiner with startup args that include visible-overlay show intent.
- [x] #2 Launcher startup remains compatible with texthooker-enabled startup and backend/socket args. - [x] #2 Launcher startup remains compatible with texthooker-enabled startup and backend/socket args.
- [x] #3 No regressions in existing startup argument construction for texthooker-only mode. - [x] #3 No regressions in existing startup argument construction for texthooker-only mode.
@@ -30,15 +34,18 @@ The `subminer` launcher starts SubMiner with `--start` but can leave the visible
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Updated `subminer` launcher startup args in `startOverlay()` to include `--show-visible-overlay` alongside `--start`. Updated `subminer` launcher startup args in `startOverlay()` to include `--show-visible-overlay` alongside `--start`.
This makes script-mode startup idempotently request visible overlay presentation instead of depending on runtime config auto-start visibility flags, while preserving existing backend/socket and optional texthooker args. This makes script-mode startup idempotently request visible overlay presentation instead of depending on runtime config auto-start visibility flags, while preserving existing backend/socket and optional texthooker args.
Scope: Scope:
- `subminer` script only. - `subminer` script only.
- No changes to AppImage internal CLI parsing or runtime services. - No changes to AppImage internal CLI parsing or runtime services.
Validation: Validation:
- Verified argument block in `startOverlay()` now includes `--show-visible-overlay` and preserves existing flags. - Verified argument block in `startOverlay()` now includes `--show-visible-overlay` and preserves existing flags.
- Confirmed texthooker-only path (`launchTexthookerOnly`) is unchanged. - Confirmed texthooker-only path (`launchTexthookerOnly`) is unchanged.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -17,11 +17,15 @@ ordinal: 49000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Overlay renderer stopped initializing after renderer.ts was split into modules. The emitted JS now uses CommonJS require/exports in a browser context (nodeIntegration disabled), causing script load failure and a blank transparent overlay with missing subtitle interactions. Overlay renderer stopped initializing after renderer.ts was split into modules. The emitted JS now uses CommonJS require/exports in a browser context (nodeIntegration disabled), causing script load failure and a blank transparent overlay with missing subtitle interactions.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Renderer script loads successfully in overlay BrowserWindow without nodeIntegration. - [x] #1 Renderer script loads successfully in overlay BrowserWindow without nodeIntegration.
- [x] #2 Visible overlay displays subtitles again on initial launch. - [x] #2 Visible overlay displays subtitles again on initial launch.
- [x] #3 Overlay keyboard/mouse interactions are functional again. - [x] #3 Overlay keyboard/mouse interactions are functional again.
@@ -31,5 +35,7 @@ Overlay renderer stopped initializing after renderer.ts was split into modules.
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Fixed a renderer module-loading regression introduced by renderer modularization. Added a dedicated renderer TypeScript build target (`tsconfig.renderer.json`) that emits browser-compatible ES modules, updated build script to compile renderer with that config, switched overlay HTML to load `renderer.js` as a module, and updated renderer runtime imports to `.js` module specifiers. Verified that built renderer output no longer contains CommonJS `require(...)` and that core test suite passes (`pnpm run test:core`). Fixed a renderer module-loading regression introduced by renderer modularization. Added a dedicated renderer TypeScript build target (`tsconfig.renderer.json`) that emits browser-compatible ES modules, updated build script to compile renderer with that config, switched overlay HTML to load `renderer.js` as a module, and updated renderer runtime imports to `.js` module specifiers. Verified that built renderer output no longer contains CommonJS `require(...)` and that core test suite passes (`pnpm run test:core`).
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -17,11 +17,15 @@ ordinal: 48000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
User confirmed renderer module-loading fix resolved the broken overlay, but startup experiment changes introduced side effects (e.g., y-s start path re-launch behavior). Revert non-essential auto-start/debugging changes in launcher/plugin/CLI startup flow while preserving renderer ESM fix. User confirmed renderer module-loading fix resolved the broken overlay, but startup experiment changes introduced side effects (e.g., y-s start path re-launch behavior). Revert non-essential auto-start/debugging changes in launcher/plugin/CLI startup flow while preserving renderer ESM fix.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Remove wrapper/plugin auto-start experiment changes that were added during debugging. - [x] #1 Remove wrapper/plugin auto-start experiment changes that were added during debugging.
- [x] #2 Restore previous y-s start behavior without relaunching a new overlay session from wrapper-managed startup side effects. - [x] #2 Restore previous y-s start behavior without relaunching a new overlay session from wrapper-managed startup side effects.
- [x] #3 Keep renderer ESM/module-loading fix intact. - [x] #3 Keep renderer ESM/module-loading fix intact.
@@ -31,5 +35,7 @@ User confirmed renderer module-loading fix resolved the broken overlay, but star
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Reverted startup experiment changes while preserving the renderer ESM fix. Removed wrapper-forced visible overlay startup and wrapper-managed mpv script opts from `subminer`, restored plugin defaults/behavior (`auto_start=true`) and removed `wrapper_managed` handling from `plugin/subminer.lua` + `plugin/subminer.conf`, and reverted CLI/bootstrap debug-path changes in `src/core/services/cli-command-service.ts` and `src/core/services/startup-service.ts` with matching test updates. Verified `pnpm run build` and full `pnpm run test:core` pass. Reverted startup experiment changes while preserving the renderer ESM fix. Removed wrapper-forced visible overlay startup and wrapper-managed mpv script opts from `subminer`, restored plugin defaults/behavior (`auto_start=true`) and removed `wrapper_managed` handling from `plugin/subminer.lua` + `plugin/subminer.conf`, and reverted CLI/bootstrap debug-path changes in `src/core/services/cli-command-service.ts` and `src/core/services/startup-service.ts` with matching test updates. Verified `pnpm run build` and full `pnpm run test:core` pass.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -20,11 +20,15 @@ ordinal: 47000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Current visible and invisible overlays can both be enabled at once, but both windows occupy full mpv bounds so hover/input targets conflict. Investigate feasibility of sizing each overlay window to subtitle content bounds (including secondary subtitles) instead of fullscreen. Also investigate decoupling secondary subtitle rendering from overlay visibility by introducing a dedicated top bar region (full-width or text-width) that remains at top and respects secondary subtitle display mode config (hover/always/never). Current visible and invisible overlays can both be enabled at once, but both windows occupy full mpv bounds so hover/input targets conflict. Investigate feasibility of sizing each overlay window to subtitle content bounds (including secondary subtitles) instead of fullscreen. Also investigate decoupling secondary subtitle rendering from overlay visibility by introducing a dedicated top bar region (full-width or text-width) that remains at top and respects secondary subtitle display mode config (hover/always/never).
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Document current overlap/input conflict behavior when both overlays are enabled. - [x] #1 Document current overlap/input conflict behavior when both overlays are enabled.
- [x] #2 Prototype or design approach for content-bounded overlay window sizing for visible and invisible overlays. - [x] #2 Prototype or design approach for content-bounded overlay window sizing for visible and invisible overlays.
- [x] #3 Evaluate interaction model and technical constraints for a dedicated top secondary-subtitle bar independent from overlay visibility. - [x] #3 Evaluate interaction model and technical constraints for a dedicated top secondary-subtitle bar independent from overlay visibility.
@@ -34,26 +38,32 @@ Current visible and invisible overlays can both be enabled at once, but both win
## Implementation Plan ## Implementation Plan
<!-- SECTION:PLAN:BEGIN --> <!-- SECTION:PLAN:BEGIN -->
1. Baseline current behavior 1. Baseline current behavior
- Trace current visible/invisible overlay window creation and sizing behavior in main process and renderer paths. - Trace current visible/invisible overlay window creation and sizing behavior in main process and renderer paths.
- Document why enabling both overlays causes overlap and input/hover conflict. - Document why enabling both overlays causes overlap and input/hover conflict.
2. Design content-bounded overlay sizing 2. Design content-bounded overlay sizing
- Evaluate measurement sources (renderer DOM bounds vs main process approximations). - Evaluate measurement sources (renderer DOM bounds vs main process approximations).
- Define sizing algorithm (content bounds + padding + min/max + screen clamping) and update triggers. - Define sizing algorithm (content bounds + padding + min/max + screen clamping) and update triggers.
- Identify required IPC contracts and ownership boundaries. - Identify required IPC contracts and ownership boundaries.
3. Design decoupled top secondary-subtitle bar 3. Design decoupled top secondary-subtitle bar
- Define a dedicated top region/window independent from primary subtitle visibility. - Define a dedicated top region/window independent from primary subtitle visibility.
- Specify behavior for secondary subtitle display modes (hover/always/never) and pointer-event policy. - Specify behavior for secondary subtitle display modes (hover/always/never) and pointer-event policy.
4. Recommend phased implementation 4. Recommend phased implementation
- Produce concrete file-level rollout steps, risks, edge cases (wrapping, long lines, resize, multi-monitor, style sync), and validation approach. - Produce concrete file-level rollout steps, risks, edge cases (wrapping, long lines, resize, multi-monitor, style sync), and validation approach.
<!-- SECTION:PLAN:END --> <!-- SECTION:PLAN:END -->
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Completed code-path investigation across overlay window creation/sizing, visibility gating, IPC mouse passthrough, and renderer interaction layers. Completed code-path investigation across overlay window creation/sizing, visibility gating, IPC mouse passthrough, and renderer interaction layers.
Documented current conflict mechanism and architecture limitation: shared fullscreen bounds ownership across both overlay windows blocks safe simultaneous activation. Documented current conflict mechanism and architecture limitation: shared fullscreen bounds ownership across both overlay windows blocks safe simultaneous activation.
@@ -63,14 +73,17 @@ Proposed renderer-driven content-bounds IPC model, per-window bounds ownership,
Included phased implementation plan with risks and edge-case handling in docs/overlay-window-sizing-investigation.md. Included phased implementation plan with risks and edge-case handling in docs/overlay-window-sizing-investigation.md.
Updated documentation reference to `overlay_window.md` because previous `docs/overlay-window-sizing-investigation.md` path is not present in repository. Updated documentation reference to `overlay_window.md` because previous `docs/overlay-window-sizing-investigation.md` path is not present in repository.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Completed investigation and design for dynamic overlay window sizing and decoupled secondary subtitle rendering. Completed investigation and design for dynamic overlay window sizing and decoupled secondary subtitle rendering.
What changed: What changed:
- Added `docs/overlay-window-sizing-investigation.md` with a code-referenced analysis of current overlay behavior. - Added `docs/overlay-window-sizing-investigation.md` with a code-referenced analysis of current overlay behavior.
- Documented why overlap/input conflicts emerge under simultaneous overlay activation: both windows are full-size and currently share bounds ownership semantics. - Documented why overlap/input conflicts emerge under simultaneous overlay activation: both windows are full-size and currently share bounds ownership semantics.
- Designed a content-bounded sizing approach based on renderer-measured DOM bounds reported to main via IPC, with clamping, jitter guards, and fallback behavior. - Designed a content-bounded sizing approach based on renderer-measured DOM bounds reported to main via IPC, with clamping, jitter guards, and fallback behavior.
@@ -78,6 +91,7 @@ What changed:
- Defined a phased file-level implementation path and explicit edge-case handling (wrapping/long lines, resize churn, multi-monitor transitions, mpv style/render sync). - Defined a phased file-level implementation path and explicit edge-case handling (wrapping/long lines, resize churn, multi-monitor transitions, mpv style/render sync).
Validation: Validation:
- Investigation validated by tracing current runtime/services/renderer code paths; no runtime behavior changes were applied in this task. - Investigation validated by tracing current runtime/services/renderer code paths; no runtime behavior changes were applied in this task.
- No automated tests were run because this task produced design documentation only (no executable code changes). - No automated tests were run because this task produced design documentation only (no executable code changes).
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -20,11 +20,15 @@ ordinal: 54000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add a script that offloads macOS package builds to a remote Mac mini over SSH, then syncs release artifacts back to the local workspace. Add a script that offloads macOS package builds to a remote Mac mini over SSH, then syncs release artifacts back to the local workspace.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Script supports remote host and path configuration. - [x] #1 Script supports remote host and path configuration.
- [x] #2 Script supports signed and unsigned macOS build modes. - [x] #2 Script supports signed and unsigned macOS build modes.
- [x] #3 Script syncs project sources to remote and copies release artifacts back locally. - [x] #3 Script syncs project sources to remote and copies release artifacts back locally.
@@ -33,7 +37,9 @@ Add a script that offloads macOS package builds to a remote Mac mini over SSH, t
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Added `scripts/build-external.sh` with: Added `scripts/build-external.sh` with:
- Defaults for host alias (`mac-mini`) and remote path (`~/build/SubMiner`) - Defaults for host alias (`mac-mini`) and remote path (`~/build/SubMiner`)
- Argument flags: `--host`, `--remote-path`, `--signed`, `--unsigned`, `--skip-sync`, `--sync-only` - Argument flags: `--host`, `--remote-path`, `--signed`, `--unsigned`, `--skip-sync`, `--sync-only`
- Rsync-based upload excluding heavyweight build artifacts and local dependencies - Rsync-based upload excluding heavyweight build artifacts and local dependencies

View File

@@ -18,11 +18,15 @@ ordinal: 14000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Execute the remaining follow-up work identified in investigation.md: remove unused scaffolding, add tests for high-risk consolidated services, and run manual smoke validation in a desktop MPV session. Execute the remaining follow-up work identified in investigation.md: remove unused scaffolding, add tests for high-risk consolidated services, and run manual smoke validation in a desktop MPV session.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Follow-up subtasks are created with explicit scope and dependencies. - [x] #1 Follow-up subtasks are created with explicit scope and dependencies.
- [x] #2 Unused architectural scaffolding and abandoned IPC abstraction files are removed or explicitly retained with documented rationale. - [x] #2 Unused architectural scaffolding and abandoned IPC abstraction files are removed or explicitly retained with documented rationale.
- [x] #3 Dedicated tests are added for higher-risk consolidated services (`overlay-shortcut-handler`, `mining-service`, `anki-jimaku-service`). - [x] #3 Dedicated tests are added for higher-risk consolidated services (`overlay-shortcut-handler`, `mining-service`, `anki-jimaku-service`).
@@ -32,6 +36,7 @@ Execute the remaining follow-up work identified in investigation.md: remove unus
## Implementation Plan ## Implementation Plan
<!-- SECTION:PLAN:BEGIN --> <!-- SECTION:PLAN:BEGIN -->
1. Create scoped subtasks for each recommendation in investigation.md and sequence them by risk and execution constraints. 1. Create scoped subtasks for each recommendation in investigation.md and sequence them by risk and execution constraints.
2. Remove dead scaffolding files and any now-unneeded exports/imports; verify build/tests remain green. 2. Remove dead scaffolding files and any now-unneeded exports/imports; verify build/tests remain green.
3. Add focused behavior tests for the three higher-risk consolidated services. 3. Add focused behavior tests for the three higher-risk consolidated services.
@@ -41,7 +46,9 @@ Execute the remaining follow-up work identified in investigation.md: remove unus
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Completed: Completed:
- Created TASK-2.1 through TASK-2.5 from `investigation.md` recommendations. - Created TASK-2.1 through TASK-2.5 from `investigation.md` recommendations.
- Finished TASK-2.1: removed unused scaffolding in `src/core/`, `src/modules/`, `src/ipc/` and cleaned internal-only service barrel export. - Finished TASK-2.1: removed unused scaffolding in `src/core/`, `src/modules/`, `src/ipc/` and cleaned internal-only service barrel export.
- Finished TASK-2.2: added dedicated tests for `overlay-shortcut-handler.ts`. - Finished TASK-2.2: added dedicated tests for `overlay-shortcut-handler.ts`.
@@ -49,5 +56,6 @@ Completed:
- Finished TASK-2.4: added dedicated tests for `anki-jimaku-service.ts`. - Finished TASK-2.4: added dedicated tests for `anki-jimaku-service.ts`.
Remaining: Remaining:
- TASK-2.5: desktop smoke validation with MPV session - TASK-2.5: desktop smoke validation with MPV session
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -26,11 +26,15 @@ ordinal: 11000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Remove unused module-architecture scaffolding and IPC abstraction files identified as dead code, and clean service barrel exports that are not needed outside service internals. Remove unused module-architecture scaffolding and IPC abstraction files identified as dead code, and clean service barrel exports that are not needed outside service internals.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Files under `src/core/{action-bus.ts,actions.ts,app-context.ts,module-registry.ts,module.ts}` are removed if unreferenced. - [x] #1 Files under `src/core/{action-bus.ts,actions.ts,app-context.ts,module-registry.ts,module.ts}` are removed if unreferenced.
- [x] #2 Unused `src/modules/` and `src/ipc/` scaffolding files are removed if unreferenced. - [x] #2 Unused `src/modules/` and `src/ipc/` scaffolding files are removed if unreferenced.
- [x] #3 `src/core/services/index.ts` no longer exports symbols that are only consumed internally (`isGlobalShortcutRegisteredSafe`). - [x] #3 `src/core/services/index.ts` no longer exports symbols that are only consumed internally (`isGlobalShortcutRegisteredSafe`).
@@ -40,6 +44,7 @@ Remove unused module-architecture scaffolding and IPC abstraction files identifi
## Implementation Plan ## Implementation Plan
<!-- SECTION:PLAN:BEGIN --> <!-- SECTION:PLAN:BEGIN -->
1. Verify all candidate files are truly unreferenced in runtime/test paths. 1. Verify all candidate files are truly unreferenced in runtime/test paths.
2. Delete dead scaffolding files and folders. 2. Delete dead scaffolding files and folders.
3. Remove unnecessary service barrel exports and fix any import fallout. 3. Remove unnecessary service barrel exports and fix any import fallout.
@@ -49,11 +54,13 @@ Remove unused module-architecture scaffolding and IPC abstraction files identifi
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Removed unused scaffolding files from `src/core/`, `src/modules/`, and `src/ipc/` that were unreferenced by runtime code. Removed unused scaffolding files from `src/core/`, `src/modules/`, and `src/ipc/` that were unreferenced by runtime code.
Updated `src/core/services/index.ts` to stop re-exporting `isGlobalShortcutRegisteredSafe`, which is only used internally by service files. Updated `src/core/services/index.ts` to stop re-exporting `isGlobalShortcutRegisteredSafe`, which is only used internally by service files.
Verification: Verification:
- `pnpm run build` passed - `pnpm run build` passed
- `pnpm run test:core` passed (18/18) - `pnpm run test:core` passed (18/18)
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -19,11 +19,15 @@ ordinal: 9000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add dedicated tests for `overlay-shortcut-handler.ts`, covering shortcut runtime handlers, fallback behavior, and key edge/error paths. Add dedicated tests for `overlay-shortcut-handler.ts`, covering shortcut runtime handlers, fallback behavior, and key edge/error paths.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Shortcut registration/unregistration handler behavior is covered. - [x] #1 Shortcut registration/unregistration handler behavior is covered.
- [x] #2 Fallback handling paths are covered for valid and invalid input. - [x] #2 Fallback handling paths are covered for valid and invalid input.
- [x] #3 Error and guard behavior is covered for missing dependencies/state. - [x] #3 Error and guard behavior is covered for missing dependencies/state.
@@ -33,7 +37,9 @@ Add dedicated tests for `overlay-shortcut-handler.ts`, covering shortcut runtime
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Added `src/core/services/overlay-shortcut-handler.test.ts` with coverage for: Added `src/core/services/overlay-shortcut-handler.test.ts` with coverage for:
- runtime handler dispatch for sync and async actions - runtime handler dispatch for sync and async actions
- async error propagation to OSD/log handling - async error propagation to OSD/log handling
- local fallback action matching, including timeout forwarding - local fallback action matching, including timeout forwarding
@@ -43,4 +49,5 @@ Added `src/core/services/overlay-shortcut-handler.test.ts` with coverage for:
Updated `package.json` `test:core` to include `dist/core/services/overlay-shortcut-handler.test.js`. Updated `package.json` `test:core` to include `dist/core/services/overlay-shortcut-handler.test.js`.
Verification: `pnpm run test:core` passed (19/19 at completion of this ticket). Verification: `pnpm run test:core` passed (19/19 at completion of this ticket).
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -19,11 +19,15 @@ ordinal: 8000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add dedicated behavior tests for `mining-service.ts` covering sentence/card mining orchestration and error boundaries. Add dedicated behavior tests for `mining-service.ts` covering sentence/card mining orchestration and error boundaries.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Happy-path behavior is covered for mining entry points. - [x] #1 Happy-path behavior is covered for mining entry points.
- [x] #2 Guard/early-return behavior is covered for missing runtime state. - [x] #2 Guard/early-return behavior is covered for missing runtime state.
- [x] #3 Error paths are covered with expected logging/OSD behavior. - [x] #3 Error paths are covered with expected logging/OSD behavior.
@@ -33,7 +37,9 @@ Add dedicated behavior tests for `mining-service.ts` covering sentence/card mini
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Added `src/core/services/mining-service.test.ts` with focused coverage for: Added `src/core/services/mining-service.test.ts` with focused coverage for:
- `copyCurrentSubtitleService` guard and success behavior - `copyCurrentSubtitleService` guard and success behavior
- `mineSentenceCardService` integration/connection guards and success path - `mineSentenceCardService` integration/connection guards and success path
- `handleMultiCopyDigitService` history-copy behavior with truncation messaging - `handleMultiCopyDigitService` history-copy behavior with truncation messaging
@@ -42,4 +48,5 @@ Added `src/core/services/mining-service.test.ts` with focused coverage for:
Updated `package.json` `test:core` to include `dist/core/services/mining-service.test.js`. Updated `package.json` `test:core` to include `dist/core/services/mining-service.test.js`.
Verification: `pnpm run test:core` passed (20/20 after adding mining tests). Verification: `pnpm run test:core` passed (20/20 after adding mining tests).
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -19,11 +19,15 @@ ordinal: 7000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add dedicated tests for `anki-jimaku-service.ts` focusing on IPC handler registration, request dispatch, and error handling behavior. Add dedicated tests for `anki-jimaku-service.ts` focusing on IPC handler registration, request dispatch, and error handling behavior.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 IPC registration behavior is validated for all channels exposed by this service. - [x] #1 IPC registration behavior is validated for all channels exposed by this service.
- [x] #2 Success-path behavior for core handler flows is validated. - [x] #2 Success-path behavior for core handler flows is validated.
- [x] #3 Failure-path behavior is validated with expected error propagation. - [x] #3 Failure-path behavior is validated with expected error propagation.
@@ -33,9 +37,11 @@ Add dedicated tests for `anki-jimaku-service.ts` focusing on IPC handler registr
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Added a lightweight registration-injection seam to `registerAnkiJimakuIpcRuntimeService` so runtime behavior can be tested without Electron IPC globals. Added a lightweight registration-injection seam to `registerAnkiJimakuIpcRuntimeService` so runtime behavior can be tested without Electron IPC globals.
Added `src/core/services/anki-jimaku-service.test.ts` with coverage for: Added `src/core/services/anki-jimaku-service.test.ts` with coverage for:
- runtime handler surface registration - runtime handler surface registration
- integration disable path and runtime-options broadcast - integration disable path and runtime-options broadcast
- subtitle history clear and field-grouping response callbacks - subtitle history clear and field-grouping response callbacks
@@ -46,4 +52,5 @@ Added `src/core/services/anki-jimaku-service.test.ts` with coverage for:
Updated `package.json` `test:core` to include `dist/core/services/anki-jimaku-service.test.js`. Updated `package.json` `test:core` to include `dist/core/services/anki-jimaku-service.test.js`.
Verification: `pnpm run test:core` passed (21/21). Verification: `pnpm run test:core` passed (21/21).
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -20,11 +20,15 @@ ordinal: 13000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Execute manual desktop smoke checks in an MPV-enabled environment to validate overlay rendering and key user workflows not fully covered by automated tests. Execute manual desktop smoke checks in an MPV-enabled environment to validate overlay rendering and key user workflows not fully covered by automated tests.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Overlay rendering and visibility toggling are verified in a real desktop session. - [x] #1 Overlay rendering and visibility toggling are verified in a real desktop session.
- [x] #2 Card mining flow is verified end-to-end. - [x] #2 Card mining flow is verified end-to-end.
- [x] #3 Field-grouping interaction is verified end-to-end. - [x] #3 Field-grouping interaction is verified end-to-end.
@@ -34,9 +38,11 @@ Execute manual desktop smoke checks in an MPV-enabled environment to validate ov
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Smoke run executed on 2026-02-10 with real Electron launch (outside sandbox) after unsetting `ELECTRON_RUN_AS_NODE=1` in command context. Smoke run executed on 2026-02-10 with real Electron launch (outside sandbox) after unsetting `ELECTRON_RUN_AS_NODE=1` in command context.
Commands executed: Commands executed:
- `electron . --help` - `electron . --help`
- `electron . --start` - `electron . --start`
- `electron . --toggle-visible-overlay` - `electron . --toggle-visible-overlay`
@@ -47,12 +53,14 @@ Commands executed:
- `electron . --stop` - `electron . --stop`
Observed runtime evidence from app logs: Observed runtime evidence from app logs:
- CLI help output rendered with expected flags. - CLI help output rendered with expected flags.
- App started and connected to MPV after reconnect attempts. - App started and connected to MPV after reconnect attempts.
- Mining flow executed and produced `Created sentence card: ...`, plus media upload logs. - Mining flow executed and produced `Created sentence card: ...`, plus media upload logs.
- Tracker/runtime loop started (`hyprland` tracker connected) and app stopped cleanly. - Tracker/runtime loop started (`hyprland` tracker connected) and app stopped cleanly.
Follow-up/constraints: Follow-up/constraints:
- Overlay *visual rendering* and visibility correctness are not directly observable from terminal logs alone and still require direct desktop visual confirmation.
- Overlay _visual rendering_ and visibility correctness are not directly observable from terminal logs alone and still require direct desktop visual confirmation.
- Field-grouping trigger command was sent, but explicit end-state confirmation in UI still needs manual verification. - Field-grouping trigger command was sent, but explicit end-state confirmation in UI still needs manual verification.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -15,11 +15,15 @@ ordinal: 45000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add renderer-to-main IPC for content measurement reporting, so main process can size each overlay window from post-layout DOM bounds. Add renderer-to-main IPC for content measurement reporting, so main process can size each overlay window from post-layout DOM bounds.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Preload exposes a typed API for reporting overlay content bounds with layer metadata. - [x] #1 Preload exposes a typed API for reporting overlay content bounds with layer metadata.
- [x] #2 Main-process IPC handler validates payload shape/range and stores latest measurement per layer. - [x] #2 Main-process IPC handler validates payload shape/range and stores latest measurement per layer.
- [x] #3 Renderer emits measurement updates on subtitle, mode, style, and render-metric changes with throttling/debounce. - [x] #3 Renderer emits measurement updates on subtitle, mode, style, and render-metric changes with throttling/debounce.
@@ -29,15 +33,19 @@ Add renderer-to-main IPC for content measurement reporting, so main process can
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Added a typed `OverlayContentMeasurement` IPC contract exposed in preload and Electron API typings. Implemented a main-process measurement store with strict payload validation and rate-limited warning logs for invalid reports. Added renderer-side debounced measurement reporting that emits updates on subtitle content/mode/style/render-metric and resize changes, explicitly sending `contentRect: null` when no measured content exists to signal fallback behavior. Added a typed `OverlayContentMeasurement` IPC contract exposed in preload and Electron API typings. Implemented a main-process measurement store with strict payload validation and rate-limited warning logs for invalid reports. Added renderer-side debounced measurement reporting that emits updates on subtitle content/mode/style/render-metric and resize changes, explicitly sending `contentRect: null` when no measured content exists to signal fallback behavior.
Added unit coverage for measurement validation and store behavior. Added unit coverage for measurement validation and store behavior.
Closed per user request to delete parent task and subtasks. Closed per user request to delete parent task and subtasks.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Implemented renderer-to-main measurement reporting for overlay content bounds with per-layer metadata. Main now validates and stores latest measurements per layer safely, renderer emits debounced updates on relevant state changes, and invalid/missing payload handling is explicit and non-spammy. Implemented renderer-to-main measurement reporting for overlay content bounds with per-layer metadata. Main now validates and stores latest measurements per layer safely, renderer emits debounced updates on relevant state changes, and invalid/missing payload handling is explicit and non-spammy.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -14,11 +14,15 @@ ordinal: 46000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
When SubMiner connects to MPV, capture the current MPV `secondary-sub-visibility` value and force it off. Keep it off during SubMiner runtime regardless of overlay visibility toggles. On app shutdown (and MPV shutdown event when possible), restore MPV `secondary-sub-visibility` to the captured pre-SubMiner value. When SubMiner connects to MPV, capture the current MPV `secondary-sub-visibility` value and force it off. Keep it off during SubMiner runtime regardless of overlay visibility toggles. On app shutdown (and MPV shutdown event when possible), restore MPV `secondary-sub-visibility` to the captured pre-SubMiner value.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Capture MPV `secondary-sub-visibility` once per MPV connection before overriding it. - [x] #1 Capture MPV `secondary-sub-visibility` once per MPV connection before overriding it.
- [x] #2 Set MPV `secondary-sub-visibility` to `no` after capture regardless of `bind_visible_overlay_to_mpv_sub_visibility`. - [x] #2 Set MPV `secondary-sub-visibility` to `no` after capture regardless of `bind_visible_overlay_to_mpv_sub_visibility`.
- [x] #3 Do not mutate/restore secondary MPV visibility as a side effect of visible overlay toggles. - [x] #3 Do not mutate/restore secondary MPV visibility as a side effect of visible overlay toggles.
@@ -29,7 +33,9 @@ When SubMiner connects to MPV, capture the current MPV `secondary-sub-visibility
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Implemented MPV secondary subtitle visibility lifecycle management: Implemented MPV secondary subtitle visibility lifecycle management:
- Moved secondary-sub visibility capture/disable to MPV connection initialization (`getInitialState` requests `secondary-sub-visibility`, then request handler stores prior value and forces `secondary-sub-visibility=no`). - Moved secondary-sub visibility capture/disable to MPV connection initialization (`getInitialState` requests `secondary-sub-visibility`, then request handler stores prior value and forces `secondary-sub-visibility=no`).
- Removed secondary-sub visibility side effects from visible overlay visibility service so overlay toggles no longer capture/restore secondary MPV state. - Removed secondary-sub visibility side effects from visible overlay visibility service so overlay toggles no longer capture/restore secondary MPV state.
- Added `restorePreviousSecondarySubVisibility()` to `MpvIpcClient`, invoked on MPV `shutdown` event and from app `onWillQuitCleanup` (best effort while connected). - Added `restorePreviousSecondarySubVisibility()` to `MpvIpcClient`, invoked on MPV `shutdown` event and from app `onWillQuitCleanup` (best effort while connected).

View File

@@ -16,11 +16,15 @@ ordinal: 34000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Implement an opt-in JLPT token annotation feature that annotates subtitle words with JLPT level in-session. The feature should use a bundled dictionary source from the existing JLPT Yomitan extension, parse/query its dictionary file to determine whether a token appears and its JLPT level, and render token-level visual tags as a colored underline spanning each token length. Colors must correspond to JLPT levels (e.g., N5/N4/N3/N2/N1) using a consistent mapping. Implement an opt-in JLPT token annotation feature that annotates subtitle words with JLPT level in-session. The feature should use a bundled dictionary source from the existing JLPT Yomitan extension, parse/query its dictionary file to determine whether a token appears and its JLPT level, and render token-level visual tags as a colored underline spanning each token length. Colors must correspond to JLPT levels (e.g., N5/N4/N3/N2/N1) using a consistent mapping.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Add an opt-in setting/feature flag so JLPT tagging is disabled by default and can be enabled per user/session as requested. - [x] #1 Add an opt-in setting/feature flag so JLPT tagging is disabled by default and can be enabled per user/session as requested.
- [x] #2 Bundle the existing JLPT Yomitan extension package/data into the project so lookups can be performed offline from local files. - [x] #2 Bundle the existing JLPT Yomitan extension package/data into the project so lookups can be performed offline from local files.
- [x] #3 Implement token-level dictionary lookup against the bundled JLPT dictionary file to determine presence and JLPT level for words in subtitle lines. - [x] #3 Implement token-level dictionary lookup against the bundled JLPT dictionary file to determine presence and JLPT level for words in subtitle lines.
@@ -34,7 +38,9 @@ Implement an opt-in JLPT token annotation feature that annotates subtitle words
<!-- AC:END --> <!-- AC:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [x] #1 Feature has a clear toggle and persistence of preference if applicable. - [x] #1 Feature has a clear toggle and persistence of preference if applicable.
- [x] #2 JLPT rendering is visually verified for all supported levels with distinct colors and no overlap/regression in subtitle legibility. - [x] #2 JLPT rendering is visually verified for all supported levels with distinct colors and no overlap/regression in subtitle legibility.
<!-- DOD:END --> <!-- DOD:END -->

View File

@@ -15,11 +15,15 @@ ordinal: 32000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Create a lookup layer that parses/queries the bundled JLPT dictionary file and returns JLPT level for a given token/word. Integrate with subtitle tokenization path with minimal performance overhead. Create a lookup layer that parses/queries the bundled JLPT dictionary file and returns JLPT level for a given token/word. Integrate with subtitle tokenization path with minimal performance overhead.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Service accepts a token/normalized token and returns JLPT level or no-match deterministically. - [x] #1 Service accepts a token/normalized token and returns JLPT level or no-match deterministically.
- [x] #2 Lookup handles expected dictionary format edge cases and unknown tokens without throwing. - [x] #2 Lookup handles expected dictionary format edge cases and unknown tokens without throwing.
- [x] #3 Lookup path is efficient enough for frame-by-frame subtitle updates. - [x] #3 Lookup path is efficient enough for frame-by-frame subtitle updates.
@@ -28,6 +32,8 @@ Create a lookup layer that parses/queries the bundled JLPT dictionary file and r
<!-- AC:END --> <!-- AC:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [x] #1 Lookup service returns JLPT level with deterministic output for test fixtures. - [x] #1 Lookup service returns JLPT level with deterministic output for test fixtures.
<!-- DOD:END --> <!-- DOD:END -->

View File

@@ -15,11 +15,15 @@ ordinal: 33000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Package and include the JLPT Yomitan extension dictionary assets in SubMiner so JLPT tagging can run without external network calls. Define a deterministic build/runtime path and loading strategy for the dictionary file and metadata versioning. Package and include the JLPT Yomitan extension dictionary assets in SubMiner so JLPT tagging can run without external network calls. Define a deterministic build/runtime path and loading strategy for the dictionary file and metadata versioning.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 JLPT dictionary asset from the existing Yomitan extension is added to the repository/build output in a tracked, offline-available location. - [x] #1 JLPT dictionary asset from the existing Yomitan extension is added to the repository/build output in a tracked, offline-available location.
- [x] #2 The loader locates and opens the JLPT dictionary file deterministically at runtime. - [x] #2 The loader locates and opens the JLPT dictionary file deterministically at runtime.
- [x] #3 Dictionary version/source is documented so future updates are explicit and reproducible. - [x] #3 Dictionary version/source is documented so future updates are explicit and reproducible.
@@ -27,6 +31,8 @@ Package and include the JLPT Yomitan extension dictionary assets in SubMiner so
<!-- AC:END --> <!-- AC:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [x] #1 Dictionary data is bundled and consumable during development and packaged app runs. - [x] #1 Dictionary data is bundled and consumable during development and packaged app runs.
<!-- DOD:END --> <!-- DOD:END -->

View File

@@ -15,11 +15,15 @@ ordinal: 44000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Render JLPT-aware token annotations as token-length colored underlines in the subtitle UI based on returned JLPT levels, without changing existing subtitle layout or primary interaction behavior. Render JLPT-aware token annotations as token-length colored underlines in the subtitle UI based on returned JLPT levels, without changing existing subtitle layout or primary interaction behavior.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 For each token with JLPT level, renderer draws an underline matching token width/length. - [x] #1 For each token with JLPT level, renderer draws an underline matching token width/length.
- [x] #2 Underlines use distinct colors by JLPT level (e.g., N5/N4/N3/N2/N1) and mapping is consistent/documented. - [x] #2 Underlines use distinct colors by JLPT level (e.g., N5/N4/N3/N2/N1) and mapping is consistent/documented.
- [x] #3 Non-tagged tokens remain visually unchanged. - [x] #3 Non-tagged tokens remain visually unchanged.
@@ -28,6 +32,8 @@ Render JLPT-aware token annotations as token-length colored underlines in the su
<!-- AC:END --> <!-- AC:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [x] #1 Visual output validated for all mapped JLPT levels with no legibility/layout regressions. - [x] #1 Visual output validated for all mapped JLPT levels with no legibility/layout regressions.
<!-- DOD:END --> <!-- DOD:END -->

View File

@@ -15,11 +15,15 @@ ordinal: 35000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add user/config setting to enable JLPT tagging, wire the feature toggle through subtitle processing/rendering, and add tests/verification for positive match, non-match, and disabled-mode behavior. Add user/config setting to enable JLPT tagging, wire the feature toggle through subtitle processing/rendering, and add tests/verification for positive match, non-match, and disabled-mode behavior.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 JLPT tagging is opt-in and defaults to disabled. - [x] #1 JLPT tagging is opt-in and defaults to disabled.
- [x] #2 When disabled, lookup/rendering pipeline does not execute JLPT processing. - [x] #2 When disabled, lookup/rendering pipeline does not execute JLPT processing.
- [x] #3 When enabled, end-to-end flow tags subtitle words via token-level lookup and rendering. - [x] #3 When enabled, end-to-end flow tags subtitle words via token-level lookup and rendering.
@@ -27,6 +31,8 @@ Add user/config setting to enable JLPT tagging, wire the feature toggle through
<!-- AC:END --> <!-- AC:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [x] #1 End-to-end option behavior and opt-in state persistence are implemented and verified. - [x] #1 End-to-end option behavior and opt-in state persistence are implemented and verified.
<!-- DOD:END --> <!-- DOD:END -->

View File

@@ -16,11 +16,15 @@ ordinal: 37000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Implement subtitle highlighting for words already known in Anki (N+1 workflow support) by introducing a one-time bootstrap query of the users Anki known-word set, storing it locally, and refreshing it periodically to reflect deck updates. The feature should allow fast in-session lookups to determine known words and visually distinguish them in subtitle rendering. Implement subtitle highlighting for words already known in Anki (N+1 workflow support) by introducing a one-time bootstrap query of the users Anki known-word set, storing it locally, and refreshing it periodically to reflect deck updates. The feature should allow fast in-session lookups to determine known words and visually distinguish them in subtitle rendering.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Add an opt-in setting/feature flag for N+1 highlighting and default it to disabled for backward-compatible behavior. - [x] #1 Add an opt-in setting/feature flag for N+1 highlighting and default it to disabled for backward-compatible behavior.
- [x] #2 Implement a one-time import/sync that queries known-word data from Anki into a local store on first enable or explicit refresh. - [x] #2 Implement a one-time import/sync that queries known-word data from Anki into a local store on first enable or explicit refresh.
- [x] #3 Store known words locally in an efficient structure for fast lookup during subtitle rendering. - [x] #3 Store known words locally in an efficient structure for fast lookup during subtitle rendering.
@@ -36,10 +40,14 @@ Implement subtitle highlighting for words already known in Anki (N+1 workflow su
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Implemented in refactor via merge from task-24-known-word-refresh (commits 854b8fb, e8f2431, ed5a249). Includes manual/periodic known-word cache refresh, opt-in N+1 highlighting path, cache persistence behavior, CLI refresh command, and related tests/docs updates. Implemented in refactor via merge from task-24-known-word-refresh (commits 854b8fb, e8f2431, ed5a249). Includes manual/periodic known-word cache refresh, opt-in N+1 highlighting path, cache persistence behavior, CLI refresh command, and related tests/docs updates.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [x] #1 N+1 known-word highlighting is configurable, performs local cached lookups, and is demonstrated to update correctly after periodic/manual refresh. - [x] #1 N+1 known-word highlighting is configurable, performs local cached lookups, and is demonstrated to update correctly after periodic/manual refresh.
<!-- DOD:END --> <!-- DOD:END -->

View File

@@ -19,11 +19,15 @@ ordinal: 28000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Leverage user-installed frequency dictionaries to color subtitle tokens based on word frequency rank, with configurable behavior: either one shared color for all words below a rank threshold or a multi-color range mapping based on frequency bands. The feature should support a configurable X (top-N words) cutoff and integrate with existing subtitle rendering flow. Leverage user-installed frequency dictionaries to color subtitle tokens based on word frequency rank, with configurable behavior: either one shared color for all words below a rank threshold or a multi-color range mapping based on frequency bands. The feature should support a configurable X (top-N words) cutoff and integrate with existing subtitle rendering flow.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Add a feature flag and configuration for frequency-based highlighting with default disabled state. - [x] #1 Add a feature flag and configuration for frequency-based highlighting with default disabled state.
- [x] #2 Support selecting a user-installed frequency dictionary source and reading word frequency data from it. - [x] #2 Support selecting a user-installed frequency dictionary source and reading word frequency data from it.
- [x] #3 Introduce a configurable top-X threshold in config for which words are eligible for frequency-based coloring. - [x] #3 Introduce a configurable top-X threshold in config for which words are eligible for frequency-based coloring.
@@ -40,16 +44,20 @@ Leverage user-installed frequency dictionaries to color subtitle tokens based on
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
2026-02-16: Updated docs for frequency dictionary behavior. Clarified built-in fallback, precedence, and shared format expectations in and .
2026-02-16: Updated docs for frequency dictionary behavior. Clarified built-in fallback, precedence, and shared format expectations in and .
Added docs references for frequency dictionary defaults and fallback behavior. Added docs references for frequency dictionary defaults and fallback behavior.
As of 2026-02-16, docs and implementation are considered complete for TASK-25; frequency highlighting fallback, custom sourcePath precedence, topX, single/banded modes, token pipeline integration, and fallback behavior are present; documentation and tests exist in src/core/services and src/renderer. As of 2026-02-16, docs and implementation are considered complete for TASK-25; frequency highlighting fallback, custom sourcePath precedence, topX, single/banded modes, token pipeline integration, and fallback behavior are present; documentation and tests exist in src/core/services and src/renderer.
2026-02-16: Frequency-dictionary highlighting feature fully complete and shipped. Task acceptance criteria, DoD, and docs alignment are all marked complete in this task record. 2026-02-16: Frequency-dictionary highlighting feature fully complete and shipped. Task acceptance criteria, DoD, and docs alignment are all marked complete in this task record.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [x] #1 Frequency-based highlighting renders using either single-color or banded-colors for valid matches, with configurable top-X threshold and documented setup. - [x] #1 Frequency-based highlighting renders using either single-color or banded-colors for valid matches, with configurable top-X threshold and documented setup.
<!-- DOD:END --> <!-- DOD:END -->

View File

@@ -16,11 +16,15 @@ ordinal: 43000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Create a help modal that auto-generates its content from the project/app layout and current configuration, showing the active keybindings and color keys for the current session in a presentable way. The modal should be navigable with arrow keys and Vim-style hjkl-style movement behavior internally but without labeling hjkl in UI, and support mouse interaction. Escape closes/goes back. Open the modal with `y-h`, and if that binding is already taken, use `y-k` as fallback. Create a help modal that auto-generates its content from the project/app layout and current configuration, showing the active keybindings and color keys for the current session in a presentable way. The modal should be navigable with arrow keys and Vim-style hjkl-style movement behavior internally but without labeling hjkl in UI, and support mouse interaction. Escape closes/goes back. Open the modal with `y-h`, and if that binding is already taken, use `y-k` as fallback.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Help modal content is generated automatically from current keybinding config and project/app layout rather than hardcoded static text. - [x] #1 Help modal content is generated automatically from current keybinding config and project/app layout rather than hardcoded static text.
- [x] #2 Modal displays current session keybindings and active color-key mappings in a clear, grouped layout with section separation for readability. - [x] #2 Modal displays current session keybindings and active color-key mappings in a clear, grouped layout with section separation for readability.
- [x] #3 Modal can be opened with `y-h` when available; if `y-h` is already bound, modal opens with `y-k` instead. - [x] #3 Modal can be opened with `y-h` when available; if `y-h` is already bound, modal opens with `y-k` instead.
@@ -34,6 +38,8 @@ Create a help modal that auto-generates its content from the project/app layout
<!-- AC:END --> <!-- AC:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [x] #1 Auto-generated help modal displays up-to-date keybinding + color mapping data and supports both keyboard (arrow/fallback path) and mouse navigation with Escape-to-close. - [x] #1 Auto-generated help modal displays up-to-date keybinding + color mapping data and supports both keyboard (arrow/fallback path) and mouse navigation with Escape-to-close.
<!-- DOD:END --> <!-- DOD:END -->

View File

@@ -22,13 +22,17 @@ ordinal: 42000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Create a lightweight inventory of files needing refactoring and their API contracts to prevent accidental coupling regression during splits. Create a lightweight inventory of files needing refactoring and their API contracts to prevent accidental coupling regression during splits.
This is a documentation-only task — no code changes. Its output (docs/structure-roadmap.md) is the prerequisite gate for all Phase 2 subtasks. This is a documentation-only task — no code changes. Its output (docs/structure-roadmap.md) is the prerequisite gate for all Phase 2 subtasks.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Inventory source files with >400 LOC and categorize by concern (bootstrap, Anki integration, MPV protocol, renderer, config, services). - [ ] #1 Inventory source files with >400 LOC and categorize by concern (bootstrap, Anki integration, MPV protocol, renderer, config, services).
- [ ] #2 Document exported API surface for each target file (entry points, exported types, event names, primary callers). - [ ] #2 Document exported API surface for each target file (entry points, exported types, event names, primary callers).
- [ ] #3 List the split sequence from the parent task plan and note any known risks per step. - [ ] #3 List the split sequence from the parent task plan and note any known risks per step.
@@ -39,6 +43,7 @@ This is a documentation-only task — no code changes. Its output (docs/structur
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
## Simplification Notes ## Simplification Notes
Original task called for named maintainer owners per component, risk-gated migration sequences, and success metrics per slice. This is heavyweight for a solo project where the developer already knows the codebase intimately. Original task called for named maintainer owners per component, risk-gated migration sequences, and success metrics per slice. This is heavyweight for a solo project where the developer already knows the codebase intimately.
@@ -46,4 +51,5 @@ Original task called for named maintainer owners per component, risk-gated migra
Reduced to: file inventory, API contracts, sequence + risks, and a shared smoke test checklist. The review analysis (in TASK-27 notes) already covers much of what this task would produce — this task captures it in a durable docs file. Reduced to: file inventory, API contracts, sequence + risks, and a shared smoke test checklist. The review analysis (in TASK-27 notes) already covers much of what this task would produce — this task captures it in a durable docs file.
Generated docs/structure-roadmap.md with file inventory, task-specific API contracts, split sequence, known risks, and smoke checklist to unlock TASK-27 subtasks. Generated docs/structure-roadmap.md with file inventory, task-specific API contracts, split sequence, known risks, and smoke checklist to unlock TASK-27 subtasks.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -24,11 +24,15 @@ ordinal: 40000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Reduce main.ts complexity by extracting bootstrap, lifecycle, overlay, IPC, and CLI wiring into explicit modules while keeping runtime behavior unchanged. Reduce main.ts complexity by extracting bootstrap, lifecycle, overlay, IPC, and CLI wiring into explicit modules while keeping runtime behavior unchanged.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Create modules under src/main/ for bootstrap/lifecycle/ipc/overlay/cli concerns. - [x] #1 Create modules under src/main/ for bootstrap/lifecycle/ipc/overlay/cli concerns.
- [x] #2 main.ts no longer owns session-specific business state; it only composes services and starts the app. - [x] #2 main.ts no longer owns session-specific business state; it only composes services and starts the app.
- [ ] #3 Public service behavior, startup order, and flags remain unchanged, validated by existing integration/manual smoke checks. - [ ] #3 Public service behavior, startup order, and flags remain unchanged, validated by existing integration/manual smoke checks.
@@ -40,6 +44,7 @@ Reduce main.ts complexity by extracting bootstrap, lifecycle, overlay, IPC, and
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
## Dependency Context ## Dependency Context
**TASK-7 is a hard prerequisite.** main.ts currently has 30+ module-level `let` declarations (mpvClient, yomitanExt, reconnectTimer, currentSubText, subtitlePosition, keybindings, ankiIntegration, secondarySubMode, etc.). Splitting main.ts into src/main/ submodules without first consolidating this state into a typed AppState container would scatter mutable state across files, making data flow even harder to trace. **TASK-7 is a hard prerequisite.** main.ts currently has 30+ module-level `let` declarations (mpvClient, yomitanExt, reconnectTimer, currentSubText, subtitlePosition, keybindings, ankiIntegration, secondarySubMode, etc.). Splitting main.ts into src/main/ submodules without first consolidating this state into a typed AppState container would scatter mutable state across files, making data flow even harder to trace.
@@ -49,10 +54,12 @@ Reduce main.ts complexity by extracting bootstrap, lifecycle, overlay, IPC, and
**Sequencing note:** This task should run AFTER TASK-27.3 (anki-integration split) completes, because AnkiIntegration is instantiated and heavily wired in main.ts. Changing both the composition root and the Anki facade simultaneously creates integration risk. Let 27.3 stabilize the Anki module boundaries first, then split main.ts around the stable API. **Sequencing note:** This task should run AFTER TASK-27.3 (anki-integration split) completes, because AnkiIntegration is instantiated and heavily wired in main.ts. Changing both the composition root and the Anki facade simultaneously creates integration risk. Let 27.3 stabilize the Anki module boundaries first, then split main.ts around the stable API.
## Folded-in work from TASK-9 and TASK-10 ## Folded-in work from TASK-9 and TASK-10
TASK-9 (remove trivial wrappers) and TASK-10 (naming conventions) have been deprioritized to low. Their scope is largely subsumed by this task: TASK-9 (remove trivial wrappers) and TASK-10 (naming conventions) have been deprioritized to low. Their scope is largely subsumed by this task:
- When main.ts is split into composition-root modules, trivial wrappers will naturally be eliminated or inlined at each module boundary. - When main.ts is split into composition-root modules, trivial wrappers will naturally be eliminated or inlined at each module boundary.
- Naming conventions should be standardized per-module as they are extracted, not as a separate global pass. - Naming conventions should be standardized per-module as they are extracted, not as a separate global pass.
Refer to TASK-9 and TASK-10 acceptance criteria as checklists during execution of this task. Refer to TASK-9 and TASK-10 acceptance criteria as checklists during execution of this task.
Deferred until TASK-7 validation and TASK-27.3 completion to avoid import-order/state scattering during composition-root extraction. Deferred until TASK-7 validation and TASK-27.3 completion to avoid import-order/state scattering during composition-root extraction.
@@ -91,10 +98,13 @@ TASK-27.2 refactor is now complete for composition-root extraction path: startup
Updated `src/main/state.ts` remains as AppState container for mutable state from TASK-7; remaining business-state writes/reads in `main.ts` are callback-based interactions through this container, not module-level mutable variables. Updated `src/main/state.ts` remains as AppState container for mutable state from TASK-7; remaining business-state writes/reads in `main.ts` are callback-based interactions through this container, not module-level mutable variables.
Per build validation after each chunk, `pnpm build` has been passing. Per build validation after each chunk, `pnpm build` has been passing.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Refactored IPC runtime registration in `main.ts` to pass `ankiJimaku` deps through `createAnkiJimakuIpcRuntimeServiceDeps(...)` and removed the bespoke `buildIpcRuntimeServicesParams()` helper; registration remains in `main.ts` via `registerIpcRuntimeServices({ ... })` with shared runtime service builders. Refactored IPC runtime registration in `main.ts` to pass `ankiJimaku` deps through `createAnkiJimakuIpcRuntimeServiceDeps(...)` and removed the bespoke `buildIpcRuntimeServicesParams()` helper; registration remains in `main.ts` via `registerIpcRuntimeServices({ ... })` with shared runtime service builders.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -22,6 +22,7 @@ ordinal: 39000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Split anki-integration.ts (2,679 LOC, 60+ methods) into cohesive modules with clear handoff contracts. Keep a stable facade API to avoid broad call-site churn. Split anki-integration.ts (2,679 LOC, 60+ methods) into cohesive modules with clear handoff contracts. Keep a stable facade API to avoid broad call-site churn.
## Target Decomposition (7 modules) ## Target Decomposition (7 modules)
@@ -37,10 +38,13 @@ Based on method clustering analysis:
7. **ui-feedback** (~150 LOC) — progress tracking, OSD notifications, status notifications 7. **ui-feedback** (~150 LOC) — progress tracking, OSD notifications, status notifications
Plus a **facade** (`src/anki-integration/index.ts`) that re-exports the public API for backward compatibility. Plus a **facade** (`src/anki-integration/index.ts`) that re-exports the public API for backward compatibility.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Extract at least 6 modules matching the decomposition map above (7 recommended). - [ ] #1 Extract at least 6 modules matching the decomposition map above (7 recommended).
- [ ] #2 Keep a stable facade API in src/anki-integration/index.ts so external callers (main.ts, mining-service) don't change. - [ ] #2 Keep a stable facade API in src/anki-integration/index.ts so external callers (main.ts, mining-service) don't change.
- [ ] #3 Field grouping cluster (~900 LOC) is extracted as its own module — it's the largest single concern. - [ ] #3 Field grouping cluster (~900 LOC) is extracted as its own module — it's the largest single concern.
@@ -54,16 +58,19 @@ Plus a **facade** (`src/anki-integration/index.ts`) that re-exports the public A
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
## Execution Notes ## Execution Notes
This task is self-contained — anki-integration.ts is a single class with a clear public API consumed by main.ts and mining-service. Internal restructuring doesn't affect other files as long as the facade is maintained. This task is self-contained — anki-integration.ts is a single class with a clear public API consumed by main.ts and mining-service. Internal restructuring doesn't affect other files as long as the facade is maintained.
**Should run first in Phase 2** because: **Should run first in Phase 2** because:
- It's the largest file (2,679 LOC vs 1,392 for main.ts) - It's the largest file (2,679 LOC vs 1,392 for main.ts)
- Its public API is narrow (class constructor + ~5 public methods) - Its public API is narrow (class constructor + ~5 public methods)
- main.ts instantiates AnkiIntegration, so stabilizing its API before splitting main.ts avoids double-refactoring - main.ts instantiates AnkiIntegration, so stabilizing its API before splitting main.ts avoids double-refactoring
## Key Risk ## Key Risk
The class has 15 private state fields that create implicit coupling between methods. The `updateLastAddedFromClipboard` method alone is ~230 lines and touches polling state, media generation, and card updates. Extraction order matters: start with the leaf clusters (ai-translation, ui-feedback, duplicate-detection) and work inward toward the stateful core (polling, card-creation, field-grouping). The class has 15 private state fields that create implicit coupling between methods. The `updateLastAddedFromClipboard` method alone is ~230 lines and touches polling state, media generation, and card updates. Extraction order matters: start with the leaf clusters (ai-translation, ui-feedback, duplicate-detection) and work inward toward the stateful core (polling, card-creation, field-grouping).
Started TASK-27.3 with a surgical extraction of the duplicate-detection cluster into `src/anki-integration-duplicate.ts` and refactoring `AnkiIntegration.findDuplicateNote()` to delegate all deck query, search escaping, and normalization logic to the new module while preserving behavior. This reduces `anki-integration.ts` by removing three private duplicate-parsing methods and keeps callsites unchanged. Remaining decomposition work still needed across polling/card-creation/field-grouping/notification clusters from the task map. Started TASK-27.3 with a surgical extraction of the duplicate-detection cluster into `src/anki-integration-duplicate.ts` and refactoring `AnkiIntegration.findDuplicateNote()` to delegate all deck query, search escaping, and normalization logic to the new module while preserving behavior. This reduces `anki-integration.ts` by removing three private duplicate-parsing methods and keeps callsites unchanged. Remaining decomposition work still needed across polling/card-creation/field-grouping/notification clusters from the task map.
@@ -71,4 +78,5 @@ Started TASK-27.3 with a surgical extraction of the duplicate-detection cluster
Second extraction pass completed: moved sentence-translation decision + AI fallback behavior out of `createSentenceCard` into `src/anki-integration/ai.ts` as `resolveSentenceBackText(...)`, with `AnkiIntegration` now delegating translation result generation to this function. This further isolates AI concerns from card-creation flow while keeping behavior and defaults intact. Second extraction pass completed: moved sentence-translation decision + AI fallback behavior out of `createSentenceCard` into `src/anki-integration/ai.ts` as `resolveSentenceBackText(...)`, with `AnkiIntegration` now delegating translation result generation to this function. This further isolates AI concerns from card-creation flow while keeping behavior and defaults intact.
Refactor for TASK-27.3 is complete and build passes after cleanup of ui-feedback delegation (src/anki-integration.ts, src/anki-integration-ui-feedback.ts). Refactor for TASK-27.3 is complete and build passes after cleanup of ui-feedback delegation (src/anki-integration.ts, src/anki-integration-ui-feedback.ts).
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -22,22 +22,27 @@ ordinal: 41000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Split mpv-service.ts (773 LOC) into thin, testable layers without changing wire protocol behavior. Split mpv-service.ts (773 LOC) into thin, testable layers without changing wire protocol behavior.
**This task absorbs the scope of TASK-8** (Reduce MpvIpcClient deps interface and separate protocol from application logic). The work proceeds in two phases: **This task absorbs the scope of TASK-8** (Reduce MpvIpcClient deps interface and separate protocol from application logic). The work proceeds in two phases:
### Phase A (was TASK-8): Separate protocol from application logic ### Phase A (was TASK-8): Separate protocol from application logic
- Reduce the 22-property `MpvIpcClientDeps` interface to protocol-level concerns only - Reduce the 22-property `MpvIpcClientDeps` interface to protocol-level concerns only
- Move application-level reactions (subtitle broadcast, overlay visibility sync, timing tracking) to event emitter or external listener pattern - Move application-level reactions (subtitle broadcast, overlay visibility sync, timing tracking) to event emitter or external listener pattern
- Make MpvIpcClient testable without mocking 22 callbacks - Make MpvIpcClient testable without mocking 22 callbacks
### Phase B: Physical file split ### Phase B: Physical file split
- Create submodules for: protocol parsing/dispatch, connection lifecycle/retry, property subscriptions/state mapping - Create submodules for: protocol parsing/dispatch, connection lifecycle/retry, property subscriptions/state mapping
- Wire the public facade to maintain API compatibility for all existing consumers - Wire the public facade to maintain API compatibility for all existing consumers
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 MpvIpcClient deps interface reduced to protocol-level concerns only (from current 22 properties). - [x] #1 MpvIpcClient deps interface reduced to protocol-level concerns only (from current 22 properties).
- [x] #2 Application-level reactions (subtitle broadcast, overlay sync, timing) handled via event emitter or external listeners registered by main.ts. - [x] #2 Application-level reactions (subtitle broadcast, overlay sync, timing) handled via event emitter or external listeners registered by main.ts.
- [x] #3 Create submodules for protocol parsing/dispatch, connection lifecycle/retry, and property subscriptions/state mapping. - [x] #3 Create submodules for protocol parsing/dispatch, connection lifecycle/retry, and property subscriptions/state mapping.
@@ -50,9 +55,11 @@ Split mpv-service.ts (773 LOC) into thin, testable layers without changing wire
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
## TASK-8 Absorption ## TASK-8 Absorption
TASK-8 and TASK-27.4 overlapped significantly: TASK-8 and TASK-27.4 overlapped significantly:
- TASK-8: "Separate protocol from application logic" + shrink deps interface - TASK-8: "Separate protocol from application logic" + shrink deps interface
- TASK-27.4: "Split into protocol, transport, property, and facade layers" - TASK-27.4: "Split into protocol, transport, property, and facade layers"
@@ -61,6 +68,7 @@ TASK-27.4 is TASK-8 + physical file splitting. Running them as separate tasks wo
**TASK-8 should be marked as superseded** once this task begins. **TASK-8 should be marked as superseded** once this task begins.
## Dependency Note ## Dependency Note
Original plan listed TASK-8 as a dependency. Since TASK-8's scope is now absorbed here, the only remaining dependency is TASK-27.1 (inventory/contracts map). Original plan listed TASK-8 as a dependency. Since TASK-8's scope is now absorbed here, the only remaining dependency is TASK-27.1 (inventory/contracts map).
Started prep: reviewed mpv-service coupling and prepared sequence for protocol/application split; no code split performed yet due current focus on keeping 27.2/27.3 sequencing compatible. Started prep: reviewed mpv-service coupling and prepared sequence for protocol/application split; no code split performed yet due current focus on keeping 27.2/27.3 sequencing compatible.
@@ -78,12 +86,15 @@ Progress update: extracted socket connect/data/error/close/send/reconnect schedu
Added focused transport lifecycle regression coverage in `src/core/services/mpv-transport.test.ts`: connect/connect-idempotence, lifecycle callback ordering, and `shutdown()` resets connection/socket state. This covers reconnect/edge-case behavior at transport layer as part of criterion #6 toward protocol + lifecycle regression protection. Added focused transport lifecycle regression coverage in `src/core/services/mpv-transport.test.ts`: connect/connect-idempotence, lifecycle callback ordering, and `shutdown()` resets connection/socket state. This covers reconnect/edge-case behavior at transport layer as part of criterion #6 toward protocol + lifecycle regression protection.
Added mpv-service unit regression for close lifecycle: `MpvIpcClient onClose resolves outstanding pending requests and triggers reconnect scheduling path via client transport callbacks (`src/core/services/mpv-service.test.ts`). This complements transport-level lifecycle tests for reconnect behavior regression coverage. Added mpv-service unit regression for close lifecycle: `MpvIpcClient onClose resolves outstanding pending requests and triggers reconnect scheduling path via client transport callbacks (`src/core/services/mpv-service.test.ts`). This complements transport-level lifecycle tests for reconnect behavior regression coverage.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Split mpv-service internals into protocol, transport, and property/state-mapping boundaries; reduced MpvIpcClient deps to protocol-level concerns with event-based app reactions in main.ts; added mpv-service/mpv-transport tests for protocol dispatch, reconnect scheduling, and lifecycle regressions; documented expected event flow in docs/structure-roadmap.md. Split mpv-service internals into protocol, transport, and property/state-mapping boundaries; reduced MpvIpcClient deps to protocol-level concerns with event-based app reactions in main.ts; added mpv-service/mpv-transport tests for protocol dispatch, reconnect scheduling, and lifecycle regressions; documented expected event flow in docs/structure-roadmap.md.
Added mpv-service reconnect regression test that asserts a reconnect lifecycle replays mpv property bootstrap commands (`secondary-sub-visibility` reset, `observe_property`, and initial `get_property` state fetches) during reconnection. Added mpv-service reconnect regression test that asserts a reconnect lifecycle replays mpv property bootstrap commands (`secondary-sub-visibility` reset, `observe_property`, and initial `get_property` state fetches) during reconnection.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -27,9 +27,11 @@ ordinal: 36000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Split positioning.ts (513 LOC) — the only oversized file in the renderer — into focused modules. The rest of the renderer structure is already well-organized and does not need reorganization. Split positioning.ts (513 LOC) — the only oversized file in the renderer — into focused modules. The rest of the renderer structure is already well-organized and does not need reorganization.
## Current Renderer State (already good) ## Current Renderer State (already good)
- `renderer.ts` (241 lines) — pure composition, well-factored - `renderer.ts` (241 lines) — pure composition, well-factored
- `state.ts` (132 lines), `context.ts` (14 lines), `subtitle-render.ts` (206 lines) — reasonable sizes - `state.ts` (132 lines), `context.ts` (14 lines), `subtitle-render.ts` (206 lines) — reasonable sizes
- `handlers/keyboard.ts` (238 lines), `handlers/mouse.ts` (271 lines) — focused - `handlers/keyboard.ts` (238 lines), `handlers/mouse.ts` (271 lines) — focused
@@ -37,11 +39,15 @@ Split positioning.ts (513 LOC) — the only oversized file in the renderer — i
- Communication already uses explicit `ctx` pattern and function parameters, not globals - Communication already uses explicit `ctx` pattern and function parameters, not globals
## What Actually Needs Work ## What Actually Needs Work
`positioning.ts` mixes visible overlay positioning, invisible overlay positioning, MPV subtitle render metrics layout, and position persistence. These are distinct concerns that should be separate modules. `positioning.ts` mixes visible overlay positioning, invisible overlay positioning, MPV subtitle render metrics layout, and position persistence. These are distinct concerns that should be separate modules.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Split positioning.ts into at least 2 focused modules (e.g., visible-positioning and invisible-positioning, or by concern: layout, persistence, metrics). - [x] #1 Split positioning.ts into at least 2 focused modules (e.g., visible-positioning and invisible-positioning, or by concern: layout, persistence, metrics).
- [x] #2 No module exceeds 300 LOC. - [x] #2 No module exceeds 300 LOC.
- [x] #3 Existing overlay behavior (subtitle positioning, drag, invisible layer metrics) unchanged. - [x] #3 Existing overlay behavior (subtitle positioning, drag, invisible layer metrics) unchanged.
@@ -52,6 +58,7 @@ Split positioning.ts (513 LOC) — the only oversized file in the renderer — i
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
TASK-11 decomposition is implemented as part of this task by moving the prior monolithic mpv-metrics function into dedicated helper modules. TASK-11 decomposition is implemented as part of this task by moving the prior monolithic mpv-metrics function into dedicated helper modules.
Refactored renderer positioning into focused modules via a new controller barrel plus helpers: position-state, invisible-offset, invisible-layout, invisible-layout-metrics, and invisible-layout-helpers. Refactored renderer positioning into focused modules via a new controller barrel plus helpers: position-state, invisible-offset, invisible-layout, invisible-layout-metrics, and invisible-layout-helpers.
@@ -63,10 +70,13 @@ Validation done in this run: TypeScript build passes (`npm run build`). Manual b
`src/renderer/positioning.ts` now re-exports `createPositioningController` from `./positioning/controller.js`. `src/renderer/positioning.ts` now re-exports `createPositioningController` from `./positioning/controller.js`.
Acceptance updates: checked #1 (at least two focused modules) and #2 (no module >300 LOC). Acceptance updates: checked #1 (at least two focused modules) and #2 (no module >300 LOC).
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Completed the renderer positioning split. `src/renderer/positioning.ts` is now a thin re-export and logic is decomposed into focused modules (`controller.ts`, `position-state.ts`, `invisible-offset.ts`, `invisible-layout.ts`, `invisible-layout-helpers.ts`, `invisible-layout-metrics.ts`). Kept `renderer.ts` call-sites unchanged and preserved APIs via controller return shape. Verified by `npm run build` and user manual validation. Completed the renderer positioning split. `src/renderer/positioning.ts` is now a thin re-export and logic is decomposed into focused modules (`controller.ts`, `position-state.ts`, `invisible-offset.ts`, `invisible-layout.ts`, `invisible-layout-helpers.ts`, `invisible-layout-metrics.ts`). Kept `renderer.ts` call-sites unchanged and preserved APIs via controller return shape. Verified by `npm run build` and user manual validation.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -18,10 +18,13 @@ ordinal: 15000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
## Updated scope ## Updated scope
Implement SQLite-first immersion tracking for mining sessions optimized for speed/size and designed for a future external DB adapter. Implement SQLite-first immersion tracking for mining sessions optimized for speed/size and designed for a future external DB adapter.
## Runtime defaults ## Runtime defaults
- Flush batch policy: flush every `25` telemetry points or `500ms`. - Flush batch policy: flush every `25` telemetry points or `500ms`.
- SQLite: `journal_mode = WAL`, `synchronous = NORMAL`, `foreign_keys = ON`, `busy_timeout = 2500ms`. - SQLite: `journal_mode = WAL`, `synchronous = NORMAL`, `foreign_keys = ON`, `busy_timeout = 2500ms`.
- Query target: `<150ms p95` for session/video/time-window reads at ~1M rows. - Query target: `<150ms p95` for session/video/time-window reads at ~1M rows.
@@ -136,23 +139,28 @@ CREATE INDEX idx_rollups_month_video ON imm_monthly_rollups(rollup_month, video_
``` ```
Notes Notes
- Integer enums keep hot rows narrow and fast; resolve labels in app layer. - Integer enums keep hot rows narrow and fast; resolve labels in app layer.
- JSON fields are only for non-core overflow attributes (bounded by policy). - JSON fields are only for non-core overflow attributes (bounded by policy).
- `source_type`/`status`/`subtitle_mode` are compact enums and keep strings out of high-frequency rows. - `source_type`/`status`/`subtitle_mode` are compact enums and keep strings out of high-frequency rows.
- This schema is a v1 contract for TASK-32 adapter work later. - This schema is a v1 contract for TASK-32 adapter work later.
## Future portability ## Future portability
- Keep all analytics logic behind a storage interface in TASK-32. - Keep all analytics logic behind a storage interface in TASK-32.
- Keep raw SQL/DDL details inside adapters. - Keep raw SQL/DDL details inside adapters.
## Execution principle ## Execution principle
- Tracking is strictly asynchronous and must never block hot paths. - Tracking is strictly asynchronous and must never block hot paths.
- Tokenization/rendering pipelines must not await DB operations. - Tokenization/rendering pipelines must not await DB operations.
- If tracker queue is saturated, user experience must remain unchanged; telemetry may be dropped with bounded loss and explicit internal warning/logging. - If tracker queue is saturated, user experience must remain unchanged; telemetry may be dropped with bounded loss and explicit internal warning/logging.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 A SQLite database schema is defined and created automatically (or initialized on startup) for immersion tracking if not present. - [x] #1 A SQLite database schema is defined and created automatically (or initialized on startup) for immersion tracking if not present.
- [x] #2 Recorded events persist at least the following fields per session/item: video name, video directory/URL, video length, lines seen, words/tokens seen, cards mined. - [x] #2 Recorded events persist at least the following fields per session/item: video name, video directory/URL, video length, lines seen, words/tokens seen, cards mined.
- [x] #3 Tracking defaults to storing data in SQLite without requiring additional DB setup for local usage. - [x] #3 Tracking defaults to storing data in SQLite without requiring additional DB setup for local usage.
@@ -180,6 +188,7 @@ Notes
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Progress review (2026-02-17): `src/core/services/immersion-tracker-service.ts` now implements SQLite-first schema init, WAL/NORMAL pragmas, async queue + batch flush (25/500ms), queue cap 1000 with drop-oldest overflow policy, payload clamp (256B), retention pruning (events 7d, telemetry 30d, daily 365d, monthly 5y), startup+24h maintenance, weekly vacuum, rollup maintenance, and query paths (`getSessionSummaries`, `getSessionTimeline`, `getDailyRollups`, `getMonthlyRollups`, `getQueryHints`). Progress review (2026-02-17): `src/core/services/immersion-tracker-service.ts` now implements SQLite-first schema init, WAL/NORMAL pragmas, async queue + batch flush (25/500ms), queue cap 1000 with drop-oldest overflow policy, payload clamp (256B), retention pruning (events 7d, telemetry 30d, daily 365d, monthly 5y), startup+24h maintenance, weekly vacuum, rollup maintenance, and query paths (`getSessionSummaries`, `getSessionTimeline`, `getDailyRollups`, `getMonthlyRollups`, `getQueryHints`).
Metadata capture is implemented for local media via ffprobe/stat/SHA-256 (`captureVideoMetadataAsync`, `getLocalVideoMetadata`) with safe null handling for missing fields. Metadata capture is implemented for local media via ffprobe/stat/SHA-256 (`captureVideoMetadataAsync`, `getLocalVideoMetadata`) with safe null handling for missing fields.
@@ -195,10 +204,13 @@ Implementation docs now include query templates and storage behavior in `docs/im
Validation/tests expanded: `src/config/config.test.ts` now covers immersion tuning parse+fallback warnings; `src/core/services/immersion-tracker-service.test.ts` adds minimum persisted/retrievable field checks and configurable policy checks. Validation/tests expanded: `src/config/config.test.ts` now covers immersion tuning parse+fallback warnings; `src/core/services/immersion-tracker-service.test.ts` adds minimum persisted/retrievable field checks and configurable policy checks.
Verification run: `pnpm run build && node --test dist/config/config.test.js dist/core/services/immersion-tracker-service.test.js` passed; sqlite-specific tracker tests are skipped automatically in environments without `node:sqlite` support. Verification run: `pnpm run build && node --test dist/config/config.test.js dist/core/services/immersion-tracker-service.test.js` passed; sqlite-specific tracker tests are skipped automatically in environments without `node:sqlite` support.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [x] #1 SQLite tracking table(s), migration history table, and indices created as part of startup or init path. - [x] #1 SQLite tracking table(s), migration history table, and indices created as part of startup or init path.
- [x] #2 Unit/integration coverage (or validated test plan) confirms minimum fields are persisted and retrievable. - [x] #2 Unit/integration coverage (or validated test plan) confirms minimum fields are persisted and retrievable.
- [x] #3 README or docs updated with storage schema, retention defaults, and extension points. - [x] #3 README or docs updated with storage schema, retention defaults, and extension points.

View File

@@ -19,9 +19,11 @@ ordinal: 16000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add Anilist integration so the app can update user anime progress after watching, by porting the core functionality of `AzuredBlue/mpv-anilist-updater` into the Electron app. The initial implementation should focus on reliable sync of watch status/progress and be structured to support future Anilist features beyond updates. Add Anilist integration so the app can update user anime progress after watching, by porting the core functionality of `AzuredBlue/mpv-anilist-updater` into the Electron app. The initial implementation should focus on reliable sync of watch status/progress and be structured to support future Anilist features beyond updates.
Requirements: Requirements:
- Port the core behavior from `AzuredBlue/mpv-anilist-updater` needed for post-watch syncing into the Electron architecture. - Port the core behavior from `AzuredBlue/mpv-anilist-updater` needed for post-watch syncing into the Electron architecture.
- Authenticate and persist Anilist credentials securely in the desktop environment. - Authenticate and persist Anilist credentials securely in the desktop environment.
- Identify anime/media item and track watched status/progress based on existing video/session data. - Identify anime/media item and track watched status/progress based on existing video/session data.
@@ -32,7 +34,9 @@ Requirements:
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Application can authenticate with Anilist and store tokens securely for desktop user sessions. - [x] #1 Application can authenticate with Anilist and store tokens securely for desktop user sessions.
- [x] #2 Anilist update flow from existing local watch/session metadata can update animes watched progress after watching. - [x] #2 Anilist update flow from existing local watch/session metadata can update animes watched progress after watching.
- [x] #3 Core functionality equivalent to mpv-anilist-updater is implemented for this use case (progress/status sync) inside the Electron app. - [x] #3 Core functionality equivalent to mpv-anilist-updater is implemented for this use case (progress/status sync) inside the Electron app.
@@ -45,21 +49,27 @@ Requirements:
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Completed child tasks TASK-29.1 and TASK-29.2: secure token persistence/fallback and persistent retry queue with backoff/dead-letter are now implemented. Completed child tasks TASK-29.1 and TASK-29.2: secure token persistence/fallback and persistent retry queue with backoff/dead-letter are now implemented.
Implemented AniList control surfaces across CLI and IPC. CLI: added `--anilist-status`, `--anilist-logout`, `--anilist-setup`, `--anilist-retry-queue` parsing/help/dispatch/runtime wiring in `src/cli/args.ts`, `src/cli/help.ts`, `src/core/services/cli-command.ts`, `src/main/cli-runtime.ts`, and `src/main.ts`. IPC: added `anilist:get-status`, `anilist:clear-token`, `anilist:open-setup`, `anilist:get-queue-status`, `anilist:retry-now` handlers and dependency wiring in `src/core/services/ipc.ts`, `src/main/dependencies.ts`, and `src/main.ts`. Added retry queue tests in `src/core/services/anilist/anilist-update-queue.test.ts`; added token-store tests in `src/core/services/anilist/anilist-token-store.test.ts` with runtime guard for environments without Electron safeStorage; updated `package.json` test list and AniList command/channel docs in `docs/configuration.md`. Implemented AniList control surfaces across CLI and IPC. CLI: added `--anilist-status`, `--anilist-logout`, `--anilist-setup`, `--anilist-retry-queue` parsing/help/dispatch/runtime wiring in `src/cli/args.ts`, `src/cli/help.ts`, `src/core/services/cli-command.ts`, `src/main/cli-runtime.ts`, and `src/main.ts`. IPC: added `anilist:get-status`, `anilist:clear-token`, `anilist:open-setup`, `anilist:get-queue-status`, `anilist:retry-now` handlers and dependency wiring in `src/core/services/ipc.ts`, `src/main/dependencies.ts`, and `src/main.ts`. Added retry queue tests in `src/core/services/anilist/anilist-update-queue.test.ts`; added token-store tests in `src/core/services/anilist/anilist-token-store.test.ts` with runtime guard for environments without Electron safeStorage; updated `package.json` test list and AniList command/channel docs in `docs/configuration.md`.
Validation run: `pnpm run test:fast` passed (config + core dist suite). New AniList queue tests run in core suite; token-store tests are auto-skipped in plain Node environments where Electron `safeStorage` is unavailable (still active when safeStorage exists). Validation run: `pnpm run test:fast` passed (config + core dist suite). New AniList queue tests run in core suite; token-store tests are auto-skipped in plain Node environments where Electron `safeStorage` is unavailable (still active when safeStorage exists).
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Completed AniList post-watch integration in the Electron app with secure token lifecycle, post-watch progress sync, and persistent retry/backoff queue with dead-letter behavior. Added user-facing control surfaces via CLI (`--anilist-status`, `--anilist-logout`, `--anilist-setup`, `--anilist-retry-queue`) and IPC (`anilist:get-status`, `anilist:clear-token`, `anilist:open-setup`, `anilist:get-queue-status`, `anilist:retry-now`), plus docs and test coverage; validated via `pnpm run test:fast`. Completed AniList post-watch integration in the Electron app with secure token lifecycle, post-watch progress sync, and persistent retry/backoff queue with dead-letter behavior. Added user-facing control surfaces via CLI (`--anilist-status`, `--anilist-logout`, `--anilist-setup`, `--anilist-retry-queue`) and IPC (`anilist:get-status`, `anilist:clear-token`, `anilist:open-setup`, `anilist:get-queue-status`, `anilist:retry-now`), plus docs and test coverage; validated via `pnpm run test:fast`.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [x] #1 Core Anilist service module exists and is wired into application flow for post-watch updates. - [x] #1 Core Anilist service module exists and is wired into application flow for post-watch updates.
- [x] #2 OAuth/token lifecycle is implemented with safe local persistence and revocation/logout behavior. - [x] #2 OAuth/token lifecycle is implemented with safe local persistence and revocation/logout behavior.
- [x] #3 A retry/backoff and dead-letter strategy for failed syncs is implemented. - [x] #3 A retry/backoff and dead-letter strategy for failed syncs is implemented.

View File

@@ -16,7 +16,9 @@ ordinal: 18000
--- ---
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Access token is stored in secure local storage rather than plain config. - [ ] #1 Access token is stored in secure local storage rather than plain config.
- [ ] #2 Token connect/disconnect UX supports revocation/logout and re-auth setup. - [ ] #2 Token connect/disconnect UX supports revocation/logout and re-auth setup.
- [ ] #3 Startup flow validates token presence/state and surfaces actionable errors. - [ ] #3 Startup flow validates token presence/state and surfaces actionable errors.
@@ -26,11 +28,15 @@ ordinal: 18000
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Implemented secure AniList token lifecycle: config token persists to encrypted token store, stored token fallback is auto-resolved at runtime, and auth state source now distinguishes literal vs stored. Implemented secure AniList token lifecycle: config token persists to encrypted token store, stored token fallback is auto-resolved at runtime, and auth state source now distinguishes literal vs stored.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 Token lifecycle module wired into AniList update/auth flow. - [ ] #1 Token lifecycle module wired into AniList update/auth flow.
- [ ] #2 Unit/integration coverage added for token storage and logout paths. - [ ] #2 Unit/integration coverage added for token storage and logout paths.
<!-- DOD:END --> <!-- DOD:END -->

View File

@@ -16,7 +16,9 @@ ordinal: 19000
--- ---
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Failed AniList mutations are enqueued with retry metadata and exponential backoff. - [ ] #1 Failed AniList mutations are enqueued with retry metadata and exponential backoff.
- [ ] #2 Transient API/network failures retry automatically without blocking playback. - [ ] #2 Transient API/network failures retry automatically without blocking playback.
- [ ] #3 Queue is idempotent per media+episode update key and survives app restarts. - [ ] #3 Queue is idempotent per media+episode update key and survives app restarts.
@@ -26,11 +28,15 @@ ordinal: 19000
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Implemented persistent AniList retry queue with exponential backoff, dead-lettering after max attempts, queue snapshot state wiring, and retry processing integrated into playback-triggered AniList update flow. Implemented persistent AniList retry queue with exponential backoff, dead-lettering after max attempts, queue snapshot state wiring, and retry processing integrated into playback-triggered AniList update flow.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 Queue service integrated into AniList post-watch update path. - [ ] #1 Queue service integrated into AniList post-watch update path.
- [ ] #2 Backoff/retry behavior covered by unit tests. - [ ] #2 Backoff/retry behavior covered by unit tests.
<!-- DOD:END --> <!-- DOD:END -->

View File

@@ -14,12 +14,15 @@ ordinal: 1000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add keybinding that will toggle edit mode on the invisible subtitles allowing for fine-grained control over positioning. use arrow keys and vim hjkl for motion and enter/ctrl+s to save and esc to cancel Add keybinding that will toggle edit mode on the invisible subtitles allowing for fine-grained control over positioning. use arrow keys and vim hjkl for motion and enter/ctrl+s to save and esc to cancel
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
- Implemented invisible subtitle position edit mode toggle with movement/save/cancel controls. - Implemented invisible subtitle position edit mode toggle with movement/save/cancel controls.
- Added persistence for invisible subtitle offsets (`invisibleOffsetXPx`, `invisibleOffsetYPx`) alongside existing `yPercent` subtitle position state. - Added persistence for invisible subtitle offsets (`invisibleOffsetXPx`, `invisibleOffsetYPx`) alongside existing `yPercent` subtitle position state.
- Updated edit mode visuals to highlight invisible subtitle text using the same styling as debug visualization. - Updated edit mode visuals to highlight invisible subtitle text using the same styling as debug visualization.

View File

@@ -16,11 +16,15 @@ ordinal: 57000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Implement optional Jellyfin integration so SubMiner can act as a lightweight Jellyfin client similar to jellyfin-mpv-shim. The feature should support connecting to Jellyfin servers, browsing playable media, and launching playback through SubMiner, including direct play when possible and transparent transcoding when required. Implement optional Jellyfin integration so SubMiner can act as a lightweight Jellyfin client similar to jellyfin-mpv-shim. The feature should support connecting to Jellyfin servers, browsing playable media, and launching playback through SubMiner, including direct play when possible and transparent transcoding when required.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Add a configurable Jellyfin integration path that can be enabled/disabled without impacting core non-Jellyfin functionality. - [x] #1 Add a configurable Jellyfin integration path that can be enabled/disabled without impacting core non-Jellyfin functionality.
- [x] #2 Support authenticating against a user-selected Jellyfin server (server URL + credentials/token) and securely storing/reusing connection settings. - [x] #2 Support authenticating against a user-selected Jellyfin server (server URL + credentials/token) and securely storing/reusing connection settings.
- [x] #3 Allow discovery or manual selection of movies/tv shows/music libraries and playback items from the connected Jellyfin server. - [x] #3 Allow discovery or manual selection of movies/tv shows/music libraries and playback items from the connected Jellyfin server.
@@ -35,9 +39,11 @@ Implement optional Jellyfin integration so SubMiner can act as a lightweight Jel
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Status snapshot (2026-02-18): TASK-31 is mostly complete and now tracks remaining closure work only for #2 and #3. Status snapshot (2026-02-18): TASK-31 is mostly complete and now tracks remaining closure work only for #2 and #3.
Completed acceptance criteria and evidence: Completed acceptance criteria and evidence:
- #1 Optional/disabled Jellyfin integration boundary verified. - #1 Optional/disabled Jellyfin integration boundary verified.
- Added tests in `src/core/services/app-ready.test.ts`, `src/core/services/cli-command.test.ts`, `src/core/services/startup-bootstrap.test.ts`, `src/core/services/jellyfin-remote.test.ts`, and `src/config/config.test.ts` to prove disabled paths do not impact core non-Jellyfin functionality and that Jellyfin side effects are gated. - Added tests in `src/core/services/app-ready.test.ts`, `src/core/services/cli-command.test.ts`, `src/core/services/startup-bootstrap.test.ts`, `src/core/services/jellyfin-remote.test.ts`, and `src/config/config.test.ts` to prove disabled paths do not impact core non-Jellyfin functionality and that Jellyfin side effects are gated.
- #4 Jellyfin playback launch through existing pipeline verified. - #4 Jellyfin playback launch through existing pipeline verified.
@@ -52,20 +58,23 @@ Completed acceptance criteria and evidence:
- #9 Docs + key integration tests/mocks completed. - #9 Docs + key integration tests/mocks completed.
Key verification runs (all passing): Key verification runs (all passing):
- `pnpm run build` - `pnpm run build`
- `node --test dist/core/services/app-ready.test.js dist/core/services/cli-command.test.js dist/core/services/startup-bootstrap.test.js dist/core/services/jellyfin-remote.test.js dist/config/config.test.js` - `node --test dist/core/services/app-ready.test.js dist/core/services/cli-command.test.js dist/core/services/startup-bootstrap.test.js dist/core/services/jellyfin-remote.test.js dist/config/config.test.js`
- `node --test dist/core/services/jellyfin.test.js dist/core/services/cli-command.test.js` - `node --test dist/core/services/jellyfin.test.js dist/core/services/cli-command.test.js`
- `pnpm run test:fast` - `pnpm run test:fast`
Open acceptance criteria (remaining work): Open acceptance criteria (remaining work):
- #2 Authentication/settings persistence hardening and explicit lifecycle validation: - #2 Authentication/settings persistence hardening and explicit lifecycle validation:
1) login -> persist -> restart -> token reuse verification 1. login -> persist -> restart -> token reuse verification
2) token-expiry re-auth/recovery path verification 2. token-expiry re-auth/recovery path verification
3) document storage guarantees/edge cases 3. document storage guarantees/edge cases
- #3 Library discovery/manual selection UX closure across intended media scope: - #3 Library discovery/manual selection UX closure across intended media scope:
1) explicit verification for movies/TV/music discovery and selection paths 1. explicit verification for movies/TV/music discovery and selection paths
2) document any intentionally out-of-scope media types/flows 2. document any intentionally out-of-scope media types/flows
Task relationship: Task relationship:
- TASK-64 remains a focused implementation slice under this epic and provides foundational cast/remote playback work referenced by this task. - TASK-64 remains a focused implementation slice under this epic and provides foundational cast/remote playback work referenced by this task.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->

View File

@@ -16,11 +16,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Establish objective pass/fail evidence that Jellyfin playback preserves metadata and media-feature parity needed for TASK-31 acceptance criterion #7, so completion is based on repeatable test coverage rather than ad-hoc checks. Establish objective pass/fail evidence that Jellyfin playback preserves metadata and media-feature parity needed for TASK-31 acceptance criterion #7, so completion is based on repeatable test coverage rather than ad-hoc checks.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Automated test coverage verifies Jellyfin playback launch preserves title and episodic identity metadata when provided by server data. - [ ] #1 Automated test coverage verifies Jellyfin playback launch preserves title and episodic identity metadata when provided by server data.
- [ ] #2 Automated test coverage verifies subtitle and audio track selection behavior is preserved through playback launch and control paths. - [ ] #2 Automated test coverage verifies subtitle and audio track selection behavior is preserved through playback launch and control paths.
- [ ] #3 Automated test coverage verifies resume position/marker behavior is preserved for partially watched items. - [ ] #3 Automated test coverage verifies resume position/marker behavior is preserved for partially watched items.

View File

@@ -21,11 +21,15 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Validate real playback behavior against Jellyfin server media in a reproducible manual matrix, then capture evidence needed to confidently close TASK-31 acceptance criterion #7. Validate real playback behavior against Jellyfin server media in a reproducible manual matrix, then capture evidence needed to confidently close TASK-31 acceptance criterion #7.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Manual verification covers at least one movie and one TV episode and confirms playback shows expected title/episode identity where applicable. - [ ] #1 Manual verification covers at least one movie and one TV episode and confirms playback shows expected title/episode identity where applicable.
- [ ] #2 Manual verification confirms subtitle track selection behavior during playback, including enable/disable or track change flows where available. - [ ] #2 Manual verification confirms subtitle track selection behavior during playback, including enable/disable or track change flows where available.
- [ ] #3 Manual verification confirms audio track selection behavior during playback for media with multiple audio tracks. - [ ] #3 Manual verification confirms audio track selection behavior during playback for media with multiple audio tracks.

View File

@@ -20,11 +20,15 @@ priority: high
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Drive TASK-31 to completion by collecting and documenting verification evidence for the remaining acceptance criteria (#2, #5, #6, #8), then update criterion status based on observed behavior and any explicit scope limits. Drive TASK-31 to completion by collecting and documenting verification evidence for the remaining acceptance criteria (#2, #5, #6, #8), then update criterion status based on observed behavior and any explicit scope limits.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Authentication flow against a user-selected Jellyfin server is verified, including persisted/reused connection settings and token reuse behavior across restart. - [ ] #1 Authentication flow against a user-selected Jellyfin server is verified, including persisted/reused connection settings and token reuse behavior across restart.
- [ ] #2 Direct-play-first behavior is verified for compatible media profiles, with evidence that attempt order matches expected policy. - [ ] #2 Direct-play-first behavior is verified for compatible media profiles, with evidence that attempt order matches expected policy.
- [ ] #3 Transcoding fallback behavior is verified for incompatible media, including correct transcode parameter handoff to playback. - [ ] #3 Transcoding fallback behavior is verified for incompatible media, including correct transcode parameter handoff to playback.

View File

@@ -19,32 +19,38 @@ priority: low
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
## Scope ## Scope
Create a storage abstraction for immersion analytics so existing SQLite-first tracking can evolve to external backends (PostgreSQL/MySQL/other) without rewriting core analytics behavior. Create a storage abstraction for immersion analytics so existing SQLite-first tracking can evolve to external backends (PostgreSQL/MySQL/other) without rewriting core analytics behavior.
## Backend portability and performance contract ## Backend portability and performance contract
- Define a canonical interface that avoids SQL dialect leakage and returns stable query result shapes for session, video, and trend analytics. - Define a canonical interface that avoids SQL dialect leakage and returns stable query result shapes for session, video, and trend analytics.
- Decouple all `TASK-28` persistence callers from raw SQLite access behind a repository/adapter boundary. - Decouple all `TASK-28` persistence callers from raw SQLite access behind a repository/adapter boundary.
- Keep domain model and query DTOs backend-agnostic; SQL specifics live in adapters. - Keep domain model and query DTOs backend-agnostic; SQL specifics live in adapters.
## Target architecture ## Target architecture
- Add provider config: `storage.provider` default `sqlite`. - Add provider config: `storage.provider` default `sqlite`.
- Use dependency injection/service factory to select adapter at startup. - Use dependency injection/service factory to select adapter at startup.
- Add adapter contract tests to validate `Session`, `Video`, `Telemetry`, `Event`, and `Rollup` operations behave identically across backends. - Add adapter contract tests to validate `Session`, `Video`, `Telemetry`, `Event`, and `Rollup` operations behave identically across backends.
- Include migration and rollout contract with compatibility/rollback notes. - Include migration and rollout contract with compatibility/rollback notes.
## Numeric operational constraints to preserve (from TASK-28) ## Numeric operational constraints to preserve (from TASK-28)
- All adapters must support write batching (or equivalent) with flush cadence equivalent to 25 records or 500ms. - All adapters must support write batching (or equivalent) with flush cadence equivalent to 25 records or 500ms.
- All adapters must enforce bounded in-memory write queue (default 1000 rows) and explicit overflow policy. - All adapters must enforce bounded in-memory write queue (default 1000 rows) and explicit overflow policy.
- All adapters should preserve index/query shapes needed for ~150ms p95 read targets on session/video/time-window queries at ~1M events. - All adapters should preserve index/query shapes needed for ~150ms p95 read targets on session/video/time-window queries at ~1M events.
- All adapters should support retention semantics equivalent to: events 7d, telemetry 30d, daily rollups 365d, monthly rollups 5y, and prune-on-startup + every 24h + idle vacuum schedule. - All adapters should support retention semantics equivalent to: events 7d, telemetry 30d, daily rollups 365d, monthly rollups 5y, and prune-on-startup + every 24h + idle vacuum schedule.
## Async and isolation constraint ## Async and isolation constraint
- Adapter API must support enqueue/write-queue semantics so tokenization/render loops never block on persistence. - Adapter API must support enqueue/write-queue semantics so tokenization/render loops never block on persistence.
- Background worker owns DB I/O; storage adapter exposes non-blocking API surface to tracking pipeline. - Background worker owns DB I/O; storage adapter exposes non-blocking API surface to tracking pipeline.
Acceptance Criteria: ## Acceptance Criteria:
--------------------------------------------------
- [ ] #1 Define a stable `ImmersionTrackingStore` interface covering session lifecycle, telemetry counters, event writes, and analytics queries (timeline, video stats, throughput, and streak/trend summaries). - [ ] #1 Define a stable `ImmersionTrackingStore` interface covering session lifecycle, telemetry counters, event writes, and analytics queries (timeline, video stats, throughput, and streak/trend summaries).
- [ ] #2 Implement a DI-bound storage repository that encapsulates all DB interaction behind the interface. - [ ] #2 Implement a DI-bound storage repository that encapsulates all DB interaction behind the interface.
- [ ] #3 Refactor `TASK-28`-related data writes/reads in the tracking pipeline to depend on the abstraction (not raw SQLite calls). - [ ] #3 Refactor `TASK-28`-related data writes/reads in the tracking pipeline to depend on the abstraction (not raw SQLite calls).
@@ -55,8 +61,8 @@ Acceptance Criteria:
- [ ] #8 Expose retention and write profile defaults in backend contracts: 25 events/500ms batching, queue cap 1000, event payload cap 256B, overflow policy, and retention windows equivalent to TASK-28. - [ ] #8 Expose retention and write profile defaults in backend contracts: 25 events/500ms batching, queue cap 1000, event payload cap 256B, overflow policy, and retention windows equivalent to TASK-28.
- [ ] #9 Preserve performance contract semantics in adapters: query/index assumptions for sub-150ms p95 local reads on ~1M event scale and same read-path shapes as TASK-28. - [ ] #9 Preserve performance contract semantics in adapters: query/index assumptions for sub-150ms p95 local reads on ~1M event scale and same read-path shapes as TASK-28.
Definition of Done: ## Definition of Done:
--------------------------------------------------
- [ ] #1 Storage interface with required method signatures and query contracts is documented in code and backlog docs. - [ ] #1 Storage interface with required method signatures and query contracts is documented in code and backlog docs.
- [ ] #2 Default SQLite adapter remains the primary implementation and passes existing/ planned immersion tracking expectations. - [ ] #2 Default SQLite adapter remains the primary implementation and passes existing/ planned immersion tracking expectations.
- [ ] #3 Non-SQLite implementation path is explicitly represented in config and adapter scaffolding. - [ ] #3 Non-SQLite implementation path is explicitly represented in config and adapter scaffolding.
@@ -66,7 +72,9 @@ Definition of Done:
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Define a stable `ImmersionTrackingStore` interface covering session lifecycle, telemetry counters, event writes, and analytics queries (timeline, video stats, throughput, and streak/trend summaries). - [ ] #1 Define a stable `ImmersionTrackingStore` interface covering session lifecycle, telemetry counters, event writes, and analytics queries (timeline, video stats, throughput, and streak/trend summaries).
- [ ] #2 Implement a DI-bound storage repository that encapsulates all DB interaction behind the interface. - [ ] #2 Implement a DI-bound storage repository that encapsulates all DB interaction behind the interface.
- [ ] #3 Refactor `TASK-28`-related data writes/reads in the tracking pipeline to depend on the abstraction (not raw SQLite calls). - [ ] #3 Refactor `TASK-28`-related data writes/reads in the tracking pipeline to depend on the abstraction (not raw SQLite calls).
@@ -83,11 +91,15 @@ Definition of Done:
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Priority deferred from medium to low: this is premature until TASK-28 (SQLite tracking) ships and a concrete second backend need emerges. The SQLite-first design in TASK-28 already accounts for future portability via schema contracts and adapter boundaries. Revisit after TASK-28 has been in use. Priority deferred from medium to low: this is premature until TASK-28 (SQLite tracking) ships and a concrete second backend need emerges. The SQLite-first design in TASK-28 already accounts for future portability via schema contracts and adapter boundaries. Revisit after TASK-28 has been in use.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 Storage interface with required method signatures and query contracts is documented in code and backlog docs. - [ ] #1 Storage interface with required method signatures and query contracts is documented in code and backlog docs.
- [ ] #2 Default SQLite adapter remains the primary implementation and passes existing/ planned immersion tracking expectations. - [ ] #2 Default SQLite adapter remains the primary implementation and passes existing/ planned immersion tracking expectations.
- [ ] #3 Non-SQLite implementation path is explicitly represented in config and adapter scaffolding. - [ ] #3 Non-SQLite implementation path is explicitly represented in config and adapter scaffolding.

View File

@@ -19,11 +19,15 @@ ordinal: 31000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
In normal operation, Electron should not spam logs while waiting for mpv socket connection. Emit mpv socket connection logs only when app logging level is debug. In regular use, keep connection attempts silent while waiting, and log exactly once when the socket connects successfully. In normal operation, Electron should not spam logs while waiting for mpv socket connection. Emit mpv socket connection logs only when app logging level is debug. In regular use, keep connection attempts silent while waiting, and log exactly once when the socket connects successfully.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 When logging level is not debug, do not emit logs for mpv socket connection attempts, retries, or wait loops. - [ ] #1 When logging level is not debug, do not emit logs for mpv socket connection attempts, retries, or wait loops.
- [ ] #2 In non-debug mode, the app should silently wait for mpv socket readiness instead of printing connection-loop noise. - [ ] #2 In non-debug mode, the app should silently wait for mpv socket readiness instead of printing connection-loop noise.
- [ ] #3 Log exactly one concise INFO log entry when a mpv socket connection succeeds (e.g., per lifecycle attempt/session). - [ ] #3 Log exactly one concise INFO log entry when a mpv socket connection succeeds (e.g., per lifecycle attempt/session).
@@ -35,11 +39,15 @@ In normal operation, Electron should not spam logs while waiting for mpv socket
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Implemented debug-gated MPV socket noise suppression in normal mode while preserving reconnect behavior. Added an internal check for SUBMINER_LOG_LEVEL==='debug' and wrapped socket reconnect-attempt, close, and error logs so regular startup/reconnect loops no longer emit per-interval messages unless debug logging is enabled. Kept existing connection-success flow unchanged. Validation: `pnpm run build`, `node --test dist/core/services/mpv-service.test.js`. Implemented debug-gated MPV socket noise suppression in normal mode while preserving reconnect behavior. Added an internal check for SUBMINER_LOG_LEVEL==='debug' and wrapped socket reconnect-attempt, close, and error logs so regular startup/reconnect loops no longer emit per-interval messages unless debug logging is enabled. Kept existing connection-success flow unchanged. Validation: `pnpm run build`, `node --test dist/core/services/mpv-service.test.js`.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 No connection-attempt/connect-wait logs are produced in non-debug mode. - [ ] #1 No connection-attempt/connect-wait logs are produced in non-debug mode.
- [ ] #2 Exactly one success log is produced when connection is established in non-debug mode. - [ ] #2 Exactly one success log is produced when connection is established in non-debug mode.
- [ ] #3 Debug mode continues to emit detailed connection logs as before. - [ ] #3 Debug mode continues to emit detailed connection logs as before.

View File

@@ -14,11 +14,15 @@ dependencies: []
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Implement an in-app episode browser invoked by Ctrl+E when mpv is open and connected to the Electron UI. The viewer should use the currently supplied directory (if app was launched with one) or fallback to the parent directory of the currently playing video. It should enumerate all available video files in target directory and sort them deterministically, then display them in a polished list/gallery with thumbnails in the Electron UI. Thumbnail behavior should prioritize existing matching images in the directory; otherwise generate thumbnails asynchronously in the background and update the modal as they become available. The same menu infrastructure should be shared with the planned Jellyfin integration and designed so it can display additional Jellyfin-sourced metadata without UI rewrites. It should also support launching/using an alternate picker mode compatible with external launcher UX patterns (e.g., via fzf/rofi), showing the same episode list/metadata in those contexts. Implement an in-app episode browser invoked by Ctrl+E when mpv is open and connected to the Electron UI. The viewer should use the currently supplied directory (if app was launched with one) or fallback to the parent directory of the currently playing video. It should enumerate all available video files in target directory and sort them deterministically, then display them in a polished list/gallery with thumbnails in the Electron UI. Thumbnail behavior should prioritize existing matching images in the directory; otherwise generate thumbnails asynchronously in the background and update the modal as they become available. The same menu infrastructure should be shared with the planned Jellyfin integration and designed so it can display additional Jellyfin-sourced metadata without UI rewrites. It should also support launching/using an alternate picker mode compatible with external launcher UX patterns (e.g., via fzf/rofi), showing the same episode list/metadata in those contexts.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Pressing Ctrl+E in connected mode opens an episode viewer modal and closes/overlays correctly in the Electron app. - [ ] #1 Pressing Ctrl+E in connected mode opens an episode viewer modal and closes/overlays correctly in the Electron app.
- [ ] #2 Episode browser source directory is resolved from CLI-provided path when present, else from currently playing video's parent directory. - [ ] #2 Episode browser source directory is resolved from CLI-provided path when present, else from currently playing video's parent directory.
- [ ] #3 Browser enumerates all supported video files in target directory and sorts them deterministically (e.g., natural/season-episode aware when possible). - [ ] #3 Browser enumerates all supported video files in target directory and sorts them deterministically (e.g., natural/season-episode aware when possible).
@@ -34,7 +38,9 @@ Implement an in-app episode browser invoked by Ctrl+E when mpv is open and conne
<!-- AC:END --> <!-- AC:END -->
## Definition of Done ## Definition of Done
<!-- DOD:BEGIN --> <!-- DOD:BEGIN -->
- [ ] #1 Feature supports Ctrl+E invocation from connected mpv session. - [ ] #1 Feature supports Ctrl+E invocation from connected mpv session.
- [ ] #2 Directory fallback behavior is implemented and validated with both passed-in and default paths. - [ ] #2 Directory fallback behavior is implemented and validated with both passed-in and default paths.
- [ ] #3 Video listing excludes unsupported formats and is correctly sorted. - [ ] #3 Video listing excludes unsupported formats and is correctly sorted.

View File

@@ -17,11 +17,15 @@ ordinal: 17000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
CI should focus on build, test, and type-check validation and should not enforce fixed-size implementation ceilings. CI should focus on build, test, and type-check validation and should not enforce fixed-size implementation ceilings.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 CI is still triggered on `push` and `pull_request` to `main`. - [x] #1 CI is still triggered on `push` and `pull_request` to `main`.
- [x] #2 A canonical test entrypoint is added (`pnpm test`) and executed in CI, or CI explicitly runs equivalent test commands. - [x] #2 A canonical test entrypoint is added (`pnpm test`) and executed in CI, or CI explicitly runs equivalent test commands.
- [x] #3 CI focuses on functional validation (build, tests, type checks) without hardcoded size gates. - [x] #3 CI focuses on functional validation (build, tests, type checks) without hardcoded size gates.
@@ -34,6 +38,7 @@ CI should focus on build, test, and type-check validation and should not enforce
## Implementation Plan ## Implementation Plan
<!-- SECTION:PLAN:BEGIN --> <!-- SECTION:PLAN:BEGIN -->
1. Add a root `pnpm test` script that runs both `test:config` and `test:core`, or keep CI explicit on these two commands. 1. Add a root `pnpm test` script that runs both `test:config` and `test:core`, or keep CI explicit on these two commands.
2. Add explicit type-check step (`pnpm exec tsc --noEmit`) unless `pnpm run build` is accepted as the intended check. 2. Add explicit type-check step (`pnpm exec tsc --noEmit`) unless `pnpm run build` is accepted as the intended check.
3. Confirm no hardcoded size gates are treated as mandatory CI quality gates. 3. Confirm no hardcoded size gates are treated as mandatory CI quality gates.
@@ -44,5 +49,7 @@ CI should focus on build, test, and type-check validation and should not enforce
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Updated `.github/workflows/ci.yml` to complete the CI contract without hardcoded size gates: added explicit `pnpm exec tsc --noEmit`, switched test execution to a canonical `pnpm test`, and kept build verification on `pnpm run build` on `ubuntu-latest` for `push`/`pull_request` to `main`. Also removed CI line-count gate enforcement by deleting `check:main-lines*` scripts from `package.json` and removing `scripts/check-main-lines.sh` from the repo. The workflow remains Linux-only by design and continues to show PR checks. Updated `.github/workflows/ci.yml` to complete the CI contract without hardcoded size gates: added explicit `pnpm exec tsc --noEmit`, switched test execution to a canonical `pnpm test`, and kept build verification on `pnpm run build` on `ubuntu-latest` for `push`/`pull_request` to `main`. Also removed CI line-count gate enforcement by deleting `check:main-lines*` scripts from `package.json` and removing `scripts/check-main-lines.sh` from the repo. The workflow remains Linux-only by design and continues to show PR checks.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -17,15 +17,18 @@ ordinal: 20000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Replace ad-hoc console.log/console.error calls throughout the codebase with a lightweight structured logger that supports configurable verbosity levels (debug, info, warn, error). Replace ad-hoc console.log/console.error calls throughout the codebase with a lightweight structured logger that supports configurable verbosity levels (debug, info, warn, error).
## Motivation ## Motivation
- TASK-33 (restrict mpv socket logs) is a symptom of a broader problem: no log-level filtering - TASK-33 (restrict mpv socket logs) is a symptom of a broader problem: no log-level filtering
- Debugging production issues requires grepping through noisy output - Debugging production issues requires grepping through noisy output
- Users report log spam in normal operation - Users report log spam in normal operation
- No way to enable verbose logging for bug reports without code changes - No way to enable verbose logging for bug reports without code changes
## Scope ## Scope
1. Create a minimal logger module (no external dependencies needed) with `debug`, `info`, `warn`, `error` levels 1. Create a minimal logger module (no external dependencies needed) with `debug`, `info`, `warn`, `error` levels
2. Add a config option for log verbosity (default: `info`) 2. Add a config option for log verbosity (default: `info`)
3. Add a CLI flag to control logging verbosity (`--log-level`) while keeping `--debug` as app/dev mode. 3. Add a CLI flag to control logging verbosity (`--log-level`) while keeping `--debug` as app/dev mode.
@@ -33,6 +36,7 @@ Replace ad-hoc console.log/console.error calls throughout the codebase with a li
5. Include context tags (service name, operation) in log output for filterability 5. Include context tags (service name, operation) in log output for filterability
## Design constraints ## Design constraints
- Zero external dependencies — use a simple wrapper over console methods - Zero external dependencies — use a simple wrapper over console methods
- Must not impact hot-path performance (subtitle rendering, tokenization) - Must not impact hot-path performance (subtitle rendering, tokenization)
- Log level should be changeable at runtime via config hot-reload if that feature exists - Log level should be changeable at runtime via config hot-reload if that feature exists
@@ -40,7 +44,9 @@ Replace ad-hoc console.log/console.error calls throughout the codebase with a li
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 A logger module exists with debug/info/warn/error levels. - [x] #1 A logger module exists with debug/info/warn/error levels.
- [x] #2 Config option controls default verbosity level. - [x] #2 Config option controls default verbosity level.
- [x] #3 CLI `--log-level` override config. - [x] #3 CLI `--log-level` override config.
@@ -53,17 +59,19 @@ Replace ad-hoc console.log/console.error calls throughout the codebase with a li
## Implementation Plan ## Implementation Plan
<!-- SECTION:PLAN:BEGIN --> <!-- SECTION:PLAN:BEGIN -->
1) Audit remaining runtime console calls and classify by target (core runtime vs help/UI/test-only).
2) Keep `--debug` scoped to Electron app/dev mode only; `--log-level` controls logging verbosity. 1. Audit remaining runtime console calls and classify by target (core runtime vs help/UI/test-only).
3) Add tests for parsing and startup to keep logging override behavior stable. 2. Keep `--debug` scoped to Electron app/dev mode only; `--log-level` controls logging verbosity.
4) Migrate remaining non-user-facing `console.*` calls in core paths (especially tokenization, jimaku, config generation, electron-backend/notifications) to logger and include context via child loggers. 3. Add tests for parsing and startup to keep logging override behavior stable.
5) Ensure mpv-related connection/reconnect messages use debug level; keep user-facing success/failure outputs when intended. 4. Migrate remaining non-user-facing `console.*` calls in core paths (especially tokenization, jimaku, config generation, electron-backend/notifications) to logger and include context via child loggers.
6) Run focused test updates for impacted files, update task notes/acceptance criteria, and finalize task state. 5. Ensure mpv-related connection/reconnect messages use debug level; keep user-facing success/failure outputs when intended.
6. Run focused test updates for impacted files, update task notes/acceptance criteria, and finalize task state.
<!-- SECTION:PLAN:END --> <!-- SECTION:PLAN:END -->
## Implementation Notes ## Implementation Notes
<!-- SECTION:NOTES:BEGIN --> <!-- SECTION:NOTES:BEGIN -->
Updated logging override semantics so `--debug` stays an app/dev-only flag and `--log-level` is the CLI logging control. Updated logging override semantics so `--debug` stays an app/dev-only flag and `--log-level` is the CLI logging control.
Migrated remaining non-user-facing runtime `console.*` calls in core paths (`notification`, `config-gen`, `electron-backend`, `jimaku`, `tokenizer`) to structured logger Migrated remaining non-user-facing runtime `console.*` calls in core paths (`notification`, `config-gen`, `electron-backend`, `jimaku`, `tokenizer`) to structured logger
@@ -75,12 +83,15 @@ Updated help text and CLI parsing/tests for logging via `--log-level` while keep
Validated with focused test run: `node --test dist/cli/args.test.js dist/core/services/startup-bootstrap-service.test.js dist/core/services/cli-command-service.test.js` Validated with focused test run: `node --test dist/cli/args.test.js dist/core/services/startup-bootstrap-service.test.js dist/core/services/cli-command-service.test.js`
Build still passes via `pnpm run build` Build still passes via `pnpm run build`
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
TASK-36 is now complete; structured logging is consistently used in core runtime paths, with CLI log verbosity controlled by `--log-level`, while `--debug` remains an Electron app/dev-mode toggle. TASK-36 is now complete; structured logging is consistently used in core runtime paths, with CLI log verbosity controlled by `--log-level`, while `--debug` remains an Electron app/dev-mode toggle.
Backlog task moved to Done after verification of build and focused tests. Backlog task moved to Done after verification of build and focused tests.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -15,12 +15,15 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Add a top-level error boundary in the renderer orchestrator that catches unhandled errors in modals and rendering logic, displays a user-friendly error message, and recovers without crashing the overlay. Add a top-level error boundary in the renderer orchestrator that catches unhandled errors in modals and rendering logic, displays a user-friendly error message, and recovers without crashing the overlay.
## Motivation ## Motivation
If a renderer modal throws (e.g., jimaku API timeout, DOM manipulation error, malformed subtitle data), the entire overlay can become unresponsive. Since the overlay is transparent and positioned over mpv, a crashed renderer is invisible but blocks interaction. If a renderer modal throws (e.g., jimaku API timeout, DOM manipulation error, malformed subtitle data), the entire overlay can become unresponsive. Since the overlay is transparent and positioned over mpv, a crashed renderer is invisible but blocks interaction.
## Scope ## Scope
1. Wrap the renderer orchestrator's modal dispatch and subtitle rendering in try/catch boundaries 1. Wrap the renderer orchestrator's modal dispatch and subtitle rendering in try/catch boundaries
2. On error: log the error, dismiss the active modal, show a brief toast/notification in the overlay 2. On error: log the error, dismiss the active modal, show a brief toast/notification in the overlay
3. Ensure the overlay returns to a usable state (subtitle display, click-through, shortcuts all work) 3. Ensure the overlay returns to a usable state (subtitle display, click-through, shortcuts all work)
@@ -28,13 +31,16 @@ If a renderer modal throws (e.g., jimaku API timeout, DOM manipulation error, ma
5. Consider a "renderer health" heartbeat from main process that can force-reload the renderer if it becomes unresponsive 5. Consider a "renderer health" heartbeat from main process that can force-reload the renderer if it becomes unresponsive
## Design constraints ## Design constraints
- Error recovery must not disrupt mpv playback - Error recovery must not disrupt mpv playback
- Toast notifications should auto-dismiss and not interfere with subtitle layout - Toast notifications should auto-dismiss and not interfere with subtitle layout
- Errors should be logged with enough context for debugging (stack trace, active modal, last subtitle state) - Errors should be logged with enough context for debugging (stack trace, active modal, last subtitle state)
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Unhandled errors in modal flows are caught and do not crash the overlay. - [ ] #1 Unhandled errors in modal flows are caught and do not crash the overlay.
- [ ] #2 After an error, the overlay returns to a functional state (subtitles render, shortcuts work). - [ ] #2 After an error, the overlay returns to a functional state (subtitles render, shortcuts work).
- [ ] #3 A brief toast/notification informs the user that an error occurred. - [ ] #3 A brief toast/notification informs the user that an error occurred.

View File

@@ -15,12 +15,15 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Improve config validation to surface clear, actionable error messages at startup when the user's config file has invalid values, missing required fields, or type mismatches. Improve config validation to surface clear, actionable error messages at startup when the user's config file has invalid values, missing required fields, or type mismatches.
## Motivation ## Motivation
The project has a config schema with validation, but invalid configs (wrong types, unknown keys after an upgrade, deprecated fields) can cause cryptic failures deep in service initialization rather than being caught and reported clearly at launch. The project has a config schema with validation, but invalid configs (wrong types, unknown keys after an upgrade, deprecated fields) can cause cryptic failures deep in service initialization rather than being caught and reported clearly at launch.
## Scope ## Scope
1. Validate the full config against the schema at startup, before any services initialize 1. Validate the full config against the schema at startup, before any services initialize
2. Collect all validation errors (don't fail on the first one) and present them as a summary 2. Collect all validation errors (don't fail on the first one) and present them as a summary
3. Show the specific field path, expected type, and actual value for each error 3. Show the specific field path, expected type, and actual value for each error
@@ -29,13 +32,16 @@ The project has a config schema with validation, but invalid configs (wrong type
6. Allow the app to start with defaults for non-critical invalid fields, warning the user about the fallback 6. Allow the app to start with defaults for non-critical invalid fields, warning the user about the fallback
## Design constraints ## Design constraints
- Must not block startup for non-critical warnings (e.g., unknown extra keys) - Must not block startup for non-critical warnings (e.g., unknown extra keys)
- Critical errors (e.g., invalid Anki field mappings) should prevent startup with a clear message - Critical errors (e.g., invalid Anki field mappings) should prevent startup with a clear message
- Config file location should be shown in error output so users know what to edit - Config file location should be shown in error output so users know what to edit
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 All config fields are validated against the schema before service initialization. - [ ] #1 All config fields are validated against the schema before service initialization.
- [ ] #2 Validation errors show field path, expected type, and actual value. - [ ] #2 Validation errors show field path, expected type, and actual value.
- [ ] #3 Multiple errors are collected and shown together, not one at a time. - [ ] #3 Multiple errors are collected and shown together, not one at a time.

View File

@@ -15,12 +15,15 @@ priority: low
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Watch the config file for changes and apply non-destructive updates (colors, font sizes, subtitle modes, overlay opacity, keybindings) without requiring an app restart. Watch the config file for changes and apply non-destructive updates (colors, font sizes, subtitle modes, overlay opacity, keybindings) without requiring an app restart.
## Motivation ## Motivation
Currently all config is loaded at startup. Users tweaking visual settings (font size, colors, subtitle positioning) must restart the app after every change, which breaks their video session. Hot-reload for safe config values would dramatically improve the tuning experience. Currently all config is loaded at startup. Users tweaking visual settings (font size, colors, subtitle positioning) must restart the app after every change, which breaks their video session. Hot-reload for safe config values would dramatically improve the tuning experience.
## Scope ## Scope
1. Watch the config file using `fs.watch` or similar 1. Watch the config file using `fs.watch` or similar
2. On change, re-parse and re-validate the config 2. On change, re-parse and re-validate the config
3. Categorize config fields as hot-reloadable vs restart-required 3. Categorize config fields as hot-reloadable vs restart-required
@@ -29,6 +32,7 @@ Currently all config is loaded at startup. Users tweaking visual settings (font
6. Debounce file-change events (editors save multiple times rapidly) 6. Debounce file-change events (editors save multiple times rapidly)
## Hot-reloadable candidates ## Hot-reloadable candidates
- Font family, size, weight, color - Font family, size, weight, color
- Subtitle background opacity/color - Subtitle background opacity/color
- Secondary subtitle display mode - Secondary subtitle display mode
@@ -37,6 +41,7 @@ Currently all config is loaded at startup. Users tweaking visual settings (font
- AI translation provider settings - AI translation provider settings
## Restart-required (NOT hot-reloadable) ## Restart-required (NOT hot-reloadable)
- Anki field mappings (affects card creation pipeline) - Anki field mappings (affects card creation pipeline)
- MeCab path / tokenizer settings - MeCab path / tokenizer settings
- MPV socket path - MPV socket path
@@ -44,7 +49,9 @@ Currently all config is loaded at startup. Users tweaking visual settings (font
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Config file changes are detected automatically via file watcher. - [ ] #1 Config file changes are detected automatically via file watcher.
- [ ] #2 Hot-reloadable fields are applied immediately without restart. - [ ] #2 Hot-reloadable fields are applied immediately without restart.
- [ ] #3 Restart-required fields trigger a user-visible notification. - [ ] #3 Restart-required fields trigger a user-visible notification.

View File

@@ -14,11 +14,15 @@ ordinal: 55000
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Refine Mermaid charts in documentation (primarily architecture docs) to improve readability, grouping, and label clarity without changing system behavior. Refine Mermaid charts in documentation (primarily architecture docs) to improve readability, grouping, and label clarity without changing system behavior.
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [x] #1 Mermaid diagrams render successfully in VitePress docs build - [x] #1 Mermaid diagrams render successfully in VitePress docs build
- [x] #2 Diagrams have clearer grouping, edge labels, and flow direction - [x] #2 Diagrams have clearer grouping, edge labels, and flow direction
- [x] #3 No broken markdown or Mermaid syntax in updated docs - [x] #3 No broken markdown or Mermaid syntax in updated docs
@@ -27,5 +31,7 @@ Refine Mermaid charts in documentation (primarily architecture docs) to improve
## Final Summary ## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN --> <!-- SECTION:FINAL_SUMMARY:BEGIN -->
Improved Mermaid diagrams in docs/architecture.md by redesigning both flowcharts with clearer subgraphs, labeled edges, and consistent lifecycle/runtime separation. Verified successful rendering via `pnpm run docs:build` with no chunk-size warning regressions. Improved Mermaid diagrams in docs/architecture.md by redesigning both flowcharts with clearer subgraphs, labeled edges, and consistent lifecycle/runtime separation. Verified successful rendering via `pnpm run docs:build` with no chunk-size warning regressions.
<!-- SECTION:FINAL_SUMMARY:END --> <!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -17,12 +17,15 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Build a visual comprehension dashboard that renders per-video "comprehension heatmaps" showing which segments had high lookup density versus segments where the user understood everything without lookups. Build a visual comprehension dashboard that renders per-video "comprehension heatmaps" showing which segments had high lookup density versus segments where the user understood everything without lookups.
## Motivation ## Motivation
Immersion tracking data (TASK-28) captures lookup counts, words seen, and cards mined per time segment. Visualizing this data gives learners a powerful way to see their progress: early episodes of a show will be "hot" (many lookups), while later episodes should cool down as vocabulary grows. Immersion tracking data (TASK-28) captures lookup counts, words seen, and cards mined per time segment. Visualizing this data gives learners a powerful way to see their progress: early episodes of a show will be "hot" (many lookups), while later episodes should cool down as vocabulary grows.
## Features ## Features
1. **Per-video heatmap**: A timeline bar colored by lookup density (green = understood, yellow = some lookups, red = many lookups) 1. **Per-video heatmap**: A timeline bar colored by lookup density (green = understood, yellow = some lookups, red = many lookups)
2. **Cross-video trends**: Show comprehension improvement across episodes of the same series 2. **Cross-video trends**: Show comprehension improvement across episodes of the same series
3. **Session summary cards**: After each session, show a summary with key metrics (time watched, words seen, cards mined, comprehension estimate) 3. **Session summary cards**: After each session, show a summary with key metrics (time watched, words seen, cards mined, comprehension estimate)
@@ -30,11 +33,13 @@ Immersion tracking data (TASK-28) captures lookup counts, words seen, and cards
5. **Export**: Generate a shareable image or markdown summary 5. **Export**: Generate a shareable image or markdown summary
## Data sources ## Data sources
- `imm_session_telemetry` (lookup_count, words_seen per sample interval) - `imm_session_telemetry` (lookup_count, words_seen per sample interval)
- `imm_session_events` (individual lookup events with timestamps) - `imm_session_events` (individual lookup events with timestamps)
- `imm_daily_rollups` / `imm_monthly_rollups` for trend data - `imm_daily_rollups` / `imm_monthly_rollups` for trend data
## Implementation notes ## Implementation notes
- Could be rendered in a dedicated Electron window or an overlay modal - Could be rendered in a dedicated Electron window or an overlay modal
- Use canvas or SVG for the heatmap visualization - Use canvas or SVG for the heatmap visualization
- Consider a simple HTML report that can be opened in a browser for sharing - Consider a simple HTML report that can be opened in a browser for sharing
@@ -42,7 +47,9 @@ Immersion tracking data (TASK-28) captures lookup counts, words seen, and cards
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Per-video heatmap renders a timeline colored by lookup density. - [ ] #1 Per-video heatmap renders a timeline colored by lookup density.
- [ ] #2 Cross-video trend view shows comprehension change across episodes. - [ ] #2 Cross-video trend view shows comprehension change across episodes.
- [ ] #3 Session summary displays time watched, words seen, cards mined, and comprehension estimate. - [ ] #3 Session summary displays time watched, words seen, cards mined, and comprehension estimate.

View File

@@ -18,12 +18,15 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Compute a real-time difficulty score for each subtitle line using JLPT level data (TASK-23) and frequency dictionary data (TASK-25), and use this score to drive smart playback features. Compute a real-time difficulty score for each subtitle line using JLPT level data (TASK-23) and frequency dictionary data (TASK-25), and use this score to drive smart playback features.
## Motivation ## Motivation
Learners at different levels have different needs. N4 learners want to pause on N2+ lines; advanced learners want to skip easy content. A per-line difficulty score enables intelligent playback that adapts to the learner's level. Learners at different levels have different needs. N4 learners want to pause on N2+ lines; advanced learners want to skip easy content. A per-line difficulty score enables intelligent playback that adapts to the learner's level.
## Features ## Features
1. **Per-line difficulty score**: Combine JLPT levels and frequency ranks of tokens to produce a composite difficulty score (e.g., 1-5 scale or JLPT-equivalent label) 1. **Per-line difficulty score**: Combine JLPT levels and frequency ranks of tokens to produce a composite difficulty score (e.g., 1-5 scale or JLPT-equivalent label)
2. **Visual difficulty indicator**: Subtle color/icon on each subtitle line indicating difficulty 2. **Visual difficulty indicator**: Subtle color/icon on each subtitle line indicating difficulty
3. **Auto-pause on difficult lines**: Configurable threshold — pause playback when a line exceeds the user's set difficulty level 3. **Auto-pause on difficult lines**: Configurable threshold — pause playback when a line exceeds the user's set difficulty level
@@ -31,19 +34,23 @@ Learners at different levels have different needs. N4 learners want to pause on
5. **Difficulty trend within a video**: Show whether difficulty increases/decreases over the episode (useful for detecting climax scenes with complex dialogue) 5. **Difficulty trend within a video**: Show whether difficulty increases/decreases over the episode (useful for detecting climax scenes with complex dialogue)
## Scoring algorithm (suggested) ## Scoring algorithm (suggested)
- For each token in a line, look up JLPT level (N5=1, N1=5) and frequency rank - For each token in a line, look up JLPT level (N5=1, N1=5) and frequency rank
- Weight unknown words (not in Anki known-word cache from TASK-24) more heavily - Weight unknown words (not in Anki known-word cache from TASK-24) more heavily
- Composite score = weighted average of token difficulties, with bonus for line length and grammar complexity - Composite score = weighted average of token difficulties, with bonus for line length and grammar complexity
- Configurable weights so users can tune sensitivity - Configurable weights so users can tune sensitivity
## Design constraints ## Design constraints
- Scoring must run synchronously during subtitle rendering without perceptible latency - Scoring must run synchronously during subtitle rendering without perceptible latency
- Score computation should be cached per subtitle line (lines repeat on seeks/replays) - Score computation should be cached per subtitle line (lines repeat on seeks/replays)
- Auto-pause should be debounced to avoid rapid pause/unpause on sequential hard lines - Auto-pause should be debounced to avoid rapid pause/unpause on sequential hard lines
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Each subtitle line receives a difficulty score based on JLPT and frequency data. - [ ] #1 Each subtitle line receives a difficulty score based on JLPT and frequency data.
- [ ] #2 A visual indicator shows per-line difficulty in the overlay. - [ ] #2 A visual indicator shows per-line difficulty in the overlay.
- [ ] #3 Auto-pause triggers when a line exceeds the user's configured difficulty threshold. - [ ] #3 Auto-pause triggers when a line exceeds the user's configured difficulty threshold.

View File

@@ -16,12 +16,15 @@ priority: low
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Implement a "review mode" that replays short video clips from previously mined Anki cards, allowing users to review vocabulary in its original immersion context rather than as isolated text cards. Implement a "review mode" that replays short video clips from previously mined Anki cards, allowing users to review vocabulary in its original immersion context rather than as isolated text cards.
## Motivation ## Motivation
Traditional Anki review shows a sentence on a card. But the original context — hearing the word spoken, seeing the scene, feeling the emotion — is far more memorable. SubMiner already captures audio clips and screenshots for cards. This feature uses that data to create a video-based review experience. Traditional Anki review shows a sentence on a card. But the original context — hearing the word spoken, seeing the scene, feeling the emotion — is far more memorable. SubMiner already captures audio clips and screenshots for cards. This feature uses that data to create a video-based review experience.
## Workflow ## Workflow
1. User activates review mode (shortcut or menu) 1. User activates review mode (shortcut or menu)
2. SubMiner queries AnkiConnect for due/new cards from a configured deck 2. SubMiner queries AnkiConnect for due/new cards from a configured deck
3. For each card, SubMiner locates the source video and timestamp (stored in card metadata) 3. For each card, SubMiner locates the source video and timestamp (stored in card metadata)
@@ -31,6 +34,7 @@ Traditional Anki review shows a sentence on a card. But the original context —
7. User grades the card (easy/good/hard/again) via shortcuts, fed back to Anki via AnkiConnect 7. User grades the card (easy/good/hard/again) via shortcuts, fed back to Anki via AnkiConnect
## Technical considerations ## Technical considerations
- Requires source video files to still be accessible (local path stored in card) - Requires source video files to still be accessible (local path stored in card)
- Falls back gracefully if video is unavailable (show audio clip + screenshot instead) - Falls back gracefully if video is unavailable (show audio clip + screenshot instead)
- MPV can seek to timestamp and play a range (`--start`, `--end` flags or `loadfile` with options) - MPV can seek to timestamp and play a range (`--start`, `--end` flags or `loadfile` with options)
@@ -38,13 +42,16 @@ Traditional Anki review shows a sentence on a card. But the original context —
- Consider a playlist mode that queues multiple clips for batch review - Consider a playlist mode that queues multiple clips for batch review
## Design constraints ## Design constraints
- Must work with existing Anki card format (no retroactive card changes required) - Must work with existing Anki card format (no retroactive card changes required)
- Graceful degradation when source video is missing - Graceful degradation when source video is missing
- Review session should be pausable and resumable - Review session should be pausable and resumable
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Review mode queries AnkiConnect for due cards and locates source video + timestamp. - [ ] #1 Review mode queries AnkiConnect for due cards and locates source video + timestamp.
- [ ] #2 Video clips play with subtitles hidden, then revealed on user action. - [ ] #2 Video clips play with subtitles hidden, then revealed on user action.
- [ ] #3 Target word is highlighted in the revealed subtitle. - [ ] #3 Target word is highlighted in the revealed subtitle.

View File

@@ -16,12 +16,15 @@ priority: low
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
Support rendering the subtitle overlay on a secondary display at a larger, more readable size while the video plays full-screen on the primary monitor. Support rendering the subtitle overlay on a secondary display at a larger, more readable size while the video plays full-screen on the primary monitor.
## Motivation ## Motivation
For study-focused sessions, reading subtitles overlaid on video at normal size can cause eye strain. Users with multiple monitors would benefit from a dedicated subtitle display — larger font, clean background, with full tokenization and click-to-lookup functionality — while the video plays unobstructed on the main screen. For study-focused sessions, reading subtitles overlaid on video at normal size can cause eye strain. Users with multiple monitors would benefit from a dedicated subtitle display — larger font, clean background, with full tokenization and click-to-lookup functionality — while the video plays unobstructed on the main screen.
## Features ## Features
1. **Detached subtitle window**: A second Electron BrowserWindow that mirrors the current subtitle content 1. **Detached subtitle window**: A second Electron BrowserWindow that mirrors the current subtitle content
2. **Configurable placement**: User selects which monitor and position for the subtitle window 2. **Configurable placement**: User selects which monitor and position for the subtitle window
3. **Independent styling**: The detached window can have different font size, background opacity, and layout than the overlay 3. **Independent styling**: The detached window can have different font size, background opacity, and layout than the overlay
@@ -30,6 +33,7 @@ For study-focused sessions, reading subtitles overlaid on video at normal size c
6. **Toggle**: Shortcut to quickly enable/disable the secondary display 6. **Toggle**: Shortcut to quickly enable/disable the secondary display
## Technical considerations ## Technical considerations
- Electron supports multi-monitor via `screen.getAllDisplays()` and `BrowserWindow` bounds - Electron supports multi-monitor via `screen.getAllDisplays()` and `BrowserWindow` bounds
- The detached window should receive subtitle updates via IPC from the main process (same path as the overlay) - The detached window should receive subtitle updates via IPC from the main process (same path as the overlay)
- Overlay on the primary monitor could optionally be hidden when the detached window is active - Overlay on the primary monitor could optionally be hidden when the detached window is active
@@ -38,7 +42,9 @@ For study-focused sessions, reading subtitles overlaid on video at normal size c
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 A detached subtitle window can be opened on a secondary monitor. - [ ] #1 A detached subtitle window can be opened on a secondary monitor.
- [ ] #2 Subtitle content is synchronized in real-time between overlay and detached window. - [ ] #2 Subtitle content is synchronized in real-time between overlay and detached window.
- [ ] #3 Detached window has independently configurable font size and styling. - [ ] #3 Detached window has independently configurable font size and styling.

View File

@@ -17,12 +17,15 @@ priority: medium
## Description ## Description
<!-- SECTION:DESCRIPTION:BEGIN --> <!-- SECTION:DESCRIPTION:BEGIN -->
After a mining session, generate a visual summary report with key metrics that can be exported as an image or markdown for sharing on language learning communities. After a mining session, generate a visual summary report with key metrics that can be exported as an image or markdown for sharing on language learning communities.
## Motivation ## Motivation
Language learners love tracking and sharing their progress. A polished session summary creates a natural sharing loop and helps users stay motivated. Communities like r/LearnJapanese, TheMoeWay Discord, and Refold regularly share immersion stats. Language learners love tracking and sharing their progress. A polished session summary creates a natural sharing loop and helps users stay motivated. Communities like r/LearnJapanese, TheMoeWay Discord, and Refold regularly share immersion stats.
## Summary contents ## Summary contents
1. **Session metrics**: Duration watched, active time, lines seen, words encountered, cards mined 1. **Session metrics**: Duration watched, active time, lines seen, words encountered, cards mined
2. **Efficiency stats**: Cards per hour, words per minute, lookup hit rate 2. **Efficiency stats**: Cards per hour, words per minute, lookup hit rate
3. **Top looked-up words**: The N most-looked-up words in the session 3. **Top looked-up words**: The N most-looked-up words in the session
@@ -31,11 +34,13 @@ Language learners love tracking and sharing their progress. A polished session s
6. **Video context**: Show/episode name, thumbnail 6. **Video context**: Show/episode name, thumbnail
## Export formats ## Export formats
- **Image**: Rendered card-style graphic (PNG) suitable for social media sharing - **Image**: Rendered card-style graphic (PNG) suitable for social media sharing
- **Markdown**: Text summary for pasting into Discord/forums - **Markdown**: Text summary for pasting into Discord/forums
- **Clipboard**: One-click copy of the summary - **Clipboard**: One-click copy of the summary
## Implementation notes ## Implementation notes
- Generate the image using HTML-to-canvas in the renderer, or a Node canvas library - Generate the image using HTML-to-canvas in the renderer, or a Node canvas library
- Data sourced from TASK-28 immersion tracking tables - Data sourced from TASK-28 immersion tracking tables
- Summary could be shown automatically at session end (when mpv closes) or on demand via shortcut - Summary could be shown automatically at session end (when mpv closes) or on demand via shortcut
@@ -43,7 +48,9 @@ Language learners love tracking and sharing their progress. A polished session s
<!-- SECTION:DESCRIPTION:END --> <!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria ## Acceptance Criteria
<!-- AC:BEGIN --> <!-- AC:BEGIN -->
- [ ] #1 Session summary shows duration, lines seen, words encountered, and cards mined. - [ ] #1 Session summary shows duration, lines seen, words encountered, and cards mined.
- [ ] #2 Top looked-up words are listed in the summary. - [ ] #2 Top looked-up words are listed in the summary.
- [ ] #3 Summary is exportable as PNG image. - [ ] #3 Summary is exportable as PNG image.

Some files were not shown because too many files have changed in this diff Show More