Implementation
Make empty-album Last.fm collection batches ratification-first. Treat SourceRow.album == "" (shown as Singles) as collection-shaped while preserving literal non-empty Singles as release-shaped. Rank cached Spotify candidates conservatively: accepted durable/manual choices first; unique normalized title + primary artist candidates already in the Retune library, saved tracks, or saved album track lists next; then unique normalized title + artist candidates even when unowned; surface owned same-artist textual near/search candidates as suggestions only; keep equal-ranked editions unresolved. Source variants participate in normalized comparison, wrong artists never auto-select, and accepted mappings remain reusable. Add only the backward-compatible AlbumCandidate.inLibrary serde-defaulted projection needed by the UI. On reopen, rerank cached candidates against current membership and persist only changes; refetch only legacy incompatible empty-album cache rows whose search term is album-shaped, preserving manual/selected mappings. Cached correct batches make zero Spotify requests; release-shaped behavior is unchanged.
Update the importer UI to explain individual matching, show automatic/suggested/needs-review counts, strong-match/library badges, inline one-click suggestions with Change Track retained, high-contrast ACTION REQUIRED for no useful candidate, and disable Import whole album until a coherent collection album is explicitly chosen. Keep calls through the shared Spotify client/request gate and visible batch only. Update architecture and persistence docs.
Empirical acceptance plan
Run focused Rust/UI regressions covering: empty collection vs literal Singles; unique owned exact auto-select; unique unowned exact auto-select; owned edition beats identical unowned; two owned editions unresolved; imperfect owned candidate suggested but not committed; wrong artist never auto-selected; manual selection preserved; accepted mapping reused; cached batch zero provider calls; only legacy incompatible rows refetch; account safety; UI summary/inline suggestion/library badge/whole-album disabled; release UI unchanged. Then run node scripts/check-docs.mjs, Rust fmt/clippy/tests, and desktop npm test/lint/tsc/build. Validate the visible batch flow manually in the app as applicable.
Implementation
Make empty-album Last.fm collection batches ratification-first. Treat
SourceRow.album == ""(shown asSingles) as collection-shaped while preserving literal non-emptySinglesas release-shaped. Rank cached Spotify candidates conservatively: accepted durable/manual choices first; unique normalized title + primary artist candidates already in the Retune library, saved tracks, or saved album track lists next; then unique normalized title + artist candidates even when unowned; surface owned same-artist textual near/search candidates as suggestions only; keep equal-ranked editions unresolved. Source variants participate in normalized comparison, wrong artists never auto-select, and accepted mappings remain reusable. Add only the backward-compatibleAlbumCandidate.inLibraryserde-defaulted projection needed by the UI. On reopen, rerank cached candidates against current membership and persist only changes; refetch only legacy incompatible empty-album cache rows whose search term is album-shaped, preserving manual/selected mappings. Cached correct batches make zero Spotify requests; release-shaped behavior is unchanged.Update the importer UI to explain individual matching, show automatic/suggested/needs-review counts, strong-match/library badges, inline one-click suggestions with Change Track retained, high-contrast ACTION REQUIRED for no useful candidate, and disable Import whole album until a coherent collection album is explicitly chosen. Keep calls through the shared Spotify client/request gate and visible batch only. Update architecture and persistence docs.
Empirical acceptance plan
Run focused Rust/UI regressions covering: empty collection vs literal
Singles; unique owned exact auto-select; unique unowned exact auto-select; owned edition beats identical unowned; two owned editions unresolved; imperfect owned candidate suggested but not committed; wrong artist never auto-selected; manual selection preserved; accepted mapping reused; cached batch zero provider calls; only legacy incompatible rows refetch; account safety; UI summary/inline suggestion/library badge/whole-album disabled; release UI unchanged. Then runnode scripts/check-docs.mjs, Rust fmt/clippy/tests, and desktop npm test/lint/tsc/build. Validate the visible batch flow manually in the app as applicable.