From ab05508acc051d9e92acc707456a6e48c945379c Mon Sep 17 00:00:00 2001 From: dev Date: Thu, 25 Jun 2026 22:00:57 +0200 Subject: [PATCH] feat(quality): rank-based candidate ordering toggle for priority mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds an opt-in `rank_candidates_by_quality` profile flag. When on, the priority-mode download walk orders candidates by the ranked-target quality (confidence/speed only break ties) instead of confidence-first. Default off keeps the byte-for-byte old behaviour, so existing installs are unaffected. Best-quality search mode is always quality-first regardless of the flag; the toggle only affects priority mode. Search-time source selection is unchanged — nothing is skipped, so a track can never go missing, only the order in which copies are tried changes. The version-mismatch force-import follows automatically: it accepts the first-tried (= best-ordered) quarantined candidate, which is the highest-quality one once the walk is quality-first. No change to its selection logic needed. - core/quality/selection.py: load_rank_candidates_by_quality() (fail-closed). - core/downloads/task_worker.py: _best_quality_ordering -> _candidate_ordering; quality-first when best_quality mode OR the toggle is on. - database/music_database.py: default profile carries the flag (False). - web_server.py: flag is preserved globally across preset apply/reset, like search_mode. - core/imports/version_mismatch_fallback.py: comment clarified (no behaviour change). Tests (TDD): load_rank_candidates_by_quality default/enabled/disabled/error; _candidate_ordering across all mode+toggle combinations + fail-closed. Co-Authored-By: Claude Opus 4.8 --- core/downloads/task_worker.py | 35 +++++++++----- core/imports/version_mismatch_fallback.py | 9 ++-- core/quality/selection.py | 20 ++++++++ database/music_database.py | 1 + .../downloads/test_worker_quality_ordering.py | 47 +++++++++++++++++++ tests/quality/test_search_mode.py | 29 ++++++++++++ web_server.py | 9 +++- 7 files changed, 134 insertions(+), 16 deletions(-) create mode 100644 tests/downloads/test_worker_quality_ordering.py diff --git a/core/downloads/task_worker.py b/core/downloads/task_worker.py index 1b7b2bc1..f615de47 100644 --- a/core/downloads/task_worker.py +++ b/core/downloads/task_worker.py @@ -54,21 +54,34 @@ def _cand_user_file(candidate): return getattr(candidate, 'username', None), getattr(candidate, 'filename', None) -def _best_quality_ordering(): - """Return ``(quality_first, targets)`` for the active search mode. +def _candidate_ordering(): + """Return ``(quality_first, targets)`` for the active search mode + toggle. - In best-quality mode the candidate walk is ordered by the user's profile - quality rank (best→worst) instead of confidence-first. Fails closed to - priority-mode ordering on any error so a profile/DB hiccup never blocks a - download. See docs/superpowers/specs/2026-06-14-best-quality-search-mode-design.md. + The candidate walk is ordered by the user's profile quality rank + (best→worst) instead of confidence-first when EITHER: + - best-quality search mode is active (always quality-first), OR + - priority mode and the ``rank_candidates_by_quality`` toggle is on + (opt-in; default off keeps the byte-for-byte confidence-first walk). + + Quality-first ordering also makes the version-mismatch force-import pick + the highest-quality candidate, because that fallback accepts the + first-tried (= best-ordered) quarantined entry. + + Fails closed to confidence-first ordering on any error so a profile/DB + hiccup never blocks a download. See + docs/superpowers/specs/2026-06-14-best-quality-search-mode-design.md. """ try: - from core.quality.selection import load_search_mode, load_profile_targets - if load_search_mode() == 'best_quality': + from core.quality.selection import ( + load_search_mode, + load_profile_targets, + load_rank_candidates_by_quality, + ) + if load_search_mode() == 'best_quality' or load_rank_candidates_by_quality(): targets, _ = load_profile_targets() return True, targets except Exception as exc: - logger.debug("[Modal Worker] best-quality ordering unavailable: %s", exc) + logger.debug("[Modal Worker] quality ordering unavailable: %s", exc) return False, None @@ -109,7 +122,7 @@ def _try_cached_candidates(task_id, batch_id, track, deps): f"[Modal Worker] Quarantine retry: trying {len(remaining)} cached " f"candidate(s) before re-searching (task {task_id})" ) - _qf, _qt = _best_quality_ordering() + _qf, _qt = _candidate_ordering() return deps.attempt_download_with_candidates( task_id, remaining, track, batch_id, quality_first=_qf, quality_targets=_qt, ) @@ -393,7 +406,7 @@ def download_track_worker(task_id: str, batch_id: Optional[str], deps: TaskWorke # Best-quality search mode: the orchestrator already pooled candidates # across every source for each query, so order the candidate walk by the # user's profile quality rank (best→worst). Computed once per task. - _best_quality, _quality_targets = _best_quality_ordering() + _best_quality, _quality_targets = _candidate_ordering() # 2. Sequential Query Search (matches GUI's start_search_worker_parallel logic) search_diagnostics = [] # Track what happened per query for detailed error messages diff --git a/core/imports/version_mismatch_fallback.py b/core/imports/version_mismatch_fallback.py index 3e0ef92d..2bf37388 100644 --- a/core/imports/version_mismatch_fallback.py +++ b/core/imports/version_mismatch_fallback.py @@ -103,9 +103,12 @@ def select_version_mismatch_fallback( # don't guess which the user wants. return None - # First tried = oldest = highest-confidence (the retry walks candidates - # best-first). The id is a "_