spencernorton commited on
Commit
375cd41
·
verified ·
1 Parent(s): d6bc955

Release armiger-zero-cue-catalog v2.1.0 (standalone featurizer, 48-tensor swarm adapter, and audited unmutated-key benchmarks)

Browse files
Files changed (3) hide show
  1. README.md +18 -17
  2. config.json +35 -10
  3. zero_cue_plugin.py +7 -3
README.md CHANGED
@@ -16,7 +16,7 @@ pipeline_tag: text-classification
16
  <h1 align="center">Armiger Plugin #3 — Zero-Cue Catalog &amp; Structural Disambiguator (<code>armiger-zero-cue-catalog</code>)</h1>
17
 
18
  <p align="center">
19
- <strong>Resolves bare-title ("zero-cue") torrents lacking season/episode syntax via an offline 929,400-key normalized media catalog and structural release rules, lifting Movie-vs-TV accuracy to <code>99.46%</code> and 11-class accuracy to <code>98.48%</code>.</strong><br>
20
  Available standalone here and pre-bundled inside <a href="https://huggingface.co/NorviTech/armiger-ultra"><code>NorviTech/armiger-ultra</code></a>.
21
  </p>
22
 
@@ -33,18 +33,19 @@ In real-world BitTorrent/DHT indexing, **2% to 4%** of movie, TV, and anime torr
33
  - `[SubGroup] Bare Japanese/English Title [1080p].mkv` (a theatrical anime film vs. a TV OVA/series without an episode number)
34
  - `Director Name - Movies 1-6 Collection (1979-1998) 1080p` (a multi-file movie pack whose 6 `.mkv` files look identical in file-count to a 6-episode TV mini-series)
35
 
36
- Even a 70B+ parameter cloud LLM must guess when given only a bare title unless it can consult a media catalog. `NorviTech/armiger-zero-cue-catalog` pairs deterministic structural guards (for multi-item media collections, interactive software archives, and structured educational materials) with an offline, O(1) hash-table lookup across **929,400 normalized keys** (`472,017` `(title, year)` pairs, `257,016` anime title stems, and `200,367` unambiguous long titles).
37
 
38
- ## Measured Accuracy Lift Across All 6 Evaluation Cohorts
39
 
40
- | Evaluation Cohort | Neural Backbone Only (`Armiger Ultra`) | + Structural Guards | **+ `armiger-zero-cue-catalog` (`Armiger Ultra`)** | **+ `armiger-zero-cue-catalog` (`Armiger 8.3 MB`)** |
41
  | :--- | :---: | :---: | :---: | :---: |
42
- | **Gold Standard (`N=2,835`)** | `97.45%` | `97.81%` | **`98.48%`** (`99.46%` Movie-vs-TV) | **`97.92%`** (`99.15%` Movie-vs-TV) |
43
- | **Fresh Torrents (`N=1,354`)** | `95.79%` | `95.94%` | **`96.60%`** | **`96.38%`** |
44
- | **Hard Edge-Cases (`N=1,025`)** | `95.71%` | `96.10%` | **`97.17%`** | **`96.20%`** |
45
- | **Validation Holdout (`N=2,237`)** | `96.92%` | `97.05%` | **`97.32%`** | **`96.51%`** |
46
- | **Specialist Torrents (`N=1,837`)** | `93.85%` | `94.18%` | **`98.26%`** | **`97.82%`** |
47
- | **Multilingual Torrents (`N=2,828`)** | `95.44%` | `95.69%` | **`98.02%`** | **`97.81%`** |
 
48
 
49
  ## Quickstart
50
 
@@ -64,14 +65,14 @@ print(res)
64
 
65
  ## Part of the Armiger Modular Plugin Suite
66
 
67
- | Plugin Repository | Bundled in `Armiger Ultra`? | Footprint | Core Capability & Measured Impact |
68
  | :--- | :---: | :---: | :--- |
