soulsync/webui/static
Broque Thomas e7ecaca3fd Fix MTV Unplugged & live-album false-quarantine pipeline
Closes #589. Tracks from MTV Unplugged / Live At / unplugged albums
consistently failed AcoustID verification with "Version mismatch:
expected (live) but file is (original)". Two upstream bugs fed into
the false positive — the AcoustID gate itself was correctly catching
the wrong file Tidal had selected. Codex diagnosed all three layers,
this fixes the two upstream causes and leaves the verifier alone.

Bug 1 — album-scoped library check false-misses owned albums

`core/downloads/master.py:184` scored "Shy Away (MTV Unplugged Live)"
(source title from playlist) vs "Shy Away" (local DB stored title)
with raw string similarity. Massive length asymmetry → ~0.3 → below
the 0.7 threshold → marked missing. Combined with the
`allow_duplicates and batch_is_album` short-circuit that disables
the global fallback for album downloads, the user's already-owned
album re-triggered every track for download. Explains the screenshot
showing "0 found / 7 missing" on an album the user manually placed.

New pure helper `core/matching/album_context_title.py:strip_redundant_album_suffix`
strips trailing parenthetical / bracket / dash suffixes whose tokens
are fully subsumed by the album context — at least one version
marker (live / unplugged / acoustic / session / concert / tour)
overlapping with the album, and every other token is either a
known marker, a year, a tolerated noise word, or a word from the
album title. Album-context-implied "live" added when the album
mentions unplugged / concert / tour / session.

Wired into the album-confirmed scope ONLY (not global matching).
Compares both raw and normalized source titles per album track and
takes the max similarity, so the helper returning the input
unchanged (when album doesn't imply version context) preserves
the pre-fix behavior.

Bug 2 — Tidal qualifier filter only ran on fallback searches

`core/tidal_download_client.py:345` set `is_fallback = attempt_idx > 0`
and only filtered when `is_fallback and required_qualifiers`. Primary
search returned all results unfiltered, so a query for "Shy Away
(MTV Unplugged Live)" could accept the studio cut if Tidal happened
to rank it first. Now the qualifier filter applies to BOTH primary
and fallback search attempts — log message updated to indicate
which path triggered.

Bug 3 — qualifier check ignored album.name

The legacy `_track_name_contains_qualifiers` only inspected the
track name. For concert / unplugged releases the live signal
typically lives in the album title, not the track title. New
`_track_matches_qualifiers` accepts a track object and inspects
both `track.name` AND `track.album.name`. Legacy helper preserved
to keep its existing test contract.

AcoustID version-mismatch gate at core/acoustid_verification.py
left intact — it correctly catches genuinely-wrong files that slip
through upstream filters. The In My Feelings (Instrumental) test
that pins this behavior continues to pass.

19 tests on the album-context helper covering MTV Unplugged
variants, dash/parens/brackets suffix shapes, year tolerance,
plural-form markers, the implied-live set, anti-regression cases
(instrumental/remix on a studio album must NOT be stripped),
empty/none defensive paths.

13 tests on the Tidal qualifier helper covering legacy
track-name-only behavior preserved, qualifier in track name alone,
qualifier in album name alone (the MTV Unplugged scenario),
multi-qualifier requirements, no-qualifiers always passes,
defensive against missing track.album, word-boundary avoiding
substring false-matches, _extract_qualifiers picking up live +
unplugged from the user's exact reporter query.

Full suite: 3053 passed.
2026-05-14 12:14:31 -07:00
..
docs update docs page 2026-03-13 08:35:28 -07:00
vendor Add WebSocket real-time updates with automatic HTTP polling fallback 2026-03-03 18:26:29 -08:00
api-monitor.js Stop watchlist countdown refetch loop 2026-05-02 22:02:00 +03:00
artists.png add static images 2026-03-09 17:35:46 -07:00
automation.png add static images 2026-03-09 17:35:46 -07:00
beatport-ui.js Add "All Libraries (combined)" mode to PlexClient 2026-05-06 15:39:19 -07:00
core.js Keep Issues and artist detail history stable 2026-05-13 22:26:24 +03:00
dashboard.png add static images 2026-03-09 17:35:46 -07:00
discover-section-controller.js Discover controller — Cin pre-review polish 2026-05-07 20:35:10 -07:00
discover.js Your Albums: selectable wishlist modal + Tidal album resolution 2026-05-11 12:36:16 -07:00
discover.png add static images 2026-03-09 17:35:46 -07:00
docs-images-needed.md Service Badges, Page Headers, Docs Page, and Bug Fixe 2026-03-10 14:47:11 -07:00
docs.js Clean up stale Artists-page references in helper.js + docs.js 2026-04-22 20:29:32 -07:00
downloads.js Quarantine management — list, approve, delete, recover 2026-05-14 08:06:19 -07:00
enrichment.js Repair job card badge — show pending count, not last-scan count 2026-05-07 08:28:17 -07:00
explorer.png Create explorer.png 2026-03-30 17:23:31 -07:00
favicon.png enlarge favicon 2026-02-13 16:11:32 -08:00
help.png Add media server setup, processing settings, text import, automation history, and streaming details 2026-03-10 15:35:18 -07:00
helper.js Fix MTV Unplugged & live-album false-quarantine pipeline 2026-05-14 12:14:31 -07:00
hydrabase.png Add Hydrabase dev UI and WebSocket support 2026-02-21 00:32:04 -08:00
import.png add static images 2026-03-09 17:35:46 -07:00
init.js Move shared shell chrome into bridge 2026-05-13 22:26:26 +03:00
library.js Merge pull request #530 from dlynas/feat/explicit-badges 2026-05-13 15:04:14 -07:00
library.png add static images 2026-03-09 17:35:46 -07:00
manifest.json Service worker for cover art + PWA manifest 2026-04-26 22:17:52 -07:00
media-player.js Split monolithic script.js (78K lines) into 17 domain modules 2026-04-21 23:52:30 -07:00
mobile.css Remove legacy issues shell code 2026-05-13 22:26:22 +03:00
pages-extra.js Persist Find & Add selections as permanent server-playlist match overrides 2026-05-14 09:39:24 -07:00
particles.js Add particle background toggle & optimize accent color caching 2026-03-13 16:05:22 -07:00
placeholder-album.png Add missing placeholder-album.png to stop 404 spam in console 2026-03-23 18:05:11 -07:00
pwa-icon-192.png Service worker for cover art + PWA manifest 2026-04-26 22:17:52 -07:00
pwa-icon-512.png Service worker for cover art + PWA manifest 2026-04-26 22:17:52 -07:00
search.js Keep Issues and artist detail history stable 2026-05-13 22:26:24 +03:00
search.png add static images 2026-03-09 17:35:46 -07:00
settings.js Configurable duration tolerance for downloaded-file integrity check 2026-05-14 06:53:36 -07:00
settings.png add static images 2026-03-09 17:35:46 -07:00
setup-wizard.css Add informative help text and tips to every setup wizard step 2026-04-11 23:26:01 -07:00
setup-wizard.js Rebrand folder terminology: Download→Input, Transfer→Output, Staging→Import 2026-04-18 17:35:20 -07:00
shared-helpers.js Fix search source picker defaulting to Spotify regardless of config 2026-05-13 15:36:48 -07:00
shell-bridge.js Move shared shell chrome into bridge 2026-05-13 22:26:26 +03:00
stats-automations.js Remove legacy issues shell code 2026-05-13 22:26:22 +03:00
style.css Polish Download Missing modal tracklist 2026-05-13 18:38:02 -07:00
sw.js Service worker for cover art + PWA manifest 2026-04-26 22:17:52 -07:00
sync-services.js Server playlist sync: append mode (preserve user-added tracks) 2026-05-10 22:52:11 -07:00
sync-spotify.js Server playlist sync: append mode (preserve user-added tracks) 2026-05-10 22:52:11 -07:00
sync.png add static images 2026-03-09 17:35:46 -07:00
trans.png Add SoulID worker with API-based debut year disambiguation 2026-03-21 10:21:06 -07:00
trans2.png Create trans2.png 2026-03-21 10:23:36 -07:00
whisoul.png Add library repair worker and UI 2026-02-21 15:00:23 -08:00
wishlist-tools.js Polish quarantine UI — fold into Library History modal as third tab 2026-05-14 08:50:24 -07:00
worker-orbs.js Add Discogs to worker orbs animation and fix button styling 2026-04-02 17:18:31 -07:00