soulsync/core/repair_jobs
BoulderBadgeDad 80d84c6de3 album completeness: fix excluded-sibling missing list + O(N) grouping (follow-up to #936)
#936 added fragmented-row grouping. two follow-ups found in review:

1) BUG: an excluded canonical sibling (a row pinned to the same canonical edition whose tracks
   fail the strict fragment match) was emitted with canonical_items but no owned set, so
   _build_missing_tracks flagged the ENTIRE tracklist as missing — including tracks the row
   already owns (e.g. a 3-track fragment of a 12-track edition reported 12 missing, not 9).
   now compute that sibling's own owned slots from its local tracks (shared
   _owned_reference_for_tracks helper, same logic as the anchor) so it reports only what it's
   actually missing and the count stays internally consistent.

2) PERF: _build_candidate_groups rescanned all albums for every canonical group — O(G*N), which
   degrades badly once many editions are pinned (fine today at G=1, latent at scale). invert to
   a single O(N) pass that assigns each row to its unique group; identical 'exactly one match'
   semantics. also added a Stop/Pause check in _prepare_work_items, which now front-loads the
   canonical lookups + matching.

3 new tests (excluded-sibling reports only its missing tracks; ambiguous candidate stays
   independent; unambiguous candidate joins) — 17 completeness + 123 repair tests green.
2026-06-27 18:18:50 -07:00
..
__init__.py tools: add Preview Clip Cleanup repair job (detect ~30s previews, re-fetch full track) 2026-06-27 16:07:41 -07:00
acoustid_scanner.py downloads: stop AcoustID scan duplicating history rows / leaving verified tracks 'unverified' (#934) 2026-06-27 09:52:39 -07:00
album_completeness.py album completeness: fix excluded-sibling missing list + O(N) grouping (follow-up to #936) 2026-06-27 18:18:50 -07:00
album_tag_consistency.py Surface silent exceptions in workers + repair jobs — ~30 sites 2026-05-07 10:27:24 -07:00
base.py Repair settings: dropdown for fixed-choice settings (canonical source_selection) 2026-06-02 15:33:13 -07:00
cache_evictor.py Metadata cache: hard LRU row cap to stop unbounded growth (7.6GB incident) 2026-05-30 23:22:05 -07:00
canonical_version_resolve.py Canonical: fix ruff lint (B023 loop-bound lambda, S110 bare except-pass) 2026-06-02 15:42:14 -07:00
dead_file_cleaner.py Dead File Cleaner: don't flag a whole library when paths just aren't reachable (#828) 2026-06-09 13:12:50 -07:00
discography_backfill.py Surface silent exceptions in workers + repair jobs — ~30 sites 2026-05-07 10:27:24 -07:00
duplicate_detector.py Fix: maintenance findings badge inflated when scan dedup-skipped 2026-05-04 08:55:13 -07:00
empty_folder_cleaner.py #912: Empty Folder Cleaner reads its opt-in from the right config key 2026-06-23 11:26:00 -07:00
expired_download_cleaner.py Expired Cleaner: set auto_fix=True so the Dry Run badge shows (was mislabeled 'Scan Only') 2026-06-07 22:24:59 -07:00
fake_lossless_detector.py Fix: maintenance findings badge inflated when scan dedup-skipped 2026-05-04 08:55:13 -07:00
library_reorganize.py #862: Library Reorganize falls back to tag-mode when an album has no source ID (media-server libs now actually reorganize) 2026-06-12 20:05:50 -07:00
library_retag.py Lyrics retag: fetch query from a read-only lyrics_meta, never db_data (no tag pollution) 2026-06-07 19:42:30 -07:00
live_commentary_cleaner.py Fix: maintenance findings badge inflated when scan dedup-skipped 2026-05-04 08:55:13 -07:00
lossy_converter.py Fix: maintenance findings badge inflated when scan dedup-skipped 2026-05-04 08:55:13 -07:00
mbid_mismatch_detector.py Surface silent exceptions in workers + repair jobs — ~30 sites 2026-05-07 10:27:24 -07:00
metadata_gap_filler.py Fix: maintenance findings badge inflated when scan dedup-skipped 2026-05-04 08:55:13 -07:00
missing_cover_art.py Cover Art Filler: scan falls back to the raw file path when mapping fails (Sokhi #fix) 2026-06-08 17:32:38 -07:00
missing_lyrics.py Lyrics Filler: convert track duration ms→s for LRClib (exact-match was silently defeated) 2026-06-07 19:45:10 -07:00
orphan_file_detector.py Orphan detector: hard-bail on a mass-orphan flood instead of warn-only 2026-06-12 08:15:23 -07:00
quality_upgrade.py refactor(quality-upgrade): remove legacy hardcoded rank constants and dead functions 2026-06-24 16:02:30 +02:00
quality_upgrade_scanner.py fix(repair-jobs): boolean settings saved as string 'true'/'false' by UI dropdown 2026-06-24 15:59:25 +02:00
relocate.py CI: silence S110 on three intentional best-effort swallows (unblocks dev build) 2026-06-11 16:00:07 -07:00
replaygain_filler.py #437: add ReplayGain Filler library-maintenance job 2026-06-11 18:41:12 -07:00
short_preview_track.py preview-clip job: enable select-all/fix-all + give the re-wishlist proper album art 2026-06-27 17:10:07 -07:00
single_album_dedup.py Fix: maintenance findings badge inflated when scan dedup-skipped 2026-05-04 08:55:13 -07:00
track_number_repair.py Canonical album version — Stage 4: Track Number Repair prefers canonical (read) 2026-06-02 11:47:42 -07:00
unknown_artist_fixer.py fix(repair): rewire Unknown Artist Fixer deferred imports (#646) 2026-05-19 22:09:15 -07:00