mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-27 18:22:41 -08:00
update docs
This commit is contained in:
@@ -5,7 +5,7 @@ status: Done
|
|||||||
assignee:
|
assignee:
|
||||||
- codex-task103-jellyfin-main-composer-20260222T220441Z-m8p1
|
- codex-task103-jellyfin-main-composer-20260222T220441Z-m8p1
|
||||||
created_date: '2026-02-22 07:13'
|
created_date: '2026-02-22 07:13'
|
||||||
updated_date: '2026-02-22 22:48'
|
updated_date: '2026-02-23 02:06'
|
||||||
labels:
|
labels:
|
||||||
- refactor
|
- refactor
|
||||||
- maintainability
|
- maintainability
|
||||||
@@ -15,6 +15,7 @@ dependencies:
|
|||||||
- TASK-94
|
- TASK-94
|
||||||
- TASK-97
|
- TASK-97
|
||||||
priority: medium
|
priority: medium
|
||||||
|
ordinal: 100000
|
||||||
---
|
---
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ status: Done
|
|||||||
assignee:
|
assignee:
|
||||||
- codex
|
- codex
|
||||||
created_date: '2026-02-22 07:13'
|
created_date: '2026-02-22 07:13'
|
||||||
updated_date: '2026-02-22 19:56'
|
updated_date: '2026-02-23 02:06'
|
||||||
labels:
|
labels:
|
||||||
- refactor
|
- refactor
|
||||||
- launcher
|
- launcher
|
||||||
@@ -14,6 +14,7 @@ dependencies:
|
|||||||
- TASK-81
|
- TASK-81
|
||||||
- TASK-102
|
- TASK-102
|
||||||
priority: medium
|
priority: medium
|
||||||
|
ordinal: 103000
|
||||||
---
|
---
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ status: Done
|
|||||||
assignee:
|
assignee:
|
||||||
- opencode-task105-unsafe-casts
|
- opencode-task105-unsafe-casts
|
||||||
created_date: '2026-02-22 07:13'
|
created_date: '2026-02-22 07:13'
|
||||||
updated_date: '2026-02-22 21:56'
|
updated_date: '2026-02-23 02:06'
|
||||||
labels:
|
labels:
|
||||||
- refactor
|
- refactor
|
||||||
- type-safety
|
- type-safety
|
||||||
@@ -14,6 +14,7 @@ dependencies:
|
|||||||
- TASK-97
|
- TASK-97
|
||||||
- TASK-80
|
- TASK-80
|
||||||
priority: medium
|
priority: medium
|
||||||
|
ordinal: 102000
|
||||||
---
|
---
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ status: Done
|
|||||||
assignee:
|
assignee:
|
||||||
- opencode-task106-immersion-modules
|
- opencode-task106-immersion-modules
|
||||||
created_date: '2026-02-22 07:14'
|
created_date: '2026-02-22 07:14'
|
||||||
updated_date: '2026-02-22 21:58'
|
updated_date: '2026-02-23 02:06'
|
||||||
labels:
|
labels:
|
||||||
- refactor
|
- refactor
|
||||||
- maintainability
|
- maintainability
|
||||||
@@ -13,6 +13,7 @@ labels:
|
|||||||
dependencies:
|
dependencies:
|
||||||
- TASK-95
|
- TASK-95
|
||||||
priority: medium
|
priority: medium
|
||||||
|
ordinal: 101000
|
||||||
---
|
---
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
---
|
---
|
||||||
id: TASK-109
|
id: TASK-109
|
||||||
title: Add Discord Rich Presence integration with polished activity card
|
title: Add Discord Rich Presence integration with polished activity card
|
||||||
status: In Progress
|
status: Done
|
||||||
assignee:
|
assignee:
|
||||||
- opencode
|
- opencode
|
||||||
created_date: '2026-02-22 19:40'
|
created_date: '2026-02-22 19:40'
|
||||||
updated_date: '2026-02-23 01:15'
|
updated_date: '2026-02-23 02:06'
|
||||||
labels:
|
labels:
|
||||||
- feature
|
- feature
|
||||||
- discord
|
- discord
|
||||||
- presence
|
- presence
|
||||||
dependencies: []
|
dependencies: []
|
||||||
priority: medium
|
priority: medium
|
||||||
|
ordinal: 104000
|
||||||
---
|
---
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
@@ -34,11 +35,11 @@ Add optional Discord Rich Presence support so SubMiner can publish current activ
|
|||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
<!-- AC:BEGIN -->
|
<!-- AC:BEGIN -->
|
||||||
- [ ] #1 Discord Rich Presence can be enabled via config and remains disabled by default.
|
- [x] #1 Discord Rich Presence can be enabled via config and remains disabled by default.
|
||||||
- [ ] #2 Activity card shows clear state/details and updates correctly across playback/session transitions.
|
- [x] #2 Activity card shows clear state/details and updates correctly across playback/session transitions.
|
||||||
- [ ] #3 Activity card visuals (assets/text) are polished and consistent with project branding.
|
- [x] #3 Activity card visuals (assets/text) are polished and consistent with project branding.
|
||||||
- [ ] #4 Runtime handles Discord closed/not installed/disconnected without crashes or noisy logs.
|
- [x] #4 Runtime handles Discord closed/not installed/disconnected without crashes or noisy logs.
|
||||||
- [ ] #5 Docs include setup steps (app/client id), config keys, and troubleshooting notes.
|
- [x] #5 Docs include setup steps (app/client id), config keys, and troubleshooting notes.
|
||||||
<!-- AC:END -->
|
<!-- AC:END -->
|
||||||
|
|
||||||
## Implementation Plan
|
## Implementation Plan
|
||||||
@@ -73,7 +74,7 @@ Updated docs/config examples (`docs/configuration.md`, `config.example.jsonc`, `
|
|||||||
|
|
||||||
## Definition of Done
|
## Definition of Done
|
||||||
<!-- DOD:BEGIN -->
|
<!-- DOD:BEGIN -->
|
||||||
- [ ] #1 Focused tests cover presence payload mapping and lifecycle update behavior.
|
- [x] #1 Focused tests cover presence payload mapping and lifecycle update behavior.
|
||||||
- [ ] #2 Manual validation confirms Discord card appearance/updates for at least one real playback session.
|
- [x] #2 Manual validation confirms Discord card appearance/updates for at least one real playback session.
|
||||||
- [ ] #3 Build/test/docs gates pass with no regressions.
|
- [x] #3 Build/test/docs gates pass with no regressions.
|
||||||
<!-- DOD:END -->
|
<!-- DOD:END -->
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ status: Done
|
|||||||
assignee:
|
assignee:
|
||||||
- codex
|
- codex
|
||||||
created_date: '2026-02-23 02:16'
|
created_date: '2026-02-23 02:16'
|
||||||
updated_date: '2026-02-23 02:29'
|
updated_date: '2026-02-23 02:53'
|
||||||
labels:
|
labels:
|
||||||
- overlay
|
- overlay
|
||||||
- subtitle
|
- subtitle
|
||||||
@@ -18,7 +18,6 @@ ordinal: 110000
|
|||||||
## Description
|
## Description
|
||||||
|
|
||||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||||
|
|
||||||
Implement a 3-window overlay layout:
|
Implement a 3-window overlay layout:
|
||||||
|
|
||||||
- Dedicated secondary subtitle window anchored to top of mpv bounds (max 20% of height).
|
- Dedicated secondary subtitle window anchored to top of mpv bounds (max 20% of height).
|
||||||
@@ -26,25 +25,31 @@ Implement a 3-window overlay layout:
|
|||||||
- Invisible overlay window constrained to remaining lower region.
|
- Invisible overlay window constrained to remaining lower region.
|
||||||
|
|
||||||
Secondary subtitle bar must stay independently anchored while visible/invisible overlays swap.
|
Secondary subtitle bar must stay independently anchored while visible/invisible overlays swap.
|
||||||
|
|
||||||
<!-- SECTION:DESCRIPTION:END -->
|
<!-- SECTION:DESCRIPTION:END -->
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
<!-- AC:BEGIN -->
|
<!-- AC:BEGIN -->
|
||||||
|
|
||||||
- [x] #1 Runtime creates/manages a third overlay window dedicated to secondary subtitles.
|
- [x] #1 Runtime creates/manages a third overlay window dedicated to secondary subtitles.
|
||||||
- [x] #2 Secondary window stays anchored to top region capped at 20% of tracked mpv bounds.
|
- [x] #2 Secondary window stays anchored to top region capped at 20% of tracked mpv bounds.
|
||||||
- [x] #3 Visible and invisible overlay windows are constrained to remaining lower region.
|
- [x] #3 Visible and invisible overlay windows are constrained to remaining lower region.
|
||||||
- [x] #4 Secondary subtitle rendering/mode updates reach dedicated top window without duplicate top bars in primary windows.
|
- [x] #4 Secondary subtitle rendering/mode updates reach dedicated top window without duplicate top bars in primary windows.
|
||||||
- [x] #5 Focused runtime/core tests cover geometry split + window wiring regressions.
|
- [x] #5 Focused runtime/core tests cover geometry split + window wiring regressions.
|
||||||
|
|
||||||
<!-- AC:END -->
|
<!-- AC:END -->
|
||||||
|
|
||||||
|
## Implementation Plan
|
||||||
|
|
||||||
|
<!-- SECTION:PLAN:BEGIN -->
|
||||||
|
Closure verification plan (2026-02-23):
|
||||||
|
1) Re-read TASK-110 via Backlog MCP and confirm Done status + AC/summary/notes completeness.
|
||||||
|
2) Validate evidence commit `b8f7d5e` still matches shipped scope (overlay secondary top bar + primary lower region split).
|
||||||
|
3) Apply backlog metadata sync only if any field is stale/missing; keep status Done.
|
||||||
|
4) Record closure verification note with timestamp and validation outcome.
|
||||||
|
Plan artifact: `docs/plans/2026-02-23-task-110-overlay-closure-verification.md`.
|
||||||
|
<!-- SECTION:PLAN:END -->
|
||||||
|
|
||||||
## Implementation Notes
|
## Implementation Notes
|
||||||
|
|
||||||
<!-- SECTION:NOTES:BEGIN -->
|
<!-- SECTION:NOTES:BEGIN -->
|
||||||
|
|
||||||
- Added new `secondary` overlay window kind and runtime factory wiring, plus manager ownership (`get/setSecondaryWindow`) and bounds setter.
|
- Added new `secondary` overlay window kind and runtime factory wiring, plus manager ownership (`get/setSecondaryWindow`) and bounds setter.
|
||||||
- Added geometry splitter `splitOverlayGeometryForSecondaryBar` (20% top secondary, 80% bottom primary), integrated into `updateVisibleOverlayBounds` / `updateInvisibleOverlayBounds` flow.
|
- Added geometry splitter `splitOverlayGeometryForSecondaryBar` (20% top secondary, 80% bottom primary), integrated into `updateVisibleOverlayBounds` / `updateInvisibleOverlayBounds` flow.
|
||||||
- Main runtime now creates secondary window alongside primary overlays and syncs secondary window visibility with `secondarySubMode`.
|
- Main runtime now creates secondary window alongside primary overlays and syncs secondary window visibility with `secondarySubMode`.
|
||||||
@@ -55,5 +60,21 @@ Secondary subtitle bar must stay independently anchored while visible/invisible
|
|||||||
- `bun test src/main/runtime/overlay-window-factory.test.ts src/main/runtime/overlay-window-factory-main-deps.test.ts src/main/runtime/overlay-window-runtime-handlers.test.ts src/renderer/error-recovery.test.ts src/core/services/overlay-window.test.ts`
|
- `bun test src/main/runtime/overlay-window-factory.test.ts src/main/runtime/overlay-window-factory-main-deps.test.ts src/main/runtime/overlay-window-runtime-handlers.test.ts src/renderer/error-recovery.test.ts src/core/services/overlay-window.test.ts`
|
||||||
- `bun run build`
|
- `bun run build`
|
||||||
- `node --test dist/core/services/overlay-manager.test.js`
|
- `node --test dist/core/services/overlay-manager.test.js`
|
||||||
|
- Commit: `b8f7d5e` (`feat(overlay): split secondary subtitles into dedicated top window`)
|
||||||
|
|
||||||
|
2026-02-23 verification pass: revalidated TASK-110 closure against Backlog finalization criteria. Confirmed status remains Done, all 5 acceptance criteria are checked, implementation notes/final summary are present, and commit `b8f7d5e` still matches shipped scope (secondary top overlay window, 20%/80% geometry split, primary-layer duplicate prevention, focused runtime/core/renderer tests). No additional code changes required.
|
||||||
<!-- SECTION:NOTES:END -->
|
<!-- SECTION:NOTES:END -->
|
||||||
|
|
||||||
|
## Final Summary
|
||||||
|
|
||||||
|
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||||
|
Implemented the requested 3-window overlay architecture:
|
||||||
|
|
||||||
|
- Secondary subtitles render in a dedicated top overlay window.
|
||||||
|
- Top secondary bar is capped at 20% of mpv bounds.
|
||||||
|
- Visible/invisible overlays are constrained to the lower remaining region.
|
||||||
|
- Secondary mode changes now directly control secondary window visibility.
|
||||||
|
- Primary overlay layers no longer duplicate secondary subtitle rendering.
|
||||||
|
|
||||||
|
All acceptance criteria are complete and merged in commit `b8f7d5e`.
|
||||||
|
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
---
|
---
|
||||||
id: TASK-88
|
id: TASK-88
|
||||||
title: Remove MeCab fallback tokenizer and simplify Yomitan token flow
|
title: Remove MeCab fallback tokenizer and simplify Yomitan token flow
|
||||||
status: To Do
|
status: Done
|
||||||
assignee: []
|
assignee: []
|
||||||
created_date: '2026-02-20 00:00'
|
created_date: '2026-02-20 00:00'
|
||||||
|
updated_date: '2026-02-23 01:44'
|
||||||
labels:
|
labels:
|
||||||
- tokenizer
|
- tokenizer
|
||||||
- refactor
|
- refactor
|
||||||
@@ -14,12 +15,15 @@ priority: medium
|
|||||||
## Description
|
## Description
|
||||||
|
|
||||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||||
|
|
||||||
Remove the MeCab fallback tokenization path and associated merge-selection complexity in subtitle tokenization. Treat Yomitan parser output as the single source of token boundaries/grouping, and keep only minimal normalization needed for downstream known-word, JLPT, and frequency annotation.
|
Remove the MeCab fallback tokenization path and associated merge-selection complexity in subtitle tokenization. Treat Yomitan parser output as the single source of token boundaries/grouping, and keep only minimal normalization needed for downstream known-word, JLPT, and frequency annotation.
|
||||||
|
|
||||||
<!-- SECTION:DESCRIPTION:END -->
|
<!-- SECTION:DESCRIPTION:END -->
|
||||||
|
|
||||||
## Action Steps
|
## Action Steps
|
||||||
|
|
||||||
<!-- SECTION:PLAN:BEGIN -->
|
<!-- SECTION:PLAN:BEGIN -->
|
||||||
|
|
||||||
1. Remove MeCab fallback execution from `tokenizeSubtitle` and delete dead fallback-specific branches.
|
1. Remove MeCab fallback execution from `tokenizeSubtitle` and delete dead fallback-specific branches.
|
||||||
2. Remove merge/candidate-selection code that is only needed to reconcile MeCab-vs-Yomitan tokenization strategies.
|
2. Remove merge/candidate-selection code that is only needed to reconcile MeCab-vs-Yomitan tokenization strategies.
|
||||||
3. Keep Yomitan parsing pipeline with minimal structural token normalization only.
|
3. Keep Yomitan parsing pipeline with minimal structural token normalization only.
|
||||||
@@ -29,18 +33,42 @@ Remove the MeCab fallback tokenization path and associated merge-selection compl
|
|||||||
<!-- SECTION:PLAN:END -->
|
<!-- SECTION:PLAN:END -->
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
<!-- AC:BEGIN -->
|
<!-- AC:BEGIN -->
|
||||||
- [ ] #1 Subtitle tokenization no longer falls back to MeCab when Yomitan parsing fails.
|
|
||||||
- [ ] #2 Token grouping logic is simplified to rely on Yomitan structure; redundant custom merge-selection logic removed.
|
- [x] #1 Subtitle tokenization no longer falls back to MeCab when Yomitan parsing fails.
|
||||||
- [ ] #3 Known-word, JLPT, frequency, and N+1 annotations still work on Yomitan-derived tokens.
|
- [x] #2 Token grouping logic is simplified to rely on Yomitan structure; redundant custom merge-selection logic removed.
|
||||||
- [ ] #4 If Yomitan parsing fails, behavior is explicit and tested (for example `tokens: null` without MeCab fallback path).
|
- [x] #3 Known-word, JLPT, frequency, and N+1 annotations still work on Yomitan-derived tokens.
|
||||||
- [ ] #5 Documentation reflects that tokenization flow is Yomitan-first and Yomitan-only.
|
- [x] #4 If Yomitan parsing fails, behavior is explicit and tested (for example `tokens: null` without MeCab fallback path).
|
||||||
|
- [x] #5 Documentation reflects that tokenization flow is Yomitan-first and Yomitan-only.
|
||||||
<!-- AC:END -->
|
<!-- AC:END -->
|
||||||
|
|
||||||
|
## Implementation Notes
|
||||||
|
|
||||||
|
<!-- SECTION:NOTES:BEGIN -->
|
||||||
|
|
||||||
|
Removed MeCab fallback tokenization from `src/core/services/tokenizer.ts`; `tokenizeSubtitle` now returns `tokens: null` when Yomitan parsing/selecting yields no tokens.
|
||||||
|
|
||||||
|
Simplified parse candidate selection in `src/core/services/tokenizer/parser-selection-stage.ts` to scanning-parser sources only; added null behavior when only `mecab` parse candidates are present.
|
||||||
|
|
||||||
|
Updated tokenizer regression suites to reflect Yomitan-only flow while preserving annotation continuity checks (known-word, JLPT, frequency, N+1) in `src/core/services/tokenizer.test.ts` and `src/core/services/tokenizer/parser-selection-stage.test.ts`.
|
||||||
|
|
||||||
|
Updated docs to remove MeCab fallback positioning and clarify Yomitan-only tokenization in `docs/usage.md` and `docs/troubleshooting.md`.
|
||||||
|
|
||||||
|
Validation run passed:
|
||||||
|
|
||||||
|
- `bun test src/core/services/tokenizer/parser-selection-stage.test.ts src/core/services/tokenizer.test.ts`
|
||||||
|
- `bun test src/core/services/subtitle-processing-controller.test.ts`
|
||||||
|
- `bun run build`
|
||||||
|
- `bun run docs:build`
|
||||||
|
<!-- SECTION:NOTES:END -->
|
||||||
|
|
||||||
## Definition of Done
|
## Definition of Done
|
||||||
|
|
||||||
<!-- DOD:BEGIN -->
|
<!-- DOD:BEGIN -->
|
||||||
- [ ] #1 `src/core/services/tokenizer.ts` no longer contains MeCab fallback tokenization branch.
|
|
||||||
- [ ] #2 Tests cover Yomitan-only pipeline and failure behavior regressions.
|
- [x] #1 `src/core/services/tokenizer.ts` no longer contains MeCab fallback tokenization branch.
|
||||||
- [ ] #3 Any removed MeCab-only merge helpers are deleted with no unused exports/imports.
|
- [x] #2 Tests cover Yomitan-only pipeline and failure behavior regressions.
|
||||||
- [ ] #4 Build and relevant tokenizer/subtitle tests pass.
|
- [x] #3 Any removed MeCab-only merge helpers are deleted with no unused exports/imports.
|
||||||
|
- [x] #4 Build and relevant tokenizer/subtitle tests pass.
|
||||||
<!-- DOD:END -->
|
<!-- DOD:END -->
|
||||||
|
|||||||
@@ -22,28 +22,6 @@ SubMiner polls AnkiConnect at a regular interval (default: 3 seconds, configurab
|
|||||||
|
|
||||||
Polling uses the query `"deck:<your-deck>" added:1` to find recently added cards. If no deck is configured, it searches all decks.
|
Polling uses the query `"deck:<your-deck>" added:1` to find recently added cards. If no deck is configured, it searches all decks.
|
||||||
|
|
||||||
## Ownership Boundaries (TASK-76)
|
|
||||||
|
|
||||||
After workflow-service decomposition, ownership is split as follows:
|
|
||||||
|
|
||||||
1. **`src/anki-integration.ts` (facade/orchestrator)**
|
|
||||||
- Owns dependency wiring, config normalization, shared helpers, and runtime lifecycle (`start`, `stop`, runtime patching).
|
|
||||||
- Routes public entry points to collaborators/workflows and keeps cross-cutting state (polling/update flags, notifications, callbacks, known-word cache).
|
|
||||||
|
|
||||||
2. **`src/anki-integration/note-update-workflow.ts`**
|
|
||||||
- Owns the "new card was detected" update path.
|
|
||||||
- Loads note data, applies sentence/audio/image/misc updates, and triggers duplicate handling via auto/manual field-grouping handlers when enabled.
|
|
||||||
|
|
||||||
3. **`src/anki-integration/field-grouping-workflow.ts`**
|
|
||||||
- Owns duplicate merge execution for auto and manual grouping.
|
|
||||||
- Resolves manual choice callback, computes merged field payloads, updates kept note, optionally deletes duplicate note, and emits grouping notifications.
|
|
||||||
|
|
||||||
4. **Existing collaborators**
|
|
||||||
- `card-creation`: manual clipboard-driven updates, sentence-card creation, and card-type/tag update operations.
|
|
||||||
- `field-grouping` service: user-triggered grouping for the last added card and merge preview assembly.
|
|
||||||
- `known-word-cache`: known-word lifecycle/refresh/persistence used by N+1 highlighting.
|
|
||||||
- `polling`: periodic AnkiConnect polling, new-note detection, tracked-note state, and connection backoff.
|
|
||||||
|
|
||||||
## Field Mapping
|
## Field Mapping
|
||||||
|
|
||||||
SubMiner maps its data to your Anki note fields. Configure these under `ankiConnect.fields`:
|
SubMiner maps its data to your Anki note fields. Configure these under `ankiConnect.fields`:
|
||||||
|
|||||||
@@ -38,8 +38,6 @@ SubMiner.AppImage --generate-config --backup-overwrite
|
|||||||
- JSONC config supports comments and trailing commas.
|
- JSONC config supports comments and trailing commas.
|
||||||
- If the target file exists, SubMiner prompts to create a timestamped backup and overwrite.
|
- If the target file exists, SubMiner prompts to create a timestamped backup and overwrite.
|
||||||
- In non-interactive shells, use `--backup-overwrite` to explicitly back up and overwrite.
|
- In non-interactive shells, use `--backup-overwrite` to explicitly back up and overwrite.
|
||||||
- `bun run generate:config-example` regenerates both repository `config.example.jsonc` and docs-served `/config.example.jsonc` from the same centralized defaults.
|
|
||||||
- `make generate-config` builds and runs the same default-config generator via local Electron.
|
|
||||||
|
|
||||||
Malformed config syntax (invalid JSON/JSONC) is startup-blocking: SubMiner shows a clear parse error with the config path and asks you to fix the file and restart.
|
Malformed config syntax (invalid JSON/JSONC) is startup-blocking: SubMiner shows a clear parse error with the config path and asks you to fix the file and restart.
|
||||||
|
|
||||||
@@ -462,14 +460,6 @@ AniList CLI commands:
|
|||||||
- `--anilist-setup`: open AniList setup/auth flow helper window.
|
- `--anilist-setup`: open AniList setup/auth flow helper window.
|
||||||
- `--anilist-retry-queue`: process one ready retry queue item immediately.
|
- `--anilist-retry-queue`: process one ready retry queue item immediately.
|
||||||
|
|
||||||
AniList IPC channels:
|
|
||||||
|
|
||||||
- `anilist:get-status`: return token status + retry queue state snapshot.
|
|
||||||
- `anilist:clear-token`: clear stored AniList token and reset token status state.
|
|
||||||
- `anilist:open-setup`: open AniList setup/auth flow helper window.
|
|
||||||
- `anilist:get-queue-status`: return retry queue state snapshot.
|
|
||||||
- `anilist:retry-now`: process one ready retry queue item immediately.
|
|
||||||
|
|
||||||
### Jellyfin
|
### Jellyfin
|
||||||
|
|
||||||
Jellyfin integration is optional and disabled by default. When enabled, SubMiner can authenticate, list libraries/items, and resolve direct/transcoded playback URLs for mpv launch.
|
Jellyfin integration is optional and disabled by default. When enabled, SubMiner can authenticate, list libraries/items, and resolve direct/transcoded playback URLs for mpv launch.
|
||||||
@@ -512,26 +502,17 @@ Jellyfin integration is optional and disabled by default. When enabled, SubMiner
|
|||||||
| `transcodeVideoCodec` | string | Preferred transcode video codec fallback (default: `h264`) |
|
| `transcodeVideoCodec` | string | Preferred transcode video codec fallback (default: `h264`) |
|
||||||
|
|
||||||
Jellyfin auth session (`accessToken` + `userId`) is stored in local encrypted storage after login/setup.
|
Jellyfin auth session (`accessToken` + `userId`) is stored in local encrypted storage after login/setup.
|
||||||
Optional environment overrides: `SUBMINER_JELLYFIN_ACCESS_TOKEN`, `SUBMINER_JELLYFIN_USER_ID`.
|
|
||||||
|
|
||||||
Jellyfin direct app CLI commands (`SubMiner.AppImage ...`):
|
Launcher subcommands:
|
||||||
|
|
||||||
- `--jellyfin`: open the in-app Jellyfin setup window (server/user/password form).
|
|
||||||
- `--jellyfin-login` with `--jellyfin-server`, `--jellyfin-username`, `--jellyfin-password`: authenticate and store token/session data.
|
|
||||||
- `--jellyfin-logout`: clear stored Jellyfin token/session data.
|
|
||||||
- `--jellyfin-libraries`: list available Jellyfin libraries.
|
|
||||||
- `--jellyfin-items`: list playable items (`--jellyfin-library-id`, optional `--jellyfin-search`, `--jellyfin-limit`).
|
|
||||||
- `--jellyfin-play`: resolve playback URL and launch (`--jellyfin-item-id`, optional audio/subtitle stream index overrides; requires connected mpv IPC).
|
|
||||||
- `--jellyfin-remote-announce`: force capability announce + visibility check in Jellyfin sessions (debug helper).
|
|
||||||
- `--jellyfin-server`: optional server URL override for Jellyfin commands.
|
|
||||||
|
|
||||||
Launcher subcommand equivalents:
|
|
||||||
|
|
||||||
- `subminer jellyfin` (or `subminer jf`) opens setup.
|
- `subminer jellyfin` (or `subminer jf`) opens setup.
|
||||||
- `subminer jellyfin -l --server ... --username ... --password ...` logs in.
|
- `subminer jellyfin -l --server ... --username ... --password ...` logs in.
|
||||||
|
- `subminer jellyfin --logout` clears stored credentials.
|
||||||
- `subminer jellyfin -p` opens play picker.
|
- `subminer jellyfin -p` opens play picker.
|
||||||
- `subminer jellyfin -d` starts cast discovery mode.
|
- `subminer jellyfin -d` starts cast discovery mode.
|
||||||
|
|
||||||
|
See [Jellyfin Integration](/jellyfin-integration) for the full setup and cast-to-device guide.
|
||||||
|
|
||||||
Jellyfin remote auto-connect runs only when all three are `true`: `jellyfin.enabled`, `jellyfin.remoteControlEnabled`, and `jellyfin.remoteControlAutoConnect`.
|
Jellyfin remote auto-connect runs only when all three are `true`: `jellyfin.enabled`, `jellyfin.remoteControlEnabled`, and `jellyfin.remoteControlAutoConnect`.
|
||||||
|
|
||||||
### Discord Rich Presence
|
### Discord Rich Presence
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ bun run build # compile dist artifacts
|
|||||||
bun run test:smoke:dist # explicit smoke scope for compiled runtime
|
bun run test:smoke:dist # explicit smoke scope for compiled runtime
|
||||||
bun run test:config:dist # optional full dist config suite
|
bun run test:config:dist # optional full dist config suite
|
||||||
bun run test:core:dist # optional full dist core suite
|
bun run test:core:dist # optional full dist core suite
|
||||||
bun run test:subtitle:dist # subtitle dist lane (currently placeholder)
|
bun run test:subtitle:dist # optional smoke lane for subtitle dist regressions
|
||||||
```
|
```
|
||||||
|
|
||||||
## Maintainability Guardrails
|
## Maintainability Guardrails
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
# Maintainability Guardrails
|
|
||||||
|
|
||||||
Purpose: keep runtime composition boundaries maintainable.
|
|
||||||
|
|
||||||
## Current Checks
|
|
||||||
|
|
||||||
- Main runtime fan-in (warning): `bun run check:main-fanin`
|
|
||||||
- Main runtime fan-in (strict): `bun run check:main-fanin:strict`
|
|
||||||
- Default main fan-in thresholds: `import lines <= 110`, `unique runtime paths <= 11`
|
|
||||||
- Runtime cycle check (warning): `bun run check:runtime-cycles`
|
|
||||||
- Runtime cycle check (strict): `bun run check:runtime-cycles:strict`
|
|
||||||
|
|
||||||
## Policy
|
|
||||||
|
|
||||||
- Keep composition/orchestration files focused on wiring.
|
|
||||||
- Do not hand-edit generated artifacts; refactor source modules.
|
|
||||||
- Keep `src/main.ts` runtime import fan-in low by routing domain imports through `src/main/runtime/domains/*` and `src/main/runtime/registry.ts`.
|
|
||||||
- Avoid runtime import cycles by extracting shared helpers into leaf modules.
|
|
||||||
@@ -36,13 +36,6 @@ Primary index coverage:
|
|||||||
- event timeline/type reads: `idx_events_session_ts`, `idx_events_type_ts`
|
- event timeline/type reads: `idx_events_session_ts`, `idx_events_type_ts`
|
||||||
- rollup reads: `idx_rollups_day_video`, `idx_rollups_month_video`
|
- rollup reads: `idx_rollups_day_video`, `idx_rollups_month_video`
|
||||||
|
|
||||||
Ownership boundaries:
|
|
||||||
|
|
||||||
- `src/core/services/immersion-tracker-service.ts`: orchestration facade (queueing, flush cadence, runtime event/session coordination).
|
|
||||||
- `src/core/services/immersion-tracker/storage.ts`: schema bootstrap, prepared statement construction, and DB record writes/updates.
|
|
||||||
- `src/core/services/immersion-tracker/session.ts`: session row lifecycle transitions (start/finalize).
|
|
||||||
- `src/core/services/immersion-tracker/metadata.ts`: local media metadata probing (`ffprobe`, sha256, parsed metadata shaping).
|
|
||||||
|
|
||||||
## Retention and Maintenance Defaults
|
## Retention and Maintenance Defaults
|
||||||
|
|
||||||
- Raw events: `7d`
|
- Raw events: `7d`
|
||||||
@@ -155,7 +148,3 @@ ORDER BY rollup_month DESC, video_id DESC
|
|||||||
LIMIT ?;
|
LIMIT ?;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Extension Points
|
|
||||||
|
|
||||||
- Adapter boundary for non-SQLite backends is tracked in `TASK-32`.
|
|
||||||
- Keep analytics/query callers bound to tracker service methods (not raw table assumptions) so persistence adapters can swap in later.
|
|
||||||
|
|||||||
173
docs/index.md
173
docs/index.md
@@ -7,16 +7,16 @@ titleTemplate: Immersion Mining Workflow for MPV
|
|||||||
hero:
|
hero:
|
||||||
name: SubMiner
|
name: SubMiner
|
||||||
text: Immersion Mining for MPV
|
text: Immersion Mining for MPV
|
||||||
tagline: Look up words, mine to Anki, and enrich cards with context — all without leaving the video.
|
tagline: Watch media, mine vocabulary, and build cards without leaving the scene.
|
||||||
image:
|
image:
|
||||||
src: /assets/SubMiner.png
|
src: /assets/SubMiner.png
|
||||||
alt: SubMiner logo
|
alt: SubMiner logo
|
||||||
actions:
|
actions:
|
||||||
- theme: brand
|
- theme: brand
|
||||||
text: Get Started
|
text: Install
|
||||||
link: /installation
|
link: /installation
|
||||||
- theme: alt
|
- theme: alt
|
||||||
text: Mining Workflow
|
text: Explore workflow
|
||||||
link: /mining-workflow
|
link: /mining-workflow
|
||||||
|
|
||||||
features:
|
features:
|
||||||
@@ -24,58 +24,124 @@ features:
|
|||||||
src: /assets/mpv.svg
|
src: /assets/mpv.svg
|
||||||
alt: mpv icon
|
alt: mpv icon
|
||||||
title: Built for mpv
|
title: Built for mpv
|
||||||
details: Connects via IPC to track subtitles in real time and render a self-contained overlay — everything bundled in a single application.
|
details: Tracks subtitles through mpv IPC in real time, with a single launch path and no external bridge services.
|
||||||
- icon:
|
- icon:
|
||||||
src: /assets/yomitan-icon.svg
|
src: /assets/yomitan-icon.svg
|
||||||
alt: Yomitan logo
|
alt: Yomitan logo
|
||||||
title: Yomitan Integration
|
title: Yomitan Integration
|
||||||
details: Hover over any word in the subtitle overlay to trigger dictionary lookups — instant definitions without leaving the player.
|
details: Keep your flow moving with instant word lookups and context-aware card creation directly from subtitles.
|
||||||
- icon:
|
- icon:
|
||||||
src: /assets/anki-card.svg
|
src: /assets/anki-card.svg
|
||||||
alt: Anki card icon
|
alt: Anki card icon
|
||||||
title: Anki Card Enrichment
|
title: Anki Card Enrichment
|
||||||
details: Add a word from Yomitan and SubMiner fills in the sentence, audio clip, screenshot, and translation automatically.
|
details: Auto-fills card fields with subtitle sentence, clipping, image, and translation so you can focus on learning.
|
||||||
- icon:
|
- icon:
|
||||||
src: /assets/dual-layer.svg
|
src: /assets/dual-layer.svg
|
||||||
alt: Dual layer icon
|
alt: Dual layer icon
|
||||||
title: Dual-Layer Subtitles
|
title: Three-Plane Overlay Stack
|
||||||
details: Interactive visible overlay plus an invisible layer aligned with mpv's own rendering for seamless click-through lookup. Both are independently controllable.
|
details: Secondary context plane + visible interactive layer + invisible interaction plane, each with independent behavior and startup state.
|
||||||
- icon:
|
- icon:
|
||||||
src: /assets/highlight.svg
|
src: /assets/highlight.svg
|
||||||
alt: Highlight icon
|
alt: Highlight icon
|
||||||
title: N+1 Highlighting
|
title: N+1 Highlighting
|
||||||
details: Marks words you already know from your Anki deck so you can spot new vocabulary and identify N+1 sentences at a glance.
|
details: Surfaces known words from your deck so unknown targets stand out during immersion sessions.
|
||||||
- icon:
|
- icon:
|
||||||
src: /assets/tokenization.svg
|
src: /assets/tokenization.svg
|
||||||
alt: Tokenization icon
|
alt: Tokenization icon
|
||||||
title: Immersion Tracking
|
title: Immersion Tracking
|
||||||
details: Every subtitle line, word, and mined card is logged to local SQLite. Daily and monthly rollups let you measure your progress over time.
|
details: Captures subtitle and mining telemetry to SQLite, with daily/monthly rollups for progress clarity.
|
||||||
- icon:
|
- icon:
|
||||||
src: /assets/subtitle-download.svg
|
src: /assets/subtitle-download.svg
|
||||||
alt: Subtitle download icon
|
alt: Subtitle download icon
|
||||||
title: Subtitle Download & Sync
|
title: Subtitle Download & Sync
|
||||||
details: Search and download Japanese subtitles from Jimaku, then sync to audio with alass or ffsubsync — all from within the player.
|
details: Pull and synchronize subtitles with Jimaku plus alass/ffsubsync in one cohesive workflow.
|
||||||
- icon:
|
- icon:
|
||||||
src: /assets/keyboard.svg
|
src: /assets/keyboard.svg
|
||||||
alt: Keyboard icon
|
alt: Keyboard icon
|
||||||
title: Keyboard-Driven
|
title: Keyboard-Driven
|
||||||
details: Mine sentences, copy subtitles, cycle display modes, and trigger field grouping — all from configurable shortcuts.
|
details: Run lookups, mining actions, clipping, and workflow toggles with one configurable shortcut surface.
|
||||||
- icon:
|
- icon:
|
||||||
src: /assets/texthooker.svg
|
src: /assets/texthooker.svg
|
||||||
alt: Texthooker icon
|
alt: Texthooker icon
|
||||||
title: Texthooker & WebSocket
|
title: Texthooker & WebSocket
|
||||||
details: Built-in texthooker page that receives subtitles over WebSocket — use it as a clipboard inserter or connect external tools.
|
details: Stream subtitles in real time to browser tools via local WebSocket and keep your stack integrated.
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<div class="landing-shell">
|
||||||
|
<section class="workflow-section">
|
||||||
|
<h2>How it fits together</h2>
|
||||||
|
<div class="workflow-steps">
|
||||||
|
<div class="workflow-step">
|
||||||
|
<div class="step-number">01</div>
|
||||||
|
<div class="step-title">Start</div>
|
||||||
|
<div class="step-desc">Launch with the wrapper or existing mpv setup and keep subtitles in sync.</div>
|
||||||
|
</div>
|
||||||
|
<div class="workflow-step">
|
||||||
|
<div class="step-number">02</div>
|
||||||
|
<div class="step-title">Lookup</div>
|
||||||
|
<div class="step-desc">Hover or click a token in the interactive overlay to open Yomitan context.</div>
|
||||||
|
</div>
|
||||||
|
<div class="workflow-step">
|
||||||
|
<div class="step-number">03</div>
|
||||||
|
<div class="step-title">Mine</div>
|
||||||
|
<div class="step-desc">Create cards from Yomitan or mine sentence cards directly from subtitle lines.</div>
|
||||||
|
</div>
|
||||||
|
<div class="workflow-step">
|
||||||
|
<div class="step-number">04</div>
|
||||||
|
<div class="step-title">Enrich</div>
|
||||||
|
<div class="step-desc">Automatically attach timing-accurate audio, sentence text, and visual evidence.</div>
|
||||||
|
</div>
|
||||||
|
<div class="workflow-step">
|
||||||
|
<div class="step-number">05</div>
|
||||||
|
<div class="step-title">Track</div>
|
||||||
|
<div class="step-desc">Review immersion history and repeat high-value patterns over time.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="demo-section">
|
||||||
|
<h2>See it in action</h2>
|
||||||
|
<p>Subtitles, lookup flow, and card enrichment from a real playback session.</p>
|
||||||
|
<video controls playsinline preload="metadata" poster="/assets/demo-poster.jpg">
|
||||||
|
<source :src="'/assets/minecard.webm'" type="video/webm" />
|
||||||
|
<source :src="'/assets/minecard.mp4'" type="video/mp4" />
|
||||||
|
<a :href="'/assets/minecard.webm'" target="_blank" rel="noreferrer">
|
||||||
|
<img :src="'/assets/minecard.gif'" alt="SubMiner demo GIF fallback" style="width: 100%; height: auto;" />
|
||||||
|
</a>
|
||||||
|
</video>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Space+Grotesk:wght@500;600;700&display=swap');
|
||||||
|
|
||||||
|
.landing-shell {
|
||||||
|
max-width: 1120px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0.5rem 1rem 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-shell,
|
||||||
|
.landing-shell .step-title,
|
||||||
|
.landing-shell h1,
|
||||||
|
.landing-shell h2 {
|
||||||
|
font-family: 'Manrope', 'Arial', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-title,
|
||||||
|
.step-number {
|
||||||
|
font-family: 'Space Grotesk', 'Manrope', 'Arial', sans-serif;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
}
|
||||||
|
|
||||||
.demo-section {
|
.demo-section {
|
||||||
max-width: 960px;
|
max-width: 960px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 0 24px;
|
padding: 2rem 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.demo-section h2 {
|
.demo-section h2 {
|
||||||
font-size: 1.5rem;
|
font-size: 1.45rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
letter-spacing: -0.01em;
|
letter-spacing: -0.01em;
|
||||||
@@ -83,7 +149,7 @@ features:
|
|||||||
|
|
||||||
.demo-section p {
|
.demo-section p {
|
||||||
color: var(--vp-c-text-2);
|
color: var(--vp-c-text-2);
|
||||||
margin-bottom: 1.25rem;
|
margin: 0 0 0.9rem;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,19 +157,19 @@ features:
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
border: 1px solid var(--vp-c-divider);
|
border: 1px solid var(--vp-c-divider);
|
||||||
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 18px 44px rgba(0, 0, 0, 0.28);
|
||||||
|
animation: card-enter 380ms ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.workflow-section {
|
.workflow-section {
|
||||||
max-width: 960px;
|
margin: 2.4rem auto 0;
|
||||||
margin: 4rem auto 0;
|
padding: 0 0 2.5rem;
|
||||||
padding: 0 24px 3rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.workflow-section h2 {
|
.workflow-section h2 {
|
||||||
font-size: 1.5rem;
|
font-size: 1.45rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1rem;
|
||||||
letter-spacing: -0.01em;
|
letter-spacing: -0.01em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,8 +195,9 @@ features:
|
|||||||
}
|
}
|
||||||
|
|
||||||
.workflow-step {
|
.workflow-step {
|
||||||
padding: 1.25rem 1.5rem;
|
padding: 1.1rem 1.25rem;
|
||||||
background: var(--vp-c-bg-soft);
|
background: var(--vp-c-bg-soft);
|
||||||
|
animation: card-enter 330ms ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.workflow-step .step-number {
|
.workflow-step .step-number {
|
||||||
@@ -154,52 +221,16 @@ features:
|
|||||||
color: var(--vp-c-text-2);
|
color: var(--vp-c-text-2);
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes card-enter {
|
||||||
|
from {
|
||||||
|
opacity: 0.8;
|
||||||
|
transform: translateY(8px);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="workflow-section">
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
<div class="workflow-steps">
|
|
||||||
<div class="workflow-step">
|
|
||||||
<div class="step-number">01</div>
|
|
||||||
<div class="step-title">Watch</div>
|
|
||||||
<div class="step-desc">Play a video in mpv. SubMiner connects via IPC and captures subtitles in real time.</div>
|
|
||||||
</div>
|
|
||||||
<div class="workflow-step">
|
|
||||||
<div class="step-number">02</div>
|
|
||||||
<div class="step-title">Look Up</div>
|
|
||||||
<div class="step-desc">Hover over a word in the subtitle overlay to trigger a Yomitan lookup — no browser or tab-switching needed.</div>
|
|
||||||
</div>
|
|
||||||
<div class="workflow-step">
|
|
||||||
<div class="step-number">03</div>
|
|
||||||
<div class="step-title">Mine</div>
|
|
||||||
<div class="step-desc">Add the word to Anki from Yomitan. SubMiner detects the new card automatically.</div>
|
|
||||||
</div>
|
|
||||||
<div class="workflow-step">
|
|
||||||
<div class="step-number">04</div>
|
|
||||||
<div class="step-title">Enrich</div>
|
|
||||||
<div class="step-desc">SubMiner fills in the sentence, audio clip, screenshot, and translation — no extra steps.</div>
|
|
||||||
</div>
|
|
||||||
<div class="workflow-step">
|
|
||||||
<div class="step-number">05</div>
|
|
||||||
<div class="step-title">Track</div>
|
|
||||||
<div class="step-desc">Every line seen and card mined is logged to local SQLite. Daily and monthly rollups let you measure immersion over time.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="demo-section">
|
|
||||||
|
|
||||||
## See It in Action
|
|
||||||
|
|
||||||
<video controls playsinline preload="metadata" poster="/assets/demo-poster.jpg">
|
|
||||||
<source :src="'/assets/minecard.webm'" type="video/webm" />
|
|
||||||
<source :src="'/assets/minecard.mp4'" type="video/mp4" />
|
|
||||||
<a :href="'/assets/minecard.webm'" target="_blank" rel="noreferrer">
|
|
||||||
<img :src="'/assets/minecard.gif'" alt="SubMiner demo GIF fallback" style="width: 100%; height: auto;" />
|
|
||||||
</a>
|
|
||||||
</video>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|||||||
@@ -225,7 +225,4 @@ SubMiner.AppImage --help # Show all CLI options
|
|||||||
|
|
||||||
You should see the overlay appear over mpv. If subtitles are loaded in the video, they will appear as interactive text in the overlay.
|
You should see the overlay appear over mpv. If subtitles are loaded in the video, they will appear as interactive text in the overlay.
|
||||||
|
|
||||||
Release/pre-release gate: run `bun run test:launcher:smoke:src` to validate launcher -> mpv IPC socket -> overlay start/stop wiring.
|
|
||||||
If the smoke lane fails, inspect `.tmp/launcher-smoke` artifacts locally; CI/release quality gates upload the same artifacts on failure.
|
|
||||||
|
|
||||||
Next: [Usage](/usage) — learn about the `subminer` wrapper, keybindings, and YouTube playback.
|
Next: [Usage](/usage) — learn about the `subminer` wrapper, keybindings, and YouTube playback.
|
||||||
|
|||||||
@@ -40,22 +40,6 @@ For reproducible updates:
|
|||||||
This repository currently ships the folder path in `electron-builder` `extraResources` as:
|
This repository currently ships the folder path in `electron-builder` `extraResources` as:
|
||||||
`vendor/yomitan-jlpt-vocab -> yomitan-jlpt-vocab`.
|
`vendor/yomitan-jlpt-vocab -> yomitan-jlpt-vocab`.
|
||||||
|
|
||||||
## Deterministic fallback behavior on malformed inputs
|
## Fallback Behavior
|
||||||
|
|
||||||
`createJlptVocabularyLookupService()` follows these rules:
|
If bank files are missing, malformed, or lack expected metadata, SubMiner skips them gracefully. When no usable entries are found, JLPT underlining is silently disabled and subtitle rendering remains unchanged.
|
||||||
|
|
||||||
- If a bank file is missing, parsing fails, or the JSON shape is unsupported, that file is skipped and processing continues.
|
|
||||||
- If entries do not expose expected frequency metadata, they are skipped.
|
|
||||||
- If no usable bank entries are found, SubMiner initializes a no-op JLPT lookup (`null` for every token).
|
|
||||||
- In all fallback cases, subtitle rendering remains unchanged (no underlines are added).
|
|
||||||
|
|
||||||
## Bundle size and startup cost
|
|
||||||
|
|
||||||
Lookup work is currently a synchronous file read + parse at enable-time and then O(1) in-memory `Map` lookups during subtitle updates.
|
|
||||||
|
|
||||||
Practical guidance:
|
|
||||||
|
|
||||||
- Keep the JLPT bundle inside `vendor/yomitan-jlpt-vocab` to avoid network lookups.
|
|
||||||
- Measure bundle size with:
|
|
||||||
- `du -sh vendor/yomitan-jlpt-vocab`
|
|
||||||
- If the JLPT source is updated, re-run `bun run build:appimage` / packaging and confirm startup logs do not report missing banks.
|
|
||||||
|
|||||||
@@ -96,10 +96,3 @@ Use `subminer <subcommand> -h` for command-specific help.
|
|||||||
- `--background` mode defaults to `warn` unless `--log-level` is explicitly set
|
- `--background` mode defaults to `warn` unless `--log-level` is explicitly set
|
||||||
- `--dev` / `--debug` control app behavior, not logging verbosity — use `--log-level` for that
|
- `--dev` / `--debug` control app behavior, not logging verbosity — use `--log-level` for that
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
Run launcher regression tests (config discovery + command branching):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bun run test:launcher
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ SubMiner now prioritizes subtitle responsiveness over heavy initialization:
|
|||||||
|
|
||||||
This keeps early playback snappy and avoids mpv-side sluggishness while startup work completes.
|
This keeps early playback snappy and avoids mpv-side sluggishness while startup work completes.
|
||||||
|
|
||||||
## The Two Overlay Layers
|
## The Three Overlay Planes
|
||||||
|
|
||||||
SubMiner uses two overlay layers, each serving a different purpose.
|
SubMiner uses three overlay planes, each serving a different purpose.
|
||||||
|
|
||||||
### Visible Overlay
|
### Visible Overlay
|
||||||
|
|
||||||
The visible overlay renders subtitles as tokenized, clickable word spans. Each word is a separate element with reading and headword data attached. This layer is styled independently from mpv subtitles and supports:
|
The visible overlay renders subtitles as tokenized, clickable word spans. Each word is a separate element with reading and headword data attached. This plane is styled independently from mpv subtitles and supports:
|
||||||
|
|
||||||
- Word-level click targets for Yomitan lookup
|
- Word-level click targets for Yomitan lookup
|
||||||
- Right-click to pause/resume
|
- Right-click to pause/resume
|
||||||
@@ -40,15 +40,29 @@ The visible overlay renders subtitles as tokenized, clickable word spans. Each w
|
|||||||
|
|
||||||
Toggle with `Alt+Shift+O` (global) or `y-t` (mpv plugin).
|
Toggle with `Alt+Shift+O` (global) or `y-t` (mpv plugin).
|
||||||
|
|
||||||
|
### Secondary Subtitle Plane
|
||||||
|
|
||||||
|
The secondary plane is a compact top-strip layer for translation and context visibility while keeping primary reading flow below. It mirrors your configured secondary subtitle preference and can be independently shown or hidden.
|
||||||
|
|
||||||
|
It is controlled by `secondarySub` configuration and shares lifecycle with the overlay stack.
|
||||||
|
|
||||||
### Invisible Overlay
|
### Invisible Overlay
|
||||||
|
|
||||||
The invisible overlay is a transparent layer that aligns precisely with mpv's own subtitle rendering. It reproduces the subtitle text at the exact position and size mpv uses, so you can click directly on the subtitles you see in the video.
|
The invisible overlay is a transparent layer aligned with mpv's own subtitle rendering. It uses mpv's subtitle metrics (font size, margins, position, scaling) to map click targets accurately.
|
||||||
|
|
||||||
This layer uses mpv's subtitle render metrics (font size, margins, position, scaling) and converts them from mpv's scaled-pixel system (reference height 720) to actual screen pixels.
|
This layer still supports:
|
||||||
|
|
||||||
Toggle with `Alt+Shift+I` (global) or `y-i` (mpv plugin).
|
- Word-level click-through lookups over the text region
|
||||||
|
- Optional manual position fine-tuning in pixel mode
|
||||||
|
- Independent toggle behavior with global shortcuts
|
||||||
|
|
||||||
**Position edit mode**: Press `Ctrl/Cmd+Shift+P` to enter edit mode, then use arrow keys (or `hjkl`) to nudge the position. `Shift` moves 4 px at a time. Press `Enter` or `Ctrl+S` to save, `Esc` to cancel.
|
Position edit mode is available via `Ctrl/Cmd+Shift+P`, then arrow keys / `hjkl` to nudge position; `Shift` moves faster. Save with `Enter` or `Ctrl+S`, cancel with `Esc`.
|
||||||
|
|
||||||
|
Toggle controls:
|
||||||
|
|
||||||
|
- `Alt+Shift+O` / `y-t`: visible overlay
|
||||||
|
- `Alt+Shift+I` / `y-i`: invisible overlay
|
||||||
|
- Secondary plane visibility is controlled via `secondarySub` config and matching global shortcuts.
|
||||||
|
|
||||||
## Looking Up Words
|
## Looking Up Words
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
# Structure Roadmap (Archived)
|
|
||||||
|
|
||||||
This page previously contained TASK-27 migration planning details.
|
|
||||||
|
|
||||||
- Canonical runtime architecture guidance now lives in `docs/architecture.md`.
|
|
||||||
- Contributor-facing implementation expectations are in `docs/development.md` and link back to `docs/architecture.md`.
|
|
||||||
- Historical task-level migration context is preserved in Backlog task records and archive folders.
|
|
||||||
@@ -87,4 +87,6 @@ Read first. Keep concise.
|
|||||||
| `opencode-task103-jellyfin-main-composer-20260222T221152Z-n3p7` | `opencode-task103-jellyfin-main-composer` | `Implement TASK-103 Jellyfin runtime wiring extraction from main.ts into composer module(s), tests, docs, and required validations (no commit).` | `in_progress` | `docs/subagents/agents/opencode-task103-jellyfin-main-composer-20260222T221152Z-n3p7.md` | `2026-02-22T22:11:52Z` |
|
| `opencode-task103-jellyfin-main-composer-20260222T221152Z-n3p7` | `opencode-task103-jellyfin-main-composer` | `Implement TASK-103 Jellyfin runtime wiring extraction from main.ts into composer module(s), tests, docs, and required validations (no commit).` | `in_progress` | `docs/subagents/agents/opencode-task103-jellyfin-main-composer-20260222T221152Z-n3p7.md` | `2026-02-22T22:11:52Z` |
|
||||||
| `opencode-task109-discord-presence-20260223T011027Z-j9r4` | `opencode-task109-discord-presence` | `Finalize TASK-109 Discord Rich Presence with plan-first workflow and backlog closure.` | `in_progress` | `docs/subagents/agents/opencode-task109-discord-presence-20260223T011027Z-j9r4.md` | `2026-02-23T01:15:39Z` |
|
| `opencode-task109-discord-presence-20260223T011027Z-j9r4` | `opencode-task109-discord-presence` | `Finalize TASK-109 Discord Rich Presence with plan-first workflow and backlog closure.` | `in_progress` | `docs/subagents/agents/opencode-task109-discord-presence-20260223T011027Z-j9r4.md` | `2026-02-23T01:15:39Z` |
|
||||||
| `codex-task88-yomitan-flow-20260223T012755Z-x4m2` | `codex-task88-yomitan-flow` | `Execute TASK-88 remove MeCab fallback tokenizer and simplify Yomitan token flow via plan-first workflow (no commit).` | `handoff` | `docs/subagents/agents/codex-task88-yomitan-flow-20260223T012755Z-x4m2.md` | `2026-02-23T01:44:16Z` |
|
| `codex-task88-yomitan-flow-20260223T012755Z-x4m2` | `codex-task88-yomitan-flow` | `Execute TASK-88 remove MeCab fallback tokenizer and simplify Yomitan token flow via plan-first workflow (no commit).` | `handoff` | `docs/subagents/agents/codex-task88-yomitan-flow-20260223T012755Z-x4m2.md` | `2026-02-23T01:44:16Z` |
|
||||||
| `codex-overlay-three-window-layout-20260223T021606Z-9z2t` | `codex-overlay-three-window-layout` | `Implement top-anchored secondary subtitle overlay window (20%) plus swappable primary overlay region (80%).` | `handoff` | `docs/subagents/agents/codex-overlay-three-window-layout-20260223T021606Z-9z2t.md` | `2026-02-23T02:29:51Z` |
|
| `codex-overlay-three-window-layout-20260223T021606Z-9z2t` | `codex-overlay-three-window-layout` | `Implement top-anchored secondary subtitle overlay window (20%) plus swappable primary overlay region (80%).` | `handoff` | `docs/subagents/agents/codex-overlay-three-window-layout-20260223T021606Z-9z2t.md` | `2026-02-23T02:44:37Z` |
|
||||||
|
| `opencode-task110-backlog-sync-20260223T025059Z-k3m7` | `opencode-task110-backlog-sync` | `Verify TASK-110 completion state and synchronize backlog metadata with plan-first workflow.` | `handoff` | `docs/subagents/agents/opencode-task110-backlog-sync-20260223T025059Z-k3m7.md` | `2026-02-23T02:53:30Z` |
|
||||||
|
| `codex-docs-page-polish-20260223T025932Z-b7k2` | `codex-docs-page-polish` | `Polish docs landing page and sync public workflow docs with current overlay stack.` | `handoff` | `docs/subagents/agents/codex-docs-page-polish-20260223T025932Z-b7k2.md` | `2026-02-23T03:19:20Z` |
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Agent: `codex-docs-page-polish-20260223T025932Z-b7k2`
|
||||||
|
|
||||||
|
- alias: `codex-docs-page-polish`
|
||||||
|
- mission: `Polish homepage/docs presentation for production readiness and remove stale overlay documentation`
|
||||||
|
- status: `handoff`
|
||||||
|
- branch: `<current>`
|
||||||
|
- started_at: `2026-02-23T02:59:52Z`
|
||||||
|
- heartbeat_minutes: `5`
|
||||||
|
|
||||||
|
## Current Work
|
||||||
|
- [2026-02-23T02:59:52Z] intent: redesign `docs/index.md` into a production-style landing page and remove outdated two-layer wording in workflow docs.
|
||||||
|
- [2026-02-23T03:05:12Z] progress: updated homepage structure, styling, and messaging; updated `docs/mining-workflow.md` to reflect three overlay planes.
|
||||||
|
- [2026-02-23T03:10:47Z] handoff: pending completion of subagent bookkeeping and final handoff summary.
|
||||||
|
- [2026-02-23T03:20:10Z] handoff: completed docs production pass; validated updates in `docs/index.md`, `docs/mining-workflow.md`, `docs/development.md`, and subagent protocol files.
|
||||||
|
|
||||||
|
## Files Touched
|
||||||
|
- `docs/index.md`
|
||||||
|
- `docs/mining-workflow.md`
|
||||||
|
- `docs/subagents/INDEX.md`
|
||||||
|
- `docs/subagents/collaboration.md`
|
||||||
|
|
||||||
|
## Assumptions
|
||||||
|
- Repo overlay behavior now uses three overlay planes (visible, invisible, secondary), and docs should reflect that in user-facing guides.
|
||||||
|
|
||||||
|
## Open Questions / Blockers
|
||||||
|
- None.
|
||||||
|
|
||||||
|
## Next Step
|
||||||
|
- Update subagent index/collaboration rows, then finalize with summary of docs cleanup.
|
||||||
@@ -41,6 +41,7 @@
|
|||||||
- `2026-02-23T02:24:10Z` implementation: added `secondary` overlay window kind/wiring, overlay-manager secondary window ownership, and geometry split helper (`top 20%` secondary + `bottom 80%` primary).
|
- `2026-02-23T02:24:10Z` implementation: added `secondary` overlay window kind/wiring, overlay-manager secondary window ownership, and geometry split helper (`top 20%` secondary + `bottom 80%` primary).
|
||||||
- `2026-02-23T02:27:40Z` renderer updates: added `secondary` layer detection, disabled measurement reports for secondary layer, and CSS layer split (secondary hidden in primary layers; subtitle/modals hidden in secondary layer).
|
- `2026-02-23T02:27:40Z` renderer updates: added `secondary` layer detection, disabled measurement reports for secondary layer, and CSS layer split (secondary hidden in primary layers; subtitle/modals hidden in secondary layer).
|
||||||
- `2026-02-23T02:29:51Z` validation: `bun run tsc --noEmit`; `bun test src/main/runtime/overlay-window-factory.test.ts src/main/runtime/overlay-window-factory-main-deps.test.ts src/main/runtime/overlay-window-runtime-handlers.test.ts src/renderer/error-recovery.test.ts src/core/services/overlay-window.test.ts`; `bun run build`; `node --test dist/core/services/overlay-manager.test.js`.
|
- `2026-02-23T02:29:51Z` validation: `bun run tsc --noEmit`; `bun test src/main/runtime/overlay-window-factory.test.ts src/main/runtime/overlay-window-factory-main-deps.test.ts src/main/runtime/overlay-window-runtime-handlers.test.ts src/renderer/error-recovery.test.ts src/core/services/overlay-window.test.ts`; `bun run build`; `node --test dist/core/services/overlay-manager.test.js`.
|
||||||
|
- `2026-02-23T02:44:37Z` backlog sync: updated `TASK-110` with final summary + commit reference (`b8f7d5e`).
|
||||||
|
|
||||||
## Files Touched
|
## Files Touched
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# Agent: `opencode-task110-backlog-sync-20260223T025059Z-k3m7`
|
||||||
|
|
||||||
|
- alias: `opencode-task110-backlog-sync`
|
||||||
|
- mission: `Verify TASK-110 completion state and synchronize backlog metadata with plan-first workflow.`
|
||||||
|
- status: `handoff`
|
||||||
|
- branch: `main`
|
||||||
|
- started_at: `2026-02-23T02:50:59Z`
|
||||||
|
- heartbeat_minutes: `5`
|
||||||
|
|
||||||
|
## Current Work (newest first)
|
||||||
|
|
||||||
|
- [2026-02-23T02:53:30Z] completed: wrote closure plan artifact, recorded plan on TASK-110, verified commit/code evidence (including parallel subagent checks), and appended verification note in backlog while keeping status `Done`.
|
||||||
|
- [2026-02-23T02:52:40Z] progress: dispatched parallel subagents for commit-scope audit and implementation-evidence audit; both confirmed AC alignment.
|
||||||
|
- [2026-02-23T02:50:59Z] intent: load TASK-110 context from Backlog MCP, write closure verification plan, execute plan, and update backlog metadata if any gap remains.
|
||||||
|
- [2026-02-23T02:50:59Z] assumptions: TASK-110 implementation already landed; this pass is verification + backlog synchronization only.
|
||||||
|
|
||||||
|
## Files Touched
|
||||||
|
|
||||||
|
- `docs/subagents/INDEX.md`
|
||||||
|
- `docs/subagents/collaboration.md`
|
||||||
|
- `docs/subagents/agents/opencode-task110-backlog-sync-20260223T025059Z-k3m7.md`
|
||||||
|
- `docs/plans/2026-02-23-task-110-overlay-closure-verification.md`
|
||||||
|
- `backlog/tasks/task-110 - Split-overlay-into-top-secondary-bar-and-bottom-primary-region.md` (via Backlog MCP)
|
||||||
|
|
||||||
|
## Assumptions
|
||||||
|
|
||||||
|
- Backlog MCP task record is source of truth for completion state.
|
||||||
|
- No code edits are required unless validation uncovers missing closure evidence.
|
||||||
|
|
||||||
|
## Open Questions / Blockers
|
||||||
|
|
||||||
|
- None.
|
||||||
|
|
||||||
|
## Next Step
|
||||||
|
|
||||||
|
- Await user confirmation; no further TASK-110 work required unless additional closure metadata is requested.
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
Shared notes. Append-only.
|
Shared notes. Append-only.
|
||||||
|
|
||||||
- [YYYY-MM-DDTHH:MM:SSZ] [agent_id|alias] note, question, dependency, conflict, decision.
|
- [YYYY-MM-DDTHH:MM:SSZ] [agent_id|alias] note, question, dependency, conflict, decision.
|
||||||
|
- [2026-02-23T03:10:47Z] [codex-docs-page-polish-20260223T025932Z-b7k2|codex-docs-page-polish] started a docs production pass to refresh `docs/index.md` landing structure and align `docs/mining-workflow.md` with current three-plane overlay behavior; added own task row in `docs/subagents/INDEX.md`.
|
||||||
|
- [2026-02-23T03:20:10Z] [codex-docs-page-polish-20260223T025932Z-b7k2|codex-docs-page-polish] completed pass: polished docs homepage design, updated outdated overlay wording in workflow guide, removed placeholder note in dev docs, and updated subagent index/collaboration records.
|
||||||
- [2026-02-19T08:21:11Z] [codex-main|planner-exec] conflict note: `docs/subagents/INDEX.md` and `docs/subagents/agents/codex-main.md` were externally updated to TASK-69 while TASK-38 work was in-flight; reconciled own row/file back to TASK-38 handoff state.
|
- [2026-02-19T08:21:11Z] [codex-main|planner-exec] conflict note: `docs/subagents/INDEX.md` and `docs/subagents/agents/codex-main.md` were externally updated to TASK-69 while TASK-38 work was in-flight; reconciled own row/file back to TASK-38 handoff state.
|
||||||
- [2026-02-20T00:01:40Z] [codex-anilist-deeplink|anilist-deeplink] preparing commit; scoping staged set to repo changes, excluding external reference dirs (vendor/yomitan-jlpt-vocab, mpv-anilist-updater).
|
- [2026-02-20T00:01:40Z] [codex-anilist-deeplink|anilist-deeplink] preparing commit; scoping staged set to repo changes, excluding external reference dirs (vendor/yomitan-jlpt-vocab, mpv-anilist-updater).
|
||||||
- [2026-02-20T05:42:54Z] [codex-subtitle-bg-20260220T054247Z-h9cu|codex-subtitle-bg] short config tweak requested: update default subtitle background color; scoping to config defaults/tests only.
|
- [2026-02-20T05:42:54Z] [codex-subtitle-bg-20260220T054247Z-h9cu|codex-subtitle-bg] short config tweak requested: update default subtitle background color; scoping to config defaults/tests only.
|
||||||
@@ -152,3 +154,6 @@ Shared notes. Append-only.
|
|||||||
- [2026-02-23T01:44:16Z] [codex-task88-yomitan-flow-20260223T012755Z-x4m2|codex-task88-yomitan-flow] completed TASK-88 implementation pass: removed MeCab fallback branch from `tokenizeSubtitle`, restricted parser-selection to `scanning-parser` candidates, refreshed tokenizer regressions for Yomitan-only flow, updated usage/troubleshooting docs, and verified tokenizer+subtitle suites/build/docs-build green.
|
- [2026-02-23T01:44:16Z] [codex-task88-yomitan-flow-20260223T012755Z-x4m2|codex-task88-yomitan-flow] completed TASK-88 implementation pass: removed MeCab fallback branch from `tokenizeSubtitle`, restricted parser-selection to `scanning-parser` candidates, refreshed tokenizer regressions for Yomitan-only flow, updated usage/troubleshooting docs, and verified tokenizer+subtitle suites/build/docs-build green.
|
||||||
- [2026-02-23T02:16:06Z] [codex-overlay-three-window-layout-20260223T021606Z-9z2t|codex-overlay-three-window-layout] overlap note: implementing user-requested 3-window overlay layout (`secondary` top bar + `visible|invisible` bottom region) in `src/core/services/overlay-window.ts`, `src/core/services/overlay-runtime-init.ts`, `src/main.ts`, renderer layer handling/CSS, and focused runtime/core tests.
|
- [2026-02-23T02:16:06Z] [codex-overlay-three-window-layout-20260223T021606Z-9z2t|codex-overlay-three-window-layout] overlap note: implementing user-requested 3-window overlay layout (`secondary` top bar + `visible|invisible` bottom region) in `src/core/services/overlay-window.ts`, `src/core/services/overlay-runtime-init.ts`, `src/main.ts`, renderer layer handling/CSS, and focused runtime/core tests.
|
||||||
- [2026-02-23T02:29:51Z] [codex-overlay-three-window-layout-20260223T021606Z-9z2t|codex-overlay-three-window-layout] completed TASK-110 implementation: added `secondary` overlay window kind + manager ownership, enforced top-20%/bottom-80% bounds split in main runtime updates, hid secondary bar in primary renderer layers, and validated via focused tests + tsc + build + dist overlay-manager test.
|
- [2026-02-23T02:29:51Z] [codex-overlay-three-window-layout-20260223T021606Z-9z2t|codex-overlay-three-window-layout] completed TASK-110 implementation: added `secondary` overlay window kind + manager ownership, enforced top-20%/bottom-80% bounds split in main runtime updates, hid secondary bar in primary renderer layers, and validated via focused tests + tsc + build + dist overlay-manager test.
|
||||||
|
- [2026-02-23T02:44:37Z] [codex-overlay-three-window-layout-20260223T021606Z-9z2t|codex-overlay-three-window-layout] backlog sync requested post-commit; updated TASK-110 `updated_date`, added commit reference (`b8f7d5e`), and added final summary block.
|
||||||
|
- [2026-02-23T02:50:59Z] [opencode-task110-backlog-sync-20260223T025059Z-k3m7|opencode-task110-backlog-sync] starting TASK-110 closure verification pass via Backlog MCP + writing-plans/executing-plans workflow; scope backlog metadata validation/sync only unless missing evidence is found.
|
||||||
|
- [2026-02-23T02:53:30Z] [opencode-task110-backlog-sync-20260223T025059Z-k3m7|opencode-task110-backlog-sync] completed verification/sync: recorded closure plan, revalidated commit/code evidence (parallel subagent audits), appended TASK-110 verification note, and confirmed task remains Done with all AC checked.
|
||||||
|
|||||||
Reference in New Issue
Block a user