Autotag: detect "junk drawer" folders with no artist/album consensus
and split them into synthetic per-cluster groups instead of forcing
one match on an unrelated pile of tracks; repair tagging_items rows
left behind by a prior scan orphan-cleanup gap.
Explore: fix an exact artist-name search being drowned out by its own
catalog entries in intent-prior scoring, and prune stale in_library
bookkeeping left behind when a referenced library row is deleted.
Download: fix a multi-library regression where every import failed
with "no library root configured" — the importer resolved the
library root from a legacy single-library config field that nothing
populates in the current multi-library model. It now resolves the
destination library per-request from the request's own library_id.
Also widen the Soulseek search window (12s -> 20s), measured against
real request history to be missing available peers on live queries.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y2Agd9af5hE7qzti2ackiS
Ships the fresh-start schema cleanup: rebuilt explore catalog index
pipeline (dump import, artifact fetch/build, incremental listen-count
refresh), a new download subsystem (Lidarr/Prowlarr/qBittorrent/SABnzbd/
slskd/yt-dlp providers, staging, reconciliation, wanted list), and the
supporting schema/query/store changes across backend and frontend.
Also includes two smaller follow-ups: bump the central index's
rebuild-after cadence from 90 to 180 days, and remove the Explore
"library only" online/offline toggle entirely (frontend-only, no
backend counterpart) rather than carry unused UI/state.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y2Agd9af5hE7qzti2ackiS
Consolidates in-progress work across autotag, explore, and library:
- autotag: beets/Picard-informed scoring engine — ID-first matching, VA
handling, recommendation tiers, and a merged distance/rank cascade, with
an eval harness for regression tracking.
- explore: offline MusicBrainz dump import/incremental refresh replaces the
legacy tier crawl; index-first local search with fuzzy matching and a
dedicated ranker; disk-free guards for dump downloads.
- library: artist-credit extraction and matching.
- lyrics: owned-library lyric search (FTS) with LRCLIB backfill.
Also: rewrite README to be user-focused, and migrate upstream to
git.ljones.me/yonlu/yellowjacket.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add phantom_file_path column to playlist_tracks (migration 7)
- Store original file_path during RemoveLibrary phantom metadata population
- After each successful scan, UPDATE phantom tracks whose phantom_file_path
now matches an audio_files row, re-linking them and clearing phantom metadata
- Update schema file, sqlc generated code, and database test for new column
Contentless FTS5 cannot delete individual rows, but stale entries are
filtered out by the JOIN against track_metadata in search queries.
The index is rebuilt on the next full rescan. Removes ~10s of overhead
for a 25K-track library removal.
artist_credit_artist.credit_id references artist_credit.id, so the
child table must be cleaned before the parent. Same FK ordering fix
as the earlier recording_genres/recordings swap.
recording_genres and release_group_recordings reference recordings.id,
so they must be deleted BEFORE the recordings table is cleaned.
Also extends toast duration to 8s for readability.
RemoveLibrary now polls until the cancelled scan goroutine finishes
before proceeding with the removal transaction. Also show removal
errors as toast messages instead of only logging to console, and
explicitly reload library list after successful removal.
Tracks from pre-multi-library schema have library_id=0 (default).
When AddLibrary creates a new library row, UPDATE orphaned tracks
whose file_path falls under the library's directory to use the new
library_id. This prevents the scan from hitting UNIQUE constraints
on every file and ensures track counts are correct immediately.