v0.0.5
Changelog
MatchMedia v0.0.5
SequenceMatcher stays on disk grouping only. Candidate ranking is token-set Jaccard plus a residual plot/parent score. Jobs record ranker: set. The release tarball is still binary, config/, public/, and LICENSE.
Ranking
Score is no longer a SequenceMatcher ratio (and no longer +0.15 for year). After the same titleNorm used for grouping (lowercase, strip non-alnum, no stemming):
- Jaccard
Jis the best|q ∩ t| / |q ∪ t|over the job title and each candidate title string (primary title plus every attr whose key starts withtitle). Parent is not inJ. - Plot
funcis length-weighted coverage of content tokens from the job title in the synopsis. Tokens inmatch.plot_stopor shorter than 3 are dropped. A token that appears in two or more synopses in this result list is down-weighted (0.25). parentCovis coverage of those same content tokens from a different parent folder in the candidate title set.- Displayed
Score=J + (1 − J) · max(func, parentCov). Exact title (J = 1) is always Score1. - Year is a sort key only when the job has a year.
Sort: content-token overlap with the job title beats none; then Score; then job title tokens as a prefix of the candidate primary title; then Jaccard; then year.
That stops short near-misses (Frieden, Crashed, Arifureta Kiseki) from beating the long official title, keeps Wednesday / Limitless above suffixed shows, and lets plot lift English disk titles that only have a Japanese TVMaze show.name (Explosion → Bakuen when aliases are absent). Parent residual lifts Magi/Sinbad and Scarlet Bond without giving Adventures a free hit on the / of.
Aliases
Optional provider titles block. TVMaze ships GET /shows/{id}/akas with max: 3. After search, candidates whose primary title already covers every content token of the job skip the extra GET. At most max of the rest are fetched, paced with min_interval_ms. Failed GETs do not fail the search. Only aliases that share a content token with the job are stored as title_aka / title_aka_2 / … so an English AKA can be Jaccard 1 (Erased).
Two franchise AKAs that both copy the same English name still tie at Score 1 and stay manual (I Shall Survive Using Potions! vs Potions Will Save Me; KonoSuba main vs Explosion spin-off when TVMaze lists the spin-off title on both shows).
Auto-match and defer
match.prefer.anime (language: Japanese, kind: Animation) runs before rank. Typed anime jobs use it as before. Untyped scan jobs use the same filter when any candidate matches.
Auto-matched if:
- best Jaccard
>= match.min_scoreand the Jaccard gap is>= match.min_margin, or - prefer actually filtered, and either a single remaining candidate’s Score meets
solo_min_score(shipped0.01), orqueryCov == 1with the usual margin on Score.
A weak solo hit does not use solo_min_score unless prefer filtered. defer: true providers still run only if the fast pass is thin (fewer than match.min_hits or best Jaccard below min_score). A prefer-filtered auto-match on the fast pass skips Jikan.
Config
version: is 0.0.5. New / now-used tunables in config/default.yaml:
match.plot_stop— stop list for plot, parent residual, and content overlapmatch.synopsis_limit— search/detail/catalog clip (shipped 4000 runes; was 400)match.solo_min_score— prefer-solo floormatch.wait_cap— in-memory wait log cap (500)scan.sample_videos— videos sampled per child (5)session.ttl_max_ms— clamp onsession.ttl_ms(shipped 86400000)
match.weights is gone. Score is the convex residual above, not a weighted sum.
Upgrade notes
- Rematch existing sessions if you want set ranking, aliases, and the new Score on old jobs (
ranker: seqrows stay as stored). - Overlay
data/config.yamlmust not rely onmatch.weights. Specials/is still agroup.kindsfolder, not extras. A Specials tree whose files repeat the series title can emit a second job of the same show (Arifureta). Addspecial/specialstogroup.extrasif you want those folded into the parent.- Scan jobs still have empty
type. Movies without OMDb/TMDB keys stayunmatched.