69
- | **[`NorviTech/armiger-swarm-survival`](https://huggingface.co/NorviTech/armiger-swarm-survival)** | **Yes** (`swarm_adapter.pt`, `swarm_survival.py`) | `163 KB` | **SwarmSurvivalNet v2 & Honeypot Residual Adapter:** **`96.83%`** Swarm Liveliness AUROC (vs. `53.04%` raw seeders), **`100.0%`** fake-seeder malware trap recall, **`0%`** content-category flip guarantee. |
70
- | **[`NorviTech/armiger-swarm-priors`](https://huggingface.co/NorviTech/armiger-swarm-priors)** | **Yes** (`swarm_priors.py`) | `29.4 KB` | **Empirical Bayes Swarm & Release-Group Priors:** 4-pathway tracker scrape prior engine, mandatory modality dropout (`p=0.60`), anomaly feature extraction, and public-tracker passkey safety filter. |
71
- | **[`NorviTech/armiger-zero-cue-catalog`](https://huggingface.co/NorviTech/armiger-zero-cue-catalog)** | **Yes** (`zero_cue_plugin.py`, `validated_zero_cue_catalog.json`) | `36.0 MB` | **Zero-Cue Catalog & Structural Disambiguator:** Offline 929,400-key normalized title-year & entity reference lookup + structural multi-file & format disambiguation rules; lifts Movie-vs-TV accuracy to **`99.46%`** and 11-class accuracy to **`98.48%`** (`98.93%` Hard Edge-Cases). |
72
- | **[`NorviTech/armiger-audio-guard`](https://huggingface.co/NorviTech/armiger-audio-guard)** | **Yes** (`audio_language_guard.py`) | `4.2 KB` | **Cross-Head Audio Language & Anime Dub Guard:** Couples `title_language` (`P(Foreign Title)`) with `lang` head to disambiguate `.en.` prepositions, `<Foreign>.ENG.Sub`, regional dubs, and `MULTi (FR EN)` tags; reaches **`98.72%`** Gold Standard and **`99.88%`** Hard Edge-Case audio accuracy. |
73
- | **[`NorviTech/armiger-calibration-dht`](https://huggingface.co/NorviTech/armiger-calibration-dht)** | **Yes** (`calibration.json`, `calibration_and_dht.py`, `armiger_dht_rsi.py`) | `115 KB` | **Conformal Calibration, BEP-44 DHT Updater & Distributed RSI Engine:** Per-head temperature scaling ($T_h$), Mondrian safety gates (`99.95%` junk balanced accuracy), `Ed25519` threshold-signed `BEP-44`/`BEP-46` DHT hot-reload, universal media-webhook/qBittorrent/Transmission/ffprobe ground-truth RSI, `X25519`+`ChaCha20-Poly1305` AEAD, distinct-ASN quorum, and 500-canary regression gate (`36/36` tests). |
74
- | **[`NorviTech/armiger-dht-db-sync`](https://huggingface.co/NorviTech/armiger-dht-db-sync)** | **Yes** (`csam_guard.py`, `armiger_dht_db_sync.py`) | `98 KB` | **Modular, CSAM-Protected, Encrypted BEP-44/BEP-46 DHT Database Sync:** Multi-stage CSAM & abuse pre-ingest blocker, `Ed25519`-signed blinded `SHA-256` tombstone purge engine, 10-category $\times$ 14-language $\times$ 7-quality sharded subscriptions with strict default-off `xxx` isolation, `X25519`+`ChaCha20-Poly1305` AEAD, binary Merkle proofs, and $K$-of-$N$ distinct-ASN Sybil quorum (`27/27` tests). |
75
 
76
  ---
77
 
 
16
  <h1 align="center">Armiger Plugin #3 — Zero-Cue Catalog &amp; Structural Disambiguator (<code>armiger-zero-cue-catalog</code>)</h1>
17
 
18
  <p align="center">
19
+ <strong>Resolves bare-title ("zero-cue") torrents lacking season/episode syntax via an offline 929,400-entry <code>BLAKE2b-64</code> cryptographically hashed media catalog (<code>26.0 MB</code>) and deterministic structural rules, lifting 5-split (<code>N=10,262</code>) category accuracy from <code>94.00%</code> to <code>95.42%</code> and specialist zero-cue accuracy from <code>87.40%</code> to <code>91.50%</code> (<code>+4.10 pp</code>).</strong><br>
20
  Available standalone here and pre-bundled inside <a href="https://huggingface.co/NorviTech/armiger-ultra"><code>NorviTech/armiger-ultra</code></a>.
21
  </p>
22
 
 
33
  - `[SubGroup] Bare Japanese/English Title [1080p].mkv` (a theatrical anime film vs. a TV OVA/series without an episode number)
34
  - `Director Name - Movies 1-6 Collection (1979-1998) 1080p` (a multi-file movie pack whose 6 `.mkv` files look identical in file-count to a 6-episode TV mini-series)
35
 
36
+ Even a 70B+ parameter cloud LLM must guess when given only a bare title unless it can consult a media catalog. `NorviTech/armiger-zero-cue-catalog` pairs deterministic structural guards with an offline, O(1) hash-table lookup across **929,400 `BLAKE2b-64` (`person=b"ArmigZCC"`) cryptographically hashed keys** (`472,017` `(title, year)` pairs, `257,016` anime title stems, and `200,367` unambiguous long titles — zero plain-text media titles stored on disk, zero `info_hash` memorization).
37
 
38
+ ## Measured Accuracy Lift Across All 6 Evaluation Cohorts (Unmutated Ground-Truth Keys)
39
 
40
+ | Evaluation Cohort (Unmutated `rows.y`) | Valid `N` | Standalone Neural (`FP32` / `INT8`) | **Fair Blind Hybrid (`+ armiger-zero-cue-catalog` FP32 / INT8)** | Net Lift |
41
  | :--- | :---: | :---: | :---: | :---: |
42
+ | **`oct15_confirmation` (Gold Standard)** | `2,835` | `95.03%` / `95.06%` (`96.60%` Movie-vs-TV) | **`95.49%`** / **`95.49%`** (**`97.15%`** Movie-vs-TV) | `+0.46 pp` |
43
+ | **`fresh_confirmation` (Fresh Holdout)** | `1,402` | `94.51%` / `94.44%` | **`94.58%`** / **`94.51%`** | `+0.07 pp` |
44
+ | **`beyond_confirmation` (Hard Edge-Cases)** | `1,025` | `92.88%` / `92.88%` (`88.74%` Movie-vs-TV) | **`95.12%`** / **`95.12%`** (**`96.54%`** Movie-vs-TV) | **`+2.24 pp`** |
45
+ | **`tc_truespec_2000` (Specialist Zero-Cue)** | `2,000` | `87.40%` / `87.35%` | **`91.50%`** / **`91.50%`** | **`+4.10 pp`** |
46
+ | **`tc_truespec_multilang_3000` (Multilingual)** | `3,000` | `97.50%` / `97.37%` | **`98.47%`** / **`98.40%`** | **`+0.97 pp`** |
47
+ | **`calibration` (Calibration Split)** | `424` | `96.46%` / `96.46%` | **`96.70%`** / **`96.70%`** | `+0.24 pp` |
48
+ | **5-Split Weighted Mean (`N=10,262`)** | **`10,262`** | **`94.00%`** / **`93.95%`** | **`95.42%`** / **`95.39%`** | **`+1.42 pp`** |
49
 
50
  ## Quickstart
51
 
 
65
 
66
  ## Part of the Armiger Modular Plugin Suite
67
 
68
+ | Plugin Repository | Bundled in `Armiger Ultra`? | Footprint | Core Capability & Measured Impact (Unmutated Ground-Truth Keys) |
69
  | :--- | :---: | :---: | :--- |
70
+ | **[`NorviTech/armiger-swarm-survival`](https://huggingface.co/NorviTech/armiger-swarm-survival)** | **Yes** (`swarm_adapter.pt`, `swarm_survival.py`) | `167 KB` (`132 KB` `.pt`) | **SwarmSurvivalNet v2 & Honeypot Residual Adapter:** Executes full 48-tensor neural forward pass (`SwarmResidualAdapter`); **`96.83%`** Multi-Source Warehouse AUROC (`N=10,278`, vs. `53.02%` raw seeders), **`92.42%`** / **`93.03%`** Public-Tracker AUROC (`N=757` / `N=493`, vs. `85.17%` raw seeders), **`100.0%`** fake-seeder malware trap recall, **`0.00%`** content-category flip guarantee. |
71
+ | **[`NorviTech/armiger-swarm-priors`](https://huggingface.co/NorviTech/armiger-swarm-priors)** | **Yes** (`swarm_priors.py`) | `29.3 KB` | **Empirical Bayes Swarm & Release-Group Priors:** 4-pathway tracker scrape prior engine (`86.64%` formula AUROC), mandatory modality dropout (`p=0.60`), anomaly feature extraction, and public-tracker passkey safety filter. |
72
+ | **[`NorviTech/armiger-zero-cue-catalog`](https://huggingface.co/NorviTech/armiger-zero-cue-catalog)** | **Yes** (`zero_cue_plugin.py`, `validated_zero_cue_catalog.json`) | `26.0 MB` (`BLAKE2b-64`) | **Zero-Cue Catalog & Structural Disambiguator:** Offline `929,400`-entry `BLAKE2b-64` cryptographically hashed catalog (`472,017` `(title, year)`, `257,016` anime stems, `200,367` long titles) + deterministic structural rules; lifts 5-split (`N=10,262`) weighted category accuracy from **`94.00%`** (Standalone Neural) to **`95.42%`** (Fair Blind Hybrid), `beyond_confirmation` (`N=1,025`) from **`92.88%`** to **`95.12%`**, and `tc_truespec_2000` (`N=2,000`) from **`87.40%`** to **`91.50%`** (`+4.10 pp`). |
73
+ | **[`NorviTech/armiger-audio-guard`](https://huggingface.co/NorviTech/armiger-audio-guard)** | **Yes** (`audio_language_guard.py`) | `3.3 KB` | **Cross-Head Audio Language & Anime Dub Guard:** Couples `title_language` (`P(Foreign Title)`) with `lang` head to disambiguate `.en.` prepositions, `<Foreign>.ENG.Sub`, regional dubs, and `MULTi (FR EN)` tags; lifts binary English-vs-Foreign audio accuracy on `oct15_confirmation` (`N=545`) from **`96.88%`** (Standalone Neural) to **`97.80%`** (`92.75%` 3-class `N=772`). |
74
+ | **[`NorviTech/armiger-calibration-dht`](https://huggingface.co/NorviTech/armiger-calibration-dht)** | **Yes** (`calibration.json`, `calibration_and_dht.py`, `armiger_dht_rsi.py`) | `181 KB` | **Conformal Calibration, BEP-44 DHT Updater & Distributed RSI Engine:** Per-head temperature scaling ($T_h$), Mondrian safety gates (**`100.00%`** junk accuracy on `oct15_confirmation` `N=2,170` & `fresh_confirmation` `N=1,291`, **`99.90%`** on `beyond_confirmation` `N=977`), Hybrid `Ed25519`+`WOTS+-SHAKE256` signed `BEP-44`/`BEP-46` DHT hot-reload, Hybrid `X25519`+`ML-KEM-768`+`ChaCha20-Poly1305` AEAD, distinct-ASN quorum, and 500-canary regression gate (`47/47` tests). |
75
+ | **[`NorviTech/armiger-dht-db-sync`](https://huggingface.co/NorviTech/armiger-dht-db-sync)** | **Yes** (`csam_guard.py`, `armiger_dht_db_sync.py`) | `155 KB` | **Modular, CSAM-Protected, Encrypted BEP-44/BEP-46 DHT Database Sync:** Multi-stage CSAM & abuse pre-ingest blocker, Hybrid PQ-signed blinded `SHA-256` tombstone purge engine, 10-category $\times$ 14-language $\times$ 7-quality sharded subscriptions with strict default-off `xxx` isolation, `X25519`+`ML-KEM-768`+`ChaCha20-Poly1305` AEAD, binary Merkle proofs, and $K$-of-$N$ distinct-ASN Sybil quorum (`27/27` tests). |
76
 
77
  ---
78
 
config.json CHANGED
@@ -2,27 +2,52 @@
2
  "plugin_name": "armiger-zero-cue-catalog",
3
  "version": "2.1.0",
4
  "part_of_suite": "NorviTech/armiger-ultra",
5
- "architecture": "offline-normalized-catalog-plus-structural-disambiguator",
 
6
  "catalog_counts": {
7
  "title_year_map": 472017,
8
  "anime_map": 257016,
9
  "title_only_map": 200367,
10
  "total_keys": 929400
11
  },
12
- "benchmarks": {
13
- "gold_standard_11class_accuracy_ultra_pct": 98.48,
14
- "gold_standard_11class_accuracy_armiger_pct": 97.92,
15
- "gold_standard_movie_vs_tv_accuracy_ultra_pct": 99.46,
16
- "gold_standard_catalog_matching_rate_ultra_pct": 98.69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  },
18
  "artifacts": {
19
  "zero_cue_plugin.py": {
20
- "size_bytes": 10882,
21
- "sha256": "8f93a357195ece2ba1609d8804cbc3e5abf7dde1785bf212df931ea4257ce395"
22
  },
23
  "validated_zero_cue_catalog.json": {
24
- "size_bytes": 36004850,
25
- "sha256": "f5b9b63ef8b2352c7b3b5cd107259aa0d95cbeba1276fa98b80a025cdd486b18"
26
  }
27
  }
28
  }
 
2
  "plugin_name": "armiger-zero-cue-catalog",
3
  "version": "2.1.0",
4
  "part_of_suite": "NorviTech/armiger-ultra",
5
+ "architecture": "blake2b-64-hashed-offline-catalog-plus-structural-disambiguator",
6
+ "key_derivation": "BLAKE2b-64 (digest_size=8, person=b'ArmigZCC') with legacy plain-text fallback",
7
  "catalog_counts": {
8
  "title_year_map": 472017,
9
  "anime_map": 257016,
10
  "title_only_map": 200367,
11
  "total_keys": 929400
12
  },
13
+ "benchmarks_unmutated_ground_truth": {
14
+ "oct15_confirmation_n2835_neural_to_hybrid_pct": [
15
+ 95.03,
16
+ 95.49
17
+ ],
18
+ "oct15_movie_vs_tv_n1296_neural_to_hybrid_pct": [
19
+ 96.53,
20
+ 97.15
21
+ ],
22
+ "fresh_confirmation_n1402_neural_to_hybrid_pct": [
23
+ 94.51,
24
+ 94.58
25
+ ],
26
+ "beyond_confirmation_n1025_neural_to_hybrid_pct": [
27
+ 92.88,
28
+ 95.12
29
+ ],
30
+ "tc_truespec_2000_n2000_neural_to_hybrid_pct": [
31
+ 87.4,
32
+ 91.5
33
+ ],
34
+ "tc_truespec_multilang_3000_n3000_neural_to_hybrid_pct": [
35
+ 97.5,
36
+ 98.47
37
+ ],
38
+ "five_split_weighted_n10262_neural_to_hybrid_pct": [
39
+ 94.0,
40
+ 95.42
41
+ ]
42
  },
43
  "artifacts": {
44
  "zero_cue_plugin.py": {
45
+ "size_bytes": 11978,
46
+ "sha256": "02a34beff29bc2b5166fe0a1efa2a35c3705e03b7b1dff69d390c271ac7d4036"
47
  },
48
  "validated_zero_cue_catalog.json": {
49
+ "size_bytes": 25990894,
50
+ "sha256": "3f42219f7e9ac1b38e7aa0f1301ae96298dd58e7d71960c371a4cdaf86c3d0b2"
51
  }
52
  }
53
  }
zero_cue_plugin.py CHANGED
@@ -30,8 +30,9 @@ IDX_COURSE = 9
30
 
31
  EXPLICIT_TV_RE = re.compile(
32
  r"(?i)(?:\bS\d{1,2}E\d{1,3}\b|\bS\d{1,2}\s*-\s*S\d{1,2}\b|\bSeason\s*(?:0?[1-9]|[1-9]\d)\b|\bStagione\s*\d+\b|\bSaison\s*\d+\b|"
33
- r"\bTemporada\s*\d+\b|\bStaffel\s*\d+\b|\bComplete\s+Series\b|\bTV\s*Series\b|\bMini\s*Series\b|\bTVRip\b|"
34
  r"\bEpisode\s+[1-9]\d*\b|\bEp\.?\s*[1-9]\d*\b|\bEpiz[oó]da\b|\bЭпизод\s*\d+\b|第[一二三四五六七八九十\d]+[季集]|【[^】]*日剧】|更新至\d+[期集]|\s-\s(?:SP|NCOP|NCED)\d*\b|\b\d{3}\s*\[(?:480p|720p|1080p|2160p)\]|"
 
35
  r"\bFull[\s\._]Event\b|\bPPV\b|\b1-\d{2}\s*\+\s*OVA\b|\btemp\.\d+\.completa\b|"
36
  r"\b\d{2}\s*-\s*\d{2,3}\s+VOSTFR\b|\s-\s\d{2,3}(?:v\d)?\s*(?:\[|\(|\b1080p\b|\b720p\b))"
37
  )
@@ -39,6 +40,7 @@ EXPLICIT_TV_RE = re.compile(
39
  EXPLICIT_MOVIE_PACK_RE = re.compile(
40
  r"(?i)(?:\bMovies?\s*\d{1,2}\s*[-~]\s*\d{1,2}\b|\bMovies?\s+Collection\b|\bTrilogy\b|\bQuadrilogy\b|\bTetralogy\b|"
41
  r"\bAnthology\b|\b\d+\s+Movies?\s+Pack\b|\[\d-\d\]\s*\[m?1080p\]\s*\[\d{4}-\d{4}\]|\bThe\s+Movie\b|"
 
42
  r"\bMovie\s+-\s+00\b|\s-\s*Movie\s*(?:\[|\(|V\d)|\bMovie\s+\d{1,2}\s*-|\bMovie:\s|"
43
  r"\bGekijouban\b|\bFilm\s+Collection\b|\bIl\s+Film\b|\bLe\s+Film\b|\bDer\s+Film\b|\bKolekcja\b|"
44
  r"\bTheatrical\s+Cut\b|\bDirector'?s\s+Cut\b|\bExtra\s+Edition\b)"
@@ -225,8 +227,10 @@ def apply_structural_and_zero_cue_disambiguation(
225
  return IDX_XXX, "structural_adult_siterip"
226
 
227
  if EXPLICIT_COMIC_RE.search(raw_name) and not re.search(r"(?i)how\s+to\s+draw", raw_name):
228
- p[IDX_COMIC] = max(p[IDX_COMIC], 0.90)
229
- return IDX_COMIC, "structural_comic_archive"
 
 
230
 
231
  if has_movie_cue and not has_tv_cue:
232
  if p[IDX_MOVIE] + p[IDX_TV] > 0.45:
 
30
 
31
  EXPLICIT_TV_RE = re.compile(
32
  r"(?i)(?:\bS\d{1,2}E\d{1,3}\b|\bS\d{1,2}\s*-\s*S\d{1,2}\b|\bSeason\s*(?:0?[1-9]|[1-9]\d)\b|\bStagione\s*\d+\b|\bSaison\s*\d+\b|"
33
+ r"\bTemporada\s*\d+\b|\bStaffel\s*\d+\b|\bComplete\s+Series\b|\bTV\s*Series\b|\bMini\s*Series\b|"
34
  r"\bEpisode\s+[1-9]\d*\b|\bEp\.?\s*[1-9]\d*\b|\bEpiz[oó]da\b|\bЭпизод\s*\d+\b|第[一二三四五六七八九十\d]+[季集]|【[^】]*日剧】|更新至\d+[期集]|\s-\s(?:SP|NCOP|NCED)\d*\b|\b\d{3}\s*\[(?:480p|720p|1080p|2160p)\]|"
35
+ r"\b[1-9]\d{2,3}\s*\((?:WEBRip|WEB-DL|BDRip|DVDRip|1080p|720p|480p)\b|"
36
  r"\bFull[\s\._]Event\b|\bPPV\b|\b1-\d{2}\s*\+\s*OVA\b|\btemp\.\d+\.completa\b|"
37
  r"\b\d{2}\s*-\s*\d{2,3}\s+VOSTFR\b|\s-\s\d{2,3}(?:v\d)?\s*(?:\[|\(|\b1080p\b|\b720p\b))"
38
  )
 
40
  EXPLICIT_MOVIE_PACK_RE = re.compile(
41
  r"(?i)(?:\bMovies?\s*\d{1,2}\s*[-~]\s*\d{1,2}\b|\bMovies?\s+Collection\b|\bTrilogy\b|\bQuadrilogy\b|\bTetralogy\b|"
42
  r"\bAnthology\b|\b\d+\s+Movies?\s+Pack\b|\[\d-\d\]\s*\[m?1080p\]\s*\[\d{4}-\d{4}\]|\bThe\s+Movie\b|"
43
+ r"\(\s*Movies?\s*\)|\[\s*Movies?\s*\]|"
44
  r"\bMovie\s+-\s+00\b|\s-\s*Movie\s*(?:\[|\(|V\d)|\bMovie\s+\d{1,2}\s*-|\bMovie:\s|"
45
  r"\bGekijouban\b|\bFilm\s+Collection\b|\bIl\s+Film\b|\bLe\s+Film\b|\bDer\s+Film\b|\bKolekcja\b|"
46
  r"\bTheatrical\s+Cut\b|\bDirector'?s\s+Cut\b|\bExtra\s+Edition\b)"
 
227
  return IDX_XXX, "structural_adult_siterip"
228
 
229
  if EXPLICIT_COMIC_RE.search(raw_name) and not re.search(r"(?i)how\s+to\s+draw", raw_name):
230
+ top_i = int(max(range(len(p)), key=p.__getitem__))
231
+ if top_i in (IDX_EBOOK, IDX_COMIC) or p[top_i] < 0.90:
232
+ p[IDX_COMIC] = max(p[IDX_COMIC], 0.90)
233
+ return IDX_COMIC, "structural_comic_archive"
234
 
235
  if has_movie_cue and not has_tv_cue:
236
  if p[IDX_MOVIE] + p[IDX_TV] > 0.45: