Rank subtitle candidates in arr-core #185

Closed
opened 2026-08-24 21:28:31 +01:00 by naps62-yolo · 1 comment
Owner

Rank subtitle candidates in arr-core, pure and heavily tested, alongside the
release scoring in §5.5. No IO, no provider knowledge — the input is a list of
candidates and the facts known about the media file, the output is an ordered
verdict list in the shape §9.3 already renders.

Rules, from DESIGN.md §15 (added by #183):

  • A moviehash match wins outright. It identifies the exact file and nothing
    else can beat it.
  • Then an exact release-name match, then same release group or same source,
    then uploader rating and download count as tiebreakers.
  • A forced candidate is never eligible. It covers foreign-language lines only
    and cannot satisfy a want.
  • An SDH candidate is eligible but ranks below any plain candidate for the same
    language.
  • Every rejected candidate names the rule that rejected it, as a value the API
    and UI can render — not a string built for a log line.

The verdict vocabulary mirrors the release path (eligible / rejected(rule))
so the manual view in §9.3 needs no second concept. There is no waived
bucket here: nothing about a subtitle is worth overriding by hand, and the
manual grab path (#199) lets the operator pick any candidate directly.

Non-goals: fetching, downloading, deciding what is wanted. Wantedness is a
reconcile-loop question (#196).

Depends on: #183

Rank subtitle candidates in `arr-core`, pure and heavily tested, alongside the release scoring in §5.5. No IO, no provider knowledge — the input is a list of candidates and the facts known about the media file, the output is an ordered verdict list in the shape §9.3 already renders. Rules, from DESIGN.md §15 (added by #183): - A `moviehash` match wins outright. It identifies the exact file and nothing else can beat it. - Then an exact release-name match, then same release group or same source, then uploader rating and download count as tiebreakers. - A forced candidate is never eligible. It covers foreign-language lines only and cannot satisfy a want. - An SDH candidate is eligible but ranks below any plain candidate for the same language. - Every rejected candidate names the rule that rejected it, as a value the API and UI can render — not a string built for a log line. The verdict vocabulary mirrors the release path (`eligible` / `rejected(rule)`) so the manual view in §9.3 needs no second concept. There is no `waived` bucket here: nothing about a subtitle is worth overriding by hand, and the manual grab path (#199) lets the operator pick any candidate directly. Non-goals: fetching, downloading, deciding what is wanted. Wantedness is a reconcile-loop question (#196). Depends on: #183
naps62-yolo added this to the Subtitles milestone 2026-08-24 21:28:31 +01:00
naps62-yolo added the area/coretype/featuredifficulty/moderatephase/9-subtitles labels 2026-08-24 21:28:31 +01:00
naps62-yolo added a new dependency 2026-08-24 21:29:27 +01:00
naps62-yolo added a new dependency 2026-08-24 21:29:27 +01:00
Author
Owner

Implemented subtitle candidate ranking in arr-core (crates/arr-core/src/subs.rs), pure and IO-free per §15. SubtitleTarget carries the known facts about the media file (moviehash, release_name, release_group, source); SubtitleCandidate carries a provider's reported evidence. rank() returns candidates ordered best-first, each paired with a SubtitleVerdict — Eligible or Rejected(SubtitleRule), mirroring the release path's verdict shape with no waived bucket. A forced candidate is always Rejected(SubtitleRule::Forced). Among eligible candidates, plain always outranks SDH for the same language (an absolute split, not a tiebreaker); within that split the order is moviehash match, then exact release-name match, then shared release group or source, then uploader rating and download count. 7 new tests cover each tier and the forced/SDH carve-outs; 130 total in arr-core, all passing.

Branch: subtitles/185-rank-subs

just ci passed (475/475 tests, clippy/fmt/machete/tokens all clean).

Findings

None outside this issue's scope.

Implemented subtitle candidate ranking in `arr-core` (`crates/arr-core/src/subs.rs`), pure and IO-free per §15. `SubtitleTarget` carries the known facts about the media file (`moviehash`, `release_name`, `release_group`, `source`); `SubtitleCandidate` carries a provider's reported evidence. `rank()` returns candidates ordered best-first, each paired with a `SubtitleVerdict` — `Eligible` or `Rejected(SubtitleRule)`, mirroring the release path's verdict shape with no `waived` bucket. A forced candidate is always `Rejected(SubtitleRule::Forced)`. Among eligible candidates, plain always outranks SDH for the same language (an absolute split, not a tiebreaker); within that split the order is `moviehash` match, then exact release-name match, then shared release group or source, then uploader rating and download count. 7 new tests cover each tier and the forced/SDH carve-outs; 130 total in `arr-core`, all passing. Branch: `subtitles/185-rank-subs` `just ci` passed (475/475 tests, clippy/fmt/machete/tokens all clean). ## Findings None outside this issue's scope.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: yolo/arr#185