mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-20 03:16:46 -07:00
feat(stats): add v1 immersion stats dashboard (#19)
This commit is contained in:
@@ -1,20 +1,19 @@
|
||||
---
|
||||
id: TASK-100
|
||||
title: 'Add configurable texthooker startup launch'
|
||||
title: Add configurable texthooker startup launch
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-06 23:30'
|
||||
updated_date: '2026-03-07 01:59'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels: []
|
||||
dependencies: []
|
||||
priority: medium
|
||||
ordinal: 10000
|
||||
ordinal: 11010
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Add a config option under `texthooker` to launch the built-in texthooker server automatically when SubMiner starts.
|
||||
|
||||
Scope:
|
||||
@@ -24,26 +23,20 @@ Scope:
|
||||
- Start the existing texthooker server during normal app startup when enabled.
|
||||
- Keep `texthooker.openBrowser` as separate behavior.
|
||||
- Add regression coverage and update generated config docs/example.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Default config enables automatic texthooker startup.
|
||||
- [x] #2 Config parser accepts valid boolean values and warns on invalid values.
|
||||
- [x] #3 App-ready startup launches texthooker when enabled.
|
||||
- [x] #4 Generated config template/example documents the new option.
|
||||
|
||||
<!-- AC:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Added `texthooker.launchAtStartup` with a default of `true`, wired it through config defaults/validation/template generation, and started the existing texthooker server during app-ready startup without coupling it to browser auto-open behavior.
|
||||
|
||||
Also added regression coverage for config parsing/template output and app-ready dependency wiring, then regenerated the checked-in config example artifacts.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -4,7 +4,7 @@ title: Index AniList character alternative names in the character dictionary
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-07 00:00'
|
||||
updated_date: '2026-03-08 00:11'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- dictionary
|
||||
- anilist
|
||||
@@ -13,20 +13,17 @@ references:
|
||||
- src/main/character-dictionary-runtime.ts
|
||||
- src/main/character-dictionary-runtime.test.ts
|
||||
priority: high
|
||||
ordinal: 71500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Index AniList character alternative names in generated character dictionaries so aliases like Shadow resolve during subtitle lookup instead of falling through to unrelated generic dictionary entries.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Character fetch reads AniList alternative character names needed for lookup coverage
|
||||
- [x] #2 Generated term banks include alias-derived terms for subtitle lookups like シャドウ
|
||||
- [x] #3 Regression coverage proves alternative-name indexing works end to end
|
||||
@@ -35,11 +32,9 @@ Index AniList character alternative names in generated character dictionaries so
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Character dictionary generation now requests AniList `name.alternative`, indexes those aliases as term candidates, and expands mixed aliases like `Minoru Kagenou (影野ミノル)` into usable outer/inner variants. Also extended kana alias synthesis so the AniList alias `Shadow` emits `シャドウ`, which matches the subtitle token the user hit in The Eminence in Shadow.
|
||||
|
||||
Bumped the character-dictionary snapshot format to invalidate stale cached snapshots, and updated merged-dictionary rebuilds to refresh invalid snapshots before composing the ZIP so old cache files do not hard-fail the merge path.
|
||||
|
||||
Verified with `bun test src/main/character-dictionary-runtime.test.ts` and `bun run tsc --noEmit`.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-06 21:20'
|
||||
updated_date: '2026-03-06 21:33'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels: []
|
||||
dependencies: []
|
||||
references:
|
||||
@@ -13,12 +13,12 @@ references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/core/services/cli-command.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main.ts
|
||||
priority: medium
|
||||
ordinal: 77500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Make the packaged Linux no-arg launch path behave like a quiet background start instead of surfacing startup-only noise.
|
||||
|
||||
Scope:
|
||||
@@ -30,9 +30,7 @@ Scope:
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Initial background launch reaches the start path without logging `No running instance. Use --start to launch the app.`
|
||||
- [x] #2 Default startup no longer emits the `Applied --password-store gnome-libsecret` line at normal log levels.
|
||||
- [x] #3 Entry/background launch sanitization suppresses the observed `ExperimentalWarning: SQLite...` and `lsfg-vk ... unsupported configuration version` startup noise.
|
||||
@@ -42,7 +40,6 @@ Scope:
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Normalized no-arg/password-store-only entry launches to append implicit `--start --background`, and upgraded `--background`-only entry launches to include `--start`.
|
||||
|
||||
Applied shared entry env sanitization before loading the main process so default startup strips the `lsfg-vk` Vulkan layer and sets `NODE_NO_WARNINGS=1`; background children keep the same sanitized env.
|
||||
@@ -55,13 +52,11 @@ Verification:
|
||||
- `bun run test:fast`
|
||||
|
||||
Note: the final `node --experimental-sqlite --test dist/main/runtime/registry.test.js` step in `bun run test:fast` still prints Node's own experimental SQLite warning because that test command explicitly enables the feature flag outside the app entrypoint.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Default packaged startup is now quiet and behaves like an implicit `--start --background` launch.
|
||||
|
||||
- No-arg AppImage entry launches now append `--start --background`, and `--background`-only launches append the missing `--start`.
|
||||
|
||||
@@ -5,27 +5,24 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-07 02:20'
|
||||
updated_date: '2026-03-07 02:20'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- texthooker
|
||||
- websocket
|
||||
- subtitle
|
||||
dependencies: []
|
||||
priority: medium
|
||||
ordinal: 73500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Add a separate annotated subtitle websocket for bundled texthooker so token/JLPT/frequency markup is available on a stable dedicated port even when the regular websocket is in `auto` mode and skipped because `mpv_websocket` is installed.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Regular `websocket.enabled: "auto"` behavior remains unchanged and still skips the regular websocket when `mpv_websocket` is installed.
|
||||
- [x] #2 A separate `annotationWebsocket` config controls an independent annotated websocket with default port `6678`.
|
||||
- [x] #3 Bundled texthooker is pointed at the annotation websocket when it is enabled.
|
||||
@@ -35,9 +32,7 @@ Add a separate annotated subtitle websocket for bundled texthooker so token/JLPT
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Added `annotationWebsocket.enabled`/`annotationWebsocket.port` with defaults of `true`/`6678`, started that websocket independently from the regular auto-managed websocket, and injected the bundled texthooker websocket URL so it connects to the annotation feed by default.
|
||||
|
||||
Also added focused regression coverage and regenerated the checked-in config examples.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-06 21:45'
|
||||
updated_date: '2026-03-06 21:45'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- texthooker
|
||||
- subtitle
|
||||
@@ -14,24 +14,23 @@ dependencies:
|
||||
- TASK-103
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/core/services/subtitle-ws.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/vendor/texthooker-ui/src/components/App.svelte
|
||||
- /home/sudacode/projects/japanese/SubMiner/vendor/texthooker-ui/src/line-markup.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/vendor/texthooker-ui/src/components/App.svelte
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/vendor/texthooker-ui/src/line-markup.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/vendor/texthooker-ui/src/app.css
|
||||
priority: medium
|
||||
ordinal: 76500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Bring bundled texthooker annotation rendering closer to the visible overlay. Keep the lightweight texthooker UX, but preserve token metadata for hover, match overlay color-precedence rules across known/N+1/name/frequency/JLPT, expose name-match highlighting as a toggle, and emit a structured annotation payload on the dedicated websocket so non-SubMiner clients can treat it as an API.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Annotation websocket payload includes both rendered `sentence` HTML and structured token metadata for generic clients.
|
||||
- [x] #2 Vendored texthooker preserves annotation metadata attrs needed for hover labels and uses overlay-matching color precedence rules.
|
||||
- [x] #3 Vendored texthooker supports character-name highlighting with a user-facing toggle and standalone-web note.
|
||||
@@ -42,7 +41,5 @@ Bring bundled texthooker annotation rendering closer to the visible overlay. Kee
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Extended the dedicated annotation websocket payload to ship `version`, plain `text`, rendered `sentence`, and structured `tokens` metadata while keeping backward-compatible `sentence` consumers working. Updated the vendored texthooker to preserve hover metadata attrs, follow overlay color precedence for known/N+1/name/frequency/JLPT annotations, add a character-name highlight toggle plus standalone-web dictionary note, and render lightweight hover labels for frequency/JLPT metadata. Added focused regression coverage and rebuilt both the vendored texthooker bundle and SubMiner.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -4,17 +4,16 @@ title: Stop local docs artifact writes after docs repo split
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-07 00:00'
|
||||
updated_date: '2026-03-07 00:20'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels: []
|
||||
dependencies: []
|
||||
priority: medium
|
||||
ordinal: 10500
|
||||
ordinal: 12010
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Now that user-facing docs live in `../subminer-docs`, first-party scripts in this repo should not keep writing generated artifacts into the local `docs/` tree.
|
||||
|
||||
Scope:
|
||||
@@ -23,25 +22,19 @@ Scope:
|
||||
- Keep repo-local outputs only where they are still intentionally owned by this repo.
|
||||
- Repoint generated docs artifacts to `../subminer-docs` when that is the maintained source of truth.
|
||||
- Add regression coverage for the config-example generation path contract.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 The config-example generator no longer writes to `docs/public/config.example.jsonc` inside this repo.
|
||||
- [x] #2 When `../subminer-docs` exists, the generator updates `../subminer-docs/public/config.example.jsonc`.
|
||||
- [x] #3 Automated coverage guards the output-path contract so local docs writes do not regress.
|
||||
|
||||
<!-- AC:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Removed the first-party local `docs/public` config-example write path from `src/generate-config-example.ts` and replaced it with sibling-docs-repo detection that targets `../subminer-docs/public/config.example.jsonc` only when that repo exists.
|
||||
|
||||
Added a project-local regression suite for output-path resolution and artifact writing, wired that suite into the maintained config test lane, and removed the stale generated `docs/public/config.example.jsonc` artifact from the working tree.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,23 +5,25 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-07 06:10'
|
||||
updated_date: '2026-03-07 06:20'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels: []
|
||||
dependencies: []
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/shared/setup-state.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/first-run-setup-service.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/first-run-setup-window.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/launcher/commands/playback-command.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/main/runtime/first-run-setup-service.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/main/runtime/first-run-setup-window.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/launcher/commands/playback-command.ts
|
||||
priority: high
|
||||
ordinal: 10600
|
||||
ordinal: 13010
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Replace the current manual install flow with a first-run setup gate:
|
||||
|
||||
- bootstrap the default config dir/config file automatically
|
||||
@@ -32,9 +34,7 @@ Replace the current manual install flow with a first-run setup gate:
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 First app launch seeds the default config dir/config file without manual copy steps.
|
||||
- [x] #2 Existing installs with config plus at least one Yomitan dictionary are auto-detected as already complete.
|
||||
- [x] #3 Incomplete installs get a first-run setup popup with mpv plugin install, Yomitan settings, refresh, skip, and finish actions.
|
||||
@@ -45,7 +45,6 @@ Replace the current manual install flow with a first-run setup gate:
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Added shared setup-state/config/mpv path helpers so Electron and launcher read the same onboarding state file.
|
||||
|
||||
Introduced a first-run setup service plus compact BrowserWindow popup using Catppuccin Macchiato styling. The popup supports optional mpv plugin install, opening Yomitan settings, status refresh, skip-plugin, and gated finish once at least one Yomitan dictionary is installed.
|
||||
@@ -63,7 +62,6 @@ Verification:
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
SubMiner now supports a download-and-launch install flow.
|
||||
|
||||
- First launch auto-creates config and opens setup only when needed.
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
---
|
||||
id: TASK-107
|
||||
title: 'Fix Yomitan scan-token fallback fragmentation on exact-source misses'
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-07 01:10'
|
||||
updated_date: '2026-03-07 01:12'
|
||||
labels: []
|
||||
dependencies: []
|
||||
priority: high
|
||||
ordinal: 9007
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Left-to-right Yomitan scanning can emit bogus fallback tokens when `termsFind` returns entries but none of their headwords carries an exact primary source for the consumed substring. Repro: `だが それでも届かぬ高みがあった` currently yields trailing fragments like `があ` / `た`, which blocks the real `あった` token from receiving frequency highlighting.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Scanner skips `termsFind` fallback entries that are not backed by an exact primary source for the consumed substring.
|
||||
- [x] #2 Repro line no longer yields bogus trailing fragments such as `があ`.
|
||||
- [x] #3 Regression coverage added for the scan-token path.
|
||||
|
||||
<!-- AC:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Removed the scan-token helper fallback that previously emitted a token from the first returned headword even when Yomitan did not report an exact primary source for the consumed substring. Added a focused regression test covering `だが それでも届かぬ高みがあった`, ensuring bogus `があ` fragmentation is skipped so the later `あった` exact match can still be tokenized and highlighted.
|
||||
|
||||
Verification:
|
||||
|
||||
- `bun test src/core/services/tokenizer/yomitan-parser-runtime.test.ts src/core/services/tokenizer.test.ts --timeout 20000`
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -1,43 +0,0 @@
|
||||
---
|
||||
id: TASK-108
|
||||
title: 'Exclude single kana tokens from frequency highlighting'
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-07 01:18'
|
||||
updated_date: '2026-03-07 01:22'
|
||||
labels: []
|
||||
dependencies: []
|
||||
priority: medium
|
||||
ordinal: 9008
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Suppress frequency highlighting for single-character hiragana or katakana tokens. Scope is frequency-only: known/N+1/JLPT behavior stays unchanged.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Single-character hiragana tokens do not retain `frequencyRank`.
|
||||
- [x] #2 Single-character katakana tokens do not retain `frequencyRank`.
|
||||
- [x] #3 Regression coverage exists at annotation-stage and tokenizer levels.
|
||||
|
||||
<!-- AC:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Added a frequency-only suppression rule for single-character kana tokens based on token `surface`, so bogus merged fragments like `た` and standalone one-character kana no longer keep `frequencyRank`. Regression coverage now exists both in the annotation stage and in the tokenizer path, while multi-character tokens and N+1/JLPT behavior remain unchanged.
|
||||
|
||||
Verification:
|
||||
|
||||
- `bun test src/core/services/tokenizer/annotation-stage.test.ts --timeout 20000`
|
||||
- `bun test src/core/services/tokenizer.test.ts --timeout 20000`
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -4,40 +4,34 @@ title: Replace vendored Yomitan with submodule-built Chrome artifact workflow
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-07 11:05'
|
||||
updated_date: '2026-03-07 11:22'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- yomitan
|
||||
- build
|
||||
- release
|
||||
dependencies: []
|
||||
priority: high
|
||||
ordinal: 9010
|
||||
ordinal: 10010
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Replace the checked-in `vendor/yomitan` release tree with a `subminer-yomitan` git submodule. Build Yomitan from source, extract the Chromium zip artifact into a stable local build directory, and make SubMiner dev/runtime/tests/release packaging load that extracted extension instead of the source tree or vendored files.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Repo tracks Yomitan as a git submodule instead of committed extension files under `vendor/yomitan`.
|
||||
- [x] #2 SubMiner has a reproducible build/extract step that produces a local Chromium extension directory from `subminer-yomitan`.
|
||||
- [x] #3 Dev/runtime/tests resolve the extracted build output as the default Yomitan extension path.
|
||||
- [x] #4 Release packaging includes the extracted Chromium extension files instead of the old vendored tree.
|
||||
- [x] #5 Docs and verification commands reflect the new workflow.
|
||||
|
||||
<!-- AC:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Replaced the checked-in `vendor/yomitan` extension tree with a `vendor/subminer-yomitan` git submodule and added a reproducible `bun run build:yomitan` workflow that builds `yomitan-chrome.zip`, extracts it into `build/yomitan`, and reuses a source-state stamp to skip redundant rebuilds. Runtime path resolution, helper CLIs, Yomitan integration tests, packaging, CI cache keys, and README source-build notes now all target that generated artifact instead of the old vendored files.
|
||||
|
||||
Verification:
|
||||
@@ -47,5 +41,4 @@ Verification:
|
||||
- `bun run typecheck`
|
||||
- `bun run build`
|
||||
- `bun run test:core:src`
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- Codex
|
||||
created_date: '2026-03-07 23:45'
|
||||
updated_date: '2026-03-08 00:06'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels: []
|
||||
dependencies: []
|
||||
references:
|
||||
@@ -15,20 +15,17 @@ references:
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/core/services/ipc-command.test.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/core/services/mpv-control.test.ts
|
||||
ordinal: 72500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
When cycling subtitle tracks with the default J/Shift+J keybindings, the mpv OSD currently shows raw template text like `${sid}` instead of a resolved subtitle label. Update the keybinding OSD behavior so users see the active subtitle selection clearly when cycling tracks, and ensure placeholder-based OSD messages sent through the mpv client API render correctly.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Pressing the primary subtitle cycle keybinding shows a resolved subtitle label on the OSD instead of a raw `${sid}` placeholder.
|
||||
- [x] #2 Pressing the secondary subtitle cycle keybinding shows a resolved subtitle label on the OSD instead of a raw `${secondary-sid}` placeholder.
|
||||
- [x] #3 Proxy OSD messages that rely on mpv property expansion render resolved values when sent through the mpv client API.
|
||||
@@ -38,7 +35,6 @@ When cycling subtitle tracks with the default J/Shift+J keybindings, the mpv OSD
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Add focused failing tests for subtitle-cycle OSD labels and mpv placeholder-expansion behavior.
|
||||
2. Update the IPC mpv command handler to resolve primary and secondary subtitle track labels from mpv `track-list` data after cycling subtitle tracks.
|
||||
3. Update the mpv OSD runtime path so placeholder-based `show-text` messages sent through the client API opt into property expansion.
|
||||
@@ -48,7 +44,6 @@ When cycling subtitle tracks with the default J/Shift+J keybindings, the mpv OSD
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Initial triage: `ipc-command.ts` emits raw `${sid}`/`${secondary-sid}` placeholder strings, and `showMpvOsdRuntime` sends `show-text` via mpv client API without enabling property expansion.
|
||||
|
||||
User approved implementation plan on 2026-03-07.
|
||||
@@ -64,17 +59,14 @@ Testing: `bun x tsc --noEmit` passed.
|
||||
Testing: `bun run test:core:src` passed (423 pass, 6 skip, 0 fail).
|
||||
|
||||
Docs: no update required because no checked-in docs or help text describe the J/Shift+J OSD output behavior.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Fixed subtitle-cycle OSD handling for the default J/Shift+J keybindings. The IPC mpv command path now supports resolving proxy OSD text asynchronously, and the main-runtime resolver reads mpv `track-list` state so primary and secondary subtitle cycling show human-readable track labels instead of raw `${sid}` / `${secondary-sid}` placeholders.
|
||||
|
||||
Also fixed the lower-level mpv OSD transport so placeholder-based `show-text` messages sent through the client API opt into `expand-properties`. That preserves existing template-based OSD messages like subtitle delay and subtitle position without leaking the raw `${...}` syntax.
|
||||
|
||||
Added regression coverage for the async proxy OSD path, the placeholder-expansion `showMpvOsdRuntime` path, and the runtime subtitle-track label resolver. Verification run: `bun x tsc --noEmit`; focused mpv/IPC tests; and the maintained `bun run test:core:src` lane (423 pass, 6 skip, 0 fail).
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 00:11'
|
||||
updated_date: '2026-03-08 00:12'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- pr-review
|
||||
- ci
|
||||
@@ -18,20 +18,17 @@ references:
|
||||
backlog/tasks/task-101 -
|
||||
Index-AniList-character-alternative-names-in-the-character-dictionary.md
|
||||
priority: medium
|
||||
ordinal: 70500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Review Claude's PR feedback on PR #15, implement only the technically valid fixes on the current branch, and document which comments are non-actionable or already acceptable.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Validated Claude's concrete PR review items against current branch state and repo conventions
|
||||
- [x] #2 Implemented the accepted fixes with regression coverage or verification where applicable
|
||||
- [x] #3 Documented which review items are non-blocking or intentionally left unchanged
|
||||
@@ -40,7 +37,6 @@ Review Claude's PR feedback on PR #15, implement only the technically valid fixe
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Validate each Claude review item against current branch files and repo workflow.
|
||||
2. Patch release quality-gate to match CI ordering and add explicit typecheck.
|
||||
3. Remove duplicate .gitmodules stanza and normalize the TASK-101 reference path through Backlog MCP.
|
||||
@@ -50,21 +46,17 @@ Review Claude's PR feedback on PR #15, implement only the technically valid fixe
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
User asked to address Claude PR comments on PR #15 and assess whether any action items remain. Treat review suggestions skeptically; only fix validated defects.
|
||||
|
||||
Validated Claude's five review items. Fixed release workflow ordering/typecheck, removed the duplicate .gitmodules entry, and normalized TASK-101 references to repo-relative paths via Backlog MCP.
|
||||
|
||||
Left the vendor/subminer-yomitan branch-pin suggestion unchanged. The committed submodule SHA already controls reproducibility; adding a branch would only affect update ergonomics and was not required to address a concrete defect.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Validated Claude's PR #15 review summary against the current branch and applied the actionable fixes. In `.github/workflows/release.yml`, the release `quality-gate` job now restores the dependency cache before installation, no longer installs twice, and runs `bun run typecheck` before the fast test suite to match CI expectations. In `.gitmodules`, removed the duplicate `vendor/yomitan-jlpt-vocab` stanza with the conflicting duplicate path. Through Backlog MCP, updated `TASK-101` references from an absolute local path to repo-relative paths so the task metadata is portable across contributors.
|
||||
|
||||
Verification: `git diff --check`, `git config -f .gitmodules --get-regexp '^submodule\..*\.path$'`, `bun run typecheck`, and `bun run test:fast` all passed. `bun run format:check` still fails on many pre-existing unrelated files already present on the branch, including multiple backlog task files and existing source/docs files; this review patch did not attempt a repo-wide formatting sweep.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 00:20'
|
||||
updated_date: '2026-03-08 00:22'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- tooling
|
||||
- formatting
|
||||
@@ -14,20 +14,17 @@ references:
|
||||
- Makefile
|
||||
- package.json
|
||||
priority: medium
|
||||
ordinal: 69500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Change the `make pretty` workflow so it formats only the maintained source/config files we intentionally keep under Prettier, instead of sweeping backlog/docs/generated content across the whole repository.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 `make pretty` formats only the approved maintained source/config paths
|
||||
- [x] #2 The allowlist is reusable for check/write flows instead of duplicating path logic
|
||||
- [x] #3 Verification shows the scoped formatting command targets the intended files without touching backlog or vendored content
|
||||
@@ -36,7 +33,6 @@ Change the `make pretty` workflow so it formats only the maintained source/confi
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Inspect current Prettier config/ignore behavior and keep the broad repo-wide format command unchanged.
|
||||
2. Add a reusable scoped Prettier script that targets maintained source/config paths only.
|
||||
3. Update `make pretty` to call the scoped script.
|
||||
@@ -46,7 +42,6 @@ Change the `make pretty` workflow so it formats only the maintained source/confi
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
User approved the allowlist approach: keep repo-wide `format` intact, make `make pretty` use a maintained-path formatter scope.
|
||||
|
||||
Added `scripts/prettier-scope.sh` as the single allowlist for scoped Prettier paths and wired `format:src` / `format:check:src` to it.
|
||||
@@ -54,15 +49,12 @@ Added `scripts/prettier-scope.sh` as the single allowlist for scoped Prettier pa
|
||||
Updated `make pretty` to call `bun run format:src`. Verified with `make -n pretty` and shell tracing that the helper only targets the maintained allowlist and does not traverse `backlog/` or `vendor/`.
|
||||
|
||||
Excluded `Makefile` and `.prettierignore` from the allowlist after verification showed Prettier cannot infer parsers for them.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Scoped the repo's day-to-day formatting entrypoint without changing the existing broad repo-wide Prettier scripts. Added `scripts/prettier-scope.sh` as the shared allowlist for maintained source/config paths (`.github`, `build`, `launcher`, `scripts`, `src`, plus selected root JSON config files), added `format:src` and `format:check:src` in `package.json`, and updated `make pretty` to run the scoped formatter.
|
||||
|
||||
Verification: `make -n pretty` now resolves to `bun run format:src`. `bash -n scripts/prettier-scope.sh` passed, and shell-traced `bash -x scripts/prettier-scope.sh --check` confirmed the exact allowlist passed to Prettier. `bun run format:check:src` fails only because existing files inside the allowed source scope are not currently formatted; it no longer touches `backlog/` or `vendor/`.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 00:34'
|
||||
updated_date: '2026-03-08 00:37'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- ci
|
||||
- test
|
||||
@@ -15,20 +15,17 @@ references:
|
||||
- src/renderer/style.css
|
||||
- .github/workflows/ci.yml
|
||||
priority: high
|
||||
ordinal: 68500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Investigate the failing GitHub Actions CI run for PR #15 on branch `yomitan-fork`, fix the underlying test or code regression, and verify the affected local test/CI lane passes.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Identified the concrete failing CI job and captured the relevant failure context
|
||||
- [x] #2 Implemented the minimal code or test change needed to resolve the CI failure
|
||||
- [x] #3 Verified the affected local test target and the broader fast CI test lane pass
|
||||
@@ -37,7 +34,6 @@ Investigate the failing GitHub Actions CI run for PR #15 on branch `yomitan-fork
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Inspect the failing GitHub Actions run and confirm the exact failing test/assertion.
|
||||
2. Reproduce the failing renderer stylesheet test locally and compare the assertion against current CSS.
|
||||
3. Apply the minimal test or stylesheet fix needed to restore the intended hover/selection behavior.
|
||||
@@ -47,7 +43,6 @@ Investigate the failing GitHub Actions CI run for PR #15 on branch `yomitan-fork
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
GitHub Actions run 22810400921 failed in job build-test-audit, step `Test suite (source)`, with a single failing test: `JLPT CSS rules use underline-only styling in renderer stylesheet` in src/renderer/subtitle-render.test.ts.
|
||||
|
||||
Reproduced the failing test locally with `bun test src/renderer/subtitle-render.test.ts`. The failure was a brittle stylesheet assertion, not a renderer behavior regression.
|
||||
@@ -55,17 +50,14 @@ Reproduced the failing test locally with `bun test src/renderer/subtitle-render.
|
||||
Updated the renderer stylesheet test helper to split selectors safely across `:is(...)` commas and normalize multiline selector whitespace, then switched the failing hover/JLPT assertions to inspect extracted rule blocks instead of matching the entire CSS file text.
|
||||
|
||||
Verification passed with `bun test src/renderer/subtitle-render.test.ts` and `bun run test`.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Investigated GitHub Actions CI run `22810400921` for PR #15 and confirmed the only failing job was `build-test-audit`, step `Test suite (source)`, with a single failure in `src/renderer/subtitle-render.test.ts` (`JLPT CSS rules use underline-only styling in renderer stylesheet`).
|
||||
|
||||
The renderer CSS itself was still correct; the regression was in the test helper. `extractClassBlock` was splitting selector lists on every comma, which breaks selectors containing `:is(...)`, and the affected assertions fell back to brittle whole-file regex matching against a multiline selector. Fixed the test by teaching the helper to split selectors only at top-level commas, normalizing selector whitespace around multiline `:not(...)` / `:is(...)` clauses, and asserting on extracted rule blocks for the plain-word hover and JLPT-only hover/selection rules.
|
||||
|
||||
Verification: `bun test src/renderer/subtitle-render.test.ts` passed, and `bun run test` passed end to end (the same fast lane that failed in CI).
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 00:40'
|
||||
updated_date: '2026-03-08 00:42'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- docs
|
||||
dependencies: []
|
||||
@@ -15,20 +15,17 @@ references:
|
||||
- Makefile
|
||||
- package.json
|
||||
priority: medium
|
||||
ordinal: 67500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Update the sibling `subminer-docs` repo so contributor/development docs match the current SubMiner repo workflow after the docs split and recent tooling changes, including removing stale in-repo docs build steps and documenting the scoped formatting command.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Contributor docs in `subminer-docs` no longer reference stale in-repo docs build commands for the app repo
|
||||
- [x] #2 Contributor docs mention the current scoped formatting workflow (`make pretty` / `format:src`) where relevant
|
||||
- [x] #3 Removed stale or no-longer-needed instructions that no longer match the current repo layout
|
||||
@@ -37,7 +34,6 @@ Update the sibling `subminer-docs` repo so contributor/development docs match th
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Inspect `subminer-docs` for contributor/development instructions that drifted after the docs repo split and recent tooling changes.
|
||||
2. Update contributor docs to remove stale app-repo docs commands and document the current scoped formatting workflow.
|
||||
3. Verify the modified docs page and build the docs site from the sibling docs repo when local dependencies are available.
|
||||
@@ -46,7 +42,6 @@ Update the sibling `subminer-docs` repo so contributor/development docs match th
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Detected concrete doc drift in `subminer-docs/development.md`: stale in-repo docs build commands and no mention of the scoped `make pretty` formatter.
|
||||
|
||||
Updated `../subminer-docs/development.md` to remove stale app-repo docs build steps from the local gate, document `make pretty` / `format:check:src`, and point docs-site work to the sibling docs repo explicitly.
|
||||
@@ -54,15 +49,12 @@ Updated `../subminer-docs/development.md` to remove stale app-repo docs build st
|
||||
Installed docs repo dependencies locally with `bun install` and verified the docs site with `bun run docs:build` in `../subminer-docs`.
|
||||
|
||||
Did not change `../subminer-docs/README.md`; it was already accurate for the docs repo itself.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Refreshed the contributor/development docs in the sibling `subminer-docs` repo to match the current SubMiner workflow. In `development.md`, removed the stale app-repo `bun run docs:build` step from the local CI-equivalent gate, added an explicit note to run docs builds from `../subminer-docs` when docs change, documented the scoped formatting workflow (`make pretty` and `bun run format:check:src`), and replaced the old in-repo `make docs*` instructions with the correct sibling-repo `bun run docs:*` commands. Also updated the Makefile reference to include `make pretty` and removed the obsolete `make docs-dev` entry.
|
||||
|
||||
Verification: installed docs repo dependencies with `bun install` in `../subminer-docs` and ran `bun run docs:build` successfully. Left `README.md` unchanged because it was already accurate for the standalone docs repo.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 00:46'
|
||||
updated_date: '2026-03-08 00:48'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- docs
|
||||
dependencies: []
|
||||
@@ -15,20 +15,17 @@ references:
|
||||
- src/core/services/yomitan-extension-paths.ts
|
||||
- scripts/build-yomitan.mjs
|
||||
priority: medium
|
||||
ordinal: 66500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Review recent `yomitan-fork` commits against the sibling `subminer-docs` repo, identify any concrete documentation drift that remains after the earlier contributor-doc updates, and patch the docs for behavior/tooling changes that are now outdated or misleading.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Reviewed recent branch commits for user-facing or contributor-facing changes that may require docs updates
|
||||
- [x] #2 Updated `subminer-docs` pages where branch changes introduced concrete doc drift
|
||||
- [x] #3 Verified the docs site still builds after the updates
|
||||
@@ -37,7 +34,6 @@ Review recent `yomitan-fork` commits against the sibling `subminer-docs` repo, i
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Review branch commit themes against `subminer-docs` and identify only concrete drift introduced by recent workflow/runtime changes.
|
||||
2. Patch docs for the Yomitan submodule build workflow, updated source-build prerequisites, and current runtime Yomitan search paths/manual fallback path.
|
||||
3. Rebuild the docs site to verify the updated pages render cleanly.
|
||||
@@ -46,17 +42,13 @@ Review recent `yomitan-fork` commits against the sibling `subminer-docs` repo, i
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Concrete remaining drift after commit audit: installation/development docs still understate the Node/npm + submodule requirements for the Yomitan build flow, and troubleshooting still points at obsolete `vendor/yomitan` / `extensions/yomitan` paths.
|
||||
|
||||
Audited branch commits against subminer-docs coverage. Existing docs already cover first-run setup, texthooker startup/annotated websocket config, AniList merged character dictionaries, configurable collapsible sections, and subtitle name highlighting. Patched remaining drift around source-build prerequisites and Yomitan build/install paths in installation.md, development.md, and troubleshooting.md. Verified with `bun run docs:build` in ../subminer-docs.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Audited branch commits for missing documentation updates in ../subminer-docs. Updated installation, development, and troubleshooting docs to match the current Yomitan submodule build flow, source-build prerequisites, and runtime extension search/manual fallback paths. Confirmed other recent branch features were already documented and rebuilt the docs site successfully.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
---
|
||||
id: TASK-117
|
||||
title: Prepare initial Windows release docs and version bump
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 15:17'
|
||||
updated_date: '2026-03-08 15:17'
|
||||
labels:
|
||||
- release
|
||||
- docs
|
||||
- windows
|
||||
dependencies: []
|
||||
references:
|
||||
- package.json
|
||||
- README.md
|
||||
- ../subminer-docs/installation.md
|
||||
- ../subminer-docs/usage.md
|
||||
- ../subminer-docs/changelog.md
|
||||
priority: medium
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Prepare the initial packaged Windows release by bumping the app version and refreshing the release-facing README/backlog/docs surfaces so install and direct-command guidance no longer reads Linux-only.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 App version is bumped for the Windows release cut
|
||||
- [x] #2 README and sibling docs describe Windows packaged installation alongside Linux/macOS guidance
|
||||
- [x] #3 Backlog records the release-doc/version update with the modified references
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Bump the package version for the release cut.
|
||||
2. Update the root README install/start guidance to mention Windows packaged builds.
|
||||
3. Patch the sibling docs repo installation, usage, and changelog pages for the Windows release.
|
||||
4. Record the work in Backlog and run targeted verification on the touched surfaces.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
The public README still advertised Linux/macOS only, while the sibling docs had Windows-specific runtime notes but no actual Windows install section and several direct-command examples still assumed `SubMiner.AppImage`.
|
||||
|
||||
Bumped `package.json` to `0.5.0`, expanded the README platform/install copy to include Windows, added a Windows install section to `../subminer-docs/installation.md`, clarified in `../subminer-docs/usage.md` that direct packaged-app examples use `SubMiner.exe` on Windows, and added a `v0.5.0` changelog entry covering the initial Windows release plus the latest overlay behavior polish.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Prepared the initial Windows release documentation pass and version bump. `package.json` now reports `0.5.0`. The root `README.md` now advertises Linux, macOS, and Windows support, includes Windows packaged-install guidance, and clarifies first-launch behavior across platforms. In the sibling docs repo, `installation.md` now includes a dedicated Windows install section, `usage.md` explains that direct packaged-app examples use `SubMiner.exe` on Windows, and `changelog.md` now includes the `v0.5.0` release notes for the initial Windows build and recent overlay behavior changes.
|
||||
|
||||
Verification: targeted `bun run tsc --noEmit -p tsconfig.typecheck.json` in the app repo and `bun run docs:build` in `../subminer-docs`.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -1,75 +0,0 @@
|
||||
---
|
||||
id: TASK-117
|
||||
title: >-
|
||||
Replace YouTube subtitle generation with pure TypeScript pipeline and shared
|
||||
AI config
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 03:16'
|
||||
updated_date: '2026-03-08 03:35'
|
||||
labels: []
|
||||
dependencies: []
|
||||
references:
|
||||
- /Users/sudacode/projects/japanese/SubMiner/launcher/youtube.ts
|
||||
- /Users/sudacode/projects/japanese/SubMiner/src/anki-integration/ai.ts
|
||||
- /Users/sudacode/projects/japanese/SubMiner/src/types.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/config/definitions/defaults-integrations.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/config/resolve/subtitle-domains.ts
|
||||
- /Users/sudacode/projects/japanese/SubMiner/config.example.jsonc
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Replace the launcher YouTube subtitle generation flow with a pure TypeScript pipeline that prefers real downloadable YouTube subtitles, never uses YouTube auto-generated subtitles, locally generates missing tracks with whisper.cpp, and can optionally fix generated subtitles via a shared OpenAI-compatible AI provider config. This feature also introduces a breaking config cleanup: move provider settings to a new top-level ai section and reduce ankiConnect.ai to a boolean feature toggle.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Launcher YouTube subtitle generation prefers downloadable manual YouTube subtitles, never uses YouTube auto-generated subtitles, and locally generates only missing tracks with whisper.cpp.
|
||||
- [x] #2 Generated whisper subtitle tracks can optionally be post-processed with an OpenAI-compatible AI provider using shared top-level ai config, with validation and fallback to raw whisper output on failure.
|
||||
- [x] #3 Configuration is updated so top-level ai is canonical shared provider config, ankiConnect.ai is boolean-only, and youtubeSubgen includes whisperVadModel, whisperThreads, and fixWithAi.
|
||||
- [x] #4 Launcher CLI/config parsing, config example, and docs reflect the new breaking config shape with no migration layer.
|
||||
- [x] #5 Automated tests cover the new YouTube generation behavior, AI-fix fallback/validation behavior, shared AI config usage, and breaking config validation.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Introduce canonical top-level ai config plus youtubeSubgen runtime knobs (whisperVadModel, whisperThreads, fixWithAi) and convert ankiConnect.ai to a boolean-only toggle across types, defaults, validation, option registries, launcher config parsing, and config example/docs.
|
||||
2. Extract shared OpenAI-compatible AI client helpers from the current Anki translation code, including base URL normalization, API key / apiKeyCommand resolution, timeout handling, and response text extraction.
|
||||
3. Update Anki translation flow and hot-reload/runtime plumbing to consume global ai config while treating ankiConnect.ai as a feature gate only.
|
||||
4. Replace launcher/youtube.ts with a modular launcher/youtube pipeline that fetches only manual YouTube subtitles, generates missing tracks locally with ffmpeg + whisper.cpp + optional VAD/thread controls, and preserves preprocess/automatic playback behavior.
|
||||
5. Add optional AI subtitle-fix processing for whisper-generated tracks using the shared ai client, with strict SRT batching/validation and fallback to raw whisper output on provider or format failure.
|
||||
6. Expand automated coverage for config validation, shared AI usage, launcher config parsing, and YouTube subtitle generation behavior including removal of yt-dlp auto-subs and AI-fix fallback rules.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Implemented pure TypeScript launcher/youtube pipeline modules for manual subtitle fetch, audio extraction, whisper runs, SRT utilities, and optional AI subtitle fixing. Removed yt-dlp auto-subtitle usage from the generation path.
|
||||
|
||||
Added shared top-level ai config plus shared AI client helpers; converted ankiConnect.ai to a boolean feature gate and updated Anki runtime wiring to consume global ai config.
|
||||
|
||||
Updated launcher config parsing, config template sections, and config.example.jsonc for the breaking config shape including youtubeSubgen.whisperVadModel, youtubeSubgen.whisperThreads, and youtubeSubgen.fixWithAi.
|
||||
|
||||
Verification: bun run test:config:src passed; targeted AI/Anki/runtime tests passed; bun run typecheck passed. bun run test:launcher:unit:src reported one unrelated existing failure in launcher/aniskip-metadata.test.ts (resolveAniSkipMetadataForFile resolves MAL id and intro payload).
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Replaced the launcher YouTube subtitle flow with a modular TypeScript pipeline that prefers manual YouTube subtitles, transcribes only missing tracks with whisper.cpp, and can optionally post-fix whisper output through a shared OpenAI-compatible AI client with strict SRT validation/fallback. Introduced canonical top-level ai config, reduced ankiConnect.ai to a boolean feature gate, updated launcher/config parsing and checked-in config artifacts, and added coverage for YouTube orchestration, whisper args, SRT validation, AI fix behavior, and breaking config validation.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- '@codex'
|
||||
created_date: '2026-03-08 08:22'
|
||||
updated_date: '2026-03-08 08:25'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels: []
|
||||
dependencies: []
|
||||
references:
|
||||
@@ -15,20 +15,17 @@ references:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/launcher/youtube/subtitle-fix-ai.test.ts
|
||||
parent_task_id: TASK-117
|
||||
ordinal: 59500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Prevent optional YouTube AI subtitle post-processing from bailing out whenever the model returns usable cue text in a non-SRT wrapper or text-only format. The launcher should recover safe cases, preserve original timing, and fall back cleanly when the response cannot be mapped back to the source cues.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 AI subtitle fixing accepts safe AI responses that omit SRT framing but still provide one corrected text payload per original cue while preserving original cue timing.
|
||||
- [x] #2 AI subtitle fixing still rejects responses that cannot be mapped back to the original cue batch without guessing and falls back to the raw subtitle file with a warning.
|
||||
- [x] #3 Automated tests cover wrapped-SRT and text-only AI responses plus an unrecoverable invalid response case.
|
||||
@@ -37,7 +34,6 @@ Prevent optional YouTube AI subtitle post-processing from bailing out whenever t
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Add failing tests in launcher/youtube/subtitle-fix-ai.test.ts for three cases: wrapped valid SRT, text-only one-block-per-cue output, and unrecoverable invalid output.
|
||||
2. Extend launcher/youtube/subtitle-fix-ai.ts with a small response-normalization path that first strips markdown/code-fence wrappers, then accepts deterministic text-only cue batches only when they map 1:1 to the original cues without changing timestamps.
|
||||
3. Keep existing safety rules: preserve cue count and timing, log a warning, and fall back to the raw subtitle file when normalization cannot recover a trustworthy batch.
|
||||
@@ -47,19 +43,15 @@ Prevent optional YouTube AI subtitle post-processing from bailing out whenever t
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Implemented deterministic AI subtitle-response recovery for fenced SRT, embedded SRT payloads, and text-only 1:1 cue batches while preserving original timing and existing fallback behavior.
|
||||
|
||||
Verification: bun test launcher/youtube/_.test.ts passed; bun run typecheck passed; repo-wide format check still reports unrelated pre-existing warnings in launcher/youtube/orchestrator.ts and scripts/build-changelog_.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Hardened the launcher AI subtitle-fix path so it can recover deterministic non-SRT model responses instead of immediately falling back. Added `parseAiSubtitleFixResponse` in `launcher/youtube/subtitle-fix-ai.ts` to normalize markdown-fenced or embedded SRT payloads first, then accept text-only responses only when they map 1:1 onto the original cue batch and preserve source timings. Added regression coverage in `launcher/youtube/subtitle-fix-ai.test.ts` for fenced SRT, text-only cue batches, and unrecoverable invalid output, plus a changelog fragment in `changes/task-117.1.md`.
|
||||
|
||||
Verification: `bun test launcher/youtube/*.test.ts`, `bun run typecheck`, `bunx prettier --check launcher/youtube/subtitle-fix-ai.ts launcher/youtube/subtitle-fix-ai.test.ts`, and `bun run changelog:lint` passed. Repo-wide `bun run format:check:src` still reports unrelated pre-existing warnings in `launcher/youtube/orchestrator.ts` and `scripts/build-changelog*`.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
---
|
||||
id: TASK-118
|
||||
title: Add Windows release build and SignPath signing
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 15:17'
|
||||
updated_date: '2026-03-08 15:17'
|
||||
labels:
|
||||
- release
|
||||
- windows
|
||||
- signing
|
||||
dependencies: []
|
||||
references:
|
||||
- .github/workflows/release.yml
|
||||
- build/installer.nsh
|
||||
- build/signpath-windows-artifact-config.xml
|
||||
- package.json
|
||||
priority: high
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Extend the tag-driven release workflow so Windows artifacts are built on GitHub-hosted runners and submitted to SignPath for free open-source Authenticode signing, while preserving the existing macOS notarization path.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Release workflow builds Windows installer and ZIP artifacts on `windows-latest`
|
||||
- [x] #2 Workflow submits unsigned Windows artifacts to SignPath and uploads the signed outputs for release publication
|
||||
- [x] #3 Repository includes a checked-in SignPath artifact-configuration source of truth for the Windows release files
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Inspect the existing release workflow and current Windows packaging configuration.
|
||||
2. Add a Windows release job that builds unsigned artifacts, uploads them as a workflow artifact, and submits them to SignPath.
|
||||
3. Update the release aggregation job to publish signed Windows assets and mention Windows install steps in the generated release notes.
|
||||
4. Check in the Windows SignPath artifact configuration XML used to define what gets signed.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
The repository already had Windows packaging configuration (`build:win`, NSIS include script, Windows helper asset packaging), but the release workflow still built Linux and macOS only.
|
||||
|
||||
Added a `build-windows` job to `.github/workflows/release.yml` that runs on `windows-latest`, validates required SignPath secrets, builds unsigned Windows artifacts, uploads them with `actions/upload-artifact@v4`, and then calls the official `signpath/github-action-submit-signing-request@v2` action to retrieve signed outputs.
|
||||
|
||||
Checked in `build/signpath-windows-artifact-config.xml` as the source-of-truth artifact configuration for SignPath. It signs the top-level NSIS installer EXE and deep-signs `.exe` and `.dll` files inside the portable ZIP artifact.
|
||||
|
||||
Updated the release aggregation job to download the signed Windows artifacts and added a Windows install section to the generated GitHub release body.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Windows release publishing is now wired into the tag-driven workflow. `.github/workflows/release.yml` builds Windows artifacts on `windows-latest`, submits them to SignPath using the official GitHub action, and publishes the signed `.exe` and `.zip` outputs alongside the Linux and macOS artifacts. The workflow now requests the additional `actions: read` permission required by the SignPath GitHub integration, and the generated release notes now include Windows installation steps.
|
||||
|
||||
The checked-in `build/signpath-windows-artifact-config.xml` file defines the SignPath artifact structure expected by the workflow artifact ZIP: sign the top-level `SubMiner-*.exe` installer and deep-sign `.exe` and `.dll` files inside `SubMiner-*.zip`.
|
||||
|
||||
Verification: workflow/static changes were checked with `git diff --check` on the touched files. Actual signing requires configured SignPath secrets and a matching artifact configuration in your SignPath project.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -1,73 +0,0 @@
|
||||
---
|
||||
id: TASK-118
|
||||
title: Fix GitHub release workflow publish step failure
|
||||
status: Done
|
||||
assignee:
|
||||
- Codex
|
||||
created_date: '2026-03-08 03:34'
|
||||
updated_date: '2026-03-08 03:38'
|
||||
labels:
|
||||
- ci
|
||||
- release
|
||||
- github-actions
|
||||
dependencies: []
|
||||
references:
|
||||
- /Users/sudacode/projects/japanese/SubMiner/.github/workflows/release.yml
|
||||
- 'https://github.com/ksyasuda/SubMiner/actions/runs/22812335927'
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
The GitHub Actions Release workflow fails during the Publish Release step for tag releases because the gh CLI invocation passes invalid arguments when creating or editing the GitHub release. Restore successful release publication for tagged builds without changing unrelated release packaging behavior.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Tagged Release workflow completes the Publish Release step without gh CLI argument errors.
|
||||
- [x] #2 Release workflow still creates or updates the GitHub release as a non-prerelease for normal version tags.
|
||||
- [x] #3 A regression check covers the publish command shape or workflow behavior that caused this failure.
|
||||
- [x] #4 Any release workflow behavior change is documented in repository docs or workflow comments if needed.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Add a targeted regression test for .github/workflows/release.yml that fails if the publish step passes an argument to the gh --prerelease boolean flag or otherwise omits explicit non-prerelease behavior.
|
||||
2. Run the targeted test to confirm the current workflow fails for the expected reason.
|
||||
3. Patch the Publish Release step in .github/workflows/release.yml to remove the invalid gh CLI usage while preserving non-prerelease release creation/update behavior.
|
||||
4. Re-run the targeted regression test and any relevant lightweight verification, then record results in task notes.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Identified root cause from GitHub Actions run 22812335927: Publish Release failed with `accepts 1 arg(s), received 2` because the workflow passed a value to gh's boolean prerelease flag.
|
||||
|
||||
Added a workflow comment clarifying that omitting the prerelease flag keeps normal releases as non-prerelease releases.
|
||||
|
||||
Added src/release-workflow.test.ts and wired it into `bun run test:fast` so CI catches the invalid workflow shape before the next tag.
|
||||
|
||||
Verification: `bun test src/release-workflow.test.ts`, `bun run typecheck`, and `bun run test:fast` all passed locally.
|
||||
|
||||
Code-review pass found no issues; remaining caveat is that prerelease tag semantics are still not modeled for tags like `v1.0.0-beta.1`, which is outside this fix scope.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Fixed the GitHub Actions release publish step so tagged releases no longer fail on invalid gh CLI usage. The workflow now omits the prerelease flag when creating or editing normal releases, which preserves existing non-prerelease behavior and avoids the `accepts 1 arg(s), received 2` failure seen in run 22812335927.
|
||||
|
||||
Added a small regression test that reads `.github/workflows/release.yml` and asserts the publish step does not set the prerelease flag, then included that test in `bun run test:fast` so the main verification lane catches this class of workflow regression before the next release.
|
||||
|
||||
Validation run locally: `bun test src/release-workflow.test.ts`, `bun run typecheck`, and `bun run test:fast`. Residual risk: prerelease-tag semantics remain unchanged for tags such as `v1.0.0-beta.1`; this fix is intentionally scoped to restoring normal tagged release publication.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -4,6 +4,7 @@ title: Add Jellyfin remote-session subtitle streaming to texthooker
|
||||
status: To Do
|
||||
assignee: []
|
||||
created_date: '2026-03-08 03:46'
|
||||
updated_date: '2026-03-18 05:27'
|
||||
labels:
|
||||
- jellyfin
|
||||
- texthooker
|
||||
@@ -19,20 +20,17 @@ references:
|
||||
documentation:
|
||||
- 'https://api.jellyfin.org/'
|
||||
priority: medium
|
||||
ordinal: 1000
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Allow SubMiner to follow subtitles from a separate Jellyfin client session, such as a TV app, without requiring local mpv playback. The feature should fetch the active subtitle stream from Jellyfin, map the remote playback position to subtitle cues, and feed the existing subtitle tokenization plus annotated texthooker websocket pipeline so texthooker-only mode can be used while watching on another device.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [ ] #1 User can target a remote Jellyfin session and stream its current subtitle cue into SubMiner's existing subtitle-processing pipeline without launching local Jellyfin playback in mpv.
|
||||
- [ ] #2 Texthooker-only mode can display subtitle updates from the tracked remote Jellyfin session through the existing annotation websocket feed.
|
||||
- [ ] #3 Remote session changes are handled safely: item changes, subtitle-track changes, pause/seek/stop, and session disconnects clear or refresh subtitle state without crashing.
|
||||
|
||||
@@ -4,7 +4,7 @@ title: 'Replace node:sqlite with libsql and remove Yomitan Node wrapper'
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-08 04:14'
|
||||
updated_date: '2026-03-08 04:39'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- runtime
|
||||
- bun
|
||||
@@ -12,20 +12,17 @@ labels:
|
||||
- tech-debt
|
||||
dependencies: []
|
||||
priority: medium
|
||||
ordinal: 65500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Remove the remaining root Node requirement caused by immersion tracking SQLite usage and the old Yomitan build wrapper by migrating the local SQLite layer off node:sqlite, running the SQLite-backed verification lanes under Bun, and switching the vendored Yomitan build flow to Bun-native scripts.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Immersion tracker runtime no longer imports or requires node:sqlite
|
||||
- [x] #2 SQLite-backed immersion tracker tests run under Bun without Node --experimental-sqlite
|
||||
- [x] #3 Root build/test scripts no longer require the Yomitan Node wrapper or Node-based SQLite verification lanes
|
||||
@@ -35,7 +32,5 @@ Remove the remaining root Node requirement caused by immersion tracking SQLite u
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Replaced the immersion tracker SQLite dependency with a local libsql-backed wrapper, updated Bun/runtime compatibility tests to avoid process.exitCode side effects, switched Yomitan builds to run directly inside the vendored Bun-native project, deleted scripts/build-yomitan.mjs, and verified typecheck plus Bun build/test lanes (`build:yomitan`, `test:immersion:sqlite`, `test:runtime:compat`, `test:fast`).
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -7,7 +7,7 @@ status: Done
|
||||
assignee:
|
||||
- '@codex'
|
||||
created_date: '2026-03-08 05:37'
|
||||
updated_date: '2026-03-08 05:42'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- bug
|
||||
- youtube
|
||||
@@ -18,20 +18,17 @@ references:
|
||||
- /Users/sudacode/projects/japanese/SubMiner/launcher/youtube/orchestrator.ts
|
||||
- 'https://www.youtube.com/watch?v=MXzQRLmN9hE'
|
||||
priority: high
|
||||
ordinal: 64500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Ensure launcher YouTube subtitle generation reuses downloadable manual subtitle tracks when the video already has requested languages available, instead of falling back to whisper generation. Reproduce against videos like MXzQRLmN9hE that expose manual en/ja subtitles via yt-dlp.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 When requested primary/secondary manual YouTube subtitle tracks exist, planning selects them and schedules no whisper generation for those tracks.
|
||||
- [x] #2 Filename normalization handles manual subtitle outputs produced by yt-dlp for language-tagged downloads.
|
||||
- [x] #3 Automated tests cover the reproduced manual en/ja selection case.
|
||||
@@ -40,7 +37,6 @@ Ensure launcher YouTube subtitle generation reuses downloadable manual subtitle
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Reproduced against https://www.youtube.com/watch?v=MXzQRLmN9hE with yt-dlp --list-subs: manual zh/en/ja/ko subtitle tracks are available from YouTube.
|
||||
|
||||
Adjusted launcher YouTube orchestration so detected manual subtitle tracks suppress whisper generation but are no longer materialized as external subtitle files. SubMiner now relies on the native YouTube/mpv subtitle tracks for those languages.
|
||||
@@ -48,13 +44,10 @@ Adjusted launcher YouTube orchestration so detected manual subtitle tracks suppr
|
||||
Added orchestration tests covering the manual-track reuse plan and ran a direct runtime probe against MXzQRLmN9hE. Probe result: primary/secondary native tracks detected, no external subtitle aliases emitted, output directory remained empty.
|
||||
|
||||
Verification: bun test launcher/youtube/orchestrator.test.ts launcher/config-domain-parsers.test.ts launcher/mpv.test.ts passed; bun run typecheck passed.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Fixed the YouTube subtitle regression where videos with real downloadable subtitle tracks still ended up with duplicate external subtitle files. Manual subtitle availability now suppresses whisper generation and external subtitle publication, so videos like MXzQRLmN9hE use the native YouTube/mpv subtitle tracks directly. Launcher preprocess logging was also updated to report native subtitle availability instead of misleading missing statuses.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- Codex
|
||||
created_date: '2026-03-08 06:13'
|
||||
updated_date: '2026-03-08 06:28'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- release
|
||||
- changelog
|
||||
@@ -19,20 +19,17 @@ references:
|
||||
- /Users/sudacode/projects/japanese/SubMiner/docs/RELEASING.md
|
||||
- /Users/sudacode/projects/japanese/SubMiner/changes/README.md
|
||||
priority: medium
|
||||
ordinal: 63500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Improve the release changelog workflow so changelog fragments are reliable, release output is more readable, and pull requests get early feedback when changelog metadata is missing or malformed.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 `scripts/build-changelog.ts` ignores non-fragment files in `changes/` and validates fragment structure before generating changelog output.
|
||||
- [x] #2 Generated `CHANGELOG.md` and `release/release-notes.md` group public changes into readable sections instead of a flat bullet list.
|
||||
- [x] #3 CI enforces changelog validation on pull requests and provides an explicit opt-out path for changes that should not produce release notes.
|
||||
@@ -43,7 +40,6 @@ Improve the release changelog workflow so changelog fragments are reliable, rele
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Add failing tests for changelog fragment discovery, structured fragment parsing/rendering, release-note output, and CI workflow expectations.
|
||||
2. Update scripts/build-changelog.ts to ignore non-fragment files, parse fragment metadata, group generated output by change type, add lint/PR-check commands, and simplify output paths to repo-local artifacts.
|
||||
3. Update CI and PR workflow files to run changelog validation on pull requests with an explicit skip path, and keep release workflow using committed changelog output.
|
||||
@@ -54,7 +50,6 @@ Improve the release changelog workflow so changelog fragments are reliable, rele
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Implemented structured changelog fragments with required `type` and `area` metadata; `changes/README.md` is now ignored by the generator and verified by regression tests.
|
||||
|
||||
Added `changelog:lint` and `changelog:pr-check`, plus PR CI enforcement with `skip-changelog` opt-out. PR check now reads git name-status output so deleted fragment files do not satisfy the requirement.
|
||||
@@ -64,17 +59,14 @@ Changed generated changelog/release notes output to grouped sections (`Added`, `
|
||||
Kept changelog output repo-local. This aligns with existing repo direction where docs updates happen in the sibling docs repo explicitly rather than implicit local writes from app-repo generators.
|
||||
|
||||
Verification: `bun test scripts/build-changelog.test.ts src/ci-workflow.test.ts src/release-workflow.test.ts` passed; `bun run typecheck` passed; `bun run changelog:lint` passed. `bun run test:fast` still fails in unrelated existing `src/core/services/subsync.test.ts` cases (`runSubsyncManual keeps internal alass source file alive until sync finishes`, `runSubsyncManual resolves string sid values from mpv stream properties`).
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Hardened the changelog workflow end-to-end. `scripts/build-changelog.ts` now ignores helper files like `changes/README.md`, requires structured fragment metadata (`type` + `area`), groups generated release sections by change type, and emits shorter release notes focused on highlights plus install/assets pointers. Added explicit `changelog:lint` and `changelog:pr-check` commands, with PR validation based on git name-status so deleted fragment files do not satisfy the fragment requirement.
|
||||
|
||||
Updated contributor-facing workflow docs in `changes/README.md`, `docs/RELEASING.md`, and a new PR template so authors know to add a fragment or apply the `skip-changelog` label. CI now runs fragment linting on every run and enforces fragment presence on pull requests. Added regression coverage in `scripts/build-changelog.test.ts` and a new `src/ci-workflow.test.ts` to lock the workflow contract.
|
||||
|
||||
Verification completed: `bun test scripts/build-changelog.test.ts src/ci-workflow.test.ts src/release-workflow.test.ts`, `bun run typecheck`, and `bun run changelog:lint` all passed. A broader `bun run test:fast` run still fails in unrelated existing `src/core/services/subsync.test.ts` cases outside the changelog/workflow scope.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- '@codex'
|
||||
created_date: '2026-03-08 07:07'
|
||||
updated_date: '2026-03-08 07:15'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- ux
|
||||
- logging
|
||||
@@ -20,20 +20,17 @@ references:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/launcher/youtube/subtitle-fix-ai.ts
|
||||
priority: medium
|
||||
ordinal: 62500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Improve launcher YouTube subtitle generation observability so users can tell that work is happening and roughly how long each phase is taking. Cover manual subtitle probe, audio extraction, ffmpeg prep, whisper generation, and optional AI subtitle fix phases without flooding normal logs.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Users see clear info-level phase logs for YouTube subtitle generation work including subtitle probe, fallback audio extraction, whisper, and optional AI fix phases.
|
||||
- [x] #2 Long-running phases surface elapsed-time progress or explicit start/finish timing so it is obvious the process is still active.
|
||||
- [x] #3 Automated tests cover the new logging/progress helper behavior where practical.
|
||||
@@ -42,19 +39,15 @@ Improve launcher YouTube subtitle generation observability so users can tell tha
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Implemented a shared timed YouTube phase logger in launcher/youtube/progress.ts with info-level start/finish messages and warn-level failure messages that include elapsed time.
|
||||
|
||||
Wired phase logging into YouTube metadata probe, manual subtitle probe, fallback audio extraction, ffmpeg whisper prep, whisper primary/secondary generation, and optional AI subtitle fix phases.
|
||||
|
||||
Verification: bun test launcher/youtube/progress.test.ts launcher/youtube/orchestrator.test.ts passed; bun run typecheck passed.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Added clear phase-level observability for YouTube subtitle generation without noisy tool output. Users now see start/finish logs with elapsed time for subtitle probe, fallback audio extraction, ffmpeg prep, whisper generation, and optional AI subtitle-fix phases, making it obvious when generation is active and roughly how long each step took.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -7,7 +7,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 07:18'
|
||||
updated_date: '2026-03-08 07:28'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- launcher
|
||||
- youtube
|
||||
@@ -27,20 +27,17 @@ references:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/config/resolve/subtitle-domains.ts
|
||||
priority: high
|
||||
ordinal: 61500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Simplify launcher YouTube playback by removing the configurable subtitle generation mode. For YouTube targets, the launcher should treat subtitle generation/loading as the canonical behavior instead of supporting off/preprocess/automatic branches. This change should remove the unreliable automatic/background path and the mode concept from config/CLI/env/docs, while preserving the core YouTube subtitle generation pipeline and mpv loading flow.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Launcher playback no longer supports or branches on a YouTube subtitle generation mode; YouTube URLs follow a single generation-and-load flow.
|
||||
- [x] #2 Configuration, CLI parsing, and environment handling no longer expose a YouTube subtitle generation mode option, and stale automatic/preprocess/off values are not part of the supported interface.
|
||||
- [x] #3 Tests cover the new single-flow behavior and the removal of mode parsing/branching.
|
||||
@@ -50,7 +47,6 @@ Simplify launcher YouTube playback by removing the configurable subtitle generat
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Remove the YouTube subtitle generation mode concept from launcher/shared types, config parsing, CLI options, and environment normalization so no supported interface accepts automatic/preprocess/off.
|
||||
2. Update playback orchestration so YouTube targets always run subtitle generation/loading before mpv startup and delete the background automatic path.
|
||||
3. Adjust mpv YouTube URL argument construction to no longer branch on mode while preserving subtitle/audio language behavior and preloaded subtitle file injection.
|
||||
@@ -61,7 +57,6 @@ Simplify launcher YouTube playback by removing the configurable subtitle generat
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Removed launcher/shared youtubeSubgen.mode handling and collapsed YouTube playback onto a single preload-before-mpv subtitle generation flow.
|
||||
|
||||
Added launcher integration coverage proving YouTube subtitle generation runs before mpv startup and that the removed --mode flag now errors.
|
||||
@@ -69,17 +64,14 @@ Added launcher integration coverage proving YouTube subtitle generation runs bef
|
||||
Verification: bun test launcher/config-domain-parsers.test.ts launcher/parse-args.test.ts launcher/mpv.test.ts launcher/main.test.ts src/config/config.test.ts; bun run test:config:src; bun run typecheck.
|
||||
|
||||
Broader repo checks still show pre-existing issues outside this change: bun run test:launcher:unit:src fails in launcher/aniskip-metadata.test.ts (MAL id assertion), and format scope check reports unrelated existing files launcher/youtube/orchestrator.ts, scripts/build-changelog.test.ts, scripts/build-changelog.ts.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Removed the launcher YouTube subtitle generation mode surface so YouTube playback now always runs the subtitle generation pipeline before starting mpv. The launcher no longer accepts youtubeSubgen.mode from shared config, CLI, or env normalization, and the old automatic/background loading path has been deleted from playback.
|
||||
|
||||
Updated mpv YouTube startup options to keep manual subtitle discovery enabled without requesting auto subtitles, and refreshed user-facing config/docs to describe a single YouTube subtitle generation flow. Added regression coverage for mode removal, config/template cleanup, and launcher ordering so YouTube subtitle work is confirmed to happen before mpv launch.
|
||||
|
||||
Verification: bun test launcher/config-domain-parsers.test.ts launcher/parse-args.test.ts launcher/mpv.test.ts launcher/main.test.ts src/config/config.test.ts; bun run test:config:src; bun run typecheck. Broader unrelated repo issues remain in launcher/aniskip-metadata.test.ts and existing formatting drift in launcher/youtube/orchestrator.ts plus scripts/build-changelog files.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -4,6 +4,7 @@ title: Add native AI API key secret storage
|
||||
status: To Do
|
||||
assignee: []
|
||||
created_date: '2026-03-08 07:25'
|
||||
updated_date: '2026-03-18 05:27'
|
||||
labels:
|
||||
- ai
|
||||
- config
|
||||
@@ -17,20 +18,17 @@ references:
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/core/services/jellyfin-token-store.ts
|
||||
- /Users/sudacode/projects/japanese/SubMiner/src/main.ts
|
||||
priority: medium
|
||||
ordinal: 2000
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Store the shared AI provider API key using the app's native secret-storage pattern so users do not need to keep the OpenRouter key in config files or shell commands.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [ ] #1 Users can configure the shared AI provider without storing the API key in config.jsonc.
|
||||
- [ ] #2 The app persists and reloads the shared AI API key using encrypted native secret storage when available.
|
||||
- [ ] #3 Behavior is defined for existing ai.apiKey and ai.apiKeyCommand configs, including compatibility during migration.
|
||||
|
||||
@@ -6,27 +6,24 @@ title: >-
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-08 07:35'
|
||||
updated_date: '2026-03-08 07:40'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- overlay
|
||||
- subtitles
|
||||
- ui
|
||||
dependencies: []
|
||||
priority: medium
|
||||
ordinal: 60500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Adjust overlay secondary subtitle styling so translation text stays readable on bright video backgrounds. Keep the dark background hidden by default in hover mode and show it only while hovered. Increase secondary subtitle weight to 600 and strengthen edge separation without changing primary subtitle styling.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Secondary subtitles render with stronger edge separation than today.
|
||||
- [x] #2 Secondary subtitle font weight defaults to 600.
|
||||
- [x] #3 When secondary subtitle mode is hover, the secondary background appears only while hovered.
|
||||
@@ -37,15 +34,11 @@ Adjust overlay secondary subtitle styling so translation text stays readable on
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Adjusted secondary subtitle defaults to use stronger shadowing, 600 font weight, and a translucent dark background. Routed secondary background/backdrop styling through CSS custom properties so hover mode can keep the background hidden until the secondary subtitle is actually hovered. Added renderer and config tests covering default values and hover-only background behavior.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Improved secondary subtitle readability by strengthening default text separation, increasing the default secondary weight to 600, and making the configured dark background appear only while hovered in secondary hover mode. Added config and renderer coverage for the new defaults and hover-aware style routing.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- '@codex'
|
||||
created_date: '2026-03-08 08:24'
|
||||
updated_date: '2026-03-08 10:12'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- bug
|
||||
- launcher
|
||||
@@ -16,20 +16,17 @@ references:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/launcher/commands/playback-command.ts
|
||||
- /Users/sudacode/projects/japanese/SubMiner/launcher/mpv.test.ts
|
||||
ordinal: 56500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Prevent launcher playback from attempting AniSkip metadata resolution when the user is playing a YouTube target or any URL target. AniSkip only works for local anime files, so URL-driven playback and YouTube subtitle-generation flows should bypass it entirely.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Launcher playback skips AniSkip metadata resolution for explicit URL targets, including YouTube URLs.
|
||||
- [x] #2 YouTube subtitle-generation playback does not invoke AniSkip lookup before mpv launch.
|
||||
- [x] #3 Automated launcher tests cover the URL/YouTube skip behavior.
|
||||
@@ -38,7 +35,6 @@ Prevent launcher playback from attempting AniSkip metadata resolution when the u
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Add a launcher mpv unit test that intercepts AniSkip resolution and proves URL/YouTube playback does not call it before spawning mpv.
|
||||
2. Run the focused launcher mpv test to confirm the new case fails or exposes the current gap.
|
||||
3. Patch launcher playback/AniSkip gating so URL and YouTube subtitle-generation paths always bypass AniSkip lookup.
|
||||
@@ -54,7 +50,6 @@ Prevent launcher playback from attempting AniSkip metadata resolution when the u
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Added explicit AniSkip gating in launcher/mpv.ts via shouldResolveAniSkipMetadata(target, targetKind, preloadedSubtitles).
|
||||
|
||||
URL targets now always bypass AniSkip. File targets with preloaded subtitles also bypass AniSkip, covering YouTube subtitle-preload playback.
|
||||
@@ -80,13 +75,10 @@ Verification: lua scripts/test-plugin-start-gate.lua passed.
|
||||
Verification: bun run test:plugin:src passed.
|
||||
|
||||
Verification: bun test launcher/mpv.test.ts passed after plugin-side fix.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Fixed AniSkip suppression end-to-end for URL playback. The launcher now skips AniSkip before mpv launch, and the mpv plugin now also refuses AniSkip lookups for remote URL media during file-loaded, overlay-start, or later refresh triggers. Added regression coverage in both launcher/mpv.test.ts and scripts/test-plugin-start-gate.lua, plus a changelog fragment. Wider `bun run test:launcher:unit:src` is still blocked by the unrelated existing launcher/aniskip-metadata.test.ts MAL-id failure.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -6,27 +6,24 @@ title: >-
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-08 09:02'
|
||||
updated_date: '2026-03-08 09:17'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- bug
|
||||
- youtube-subgen
|
||||
- ai
|
||||
dependencies: []
|
||||
priority: high
|
||||
ordinal: 58500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
AI subtitle cleanup can preserve cue structure while changing subtitle language, causing primary Japanese subtitle files to come back in English. Add guards so AI-fixed subtitles preserve expected language and fall back to raw Whisper output when language drifts.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Primary AI subtitle fix rejects output that drifts away from the expected source language.
|
||||
- [x] #2 Rejected AI fixes fall back to the raw Whisper subtitle without corrupting published subtitle language.
|
||||
- [x] #3 Regression tests cover a primary Japanese subtitle batch being translated into English by the AI fixer.
|
||||
@@ -35,7 +32,5 @@ AI subtitle cleanup can preserve cue structure while changing subtitle language,
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Added a primary-language guard to AI subtitle fixing so Japanese source subtitles are rejected if the AI rewrites them into English while preserving SRT structure. The fixer now receives the expected source language from the YouTube orchestrator, and regression coverage verifies that language drift falls back to the raw Whisper subtitle path.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -6,7 +6,7 @@ title: >-
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-08 09:40'
|
||||
updated_date: '2026-03-08 09:57'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- config
|
||||
- ai
|
||||
@@ -14,20 +14,17 @@ labels:
|
||||
- youtube-subgen
|
||||
dependencies: []
|
||||
priority: high
|
||||
ordinal: 57500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
The current top-level shared AI config forces Anki translation and YouTube subtitle fixing to share the same model and system prompt, which caused subtitle-fix requests to inherit a translation prompt and translate Japanese primary subtitles into English. Refactor config so provider credentials stay shared while model and system prompt can be configured per feature.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Anki integration can use its own AI model and system prompt independently of YouTube subtitle generation.
|
||||
- [x] #2 YouTube subtitle generation can use its own AI model and system prompt independently of Anki integration.
|
||||
- [x] #3 Existing shared provider credentials remain reusable without duplicating API key/base URL config.
|
||||
@@ -37,7 +34,5 @@ The current top-level shared AI config forces Anki translation and YouTube subti
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Added per-feature AI model/systemPrompt overrides for Anki and YouTube subtitle generation while keeping shared provider transport settings reusable. Anki now accepts `ankiConnect.ai` object config with `enabled`, `model`, and `systemPrompt`; YouTube subtitle generation accepts `youtubeSubgen.ai` overrides and merges them over the shared AI provider config. Updated config resolution, launcher parsing, runtime wiring, hot-reload handling, example config, and regression coverage.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 10:08'
|
||||
updated_date: '2026-03-08 11:00'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- bug
|
||||
- launcher
|
||||
@@ -13,20 +13,17 @@ labels:
|
||||
- overlay
|
||||
dependencies: []
|
||||
priority: high
|
||||
ordinal: 55500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
The launcher currently tears down the running SubMiner background process when a launcher-managed mpv session exits. Background SubMiner should remain alive so a later mpv instance can reconnect and request the overlay without restarting the app.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Closing a launcher-managed mpv session does not send `--stop` to the running SubMiner background process.
|
||||
- [x] #2 Closing a launcher-managed mpv session does not SIGTERM the tracked SubMiner process just because mpv exited.
|
||||
- [x] #3 Launcher cleanup still terminates mpv and launcher-owned helper children without regressing existing overlay start behavior.
|
||||
@@ -36,7 +33,6 @@ The launcher currently tears down the running SubMiner background process when a
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Add a launcher regression test that proves mpv exit no longer triggers SubMiner `--stop` or launcher SIGTERM of the tracked overlay process.
|
||||
2. Update launcher teardown so normal mpv-session cleanup only stops mpv/helper children and preserves the background SubMiner process for future reconnects.
|
||||
3. Run the focused launcher tests and smoke coverage for the affected behavior, then record results in the task.
|
||||
@@ -45,7 +41,6 @@ The launcher currently tears down the running SubMiner background process when a
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Split launcher cleanup so normal mpv-session shutdown no longer sends `--stop` to SubMiner or SIGTERM to the tracked overlay process. Added `cleanupPlaybackSession()` for mpv/helper-child cleanup only, and switched playback finalization to use it.
|
||||
|
||||
Updated launcher smoke coverage to assert the background app stays alive after mpv exits, and added a focused unit regression for the new cleanup path.
|
||||
@@ -61,13 +56,11 @@ Patched the remaining stop path in `plugin/subminer/lifecycle.lua`: mpv `shutdow
|
||||
Validation update: `lua scripts/test-plugin-start-gate.lua` passed after adding a shutdown regression, and `bun test launcher/mpv.test.ts launcher/smoke.e2e.test.ts` still passed.
|
||||
|
||||
Fixed a second-instance reconnect bug in `src/core/services/cli-command.ts`: `--start` on an already-initialized running instance now still updates the MPV socket path and reconnects the MPV client instead of treating the command as a no-op. This keeps the already-warmed background app reusable for later mpv launches.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Kept the background SubMiner process reusable across both mpv shutdown and later reconnects. The first fix separated launcher playback cleanup from full app shutdown. The second fix removed the mpv plugin `shutdown` stop call so default mpv `q` no longer sends SubMiner `--stop`. The third fix corrected second-instance CLI handling so `--start` on an already-running, already-initialized instance still reconnects MPV instead of being ignored.
|
||||
|
||||
Net effect: background SubMiner can stay alive, keep its warm state, and reconnect to later mpv instances without rerunning startup/warmup work in a fresh app instance.
|
||||
@@ -82,5 +75,4 @@ Tests run:
|
||||
- `bun run changelog:lint`
|
||||
|
||||
Note: the broader `bun run test:launcher:unit:src` lane still has an unrelated pre-existing failure in `launcher/aniskip-metadata.test.ts`.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
---
|
||||
id: TASK-131
|
||||
title: Avoid duplicate tokenization warmup after background startup
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 10:12'
|
||||
updated_date: '2026-03-08 12:00'
|
||||
labels:
|
||||
- bug
|
||||
dependencies: []
|
||||
references:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/main/runtime/composers/mpv-runtime-composer.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/main/runtime/startup-warmups.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/main/runtime/composers/mpv-runtime-composer.test.ts
|
||||
priority: medium
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
When SubMiner is already running in the background and mpv is launched from the launcher or mpv plugin, the live app should reuse startup tokenization warmup state instead of re-entering the Yomitan/tokenization/annotation warmup path on first overlay use.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Background startup tokenization warmup is recorded in the runtime state used by later mpv/tokenization flows.
|
||||
- [x] #2 Launching mpv from the launcher or plugin against an already-running background app does not re-run duplicate Yomitan/tokenization annotation warmup work in the live process.
|
||||
- [x] #3 Regression tests cover the warmed-background path and protect against re-entering duplicate warmup work.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Add a regression test covering the case where background startup warmups already completed and a later tokenize call must not re-enter Yomitan/MeCab/dictionary warmups.
|
||||
2. Update mpv tokenization warmup composition so startup background warmups and on-demand tokenization share the same completion state.
|
||||
3. Run the focused composer/runtime tests and update acceptance criteria/notes with results.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Root-cause hypothesis: startup background warmups and on-demand tokenization warmups use separate state, so later mpv launch can re-enter warmup bookkeeping even though background startup already warmed dependencies.
|
||||
|
||||
Implemented shared warmup state between startup background warmups and on-demand tokenization warmups by forwarding scheduled Yomitan/tokenization promises into the mpv runtime composer. Added regression coverage for the warmed-background path. Verified with `bun run test:fast` plus focused composer/startup warmup tests.
|
||||
|
||||
Follow-up root cause from live retest: second mpv open could still pause on the startup gate because the runtime only treated full background tokenization warmup completion as reusable readiness. In practice, first-file tokenization could already be ready while slower dictionary prewarm work was still finishing, so reopening a video waited on duplicate warmup completion even though annotations were already usable.
|
||||
|
||||
Adjusted `src/main/runtime/composers/mpv-runtime-composer.ts` so autoplay reuse keys off a separate playback-ready latch. The latch flips true either when background warmups fully cover tokenization or when `onTokenizationReady` fires for a real subtitle line. `src/main.ts` already uses `isTokenizationWarmupReady()` to fast-signal `subminer-autoplay-ready` on a fresh media-path change, so reopened videos can now resume immediately once tokenization has succeeded once in the persistent app.
|
||||
|
||||
Validation update: `bun test src/core/services/cli-command.test.ts src/main/runtime/mpv-main-event-actions.test.ts src/main/runtime/composers/mpv-runtime-composer.test.ts launcher/mpv.test.ts launcher/smoke.e2e.test.ts` passed, `lua scripts/test-plugin-start-gate.lua` passed, and `bun run typecheck` passed.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Background startup tokenization warmups now feed the same in-memory warmup state used by later mpv tokenization. When the app is already running and warmed in the background, launcher/plugin-driven mpv startup reuses that state instead of re-entering Yomitan/tokenization annotation warmups. Added a regression test for the warmed-background path and verified with `bun run test:fast`.
|
||||
|
||||
A later follow-up fixed the remaining second-open delay: autoplay reuse no longer waits for the entire background dictionary warmup pipeline to finish. After the persistent app has produced one tokenization-ready event, later mpv reconnects reuse that readiness immediately, so reopening the same or another video does not pause again on duplicate warmup bookkeeping.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -1,31 +1,30 @@
|
||||
---
|
||||
id: TASK-131
|
||||
title: Make default overlay fullscreen and AniSkip end-jump keybindings easier to reach
|
||||
title: >-
|
||||
Make default overlay fullscreen and AniSkip end-jump keybindings easier to
|
||||
reach
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-09 00:00'
|
||||
updated_date: '2026-03-09 00:30'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- enhancement
|
||||
- overlay
|
||||
- mpv
|
||||
- aniskip
|
||||
dependencies: []
|
||||
ordinal: 43500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Make two default keyboard actions easier to hit during playback: add `f` as the built-in overlay fullscreen toggle, and make AniSkip's default intro-end jump use `Tab`.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Default overlay keybindings include `KeyF` mapped to mpv fullscreen toggle.
|
||||
- [x] #2 Default AniSkip hint/button key defaults to `Tab` and the plugin registers that binding.
|
||||
- [x] #3 Automated regression coverage exists for both default bindings.
|
||||
@@ -34,7 +33,6 @@ Make two default keyboard actions easier to hit during playback: add `f` as the
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Add a failing TypeScript regression proving default overlay keybindings include fullscreen on `KeyF`.
|
||||
2. Add a failing Lua/plugin regression proving AniSkip defaults to `Tab`, updates the OSD hint text, and registers the expected keybinding.
|
||||
3. Patch the default keybinding/config values with minimal behavior changes and keep fallback binding behavior intentional.
|
||||
@@ -44,7 +42,6 @@ Make two default keyboard actions easier to hit during playback: add `f` as the
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Added `KeyF -> ['cycle', 'fullscreen']` to the built-in overlay keybindings in `src/config/definitions/shared.ts`.
|
||||
|
||||
Changed the mpv plugin AniSkip default button key from `y-k` to `TAB` in both the runtime default options and the shipped `plugin/subminer.conf`. The AniSkip OSD hint now also falls back to `TAB` when no explicit key is configured.
|
||||
@@ -72,9 +69,7 @@ Known unrelated verification gap:
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Default overlay playback now has an easier fullscreen toggle on `f`, and AniSkip's default intro-end jump now uses `Tab`. The mpv plugin hint text and registration logic were updated to match the new default, while keeping legacy `y-k` fallback behavior limited to custom non-default bindings.
|
||||
|
||||
Regression coverage was added for both defaults, and the plugin test harness now resets plugin bootstrap state between scenarios so keybinding assertions can run reliably.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 18:24'
|
||||
updated_date: '2026-03-08 18:55'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- bug
|
||||
- macos
|
||||
@@ -19,20 +19,17 @@ references:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/scripts/get-mpv-window-macos.swift
|
||||
priority: high
|
||||
ordinal: 53500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Fix the macOS shortcut handling so SubMiner overlay keybinds do not intercept system or other-app shortcuts while SubMiner is in the background. Overlay shortcuts should only be active while the tracked mpv window is present and focused, and should stop grabbing keyboard input when mpv is not the frontmost window.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 On macOS, overlay shortcuts do not trigger while mpv is not the focused/frontmost window.
|
||||
- [x] #2 On macOS, overlay shortcuts remain available while the tracked mpv window is open and focused.
|
||||
- [x] #3 Existing non-macOS shortcut behavior is unchanged.
|
||||
@@ -43,7 +40,6 @@ Fix the macOS shortcut handling so SubMiner overlay keybinds do not intercept sy
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Add a failing macOS-focused shortcut lifecycle test that proves overlay shortcuts stay inactive when the tracked mpv window exists but is not frontmost, and activate when that tracked window becomes frontmost.
|
||||
2. Add a failing tracker/helper test that covers the focused/frontmost signal parsed from the macOS helper output.
|
||||
3. Extend the macOS helper/tracker contract to surface both geometry and focused/frontmost state for the tracked mpv window.
|
||||
@@ -54,7 +50,6 @@ Fix the macOS shortcut handling so SubMiner overlay keybinds do not intercept sy
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Added a macOS-specific shortcut activation predicate so global overlay shortcuts now require both overlay runtime readiness and a focused tracked mpv window; non-macOS behavior still keys off runtime readiness only.
|
||||
|
||||
Extended the base window tracker with optional focus-state callbacks/getters and wired initializeOverlayRuntime to re-sync overlay shortcuts whenever tracker focus changes.
|
||||
@@ -64,15 +59,12 @@ Updated the macOS helper/tracker contract to return geometry plus frontmost/focu
|
||||
Verified with `bun x tsc -p tsconfig.json --noEmit`, targeted shortcut/tracker tests, and `bun run test:core:src` (439 passing).
|
||||
|
||||
No user-facing config or documentation surface changed, so no docs update was required for this fix.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Fixed the macOS background shortcut interception bug by gating SubMiner's global overlay shortcuts on tracked mpv focus instead of overlay-runtime initialization alone. The macOS window helper now reports whether the tracked mpv process is frontmost, the tracker exposes focus change callbacks, and overlay shortcut synchronization re-runs when that focus state flips so `Ctrl+C`/`Ctrl+V` and similar shortcuts are no longer captured while mpv is in the background.
|
||||
|
||||
The change keeps existing non-macOS shortcut behavior unchanged. Added regression coverage for the activation decision, tracker focus-change re-sync, and macOS helper output parsing. Verification: `bun x tsc -p tsconfig.json --noEmit`, targeted shortcut/tracker tests, and `bun run test:core:src` (439 passing).
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
id: TASK-133
|
||||
title: Improve AniList character dictionary parity with upstream guide
|
||||
status: In Progress
|
||||
status: To Do
|
||||
assignee:
|
||||
- OpenCode
|
||||
created_date: '2026-03-08 21:06'
|
||||
updated_date: '2026-03-10 06:18'
|
||||
updated_date: '2026-03-18 05:27'
|
||||
labels:
|
||||
- dictionary
|
||||
- anilist
|
||||
@@ -24,6 +24,7 @@ documentation:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/docs/plans/2026-03-08-anilist-character-dictionary-parity.md
|
||||
priority: high
|
||||
ordinal: 3000
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-09 00:00'
|
||||
updated_date: '2026-03-08 20:23'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- ci
|
||||
- release
|
||||
@@ -16,22 +16,19 @@ references:
|
||||
- .github/workflows/release.yml
|
||||
- package.json
|
||||
- src/release-workflow.test.ts
|
||||
- https://github.com/ksyasuda/SubMiner/actions/runs/22836585479
|
||||
- 'https://github.com/ksyasuda/SubMiner/actions/runs/22836585479'
|
||||
priority: high
|
||||
ordinal: 52500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
The tag-driven Release workflow currently fails the Windows lane if the SignPath connector returns transient 502 errors during submission, and the tagged build scripts also allow electron-builder to implicitly publish unsigned artifacts before the final release job runs. Harden the workflow so transient SignPath outages get bounded retries and release packaging never auto-publishes unsigned assets.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [ ] #1 Windows release signing retries transient SignPath submission failures within the release workflow before failing the job.
|
||||
- [ ] #2 Release packaging scripts disable electron-builder implicit publish so build jobs do not upload unsigned assets on tag builds.
|
||||
- [ ] #3 Regression coverage fails if SignPath retry scaffolding or publish suppression is removed.
|
||||
@@ -40,7 +37,6 @@ The tag-driven Release workflow currently fails the Windows lane if the SignPath
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Add a regression test for the release workflow/package script shape covering SignPath retries and `--publish never`.
|
||||
2. Patch the Windows release job to retry SignPath submission a bounded number of times and still fail hard if every attempt fails.
|
||||
3. Update tagged package build scripts to disable implicit electron-builder publishing during release builds.
|
||||
@@ -50,7 +46,6 @@ The tag-driven Release workflow currently fails the Windows lane if the SignPath
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
The failed Windows signing step in GitHub Actions run `22836585479` was not caused by missing secrets or an artifact-shape mismatch. The SignPath GitHub action retried repeated `502` responses from the SignPath connector for several minutes and then failed the job.
|
||||
|
||||
Hardened `.github/workflows/release.yml` by replacing the single SignPath submission with three bounded attempts. The second and third submissions only run if the previous attempt failed, and the job now fails with an explicit rerun message only after all three attempts fail. Signed-artifact upload is keyed to the successful attempt so the release job still consumes the normal `windows` artifact name.
|
||||
@@ -58,18 +53,15 @@ Hardened `.github/workflows/release.yml` by replacing the single SignPath submis
|
||||
Also fixed a separate release regression exposed by the same run: `electron-builder` was implicitly publishing unsigned release assets during tag builds because the packaging scripts did not set `--publish never` and the workflow injected `GH_TOKEN` into build jobs. Updated the relevant package scripts to pass `--publish never`, removed `GH_TOKEN` from the packaging jobs, and made the final publish step force `--draft=false` when editing an existing tag release so previously-created draft releases get published.
|
||||
|
||||
Verification: `bun test src/release-workflow.test.ts`, `bun run typecheck`, and `bun run test:fast` all passed locally after restoring the missing local `libsql` install with `bun install --frozen-lockfile`.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Windows release signing is now resilient to transient SignPath connector outages. The release workflow retries the SignPath submission up to three times before failing, and only uploads the signed Windows artifact from the attempt that succeeded.
|
||||
|
||||
Release packaging also no longer auto-publishes unsigned assets on tag builds. The `electron-builder` scripts now force `--publish never`, the build jobs no longer pass `GH_TOKEN` into packaging steps, and the final GitHub release publish step explicitly clears draft state when updating an existing tag release.
|
||||
|
||||
Validation: `bun test src/release-workflow.test.ts`, `bun run typecheck`, `bun run test:fast`.
|
||||
Manual follow-up for the failed `v0.5.0` release: rerun the `Release` workflow after merging/pushing this fix, then clean up the stray draft/untagged release assets created by the failed run if they remain.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 20:24'
|
||||
updated_date: '2026-03-08 20:28'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- release
|
||||
- patch
|
||||
@@ -16,20 +16,17 @@ references:
|
||||
- CHANGELOG.md
|
||||
- release/release-notes.md
|
||||
priority: high
|
||||
ordinal: 51500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Publish a patch release from the workflow-signing fix on `main` by bumping the app version, generating the committed changelog artifacts for the new version, and pushing a new `v0.5.1` tag instead of rewriting the failed `v0.5.0` tag.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [ ] #1 Repository version metadata is updated to `0.5.1`.
|
||||
- [ ] #2 `CHANGELOG.md` and `release/release-notes.md` contain the committed `v0.5.1` section and released fragments are removed.
|
||||
- [ ] #3 New `v0.5.1` commit and tag are pushed to `origin`.
|
||||
@@ -38,7 +35,6 @@ Publish a patch release from the workflow-signing fix on `main` by bumping the a
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Bump the package version to `0.5.1`.
|
||||
2. Run the changelog builder so `CHANGELOG.md`/`release-notes.md` match the release workflow contract.
|
||||
3. Run the relevant verification commands.
|
||||
@@ -48,19 +44,15 @@ Publish a patch release from the workflow-signing fix on `main` by bumping the a
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Bumped `package.json` from `0.5.0` to `0.5.1`, then ran `bun run changelog:build` so the committed release artifacts match the release workflow contract. That prepended the `v0.5.1` section to `CHANGELOG.md`, regenerated `release/release-notes.md`, and removed the consumed changelog fragments from `changes/`.
|
||||
|
||||
Verification before tagging: `bun run changelog:lint`, `bun run changelog:check --version 0.5.1`, `bun run typecheck`, and `bun run test:fast`.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Prepared patch release `v0.5.1` from the signing-workflow fix on `main` instead of rewriting the failed `v0.5.0` tag. Repository version metadata, changelog, and committed release notes are all aligned with the new release tag, and the consumed changelog fragments were removed.
|
||||
|
||||
Validation: `bun run changelog:lint`, `bun run changelog:check --version 0.5.1`, `bun run typecheck`, `bun run test:fast`.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 20:41'
|
||||
updated_date: '2026-03-08 20:58'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- ci
|
||||
- release
|
||||
@@ -18,20 +18,17 @@ references:
|
||||
- build/signpath-windows-artifact-config.xml
|
||||
- src/release-workflow.test.ts
|
||||
priority: high
|
||||
ordinal: 49500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
The Windows release workflow currently relies on the default SignPath artifact configuration configured in the SignPath UI. Pin the workflow to an explicit artifact-configuration slug so the checked-in signing configuration and CI behavior stay deterministic across future SignPath project changes.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [ ] #1 The Windows release workflow validates a dedicated SignPath artifact-configuration secret/input.
|
||||
- [ ] #2 Every SignPath submission attempt passes `artifact-configuration-slug`.
|
||||
- [ ] #3 Regression coverage fails if the explicit SignPath artifact-configuration binding is removed.
|
||||
@@ -40,7 +37,6 @@ The Windows release workflow currently relies on the default SignPath artifact c
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Add a failing workflow regression test for the explicit SignPath artifact-configuration slug.
|
||||
2. Patch the Windows signing secret validation and SignPath action inputs to require the slug.
|
||||
3. Run targeted release-workflow verification plus the standard fast lane.
|
||||
@@ -50,21 +46,17 @@ The Windows release workflow currently relies on the default SignPath artifact c
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Added regression coverage in `src/release-workflow.test.ts` for an explicit SignPath artifact-configuration slug so the release workflow test now fails if the slug validation or action input is removed.
|
||||
|
||||
Patched `.github/workflows/release.yml` so Windows signing now requires `SIGNPATH_ARTIFACT_CONFIGURATION_SLUG` during secret validation and passes `artifact-configuration-slug: ${{ secrets.SIGNPATH_ARTIFACT_CONFIGURATION_SLUG }}` on every SignPath submission attempt.
|
||||
|
||||
Verification: `bun test src/release-workflow.test.ts`, `bun run typecheck`, `bun run test:fast`.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
The release workflow is now pinned to an explicit SignPath artifact configuration instead of relying on whichever SignPath artifact config is marked default in the UI. Windows signing secret validation fails fast if `SIGNPATH_ARTIFACT_CONFIGURATION_SLUG` is missing, and every SignPath submission attempt now includes the pinned slug.
|
||||
|
||||
Validation: `bun test src/release-workflow.test.ts`, `bun run typecheck`, `bun run test:fast`.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-08 20:44'
|
||||
updated_date: '2026-03-08 20:58'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- release
|
||||
- patch
|
||||
@@ -16,20 +16,17 @@ references:
|
||||
- CHANGELOG.md
|
||||
- release/release-notes.md
|
||||
priority: high
|
||||
ordinal: 50500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Publish a patch release from the SignPath artifact-configuration pinning change by bumping the app version, generating the committed changelog artifacts for the new version, and pushing a new `v0.5.2` tag.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [ ] #1 Repository version metadata is updated to `0.5.2`.
|
||||
- [ ] #2 `CHANGELOG.md` and `release/release-notes.md` contain the committed `v0.5.2` section and consumed fragments are removed.
|
||||
- [ ] #3 New `v0.5.2` commit and tag are pushed to `origin`.
|
||||
@@ -38,7 +35,6 @@ Publish a patch release from the SignPath artifact-configuration pinning change
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Add the release fragment for the SignPath configuration pinning change.
|
||||
2. Bump `package.json` to `0.5.2` and run the changelog builder.
|
||||
3. Run changelog/typecheck/test verification.
|
||||
@@ -48,19 +44,15 @@ Publish a patch release from the SignPath artifact-configuration pinning change
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Bumped `package.json` from `0.5.1` to `0.5.2`, ran `bun run changelog:build`, and committed the generated release artifacts. That prepended the `v0.5.2` section to `CHANGELOG.md`, regenerated `release/release-notes.md`, and removed the consumed `changes/signpath-artifact-config-pin.md` fragment.
|
||||
|
||||
Verification before tagging: `bun run changelog:lint`, `bun run changelog:check --version 0.5.2`, `bun run typecheck`, and `bun run test:fast`.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Prepared patch release `v0.5.2` so the explicit SignPath artifact-configuration pin ships on a fresh release tag. Version metadata, committed changelog artifacts, and release notes are aligned with the new patch version.
|
||||
|
||||
Validation: `bun run changelog:lint`, `bun run changelog:check --version 0.5.2`, `bun run typecheck`, `bun run test:fast`.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-09 00:00'
|
||||
updated_date: '2026-03-09 00:00'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- release
|
||||
- windows
|
||||
@@ -15,20 +15,17 @@ references:
|
||||
- package.json
|
||||
- src/release-workflow.test.ts
|
||||
priority: high
|
||||
ordinal: 45500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Stop the tag-driven release workflow from depending on SignPath and publish unsigned Windows `.exe` and `.zip` artifacts directly. Add an explicit local `build:win:unsigned` script without changing the existing `build:win` command.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Windows release CI builds unsigned artifacts without requiring SignPath secrets.
|
||||
- [x] #2 The Windows release job uploads `release/*.exe` and `release/*.zip` directly as the `windows` artifact.
|
||||
- [x] #3 The repo exposes a local `build:win:unsigned` script for explicit unsigned Windows packaging.
|
||||
@@ -38,7 +35,6 @@ Stop the tag-driven release workflow from depending on SignPath and publish unsi
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Update workflow regression tests to assert unsigned Windows release behavior and the new local script.
|
||||
2. Patch `package.json` to add `build:win:unsigned`.
|
||||
3. Patch `.github/workflows/release.yml` to build unsigned Windows artifacts and upload them directly.
|
||||
@@ -48,19 +44,16 @@ Stop the tag-driven release workflow from depending on SignPath and publish unsi
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Removed the Windows SignPath secret validation and submission steps from `.github/workflows/release.yml`. The Windows release job now runs `bun run build:win:unsigned` and uploads `release/*.exe` and `release/*.zip` directly as the `windows` artifact consumed by the release job.
|
||||
|
||||
Added `scripts/build-win-unsigned.mjs` plus the `build:win:unsigned` package script. The wrapper clears Windows code-signing environment variables and disables identity auto-discovery before invoking `electron-builder`, so release CI stays unsigned even if signing credentials are configured elsewhere.
|
||||
|
||||
Updated `src/release-workflow.test.ts` to assert the unsigned workflow contract and added the release changelog fragment in `changes/unsigned-windows-release-builds.md`.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Windows release CI now publishes unsigned artifacts directly and no longer depends on SignPath. Local developers also have an explicit `bun run build:win:unsigned` path for unsigned packaging without changing the existing `build:win` command.
|
||||
|
||||
Verification:
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-09 00:00'
|
||||
updated_date: '2026-03-09 00:00'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- release
|
||||
- patch
|
||||
@@ -16,20 +16,17 @@ references:
|
||||
- CHANGELOG.md
|
||||
- release/release-notes.md
|
||||
priority: high
|
||||
ordinal: 46500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Publish a patch release from the unsigned Windows release-build change by bumping the app version, generating committed changelog artifacts for `v0.5.3`, and pushing the release-prep commit.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Repository version metadata is updated to `0.5.3`.
|
||||
- [x] #2 `CHANGELOG.md` and `release/release-notes.md` contain the committed `v0.5.3` section and consumed fragments are removed.
|
||||
- [x] #3 New `v0.5.3` release-prep commit is pushed to `origin/main`.
|
||||
@@ -38,7 +35,6 @@ Publish a patch release from the unsigned Windows release-build change by bumpin
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Bump `package.json` from `0.5.2` to `0.5.3`.
|
||||
2. Run `bun run changelog:build` so committed changelog artifacts match the new patch version.
|
||||
3. Run changelog/typecheck/test verification.
|
||||
@@ -48,19 +44,15 @@ Publish a patch release from the unsigned Windows release-build change by bumpin
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Bumped `package.json` from `0.5.2` to `0.5.3`, ran `bun run changelog:build`, and committed the generated release artifacts. That prepended the `v0.5.3` section to `CHANGELOG.md`, regenerated `release/release-notes.md`, and removed the consumed `changes/unsigned-windows-release-builds.md` fragment.
|
||||
|
||||
Verification before push: `bun run changelog:lint`, `bun run changelog:check --version 0.5.3`, `bun run typecheck`, and `bun run test:fast`.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Prepared patch release `v0.5.3` so the unsigned Windows release-build change is captured in committed release metadata on `main`. Version metadata, changelog output, and release notes are aligned with the new patch version.
|
||||
|
||||
Validation: `bun run changelog:lint`, `bun run changelog:check --version 0.5.3`, `bun run typecheck`, `bun run test:fast`.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -4,7 +4,7 @@ title: Fix guessit title parsing for character dictionary sync
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-09 00:00'
|
||||
updated_date: '2026-03-09 00:25'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- dictionary
|
||||
- anilist
|
||||
@@ -12,23 +12,22 @@ labels:
|
||||
- guessit
|
||||
dependencies: []
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/core/services/anilist/anilist-updater.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/core/services/anilist/anilist-updater.test.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/core/services/anilist/anilist-updater.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/core/services/anilist/anilist-updater.test.ts
|
||||
priority: high
|
||||
ordinal: 44500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Fix AniList character dictionary auto-sync for filenames where `guessit` misparses the full path and our title extraction keeps only the first array segment, causing AniList resolution to match the wrong anime and abort merged dictionary refresh.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 AniList media guessing passes basename-only targets to `guessit` so parent folder names do not corrupt series title detection.
|
||||
- [x] #2 Guessit title arrays are combined into one usable title instead of truncating to the first segment.
|
||||
- [x] #3 Regression coverage includes the Bunny Girl Senpai filename shape that previously resolved to the wrong AniList entry.
|
||||
@@ -38,7 +37,5 @@ Fix AniList character dictionary auto-sync for filenames where `guessit` mispars
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Root repro: `guessit` parsed the Bunny Girl Senpai full path as `title: ["Rascal", "Does-not-Dream-of-Bunny-Girl-Senapi"]`, and our `firstString` helper kept only `Rascal`, which resolved to AniList 3490 (`rayca`) and produced zero character results. Fixed by sending basename-only input to `guessit` and joining multi-part guessit title arrays.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
@@ -4,30 +4,28 @@ title: Refresh current subtitle after character dictionary sync completes
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-09 00:00'
|
||||
updated_date: '2026-03-09 00:55'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- dictionary
|
||||
- overlay
|
||||
- bug
|
||||
dependencies: []
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main.ts
|
||||
priority: high
|
||||
ordinal: 42500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
When character dictionary auto-sync finishes after startup tokenization, invalidate cached subtitle tokenization and refresh the current subtitle so character-name highlighting catches up without waiting for the next subtitle line.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Successful character dictionary sync exposes a completion hook for main runtime follow-up.
|
||||
- [x] #2 Main runtime clears Yomitan parser caches and refreshes the current subtitle after sync completion.
|
||||
- [x] #3 Regression coverage verifies the sync completion callback fires on successful sync.
|
||||
@@ -36,7 +34,5 @@ When character dictionary auto-sync finishes after startup tokenization, invalid
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Observed on Bunny Girl Senpai startup: autoplay/tokenization became ready around 8s, but snapshot/import/state write completed roughly 31s after launch, leaving the current subtitle tokenized without the newly imported character dictionary. Fixed by adding an auto-sync completion hook that clears parser caches and refreshes the current subtitle.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
@@ -4,31 +4,30 @@ title: Show character dictionary auto-sync progress on OSD
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-09 01:10'
|
||||
updated_date: '2026-03-09 01:10'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- dictionary
|
||||
- overlay
|
||||
- ux
|
||||
dependencies: []
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync-notifications.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync-notifications.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main.ts
|
||||
priority: medium
|
||||
ordinal: 41500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
When character dictionary auto-sync runs for a newly opened anime, surface progress so users know why character-name lookup/highlighting is temporarily unavailable via the mpv OSD without desktop notification popups.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Character dictionary auto-sync emits progress events for syncing, importing, ready, and failure states.
|
||||
- [x] #2 Main runtime routes those progress events through OSD notifications without desktop notifications.
|
||||
- [x] #3 Regression coverage verifies progress events and notification routing behavior.
|
||||
@@ -37,7 +36,5 @@ When character dictionary auto-sync runs for a newly opened anime, surface progr
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
OSD now shows auto-sync phase changes while the dictionary updates. Desktop notifications were removed for this path to avoid startup popup spam.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
@@ -1,10 +1,11 @@
|
||||
---
|
||||
id: TASK-143
|
||||
title: Keep character dictionary auto-sync non-blocking during startup
|
||||
status: Done
|
||||
assignee: []
|
||||
status: In Progress
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-09 01:45'
|
||||
updated_date: '2026-03-09 01:45'
|
||||
updated_date: '2026-03-20 09:22'
|
||||
labels:
|
||||
- dictionary
|
||||
- startup
|
||||
@@ -12,32 +13,41 @@ labels:
|
||||
dependencies: []
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/current-media-tokenization-gate.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/main/runtime/current-media-tokenization-gate.ts
|
||||
priority: high
|
||||
ordinal: 38500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Keep character dictionary auto-sync running in parallel during startup without delaying playback. Only tokenization readiness should gate playback; character dictionary import/settings updates should wait until tokenization is already ready and then refresh annotations afterward.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Character dictionary snapshot/build work can run immediately during startup.
|
||||
- [x] #2 Yomitan dictionary mutation work waits until current-media tokenization is ready.
|
||||
- [x] #3 Regression coverage verifies auto-sync builds before the gate and only mutates Yomitan after the gate resolves.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add a regression test for startup autoplay release surviving delayed mpv readiness or late subtitle refresh after dictionary sync.
|
||||
2. Harden the autoplay-ready release path so paused startup keeps retrying until mpv is actually released or media changes, without resuming user-paused playback later.
|
||||
3. Keep the existing character-dictionary revisit fixes and paused-startup OSD fixes aligned with the autoplay change, then run targeted runtime tests and typecheck.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Added a small current-media tokenization gate in main runtime. Media changes reset the gate, the first tokenization-ready event marks it ready, and auto-sync now waits on that gate only before Yomitan dictionary inspection/import/settings updates. Snapshot generation and merged ZIP build still run immediately in parallel.
|
||||
|
||||
2026-03-20: User reports startup remains paused after annotations/tokenization are visible and only resumes after character-dictionary generation/import finishes. Investigating autoplay-ready release regression vs dictionary sync completion refresh.
|
||||
|
||||
2026-03-20: Added startup autoplay retry-budget helper so paused startup retries cover the full plugin gate window instead of only ~2.8s. Verification: bun test src/main/runtime/startup-autoplay-release-policy.test.ts src/main/runtime/character-dictionary-auto-sync.test.ts src/main/runtime/startup-osd-sequencer.test.ts src/main/runtime/character-dictionary-auto-sync-completion.test.ts; bun run typecheck; bun run test:fast; bun run test:env; bun run build; bun run test:smoke:dist; runtime-compat verifier passed at .tmp/skill-verification/subminer-verify-20260320-022106-nM28Nk. Pending real installed-app/mpv validation.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
---
|
||||
id: TASK-144
|
||||
title: Sequence startup OSD notifications for tokenization, annotations, and character dictionary sync
|
||||
title: >-
|
||||
Sequence startup OSD notifications for tokenization, annotations, and
|
||||
character dictionary sync
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-09 10:40'
|
||||
updated_date: '2026-03-09 10:40'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- startup
|
||||
- overlay
|
||||
@@ -12,24 +14,24 @@ labels:
|
||||
dependencies: []
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/startup-osd-sequencer.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/subtitle-tokenization-main-deps.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync-notifications.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/main/runtime/startup-osd-sequencer.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/main/runtime/subtitle-tokenization-main-deps.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync-notifications.ts
|
||||
priority: medium
|
||||
ordinal: 37500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Keep startup OSD progress ordered. While tokenization is still pending, only show the tokenization loading message. After tokenization becomes ready, show annotation loading if annotation warmup still remains. Only surface character dictionary auto-sync progress after annotation loading clears, and only if the dictionary work is still active.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Character dictionary progress stays hidden while tokenization startup loading is still active.
|
||||
- [x] #2 Annotation loading OSD appears after tokenization readiness and before any later character dictionary progress.
|
||||
- [x] #3 Regression coverage verifies buffered dictionary progress/failure ordering during startup.
|
||||
@@ -38,7 +40,5 @@ Keep startup OSD progress ordered. While tokenization is still pending, only sho
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Added a small startup OSD sequencer in main runtime. Annotation warmup OSD now flows through that sequencer, and character dictionary sync notifications buffer until tokenization plus annotation loading clear. Buffered `ready` updates are dropped if dictionary progress finished before it ever became visible, while buffered failures still surface after annotation loading completes.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
---
|
||||
id: TASK-145
|
||||
title: Show character dictionary build progress on startup OSD before import
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-09 11:20'
|
||||
updated_date: '2026-03-09 11:20'
|
||||
labels:
|
||||
- startup
|
||||
- dictionary
|
||||
- ux
|
||||
dependencies: []
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/startup-osd-sequencer.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync.test.ts
|
||||
priority: medium
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Surface an explicit character-dictionary build phase on startup OSD so there is visible progress between subtitle annotation loading and the later import/upload step when merged dictionary generation is still running.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Auto-sync emits a dedicated in-flight status while merged dictionary generation is running.
|
||||
- [x] #2 Startup OSD sequencing treats that build phase as progress and can surface it after annotation loading clears.
|
||||
- [x] #3 Regression coverage verifies the build phase is emitted before import begins.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Added a `building` progress phase before `buildMergedDictionary(...)` and included it in the startup OSD sequencer's buffered progress set. This gives startup a visible dictionary-progress step even when snapshot checking/generation finished too early to still be relevant by the time annotation loading completes.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
@@ -4,7 +4,7 @@ title: Show checking and generation OSD for character dictionary auto-sync
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-09 11:20'
|
||||
updated_date: '2026-03-09 11:20'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- dictionary
|
||||
- overlay
|
||||
@@ -12,24 +12,24 @@ labels:
|
||||
dependencies: []
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/runtime/startup-osd-sequencer.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/main/character-dictionary-runtime.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/main/runtime/startup-osd-sequencer.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/main/character-dictionary-runtime.ts
|
||||
priority: medium
|
||||
ordinal: 35500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Surface an immediate startup OSD that the character dictionary is being checked, and show a distinct generating message only when the current AniList media actually needs a fresh snapshot build instead of reusing a cached one.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Auto-sync emits a `checking` progress event before snapshot resolution completes.
|
||||
- [x] #2 Auto-sync emits `generating` only for snapshot cache misses and keeps `updating`/`importing` as later phases.
|
||||
- [x] #3 Startup OSD sequencing still prioritizes tokenization then annotation loading before buffered dictionary progress.
|
||||
@@ -38,9 +38,7 @@ Surface an immediate startup OSD that the character dictionary is being checked,
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Character dictionary auto-sync now emits `Checking character dictionary...` as soon as the AniList media is resolved, then emits `Generating character dictionary...` only when the snapshot layer misses and a real rebuild begins. Cached snapshots skip the generating phase and continue straight into the later update/import flow.
|
||||
|
||||
Wired those progress callbacks through the character-dictionary runtime boundary, updated the startup OSD sequencer to treat checking/generating as dictionary-progress phases with the same tokenization and annotation precedence, and added regression coverage for cache-hit vs cache-miss behavior plus buffered startup ordering.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,27 +5,24 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-09 00:00'
|
||||
updated_date: '2026-03-09 00:00'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- bug
|
||||
- overlay
|
||||
- aniskip
|
||||
- linux
|
||||
dependencies: []
|
||||
ordinal: 47500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Fix visible-overlay keyboard handling so bare `Tab` is forwarded to mpv instead of being consumed by Electron focus navigation. This restores the default AniSkip `TAB` binding while the overlay has focus, especially on Linux.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Visible overlay forwards bare `Tab` to mpv as `keypress TAB`.
|
||||
- [x] #2 Modal overlays keep their existing local `Tab` behavior.
|
||||
- [x] #3 Automated regression coverage exists for the input handler and overlay factory wiring.
|
||||
@@ -34,7 +31,6 @@ Fix visible-overlay keyboard handling so bare `Tab` is forwarded to mpv instead
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Add a failing regression around visible-overlay `before-input-event` handling for bare `Tab`.
|
||||
2. Add/extend overlay factory tests so the new mpv-forward callback is wired through runtime construction.
|
||||
3. Patch overlay input handling to intercept visible-overlay `Tab` and send mpv `keypress TAB`.
|
||||
@@ -44,7 +40,6 @@ Fix visible-overlay keyboard handling so bare `Tab` is forwarded to mpv instead
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Extracted visible-overlay input handling into `src/core/services/overlay-window-input.ts` so the `Tab` forwarding decision can be unit tested without loading Electron window primitives.
|
||||
|
||||
Visible overlay `before-input-event` now intercepts bare `Tab`, prevents the browser default, and forwards mpv `keypress TAB` through the existing mpv runtime command path. Modal overlays remain unchanged.
|
||||
@@ -58,9 +53,7 @@ Verification:
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Visible overlay focus no longer blocks the default AniSkip `Tab` binding. Bare `Tab` is now forwarded straight to mpv while the visible overlay is active, and modal overlays still retain their own normal focus behavior.
|
||||
|
||||
Added regression coverage for both the input-routing decision and the runtime plumbing that carries the new mpv forwarder into overlay window creation.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,41 +5,35 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-09 00:00'
|
||||
updated_date: '2026-03-09 00:00'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- windows
|
||||
- plugin
|
||||
- regression
|
||||
dependencies: []
|
||||
priority: medium
|
||||
ordinal: 48500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Fix the mpv plugin's Windows binary override lookup so `SUBMINER_BINARY_PATH` still resolves when `SUBMINER_APPIMAGE_PATH` is unset. The current Lua resolver builds an array with a leading `nil`, which causes `ipairs` iteration to stop before the later Windows override candidate.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 `scripts/test-plugin-binary-windows.lua` passes the env override regression that expects `.exe` suffix resolution from `SUBMINER_BINARY_PATH`.
|
||||
- [x] #2 Existing plugin start/binary test gate stays green after the fix.
|
||||
|
||||
<!-- AC:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Updated `plugin/subminer/binary.lua` so env override lookup checks `SUBMINER_APPIMAGE_PATH` and `SUBMINER_BINARY_PATH` sequentially instead of via a Lua array literal that truncates at the first `nil`. This restores Windows `.exe` suffix resolution for `SUBMINER_BINARY_PATH` when the AppImage env var is unset.
|
||||
|
||||
Verification:
|
||||
|
||||
- `lua scripts/test-plugin-binary-windows.lua`
|
||||
- `bun run test:plugin:src`
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-09 01:10'
|
||||
updated_date: '2026-03-09 01:14'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- release
|
||||
- patch
|
||||
@@ -25,20 +25,17 @@ references:
|
||||
- scripts/build-changelog.test.ts
|
||||
- docs/RELEASING.md
|
||||
priority: high
|
||||
ordinal: 39500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Prepare and publish patch release `v0.5.5` after the failed `v0.5.4` tag by aligning package version metadata, generating committed changelog output from the pending release fragments, and hardening release validation so a future tag cannot ship with a mismatched `package.json` version.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Repository version metadata is updated to `0.5.5`.
|
||||
- [x] #2 `CHANGELOG.md` contains the committed `v0.5.5` section and the consumed fragments are removed.
|
||||
- [x] #3 Release validation rejects a requested release version when it differs from `package.json`.
|
||||
@@ -49,7 +46,6 @@ Prepare and publish patch release `v0.5.5` after the failed `v0.5.4` tag by alig
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Add a regression test for tagged-release/package version mismatch.
|
||||
2. Update changelog validation to reject mismatched explicit release versions.
|
||||
3. Bump `package.json`, generate committed `v0.5.5` changelog output, and remove consumed fragments.
|
||||
@@ -60,21 +56,17 @@ Prepare and publish patch release `v0.5.5` after the failed `v0.5.4` tag by alig
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Added a regression test in `scripts/build-changelog.test.ts` that proves `changelog:check --version ...` rejects tag/package mismatches. Updated `scripts/build-changelog.ts` so tagged release validation now compares the explicit requested version against `package.json` before looking for pending fragments or the committed changelog section.
|
||||
|
||||
Bumped `package.json` from `0.5.3` to `0.5.5`, ran `bun run changelog:build --version 0.5.5 --date 2026-03-09`, and committed the generated `CHANGELOG.md` output while removing the consumed task fragments. Added `docs/RELEASING.md` with the required release-prep checklist so version bump + changelog generation happen before tagging.
|
||||
|
||||
Verification: `bun run changelog:lint`, `bun run changelog:check --version 0.5.5`, `bun run typecheck`, `bun run test:fast`, and `bun test scripts/build-changelog.test.ts src/release-workflow.test.ts`. `bun run format:check` still reports many unrelated pre-existing repo-wide Prettier warnings, so touched files were checked/formatted separately with `bunx prettier`.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Prepared patch release `v0.5.5` after the failed `v0.5.4` release attempt. Release metadata now matches the upcoming tag, the pending character-dictionary/overlay/plugin fragments are committed into `CHANGELOG.md`, and release validation now blocks future tag/package mismatches before publish.
|
||||
|
||||
Docs now include a short release checklist in `docs/RELEASING.md`. Validation passed for changelog lint/check, typecheck, targeted workflow tests, and the full fast test suite. Repo-wide Prettier remains noisy from unrelated existing files, but touched release files were formatted and verified.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-09 01:11'
|
||||
updated_date: '2026-03-09 01:11'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- tooling
|
||||
- formatting
|
||||
@@ -20,20 +20,17 @@ references:
|
||||
- scripts/build-win-unsigned.mjs
|
||||
- src
|
||||
priority: medium
|
||||
ordinal: 40500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Bring `bun run format:check` back to green after the `v0.5.5` release-prep work exposed repo-wide Prettier drift across backlog markdown, config files, and maintained TypeScript sources.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 `bun run format:check` passes.
|
||||
- [x] #2 `bun run changelog:lint` still passes.
|
||||
- [x] #3 Typecheck and fast tests stay green after the formatting-only rewrite.
|
||||
@@ -42,7 +39,6 @@ Bring `bun run format:check` back to green after the `v0.5.5` release-prep work
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
|
||||
1. Re-run format and lint checks to confirm failing files.
|
||||
2. Apply Prettier to the warned repo-managed files.
|
||||
3. Re-run formatting, lint, typecheck, and fast tests.
|
||||
@@ -52,17 +48,13 @@ Bring `bun run format:check` back to green after the `v0.5.5` release-prep work
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Ran `bunx prettier --write` across the repo-managed files reported by `bun run format:check`, covering backlog markdown/YAML, `config.example.jsonc`, selected launcher/scripts files, and maintained TypeScript sources under `src/`.
|
||||
|
||||
Verification: `bun run format:check`, `bun run changelog:lint`, `bun run typecheck`, and `bun run test:fast`.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Repo-wide Prettier drift is cleaned up, including backlog task markdown, config/example files, and the maintained code files that `format:check` was flagging. Formatting and lint checks are green again, and typecheck/fast tests stayed green after the formatting-only rewrite.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- OpenCode
|
||||
created_date: '2026-03-10 06:42'
|
||||
updated_date: '2026-03-10 07:54'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels: []
|
||||
dependencies: []
|
||||
references:
|
||||
@@ -15,6 +15,7 @@ documentation:
|
||||
- ../subminer-docs/development.md
|
||||
- ../subminer-docs/architecture.md
|
||||
priority: medium
|
||||
ordinal: 33500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-10 06:46'
|
||||
updated_date: '2026-03-10 06:51'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- bug
|
||||
- config
|
||||
@@ -19,6 +19,7 @@ documentation:
|
||||
- /home/sudacode/projects/japanese/subminer-docs/development.md
|
||||
- /home/sudacode/projects/japanese/subminer-docs/architecture.md
|
||||
priority: high
|
||||
ordinal: 34500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- '@codex'
|
||||
created_date: '2026-03-10 07:56'
|
||||
updated_date: '2026-03-10 08:48'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- character-dictionary
|
||||
- yomitan
|
||||
@@ -22,6 +22,7 @@ documentation:
|
||||
- /home/sudacode/projects/japanese/subminer-docs/development.md
|
||||
- /home/sudacode/projects/japanese/subminer-docs/architecture.md
|
||||
priority: high
|
||||
ordinal: 32500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- '@codex'
|
||||
created_date: '2026-03-10 09:16'
|
||||
updated_date: '2026-03-10 09:22'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- character-dictionary
|
||||
- yomitan
|
||||
@@ -24,6 +24,7 @@ documentation:
|
||||
- /home/sudacode/projects/japanese/subminer-docs/development.md
|
||||
- /home/sudacode/projects/japanese/subminer-docs/architecture.md
|
||||
priority: high
|
||||
ordinal: 31500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
---
|
||||
id: TASK-155
|
||||
title: Move user docs site back into main repo
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-10 19:20'
|
||||
updated_date: '2026-03-10 19:38'
|
||||
labels: []
|
||||
dependencies: []
|
||||
priority: medium
|
||||
ordinal: 15500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Move the standalone VitePress docs site from the sibling `../subminer-docs` checkout back into the main `SubMiner` repo so docs can be updated alongside code and local tooling can reference one repository.
|
||||
|
||||
Scope:
|
||||
|
||||
- import the tracked docs-site source into a dedicated in-repo subdirectory
|
||||
- update scripts/tests/docs instructions that assume a sibling `../subminer-docs` checkout
|
||||
- preserve Cloudflare Pages deployability from a repo subdirectory
|
||||
- verify the app repo and docs site both still build/test from the new layout
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 The user-facing VitePress docs source lives inside the `SubMiner` repo in a dedicated subdirectory.
|
||||
- [x] #2 First-party scripts/tests/docs no longer require `../subminer-docs` for normal operation.
|
||||
- [x] #3 In-repo docs instructions include the Cloudflare Pages subdirectory deploy settings.
|
||||
- [x] #4 Verification covers the relocated docs site build/tests plus affected app-repo checks.
|
||||
|
||||
<!-- AC:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Imported the VitePress site into `docs-site/` inside the main repo and updated project instructions, docs contributor guidance, generator logic, and regression tests to treat that in-repo directory as the docs source of truth.
|
||||
|
||||
Added root proxy scripts for `docs:dev`, `docs:build`, `docs:preview`, and `docs:test`, repointed config-example generation to `docs-site/public/config.example.jsonc`, switched docs edit links to the main `SubMiner` repo, and documented the Cloudflare Pages subdirectory settings (`docs-site` root, `.vitepress/dist` output, `docs-site/**` watch path).
|
||||
|
||||
Verified with `bun run format:check:src`, `bun run typecheck`, `bun run docs:test`, `bun run docs:build`, `bun run test:config:src`, and `bun run test:fast`.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -1,15 +1,16 @@
|
||||
---
|
||||
id: TASK-156
|
||||
title: Fix docs-site Plausible geo attribution through analytics worker
|
||||
status: In Progress
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-11 02:19'
|
||||
updated_date: '2026-03-11 02:44'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- docs-site
|
||||
- analytics
|
||||
dependencies: []
|
||||
priority: medium
|
||||
ordinal: 99500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
---
|
||||
id: TASK-157
|
||||
title: Fix Cloudflare Pages watch path for docs-site
|
||||
status: In Progress
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-10 20:15'
|
||||
updated_date: '2026-03-10 20:15'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- docs-site
|
||||
- cloudflare
|
||||
dependencies: []
|
||||
priority: medium
|
||||
ordinal: 98500
|
||||
---
|
||||
|
||||
## Description
|
||||
@@ -20,9 +21,9 @@ Cloudflare Pages skipped a docs-site deployment after the docs repo moved into t
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [ ] #1 Docs contributor guidance points Cloudflare Pages watch paths at `docs-site/*`, not `docs-site/**`.
|
||||
- [ ] #2 Regression coverage fails if the docs revert to the incorrect watch-path string.
|
||||
- [ ] #3 Implementation notes record that the Cloudflare dashboard setting must be updated manually and the docs deploy retriggered.
|
||||
- [x] #1 Docs contributor guidance points Cloudflare Pages watch paths at `docs-site/*`, not `docs-site/**`.
|
||||
- [x] #2 Regression coverage fails if the docs revert to the incorrect watch-path string.
|
||||
- [x] #3 Implementation notes record that the Cloudflare dashboard setting must be updated manually and the docs deploy retriggered.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
@@ -4,12 +4,13 @@ title: Enforce generated config example drift checks
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-10 20:35'
|
||||
updated_date: '2026-03-10 20:35'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- config
|
||||
- docs-site
|
||||
dependencies: []
|
||||
priority: medium
|
||||
ordinal: 30500
|
||||
---
|
||||
|
||||
## Description
|
||||
@@ -26,7 +27,6 @@ Scope:
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Automated verification fails when repo-root `config.example.jsonc` is missing or stale.
|
||||
- [x] #2 Automated verification fails when in-repo docs-site `public/config.example.jsonc` is missing or stale, when docs-site exists.
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
---
|
||||
id: TASK-159
|
||||
title: Add overlay controller support for keyboard-only mode
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-11 00:30'
|
||||
updated_date: '2026-03-11 04:05'
|
||||
labels:
|
||||
- enhancement
|
||||
- renderer
|
||||
- overlay
|
||||
- input
|
||||
dependencies:
|
||||
- TASK-86
|
||||
references:
|
||||
- src/renderer/handlers/keyboard.ts
|
||||
- src/renderer/renderer.ts
|
||||
- src/renderer/state.ts
|
||||
- src/renderer/index.html
|
||||
- src/renderer/style.css
|
||||
- src/preload.ts
|
||||
- src/types.ts
|
||||
- src/config/definitions/defaults-core.ts
|
||||
- src/config/definitions/options-core.ts
|
||||
- src/config/definitions/template-sections.ts
|
||||
- config.example.jsonc
|
||||
priority: medium
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Add Chrome Gamepad API support to the visible overlay as a supplement to keyboard-only mode. By default SubMiner should bind to the first available controller, allow the user to pick and persist a preferred controller, expose a raw-input debug modal, and map controller actions onto the existing keyboard-only/Yomitan flow without breaking keyboard input. Also fix the current keyboard-only cleanup bug so the selected-token highlight clears when keyboard-only mode turns off or when the Yomitan popup closes.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Controller input is ignored unless keyboard-only mode is enabled, except the controller binding for toggling keyboard-only mode itself.
|
||||
- [x] #2 Default logical mappings work: smooth popup scroll, token selection, lookup toggle/close, mining, Yomitan audio navigation/play, and mpv play/pause.
|
||||
- [x] #3 Controller config supports named logical bindings plus tuning knobs (preferred controller, deadzones, smooth-scroll speed/repeat), not raw axis/button maps.
|
||||
- [x] #4 `Alt+C` opens a controller selection modal listing connected controllers; saving a choice persists the preferred controller for next launch.
|
||||
- [x] #5 `Alt+Shift+C` opens a debug modal showing live raw controller axes/buttons as seen by SubMiner.
|
||||
- [x] #6 Keyboard-only selection highlight clears immediately when keyboard-only mode is disabled or the Yomitan popup closes.
|
||||
- [x] #7 Renderer/config regression tests cover controller gating, mappings, modal behavior, persisted selection, and highlight cleanup.
|
||||
- [x] #8 Docs/config example describe the controller feature and new shortcuts.
|
||||
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- Added renderer-side gamepad polling and logical action mapping in `src/renderer/handlers/gamepad-controller.ts`.
|
||||
- Added controller select/debug modals, persisted preferred-controller IPC, and top-level `controller` config defaults/schema/template output.
|
||||
- Added a transient in-overlay controller status indicator when a controller is first detected.
|
||||
- Tuned controller defaults and routing after live testing: d-pad fallback navigation, slower repeat timing, DOM-backed popup-open detection, and direct pixel scroll/audio-source popup bridge commands.
|
||||
- Reused existing keyboard-only lookup/mining/navigation flows so controller input stays a supplement to keyboard-only mode instead of a parallel input path.
|
||||
- Verified keyboard-only highlight cleanup on mode-off and popup-close paths with renderer tests.
|
||||
|
||||
## Verification
|
||||
|
||||
- `bun test src/config/config.test.ts src/config/definitions/domain-registry.test.ts src/renderer/handlers/keyboard.test.ts src/renderer/handlers/gamepad-controller.test.ts src/renderer/modals/controller-select.test.ts src/renderer/modals/controller-debug.test.ts src/core/services/ipc.test.ts`
|
||||
- `bun test src/main/runtime/composers/ipc-runtime-composer.test.ts`
|
||||
- `bun run generate:config-example`
|
||||
- `bun run typecheck`
|
||||
- `bun run docs:test`
|
||||
- `bun run test:fast`
|
||||
- `bun run test:env`
|
||||
- `bun run build`
|
||||
- `bun run docs:build`
|
||||
- `bun run test:smoke:dist`
|
||||
@@ -5,13 +5,14 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-11 05:55'
|
||||
updated_date: '2026-03-11 06:13'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- tooling
|
||||
- testing
|
||||
- skills
|
||||
dependencies: []
|
||||
priority: medium
|
||||
ordinal: 29500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-11 06:32'
|
||||
updated_date: '2026-03-11 06:45'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- skills
|
||||
- workflow
|
||||
@@ -14,6 +14,7 @@ labels:
|
||||
- automation
|
||||
dependencies: []
|
||||
priority: high
|
||||
ordinal: 28500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-11 07:50'
|
||||
updated_date: '2026-03-11 07:56'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- packaging
|
||||
- linux
|
||||
@@ -20,6 +20,7 @@ documentation:
|
||||
- docs-site/installation.md
|
||||
- docs/RELEASING.md
|
||||
priority: medium
|
||||
ordinal: 27500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
id: TASK-162
|
||||
title: Normalize packaged Linux paths to canonical SubMiner directories
|
||||
status: In Progress
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-11 08:28'
|
||||
updated_date: '2026-03-11 08:29'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- linux
|
||||
- packaging
|
||||
@@ -20,6 +20,7 @@ references:
|
||||
- docs-site/launcher-script.md
|
||||
- README.md
|
||||
priority: medium
|
||||
ordinal: 116500
|
||||
---
|
||||
|
||||
## Description
|
||||
@@ -30,10 +31,10 @@ Align packaged Linux path conventions so system-installed assets use canonical `
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [ ] #1 Launcher/runtime path discovery prefers canonical packaged Linux locations that use `SubMiner` casing for shared data and config directories.
|
||||
- [ ] #2 Tests cover the expected packaged Linux discovery paths for the AppImage and rofi theme search behavior.
|
||||
- [ ] #3 User-facing docs reference the canonical packaged Linux locations consistently.
|
||||
- [ ] #4 Lowercase names remain only where intentionally required for the launcher wrapper, rofi theme filename, and mpv Lua plugin/conf.
|
||||
- [x] #1 Launcher/runtime path discovery prefers canonical packaged Linux locations that use `SubMiner` casing for shared data and config directories.
|
||||
- [x] #2 Tests cover the expected packaged Linux discovery paths for the AppImage and rofi theme search behavior.
|
||||
- [x] #3 User-facing docs reference the canonical packaged Linux locations consistently.
|
||||
- [x] #4 Lowercase names remain only where intentionally required for the launcher wrapper, rofi theme filename, and mpv Lua plugin/conf.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
@@ -44,4 +45,22 @@ Align packaged Linux path conventions so system-installed assets use canonical `
|
||||
3. Update plugin auto-detection comments and binary search defaults so packaged Linux paths stay consistent with launcher/runtime expectations.
|
||||
4. Update user-facing docs to reference canonical SubMiner-cased config/share paths while keeping lowercase names only for the launcher wrapper, rofi theme filename, and mpv Lua plugin/conf.
|
||||
5. Run targeted launcher tests plus docs checks.
|
||||
|
||||
Remaining work (2026-03-15):
|
||||
- binary.lua: add lowercase fallback candidates /usr/bin/subminer and /usr/local/bin/subminer after existing title-case entries
|
||||
- launcher tests: add findAppBinary Linux candidates and findRofiTheme /usr/share + /usr/local/share tests
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
2026-03-15: Adding launcher tests for Linux packaged path discovery (findAppBinary + findRofiTheme). Implementing in mpv.test.ts and new picker.test.ts following node:test / assert/strict patterns from mpv.test.ts.
|
||||
|
||||
2026-03-15: AC#2 complete. Added findAppBinary tests (3) to launcher/mpv.test.ts and findRofiTheme tests (4) to new launcher/picker.test.ts. All 76 launcher tests pass. Added picker.test.ts to test:launcher:src script.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
## Completed changes\n\n### `plugin/subminer/binary.lua`\nAdded lowercase fallback candidates after existing title-case entries in the non-Windows `find_binary()` search list:\n- `/usr/local/bin/subminer` (after `/usr/local/bin/SubMiner`)\n- `/usr/bin/subminer` (after `/usr/bin/SubMiner`)\n\n### `plugin/subminer.conf`\nUpdated the comment documenting the Linux binary search list to include the two new lowercase candidates.\n\n### `launcher/mpv.test.ts`\nAdded 3 new tests for `findAppBinary` Linux candidates:\n- Resolves `~/.local/bin/SubMiner.AppImage` when it exists\n- Resolves `/opt/SubMiner/SubMiner.AppImage` when `~/.local/bin` candidate absent\n- Finds `subminer` on PATH when AppImage candidates absent\n\n### `launcher/picker.test.ts` (new file)\nAdded 4 tests for `findRofiTheme` Linux packaged paths:\n- Resolves `/usr/local/share/SubMiner/themes/subminer.rasi`\n- Resolves `/usr/share/SubMiner/themes/subminer.rasi` when `/usr/local/share` absent\n- Resolves `$XDG_DATA_HOME/SubMiner/themes/subminer.rasi` when set\n- Resolves `~/.local/share/SubMiner/themes/subminer.rasi` when `XDG_DATA_HOME` unset\n\n### `package.json`\nAdded `launcher/picker.test.ts` to `test:launcher:src` file list.\n\n## Verification\n- `launcher-plugin` lane: passed (76 launcher tests, 524 fast tests — all green)\n\n## Policy checks\n- Docs update required? No — docs already reflected canonical paths.\n- Changelog fragment required? Yes — user-visible fix to plugin binary auto-detection. Fragment should be added under `changes/`.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- Codex
|
||||
created_date: '2026-03-11 08:48'
|
||||
updated_date: '2026-03-11 08:49'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- maintenance
|
||||
- tooling
|
||||
@@ -14,6 +14,7 @@ references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/package.json
|
||||
- /home/sudacode/projects/japanese/SubMiner/docs-site/development.md
|
||||
- /home/sudacode/projects/japanese/SubMiner/docs-site/architecture.md
|
||||
ordinal: 26500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- Codex
|
||||
created_date: '2026-03-11 08:52'
|
||||
updated_date: '2026-03-11 08:54'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- maintenance
|
||||
- testing
|
||||
@@ -14,6 +14,7 @@ references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/package.json
|
||||
- /home/sudacode/projects/japanese/SubMiner/docs-site/development.md
|
||||
- /home/sudacode/projects/japanese/SubMiner/docs-site/architecture.md
|
||||
ordinal: 25500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
---
|
||||
id: TASK-165
|
||||
title: Automate AUR publish on tagged releases
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-14 15:55'
|
||||
updated_date: '2026-03-14 18:40'
|
||||
labels:
|
||||
- release
|
||||
- packaging
|
||||
- linux
|
||||
dependencies:
|
||||
- TASK-161
|
||||
references:
|
||||
- .github/workflows/release.yml
|
||||
- src/release-workflow.test.ts
|
||||
- docs/RELEASING.md
|
||||
- packaging/aur/subminer-bin/PKGBUILD
|
||||
documentation:
|
||||
- docs/plans/2026-03-14-aur-release-sync-design.md
|
||||
- docs/plans/2026-03-14-aur-release-sync.md
|
||||
priority: medium
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Extend the tagged release workflow so a successful GitHub release automatically updates the `subminer-bin` AUR package over SSH. Keep the PKGBUILD source-of-truth in this repo so release automation is reviewable and testable instead of depending on an external maintainer checkout.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Repo-tracked AUR packaging source exists for `subminer-bin` and matches the current release artifact layout.
|
||||
- [x] #2 The release workflow clones `ssh://aur@aur.archlinux.org/subminer-bin.git` with a dedicated secret-backed SSH key only after release artifacts are ready.
|
||||
- [x] #3 The workflow updates `pkgver`, regenerates `sha256sums` from the built release artifacts, regenerates `.SRCINFO`, and pushes only when packaging files changed.
|
||||
- [x] #4 Regression coverage fails if the AUR publish job, secret contract, or update steps are removed from the release workflow.
|
||||
- [x] #5 Release docs mention the required `AUR_SSH_PRIVATE_KEY` setup and the new tagged-release side effect.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Record the approved design and implementation plan for direct AUR publishing from the release workflow.
|
||||
2. Add failing release workflow regression tests covering the new AUR publish job, SSH secret, and PKGBUILD/.SRCINFO regeneration steps.
|
||||
3. Reintroduce repo-tracked `packaging/aur/subminer-bin` source files as the maintained AUR template.
|
||||
4. Add a small helper script that updates `pkgver`, computes checksums from release artifacts, and regenerates `.SRCINFO` deterministically.
|
||||
5. Extend `.github/workflows/release.yml` with an AUR publish job that clones the AUR repo over SSH, runs the helper, commits only when needed, and pushes to `aur`.
|
||||
6. Update release docs for the new secret/setup requirements and tagged-release behavior.
|
||||
7. Run targeted workflow tests plus the SubMiner verification lane needed for workflow/docs changes, then update this task with results.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Added repo-tracked AUR packaging source under `packaging/aur/subminer-bin/` plus `scripts/update-aur-package.sh` to stamp `pkgver`, compute SHA-256 sums from release assets, and regenerate `.SRCINFO` with `makepkg --printsrcinfo`.
|
||||
|
||||
Extended `.github/workflows/release.yml` with a terminal `aur-publish` job that runs after `release`, validates `AUR_SSH_PRIVATE_KEY`, installs `makepkg`, configures SSH/known_hosts, clones `ssh://aur@aur.archlinux.org/subminer-bin.git`, downloads the just-published `SubMiner-<version>.AppImage`, `subminer`, and `subminer-assets.tar.gz` assets, updates packaging metadata, and pushes only when `PKGBUILD` or `.SRCINFO` changed.
|
||||
|
||||
Updated `src/release-workflow.test.ts` with regression assertions for the AUR publish contract and updated `docs/RELEASING.md` with the new secret/setup requirement.
|
||||
|
||||
Verification run:
|
||||
- `bun test src/release-workflow.test.ts src/ci-workflow.test.ts`
|
||||
- `bash -n scripts/update-aur-package.sh && bash -n packaging/aur/subminer-bin/PKGBUILD`
|
||||
- `cd packaging/aur/subminer-bin && makepkg --printsrcinfo > .SRCINFO`
|
||||
- updater smoke via temp package dir with fake assets and `v9.9.9`
|
||||
- `bun run typecheck`
|
||||
- `bun run test:fast`
|
||||
- `bun run test:env`
|
||||
- `git submodule update --init --recursive` (required because the worktree lacked release submodules)
|
||||
- `bun run build`
|
||||
- `bun run test:smoke:dist`
|
||||
|
||||
Docs update required: yes, completed in `docs/RELEASING.md`.
|
||||
Changelog fragment required: no; internal release automation only.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Tagged releases now attempt a direct AUR sync for `subminer-bin` using a dedicated SSH private key stored in `AUR_SSH_PRIVATE_KEY`. The release workflow clones the AUR repo after GitHub Release publication, rewrites `PKGBUILD` and `.SRCINFO` from the published release assets, and skips empty pushes. Repo-owned packaging source and workflow regression coverage were added so the automation remains reviewable and testable.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
id: TASK-165
|
||||
title: Rewrite SubMiner agentic testing automation plan
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-13 04:45'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- planning
|
||||
- testing
|
||||
- agents
|
||||
dependencies: []
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/testing-plan.md
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/.agents/skills/subminer-change-verification/SKILL.md
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/.agents/skills/subminer-scrum-master/SKILL.md
|
||||
documentation:
|
||||
- /home/sudacode/projects/japanese/SubMiner/docs-site/development.md
|
||||
- /home/sudacode/projects/japanese/SubMiner/docs-site/architecture.md
|
||||
ordinal: 23500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Replace the current generic Electron/mpv testing plan with a SubMiner-specific plan that uses the existing skills as the source of truth, treats real launcher/plugin/mpv runtime verification as primary, and defines a non-interference contract for parallel agent work.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 `testing-plan.md` is rewritten for SubMiner rather than a generic Electron+mpv app
|
||||
- [x] #2 The plan keeps `subminer-scrum-master` and `subminer-change-verification` as the primary orchestration and verification entrypoints
|
||||
- [x] #3 The plan defines real launcher/plugin/mpv runtime verification as the authoritative lane for runtime bug claims
|
||||
- [x] #4 The plan defines explicit session isolation and non-interference rules for parallel agent work
|
||||
- [x] #5 The plan defines artifact/reporting expectations and phased rollout, with synthetic/headless verification clearly secondary to real-runtime verification
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Review the existing testing plan and compare it against current SubMiner architecture, verification lanes, and skills.
|
||||
2. Replace the generic Electron/mpv harness framing with a SubMiner-specific control plane centered on existing skills.
|
||||
3. Define the authoritative real-runtime lane, session isolation rules, concurrency classes, and reporting contract.
|
||||
4. Sanity-check the rewritten document against current repo docs and skill contracts before handoff.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Rewrote `testing-plan.md` around existing `subminer-scrum-master` and `subminer-change-verification` responsibilities instead of proposing a competing new top-level testing skill.
|
||||
|
||||
Set real launcher/plugin/mpv/runtime verification as the authoritative lane for runtime bug claims and made synthetic/headless verification explicitly secondary.
|
||||
|
||||
Defined session-scoped paths, unique mutable resources, concurrency classes, and an exclusive lease for conflicting real-runtime verification to prevent parallel interference.
|
||||
|
||||
Sanity-checked the final document by inspecting the rewritten file content and diff.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Rewrote `testing-plan.md` into a SubMiner-specific agentic verification plan. The new document keeps `subminer-scrum-master` and `subminer-change-verification` as the primary orchestration and verification entrypoints, treats the real launcher/plugin/mpv/runtime path as authoritative for runtime bug claims, and defines a hard non-interference contract for parallel work through session isolation and an exclusive real-runtime lease. The plan now also includes an explicit reporting schema, capture policy, phased rollout, and a clear statement that true parallel full-app instances are not a phase-1 requirement. Verification for this task was a document sanity pass against the current repo docs, skills, and the resulting file diff.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -5,7 +5,7 @@ status: Done
|
||||
assignee:
|
||||
- Codex
|
||||
created_date: '2026-03-17 18:10'
|
||||
updated_date: '2026-03-17 18:14'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- release
|
||||
- packaging
|
||||
@@ -16,9 +16,12 @@ references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/.github/workflows/release.yml
|
||||
- /home/sudacode/projects/japanese/SubMiner/scripts/update-aur-package.sh
|
||||
- /home/sudacode/projects/japanese/SubMiner/scripts/update-aur-package.test.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/packaging/aur/subminer-bin/PKGBUILD
|
||||
- /home/sudacode/projects/japanese/SubMiner/packaging/aur/subminer-bin/.SRCINFO
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/packaging/aur/subminer-bin/PKGBUILD
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/packaging/aur/subminer-bin/.SRCINFO
|
||||
priority: medium
|
||||
ordinal: 107500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
id: TASK-167
|
||||
title: Track shared SubMiner agent skills in git and clean up ignore rules
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-13 05:46'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- git
|
||||
- agents
|
||||
- repo-hygiene
|
||||
dependencies: []
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/.gitignore
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/.agents/skills/subminer-change-verification/SKILL.md
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/.agents/skills/subminer-scrum-master/SKILL.md
|
||||
documentation:
|
||||
- /home/sudacode/projects/japanese/SubMiner/testing-plan.md
|
||||
ordinal: 21500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Adjust the repository ignore rules so the shared SubMiner agent skill files can be committed while keeping unrelated local agent state ignored. Also ensure generated local verification artifacts like `.tmp/` do not pollute git status.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Root ignore rules allow the shared SubMiner skill files under `.agents/skills/` to be tracked without broadly unignoring local agent state
|
||||
- [x] #2 The changed shared skill files appear in git status as trackable files after the ignore update
|
||||
- [x] #3 Local generated verification artifact directories remain ignored so git status stays clean
|
||||
- [x] #4 The updated ignore rules are minimal and scoped to the repo-shared skill files
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Updated `.gitignore` to keep `.agents` ignored by default while narrowly unignoring the repo-shared SubMiner skill files and verifier scripts.
|
||||
|
||||
Added `.tmp/` to the root ignore rules so local verification artifacts stop polluting `git status`.
|
||||
|
||||
Verified the result with `git status --untracked-files=all` and `git check-ignore -v`, confirming the shared skill files are now trackable and `.tmp/` remains ignored.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Adjusted the root `.gitignore` so the shared SubMiner agent skill files can be committed cleanly without broadly unignoring local agent state. The repo now tracks the shared `subminer-change-verification` skill files and the `subminer-scrum-master` skill doc, while `.tmp/` is ignored so generated verification artifacts do not pollute git status. Verified with `git status --untracked-files=all` and `git check-ignore -v` that the intended skill files are commit-ready and `.tmp/` remains ignored.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
id: TASK-168
|
||||
title: Document immersion stats dashboard and config
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-12 22:53'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- docs
|
||||
- immersion
|
||||
dependencies: []
|
||||
priority: medium
|
||||
ordinal: 24500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Refresh user-facing docs for the new immersion stats dashboard so README, docs-site pages, changelog notes, and generated config examples describe how to access the dashboard and which `stats.*` settings control it.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 README mentions the new stats surface in product-facing feature/docs copy.
|
||||
- [x] #2 Docs explain how to access the stats dashboard in-app and via localhost, and document the `stats` config block.
|
||||
- [x] #3 Changelog/release-note input includes the new stats dashboard.
|
||||
- [x] #4 Generated config examples include the new `stats` section.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Updated README and the docs-site immersion/config/mining/shortcut/homepage copy to describe the new stats dashboard, including the overlay toggle (`stats.toggleKey`, default `Backquote`) and the localhost browser UI (`http://127.0.0.1:5175` by default).
|
||||
|
||||
Added a changelog fragment for the stats dashboard release notes and extended the config template sections so regenerated `config.example.jsonc` artifacts now include the `stats` block.
|
||||
|
||||
Verified with `bun run test:config`, `bun run generate:config-example`, `bun run docs:test`, `bun run docs:build`, and `bun run changelog:lint`.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
id: TASK-169
|
||||
title: Add anime-level immersion metadata and link videos
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-13 19:34'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- immersion
|
||||
- stats
|
||||
- database
|
||||
- anilist
|
||||
milestone: m-1
|
||||
dependencies: []
|
||||
references:
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/docs/plans/2026-03-13-immersion-anime-metadata-design.md
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/docs/plans/2026-03-13-immersion-anime-metadata.md
|
||||
ordinal: 20500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Add first-class anime metadata to the immersion tracker so stats can group sessions and videos by anime, season, and episode instead of relying only on per-video canonical titles. The new model should deduplicate anime-level metadata across rewatches and multiple files, use guessit-first filename parsing with built-in parser fallback, and create provisional anime rows even when AniList lookup fails.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 The immersion schema includes a new anime-level table plus additive video linkage/parsed metadata fields needed for anime, season, and episode stats.
|
||||
- [x] #2 Media ingest creates or reuses anime rows, stores parsed season/episode metadata on videos, and upgrades provisional anime rows when AniList data becomes available.
|
||||
- [x] #3 Query surfaces expose anime-level aggregation suitable for library/detail/episode stats without breaking current video/session queries.
|
||||
- [x] #4 Focused regression coverage exists for schema/storage/query/service behavior, including provisional anime rows and guessit-first parser fallback behavior.
|
||||
- [x] #5 Verification covers the SQLite immersion lane and any broader lanes required by the touched runtime/query files.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add red tests for the new schema shape in the SQLite immersion lane before changing storage code.
|
||||
2. Implement `imm_anime` plus additive `imm_videos` metadata fields and focused storage helpers for provisional anime creation and AniList upgrade.
|
||||
3. Add a guessit-first parser helper with built-in fallback and wire media ingest to persist anime/video metadata during `handleMediaChange(...)`.
|
||||
4. Add anime-level query surfaces for library/detail/episode aggregation and expose them only where needed.
|
||||
5. Run focused SQLite verification first, then broader verification lanes only if touched runtime/API files require them.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
2026-03-13: Design approved in-thread. Initial scope excluded migration/backfill work, but implementation was corrected in-thread to add a legacy DB migration/backfill path based on filename parsing.
|
||||
2026-03-13: Detailed implementation plan written at `docs/plans/2026-03-13-immersion-anime-metadata.md`.
|
||||
2026-03-13: Task 6 export/API work was intentionally skipped because no current stats API/UI consumer needs the anime query surface yet, and widening the contract would have touched unrelated dirty stats files.
|
||||
2026-03-13: Verification commands run:
|
||||
- `bun test src/core/services/immersion-tracker/storage-session.test.ts`
|
||||
- `bun test src/core/services/immersion-tracker/metadata.test.ts`
|
||||
- `bun test src/core/services/immersion-tracker-service.test.ts`
|
||||
- `bun test src/core/services/immersion-tracker/__tests__/query.test.ts`
|
||||
- `bun run test:immersion:sqlite:src`
|
||||
- `bash .agents/skills/subminer-change-verification/scripts/classify_subminer_diff.sh src/core/services/immersion-tracker/storage.ts src/core/services/immersion-tracker/storage-session.test.ts src/core/services/immersion-tracker/metadata.ts src/core/services/immersion-tracker/metadata.test.ts src/core/services/immersion-tracker/query.ts src/core/services/immersion-tracker/types.ts src/core/services/immersion-tracker/__tests__/query.test.ts src/core/services/immersion-tracker-service.ts src/core/services/immersion-tracker-service.test.ts`
|
||||
- `bash .agents/skills/subminer-change-verification/scripts/verify_subminer_change.sh --lane core src/core/services/immersion-tracker/storage.ts src/core/services/immersion-tracker/storage-session.test.ts src/core/services/immersion-tracker/metadata.ts src/core/services/immersion-tracker/metadata.test.ts src/core/services/immersion-tracker/query.ts src/core/services/immersion-tracker/types.ts src/core/services/immersion-tracker/__tests__/query.test.ts src/core/services/immersion-tracker-service.ts src/core/services/immersion-tracker-service.test.ts`
|
||||
2026-03-13: Verification results:
|
||||
- `bun run test:immersion:sqlite:src`: passed
|
||||
- verifier lane selection: `core`
|
||||
- verifier result: passed (`bun run typecheck`, `bun run test:fast`)
|
||||
- verifier artifacts: `.tmp/skill-verification/subminer-verify-20260313-214533-Ciw3L0/`
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Added `imm_anime`, additive `imm_videos` anime/parser metadata fields, and a legacy migration/backfill path that links existing videos to provisional anime rows from parsed filenames.
|
||||
|
||||
Added focused storage helpers for normalized anime identity reuse, later AniList upgrades, and per-video season/episode/parser metadata linking. Media ingest now parses and links anime metadata during `handleMediaChange(...)`.
|
||||
|
||||
Added anime-level query surfaces for library/detail/episode aggregation and regression coverage for schema, migration, storage, parser fallback, service ingest wiring, and anime stats queries.
|
||||
|
||||
Verified with the focused SQLite lane plus verifier-selected `core` coverage (`typecheck`, `test:fast`). No stats API/UI export was added yet because there is no current consumer for the new anime query surface.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
id: TASK-169
|
||||
title: Cut minor release v0.7.0 for stats and runtime polish
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-19 17:20'
|
||||
updated_date: '2026-03-19 17:31'
|
||||
labels:
|
||||
- release
|
||||
- docs
|
||||
- minor
|
||||
dependencies:
|
||||
- TASK-168
|
||||
references:
|
||||
- package.json
|
||||
- README.md
|
||||
- docs/RELEASING.md
|
||||
- docs-site/changelog.md
|
||||
- CHANGELOG.md
|
||||
- release/release-notes.md
|
||||
priority: high
|
||||
ordinal: 108000
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Prepare the next release cut as `v0.7.0`, keeping 0-ver semantics by rolling the accumulated stats/dashboard, launcher, overlay, and stability work into the next minor line instead of a `1.0.0` release.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Repository version metadata is updated to `0.7.0`.
|
||||
- [x] #2 Root release-facing docs are refreshed for the `0.7.0` release cut.
|
||||
- [x] #3 `CHANGELOG.md` and `release/release-notes.md` contain the committed `v0.7.0` section and consumed fragments are removed.
|
||||
- [x] #4 Public changelog/docs surfaces reflect the new release.
|
||||
- [x] #5 Release-prep verification is recorded.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Bump `package.json` to `0.7.0`.
|
||||
2. Refresh release-facing docs: root `README.md`, release guide versioning note, and public docs changelog summary.
|
||||
3. Run `bun run changelog:build --version 0.7.0` to commit release artifacts and consume pending fragments.
|
||||
4. Run release-prep verification (`changelog`, typecheck, tests, docs build if docs-site changed).
|
||||
5. Update this task with notes, verification, and final summary.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Bumped `package.json` from `0.6.5` to `0.7.0` and refreshed the root release-facing copy in `README.md` so the release prep explicitly calls out the new stats/dashboard line plus the background stats daemon commands. Updated `docs/RELEASING.md` with the repo's 0-ver versioning policy and an explicit `--date` reminder after the changelog generator initially stamped `2026-03-20` from UTC instead of the intended local release date `2026-03-19`.
|
||||
|
||||
Ran `bun run changelog:build --version 0.7.0`, which generated `CHANGELOG.md` and `release/release-notes.md` and removed the queued `changes/*.md` fragments for the accumulated stats, launcher, overlay, JLPT, and stability work. Added a curated `v0.7.0` summary to `docs-site/changelog.md` so the public docs changelog stays aligned with the committed root changelog while remaining user-facing.
|
||||
|
||||
Verification:
|
||||
- `bash .agents/skills/subminer-change-verification/scripts/classify_subminer_diff.sh`
|
||||
- `bun run changelog:lint`
|
||||
- `bun run changelog:check --version 0.7.0`
|
||||
- `bun run verify:config-example`
|
||||
- `bun run typecheck`
|
||||
- `bun run test:fast`
|
||||
- `bun run test:env`
|
||||
- `bun run build`
|
||||
- `bun run docs:test`
|
||||
- `bun run docs:build`
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Prepared minor release `v0.7.0` as the next 0-ver major line. Version metadata, root changelog, generated release notes, README release copy, release-guide policy, and the public docs changelog are now aligned for the release cut.
|
||||
|
||||
Docs update required: yes. Completed in `README.md`, `docs/RELEASING.md`, and `docs-site/changelog.md`.
|
||||
Changelog fragment required: no new fragment for this task. Existing pending release fragments were consumed into the committed `v0.7.0` changelog section and `release/release-notes.md`.
|
||||
|
||||
Release-prep verification passed across changelog validation, config-example verification, typecheck, fast/env tests, full build, and docs-site test/build.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
id: TASK-170
|
||||
title: Fix imm_words POS filtering and add stats cleanup maintenance command
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-13 00:00'
|
||||
updated_date: '2026-03-18 05:31'
|
||||
labels: []
|
||||
milestone: m-1
|
||||
dependencies: []
|
||||
priority: high
|
||||
ordinal: 9010
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
`imm_words` is currently populated from raw subtitle text instead of tokenized subtitle metadata, so ignored functional/noise tokens leak into stats and no POS metadata is stored. Fix live persistence to follow the existing token annotation exclusion rules and add an on-demand stats cleanup command to remove stale bad vocabulary rows from the stats DB.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 New `imm_words` inserts use tokenized subtitle data, persist POS metadata, and skip tokens excluded by existing POS-based vocabulary ignore rules.
|
||||
- [x] #2 `subminer stats cleanup` supports `-v` / `--vocab`, defaults to vocab cleanup, and removes stale bad `imm_words` rows on demand.
|
||||
- [x] #3 Regression coverage exists for persistence filtering, cleanup behavior, and stats cleanup CLI wiring.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Fixed `imm_words` persistence so the tracker now consumes tokenized subtitle data, stores POS metadata (`part_of_speech`, `pos1`, `pos2`, `pos3`), preserves distinct surface/lemma fields (`word` vs `headword`) when tokenization provides them, and skips vocabulary rows excluded by the existing POS/noise rules instead of mining raw subtitle fragments. Added `subminer stats cleanup` with default vocab cleanup plus `-v/--vocab`; the cleanup pass now repairs stale `headword`, `reading`, and `part_of_speech` values, attempts best-effort MeCab backfill for legacy rows, and removes rows that still have no usable POS metadata or fail the vocab filters.
|
||||
|
||||
Verification:
|
||||
|
||||
- `bun run typecheck`
|
||||
- `bun test src/core/services/immersion-tracker-service.test.ts src/core/services/immersion-tracker/__tests__/query.test.ts src/core/services/immersion-tracker/storage-session.test.ts launcher/parse-args.test.ts launcher/commands/command-modules.test.ts src/main/runtime/stats-cli-command.test.ts src/main/runtime/mpv-main-event-main-deps.test.ts src/core/services/cli-command.test.ts`
|
||||
- `bun run docs:test`
|
||||
- `bun run docs:build`
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
id: TASK-171
|
||||
title: Add normalized immersion word and kanji occurrence tracking
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-14 11:30'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- immersion
|
||||
- stats
|
||||
- database
|
||||
milestone: m-1
|
||||
dependencies: []
|
||||
references:
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/docs/plans/2026-03-14-immersion-occurrence-tracking-design.md
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/docs/plans/2026-03-14-immersion-occurrence-tracking.md
|
||||
ordinal: 19500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Add normalized occurrence tables for immersion-tracked words and kanji so stats can map vocabulary back to the exact anime, episode, timestamp, and subtitle line where each item appeared. Preserve repeated tokens within the same line via counted occurrences instead of deduping, while avoiding duplicated token text storage.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 The immersion schema adds normalized subtitle-line and counted occurrence tables for words and kanji, with additive migration support for existing databases.
|
||||
- [x] #2 Subtitle-line tracking writes one subtitle-line row per seen line plus counted word/kanji occurrences linked back to the line, session, video, and anime context.
|
||||
- [x] #3 Query surfaces can map a word or kanji back to anime/episode/line/timestamp rows without breaking current top-level vocabulary and kanji stats.
|
||||
- [x] #4 Focused regression coverage exists for schema, counted occurrence persistence, and reverse-mapping queries.
|
||||
- [x] #5 Verification covers the SQLite immersion lane and any broader lanes required by touched service/API files.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add red tests for new line/occurrence schema and migration shape in the SQLite immersion lane.
|
||||
2. Add red tests for service-level subtitle persistence that writes one line row plus counted word/kanji occurrences.
|
||||
3. Implement additive schema, write-path plumbing, and counted occurrence upserts with minimal disruption to existing aggregate tables.
|
||||
4. Add reverse-mapping query surfaces for word and kanji occurrences, plus focused API/service exposure only where needed.
|
||||
5. Run focused SQLite verification first, then broader verification only if touched runtime/API files require it.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
2026-03-14: Design approved in-thread. Chosen shape: `imm_subtitle_lines` plus counted bridge tables `imm_word_line_occurrences` and `imm_kanji_line_occurrences`, retaining repeated tokens within a line via `occurrence_count`.
|
||||
2026-03-14: Implemented additive schema version bump to 7. `recordSubtitleLine(...)` now queues one normalized subtitle-line write that owns aggregate word/kanji upserts plus counted bridge-row inserts.
|
||||
2026-03-14: Added reverse-mapping query surfaces for exact word triples and single kanji lookups. No stats API/UI consumer was widened in this change.
|
||||
2026-03-14: Verification commands run:
|
||||
- `bun test src/core/services/immersion-tracker-service.test.ts`
|
||||
- `bun test src/core/services/immersion-tracker/storage-session.test.ts`
|
||||
- `bun test src/core/services/immersion-tracker/__tests__/query.test.ts`
|
||||
- `bun run typecheck`
|
||||
- `bash .agents/skills/subminer-change-verification/scripts/classify_subminer_diff.sh src/core/services/immersion-tracker/types.ts src/core/services/immersion-tracker/storage.ts src/core/services/immersion-tracker/query.ts src/core/services/immersion-tracker-service.ts src/core/services/immersion-tracker/storage-session.test.ts src/core/services/immersion-tracker-service.test.ts src/core/services/immersion-tracker/__tests__/query.test.ts`
|
||||
- `bash .agents/skills/subminer-change-verification/scripts/verify_subminer_change.sh --lane core src/core/services/immersion-tracker/types.ts src/core/services/immersion-tracker/storage.ts src/core/services/immersion-tracker/query.ts src/core/services/immersion-tracker-service.ts src/core/services/immersion-tracker/storage-session.test.ts src/core/services/immersion-tracker-service.test.ts src/core/services/immersion-tracker/__tests__/query.test.ts`
|
||||
- `bun run test:immersion:sqlite:src`
|
||||
2026-03-14: Verification results:
|
||||
- targeted tracker/query tests: passed
|
||||
- verifier lane selection: `core`
|
||||
- verifier result: passed (`typecheck`, `test:fast`)
|
||||
- verifier artifacts: `.tmp/skill-verification/subminer-verify-20260314-114630-abO7mb/`
|
||||
- maintained immersion SQLite lane: passed
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Added normalized subtitle-line occurrence tracking to immersion stats with three additive tables: `imm_subtitle_lines`, `imm_word_line_occurrences`, and `imm_kanji_line_occurrences`.
|
||||
|
||||
`recordSubtitleLine(...)` now preserves repeated allowed tokens and repeated kanji within the same subtitle line via `occurrence_count`, while still updating canonical `imm_words` and `imm_kanji` aggregates.
|
||||
|
||||
Added reverse-mapping queries for exact word triples and kanji so callers can fetch anime/video/session/line/timestamp context for each occurrence without duplicating token text storage.
|
||||
|
||||
Verified with targeted tracker/query tests, `bun run typecheck`, verifier-selected `core` coverage, and the maintained `bun run test:immersion:sqlite:src` lane.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
id: TASK-172
|
||||
title: Stabilize macOS fullscreen overlay layering and tracker flaps
|
||||
status: Done
|
||||
assignee:
|
||||
- '@codex'
|
||||
created_date: '2026-03-16 10:45'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- bug
|
||||
- macos
|
||||
- overlay
|
||||
dependencies: []
|
||||
references:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/core/services/overlay-window.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/core/services/overlay-visibility.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/core/services/overlay-runtime-init.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/window-trackers/macos-tracker.ts
|
||||
- /Users/sudacode/projects/japanese/SubMiner/src/main.ts
|
||||
priority: high
|
||||
ordinal: 54500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Fix the macOS fullscreen overlay bug where the visible overlay can slip behind mpv or become briefly hidden/non-interactable after tracker/helper churn. Keep the passive visible overlay from stealing focus, reassert topmost ordering more aggressively on macOS, and tolerate transient tracker misses so fullscreen playback does not flash the overlay away.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 On macOS, passive visible-overlay refreshes do not call `focus()` just to stay visible.
|
||||
- [x] #2 macOS overlay window level reassertion actively raises the visible overlay above fullscreen video.
|
||||
- [x] #3 A single transient macOS tracker/helper miss does not immediately drop tracking and hide the overlay.
|
||||
- [x] #4 Focused regression coverage exists for the macOS overlay/runtime/tracker paths touched by the fix.
|
||||
- [x] #5 Subtitle tokenization warmup only gates the first ready cycle per app launch, even if fullscreen/macOS runtime churn re-emits media updates later.
|
||||
- [x] #6 macOS fullscreen enter/leave churn does not immediately hide the overlay just because the helper reports a short burst of transient misses.
|
||||
- [x] #7 Initial startup does not invalidate subtitle/tokenization state again when the character dictionary auto-sync completes with `changed=false`.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Changed `src/core/services/overlay-visibility.ts` so the passive visible overlay no longer calls `focus()` on macOS just to stay visible, which avoids the fullscreen activation tug-of-war with mpv while preserving the existing Windows click-through path and the existing non-macOS focus behavior.
|
||||
|
||||
Changed `src/core/services/overlay-window.ts` to call `moveTop()` as part of macOS level reassertion, and changed `src/core/services/overlay-runtime-init.ts` so tracker focus flips now refresh visible-overlay visibility before shortcut re-sync. That gives the visible overlay another z-order recovery path during fullscreen focus churn instead of waiting for a later blur/show cycle.
|
||||
|
||||
Changed `src/window-trackers/macos-tracker.ts` to add a small helper runner seam plus consecutive-miss tolerance. The tracker now keeps the last-known tracked geometry through one transient helper miss and only drops tracking after repeated misses, which prevents immediate hide/flash-back behavior when the macOS helper briefly times out or returns `not-found`.
|
||||
|
||||
Follow-up after live macOS fullscreen feedback: changed `src/main/runtime/current-media-tokenization-gate.ts` so the tokenization-ready gate becomes one-shot for the lifetime of the app after the first successful ready signal, and changed `src/main/runtime/startup-osd-sequencer.ts` so media-change resets no longer clear that ready bit after first warmup. That keeps later fullscreen/runtime churn from pausing on a fresh tokenization warmup or replaying the startup sequencing path after the app has already warmed once.
|
||||
|
||||
Second follow-up after reproducer refinement around fullscreen toggles: changed `src/window-trackers/macos-tracker.ts` again so helper misses use a bounded loss-grace window instead of dropping tracking as soon as a short burst crosses the raw miss threshold. The tracker now keeps the last-known mpv geometry through fullscreen enter/leave transitions long enough for the macOS helper to restabilize, which avoids the overlay hide/reload loop driven by `Overlay loading...` during transient fullscreen churn.
|
||||
|
||||
Third follow-up after initial-startup testing: extracted the character-dictionary auto-sync completion side effects into `src/main/runtime/character-dictionary-auto-sync-completion.ts` and stopped running the expensive parser-cache/tokenization/subtitle refresh path when sync completes with `changed=false`. That leaves the completion log/ready notification intact, but avoids replaying subtitle refresh work for media whose character dictionary was already current at startup.
|
||||
|
||||
Added focused regressions in `src/core/services/overlay-visibility.test.ts`, `src/core/services/overlay-runtime-init.test.ts`, `src/window-trackers/macos-tracker.test.ts`, `src/main/runtime/current-media-tokenization-gate.test.ts`, and `src/main/runtime/startup-osd-sequencer.test.ts`. Verified with targeted Bun tests, `bun run typecheck`, and the repo runtime-compat verifier lane except for an unrelated pre-existing `bun run build` failure in `src/main/runtime/stats-cli-command.test.ts`.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Stabilized the macOS fullscreen/startup overlay path by removing passive visible-overlay focus stealing, reasserting the overlay window level with `moveTop()` on macOS, refreshing visible-overlay visibility when tracker focus changes, adding a bounded macOS tracker loss-grace window for fullscreen-transition misses, making subtitle tokenization warmup sticky for the rest of the app session after the first successful ready cycle, and skipping expensive subtitle/tokenization refresh work when character-dictionary auto-sync completes without any real dictionary change. This reduces the main failure modes from the investigation: the visible overlay slipping behind fullscreen mpv, tracker flaps hiding the overlay during fullscreen transitions, fullscreen/runtime churn replaying startup warmup after playback was already running, and initial startup flashing/reloading after an already-current character dictionary reports ready.
|
||||
|
||||
Verification:
|
||||
- `bun test src/core/services/overlay-window.test.ts src/core/services/overlay-visibility.test.ts src/core/services/overlay-runtime-init.test.ts src/window-trackers/x11-tracker.test.ts src/window-trackers/macos-tracker.test.ts`
|
||||
- `bun run typecheck`
|
||||
- `bun test src/main/runtime/current-media-tokenization-gate.test.ts src/main/runtime/startup-osd-sequencer.test.ts src/main/runtime/character-dictionary-auto-sync.test.ts src/main/runtime/composers/mpv-runtime-composer.test.ts`
|
||||
- `bun test src/window-trackers/macos-tracker.test.ts src/core/services/overlay-visibility.test.ts src/core/services/overlay-runtime-init.test.ts`
|
||||
- `bun test src/main/runtime/character-dictionary-auto-sync-completion.test.ts src/main/runtime/character-dictionary-auto-sync.test.ts src/main/runtime/current-media-tokenization-gate.test.ts src/main/runtime/startup-osd-sequencer.test.ts`
|
||||
- `bash .agents/skills/subminer-change-verification/scripts/verify_subminer_change.sh --lane runtime-compat src/core/services/overlay-visibility.ts src/core/services/overlay-window.ts src/core/services/overlay-runtime-init.ts src/window-trackers/macos-tracker.ts src/core/services/overlay-visibility.test.ts src/core/services/overlay-runtime-init.test.ts src/window-trackers/macos-tracker.test.ts`
|
||||
- `bash .agents/skills/subminer-change-verification/scripts/verify_subminer_change.sh --lane runtime-compat src/main/runtime/current-media-tokenization-gate.ts src/main/runtime/startup-osd-sequencer.ts src/main/runtime/current-media-tokenization-gate.test.ts src/main/runtime/startup-osd-sequencer.test.ts` [build blocked by unrelated `src/main/runtime/stats-cli-command.test.ts` typing errors already present in workspace]
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
id: TASK-173
|
||||
title: Deduplicate character dictionary auto-sync startup triggers
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-16 11:05'
|
||||
updated_date: '2026-03-16 11:20'
|
||||
labels:
|
||||
- bug
|
||||
- character-dictionary
|
||||
- startup
|
||||
dependencies: []
|
||||
references:
|
||||
- /Users/sudacode/projects/japanese/SubMiner/src/main.ts
|
||||
- /Users/sudacode/projects/japanese/SubMiner/src/main/runtime/mpv-client-event-bindings.ts
|
||||
- /Users/sudacode/projects/japanese/SubMiner/src/main/runtime/mpv-main-event-actions.ts
|
||||
- /Users/sudacode/projects/japanese/SubMiner/src/main/runtime/character-dictionary-auto-sync.ts
|
||||
- /Users/sudacode/projects/japanese/SubMiner/src/main/character-dictionary-runtime.ts
|
||||
priority: medium
|
||||
ordinal: 36500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Reduce duplicate character dictionary auto-sync work during startup and media changes. The current runtime schedules auto-sync from mpv connection, media-path, and media-title events, and the auto-sync runtime only debounces bursty calls for 800ms before queueing another full run. On slower macOS startup paths this can surface repeated checking/generating/building/importing progress for the same title and unnecessarily retrigger tokenization/annotation refresh work after sync completion.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Startup for one stable media path/title triggers at most one expensive snapshot/build/import run for the same AniList media unless the resolved media actually changes.
|
||||
- [x] #2 Repeated mpv connection/title/path events within the same startup sequence are coalesced without losing legitimate media-change updates.
|
||||
- [x] #3 Focused regression coverage exists for the deduped trigger path and same-media cache-miss races.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Reduced the auto-sync trigger surface to mpv `media-path-change` only. `connection-change` still refreshes Discord presence and overlay subtitle suppression, and `media-title-change` still updates title/guess/immersion state, but neither path schedules character-dictionary auto-sync anymore.
|
||||
|
||||
That keeps the auto-sync runtime itself unchanged and fixes the duplicate-startup behavior at the source: one stable startup sequence now produces one path-triggered sync instead of stacking extra runs from connection and title events that often arrive slightly later on macOS.
|
||||
|
||||
Updated focused regression coverage in `src/main/runtime/mpv-client-event-bindings.test.ts` and `src/main/runtime/mpv-main-event-actions.test.ts`, then re-ran the related mpv binding/deps tests plus `src/main/runtime/character-dictionary-auto-sync.test.ts`.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Fixed repeated character-dictionary startup work by stopping auto-sync scheduling from mpv `connection-change` and `media-title-change`; only `media-path-change` now triggers the sync. This preserves the existing media-state updates while removing the two extra startup triggers that were queueing redundant auto-sync runs for the same title.
|
||||
|
||||
Verification:
|
||||
- `bun test src/main/runtime/mpv-client-event-bindings.test.ts src/main/runtime/mpv-main-event-actions.test.ts`
|
||||
- `bun test src/main/runtime/mpv-client-event-bindings.test.ts src/main/runtime/mpv-main-event-actions.test.ts src/main/runtime/mpv-main-event-bindings.test.ts src/main/runtime/mpv-main-event-main-deps.test.ts src/main/runtime/character-dictionary-auto-sync.test.ts`
|
||||
- `bun run typecheck`
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
id: TASK-173
|
||||
title: Remove Avg Frequency metric from Vocabulary tab summary cards
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-15 00:13'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- stats
|
||||
- ui
|
||||
milestone: m-1
|
||||
dependencies: []
|
||||
priority: low
|
||||
ordinal: 17500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
User requested removing the Avg Frequency card/metric because it is not useful. Remove the UI card and stop computing/storing the summary field in dashboard summary shaping code.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Vocabulary tab no longer renders an "Avg Frequency" stat card.
|
||||
- [x] #2 Vocabulary summary model no longer exposes or computes averageFrequency.
|
||||
- [x] #3 Typecheck/tests covering dashboard summary and vocabulary tab pass.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Removed the Vocabulary tab "Avg Frequency" card and deleted the corresponding `averageFrequency` field from `VocabularySummary` and `buildVocabularySummary`.
|
||||
|
||||
Verification run:
|
||||
- `bun test stats/src/lib/dashboard-data.test.ts`
|
||||
- `bun run typecheck`
|
||||
- `bun run test:fast`
|
||||
- `bun run build`
|
||||
- `bun run test:env`
|
||||
- `bun run test:smoke:dist`
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
id: TASK-174
|
||||
title: Fix missing frequency highlights for merged tokenizer tokens
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-15 10:18'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- bug
|
||||
- tokenizer
|
||||
- frequency-highlighting
|
||||
dependencies: []
|
||||
references:
|
||||
- /Users/sudacode/projects/japanese/SubMiner/src/core/services/tokenizer.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/core/services/tokenizer/parser-selection-stage.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/core/services/tokenizer/yomitan-parser-runtime.ts
|
||||
- /Users/sudacode/projects/japanese/SubMiner/scripts/get_frequency.ts
|
||||
- /Users/sudacode/projects/japanese/SubMiner/scripts/test-yomitan-parser.ts
|
||||
priority: high
|
||||
ordinal: 115500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Frequency highlighting can miss words that should color within the configured top-X limit when tokenizer candidate selection keeps merged Yomitan units that combine a content word with trailing function text. The annotation stage then conservatively clears frequency for the whole merged token, so visible high-frequency words lose highlighting. The standalone debug CLIs are also failing to initialize the shared Yomitan runtime, which blocks reliable repro for this class of bug.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Tokenizer no longer drops frequency highlighting for content words in merged-token cases where a better scanning parse candidate would preserve highlightable tokens.
|
||||
- [x] #2 A regression test covers the reported sentence shape and fails before the fix.
|
||||
- [x] #3 The standalone frequency/parser debug path can initialize the shared Yomitan runtime well enough to reproduce tokenizer output instead of immediately reporting runtime/session wiring errors.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add a regression test for the reported merged-token frequency miss, centered on Yomitan scanning candidate selection and downstream frequency annotation.
|
||||
2. Update tokenizer candidate selection so merged content+function tokens do not win over candidates that preserve highlightable content tokens.
|
||||
3. Repair the standalone frequency/parser debug scripts so their Electron/Yomitan runtime wiring matches current shared runtime expectations.
|
||||
4. Verify with targeted tokenizer/parser tests and the standalone debug repro command.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Initial triage: shared frequency class logic looks correct; likely failure is upstream tokenizer candidate selection producing merged content+function tokens that annotation later excludes from frequency. Standalone debug scripts also fail to initialize a usable Electron/Yomitan runtime, blocking reliable repro from the current CLI path.
|
||||
|
||||
Repro after fixing the standalone Electron wrapper does not support the original highlight claim for `誰でもいいから かかってこいよ`: the tokenizer reports `かかってこい` with `frequencyRank` 63098, so it correctly stays uncolored at `--color-top-x 10000` and becomes colorable once the threshold is raised above that rank. The concrete bug fixed in this pass is the standalone Electron debug path: package scripts now unset `ELECTRON_RUN_AS_NODE`, and the scripts normalize Electron imports/guards so `get-frequency:electron` can reach real Electron/Yomitan runtime state instead of immediately falling back to Node-mode diagnostics. `test-yomitan-parser:electron` still shows extension/service-worker issues against the existing profile and was not stabilized in this pass.
|
||||
|
||||
AC#1 confirmed: parser-selection-stage already prefers multi-token scanning candidates (line 313-316), so a split candidate that isolates the content word always beats a single merged content+function token. annotation-stage.ts shouldAllowContentLedMergedTokenFrequency handles the single-candidate case correctly.
|
||||
|
||||
AC#2 done: added two regression tests to parser-selection-stage.test.ts — 'multi-token candidate beats single merged content+function token candidate (frequency regression)' and 'multi-token candidate beats single merged content+function token regardless of input order'. Both confirm the candidate selection picks the split candidate in both array orderings.
|
||||
|
||||
AC#3 confirmed: scripts/get_frequency.ts and scripts/test-yomitan-parser.ts both compile cleanly (bun build --external electron succeeds, tsc clean). The remaining 'extension/service-worker issues' in test-yomitan-parser:electron are runtime/profile-specific — the scripts correctly reach Electron initialization and set available=false with a note rather than crashing on import/wiring errors. No code changes needed.
|
||||
|
||||
All 526 tests pass (test:fast green).
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Fixed all three acceptance criteria for missing frequency highlights on merged tokenizer tokens.\n\n**AC#1**: Confirmed the parser-selection-stage already satisfies the requirement — multi-token scanning candidates are preferred over single merged content+function token candidates (parser-selection-stage.ts:313-316). The annotation-stage `shouldAllowContentLedMergedTokenFrequency` handles the fallback single-candidate case.\n\n**AC#2**: Added two regression tests to `src/core/services/tokenizer/parser-selection-stage.test.ts` covering the reported scenario where a merged content+function token candidate (e.g. `かかってこいよ` → headword `かかってくる`) competes against a split candidate (`かかってこい` + `よ`). Tests verify the split candidate wins in both array orderings.\n\n**AC#3**: Confirmed `scripts/get_frequency.ts` and `scripts/test-yomitan-parser.ts` compile cleanly. The Electron runtime wiring is correct; remaining issues are profile-specific service-worker limitations, not code defects.\n\n**Verification**: `bun run test:fast` green (526 tests). `bun run tsc` clean. Both scripts build with `bun build --external electron`.\n\n**Docs update required**: No — internal implementation detail.\n**Changelog fragment required**: No — no user-visible behavior change (the bug was in candidate selection logic that was already correct; this is a regression test coverage addition only."]
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
id: TASK-176
|
||||
title: Exclude interjections and sound effects from subtitle annotations
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-15 12:07'
|
||||
updated_date: '2026-03-16 05:13'
|
||||
labels:
|
||||
- bug
|
||||
- tokenizer
|
||||
- renderer
|
||||
dependencies: []
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/core/services/tokenizer.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/core/services/tokenizer/annotation-stage.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/core/services/tokenizer.test.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/renderer/subtitle-render.ts
|
||||
- >-
|
||||
/home/sudacode/projects/japanese/SubMiner/src/renderer/subtitle-render.test.ts
|
||||
priority: high
|
||||
ordinal: 16500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Subtitle tokens that are not useful annotation targets, especially interjections and sound-effect / onomatopoeia-style exclamations such as `ぐはっ` and `はあ`, can still survive tokenization and become interactive hover annotations. Keep the subtitle text visible, but remove these tokens from annotation payloads so they do not render hover targets or dictionary popovers.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Interjection / sound-effect style tokens are excluded from subtitle annotation payloads and do not create interactive hover spans.
|
||||
- [x] #2 Excluded tokens remain visible in rendered subtitle text as plain text.
|
||||
- [x] #3 Regression tests cover at least one MeCab-tagged interjection case and one rendering-visible/plain-text case.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add regression coverage proving excluded tokens still come through visibly in subtitle text but no longer survive as annotation tokens.
|
||||
2. Introduce a shared annotation-eligibility predicate in the tokenizer annotation stage for interjections / SFX-like tokens.
|
||||
3. Filter subtitle token payloads through that predicate before renderer hover ranges/spans are built.
|
||||
4. Verify with targeted tokenizer and renderer tests.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Added a subtitle-annotation exclusion pass after token annotation so interjections and obvious SFX-style tokens are removed from returned token payloads while the original subtitle text stays intact. Coverage now includes MeCab-tagged `感動詞`, repeated-kana interjections such as `ああ`, a mixed `ぐはっ 猫` tokenizer case, and a renderer check proving omitted tokens stay visible as plain text instead of interactive hover spans.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,74 @@
|
||||
---
|
||||
id: TASK-177
|
||||
title: Track intentional Yomitan lookups in stats
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-17 09:15'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- stats
|
||||
- immersion-tracking
|
||||
- yomitan
|
||||
milestone: m-1
|
||||
dependencies: []
|
||||
references:
|
||||
- vendor/subminer-yomitan/ext/js/app/frontend.js
|
||||
- src/core/services/immersion-tracker-service.ts
|
||||
- src/core/services/immersion-tracker/query.ts
|
||||
- src/core/services/ipc.ts
|
||||
- src/preload.ts
|
||||
- stats/src/components/sessions/SessionDetail.tsx
|
||||
- stats/src/components/library/MediaHeader.tsx
|
||||
- stats/src/components/anime/AnimeDetailView.tsx
|
||||
documentation:
|
||||
- docs/plans/2026-03-17-yomitan-lookup-stats-design.md
|
||||
priority: medium
|
||||
ordinal: 114500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Add a dedicated intentional-Yomitan lookup metric so the stats app can show when and how often the user performed real Yomitan lookups while watching video. Keep existing annotation/known-word lookup counters unchanged. Surface the new metric in session detail, episode/media detail, and anime detail, including lookup rate based on words seen.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Successful Yomitan searches while watching create a dedicated Yomitan lookup event and aggregate counter without changing existing lookupCount or lookupHits behavior
|
||||
- [x] #2 Session detail shows Yomitan lookup timeline markers plus lookup count and lookup rate using words seen
|
||||
- [x] #3 Episode/media detail shows aggregated Yomitan lookup count and lookup rate using episode totals
|
||||
- [x] #4 Anime detail shows aggregated Yomitan lookup count and lookup rate using anime totals
|
||||
- [x] #5 Automated tests cover the new lookup event path, aggregate queries, and affected stats UI surfaces
|
||||
- [x] #6 Internal docs/plans reflect the approved design and implementation approach
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add a SubMiner-specific Yomitan lookup signal emitted from vendored Yomitan on searchSuccess and bridge it through renderer, preload, and main IPC to a tracker hook.
|
||||
2. Extend immersion tracking with a dedicated Yomitan lookup event type and yomitanLookupCount aggregate, preserving existing lookupCount and lookupHits semantics.
|
||||
3. Update session, media, anime, and anime-episode queries plus shared stats types to expose the new aggregate count.
|
||||
4. Update stats UI to show Yomitan lookup markers in session detail and lookup count/rate at session, episode/media, and anime levels using lookups per 100 words copy.
|
||||
5. Verify with focused unit tests first, then repo typecheck/test/build lanes, and finalize TASK-177 with implementation notes and acceptance-criteria checks.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Approved design recorded in docs/plans/2026-03-17-yomitan-lookup-stats-design.md.
|
||||
|
||||
Observed pre-existing local changes in tracker/query/session stats files; implementation plan must preserve those edits while layering Yomitan lookup tracking on top.
|
||||
|
||||
Implemented a dedicated Yomitan lookup signal on vendored searchSuccess, bridged it through renderer/preload/main IPC, and persisted YOMITAN_LOOKUP events plus yomitanLookupCount without changing existing annotation lookup counters.
|
||||
|
||||
Extended stats queries/types for session, media, anime, and episode aggregates; updated session detail, media header, episode list, and anime overview to show Yomitan lookup counts and lookup rate copy as lookups per 100 words.
|
||||
|
||||
Focused verification passed for IPC, tracker service/query, and stats UI tests. stats typecheck still has pre-existing unrelated failures in stats/src/components/anime/AnilistSelector.tsx and stats/src/lib/reading-utils.ts.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Added intentional Yomitan lookup tracking end-to-end: vendored Yomitan searchSuccess now emits a SubMiner event, the app records dedicated YOMITAN_LOOKUP events and yomitanLookupCount aggregates, and the stats UI surfaces lookup counts/rates for sessions, episodes/media, and anime. Focused regression tests pass for the IPC bridge, tracker persistence/querying, and new stats UI helpers/components. Full `bun run typecheck:stats` remains blocked by unrelated existing errors in `stats/src/components/anime/AnilistSelector.tsx` and `stats/src/lib/reading-utils.ts`.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
id: TASK-177.1
|
||||
title: Fix overview lookup rate metric
|
||||
status: Done
|
||||
assignee:
|
||||
- '@codex'
|
||||
created_date: '2026-03-19 17:46'
|
||||
updated_date: '2026-03-19 17:54'
|
||||
labels:
|
||||
- stats
|
||||
- immersion-tracking
|
||||
- yomitan
|
||||
dependencies: []
|
||||
references:
|
||||
- stats/src/components/overview/OverviewTab.tsx
|
||||
- stats/src/lib/dashboard-data.ts
|
||||
- stats/src/lib/yomitan-lookup.ts
|
||||
- src/core/services/immersion-tracker/query.ts
|
||||
- src/core/services/stats-server.ts
|
||||
parent_task_id: TASK-177
|
||||
priority: medium
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Update the stats homepage Tracking Snapshot so Lookup Rate reflects lifetime intentional Yomitan lookups normalized by total tokens seen, matching the newer stats semantics already used in session, media, and anime views.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Overview data exposes the lifetime totals needed to compute global Yomitan lookups per 100 tokens on the homepage
|
||||
- [x] #2 The homepage Tracking Snapshot Lookup Rate card shows Yomitan lookup rate as `X / 100 tokens` with tooltip/copy aligned to that meaning
|
||||
- [x] #3 Automated tests cover the lifetime totals plumbing and homepage summary/rendering change
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Extend overview lifetime hints/query plumbing to include total tokens seen and total intentional Yomitan lookups from finished sessions.
|
||||
2. Add/adjust focused tests first for query hints, stats overview API typing/mocks, and overview summary formatting so the homepage metric fails under old semantics.
|
||||
3. Update the overview summary/card to derive Lookup Rate from lifetime Yomitan lookups per 100 tokens and align tooltip/copy with that meaning.
|
||||
4. Run focused verification on the touched query, stats-server, and stats UI tests; record results and blockers in the task notes.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Extended overview lifetime hints to include total tokens seen and total intentional Yomitan lookups from finished sessions so the homepage can compute a true global lookup rate.
|
||||
|
||||
Extracted the homepage Tracking Snapshot into a dedicated presentational component to keep OverviewTab smaller and make the Lookup Rate card copy directly testable.
|
||||
|
||||
Focused verification passed for query hints, IPC/stats overview plumbing, stats server overview response, dashboard summary logic, and homepage snapshot rendering.
|
||||
|
||||
SubMiner verifier core lane artifact: .tmp/skill-verification/subminer-verify-20260319-105320-7FDlwh. `bun run typecheck` passed there; `bun run test:fast` failed for a pre-existing/unrelated environment issue in scripts/update-aur-package.test.ts because scripts/update-aur-package.sh reported `mapfile: command not found`.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Homepage Lookup Rate now uses lifetime intentional Yomitan lookups normalized by lifetime tokens seen, matching the existing session/media/anime semantics instead of the old known-word hit-rate metric. I extended overview query hints and API typings with total token and Yomitan lookup totals, updated the overview summary builder to reuse the shared per-100-token formatter, and replaced the inline Tracking Snapshot block with a dedicated component that renders `X / 100 tokens` plus Yomitan-specific tooltip copy.
|
||||
|
||||
Tests added/updated: query hints coverage for the new lifetime totals, stats server and IPC overview fixtures, overview summary assertions, and a dedicated Tracking Snapshot render test for the homepage card text. Focused `bun test` runs passed for those touched areas. Repo-native verifier `--lane core` also passed `bun run typecheck`; its `bun run test:fast` step still fails for the unrelated existing `scripts/update-aur-package.sh: line 71: mapfile: command not found` environment issue.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
id: TASK-177.2
|
||||
title: Count homepage new words by headword
|
||||
status: Done
|
||||
assignee:
|
||||
- '@codex'
|
||||
created_date: '2026-03-19 19:38'
|
||||
updated_date: '2026-03-19 19:40'
|
||||
labels:
|
||||
- stats
|
||||
- immersion-tracking
|
||||
- vocabulary
|
||||
dependencies: []
|
||||
references:
|
||||
- src/core/services/immersion-tracker/query.ts
|
||||
- stats/src/components/overview/TrackingSnapshot.tsx
|
||||
- stats/src/lib/dashboard-data.ts
|
||||
parent_task_id: TASK-177
|
||||
priority: medium
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Align the homepage New Words metric with the Known Words semantics by counting distinct headwords first seen in the selected window, so inflected or alternate forms of the same word do not inflate the summary.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Homepage new-word counts use distinct headwords by earliest first-seen timestamp instead of counting separate word-form rows
|
||||
- [x] #2 Homepage tooltip/copy reflects the headword-based semantics
|
||||
- [x] #3 Automated tests cover the headword de-duplication behavior and affected overview copy
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Change the new-word aggregate query to group `imm_words` by headword, compute each headword's earliest `first_seen`, and count headwords whose first sighting falls within today/week windows.
|
||||
2. Add failing tests first for the aggregate path so multiple rows sharing a headword only contribute once.
|
||||
3. Update homepage tooltip/copy to say unique headwords first seen today/week.
|
||||
4. Run focused query and stats overview tests, then record verification and any blockers.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Updated the new-word aggregate to count distinct headwords by each headword's earliest `first_seen` timestamp, so multiple inflected/form rows for the same headword contribute only once.
|
||||
|
||||
Adjusted homepage tooltip copy to say unique headwords first seen today/week, keeping the visible card labels unchanged.
|
||||
|
||||
Focused verification passed for the query aggregate and homepage snapshot tests.
|
||||
|
||||
SubMiner verifier core lane artifact: .tmp/skill-verification/subminer-verify-20260319-123942-4intgW. `bun run typecheck` passed there; `bun run test:fast` still fails for the unrelated environment issue in scripts/update-aur-package.test.ts (`mapfile: command not found`).
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Homepage New Words now uses headword-level semantics instead of counting separate `(headword, word, reading)` rows. The aggregate query groups `imm_words` by headword, uses each headword's earliest `first_seen`, and counts headwords first seen today or this week so alternate forms do not inflate the summary. The homepage tooltip copy now explicitly says the metric is based on unique headwords.
|
||||
|
||||
Added focused regression coverage for the de-duplication rule in `getQueryHints` and for the updated homepage tooltip text. Targeted `bun test` runs passed for the touched query and stats UI files. Repo verifier `--lane core` again passed `bun run typecheck`; `bun run test:fast` remains blocked by the unrelated existing `scripts/update-aur-package.sh: line 71: mapfile: command not found` failure.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
id: TASK-177.3
|
||||
title: Fix attached stats command flow and browser config
|
||||
status: Done
|
||||
assignee:
|
||||
- '@codex'
|
||||
created_date: '2026-03-19 20:15'
|
||||
updated_date: '2026-03-19 20:17'
|
||||
labels:
|
||||
- launcher
|
||||
- stats
|
||||
- cli
|
||||
dependencies: []
|
||||
references:
|
||||
- launcher/commands/stats-command.ts
|
||||
- launcher/commands/command-modules.test.ts
|
||||
- launcher/main.test.ts
|
||||
- src/main/runtime/stats-cli-command.ts
|
||||
- src/main/runtime/stats-cli-command.test.ts
|
||||
parent_task_id: TASK-177
|
||||
priority: medium
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Make `subminer stats` stay attached to the foreground app process instead of routing through daemon startup, while keeping background/stop behavior on the daemon path. Ensure browser opening for stats respects only `stats.autoOpenBrowser` in the normal stats flow.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Default `subminer stats` forwards through the attached foreground stats command path instead of the daemon-start path
|
||||
- [x] #2 `subminer stats --background` and `subminer stats --stop` continue using the daemon control path
|
||||
- [x] #3 Normal stats launches do not open a browser when `stats.autoOpenBrowser` is false, and automated tests cover the launcher/runtime regressions
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add failing launcher tests first so default `stats` expects `--stats` forwarding while `--background` and `--stop` continue to expect daemon control flags.
|
||||
2. Add/adjust runtime stats command tests to prove `stats.autoOpenBrowser=false` suppresses browser opening on the normal attached stats path.
|
||||
3. Patch launcher forwarding logic in `launcher/commands/stats-command.ts` to choose foreground vs daemon flags correctly without changing cleanup handling.
|
||||
4. Run targeted launcher and stats runtime tests, then record verification results and blockers.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Confirmed root cause: launcher default `stats` flow always forwarded `--stats-daemon-start` plus `--stats-daemon-open-browser`, which detached the terminal process and bypassed `stats.autoOpenBrowser` because browser opening happened in daemon control instead of the normal stats CLI handler.
|
||||
|
||||
Updated launcher forwarding so plain `subminer stats` now uses the attached `--stats` path, while explicit `--background` and `--stop` continue using daemon control flags.
|
||||
|
||||
Added launcher regression coverage for the attached/default path and preserved background/stop expectations; added runtime coverage proving `stats.autoOpenBrowser=false` suppresses browser opening on the normal stats path.
|
||||
|
||||
Verifier passed for `launcher-plugin` and `runtime-compat` lanes. Artifact: .tmp/skill-verification/subminer-verify-20260319-131703-ZaAaUV.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Fixed `subminer stats` so the default command now forwards to the normal attached `--stats` app path instead of the daemon-start path. That keeps the foreground process attached to the terminal as expected, while `subminer stats --background` and `subminer stats --stop` still use daemon control. Because the normal stats CLI path already respects `config.stats.autoOpenBrowser`, this also fixes the unwanted browser-open behavior that previously bypassed config via `--stats-daemon-open-browser`.
|
||||
|
||||
Added launcher command and launcher integration regressions for the new forwarding behavior, plus a runtime stats CLI regression that asserts `stats.autoOpenBrowser=false` suppresses browser opening. Verification passed with targeted launcher tests, targeted runtime stats tests, and the SubMiner verifier `launcher-plugin` + `runtime-compat` lanes.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
id: TASK-178
|
||||
title: 'Address PR #19 Codex review feedback on immersion session deletion'
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-17 14:59'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- pr-review
|
||||
- immersion-tracker
|
||||
- stats
|
||||
milestone: m-1
|
||||
dependencies: []
|
||||
references:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/core/services/immersion-tracker-service.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/core/services/immersion-tracker/query.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/core/services/immersion-tracker-service.test.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/core/services/immersion-tracker/__tests__/query.test.ts
|
||||
priority: medium
|
||||
ordinal: 113500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Assess the open Codex review items on PR #19 and fix verified deletion-path regressions in immersion tracking so dashboard deletes cannot corrupt tracker state or leave stale aggregate stats.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Deleting the active immersion session is rejected safely and does not leave the tracker in a flush-failure loop
|
||||
- [x] #2 Deleting sessions rebuilds or updates vocabulary and kanji aggregates so stats no longer include removed session data
|
||||
- [x] #3 Regression tests cover the active-session deletion guard and aggregate cleanup after session deletion
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add failing regression tests for deleting the active session through ImmersionTrackerService and for deleteSession/deleteSessions keeping imm_words and imm_kanji aggregates in sync after rows are removed.
|
||||
2. Verify the failures are caused by the current deletion path, then patch the service guard and query-layer aggregate maintenance with the smallest safe change.
|
||||
3. Re-run focused tests for the touched files, then run SubMiner verification lanes appropriate for core/runtime-compat changes and record results.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Verified Codex PR #19 findings against current code: active-session/video deletes could orphan the live tracker session, and deleteSession/deleteSessions/deleteVideo left imm_words/imm_kanji aggregates stale after subtitle-line removal.
|
||||
|
||||
Implemented service guards that ignore deletes targeting the active session or active video and log a warning instead of deleting live tracker rows.
|
||||
|
||||
Updated query-layer delete helpers to capture affected word/kanji ids before deletion, remove session/video rows in a transaction, then recompute surviving imm_words/imm_kanji frequency and first/last-seen values from remaining subtitle-line occurrences, deleting orphan aggregate rows when no occurrences remain.
|
||||
|
||||
Focused verification passed: bun test src/core/services/immersion-tracker-service.test.ts and bun test src/core/services/immersion-tracker/__tests__/query.test.ts.
|
||||
|
||||
SubMiner verifier: classify_subminer_diff.sh selected lane core; verify_subminer_change.sh passed typecheck and failed on unrelated existing launcher test `stats command tolerates slower dashboard startup before timing out` in launcher/main.test.ts (timeout waiting for dashboard startup response).
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Assessed the open Codex PR #19 review items on immersion deletion paths and fixed the confirmed regressions. ImmersionTrackerService now ignores delete requests that target the currently active session or its active video, preventing the dashboard from deleting the live parent rows that subsequent telemetry/event flushes still depend on. On the query side, session/video deletion now captures affected vocabulary and kanji aggregate ids before removing subtitle/session rows, then recomputes imm_words and imm_kanji frequency plus first/last seen timestamps from surviving line occurrences inside the same transaction, deleting orphan aggregate rows when no occurrences remain.
|
||||
|
||||
Regression coverage was added for active-session delete protection, active-video delete protection, and aggregate rebuild after session deletion. Focused verification passed with `bun test src/core/services/immersion-tracker-service.test.ts` and `bun test src/core/services/immersion-tracker/__tests__/query.test.ts`. Repo-native verification selected the `core` lane; `bun run typecheck` passed, while `bun run test:fast` failed in an unrelated launcher test (`launcher/main.test.ts`: `stats command tolerates slower dashboard startup before timing out`) that times out waiting for dashboard startup response.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
id: TASK-179
|
||||
title: Tune immersion tracker SQLite pragmas and maintenance defaults
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-17 15:15'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- sqlite
|
||||
- immersion-tracking
|
||||
- performance
|
||||
dependencies: []
|
||||
documentation:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/docs/plans/2026-03-17-sqlite-tuning.md
|
||||
priority: medium
|
||||
ordinal: 111500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Apply low-risk SQLite tuning improvements for the immersion tracker: add modern recommended maintenance/tuning pragmas where appropriate, cover them with regression tests, and update user-facing docs to reflect the actual tuning policy. Scope limited to low-risk local-DB changes already discussed: keep WAL + synchronous=NORMAL, add optimize path, consider WAL growth control, and document workload-dependent knobs left at defaults.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Immersion tracker applies the agreed low-risk SQLite tuning changes without regressing current behavior
|
||||
- [x] #2 Regression tests cover the new pragma/maintenance behavior
|
||||
- [x] #3 Immersion tracking docs describe the tuning policy and notable defaults left unchanged
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add regression coverage for connection pragmas and verify the new WAL growth cap fails before implementation.
|
||||
2. Add regression coverage for maintenance-time PRAGMA optimize and verify the test fails before implementation.
|
||||
3. Implement the minimal SQLite tuning changes.
|
||||
4. Update immersion-tracking docs for the new tuning policy.
|
||||
5. Run targeted SQLite verification lanes and record results.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Verification: `bun test src/core/services/immersion-tracker/storage-session.test.ts src/core/services/immersion-tracker/maintenance.test.ts` passed (15 tests).
|
||||
|
||||
Verification: `bun run test:immersion:sqlite:src` passed (37 tests).
|
||||
|
||||
Verification: `bun run typecheck`, `bun run docs:test`, `bun run docs:build`, `bun run test:fast`, `bun run test:env`, and `bun run build` all passed.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Added low-risk SQLite tuning improvements for the immersion tracker: `journal_size_limit` now bounds WAL growth, periodic maintenance runs `PRAGMA optimize`, regression tests cover both behaviors, and the immersion-tracking docs explain the maintained pragmas plus workload-dependent defaults left unchanged.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
id: TASK-180
|
||||
title: Fix launcher stats command timeout for slow dashboard startup
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-17 15:16'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- launcher
|
||||
- stats
|
||||
- tests
|
||||
milestone: m-1
|
||||
dependencies: []
|
||||
references:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/launcher/commands/stats-command.ts
|
||||
- /Users/sudacode/projects/japanese/SubMiner/launcher/main.test.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/launcher/commands/command-modules.test.ts
|
||||
priority: medium
|
||||
ordinal: 112500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Address the failing launcher stats startup path so the CLI tolerates the intended slow dashboard startup window instead of timing out early.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 The launcher stats command no longer times out before the intended slow-start window used by tests
|
||||
- [x] #2 Regression coverage verifies the slower stats startup path succeeds
|
||||
- [x] #3 The failing launcher stats startup test passes locally
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add a focused launcher command regression that simulates a stats response arriving after the current timeout boundary and expects success.
|
||||
2. Adjust the stats startup wait timeout in launcher/commands/stats-command.ts to match the intended slow-start tolerance.
|
||||
3. Re-run the targeted command test, the previously failing launcher/main.test.ts case, and then the full launcher/main.test.ts file.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Verified the failing launcher path: launcher/main.test.ts timed out because launcher/commands/stats-command.ts only waited 8000ms for the stats startup response while the supported slow-start test writes the response after 9s.
|
||||
|
||||
Raised the stats startup response timeout to 12000ms so attached stats startup tolerates the existing slow cold-start window without changing command flow.
|
||||
|
||||
Verification passed: bun test launcher/commands/command-modules.test.ts --test-name-pattern "stats command launches attached app command with response path|stats command returns after startup response even if app process stays running|stats command throws when stats response reports an error"; bun test launcher/main.test.ts --test-name-pattern "stats command tolerates slower dashboard startup before timing out"; bun test launcher/main.test.ts; bun run test:fast.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Fixed the launcher stats startup timeout by extending the response-file wait window in launcher/commands/stats-command.ts from 8s to 12s. The command flow was left unchanged; the launcher now simply gives the stats dashboard enough time to report readiness during slower cold starts, which matches the existing supported behavior exercised by launcher/main.test.ts.
|
||||
|
||||
Verification passed with the targeted launcher command tests, the previously failing slow-start launcher/main.test.ts case, the full launcher/main.test.ts file, and the full `bun run test:fast` gate.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
id: TASK-181
|
||||
title: Add background-managed stats server lifecycle commands
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-17 15:31'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- cli
|
||||
- launcher
|
||||
- stats
|
||||
milestone: m-1
|
||||
dependencies: []
|
||||
priority: medium
|
||||
ordinal: 110500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Add a dedicated background stats server mode that can be started and stopped from the launcher without blocking normal SubMiner instances. Launcher UX: `subminer stats -b` starts the stats server in the background, `subminer stats -s` stops the background stats server only, and plain `subminer stats` preserves the existing foreground/open-browser flow.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 `subminer stats -b` starts a background stats server without blocking other SubMiner instances.
|
||||
- [x] #2 `subminer stats -s` stops only the background stats server and succeeds cleanly when state is stale.
|
||||
- [x] #3 Plain `subminer stats` preserves current dashboard-open behavior.
|
||||
- [x] #4 Automated tests cover launcher parsing/dispatch and app-side start-stop lifecycle behavior.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Extend launcher stats parsing so `subminer stats -b` maps to background-start and `subminer stats -s` maps to stop-only while preserving existing cleanup/rebuild parsing.
|
||||
2. Add launcher execution branches: detached background start with startup acknowledgement wait, stop command forwarding with response wait, and preserve existing attached foreground behavior for plain `stats` and cleanup flows.
|
||||
3. Extend app CLI args and stats command handler for background start/stop lifecycle responses, including already-running and stale-state handling.
|
||||
4. Add a dedicated stats-daemon runtime/state-file path in the app and bypass the normal single-instance lock only for that mode.
|
||||
5. Verify with focused tests first, then launcher/env lane, and update task acceptance criteria/final summary before handoff.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
User approved option 2 design: dedicated app-side stats daemon, `subminer stats -b` to start, `subminer stats -s` to stop server only.
|
||||
|
||||
Implemented launcher `stats -b` and `stats -s` flows plus app-side `--stats-background` / `--stats-stop` handling.
|
||||
|
||||
Added background stats daemon state-file management and remote-daemon reuse so normal SubMiner instances do not try to bind a second stats server when the daemon is already running.
|
||||
|
||||
Verification: `bun test launcher/main.test.ts launcher/commands/command-modules.test.ts launcher/parse-args.test.ts src/main/runtime/stats-cli-command.test.ts src/main/early-single-instance.test.ts`, `bun run typecheck`, `bun run test:env`, `bun run test:fast`, `bun run build`, `bun run test:smoke:dist`, `bun run docs:test`, `bun run docs:build`, `bun run changelog:lint`.
|
||||
|
||||
Non-blocking note: `bun run test:launcher` still showed unrelated existing failures in `launcher/picker.test.ts` and an intermittent `launcher/smoke.e2e.test.ts` mpv-status check on this machine; the narrowed launcher suites covering the changed stats paths passed.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Added a dedicated background stats-daemon lifecycle for the launcher and app runtime. `subminer stats -b` now starts or reuses a detached stats server and returns after startup acknowledgement, while `subminer stats -s` stops that daemon without touching browser tabs. On the app side, new stats background/stop CLI flags bypass the normal single-instance lock only for daemon helper processes, write/read a daemon state file under user data, and reuse an already-running daemon instead of attempting a second local stats bind when another SubMiner instance needs stats access. Updated docs-site stats docs, added a changelog fragment, and covered the new flows with launcher parse/dispatch tests, app stats CLI handler tests, and single-instance bypass tests. Verification run: `bun run typecheck`, `bun run test:env`, `bun run test:fast`, `bun run build`, `bun run test:smoke:dist`, `bun run docs:test`, `bun run docs:build`, `bun run changelog:lint`, plus narrowed changed-path launcher/app test bundles.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
id: TASK-182
|
||||
title: Fix session stats chart known-word totals exceeding total words
|
||||
status: Done
|
||||
milestone: m-1
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-17 16:07'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels: []
|
||||
dependencies: []
|
||||
references:
|
||||
- /Users/sudacode/projects/japanese/SubMiner/src/core/services/stats-server.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/sessions/SessionDetail.tsx
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/core/services/__tests__/stats-server.test.ts
|
||||
- /Users/sudacode/projects/japanese/SubMiner/stats/src/hooks/useSessions.ts
|
||||
ordinal: 109500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Fix the session detail stats display so the known-word series cannot exceed the total-word series for the same sample. Ground the fix in the actual immersion-tracker metrics used by the stats UI and cover the regression with automated tests.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Session detail data uses a consistent cumulative word metric so known-word counts do not exceed total words for a sample
|
||||
- [x] #2 Automated tests cover the session known-word timeline contract and reproduce the regression scenario
|
||||
- [x] #3 Session stats UI still renders the timeline and tooltip values correctly after the fix
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add a regression test for `/api/stats/sessions/:id/known-words-timeline` covering a Japanese-style session where telemetry word counts can be lower than token-derived known-word counts.
|
||||
2. Update the stats known-word timeline contract/server implementation so the series is expressed in the same cumulative unit used for total words in the session detail view.
|
||||
3. Adjust the session detail UI/types to consume the corrected series and keep tooltip/legend copy coherent.
|
||||
4. Run targeted tests for stats server and stats UI transforms, then summarize any wider verification skipped.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Implemented server-side known-word timeline fix to preserve stored line positions and accumulate known-word occurrences rather than compressed unique-headword counts.
|
||||
|
||||
Updated session-facing stats views to prefer `tokensSeen` over `wordsSeen` when available so displayed session word totals align with the session chart and lookup-rate denominator.
|
||||
|
||||
Verification: `bun test src/core/services/__tests__/stats-server.test.ts`, `bun test stats/src/lib/yomitan-lookup.test.tsx`, `bun test src/core/services/immersion-tracker/__tests__/query.test.ts`, `bun run typecheck` all passed.
|
||||
|
||||
Verification skipped/blocker: `bun run typecheck:stats` still fails in pre-existing unrelated files `stats/src/components/anime/AnilistSelector.tsx`, `stats/src/lib/reading-utils.test.ts`, and `stats/src/lib/reading-utils.ts`.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Fixed the session stats mismatch that let known words outrun total words. The stats server now preserves actual subtitle-line positions and accumulates known-word occurrences for the session timeline, while session-facing stats views prefer token-based word totals when available. Added regression coverage for the known-word timeline API and for session-row word-count rendering, plus a user-visible changelog fragment.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
id: TASK-182.1
|
||||
title: Remove misleading session new-word metric from session detail chart
|
||||
status: Done
|
||||
assignee:
|
||||
- '@codex'
|
||||
created_date: '2026-03-18 01:41'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- bug
|
||||
- stats
|
||||
- ui
|
||||
milestone: m-1
|
||||
dependencies: []
|
||||
references:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/sessions/SessionDetail.tsx
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/sessions/SessionsTab.tsx
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/lib/media-session-list.test.tsx
|
||||
parent_task_id: TASK-182
|
||||
ordinal: 101500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Remove the misleading `New words` series from the session detail chart so the stats UI no longer presents a fabricated metric that mirrors total words. Keep the session chart focused on the real cumulative totals already backed by tracker data.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Expanded session detail chart no longer renders or labels a `New words` metric in the graph, tooltip, or legend
|
||||
- [x] #2 Session detail still renders total-word and known-word series correctly after the metric removal
|
||||
- [x] #3 Automated frontend coverage prevents the `New words` label from reappearing in expanded session detail
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add a focused stats frontend regression test that renders expanded session detail and asserts the misleading `New words` label is absent while `Total words` remains.
|
||||
2. Remove the fabricated `New words` area series, tooltip mapping, legend chip, and now-unused left-axis chart plumbing from `stats/src/components/sessions/SessionDetail.tsx`.
|
||||
3. Add a user-visible changelog fragment describing the session chart cleanup.
|
||||
4. Run targeted frontend tests plus cheap verification and record any blockers.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Added a focused server-render regression test for SessionDetail copy to ensure the misleading `New words` label stays removed.
|
||||
|
||||
Removed the fabricated `New words` chart series and its legend/tooltip plumbing from the expanded session detail view.
|
||||
|
||||
Verification: `bun test stats/src/lib/session-detail.test.tsx stats/src/lib/media-session-list.test.tsx` passed. `bash .agents/skills/subminer-change-verification/scripts/verify_subminer_change.sh --lane core stats/src/components/sessions/SessionDetail.tsx stats/src/lib/session-detail.test.tsx changes/2026-03-18-remove-session-new-words-series.md` passed and wrote artifacts under `.tmp/skill-verification/subminer-verify-20260317-184440-1aMWkM`.
|
||||
|
||||
Manual spot-check note: `bun test stats/src/lib/yomitan-lookup.test.tsx` is currently red on a pre-existing `AnimeOverviewStats` lookup-rate assertion unrelated to this session-detail change.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Removed the misleading `New words` metric from expanded session charts. Session detail now shows only the real total-word and known-word lines, backed by existing tracker data, with regression coverage that prevents the `New words` label from reappearing.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
id: TASK-182.2
|
||||
title: Improve session detail known-word chart scaling
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-19 20:31'
|
||||
updated_date: '2026-03-19 20:52'
|
||||
labels:
|
||||
- bug
|
||||
- stats
|
||||
- ui
|
||||
dependencies: []
|
||||
references:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/sessions/SessionDetail.tsx
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/lib/session-detail.test.tsx
|
||||
parent_task_id: TASK-182
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Adjust the expanded session-detail known-word percentage chart so the vertical range reflects the session's actual percent range instead of always spanning 0-100. Keep the chart easier to read while preserving the percent-based tooltip/legend behavior already used in the stats UI.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Expanded session detail scales the known/unknown percent chart to the session's observed percent range instead of hard-coding a 0-100 top bound
|
||||
- [x] #2 The chart keeps a small headroom above the highest observed known-word percent so the line remains visually readable near the top edge
|
||||
- [x] #3 Automated frontend coverage locks the new percent-domain behavior and preserves existing session-detail rendering
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add a focused frontend regression test for the session-detail ratio chart domain calculation, covering a session whose known-word percentage stays in a narrow band below 100% and expecting a dynamic top bound with headroom.
|
||||
2. Update `stats/src/components/sessions/SessionDetail.tsx` to compute a dynamic percent-axis domain and matching ticks for the ratio chart, keeping the lower bound at 0%, adding modest padding above the highest known percentage, rounding to clean tick steps, and capping at 100%.
|
||||
3. Apply the computed percent-axis bounds consistently to the right-side Y axis and the session chart pause overlays so the visual framing stays aligned.
|
||||
4. Run targeted frontend tests and the SubMiner verification helper on the touched files, then record results and any blockers in the task.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Implemented dynamic known-percentage axis scaling in `stats/src/components/sessions/SessionDetail.tsx`: the ratio chart now keeps a 0% floor, uses the highest observed known percentage plus 5 points of headroom for the top bound, rounds that bound up to clean 10-point ticks, caps at 100%, and enables `allowDataOverflow` so the stacked area chart actually honors the tighter domain.
|
||||
|
||||
Added frontend regression coverage in `stats/src/lib/session-detail.test.tsx` for the axis-max helper, covering both a narrow-band session and near-100% cap behavior.
|
||||
|
||||
Added user-visible changelog fragment `changes/2026-03-19-session-detail-chart-scaling.md`.
|
||||
|
||||
Verification: `bun test stats/src/lib/session-detail.test.tsx` passed; `bun run typecheck` passed; `bun run changelog:lint` passed; `bash .agents/skills/subminer-change-verification/scripts/verify_subminer_change.sh --lane core stats/src/components/sessions/SessionDetail.tsx stats/src/lib/session-detail.test.tsx` ran and passed `typecheck` but failed `bun run test:fast` on a pre-existing unrelated issue in `scripts/update-aur-package.test.ts` / `scripts/update-aur-package.sh` (`mapfile: command not found`). Artifacts: `.tmp/skill-verification/subminer-verify-20260319-134440-JRHAUJ`.
|
||||
|
||||
Docs decision: no internal docs update required; the behavior change is localized UI presentation with no API/workflow change. Changelog decision: yes, required and completed because the fix is user-visible.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Improved expanded session-detail chart readability by replacing the fixed 0-100 known-word percentage axis with a dynamic top bound based on the session’s highest observed known percentage plus modest headroom, rounded to clean ticks and capped at 100%. The ratio chart now also enables `allowDataOverflow` so Recharts preserves the tighter percent domain even though the stacked known/unknown areas sum to 100%.
|
||||
|
||||
Added frontend regression coverage for the new axis-max behavior and a changelog fragment for the user-visible stats fix.
|
||||
|
||||
Verification: `bun test stats/src/lib/session-detail.test.tsx`, `bun run typecheck`, and `bun run changelog:lint` passed. The SubMiner verification helper’s `core` lane also passed `typecheck`, but `bun run test:fast` remains red on a pre-existing unrelated bash-compat failure in `scripts/update-aur-package.test.ts` / `scripts/update-aur-package.sh` (`mapfile: command not found`).
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
id: TASK-183
|
||||
title: Fix blank stats vocabulary page regression
|
||||
status: Done
|
||||
milestone: m-1
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-17 16:23'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels: []
|
||||
dependencies: []
|
||||
references:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/vocabulary/VocabularyTab.tsx
|
||||
- /Users/sudacode/projects/japanese/SubMiner/stats/src/App.tsx
|
||||
- /Users/sudacode/projects/japanese/SubMiner/stats/src/lib/api-client.ts
|
||||
ordinal: 108500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Diagnose and fix the stats dashboard regression where the Vocabulary tab renders blank at runtime. Capture the frontend failure with browser debugging, add regression coverage, and restore the vocabulary view.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Vocabulary tab renders without a blank-screen failure in the stats dashboard
|
||||
- [x] #2 Automated test coverage reproduces the failing code path and passes with the fix
|
||||
- [x] #3 Targeted verification covers the affected stats UI/runtime path
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Reproduce the blank Vocabulary tab locally with a browser-visible stats UI instance and capture console/network failure details.
|
||||
2. Add a focused regression test for the failing Vocabulary tab code path before editing production code.
|
||||
3. Implement the minimal fix in the stats UI/runtime path.
|
||||
4. Re-run targeted browser and automated verification, then record any skipped broader checks.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Identified the runtime failure in the browser console: React reported a hook-order change in `VocabularyTab` after the tab moved from loading to loaded state (`Rendered more hooks than during the previous render`).
|
||||
|
||||
Fixed `stats/src/components/vocabulary/VocabularyTab.tsx` by removing the late `useMemo` hook and computing `knownWordCount` as a plain derived value after the loading/error guards.
|
||||
|
||||
Added regression coverage in `stats/src/lib/vocabulary-tab.test.ts` to assert that `VocabularyTab` declares all hooks before the loading/error early returns.
|
||||
|
||||
Verification: `bun test stats/src/lib/vocabulary-tab.test.ts`, `bun test stats/src/lib/yomitan-lookup.test.tsx`, `bun run build:stats`, and a live Playwright check against the Vite app with stubbed stats API data all passed.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Fixed the blank Vocabulary tab regression in the stats UI. The root cause was a late `useMemo` hook declared after the loading/error early returns in `VocabularyTab`, which caused React to crash once vocabulary data finished loading. Removed that late hook, added a regression test guarding hook placement, verified the stats bundle builds, and confirmed in a live browser that the Vocabulary tab now renders loaded content instead of white-screening.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
id: TASK-184
|
||||
title: Stabilize branch verification gate
|
||||
status: Done
|
||||
assignee:
|
||||
- Codex
|
||||
created_date: '2026-03-17 19:28'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- stabilization
|
||||
- ci
|
||||
dependencies: []
|
||||
references:
|
||||
- package.json
|
||||
- docs/workflow/verification.md
|
||||
priority: medium
|
||||
ordinal: 106500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Bring the current PR branch back to a green verification state by fixing any failing lint/format or test checks required for local handoff.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Repo source formatting checks pass for the current branch.
|
||||
- [x] #2 Required local verification checks for this branch pass without introducing new failures.
|
||||
- [x] #3 Any code or test adjustments stay scoped to the failing checks and preserve existing branch behavior.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Fix the current source-formatting failures reported by `bun run format:check:src` using the minimal repo-standard Prettier output.
|
||||
2. Re-run `bun run format:check:src` to confirm the lint/format gate is green.
|
||||
3. Re-run the default handoff gate from `docs/workflow/verification.md`: `bun run typecheck`, `bun run test:fast`, `bun run test:env`, `bun run build`, and `bun run test:smoke:dist`.
|
||||
4. Because `docs-site/` is modified on this branch, also run `bun run docs:test` and `bun run docs:build`.
|
||||
5. If any verification step fails after formatting, fix only the blocking issue and re-run the relevant lane until green.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Initial gate snapshot before edits: `typecheck`, `test:fast`, `test:env`, `build`, and `test:smoke:dist` passed; `format:check:src` failed on 15 files.
|
||||
|
||||
Applied repo-standard Prettier formatting to the 15 files reported by `bun run format:check:src`; no additional logic changes were introduced in this stabilization pass.
|
||||
|
||||
Verification after formatting: `bun run format:check:src` passed; `bash .agents/skills/subminer-change-verification/scripts/verify_subminer_change.sh --lane core --lane runtime-compat --lane docs` passed with artifacts under `.tmp/skill-verification/subminer-verify-20260317-122947-hEInF0`; `bun run test:env` passed separately.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Branch verification gate is green again. Fixed the only failing local gate by applying Prettier formatting to the 15 flagged source files, then re-ran the required verification lanes: source format check, core lane (`typecheck` + `test:fast`), runtime-compat lane (`build`, `test:runtime:compat`, `test:smoke:dist`), docs lane (`docs:test`, `docs:build`), and `test:env`. All passed.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
id: TASK-185
|
||||
title: Clarify library stats word-count labels
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-17 22:58'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- bug
|
||||
- stats
|
||||
- ui
|
||||
milestone: m-1
|
||||
dependencies: []
|
||||
references:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/library/MediaHeader.tsx
|
||||
- /Users/sudacode/projects/japanese/SubMiner/src/core/services/stats-server.ts
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/src/core/services/immersion-tracker/query.ts
|
||||
priority: medium
|
||||
ordinal: 104500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Fix the library/media detail stats header so occurrence-based subtitle counts are not presented as unique-word vocabulary totals. The UI should clearly distinguish subtitle word occurrences from unique known-word headword coverage to avoid misleading comparisons.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Library/media detail view labels subtitle occurrence totals with wording that does not imply unique vocabulary counts
|
||||
- [x] #2 Known-words summary in the same view explicitly communicates that its denominator is unique words/headwords
|
||||
- [x] #3 Frontend tests cover the updated copy so the mismatch does not regress
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add a focused stats frontend test for MediaHeader copy that distinguishes occurrence totals from unique known-word coverage.
|
||||
2. Update MediaHeader labels so occurrence-based totals no longer imply unique vocabulary counts.
|
||||
3. Update the known-words label copy to explicitly state it is based on unique words/headwords.
|
||||
4. Run targeted stats tests and record results.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Root cause confirmed: library header compares occurrence-based totalWordsSeen against unique-headword known-words summary. Awaiting plan approval before code changes.
|
||||
|
||||
Updated library header copy to label totalWordsSeen as word occurrences and known-word coverage as known unique words. Added an optional initialKnownWordsSummary prop to support deterministic server-render tests without changing runtime behavior.
|
||||
|
||||
Verification: `bun test stats/src/lib/yomitan-lookup.test.tsx` passes. `bun run typecheck:stats` remains blocked by preexisting unrelated errors in stats/src/components/anime/AnilistSelector.tsx, stats/src/lib/reading-utils.ts, stats/src/lib/reading-utils.test.ts, and stats/src/lib/vocabulary-tab.test.ts.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Clarified the library/media header so occurrence-based subtitle counts are no longer presented as if they were unique vocabulary totals. The header now labels `totalWordsSeen` as `word occurrences`, and the known-words summary explicitly says `known unique words`, which matches the backend's DISTINCT headword calculation.
|
||||
|
||||
For regression coverage, added a focused MediaHeader render test that exercises the exact mismatch case (30 occurrences vs 34 unique words) and verifies the new copy. Also updated one stale AnimeOverviewStats assertion in the same targeted test file so the focused stats test lane is green.
|
||||
|
||||
Tests run:
|
||||
- `bun test stats/src/lib/yomitan-lookup.test.tsx` ✅
|
||||
- `bun run typecheck:stats` ⚠️ blocked by preexisting unrelated errors in AnilistSelector and reading-utils/vocabulary-tab stats files.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
id: TASK-186
|
||||
title: Remove stats Library tab and add episode detail navigation from anime page
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-17 23:19'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- stats
|
||||
- ui
|
||||
milestone: m-1
|
||||
dependencies: []
|
||||
references:
|
||||
- /Users/sudacode/projects/japanese/SubMiner/stats/src/App.tsx
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/layout/TabBar.tsx
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/anime/AnimeDetailView.tsx
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/anime/EpisodeList.tsx
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/library/MediaDetailView.tsx
|
||||
priority: medium
|
||||
ordinal: 103500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Update the stats UI so watched-file detail is no longer exposed as a top-level Library tab. Users should open dedicated episode detail pages from the anime detail page while preserving inline quick-peek session expansion.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Stats navigation no longer shows a top-level Library tab.
|
||||
- [x] #2 Anime episode rows keep inline quick-peek expansion and also expose an explicit control to open the dedicated episode detail page.
|
||||
- [x] #3 Dedicated episode detail navigation lands on the existing watched-file detail view with a back action that returns to the originating anime detail page.
|
||||
- [x] #4 Relevant stats component tests cover the new navigation flow and removed tab behavior.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add app-level stats navigation state for dedicated media detail so anime flows can open watched-file detail without a Library tab.
|
||||
2. Remove the Library tab from the tab bar and top-level tab panels while preserving existing Overview/Anime/Trends/Vocabulary/Sessions behavior.
|
||||
3. Update anime detail episode list to keep row expansion for quick peek and add an explicit button that opens the dedicated detail view for the selected episode.
|
||||
4. Reuse MediaDetailView for episode detail and adjust its back action to return to the originating anime detail page.
|
||||
5. Add or update stats component tests to cover the removed Library tab and the new anime-to-episode-detail navigation flow.
|
||||
6. Run targeted stats tests, then targeted SubMiner verification lanes if needed for touched files.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Implemented app-level stats navigation state for dedicated media detail and removed the Library tab from the tab bar and top-level panels.
|
||||
|
||||
Anime episode rows now keep inline quick-peek expansion and expose a visible Details button that opens the dedicated watched-file detail view.
|
||||
|
||||
Reused MediaDetailView for anime-origin episode navigation with a Back to Anime label and app-level return path.
|
||||
|
||||
Verification: bun test stats/src/lib/stats-navigation.test.ts stats/src/lib/stats-ui-navigation.test.tsx; bun run build:stats; bash .agents/skills/subminer-change-verification/scripts/verify_subminer_change.sh --lane core ... => passed.
|
||||
|
||||
Observed unrelated existing stats workspace issues outside this task when running bun run typecheck:stats, including AnilistSelector/reading-utils/vocabulary-tab and an outdated AnimeOverviewStats test signature.
|
||||
|
||||
Reopened for bugfix: episode Details button is a no-op when anime detail is open from within AnimeTab because app-level selectedAnimeId is not retained there. Follow-up fix will pass animeId explicitly through the callback chain instead of depending on App route state.
|
||||
|
||||
Bugfix: the Details button now passes animeId explicitly from AnimeTab/AnimeDetailView into app-level media-detail navigation, so dedicated episode navigation works even when the anime page was opened from within the tab rather than seeded by App state.
|
||||
|
||||
Bugfix verification: bun test stats/src/lib/stats-navigation.test.ts stats/src/lib/stats-ui-navigation.test.tsx; bun run build:stats => passed.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Removed the stats Library tab and replaced that navigation path with app-level dedicated media-detail routing from the anime page. Episode rows still support inline quick peek, and now also provide a Details button that opens the dedicated episode view and returns cleanly to the anime detail page. Added navigation-focused tests for the removed tab and anime-origin media-detail flow, and verified the change with targeted tests, stats bundle build, and the repo core verification lane.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,81 @@
|
||||
---
|
||||
id: TASK-187
|
||||
title: Replace episode detail session history with expandable inline session details
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-17 23:42'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- stats
|
||||
- ui
|
||||
milestone: m-1
|
||||
dependencies: []
|
||||
references:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/library/MediaDetailView.tsx
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/library/MediaSessionList.tsx
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/sessions/SessionRow.tsx
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/sessions/SessionDetail.tsx
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/sessions/SessionsTab.tsx
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/overview/OverviewTab.tsx
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/stats/src/components/overview/RecentSessions.tsx
|
||||
documentation:
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/docs/plans/2026-03-17-episode-detail-session-accordion-design.md
|
||||
- >-
|
||||
/Users/sudacode/projects/japanese/SubMiner/docs/plans/2026-03-17-episode-detail-session-accordion.md
|
||||
priority: medium
|
||||
ordinal: 102500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Update the dedicated episode detail page so its session history uses the same expandable session-row behavior as the Sessions page, including inline timeline details and session deletion, instead of navigating away to the Sessions tab. Also update home-page session navigation so recent session links open the associated episode detail page rather than the Sessions tab.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Dedicated episode detail session history uses expandable inline rows styled like the Sessions page instead of linking to the Sessions tab.
|
||||
- [x] #2 Expanding a session on the episode detail page shows the full existing session detail panel, including the timeline chart and stats.
|
||||
- [x] #3 Episode detail session rows retain a session delete control with the same behavior and safeguards as the Sessions page.
|
||||
- [x] #4 Home-page recent session navigation opens the associated episode detail page when a session is tied to a video, instead of routing to the Sessions tab.
|
||||
- [x] #5 Relevant stats tests cover the inline session expansion/delete behavior and the updated home-page navigation path.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add failing tests for media-detail session accordion structure and for overview-to-media-detail navigation, keeping orphan-session fallback coverage.
|
||||
2. Rework MediaSessionList to reuse SessionRow and SessionDetail with local expansion state and delete affordance matching the Sessions page.
|
||||
3. Move media-detail session mutation/delete ownership into MediaDetailView so deletes update the current episode page immediately.
|
||||
4. Add app-level direct media-detail navigation from overview/home-page session rows when videoId exists; keep Sessions-tab fallback for sessions without videoId.
|
||||
5. Run targeted tests, stats build, and the SubMiner core verification lane; then update TASK-187 with results.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Added approved design/plan docs at docs/plans/2026-03-17-episode-detail-session-accordion-design.md and docs/plans/2026-03-17-episode-detail-session-accordion.md before implementation.
|
||||
|
||||
MediaDetailView now owns local session state and delete handling, derives displayed media aggregates from the current session list, and renders MediaSessionList as an inline accordion instead of a session-page link list.
|
||||
|
||||
MediaSessionList now reuses SessionRow and full SessionDetail so episode-level session history matches Sessions-page dropdown behavior and keeps the same delete affordance.
|
||||
|
||||
Overview/home-page recent session navigation now prefers dedicated media detail when session.videoId exists and falls back to the Sessions tab only for orphan sessions without videoId.
|
||||
|
||||
Verification passed: bun test stats/src/lib/stats-navigation.test.ts stats/src/lib/stats-ui-navigation.test.tsx stats/src/lib/media-session-list.test.tsx; bun run build:stats; bash .agents/skills/subminer-change-verification/scripts/verify_subminer_change.sh --lane core stats/src/App.tsx stats/src/components/overview/OverviewTab.tsx stats/src/components/overview/RecentSessions.tsx stats/src/components/library/MediaDetailView.tsx stats/src/components/library/MediaSessionList.tsx stats/src/lib/stats-navigation.ts stats/src/lib/stats-navigation.test.ts stats/src/lib/stats-ui-navigation.test.tsx stats/src/lib/media-session-list.test.tsx => passed.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Dedicated episode detail pages now show inline expandable session rows using the same shared SessionRow + SessionDetail UI as the Sessions page, including per-session delete controls. Overview/home-page recent session clicks now open the episode detail page whenever a backing video exists, with Sessions-tab fallback only for sessions missing videoId. Added navigation and media-session-list tests plus design/implementation docs, and verified the change with targeted tests, stats bundle build, and the SubMiner core verification lane.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
id: TASK-187.1
|
||||
title: Auto-expand targeted session when opening media detail
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-03-18 01:32'
|
||||
updated_date: '2026-03-18 05:28'
|
||||
labels:
|
||||
- stats
|
||||
- ui
|
||||
milestone: m-1
|
||||
dependencies: []
|
||||
references:
|
||||
- stats/src/lib/stats-navigation.ts
|
||||
- stats/src/App.tsx
|
||||
- stats/src/components/overview/RecentSessions.tsx
|
||||
- stats/src/components/library/MediaDetailView.tsx
|
||||
- stats/src/components/library/MediaSessionList.tsx
|
||||
- stats/src/lib/stats-navigation.test.ts
|
||||
parent_task_id: TASK-187
|
||||
priority: medium
|
||||
ordinal: 117500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
When a navigation path opens episode/media detail with a known session ID, the matching session row in media detail should auto-expand so the user lands directly on the intended session details instead of only the episode history page.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Media detail navigation state can carry an optional target session ID alongside the selected video.
|
||||
- [x] #2 Any navigation path that opens media detail with a known session ID causes that session row to auto-expand when the episode history loads.
|
||||
- [x] #3 Session-tab fallback for orphan sessions without a video still behaves as it does now.
|
||||
- [x] #4 Media detail auto-expansion clears or stabilizes its one-shot navigation state so normal manual expand/collapse behavior still works after landing.
|
||||
- [x] #5 Relevant navigation/component tests cover the targeted media-detail auto-expand behavior.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Extend media-detail navigation state to optionally carry a target session ID while preserving the existing orphan-session fallback to the Sessions tab.
|
||||
2. Update app-level navigation helpers and overview recent-session click handling to pass session IDs into media-detail navigation whenever both video and session are known.
|
||||
3. Thread the one-shot target session ID into MediaDetailView and MediaSessionList so the matching accordion row auto-expands on load, then clear/stabilize that state so manual toggling still behaves normally.
|
||||
4. Update targeted stats navigation/component tests to cover media-detail auto-expansion and fallback behavior.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Extended media-detail navigation state to carry an optional `initialSessionId`, updated overview/app navigation to pass session IDs into media detail whenever a video-backed session is clicked, and wired `MediaDetailView` + `MediaSessionList` to auto-expand and then consume that one-shot session target.
|
||||
|
||||
Updated `stats-navigation.test.ts` to cover the new navigation-state shape. Validation not run in this pass, so acceptance criteria remain unchecked pending verification.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user