soulsync/core/playlists
BoulderBadgeDad 6e622d30f1 #901: give file-import playlist tracks a stable id so manual matches stick
A Find & Add on a file-import (CSV/M3U/TXT) playlist track was silently dropped and
the track re-appeared as 'extra' (radoslav-orlov). Root cause: unlike Spotify/YouTube
(native ids), file-import + iTunes-only tracks arrive with an EMPTY source_track_id —
and the whole manual-match system keys on it. _persist_find_and_add_match is a no-op
on an empty id, and find_manual_library_match_by_source_track_id returns None for one,
so the match can be neither recorded nor looked up. That's the youtube-vs-file
difference the reporter noticed.

Fix: stable_source_track_id() derives a DETERMINISTIC 'file:<hash>' id from the track
identity (artist|title|album, normalized) when there's no native id; mirror_playlist
assigns it so the SAME song gets the SAME id across re-imports/discovery — exactly
what the match lookup needs. Native ids are used verbatim; bonus: discovery extra_data
now survives a re-import for these tracks too.

Tests: helper (native passthrough, deterministic + case/field-insensitive, distinct
per song, empty-on-no-title, file: prefix); mirror_playlist integration (file tracks
get stable distinct ids, stable across re-import, native ids untouched). 319 playlist/
sync/discovery/mirrored tests green.
2026-06-22 08:53:24 -07:00
..
sources Fix: auto-sync capped public Spotify playlists at 100 tracks (#838) 2026-06-10 18:31:43 -07:00
__init__.py Lift _prepare_stream_task + playlist_explorer_build_tree to core/ 2026-04-29 11:26:07 -07:00
explorer.py Final silent-exception sweep + ruff S110 lint guardrail — ~45 sites 2026-05-07 11:16:06 -07:00
item_naming.py Organize-by-playlist: optional custom file naming for the playlist folder 2026-06-21 21:57:20 -07:00
lb_series.py Roll LB Weekly / Top series into single rolling mirrors (Phase 1c.2.1) 2026-05-26 15:49:49 -07:00
materialize.py Organize-by-playlist: optional custom file naming for the playlist folder 2026-06-21 21:57:20 -07:00
materialize_service.py Organize-by-playlist: optional custom file naming for the playlist folder 2026-06-21 21:57:20 -07:00
naming.py Mirrored playlists: custom name alias (overrides display + sync name, survives upstream refresh) — card rename button like the source-ref editor 2026-06-13 00:23:56 -07:00
organize_download.py PR #780 follow-ups: snapshot-based stale check + submit guard + dead code 2026-06-03 20:45:17 -07:00
pipeline.py Auto-Sync: fix LB pipelines stuck on "Refreshing:" for 5+ minutes 2026-05-27 18:04:55 -07:00
source_refs.py #901: give file-import playlist tracks a stable id so manual matches stick 2026-06-22 08:53:24 -07:00