Scoring: resolution preference is a filter, never a score term #113

Closed
opened 2026-08-23 11:55:09 +01:00 by naps62-yolo · 1 comment
Owner

Observed live: a 23 GB 2160p release ranks below several 1080p releases for the same movie.

Root cause: resolution_pref only gates eligibility (arr-core/src/policy.rs, allowed_by_root). The score (arr-core/src/score.rs) has no resolution term — each release scores against its own resolution's size band, so an at-target 1080p (1000 size points) beats a 23 GB 4K (~940–960 against the 2160p band, floor 8 / target 22 / penalty 60 per GiB over) once seeders are added. DESIGN.md §5.5 is silent on cross-resolution ranking; resolution_pref being an ordered list implies a preference the scorer never implements.

Fix:

  1. Add a resolution-rank term to ScoreWeights (policy data, like the existing weights): points per step of resolution_preference, last entry worth zero, each earlier entry one step more.
  2. Size the seeded default so that a 4K anywhere between its floor and a few GiB over target outranks an at-target 1080p, while a 4K far over target (say 10+ GiB) can still lose. With the current 60/GiB penalty something around 300 per step behaves that way — but pick deliberately and write the reasoning down.
  3. Migration: new column or JSON field on policies, seeded for the existing rows (movies main, movies kids, series).
  4. Expose the term in the API score breakdown (the UI explains rankings from the score terms).
  5. Amend DESIGN.md §5.5 to state how resolutions rank against each other — the current text only covers within-band size distance.

Unknown resolution should keep scoring zero on the new term, same spirit as the existing bands: no claim is no opinion, not a penalty.

Observed live: a 23 GB 2160p release ranks below several 1080p releases for the same movie. Root cause: `resolution_pref` only gates eligibility (`arr-core/src/policy.rs`, `allowed_by_root`). The score (`arr-core/src/score.rs`) has no resolution term — each release scores against its own resolution's size band, so an at-target 1080p (1000 size points) beats a 23 GB 4K (~940–960 against the 2160p band, floor 8 / target 22 / penalty 60 per GiB over) once seeders are added. DESIGN.md §5.5 is silent on cross-resolution ranking; `resolution_pref` being an ordered list implies a preference the scorer never implements. Fix: 1. Add a resolution-rank term to `ScoreWeights` (policy data, like the existing weights): points per step of `resolution_preference`, last entry worth zero, each earlier entry one step more. 2. Size the seeded default so that a 4K anywhere between its floor and a few GiB over target outranks an at-target 1080p, while a 4K far over target (say 10+ GiB) can still lose. With the current 60/GiB penalty something around 300 per step behaves that way — but pick deliberately and write the reasoning down. 3. Migration: new column or JSON field on `policies`, seeded for the existing rows (movies main, movies kids, series). 4. Expose the term in the API score breakdown (the UI explains rankings from the score terms). 5. Amend DESIGN.md §5.5 to state how resolutions rank against each other — the current text only covers within-band size distance. Unknown resolution should keep scoring zero on the new term, same spirit as the existing bands: no claim is no opinion, not a penalty.
naps62-yolo added the area/coredifficulty/moderatephase/2-logictype/feature labels 2026-08-23 11:55:09 +01:00
Author
Owner

Fixed in a5b3680, on main.

ScoreWeights gains resolution_step: each step up resolution_pref is worth that many points, the last entry zero, an unranked or unclaimed resolution zero as well.

Seeded at 300, chosen against the 4K band (target 22 GiB, 60 points per gibibyte over) — five gibibytes of overshoot. A 4K up to about 27 GB now beats an at-target 1080p; a 40 GB one still loses. Below target a 4K has to be within about four gibibytes of its own target to win, which keeps an 8 GB mud-quality 4K from beating a good 1080p.

  • Migration 0015_policy_resolution_rank.sql seeds all existing rows. The 0004 column default predates the field, so the loader falls back to the engine default when it is absent rather than ranking everything the same.
  • /api/releases responses carry score_terms (size, source, seeders, resolution), so the UI can explain a ranking from the terms.
  • DESIGN.md §5.5 now states how resolutions rank against each other and why 300.

just ci green.

Fixed in a5b3680, on main. `ScoreWeights` gains `resolution_step`: each step up `resolution_pref` is worth that many points, the last entry zero, an unranked or unclaimed resolution zero as well. Seeded at 300, chosen against the 4K band (target 22 GiB, 60 points per gibibyte over) — five gibibytes of overshoot. A 4K up to about 27 GB now beats an at-target 1080p; a 40 GB one still loses. Below target a 4K has to be within about four gibibytes of its own target to win, which keeps an 8 GB mud-quality 4K from beating a good 1080p. - Migration `0015_policy_resolution_rank.sql` seeds all existing rows. The 0004 column default predates the field, so the loader falls back to the engine default when it is absent rather than ranking everything the same. - `/api/releases` responses carry `score_terms` (`size`, `source`, `seeders`, `resolution`), so the UI can explain a ranking from the terms. - DESIGN.md §5.5 now states how resolutions rank against each other and why 300. `just ci` green.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: yolo/arr#113