From e179b9bf905f3f83abe3075569c0d66071be5809 Mon Sep 17 00:00:00 2001 From: Breadway Date: Tue, 21 Jul 2026 21:52:40 +0800 Subject: [PATCH] Apply quality gates before queuing for review, not just before auto-grab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "reject sub-1080p when a better resolution exists in this batch" gate (and every other quality gate) only ran on the confident auto-match path — a low-confidence match skipped straight to queue_for_review before ever reaching it. A human review decision is about whether this is genuinely the right show, not a backdoor around quality standards; a title match being ambiguous is no reason to let a worse-quality release through untested. Verified live: several 720p season-pack releases were sitting in the review queue for shows that also had 1080p+ alternatives in the same search batch. Moved the gate check ahead of the review-queue branch so it applies uniformly. --- breadarrd/src/scheduler.rs | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/breadarrd/src/scheduler.rs b/breadarrd/src/scheduler.rs index f47f812..2af2e01 100644 --- a/breadarrd/src/scheduler.rs +++ b/breadarrd/src/scheduler.rs @@ -534,17 +534,6 @@ async fn process_item( episode_id = Some(eid); } - if needs_review { - matcher::queue_for_review( - conn, - &item.title, - &candidate, - Some(&item.link), - Some(source_id), - )?; - return Ok(ProcessOutcome::QueuedForReview); - } - let anime = match media_item.tvdb_id { Some(id) => is_anime(conn, id)?, None => false, @@ -566,10 +555,30 @@ async fn process_item( is_season_pack: season_pack_number.is_some(), }; + // Quality gates — including "reject sub-1080p when a 1080p+ alternative + // exists in this same batch" — apply before a candidate ever reaches a + // human, not just on the confident auto-grab path. A human's review + // decision is about whether this is genuinely the right show/season; + // it was never meant to also be the place quality standards get + // relaxed just because the title match happened to be ambiguous + // (verified live: several 720p season-pack releases sat in the review + // queue for shows that also had 1080p+ releases available in the same + // search, when they should have been silently gate-rejected instead). if let GateResult::Reject(reason) = scoring::evaluate_gates(&parsed, &gate_ctx, &profile) { return Ok(ProcessOutcome::GateRejected(reason)); } + if needs_review { + matcher::queue_for_review( + conn, + &item.title, + &candidate, + Some(&item.link), + Some(source_id), + )?; + return Ok(ProcessOutcome::QueuedForReview); + } + let release_score = scoring::score(&parsed, item.seeders.unwrap_or(0), false, &profile); let existing_best = match (episode_id, season_pack_number) { (Some(eid), _) => best_existing_score(conn, eid)?,