This release adds 3 notable features for engineering teams evaluating rollout.
✓ No known CVEs patched in this version
Summary
AI summaryUpdates UI consistency, Test plan, and Mant across a mixed release.
Changes in this release
| Type | Severity | Summary | CVE |
|---|---|---|---|
| Feature | Low |
Adds a **Deep Scan** option to the Database Updater tool in the UI. Adds a **Deep Scan** option to the Database Updater tool in the UI. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Bugfix | Medium |
Fixes download path using incorrect album name when $year is not a valid year. Fixes download path using incorrect album name when $year is not a valid year. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Bugfix | Medium |
Prevents Reorganize from moving quarantined files out of the `/deleted` folder. Prevents Reorganize from moving quarantined files out of the `/deleted` folder. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Bugfix | Medium |
Moves wishlist album‑bundle downloads to a dedicated executor, preventing queue starvation. Moves wishlist album‑bundle downloads to a dedicated executor, preventing queue starvation. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Bugfix | Medium |
Adds a 180‑second stall guard for Soulseek album polls, classifies aborted transfers as failed, and falls back to per‑track flow when needed. Adds a 180‑second stall guard for Soulseek album polls, classifies aborted transfers as failed, and falls back to per‑track flow when needed. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Bugfix | Medium |
Prevents search results from disappearing when interacting with the media player. Prevents search results from disappearing when interacting with the media player. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Bugfix | Medium |
Stops import from overwriting the album‑artist tag to "Unknown Artist". Stops import from overwriting the album‑artist tag to "Unknown Artist". Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Bugfix | Medium |
Resolves Spotify playlist sync showing only the first 100 tracks by handling pagination. Resolves Spotify playlist sync showing only the first 100 tracks by handling pagination. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Bugfix | Medium |
Eliminates duplicate tracks in albums with Japanese / CJK titles by normalizing similarity. Eliminates duplicate tracks in albums with Japanese / CJK titles by normalizing similarity. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Bugfix | Medium |
Fixes Usenet album bundles stuck at 99‑100 % by handling the SAB status transition gap. Fixes Usenet album bundles stuck at 99‑100 % by handling the SAB status transition gap. Source: llm_adapter@2026-05-30 Confidence: high |
— |
Full changelog
SoulSync 2.6.4 — Merge dev → main
Patch release on top of 2.5.2 (the last tag on main). The 2.6.x line was bumped on dev but never tagged / published, so this is the first time all of it reaches users. Big patch — bug fixes across downloads / wishlist / library, a chunk of internal hardening, and some UI consistency work.
Version constant: 2.6.4 (web_server.py:_SOULSYNC_BASE_VERSION).
Headline bug fixes
#745 — Every download saved with the first 4 chars of the album name where $year should be.
The $year template variable was a blind release_date[:4] slice. When something upstream put the album NAME into release_date, that slice emitted garbage — "Mantras (Deluxe)"[:4] → "Mant", so files landed in Mantras (Deluxe) (Mant) [Album]/ instead of (2026). Added _extract_year_from_release_date(): returns the leading 4 chars only when they're a plausible year (isdigit, 1900 < y ≤ 2100), else empty — matching the guard soulid_worker._extract_year already uses. A non-year now resolves to empty and the template's bracket-cleanup drops the empty (). Fixed at the shared post-process path builder (core/imports/paths.build_final_path_for_track) that downloads, reorganize, AND imports all route through, so it's covered everywhere at once. Defensive layer — stops the symptom regardless of which upstream poisons release_date; the exact upstream (Soulseek + AcoustID + a future-dated album) is still being chased separately.
#746 — Library Reorganize pulling files back out of the /deleted folder.
The Duplicate Cleaner quarantines de-duped files into <transfer>/deleted/. If a user's media server scans the transfer folder (e.g. a /music root holding both the library and the transfer dir), those quarantined files get real DB rows — and Reorganize, being purely DB-driven, would dutifully move them back OUT of /deleted to the template location. We can't stop the rows existing (they come from the server), so the fix is bounded to Reorganize as the reporter asked: skip any track whose resolved path is under <transfer>/deleted. Anchored to the prefix (not a substring) so a real album like "Deleted Scenes" is kept; surfaced as a skip in the preview, mirrored on apply.
#740 — Wishlist album-bundle downloads jamming the whole queue.
Per-album wishlist bundles were blocking the shared 3-worker missing-tracks pool (a 2.6.3 regression). Moved album-bundle downloads onto a dedicated album_bundle_executor so a big bundle can't starve the per-track pool. User-validated on a 73-track run.
#747 — Soulseek album poll hangs on a stalled/dead peer.
A peer that stalls (stuck InProgress/Queued, dropped transfers, or "Completed, Aborted" at 0 bytes) used to spin the bundle poll to its full ~6h timeout. Three fixes: a 180s bundle-level stall guard (resolves with whatever completed when nothing progresses); "Aborted"/"Cancelled" correctly classified as failed (the "Completed, Aborted" string was misread as a completed-but-missing file); and when the chosen folder yields nothing usable, fall back to the proven per-track flow instead of hard-failing the batch. failed batches now also age out of the stuck-batch cleanup.
#732 — Search results disappear when interacting with the media player.
The outside-click allow-lists didn't include the player popup, so clicking into the mini-player counted as a click-away and tore down the results. Added the player to the allow-lists.
#735 — Import overwriting the album-artist tag to "Unknown Artist".
#736 — Spotify playlist sync showing only the first 100 tracks (pagination cutoff).
#722 — Duplicate tracks in albums with Japanese / CJK titles (similarity normalisation didn't fold CJK width/forms).
#721 — Usenet album bundles stuck on "downloading release" / 99–100%. Two-stage SAB History handoff: 2.6.4 covers the gap where SAB flips status to Completed before its post-processing writes the final storage field, plus writable staging dir + client→local path resolution.
#728 — Usenet album progress fetch from SAB (contributor PR, @IamGroot60).
Also: enhanced artist view no longer 404s for library artists opened via source ID; MusicBrainz artist discography no longer capped at 25 releases; album art now embeds at highest available resolution across all art paths (HiFi/MB cover art uses the CAA 1200px thumbnail instead of the flaky /front original).
Internal hardening (no user-facing change, lots of safety)
Wishlist orchestration unified. Manual wishlist runs now route through the same shared engine as auto (_run_wishlist_cycle), with batch-row construction centralized in make_wishlist_batch_row. Auto behavior proven unchanged; manual is now identical to auto instead of a parallel reimplementation.
DB schema hardening. Added a schema_migrations ledger + PRAGMA user_version backstop; stopped watchlist_artists rebuilds from silently dropping amazon_artist_id; normalized legacy comma-separated genres to canonical JSON; introduced a canonical source-ID registry (core/source_ids.py) and adopted it at the highest-value sites.
Discovery endpoints lift (10 commits). Collapsed ~10 families of near-duplicate per-source discovery endpoints (get_*_sync_status, reset_*_playlist, start_*_sync, etc.) into shared helpers.
Exception surfacing. ~70 silent except: pass sites across remaining modules now log instead of swallowing.
UI consistency
- New shared
.btnprimitive +.btn--sm/.btn--block/.btn--warningtiers; migrated config-modal, wishlist, watchlist, and sync-history button families onto it. - Shared
.page-shellcard primitive extracted; automations, playlist-explorer, settings, sync, and exception pages adopted it..tab/.cardprimitives added. - Downloads moved above Automations in the sidebar.
- Tools → Database Updater: added a Deep Scan option.
- Basic search visual overhaul + per-source picker in hybrid mode; standardized artist-detail hero action buttons.
Test plan
- [x] Full suite green on
dev(4400+ tests) - [x] #745: import-path tests — differential-verified the poisoned
release_dateproduces the exact(Mant)folder without the fix, clean folder with it; real years preserved - [x] #746: 8 unit + 2 integration reorganize tests, differential-verified; 128 adjacent reorganize tests green
- [x] #747: 6 poll-stall + 2 fallback tests (fake-clock), differential-verified; live Slipknot run no longer wedges the queue
- [x] #740: dedicated-pool fix user-validated on a 73-track run
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
Related context
Related tools
Beta — feedback welcome: [email protected]