soulsync/tests/library
BoulderBadgeDad 696119d5ac Expired Download Cleaner: retention-based cleanup of watchlist/playlist downloads (Boulder)
A Library Maintenance job that cleans up downloads tracked by Download Origins
once they pass a per-origin retention window — findings by default, opt-in
auto-delete.

A download is only ever proposed for deletion when ALL hold: older than its
origin's retention, NOT still in an actively-mirrored playlist / watched
artist, and played fewer than the keep-threshold (default 2 → "played more
than once is kept"). Only touches downloads recorded from the Download Origins
feature forward — never pre-existing or manual library.

- core/library/expired_cleanup.py: pure decision core (retention_cutoff,
  is_expired, select_expired) — no DB/clock, fully tested. play_count is the
  reliable listen signal (last_played is often unpopulated, so recency isn't
  used).
- ExpiredDownloadCleanerJob: gathers facts (play_count via a new
  get_origin_cleanup_candidates join; active-mirror via get_mirrored_playlists;
  watch via get_watchlist_artists) and either creates 'expired_download'
  findings or, with auto_delete on, deletes in-scan. Default OFF, both
  retentions default 'off'. Settings auto-render in the Library Maintenance
  panel (same as Cover Art / Lyrics / Re-tag).
- delete_origin_download(): shared delete (resolve path → remove file → drop
  track row → drop history row); a file that won't delete keeps its row +
  reports. Used by auto mode AND the _fix_expired_download apply handler.
- Frontend: type/action ('Delete')/result labels + finding detail render.

Tests: 9 on the pure brain (windows, off, per-origin, protected, play-count
threshold, bad age) + 7 on the job (no-op when off, findings, mirror/watch
protection, auto-delete, delete helper missing/real file). 185 repair/origin
tests pass.
2026-06-07 22:06:56 -07:00
..
__init__.py Lift _execute_retag to core/library/retag.py 2026-04-29 09:03:42 -07:00
test_artist_image.py Drop platform-biased trailing-backslash test for derive_artist_folder 2026-05-13 11:52:04 -07:00
test_direct_id_match.py Manual match: paste a MusicBrainz ID/URL to match directly (Ashh) 2026-06-07 13:04:17 -07:00
test_embedded_id_reconcile.py Auto-reconcile embedded IDs for new tracks on library scans 2026-06-05 18:31:11 -07:00
test_expired_cleanup.py Expired Download Cleaner: retention-based cleanup of watchlist/playlist downloads (Boulder) 2026-06-07 22:06:56 -07:00
test_file_tags.py Add per-download Audit Trail modal to Library History 2026-05-13 09:50:24 -07:00
test_missing_track_import.py Test missing-track existing file imports 2026-05-17 14:18:17 -07:00
test_path_resolver.py Album Completeness: surface diagnostic when resolver can't find album folder 2026-05-12 14:04:15 -07:00