Apply quality gates before queuing for review, not just before auto-grab

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.
This commit is contained in:
Breadway 2026-07-21 21:52:40 +08:00
parent 2f0d8300ce
commit e179b9bf90

View file

@ -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)?,