#!/usr/bin/env python3 """КОНТАМИНАЦИОННАЯ ПРОБА ФАЗЫ Д — ЖИЛЬЦАМИ и на книгах, которые фаза реально покупает. Платный. Заказ (Д3 и Д6) требует пробу «ЖИЛЬЦАМИ» — правило эксп-22 §1.1: гонять теми, кто работает, а не удобной моделью. Непригоден по пробе → СТОП и пинг, замену без слова владельца не искать. Риг НЕ пере-изобретается: берётся `eval/role_topology/contamination.py` и настраивается через свои глобали — тем же приёмом, каким `money_d` настраивает кассу, а `sud` — судейский риг. Метод пробы остаётся его: УЗНАВАНИЕ («что за произведение и кто автор») плюс КЛОУЗ ПО ИМЕНИ (из отрывка вырезано имя собственное, модель называет пропущенное). Пороги — его же, объявленные до данных: узнавание ≥3/5 = «знает о книге», клоуз ≥2/5 = «знает конкретику, то есть текст был в обучении». ⚠ ЧТО ЗДЕСЬ ДОБАВЛЕНО И ЗАЧЕМ. 1. **Книги фазы.** Прошлый прогон мерил `gu-zhenren`, `jinpingmei`, `fifty_shades`, `kristoff` и СТАРУЮ японскую книгу. Новая японская (`enkan_no_hate`, замена по слову владельца после срабатывания гардрейла 18+) не мерена ВООБЩЕ, а Д6 покупается именно на ней. 2. **Жильцы вместо удобной модели.** Прошлый прогон гнался `gpt-5.6-luna`. Это не жилец: черновики делает `deepseek-v4-flash`, редактуру `deepseek-v4-pro`. Знание книги ИМИ и есть то, что завышает качество перевода, а знание посторонней модели не значит ничего. 3. **Бюджет вывода поднят.** Редакция 1 прошлой пробы звала flash с 16000 токенов и получала 0–46 знаков: у DeepSeek размышление тарифицируется и считается ВНУТРИ бюджета, поэтому на короткий ответ ничего не оставалось (стена quirks §10; ровно эта же стена сегодня съела 14 клеток арма A1B). Ответ здесь нужен КОРОТКИЙ, а думать модель будет много — значит бюджет должен вмещать размышление ЦЕЛИКОМ, иначе «НЕ ЗНАЮ» будет означать «не успел сказать». ⚠ Если и при поднятом бюджете жилец возвращает пустоту — это НЕ «книга чиста», а непригодность пробы на этом жильце, и она объявляется отдельно, а не растворяется в нуле. 4. **Положительный контроль обязателен на КАЖДОМ жильце.** Нулевой результат неинтерпретируем: «модель не знает книгу» и «проба не работает на этой модели» дают одну картину. Контроль — `jinpingmei` (минский канон, public domain, заведомо в претрейне). Не сработал контроль — аннулируется весь прогон этого жильца, а не отдельная книга. Запуск: contam_d.py --dry # план, $0 contam_d.py # платный """ from __future__ import annotations import importlib.util import sys from pathlib import Path REPO = Path("/home/ubuntu/projects/textmachine") ZONE = Path(__file__).resolve().parent for d in ("dovodka", "role_topology", "tenant_panel"): sys.path.insert(0, str(REPO / "eval" / d)) def _load(name: str, path: Path): spec = importlib.util.spec_from_file_location(name, path) mod = importlib.util.module_from_spec(spec) sys.modules[name] = mod spec.loader.exec_module(mod) return mod MONEY = _load("money_d", ZONE / "money_d.py") CT = _load("contam21", REPO / "eval" / "role_topology" / "contamination.py") # Жильцы: те, кто реально работает на парах. Проба на каждом отдельно. RESIDENTS = ("deepseek-v4-flash", "deepseek-v4-pro") # Книги, которые фаза Д покупает, плюс обязательный положительный контроль. BOOKS_D = { "enkan-ja": dict(path=Path.home() / "books" / "enkan_no_hate_ja.txt", lang="ja", titles=["円環の果てに", "enkan", "円環"], note="ja-ось Д6; первая публикация 2026-07-30, 18 глав — НЕ мерена ни разу"), "kristoff-en": dict(path=Path.home() / "books" / "Kristoff_Jay_-_Empire_of_the_Vampire_3_-_Empire_of_the_Dawn.epub", lang="en", titles=["empire of the dawn", "empire of the vampire", "кристофф", "kristoff"], note="en-ось Д3; luna узнала СЕРИЮ 1 раз из 5 — жильцами не мерена"), "jinpingmei": dict(path=Path.home() / "books" / "jinpingmei" / "jinpingmei-ctext-zhs.txt", lang="zh", titles=["金瓶梅", "золотой лотос", "jin ping mei"], note="ПОЛОЖИТЕЛЬНЫЙ КОНТРОЛЬ — обязателен на каждом жильце"), } def main() -> int: dry = "--dry" in sys.argv print("КОНТАМИНАЦИОННАЯ ПРОБА ФАЗЫ Д — жильцами\n") print(f"{'книга':14s}{'язык':>6s} что это") for b, m in BOOKS_D.items(): ok = "" if m["path"].exists() else " ⛔ ФАЙЛА НЕТ" print(f"{b:14s}{m['lang']:>6s} {m['note']}{ok}") print(f"\nжильцы: {' · '.join(RESIDENTS)}") print("пороги (объявлены ДО данных, взяты из рига эксп-21): " "узнавание ≥3/5 = знает о книге · клоуз ≥2/5 = знает конкретику") if dry: print("\n--dry: покупок нет") return 0 print("\n⚠ платный режим ещё не подключён к кассе фазы — см. TODO ниже") return 0 if __name__ == "__main__": sys.exit(main())