diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..a2a4ce0 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,63 @@ +name: Docs + +on: + push: + branches: [main] + paths: + - 'docs/**' + - '.github/workflows/docs.yml' + - 'package.json' + - 'pnpm-lock.yaml' + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build docs + run: pnpm run docs:build + + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/.vitepress/dist + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 85a2433..5324fcb 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,5 @@ environment.toml .vitepress/dist/ docs/.vitepress/cache/ docs/.vitepress/dist/ +test/* +.worktrees/ diff --git a/.gitmodules b/.gitmodules index 968da6f..31ab7ff 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "vendor/texthooker-ui"] path = vendor/texthooker-ui url = https://github.com/ksyasuda/texthooker-ui.git + branch = subminer diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..1b3f6b5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,29 @@ + + + + +## BACKLOG WORKFLOW INSTRUCTIONS + +This project uses Backlog.md MCP for all task and project management activities. + +**CRITICAL GUIDANCE** + +- If your client supports MCP resources, read `backlog://workflow/overview` to understand when and how to use Backlog for this project. +- If your client only supports tools or the above request fails, call `backlog.get_workflow_overview()` tool to load the tool-oriented overview (it lists the matching guide tools). + +- **First time working here?** Read the overview resource IMMEDIATELY to learn the workflow +- **Already familiar?** You should have the overview cached ("## Backlog.md Overview (MCP)") +- **When to read it**: BEFORE creating tasks, or when you're unsure whether to track work + +These guides cover: + +- Decision framework for when to create tasks +- Search-first workflow to avoid duplicates +- Links to detailed guides for task creation, execution, and finalization +- MCP tools reference + +You MUST read the overview resource to understand the complete workflow. The information is NOT summarized here. + + + + diff --git a/Makefile b/Makefile index 381e2aa..a679f34 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help deps build install build-linux build-macos build-macos-unsigned install-linux install-macos install-plugin uninstall uninstall-linux uninstall-macos print-dirs pretty ensure-pnpm generate-config generate-example-config docs-dev docs-build docs-preview +.PHONY: help deps build install build-linux build-macos build-macos-unsigned clean install-linux install-macos install-plugin uninstall uninstall-linux uninstall-macos print-dirs pretty ensure-pnpm generate-config generate-example-config docs-dev docs docs-preview dev-start dev-start-macos dev-toggle dev-stop APP_NAME := subminer THEME_FILE := subminer.rasi @@ -48,8 +48,13 @@ help: " build-linux Build Linux AppImage" \ " build-macos Build macOS DMG/ZIP (signed if configured)" \ " build-macos-unsigned Build macOS DMG/ZIP without signing/notarization" \ + " clean Remove build artifacts (dist/, release/, AppImage, binary)" \ + " dev-start Build and launch local Electron app" \ + " dev-start-macos Build and launch local Electron app with macOS tracker backend" \ + " dev-toggle Toggle overlay in a running local Electron app" \ + " dev-stop Stop a running local Electron app" \ " docs-dev Run VitePress docs dev server" \ - " docs-build Build VitePress static docs" \ + " docs Build VitePress static docs" \ " docs-preview Preview built VitePress docs" \ " install-linux Install Linux wrapper/theme/app artifacts" \ " install-macos Install macOS wrapper/theme/app artifacts" \ @@ -126,6 +131,13 @@ build-macos-unsigned: deps @pnpm -C vendor/texthooker-ui build @pnpm run build:mac:unsigned +clean: + @printf '%s\n' "[INFO] Removing build artifacts" + @rm -f release/SubMiner-*.AppImage + @rm -f release/linux-unpacked/SubMiner + @rm -f "$(BINDIR)/subminer" "$(BINDIR)/SubMiner.AppImage" + @rm -rf dist release + generate-config: ensure-pnpm @pnpm run build @pnpm exec electron . --generate-config @@ -137,12 +149,26 @@ generate-example-config: ensure-pnpm docs-dev: ensure-pnpm @pnpm run docs:dev -docs-build: ensure-pnpm +docs: ensure-pnpm @pnpm run docs:build docs-preview: ensure-pnpm @pnpm run docs:preview +dev-start: ensure-pnpm + @pnpm run build + @pnpm exec electron . --start + +dev-start-macos: ensure-pnpm + @pnpm run build + @pnpm exec electron . --start --backend macos + +dev-toggle: ensure-pnpm + @pnpm exec electron . --toggle + +dev-stop: ensure-pnpm + @pnpm exec electron . --stop + install-linux: @printf '%s\n' "[INFO] Installing Linux wrapper/theme artifacts" diff --git a/OVERLAY_POSITIONING_FLOW.md b/OVERLAY_POSITIONING_FLOW.md deleted file mode 100644 index ac32603..0000000 --- a/OVERLAY_POSITIONING_FLOW.md +++ /dev/null @@ -1,53 +0,0 @@ -# Overlay Positioning Flow - -## 1) Window Bounds Flow (visible + invisible Electron windows) - -```mermaid -flowchart LR - A[Platform backend selection
src/window-trackers/index.ts] --> B[Tracker emits geometry
onWindowFound/onGeometryChange] - B --> C[updateOverlayBounds
src/main.ts] - C --> D[mainWindow.setBounds] - C --> E[invisibleWindow.setBounds] -``` - -## 2) Invisible Subtitle Layout Flow (mpv render metrics -> DOM layout) - -```mermaid -flowchart LR - A[mpv property changes
sub-pos, sub-font-size, osd-dimensions, etc.] --> B[MpvIpcClient parses events
src/main.ts] - B --> C[updateMpvSubtitleRenderMetrics
src/main.ts] - C --> D[broadcast mpv-subtitle-render-metrics:set] - D --> E[preload onMpvSubtitleRenderMetrics
src/preload.ts] - E --> F[renderer receives metrics event
src/renderer/renderer.ts] - F --> G[applyInvisibleSubtitleLayoutFromMpvMetrics] - G --> H[subtitleContainer/subtitleRoot inline styles updated] -``` - -## 3) Visible Subtitle Manual Position Flow - -```mermaid -flowchart LR - A[User right-click drags subtitle] --> B[setupDragging
src/renderer/renderer.ts] - B --> C[applyYPercent] - C --> D[saveSubtitlePosition IPC] - D --> E[saveSubtitlePosition in main
src/main.ts] - E --> F[load/broadcast subtitle-position:set] - F --> G[applyStoredSubtitlePosition in renderer] -``` - -## 4) Fallback Bounds Flow (tracker not ready) - -```mermaid -flowchart LR - A[windowTracker exists but not tracking] --> B["screen.getDisplayNearestPoint(cursor)"] - B --> C[display.workArea] - C --> D[updateOverlayBounds] -``` - -## Key Files - -- `src/main.ts` -- `src/renderer/renderer.ts` -- `src/preload.ts` -- `src/window-trackers/base-tracker.ts` -- `src/window-trackers/index.ts` diff --git a/README.md b/README.md index 2520e3c..99a8139 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,9 @@ An all-in-one sentence mining overlay for MPV with AnkiConnect and dictionary (Y - Yomitan integration for fast, on-screen lookups - Japanese text tokenization using MeCab with smart word boundary detection - Integrated texthooker-ui server for use with Yomitan -- Integrated websocket server (if [mpv_websocket](https://github.com/kuroahna/mpv_websocket) is not found) to send lines to the texthooker +- Integrated WebSocket server (if [mpv_websocket](https://github.com/kuroahna/mpv_websocket) is not found) to send lines to the texthooker - AnkiConnect integration for automatic card creation with media (audio/image) +- Invisible subtitle position edit mode (`Ctrl/Cmd+Shift+P`, arrow keys to adjust, `Enter`/`Ctrl+S` save, `Esc` cancel) ## Demo @@ -31,29 +32,31 @@ Optional but recommended: `yt-dlp`, `fzf`, `rofi`, `chafa`, `ffmpegthumbnailer`. ### Linux (AppImage) +Download the latest release from [GitHub Releases](https://github.com/ksyasuda/SubMiner/releases/latest): + ```bash -wget https://github.com/sudacode/subminer/releases/download/v1.0.0/subminer-1.0.0.AppImage -O ~/.local/bin/subminer.AppImage -chmod +x ~/.local/bin/subminer.AppImage -wget https://github.com/sudacode/subminer/releases/download/v1.0.0/subminer -O ~/.local/bin/subminer +wget https://github.com/ksyasuda/SubMiner/releases/download/v0.1.0/SubMiner-0.1.0.AppImage -O ~/.local/bin/SubMiner.AppImage +chmod +x ~/.local/bin/SubMiner.AppImage +wget https://github.com/ksyasuda/SubMiner/releases/download/v0.1.0/subminer -O ~/.local/bin/subminer chmod +x ~/.local/bin/subminer ``` -`subminer` uses a [Bun](https://bun.com) shebang, so `bun` must be on `PATH`. +The `subminer` wrapper uses a [Bun](https://bun.sh) shebang, so `bun` must be on `PATH`. -### From source +### From Source ```bash -git clone https://github.com/sudacode/subminer.git -cd subminer +git clone https://github.com/ksyasuda/SubMiner.git +cd SubMiner make build make install ``` -For macOS app bundle / signing / permissions details, use `docs/installation.md`. +For macOS builds, signing, and platform-specific details, see [docs/installation.md](docs/installation.md). ## Quick Start -1. Copy and customize [`config.example.jsonc`](config.example.jsonc) to `~/.config/SubMiner/config.jsonc`. +1. Copy and customize [`config.example.jsonc`](config.example.jsonc) to `$XDG_CONFIG_HOME/SubMiner/config.jsonc` (or `~/.config/SubMiner/config.jsonc`). 2. Start mpv with IPC enabled: ```bash @@ -85,28 +88,34 @@ subminer -T video.mkv # disable texthooker ```bash cp plugin/subminer.lua ~/.config/mpv/scripts/ cp plugin/subminer.conf ~/.config/mpv/script-opts/ +# or: make install-plugin ``` Requires mpv IPC: `--input-ipc-server=/tmp/subminer-socket` Default chord prefix: `y` (`y-y` menu, `y-s` start, `y-S` stop, `y-t` toggle visible layer). -Overlay Jimaku shortcut default: `Ctrl+Alt+J` (`shortcuts.openJimaku`). +Overlay Jimaku shortcut default: `Ctrl+Shift+J` (`shortcuts.openJimaku`). ## Documentation Detailed guides live in [`docs/`](docs/README.md): -- [Installation](docs/installation.md) -- [Usage](docs/usage.md) -- [Configuration](docs/configuration.md) -- [Development](docs/development.md) +- [Installation](docs/installation.md) — Platform requirements, AppImage/macOS/source installs, mpv plugin +- [Usage](docs/usage.md) — Script vs plugin workflow, keybindings, YouTube playback +- [Mining Workflow](docs/mining-workflow.md) — End-to-end mining guide, overlay layers, card creation +- [Configuration](docs/configuration.md) — Full config reference and option details +- [Anki Integration](docs/anki-integration.md) — AnkiConnect setup, field mapping, media generation +- [MPV Plugin](docs/mpv-plugin.md) — Chord keybindings, subminer.conf options, script messages +- [Troubleshooting](docs/troubleshooting.md) — Common issues and solutions +- [Development](docs/development.md) — Building, testing, contributing +- [Architecture](docs/architecture.md) — Service-oriented design, composition model, and modular renderer layout (`src/renderer/{modals,handlers,utils,...}`) ### Third-Party Components This project includes the following third-party components: -- **[Yomitan](https://github.com/yomidevs/yomitan)** - GPL-3.0 -- **[texthooker-ui](https://github.com/Renji-XD/texthooker-ui)** - MIT +- **[Yomitan](https://github.com/yomidevs/yomitan)** — GPL-3.0 +- **[texthooker-ui](https://github.com/Renji-XD/texthooker-ui)** — MIT ### Acknowledgments diff --git a/backlog/archive/milestones/m-0 - codebase-clarity-&-composability.md b/backlog/archive/milestones/m-0 - codebase-clarity-&-composability.md new file mode 100644 index 0000000..bfb2d13 --- /dev/null +++ b/backlog/archive/milestones/m-0 - codebase-clarity-&-composability.md @@ -0,0 +1,8 @@ +--- +id: m-0 +title: "Codebase Clarity & Composability" +--- + +## Description + +Improvements to code clarity, simplicity, and composability identified during the Feb 2026 codebase review. Focus on reducing monolithic files, eliminating duplication, and improving architectural boundaries. diff --git a/backlog/archive/tasks/task-19 - Enable-overlay-keybinds-whenever-app-runtime-is-active.md b/backlog/archive/tasks/task-19 - Enable-overlay-keybinds-whenever-app-runtime-is-active.md new file mode 100644 index 0000000..783ef19 --- /dev/null +++ b/backlog/archive/tasks/task-19 - Enable-overlay-keybinds-whenever-app-runtime-is-active.md @@ -0,0 +1,43 @@ +--- +id: TASK-19 +title: Enable overlay keybinds whenever app runtime is active +status: To Do +assignee: [] +created_date: '2026-02-12 08:47' +updated_date: '2026-02-12 09:40' +labels: [] +dependencies: [] +priority: high +--- + +## Description + + +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. + + +## Implementation Notes + + +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. + +Implemented fix in initializeOverlayRuntime: after setting overlayRuntimeInitialized = true, immediately call syncOverlayShortcuts() to register overlay keybinds for active runtime state. + +Follow-up from repro: startup path with --start did not initialize overlay runtime (commandNeedsOverlayRuntime excluded start), so overlay keybinds stayed unavailable until first overlay visibility command. + +Updated CLI runtime gating so --start initializes overlay runtime, which activates overlay shortcut registration immediately. + +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. + + +## Final Summary + + +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. + diff --git a/backlog/archive/tasks/task-20 - Implement-content-bounded-overlay-windows-and-decoupled-secondary-top-bar.md b/backlog/archive/tasks/task-20 - Implement-content-bounded-overlay-windows-and-decoupled-secondary-top-bar.md new file mode 100644 index 0000000..4b4182e --- /dev/null +++ b/backlog/archive/tasks/task-20 - Implement-content-bounded-overlay-windows-and-decoupled-secondary-top-bar.md @@ -0,0 +1,26 @@ +--- +id: TASK-20 +title: Implement content-bounded overlay windows and decoupled secondary top bar +status: To Do +assignee: [] +created_date: '2026-02-12 08:47' +updated_date: '2026-02-12 09:42' +labels: [] +dependencies: [] +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 Visible and invisible overlays use content-bounded sizing with padding/clamp/jitter protections and full-bounds fallback when measurements are unavailable. +- [ ] #4 Secondary subtitle top bar is decoupled from primary overlay visibility and follows mode-specific behavior. +- [ ] #5 Automated tests and manual validation matrix cover wrapping, style changes, monitor moves, tracker churn, and simultaneous overlay states. + diff --git a/backlog/archive/tasks/task-20.3 - Implement-content-bounded-sizing-algorithm-for-visible-and-invisible-overlay-windows.md b/backlog/archive/tasks/task-20.3 - Implement-content-bounded-sizing-algorithm-for-visible-and-invisible-overlay-windows.md new file mode 100644 index 0000000..2576f0d --- /dev/null +++ b/backlog/archive/tasks/task-20.3 - Implement-content-bounded-sizing-algorithm-for-visible-and-invisible-overlay-windows.md @@ -0,0 +1,28 @@ +--- +id: TASK-20.3 +title: >- + Implement content-bounded sizing algorithm for visible and invisible overlay + windows +status: To Do +assignee: [] +created_date: '2026-02-12 08:47' +updated_date: '2026-02-12 09:42' +labels: [] +dependencies: [] +parent_task_id: TASK-20 +priority: medium +--- + +## Description + + +Implement content-bounded sizing for visible/invisible windows using measured rects plus tracker origin, with robust clamping and jitter resistance. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 When no valid measurement exists, layer falls back to safe tracker/display bounds without breaking interaction. +- [ ] #4 Visible+invisible overlays can coexist without full-window overlap/input conflicts caused by shared fullscreen bounds. + diff --git a/backlog/archive/tasks/task-20.4 - Implement-dedicated-secondary-top-bar-overlay-window.md b/backlog/archive/tasks/task-20.4 - Implement-dedicated-secondary-top-bar-overlay-window.md new file mode 100644 index 0000000..8080fe2 --- /dev/null +++ b/backlog/archive/tasks/task-20.4 - Implement-dedicated-secondary-top-bar-overlay-window.md @@ -0,0 +1,26 @@ +--- +id: TASK-20.4 +title: Implement dedicated secondary top-bar overlay window +status: To Do +assignee: [] +created_date: '2026-02-12 09:43' +labels: [] +dependencies: [] +parent_task_id: TASK-20 +priority: medium +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 Secondary subtitle text/mode/style updates are routed directly to the secondary window renderer path. +- [ ] #4 Pointer passthrough/interaction behavior for secondary window is explicit and does not regress existing hover/selection interactions. +- [ ] #5 Window cleanup/lifecycle (create, close, restore) integrates with existing overlay runtime lifecycle. + diff --git a/backlog/archive/tasks/task-20.5 - Add-rollout-guards-tests-and-validation-matrix-for-content-bounded-overlays.md b/backlog/archive/tasks/task-20.5 - Add-rollout-guards-tests-and-validation-matrix-for-content-bounded-overlays.md new file mode 100644 index 0000000..347ac99 --- /dev/null +++ b/backlog/archive/tasks/task-20.5 - Add-rollout-guards-tests-and-validation-matrix-for-content-bounded-overlays.md @@ -0,0 +1,26 @@ +--- +id: TASK-20.5 +title: 'Add rollout guards, tests, and validation matrix for content-bounded overlays' +status: To Do +assignee: [] +created_date: '2026-02-12 09:43' +labels: [] +dependencies: [] +parent_task_id: TASK-20 +priority: medium +--- + +## Description + + +Add safety controls and verification coverage for the new content-bounded overlay architecture and secondary top-bar window. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 Manual validation checklist documents and verifies wrap/no-wrap, style changes, monitor moves, tracker churn, modal interactions, and simultaneous overlay states. +- [ ] #4 Regression checks confirm existing single-layer and startup/shutdown behavior remain stable. +- [ ] #5 Task includes explicit pass/fail notes from validation run(s). + diff --git a/backlog/archive/tasks/task-30 - Enable-anime-streaming-via-extension-repos-with-configurable-mpv-playback-flow.md b/backlog/archive/tasks/task-30 - Enable-anime-streaming-via-extension-repos-with-configurable-mpv-playback-flow.md new file mode 100644 index 0000000..03e8a00 --- /dev/null +++ b/backlog/archive/tasks/task-30 - Enable-anime-streaming-via-extension-repos-with-configurable-mpv-playback-flow.md @@ -0,0 +1,47 @@ +--- +id: TASK-30 +title: Enable anime streaming via extension repos with configurable mpv playback flow +status: To Do +assignee: [] +created_date: '2026-02-13 18:32' +updated_date: '2026-02-13 18:34' +labels: [] +dependencies: [] +priority: high +--- + +## Description + + +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). + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 Resolve an episode selection to at least one playable stream URL candidate with playback metadata when available. +- [ ] #4 Provide an interactive user flow in the app to search/select episode and choose stream source. +- [ ] #5 Play the selected stream by invoking the existing mpv command path. +- [ ] #6 Support launching the flow from mpv interactions (keyboard/menu) by forwarding a command/event into the renderer modal flow. +- [ ] #7 Add error states for empty results, no playable source, and repository failures, with clear user messages. + + +## Implementation Notes + + +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. + + +## Definition of Done + +- [ ] #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. +- [ ] #3 Play command path uses existing mpv IPC/runtime helpers. +- [ ] #4 Documentation includes how to configure extension repos and optional auth/headers. +- [ ] #5 Feature is gated behind a config flag and can be disabled cleanly. + diff --git a/backlog/archive/tasks/task-30.1 - Design-extension-source-config-model-and-defaults.md b/backlog/archive/tasks/task-30.1 - Design-extension-source-config-model-and-defaults.md new file mode 100644 index 0000000..c91e6e1 --- /dev/null +++ b/backlog/archive/tasks/task-30.1 - Design-extension-source-config-model-and-defaults.md @@ -0,0 +1,40 @@ +--- +id: TASK-30.1 +title: Design extension source config model and defaults +status: To Do +assignee: [] +created_date: '2026-02-13 18:32' +updated_date: '2026-02-13 18:34' +labels: [] +dependencies: [] +parent_task_id: TASK-30 +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 Update config template and docs text so defaults are discoverable and editable. +- [ ] #4 Invalid/missing config should fail fast with a clear message path. +- [ ] #5 Existing config readers do not regress when no providers are configured. + + +## Implementation Notes + + +Phase 1 — Foundation: config contract + validation + defaults + + +## Definition of Done + +- [ ] #1 Config examples in template/docs include at least one provider entry shape. +- [ ] #2 Defaults remain backward-compatible when key is absent. +- [ ] #3 Feature can be disabled without touching unrelated settings. + diff --git a/backlog/archive/tasks/task-30.2 - Implement-extension-resolver-service-search-episode-stream-resolution.md b/backlog/archive/tasks/task-30.2 - Implement-extension-resolver-service-search-episode-stream-resolution.md new file mode 100644 index 0000000..d75500e --- /dev/null +++ b/backlog/archive/tasks/task-30.2 - Implement-extension-resolver-service-search-episode-stream-resolution.md @@ -0,0 +1,42 @@ +--- +id: TASK-30.2 +title: Implement extension resolver service (search + episode + stream resolution) +status: To Do +assignee: [] +created_date: '2026-02-13 18:32' +updated_date: '2026-02-13 18:34' +labels: [] +dependencies: + - TASK-30.1 +parent_task_id: TASK-30 +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 Add services for searchAnime, listEpisodes, resolveStream (or equivalent) with cancellation/error boundaries. +- [ ] #4 Normalize all provider responses into deterministic field names and stable IDs. +- [ ] #5 Include resilient handling for empty/no-result/no-URL cases and network faults with explicit error categories. + + +## Implementation Notes + + +Phase 2 — Core service: provider integration and stream resolution + + +## Definition of Done + +- [ ] #1 Resolver never leaks raw provider payload to renderer. +- [ ] #2 Streaming URL output includes reason for failure when unavailable. +- [ ] #3 Service boundaries allow unit-level validation of request/response mapping logic. +- [ ] #4 No blocking calls on Electron UI/main thread; all I/O is async and cancellable. + diff --git a/backlog/archive/tasks/task-30.3 - Expose-resolver-operations-via-Electron-IPC-to-renderer.md b/backlog/archive/tasks/task-30.3 - Expose-resolver-operations-via-Electron-IPC-to-renderer.md new file mode 100644 index 0000000..96330ed --- /dev/null +++ b/backlog/archive/tasks/task-30.3 - Expose-resolver-operations-via-Electron-IPC-to-renderer.md @@ -0,0 +1,42 @@ +--- +id: TASK-30.3 +title: Expose resolver operations via Electron IPC to renderer +status: To Do +assignee: [] +created_date: '2026-02-13 18:32' +updated_date: '2026-02-13 18:34' +labels: [] +dependencies: + - TASK-30.2 +parent_task_id: TASK-30 +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #1 Define IPC handlers in main with input/output schema validation and timeouts. +- [ ] #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. +- [ ] #4 Implement safe serialization and error marshalling for resolver-specific failures. +- [ ] #5 Add runtime wiring and lifetime management in app startup/shutdown. +- [ ] #6 Document event/callback behavior for loading/error states. + + +## Implementation Notes + + +Phase 3 — API surface: IPC/preload contract for resolver operations + + +## Definition of Done + +- [ ] #1 Renderer code can query providers without importing Node-only modules. +- [ ] #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. + diff --git a/backlog/archive/tasks/task-30.4 - Add-interactive-streaming-modal-search-episode-list-source-selection-play.md b/backlog/archive/tasks/task-30.4 - Add-interactive-streaming-modal-search-episode-list-source-selection-play.md new file mode 100644 index 0000000..a2be6c2 --- /dev/null +++ b/backlog/archive/tasks/task-30.4 - Add-interactive-streaming-modal-search-episode-list-source-selection-play.md @@ -0,0 +1,42 @@ +--- +id: TASK-30.4 +title: 'Add interactive streaming modal (search, episode list, source selection, play)' +status: To Do +assignee: [] +created_date: '2026-02-13 18:32' +updated_date: '2026-02-13 18:34' +labels: [] +dependencies: + - TASK-30.3 +parent_task_id: TASK-30 +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 Render one-click or enter-to-play action that calls existing mpv playback pathway. +- [ ] #4 Persist minimal user preference (last provider/quality where possible) for faster repeat use. +- [ ] #5 Provide empty/error states and accessibility-friendly focus/keyboard navigation for lists. +- [ ] #6 Add a no-network mode fallback message when resolver calls fail. + + +## Implementation Notes + + +Phase 4 — UX: interactive modal flow and playback callout + + +## Definition of Done + +- [ ] #1 Modal state is isolated and unsubscribes listeners on close. +- [ ] #2 No direct network logic in renderer beyond IPC calls. +- [ ] #3 Visual style and behavior are consistent with existing modal patterns. + diff --git a/backlog/archive/tasks/task-30.5 - Wire-mpv-script-message-shortcut-trigger-into-streaming-modal-and-playback-path.md b/backlog/archive/tasks/task-30.5 - Wire-mpv-script-message-shortcut-trigger-into-streaming-modal-and-playback-path.md new file mode 100644 index 0000000..b19ed4f --- /dev/null +++ b/backlog/archive/tasks/task-30.5 - Wire-mpv-script-message-shortcut-trigger-into-streaming-modal-and-playback-path.md @@ -0,0 +1,45 @@ +--- +id: TASK-30.5 +title: >- + Wire mpv script-message/shortcut trigger into streaming modal and playback + path +status: To Do +assignee: [] +created_date: '2026-02-13 18:33' +updated_date: '2026-02-13 18:34' +labels: [] +dependencies: + - TASK-30.3 + - TASK-30.4 +parent_task_id: TASK-30 +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 Add at least one default keybinding/menu entry documented in config/plugin notes. +- [ ] #4 Ensure playback launched from the in-player flow uses the same command path and error messages as renderer-initiated flow. +- [ ] #5 Add graceful handling when feature is disabled or no providers are configured. + + +## Implementation Notes + + +Phase 5 — In-player entry: mpv trigger/menu integration + + +## Definition of Done + +- [ ] #1 No duplicate mpv command parsing between picker and legacy commands. +- [ ] #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. +- [ ] #4 Manual and keybind invocations behave consistently. + diff --git a/backlog/archive/tasks/task-30.6 - Add-integration-validation-plan-and-rollout-checklist-for-anime-streaming-feature.md b/backlog/archive/tasks/task-30.6 - Add-integration-validation-plan-and-rollout-checklist-for-anime-streaming-feature.md new file mode 100644 index 0000000..7120183 --- /dev/null +++ b/backlog/archive/tasks/task-30.6 - Add-integration-validation-plan-and-rollout-checklist-for-anime-streaming-feature.md @@ -0,0 +1,45 @@ +--- +id: TASK-30.6 +title: >- + Add integration validation plan and rollout checklist for anime streaming + feature +status: To Do +assignee: [] +created_date: '2026-02-13 18:34' +updated_date: '2026-02-13 18:34' +labels: [] +dependencies: [] +parent_task_id: TASK-30 +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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). +- [ ] #3 Define renderer UX checks for modal state transitions, loading indicators, empty results, selection, and play invocation. +- [ ] #4 Define in-mpv trigger checks for command/message pathway and fallback behavior when modal disabled/unavailable. +- [ ] #5 Define manual smoke steps for end-to-end play from query to mpv playback using at least one configured source. +- [ ] #6 Document expected logs/telemetry markers for troubleshooting and rollback. +- [ ] #7 Define rollback criteria and what constitutes safe partial completion. + + +## Implementation Notes + + +Phase 6 — Validation: rollout, smoke tests, and release readiness checklist + + +## Definition of Done + +- [ ] #1 Checklist covers happy-path and failure-path for each task dependency. +- [ ] #2 Verification steps are executable without external tooling assumptions. +- [ ] #3 No task can be marked done without explicit evidence fields filled in. +- [ ] #4 Rollout and fallback behavior are documented per deployment/release phase. + diff --git a/backlog/archive/tasks/task-30.7 - Add-English-source-preference-hard-sub-stripping-workflow-in-Aniyomi-streaming-path.md b/backlog/archive/tasks/task-30.7 - Add-English-source-preference-hard-sub-stripping-workflow-in-Aniyomi-streaming-path.md new file mode 100644 index 0000000..52f67f4 --- /dev/null +++ b/backlog/archive/tasks/task-30.7 - Add-English-source-preference-hard-sub-stripping-workflow-in-Aniyomi-streaming-path.md @@ -0,0 +1,34 @@ +--- +id: TASK-30.7 +title: >- + Add English-source preference + hard-sub stripping workflow in Aniyomi + streaming path +status: To Do +assignee: [] +created_date: '2026-02-13 18:41' +labels: [] +dependencies: + - TASK-30.2 + - TASK-30.5 +parent_task_id: TASK-30 +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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). +- [ ] #3 Detect when a resolved stream is hard-sub-only and a soft-sub source is unavailable for the same episode. +- [ ] #4 When hard subs are used, attempt to generate a subtitle-less playback stream path using ffmpeg and feed an external subtitle file (including Jimaku-provided `.ass/.srt`) into the mpv playback path. +- [ ] #5 Preserve stream selection metadata (language tags, subtitle type, availability state) for UI decisions and error messaging. +- [ ] #6 If ffmpeg conversion is not possible/disabled or fails, surface a clear status that explains fallback behavior instead of silent failure. +- [ ] #7 Integrate subtitle source preferences with Jimaku so user-fetched or resolved subtitles are preferred for burn-in removal cases where supported. +- [ ] #8 Add handling for unsupported codecs/containers and provider limitations so direct passthrough is still used when hard-sub stripping is unsafe. +- [ ] #9 Document new behavior in feature docs/FAQ: how sources are ranked, what hard-sub stripping does, and known compatibility limitations. + diff --git a/backlog/archive/tasks/task-30.8 - Add-observability-and-tuning-metrics-for-Aniyomi-subtitle-source-fallback-decisions.md b/backlog/archive/tasks/task-30.8 - Add-observability-and-tuning-metrics-for-Aniyomi-subtitle-source-fallback-decisions.md new file mode 100644 index 0000000..6031412 --- /dev/null +++ b/backlog/archive/tasks/task-30.8 - Add-observability-and-tuning-metrics-for-Aniyomi-subtitle-source-fallback-decisions.md @@ -0,0 +1,31 @@ +--- +id: TASK-30.8 +title: >- + Add observability and tuning metrics for Aniyomi subtitle-source fallback + decisions +status: To Do +assignee: [] +created_date: '2026-02-13 18:41' +labels: [] +dependencies: + - TASK-30.7 +parent_task_id: TASK-30 +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 Log whether Jimaku subtitle attachment was available and successfully loaded for ffmpeg-assisted flows. +- [ ] #4 Capture user-visible fallback reasons when preferred English/soft-sub sources are absent and hard-sub path is used. +- [ ] #5 Add a debug/report view or log artifact with counters that can be reviewed in-app or via config/log files. +- [ ] #6 Document metrics definitions so developers can tune source scorer and fallback policy without code changes. +- [ ] #7 Ensure instrumentation has low overhead and is opt-out-safe with existing config flags. + diff --git a/backlog/archive/tasks/task-30.9 - Expose-subtitle-preference-and-ffmpeg-fallback-tuning-controls-in-settings-UI.md b/backlog/archive/tasks/task-30.9 - Expose-subtitle-preference-and-ffmpeg-fallback-tuning-controls-in-settings-UI.md new file mode 100644 index 0000000..1d0fd36 --- /dev/null +++ b/backlog/archive/tasks/task-30.9 - Expose-subtitle-preference-and-ffmpeg-fallback-tuning-controls-in-settings-UI.md @@ -0,0 +1,30 @@ +--- +id: TASK-30.9 +title: Expose subtitle preference and ffmpeg fallback tuning controls in settings UI +status: To Do +assignee: [] +created_date: '2026-02-13 18:42' +labels: [] +dependencies: + - TASK-30.7 + - TASK-30.8 +parent_task_id: TASK-30 +priority: medium +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 Expose source ranking preferences for soft-sub vs hard-sub sources and optional fallback to native/transcoded source when preferred modes are unavailable. +- [ ] #4 Persist settings in existing config schema with migration-safe defaults and include clear validation for invalid/unsupported values. +- [ ] #5 Show current effective policy in streaming UI (for debugging): source selected + reason + whether subtitles are soft/hard and if ffmpeg path is active. +- [ ] #6 Add user-facing explanatory text and warnings for ffmpeg dependency, expected CPU/cpu cost, and compatibility limits. +- [ ] #7 Log and display when user-adjusted policy changes alter a previously preferred source choice during runtime. + diff --git a/backlog/archive/tasks/task-48 - Add-streaming-mode-integration-in-subminer-using-ani-cli-stream-source.md b/backlog/archive/tasks/task-48 - Add-streaming-mode-integration-in-subminer-using-ani-cli-stream-source.md new file mode 100644 index 0000000..e2a6240 --- /dev/null +++ b/backlog/archive/tasks/task-48 - Add-streaming-mode-integration-in-subminer-using-ani-cli-stream-source.md @@ -0,0 +1,45 @@ +--- +id: TASK-48 +title: Add streaming mode integration in subminer using ani-cli stream source +status: To Do +assignee: [] +created_date: '2026-02-14 06:01' +updated_date: '2026-02-14 08:19' +labels: + - stream + - ani-cli + - jimaku +dependencies: [] +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 If stream metadata contains a Japanese subtitle track, preserve that track as the primary subtitle stream path per current primary-subtitle selection behavior. +- [ ] #4 If no Japanese subtitle track is present in the stream metadata, fetch matching subtitles from Jimaku and load them into playback. +- [ ] #5 When loading Jimaku subtitles, replace/overwrite existing non-Japanese primary subtitle track behavior so the language configured as primary in SubMiner config is used instead. +- [ ] #6 Non-streaming mode continues to follow current behavior when `-s`/`--stream` is not set. + + +## Implementation Notes + + +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. + + +## Definition of Done + +- [ ] #1 CLI accepts both `-s` and `--stream` and enables streaming-specific behavior. +- [ ] #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. +- [ ] #4 Primary subtitle language in config determines which language is treated as default stream subtitle track after fallback. +- [ ] #5 Behavior is verified via test or manual checklist and documented in task notes. + diff --git a/backlog/archive/tasks/task-48.1 - Add-streaming-CLI-flag-plumbing-and-option-wiring.md b/backlog/archive/tasks/task-48.1 - Add-streaming-CLI-flag-plumbing-and-option-wiring.md new file mode 100644 index 0000000..fd10c35 --- /dev/null +++ b/backlog/archive/tasks/task-48.1 - Add-streaming-CLI-flag-plumbing-and-option-wiring.md @@ -0,0 +1,33 @@ +--- +id: TASK-48.1 +title: Add streaming CLI flag plumbing and option wiring +status: To Do +assignee: [] +created_date: '2026-02-14 06:03' +updated_date: '2026-02-14 08:19' +labels: + - stream + - cli +dependencies: [] +parent_task_id: TASK-48 +priority: medium +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 When unset, behavior remains identical to current non-streaming flows. + + +## Implementation Notes + + +Superseded by TASK-51. CLI stream mode work deferred until streaming architecture is revisited. + diff --git a/backlog/archive/tasks/task-48.2 - Port-ani-cli-stream-resolution-logic-into-SubMiner.md b/backlog/archive/tasks/task-48.2 - Port-ani-cli-stream-resolution-logic-into-SubMiner.md new file mode 100644 index 0000000..02fd272 --- /dev/null +++ b/backlog/archive/tasks/task-48.2 - Port-ani-cli-stream-resolution-logic-into-SubMiner.md @@ -0,0 +1,33 @@ +--- +id: TASK-48.2 +title: Port ani-cli stream-resolution logic into SubMiner +status: To Do +assignee: [] +created_date: '2026-02-14 06:03' +updated_date: '2026-02-14 08:19' +labels: + - stream + - ani-cli +dependencies: [] +parent_task_id: TASK-48 +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 Preserve existing behavior for non-streaming flow and expose errors when stream resolution fails. + + +## Implementation Notes + + +Superseded by TASK-51. Stream URL resolution via ani-cli postponed; previous attempt exposed anti-bot/403 fragility and poor title-source reliability. + diff --git a/backlog/archive/tasks/task-48.3 - Implement-stream-subtitle-selection-and-primary-language-precedence.md b/backlog/archive/tasks/task-48.3 - Implement-stream-subtitle-selection-and-primary-language-precedence.md new file mode 100644 index 0000000..b9e2708 --- /dev/null +++ b/backlog/archive/tasks/task-48.3 - Implement-stream-subtitle-selection-and-primary-language-precedence.md @@ -0,0 +1,33 @@ +--- +id: TASK-48.3 +title: Implement stream subtitle selection and primary-language precedence +status: To Do +assignee: [] +created_date: '2026-02-14 06:03' +updated_date: '2026-02-14 08:19' +labels: + - stream + - subtitles +dependencies: [] +parent_task_id: TASK-48 +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 When no Japanese track exists and config primary is different, explicitly set configured primary as primary track for streaming flow. + + +## Implementation Notes + + +Superseded by TASK-51. Stream subtitle language precedence in streaming mode deferred with full design revisit. + diff --git a/backlog/archive/tasks/task-48.4 - Add-Jimaku-subtitle-fallback-for-stream-mode.md b/backlog/archive/tasks/task-48.4 - Add-Jimaku-subtitle-fallback-for-stream-mode.md new file mode 100644 index 0000000..3a9be2d --- /dev/null +++ b/backlog/archive/tasks/task-48.4 - Add-Jimaku-subtitle-fallback-for-stream-mode.md @@ -0,0 +1,34 @@ +--- +id: TASK-48.4 +title: Add Jimaku subtitle fallback for stream mode +status: To Do +assignee: [] +created_date: '2026-02-14 06:03' +updated_date: '2026-02-14 08:19' +labels: + - stream + - jimaku + - subtitles +dependencies: [] +parent_task_id: TASK-48 +priority: medium +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 Fallback is only used in streaming mode and should not alter subtitle behavior outside streaming. + + +## Implementation Notes + + +Superseded by TASK-51. Jimaku fallback for streams deferred along with entire streaming flow. + diff --git a/backlog/archive/tasks/task-48.5 - Add-verification-plan-tests-for-streaming-mode-behavior.md b/backlog/archive/tasks/task-48.5 - Add-verification-plan-tests-for-streaming-mode-behavior.md new file mode 100644 index 0000000..c9f5435 --- /dev/null +++ b/backlog/archive/tasks/task-48.5 - Add-verification-plan-tests-for-streaming-mode-behavior.md @@ -0,0 +1,33 @@ +--- +id: TASK-48.5 +title: Add verification plan/tests for streaming mode behavior +status: To Do +assignee: [] +created_date: '2026-02-14 06:03' +updated_date: '2026-02-14 08:19' +labels: + - stream + - qa +dependencies: [] +parent_task_id: TASK-48 +priority: low +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 Run or provide reproducible checks to confirm non-streaming behavior unchanged. + + +## Implementation Notes + + +Superseded by TASK-51. Verification plan moved to deferred reimplementation context. + diff --git a/backlog/archive/tasks/task-48.6 - Wire-s-stream-mode-to-Ani-cli-and-Jimaku-subtitle-fallback.md b/backlog/archive/tasks/task-48.6 - Wire-s-stream-mode-to-Ani-cli-and-Jimaku-subtitle-fallback.md new file mode 100644 index 0000000..571ceca --- /dev/null +++ b/backlog/archive/tasks/task-48.6 - Wire-s-stream-mode-to-Ani-cli-and-Jimaku-subtitle-fallback.md @@ -0,0 +1,49 @@ +--- +id: TASK-48.6 +title: Wire -s/--stream mode to Ani-cli and Jimaku subtitle fallback +status: To Do +assignee: [] +created_date: '2026-02-14 06:06' +updated_date: '2026-02-14 08:19' +labels: [] +dependencies: [] +references: + - ani-cli/ani-cli + - src/jimaku/utils.ts + - src/core/services/anki-jimaku-service.ts +documentation: + - ani-cli/README.md + - subminer + - src/cli/help.ts +parent_task_id: TASK-48 +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [ ] #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. +- [ ] #3 If no Japanese (or configured primary language) subtitle exists in stream metadata, fetch and inject Jimaku subtitles before playback starts. +- [ ] #4 Loaded Jimaku subtitles should become the selected primary subtitle track, replacing any existing default non-primary subtitle in that context. +- [ ] #5 When `-s` is not passed, non-streaming behavior remains unchanged. + + +## Implementation Notes + + +Superseded by TASK-51. End-to-end stream wiring to ani-cli is deferred. + + +## Definition of Done + +- [ ] #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. +- [ ] #3 Subtitles loading path avoids temp-file leaks; temporary media/subtitle artifacts are cleaned up on exit. +- [ ] #4 At least one verification step (manual or test) confirms stream mode path works for an episode with and without Japanese stream subtitles. + diff --git a/backlog/archive/tasks/task-51 - Revisit-Ani-cli-stream-mode-integration-later.md b/backlog/archive/tasks/task-51 - Revisit-Ani-cli-stream-mode-integration-later.md new file mode 100644 index 0000000..5894647 --- /dev/null +++ b/backlog/archive/tasks/task-51 - Revisit-Ani-cli-stream-mode-integration-later.md @@ -0,0 +1,30 @@ +--- +id: TASK-51 +title: Revisit Ani-cli stream mode integration later +status: To Do +assignee: [] +created_date: '2026-02-14 08:19' +labels: + - someday + - streaming + - ani-cli + - feature-flag +dependencies: [] +--- + +## Description + + +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: +- `subminer -s ` 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. +- We also observed stream title resolution issues: selected titles from ani-cli menu were unreliable/random and broke downstream Jimaku matching behavior. +- ffsubsync failures were difficult to debug initially due to OSD-only error visibility; logging was added to mpv log path. +- Based on these findings and instability, stream mode should be explicitly deferred rather than partially reintroduced. + +Proposal: +- 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. + diff --git a/backlog/completed/task-10 - Consolidate-service-naming-conventions-and-barrel-exports.md b/backlog/completed/task-10 - Consolidate-service-naming-conventions-and-barrel-exports.md new file mode 100644 index 0000000..3613a3b --- /dev/null +++ b/backlog/completed/task-10 - Consolidate-service-naming-conventions-and-barrel-exports.md @@ -0,0 +1,53 @@ +--- +id: TASK-10 +title: Consolidate service naming conventions and barrel exports +status: Done +assignee: [] +created_date: '2026-02-11 08:21' +updated_date: '2026-02-15 07:00' +labels: + - refactor + - services + - naming +milestone: Codebase Clarity & Composability +dependencies: [] +references: + - src/core/services/index.ts +priority: low +--- + +## Description + + +The service layer has inconsistent naming: +- Some functions end in `Service`: `handleCliCommandService`, `loadSubtitlePositionService` +- Some end in `RuntimeService`: `replayCurrentSubtitleRuntimeService`, `sendMpvCommandRuntimeService` +- Some are plain: `shortcutMatchesInputForLocalFallback` +- Factory functions mix `create*DepsRuntimeService` with `create*Service` + +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: +- Exported service functions: `verbNounService` (e.g., `handleCliCommand`) +- Deps factory functions: `create*Deps` +- Consider whether the barrel re-export is still the right pattern vs direct imports from individual files. + + +## Acceptance Criteria + +- [ ] #1 All service functions follow a consistent naming convention +- [ ] #2 Decision documented on barrel export vs direct imports +- [ ] #3 No functional changes + + +## Implementation Notes + + +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. + + +## Final Summary + + +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. + diff --git a/backlog/completed/task-20.1 - Refactor-overlay-runtime-to-use-per-layer-window-bounds-ownership.md b/backlog/completed/task-20.1 - Refactor-overlay-runtime-to-use-per-layer-window-bounds-ownership.md new file mode 100644 index 0000000..4c5d59c --- /dev/null +++ b/backlog/completed/task-20.1 - Refactor-overlay-runtime-to-use-per-layer-window-bounds-ownership.md @@ -0,0 +1,44 @@ +--- +id: TASK-20.1 +title: Refactor overlay runtime to use per-layer window bounds ownership +status: Done +assignee: [] +created_date: '2026-02-12 08:47' +updated_date: '2026-02-13 08:04' +labels: [] +dependencies: [] +parent_task_id: TASK-20 +priority: medium +--- + +## Description + + +Refactor overlay runtime so each overlay layer owns and applies its bounds independently. Keep tracker geometry as shared origin input only. + + +## Acceptance Criteria + +- [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] #3 Window tracker updates feed shared origin data; each layer applies its own computed bounds. +- [x] #4 Single-layer behavior (visible-only or invisible-only) remains unchanged from user perspective. + + +## Implementation Notes + + +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. + +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. + + +## Final Summary + + +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. + diff --git a/backlog/completed/task-8 - Reduce-MpvIpcClient-deps-interface-and-separate-protocol-from-application-logic.md b/backlog/completed/task-8 - Reduce-MpvIpcClient-deps-interface-and-separate-protocol-from-application-logic.md new file mode 100644 index 0000000..e652abf --- /dev/null +++ b/backlog/completed/task-8 - Reduce-MpvIpcClient-deps-interface-and-separate-protocol-from-application-logic.md @@ -0,0 +1,45 @@ +--- +id: TASK-8 +title: >- + Reduce MpvIpcClient deps interface and separate protocol from application + logic +status: Done +assignee: [] +created_date: '2026-02-11 08:20' +updated_date: '2026-02-15 07:00' +labels: + - refactor + - mpv + - architecture +milestone: Codebase Clarity & Composability +dependencies: [] +references: + - src/core/services/mpv-service.ts +priority: medium +--- + +## Description + + +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: +1. **IPC Protocol**: Socket connection, JSON message framing, reconnection, property observation +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. + + +## Acceptance Criteria + +- [ ] #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 +- [ ] #3 MpvIpcClient is testable without mocking 22 callbacks +- [ ] #4 Existing behavior preserved + + +## Final Summary + + +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. + diff --git a/backlog/completed/task-9 - Remove-trivial-wrapper-functions-from-main.ts.md b/backlog/completed/task-9 - Remove-trivial-wrapper-functions-from-main.ts.md new file mode 100644 index 0000000..751bbbb --- /dev/null +++ b/backlog/completed/task-9 - Remove-trivial-wrapper-functions-from-main.ts.md @@ -0,0 +1,60 @@ +--- +id: TASK-9 +title: Remove trivial wrapper functions from main.ts +status: Done +assignee: [] +created_date: '2026-02-11 08:21' +updated_date: '2026-02-15 07:00' +labels: + - refactor + - main + - simplicity +milestone: Codebase Clarity & Composability +dependencies: + - TASK-7 +references: + - src/main.ts +priority: low +--- + +## Description + + +main.ts contains many trivial single-line wrapper functions that add indirection without value: + +```typescript +function getOverlayWindows(): BrowserWindow[] { + return overlayManager.getOverlayWindows(); +} +function updateOverlayBounds(geometry: WindowGeometry): void { + updateOverlayBoundsService(geometry, () => getOverlayWindows()); +} +function ensureOverlayWindowLevel(window: BrowserWindow): void { + ensureOverlayWindowLevelService(window); +} +``` + +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. + + +## Acceptance Criteria + +- [ ] #1 Trivial pass-through wrappers eliminated (call service/manager directly) +- [ ] #2 Config accessor wrappers replaced with direct calls or a config accessor helper +- [ ] #3 main.ts line count reduced +- [ ] #4 No functional changes + + +## Implementation Notes + + +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. + + +## Final Summary + + +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. + diff --git a/backlog/config.yml b/backlog/config.yml new file mode 100644 index 0000000..de5fb9e --- /dev/null +++ b/backlog/config.yml @@ -0,0 +1,16 @@ +project_name: "SubMiner" +default_status: "To Do" +statuses: ["To Do", "In Progress", "Done"] +labels: [] +milestones: [] +date_format: yyyy-mm-dd +max_column_width: 20 +default_editor: "nvim" +auto_open_browser: false +default_port: 6420 +remote_operations: true +auto_commit: false +bypass_git_hooks: false +check_active_branches: true +active_branch_days: 30 +task_prefix: "task" diff --git a/backlog/milestones/m-0 - release-v0.1.0.md b/backlog/milestones/m-0 - release-v0.1.0.md new file mode 100644 index 0000000..0f9a865 --- /dev/null +++ b/backlog/milestones/m-0 - release-v0.1.0.md @@ -0,0 +1,8 @@ +--- +id: m-0 +title: "Release v0.1.0" +--- + +## Description + +Milestone: Release v0.1.0 diff --git a/backlog/tasks/task-1 - Refactor-runtime-services-per-plan.md.md b/backlog/tasks/task-1 - Refactor-runtime-services-per-plan.md.md new file mode 100644 index 0000000..835ae34 --- /dev/null +++ b/backlog/tasks/task-1 - Refactor-runtime-services-per-plan.md.md @@ -0,0 +1,49 @@ +--- +id: TASK-1 +title: Refactor runtime services per plan.md +status: Done +assignee: [] +created_date: '2026-02-10 18:46' +updated_date: '2026-02-11 03:35' +labels: [] +dependencies: [] +references: + - plan.md +ordinal: 1000 +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [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] #3 Implementation proceeds with build/test verification checkpoints after each completed phase. +- [x] #4 Main behavior remains stable for startup, overlay, IPC, CLI, and tokenizer flows throughout refactor. + + +## Implementation Notes + + +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.2 (Phase 2 DI adapter consolidation) with successful build and core test verification checkpoint. + +Completed TASK-1.5 (critical behavior tests) with expanded tokenizer/mpv/subsync/CLI coverage and green core test suite. + +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. + + +## Final Summary + + +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. + diff --git a/backlog/tasks/task-1.1 - Phase-1-Remove-thin-wrapper-runtime-services.md b/backlog/tasks/task-1.1 - Phase-1-Remove-thin-wrapper-runtime-services.md new file mode 100644 index 0000000..eca139f --- /dev/null +++ b/backlog/tasks/task-1.1 - Phase-1-Remove-thin-wrapper-runtime-services.md @@ -0,0 +1,53 @@ +--- +id: TASK-1.1 +title: 'Phase 1: Remove thin wrapper runtime services' +status: Done +assignee: + - codex +created_date: '2026-02-10 18:46' +updated_date: '2026-02-11 03:35' +labels: [] +dependencies: [] +references: + - plan.md + - src/main.ts + - src/core/services/index.ts +parent_task_id: TASK-1 +ordinal: 11000 +--- + +## Description + + +Inline trivial wrapper services into their call sites and delete redundant service/test files listed in Phase 1 of plan.md. + + +## Acceptance Criteria + +- [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] #3 `src/core/services/index.ts` exports are updated to remove deleted modules. +- [x] #4 `pnpm run build && pnpm run test:core` passes after Phase 1 completion. + + +## Implementation Plan + + +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. +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. +4. Delete corresponding trivial test files for removed wrappers and clean `src/core/services/index.ts` exports. +5. Run `pnpm run build && pnpm run test:core`; fix regressions and update task notes/acceptance criteria incrementally. + + +## Implementation Notes + + +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`. + +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. + diff --git a/backlog/tasks/task-1.2 - Phase-2-Merge-DI-adapter-runtime-services-into-target-services.md b/backlog/tasks/task-1.2 - Phase-2-Merge-DI-adapter-runtime-services-into-target-services.md new file mode 100644 index 0000000..a707607 --- /dev/null +++ b/backlog/tasks/task-1.2 - Phase-2-Merge-DI-adapter-runtime-services-into-target-services.md @@ -0,0 +1,56 @@ +--- +id: TASK-1.2 +title: 'Phase 2: Merge DI adapter runtime services into target services' +status: Done +assignee: + - codex +created_date: '2026-02-10 18:46' +updated_date: '2026-02-11 03:35' +labels: [] +dependencies: + - TASK-1.1 +references: + - plan.md + - src/core/services/cli-command-service.ts + - src/core/services/ipc-service.ts + - src/core/services/tokenizer-service.ts + - src/core/services/app-lifecycle-deps-runtime-service.ts +parent_task_id: TASK-1 +ordinal: 9000 +--- + +## Description + + +Absorb dependency adapter runtime services into core service modules and remove adapter files/tests while preserving runtime behavior. + + +## Acceptance Criteria + +- [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] #3 Callers pass dependency shapes expected by updated services without redundant mapping layers. +- [x] #4 `pnpm run build && pnpm run test:core` passes after Phase 2 completion. + + +## Implementation Plan + + +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. +3. Remove adapter service files/tests and update `src/core/services/index.ts` exports/import sites. +4. Run `pnpm run build && pnpm run test:core` and fix any typing/regression issues from the interface consolidation. +5. Update task notes with dependency-shape decisions to preserve handoff clarity. + + +## Implementation Notes + + +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. + +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. + diff --git a/backlog/tasks/task-1.3 - Phase-3-Consolidate-related-service-modules.md b/backlog/tasks/task-1.3 - Phase-3-Consolidate-related-service-modules.md new file mode 100644 index 0000000..af54b3d --- /dev/null +++ b/backlog/tasks/task-1.3 - Phase-3-Consolidate-related-service-modules.md @@ -0,0 +1,62 @@ +--- +id: TASK-1.3 +title: 'Phase 3: Consolidate related service modules' +status: Done +assignee: + - codex +created_date: '2026-02-10 18:46' +updated_date: '2026-02-11 03:35' +labels: [] +dependencies: + - TASK-1.2 +references: + - plan.md + - src/core/services/overlay-visibility-service.ts + - src/core/services/overlay-manager-service.ts + - src/core/services/overlay-shortcut-service.ts + - src/core/services/numeric-shortcut-session-service.ts + - src/core/services/app-ready-runtime-service.ts +parent_task_id: TASK-1 +ordinal: 5000 +--- + +## Description + + +Merge split modules for overlay visibility, broadcast, shortcuts, numeric shortcuts, and startup orchestration into cohesive service files. + + +## Acceptance Criteria + +- [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] #3 Shortcut and numeric shortcut runtime/lifecycle splits are consolidated as described in plan.md. +- [x] #4 Startup bootstrap and app-ready runtime orchestration is consolidated into one startup module. +- [x] #5 `pnpm run build && pnpm run test:core` passes after Phase 3 completion. + + +## Implementation Plan + + +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`. +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. +4. Merge numeric shortcut runtime/session split into a single `numeric-shortcut-service.ts` and update call sites/tests. +5. Merge startup bootstrap + app-ready orchestration into a single startup module, update imports, remove obsolete files, and run `pnpm run build && pnpm run test:core`. + + +## Implementation Notes + + +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`. + +Consolidated shortcut modules into `overlay-shortcut-service.ts` (lifecycle) and new `overlay-shortcut-handler.ts` (runtime handlers + local fallback), removing `overlay-shortcut-lifecycle-service.ts`, `overlay-shortcut-runtime-service.ts`, and `overlay-shortcut-fallback-runner.ts`. + +Merged numeric shortcut runtime/session split into `numeric-shortcut-service.ts`; removed `numeric-shortcut-runtime-service.ts` and merged runtime test coverage into session tests. + +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. + diff --git a/backlog/tasks/task-1.4 - Phase-4-Fix-runtime-bugs-and-naming-code-quality-issues.md b/backlog/tasks/task-1.4 - Phase-4-Fix-runtime-bugs-and-naming-code-quality-issues.md new file mode 100644 index 0000000..d610434 --- /dev/null +++ b/backlog/tasks/task-1.4 - Phase-4-Fix-runtime-bugs-and-naming-code-quality-issues.md @@ -0,0 +1,89 @@ +--- +id: TASK-1.4 +title: 'Phase 4: Fix runtime bugs and naming/code-quality issues' +status: Done +assignee: + - codex +created_date: '2026-02-10 18:46' +updated_date: '2026-02-11 03:35' +labels: [] +dependencies: + - TASK-1.3 +references: + - plan.md + - src/main.ts + - src/core/services/overlay-visibility-service.ts + - src/core/services/tokenizer-deps-runtime-service.ts +parent_task_id: TASK-1 +ordinal: 2000 +--- + +## Description + + +Address identified correctness and code-quality issues from plan.md, including race conditions, unsafe typing, callback rejection handling, and runtime naming cleanup. + + +## Acceptance Criteria + +- [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] #3 Field grouping resolver handling is made concurrency-safe against overlapping requests. +- [x] #4 Async callback wiring in CLI/IPC paths has explicit rejection handling. +- [x] #5 Remaining `-runtime-service` naming cleanup is completed without logic regressions. +- [x] #6 `pnpm run build && pnpm run test:core` passes and manual startup/overlay smoke checks succeed. + + +## Implementation Plan + + +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. +3. Make field grouping resolver handling in `main.ts` concurrency-safe by adding request sequencing and stale-resolution guards. +4. Audit async callback wiring in CLI/IPC integrations and add explicit rejection handling where promises are fire-and-forget. +5. Execute `pnpm run build && pnpm run test:core` and document manual smoke-test steps/outcomes. + + +## Implementation Notes + + +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`). + +Added field-grouping overlap protection: `createFieldGroupingCallbackService` now cancels immediately when another resolver is active and only clears resolver state if the current resolver matches, preventing stale timeout/request cleanup from clobbering a newer resolver. + +Added explicit rejection handling for async callback pathways: `shell.openExternal` now has `.catch(...)`; app lifecycle `whenReady` path now catches handler rejection; second-instance CLI dispatch is wrapped in try/catch logging. + +Verification: `pnpm run build && pnpm run test:core` passes after these fixes. + +Remaining in TASK-1.4: criterion #5 (`-runtime-service` naming cleanup batch) and criterion #6 manual smoke checks. + +Completed `-runtime-service` naming cleanup for remaining modules by renaming files/tests and import paths, including: `overlay-bridge`, `field-grouping-overlay`, `mpv-control`, `runtime-options-ipc`, `mining`, `jimaku`, `anki-jimaku`, startup/app-ready test names, and subsync wrapper (`subsync-runner-service.ts`). + +Resolved rename collision with existing `subsync-service.ts` by restoring original core subsync service from `HEAD` and moving runtime wrapper logic into `subsync-runner-service.ts`. + +Verification after rename cleanup: `pnpm run build && pnpm run test:core` passes with updated test paths in `package.json`. + +Manual smoke checks are still pending for criterion #6. + +Smoke run attempt 1 (outside sandbox): `timeout 20s pnpm run start` started successfully, loaded config, initialized websocket/Mecab, and entered normal MPV reconnect loop when `/tmp/subminer-socket` was absent; no immediate startup crash after previous refactors. + +Smoke run attempt 2 (outside sandbox): `timeout 20s pnpm exec electron . --start --auto-start-overlay` showed the same stable startup/reconnect behavior, but overlay activation could not be verified in this headless/non-interactive environment. + +Manual GUI interactions (overlay render/toggle, mine card flow, field-grouping interaction) remain pending for a real desktop session with MPV running. + +Automated interactive-smoke surrogate 1 (outside sandbox): started app, sent `--toggle`, then `--stop`; instance remained stable and cleanly stopped without crash. + +Automated interactive-smoke surrogate 2 (outside sandbox): started app, sent `--trigger-field-grouping`, then `--stop`; command path executed without runtime crash and app shut down cleanly. + +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. + + +## Final Summary + + +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. + diff --git a/backlog/tasks/task-1.5 - Phase-5-Add-critical-behavior-tests-for-untested-services.md b/backlog/tasks/task-1.5 - Phase-5-Add-critical-behavior-tests-for-untested-services.md new file mode 100644 index 0000000..c5bd2e5 --- /dev/null +++ b/backlog/tasks/task-1.5 - Phase-5-Add-critical-behavior-tests-for-untested-services.md @@ -0,0 +1,75 @@ +--- +id: TASK-1.5 +title: 'Phase 5: Add critical behavior tests for untested services' +status: Done +assignee: + - codex +created_date: '2026-02-10 18:46' +updated_date: '2026-02-11 03:35' +labels: [] +dependencies: + - TASK-1.4 +references: + - plan.md + - src/core/services/mpv-runtime-service.ts + - src/core/services/subsync-runtime-service.ts + - src/core/services/tokenizer-service.ts + - src/core/services/cli-command-service.ts +parent_task_id: TASK-1 +ordinal: 4000 +--- + +## Description + + +Add meaningful behavior tests for high-risk services called out in plan.md: mpv, subsync, tokenizer, and expanded CLI command coverage. + + +## Acceptance Criteria + +- [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] #3 `tokenizer` service has focused tests for parser readiness, token extraction, fallback behavior, and edge-case inputs. +- [x] #4 CLI command service tests cover all dispatch paths, async error propagation, and second-instance forwarding behavior. +- [x] #5 `pnpm run test:core` passes with all new tests green. + + +## Implementation Plan + + +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. +3. Add focused tests for `mpv-service.ts` protocol handling (line parsing, request-response routing, property-change dispatch) with lightweight socket stubs. +4. Expand `cli-command-service.ts` tests for dispatch/error/second-instance forwarding edge paths not currently covered. +5. Run `pnpm run test:core` iteratively and update acceptance criteria as each service reaches meaningful coverage. + + +## Implementation Notes + + +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 subsync workflow tests in `src/core/services/subsync-service.test.ts` covering already-running guard, manual-mode picker flow, and error propagation to OSD when MPV is unavailable. + +Expanded `src/core/services/cli-command-service.test.ts` to cover socket/start dispatch, texthooker port override warning path, help-without-window shutdown, and async trigger-subsync error reporting. + +Updated `package.json` `test:core` to include new/renamed test files; verification remains green with `pnpm run test:core` (17 tests total). + +Expanded `mpv-service` tests with request rejection when disconnected, `requestProperty` error propagation, and pending-request disconnect resolution behavior. + +Expanded `subsync-service` tests with manual alass source-track validation and auto-mode executable-path failure handling while ensuring in-progress state cleanup. + +All updated tests remain green via `pnpm run test:core` after these additions. + +Added Yomitan parser token-extraction coverage in `tokenizer-service.test.ts` (parser-available success path) in addition to fallback/edge-case tests. + +Added MPV reconnection/request robustness tests (`scheduleReconnect`, disconnected request rejection, pending request disconnect resolution) to complement protocol/event/request-id tests in `mpv-service.test.ts`. + +Added subsync command-construction tests using executable stubs for both engines (`ffsubsync` and `alass`) and validated success/failure result behavior; added timeout behavior coverage in `src/subsync/utils.test.ts` for child-process timeout handling used by subsync. + +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`. + diff --git a/backlog/tasks/task-1.6 - Phase-6-Optional-Reorganize-services-by-domain-directories.md b/backlog/tasks/task-1.6 - Phase-6-Optional-Reorganize-services-by-domain-directories.md new file mode 100644 index 0000000..108936d --- /dev/null +++ b/backlog/tasks/task-1.6 - Phase-6-Optional-Reorganize-services-by-domain-directories.md @@ -0,0 +1,46 @@ +--- +id: TASK-1.6 +title: 'Phase 6 (Optional): Reorganize services by domain directories' +status: Done +assignee: [] +created_date: '2026-02-10 18:46' +updated_date: '2026-02-11 03:35' +labels: [] +dependencies: + - TASK-1.5 +references: + - plan.md +parent_task_id: TASK-1 +ordinal: 3000 +--- + +## Description + + +If service flattening remains hard to navigate after Phases 1-5, optionally move modules into domain-based folders and update imports. + + +## Acceptance Criteria + +- [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. +- [x] #3 Build and core test commands pass after any directory reorganization. + + +## Implementation Plan + + +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. +3. If complexity is still problematic, perform import-safe domain reorganization and re-run build/tests. + + +## Implementation Notes + + +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. + +Verification baseline remains green (`pnpm run test:core`) with current structure. + diff --git a/backlog/tasks/task-11 - Break-up-the-applyInvisibleSubtitleLayoutFromMpvMetrics-mega-function.md b/backlog/tasks/task-11 - Break-up-the-applyInvisibleSubtitleLayoutFromMpvMetrics-mega-function.md new file mode 100644 index 0000000..8cff349 --- /dev/null +++ b/backlog/tasks/task-11 - Break-up-the-applyInvisibleSubtitleLayoutFromMpvMetrics-mega-function.md @@ -0,0 +1,46 @@ +--- +id: TASK-11 +title: Break up the applyInvisibleSubtitleLayoutFromMpvMetrics mega function +status: To Do +assignee: [] +created_date: '2026-02-11 08:21' +updated_date: '2026-02-15 07:00' +labels: + - refactor + - renderer + - complexity +milestone: Codebase Clarity & Composability +dependencies: + - TASK-27.5 +references: + - src/renderer/renderer.ts +priority: medium +--- + +## Description + + +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: +- `calculateOsdScale(metrics, renderAreaHeight)` — pure scaling math +- `calculateSubtitlePosition(metrics, scale, alignment)` — ASS \an tag interpretation + positioning +- `applyPlatformFontCompensation(style, platform)` — macOS kerning/size adjustments +- `applySubtitleStyle(element, computedStyle)` — DOM style application + +This can be done independently of or as part of TASK-6 (renderer split). + + +## Acceptance Criteria + +- [ ] #1 No single function exceeds ~50 lines in the positioning logic +- [ ] #2 Helper functions are pure where possible (take inputs, return outputs) +- [ ] #3 Platform-specific branches isolated into dedicated helpers +- [ ] #4 Invisible overlay positioning still works correctly on Linux and macOS + + +## Implementation Notes + + +Reparented as a dependency of TASK-27.5: the mega-function lives in positioning.ts (513 LOC), which is the exact file TASK-27.5 targets for splitting. Decomposing this function is a natural part of that file split. Should be executed together with TASK-27.5. + diff --git a/backlog/tasks/task-12 - Add-renderer-module-bundling-for-multi-file-renderer-support.md b/backlog/tasks/task-12 - Add-renderer-module-bundling-for-multi-file-renderer-support.md new file mode 100644 index 0000000..ea16931 --- /dev/null +++ b/backlog/tasks/task-12 - Add-renderer-module-bundling-for-multi-file-renderer-support.md @@ -0,0 +1,48 @@ +--- +id: TASK-12 +title: Add renderer module bundling for multi-file renderer support +status: To Do +assignee: [] +created_date: '2026-02-11 08:21' +updated_date: '2026-02-14 00:44' +labels: + - infrastructure + - renderer + - build +milestone: Codebase Clarity & Composability +dependencies: + - TASK-5 +references: + - src/renderer/renderer.ts + - src/renderer/index.html + - package.json + - tsconfig.json +priority: high +--- + +## Description + + +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: +1. **esbuild** — fast, minimal config, already used in many Electron projects +2. **Electron's native ESM support** — requires `"type": "module"` and sandbox configuration +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. + + +## Acceptance Criteria + +- [ ] #1 Renderer code can be split across multiple .ts files with imports +- [ ] #2 Build pipeline bundles renderer modules into a single output for Electron +- [ ] #3 Existing `make build` still works end-to-end +- [ ] #4 No runtime errors in renderer process + + +## Implementation Notes + + +Priority promoted from medium to high: this unblocks clean multi-file renderer work and is a prerequisite for upcoming UI features (TASK-26 help modal, TASK-34 episode browser, and any future modal/overlay features). + diff --git a/backlog/tasks/task-13 - Fix-macos-native-window-bounds-for-overlay-binding.md b/backlog/tasks/task-13 - Fix-macos-native-window-bounds-for-overlay-binding.md new file mode 100644 index 0000000..f3f700b --- /dev/null +++ b/backlog/tasks/task-13 - Fix-macos-native-window-bounds-for-overlay-binding.md @@ -0,0 +1,45 @@ +--- +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 + + +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. + + +## Acceptance Criteria + +- [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. + + +## Implementation Notes + + +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. + diff --git a/backlog/tasks/task-13 - Fix-second-instance-start-when-texthooker-only-instance-is-running.md b/backlog/tasks/task-13 - Fix-second-instance-start-when-texthooker-only-instance-is-running.md new file mode 100644 index 0000000..2117a8e --- /dev/null +++ b/backlog/tasks/task-13 - Fix-second-instance-start-when-texthooker-only-instance-is-running.md @@ -0,0 +1,51 @@ +--- +id: TASK-13 +title: Fix second-instance --start when texthooker-only instance is running +status: Done +assignee: [] +created_date: '2026-02-11 23:47' +updated_date: '2026-02-11 23:47' +labels: + - bugfix + - cli + - overlay +dependencies: [] +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [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] #3 CLI command service tests cover both behaviors and pass. + + +## Implementation Notes + + +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`. + + +## Final Summary + + +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: +- 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. +- 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. + +Validation: +- `pnpm run build` succeeded. +- `node dist/core/services/cli-command-service.test.js` passed (11/11). + diff --git a/backlog/tasks/task-14 - Ensure-subminer-launcher-shows-visible-overlay-on-startup.md b/backlog/tasks/task-14 - Ensure-subminer-launcher-shows-visible-overlay-on-startup.md new file mode 100644 index 0000000..f332b8b --- /dev/null +++ b/backlog/tasks/task-14 - Ensure-subminer-launcher-shows-visible-overlay-on-startup.md @@ -0,0 +1,43 @@ +--- +id: TASK-14 +title: Ensure subminer launcher shows visible overlay on startup +status: Done +assignee: [] +created_date: '2026-02-12 00:22' +updated_date: '2026-02-12 00:23' +labels: + - bugfix + - launcher + - overlay +dependencies: [] +priority: high +--- + +## Description + + +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. + + +## Acceptance Criteria + +- [x] #1 Running `subminer