Pair playlists on their folder path, not their title - #3
Merged
Conversation
verify compared some source playlists against the wrong Engine list, and every
instance of that invents discrepancies on a conversion that is correct. That is
the worse direction for this tool to fail in: a verifier that cries wolf gets
ignored, and the next real defect goes unread.
Three ways it mispaired
-----------------------
The lookup was keyed on title alone with last-write-wins, so two playlists named
"Chill" in different folders collapsed onto one list. Engine's uniqueness
constraint is per-parent, so that is legal and common.
Within one folder, rekordbox allows duplicate names and Engine does not, so the
writer renames the second to "Name (2)". Both source lists still carry the
original name, and the exact-title lookup therefore succeeded for every one of
them, resolving all N duplicates to the first list. The suffix scan meant to
handle this was unreachable.
That scan also matched on startswith("Name ("), so a playlist absent from the
database resolved to any unrelated list whose title merely began the same way —
"House" was verified against "House (old)", reported as wrong tracks instead of
as missing, pointing at the wrong playlist entirely.
One naming implementation
-------------------------
playlist_naming.py now owns the sibling ordering and the rename, and both the
writer that applies the names and the verifier that must predict them use it.
The two have to travel together: the suffix a duplicate receives depends on the
sibling order, so extracting the rename alone would leave verify re-deriving the
ordering by hand — the same coupling that produced these defects.
Pairing is on the whole path as a tuple of titles, not a joined string, because
rekordbox permits "/" in a playlist name; joining is for display only.
A retitled list is now reported
-------------------------------
A test asserted that a source "Main Set" should still match a database list
retitled "Main Set (2)". That was the startswith bug in test form: with one
source playlist the writer can never emit a suffix, so that database state means
something else changed it, and test_verify_catches_playlist_rename already
asserts an external retitle is reported. The old test demanded the opposite
outcome for the same operation whenever the new title happened to look like a
rename. It is replaced by one asserting the retitle is reported, and the case it
claimed to defend is covered properly by a test that builds two same-named
playlists and checks each pairs with the list it became.
Breaking: playlist discrepancy keys are now path-qualified.
696 tests (8 new), 88% branch coverage, playlist_naming at 100%, ruff + mypy clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3aF4y4GdsuJta2bfYUZ8w
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
verifycompared some source playlists against the wrong Engine list. Every instance of that invents discrepancies on a conversion that is correct — the worse direction for this tool to fail in, since a verifier that cries wolf gets ignored and the next real defect goes unread.Found while investigating the "phantom playlist entry" incident. These defects can manufacture that exact symptom (two playlists, one extra track each) on their own, independent of whatever caused the original report.
Three ways it mispaired
title_to_idkeyed on title alone, last-write-winsChillin different folders collapse onto one list. Engine's uniqueness constraint is per-parent, so this is legal and common.Name (2), but both source lists still carry the original name — so all N duplicates resolve to list #1. The suffix scan meant to handle this was unreachable.startswith("Name (")Housewas verified againstHouse (old), reported as wrong tracks rather than missing.One naming implementation
playlist_naming.pynow owns the sibling ordering and the rename, used by both the writer that applies the names and the verifier that must predict them.The two have to travel together: the suffix a duplicate receives depends on the sibling order, so extracting the rename alone would leave verify re-deriving the ordering by hand — the same coupling that produced these defects.
Pairing uses the whole path as a tuple of titles rather than a joined string, because rekordbox permits
/in a playlist name; joining is display-only.Playlist discrepancy keys are now path-qualified:
Nothing parses these keys programmatically (
report.pyprintsd.fieldverbatim;VerifyResulthas no JSON serialization), but scripts grepping verify's output need updating.A rewritten test — please scrutinize this one
A pre-existing test asserted that a source
Main Setshould still match a database list retitledMain Set (2), and this PR makes that report as missing instead.That test was defect #3 in test form. With a single source playlist the writer can never emit a suffix, so that database state means something else modified it — and
test_verify_catches_playlist_renamealready asserts an external retitle is reported. The old test demanded the opposite outcome for the same operation whenever the new title happened to resemble a rename.The case it claimed to defend is now covered properly, by a test that builds two same-named playlists and asserts each pairs with the list it actually became.
Verification
playlist_naming.pyat 100% line + branch coverage; total 87.79% (floor 85%)Not included
Remaining workstreams from the investigation are specified in
.omc/plans/playlist-phantom-entry-root-cause.mdand deliberately left out of this PR: source provenance + torn-file gate + inline pre-publish oracle (W1), external-edit classifier (W3), and thenum_rows_largereader probe (W4, needs a real largeexport.pdb).🤖 Generated with Claude Code
https://claude.ai/code/session_01V3aF4y4GdsuJta2bfYUZ8w