Skip to content

Stop album-wide "- Live" suffixes from blocking Spotify track matches - #226

Merged
dprodger merged 1 commit into
mainfrom
fix/spotify-album-wide-live-suffix
Nov 9, 2026
Merged

dprodger merged 1 commit into
mainfrom
fix/spotify-album-wide-live-suffix

Conversation

@dprodger

@dprodger dprodger commented Nov 9, 2026

Copy link
Copy Markdown
Owner

Production case: recording 2038d869 ("I'll See You Again", Keith Jarrett trio, After the Fall) had no Spotify link despite being on Spotify as track 6VvA3581KyjfhIxMQ6WNvw. The album search was never the problem — it scores 100% on title, artist, tracklist coverage and ordering against album 6KCtVTAKemrqpVZLLdxB2c. The track scored 105% with a 53ms duration delta and was then thrown away by the version-keyword asymmetry rejection from b032618.

That guard exists for the reverse direction: MB "Peace (live at the Newport Jazz Festival)" linked to a lone studio "Peace" on Day Breaks, 63s apart, where the keyword is the only signal the two are different performances. But the test is symmetric, so it also fires when Spotify suffixes every track on a live album " - Live" and titles the album "After The Fall (Live)" while MusicBrainz annotates neither. There the asymmetry is labelling convention and says nothing about which performance a track is.

Fix: a new version_keyword_is_album_wide() recognises that labelling — an annotated Spotify album title, or >=80% of the album's track titles carrying a keyword. The ratio bar is deliberately high so a studio album with a few bonus live cuts does NOT clear it, since there the keyword still discriminates. match_tracks_for_release gains two escapes from the rejection, both gated on the keyword being on the Spotify side only: album-wide labelling, and a duration delta within 5s (a safety net for live albums Spotify annotates only partially, consistent with duration_confidence already scoring <=5s as 1.0). A keyword on the MB side that Spotify lacks is the original false-positive shape and stays rejected unconditionally. The rejection path, including its stale-link cleanup, is otherwise untouched.

spotify_album_name is threaded through match_tracks_for_release from the call site that has it; the rematch_tracks path holds only an album ID, so it passes nothing and relies on the per-track ratio rather than spending an extra API call.

Knock-on effect of the old behavior: because the song's only track on the release failed, the album match was discarded as a possible false positive, so the release carried no Spotify album link or cover art either, and the other recordings on it went unlinked. ~628 recording_releases rows DB-wide show this shape (a non-Spotify link whose title carries a version keyword, no Spotify link) — an upper bound, not a confirmed count.

Verified by dry run: the recording now matches 6VvA3581KyjfhIxMQ6WNvw and the release picks up its album ID and artwork, while a live run over Day Breaks still rejects the Peace pair and still matches the studio take. Note that a backfill needs rematch_all, since the old failure is cached by is_track_match_cached_failure.

Tests: 11 new in TestVersionKeywordIsAlbumWide covering the full-album case, album-title-alone, the Peace shape, the ratio boundary either side of 80%, and the no-evidence paths that preserve strict behavior. Full backend suite passes (682).

Production case: recording 2038d869 ("I'll See You Again", Keith Jarrett
trio, After the Fall) had no Spotify link despite being on Spotify as
track 6VvA3581KyjfhIxMQ6WNvw. The album search was never the problem —
it scores 100% on title, artist, tracklist coverage and ordering against
album 6KCtVTAKemrqpVZLLdxB2c. The track scored 105% with a 53ms duration
delta and was then thrown away by the version-keyword asymmetry
rejection from b032618.

That guard exists for the reverse direction: MB "Peace (live at the
Newport Jazz Festival)" linked to a lone studio "Peace" on Day Breaks,
63s apart, where the keyword is the only signal the two are different
performances. But the test is symmetric, so it also fires when Spotify
suffixes every track on a live album " - Live" and titles the album
"After The Fall (Live)" while MusicBrainz annotates neither. There the
asymmetry is labelling convention and says nothing about which
performance a track is.

Fix: a new version_keyword_is_album_wide() recognises that labelling —
an annotated Spotify album title, or >=80% of the album's track titles
carrying a keyword. The ratio bar is deliberately high so a studio album
with a few bonus live cuts does NOT clear it, since there the keyword
still discriminates. match_tracks_for_release gains two escapes from the
rejection, both gated on the keyword being on the Spotify side only:
album-wide labelling, and a duration delta within 5s (a safety net for
live albums Spotify annotates only partially, consistent with
duration_confidence already scoring <=5s as 1.0). A keyword on the MB
side that Spotify lacks is the original false-positive shape and stays
rejected unconditionally. The rejection path, including its stale-link
cleanup, is otherwise untouched.

spotify_album_name is threaded through match_tracks_for_release from the
call site that has it; the rematch_tracks path holds only an album ID,
so it passes nothing and relies on the per-track ratio rather than
spending an extra API call.

Knock-on effect of the old behavior: because the song's only track on
the release failed, the album match was discarded as a possible false
positive, so the release carried no Spotify album link or cover art
either, and the other recordings on it went unlinked. ~628
recording_releases rows DB-wide show this shape (a non-Spotify link
whose title carries a version keyword, no Spotify link) — an upper
bound, not a confirmed count.

Verified by dry run: the recording now matches 6VvA3581KyjfhIxMQ6WNvw
and the release picks up its album ID and artwork, while a live run over
Day Breaks still rejects the Peace pair and still matches the studio
take. Note that a backfill needs rematch_all, since the old failure is
cached by is_track_match_cached_failure.

Tests: 11 new in TestVersionKeywordIsAlbumWide covering the full-album
case, album-title-alone, the Peace shape, the ratio boundary either side
of 80%, and the no-evidence paths that preserve strict behavior. Full
backend suite passes (682).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@dprodger
dprodger merged commit be71f3e into main Nov 9, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant