Storing the season 1 artwork left a cover row with a blob but no AniList id,
which fetchIfMissing's `existing.coverBlob` early return serves forever. The
video's metadata would then stay null permanently, even after AniList published
the sequel relation, because the lookup was never reached again. The existing
no-match retry window did not apply since it requires a null coverUrl.
Cache a plain no-match instead, so the unresolved season reuses NO_MATCH_RETRY_MS
and recovers on its own once the relation exists.
Two cases where an unresolved season still produced a confident wrong answer:
- Cover art warned but then wrote the season 1 anilistId and episodesTotal via
upsertCoverArt/updateAnimeAnilistInfo. Since a cached coverBlob short-circuits
the next call, that metadata never re-resolved. Keep the artwork as a stand-in
but withhold the id, titles and episode count when the season is unresolved.
- pickByAirOrder sorted entries with no air year last, shifting every later
season by one while still reporting seasonResolved. Decline instead when any
franchise entry lacks a year.
A well-formed search returning zero media is deterministic for that title, so
the retry queue just burns rate limit against it. Transient failures (network,
GraphQL errors, malformed data) throw inside the query executor and are still
caught as retryable, so only genuine no-matches become non-retryable.
- Add season-resolver: search base title, walk AniList SEQUEL relations (falling back to air-date ordering) to reach the requested season, since AniList has no numbered-season entries
- Stop writing progress to the season 1 entry when the season can't be resolved; skip the update and point at a manual override instead
- Scope character dictionary AniList overrides by detected season as well as directory, and let an override pin the media id used for watch-progress updates too
- Reuse the season resolver for cover art lookup so per-season art doesn't fall back to season 1
- Don't cache an unresolved season as a match, so the fallback can't stick for later episodes
- Update docs and changelog entry for the fix
- Add formatRofiPrompt to trim trailing whitespace and append a single space, keeping the prompt from running into the input field
- Apply it across all rofi -p usages in picker.ts and history-command.ts
- Add tests for formatRofiPrompt edge cases (empty/whitespace-only prompts)
- Extract buildHistoryEntryActions to build the series action menu, now including a previous-episode option alongside replay/next/browse/quit
- Update docs and changelog entry to describe the new option
- Add tests covering previous/replay/next ordering and omission when last watched file is missing
- AnkiConnect proxy now detects EADDRINUSE, logs a warning, and surfaces an overlay notification instead of crashing video startup
- Background AppImage bootstrap runs Chromium with in-process-gpu so no GPU child survives app.exit() and outlives the FUSE mount, fixing the remaining DrKonqi "Service Crash" case
- Add changelog fragment for the proxy fix; update the AppImage quit fragment with the GPU child root cause
- Merge the five separate sync change fragments (launcher command, UI window, close/quit fixes, active-session double-count, monthly rollup timezone) into a single changes/sync.md
- Fold kana-pos-content-classification.md into annotation-noise-rule-table.md
- Drop the now-stale Unreleased sections from CHANGELOG.md and docs-site/changelog.md
- Tweak tsukihime-english-subtitles.md wording
- Autoplay-ready gate now ignores untokenized subtitle payloads while tokenization warmup is pending, so playback doesn't resume before the first tokenized cue
- Wire isTokenizationReady dep through main.ts and update gate/wiring tests accordingly
- Drop stale release/release-notes.md, add changelog entry under changes/
Background AppImage launches executed directly from a FUSE mount owned by a
short-lived helper's AppImage runtime. On quit, the runtime unmounted the
squashfs while utility children (network service) were still mid-shutdown,
SIGBUSing them and triggering KDE Service Crash notifications on every video
close. Detach a POSIX-sh supervisor instead: mount via --appimage-mount, run
AppRun from the mount, and release the holder only once no process still
executes from the mount. Falls back to the old direct launch on any failure
or with SUBMINER_NO_APPIMAGE_MOUNT_KEEPALIVE=1.
- Merge related fix entries into single files (name-match-span-merge into character-name-split-and-scan-recovery, kanji-non-independent-noun-annotations + lexicalized-expression-frequency into content-adverb-annotation-stop-list, greedy-name-parsing-priority into character-name-split-and-scan-recovery, kiku-field-grouping-cancel-double-toast into kiku-field-grouping-modal-recovery, history-rofi-cover-art into launcher-history-command)
- Rewrite remaining entries for brevity and reclassify stats-trend-title-limits as "changed"
- Add allowReadingOnlyMatch:false to kanji token known-word lookups so 渓谷/けいこく no longer matches a mined 警告/けいこく card via reading-only index
- Greedy name pre-pass yields when a strictly longer generic word starts at the same position (空 no longer splits 空気; ties still go to the name)
- 確かに and やはり no longer excluded from frequency/JLPT highlighting and vocab stats
- Stop-word list now covers only interjections, pronouns, and grammar fragments