#!/usr/bin/env python3 """Д6 — РАЗВЕДОЧНАЯ ОСЬ ja→ru на 9 единицах «円環の果てに». Платный. ⚠ СТАТУС — РАЗВЕДКА, объявлен пре-регистрацией (Д0.5) и закреплён арифметикой: при n=9 и sd 2.90 MDE оси 2.90 против цели 2.00, то есть несущего вывода она дать НЕ МОЖЕТ ни при каком исходе. `power.FORCED_DESCRIPTIVE` держит это механически — ось объявлена описательной ДО денег, и превращать её результат в вывод «японский ведёт себя так-то» нельзя даже при красивых числах. Механизмы не дублируются: базы покупает общий `contour.buy_bases`, однопроходку — общий `contour.cmd_run`. Здесь только японо-специфичное — единицы, модели, касса. D0 черновик (`deepseek-v4-flash`) база J0 боевая связка: черновик + боевой редактор эталон оси J2 однопроходка уравненного мандата единственный контур разведки Контроль оси — `J0/D0`: покупает ли редактор что-нибудь поверх черновика на этой паре. ⚠ Материал прошёл гардрейл 18+ (0 срабатываний из 48 чанков) и контам-пробу жильцами (0/5 узнавание и 0/5 клоуз у обоих при сработавшем положительном контроле). Запуск: ja_axis.py --dry | --bases | --arms | --selftest """ from __future__ import annotations import importlib.util import json import sys from pathlib import Path REPO = Path("/home/ubuntu/projects/textmachine") ZONE = Path(__file__).resolve().parent for d in ("dovodka", "editor_tier", "tenant_panel", "role_topology", "bank_arbitration"): 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 C = _load("contour_ja", ZONE / "contour.py") MJ = _load("material_ja_ax", ZONE / "material_ja.py") MONEY, PR, PARA = C.MONEY, C.PR, C.PARA DRAFT_MODEL = "deepseek-v4-flash" EDITOR = "deepseek-v4-pro" PFX = "dv-c" # ⚠ Японский плотнее китайского на знак, а размышление DeepSeek тарифицируется ВНУТРИ бюджета: # при умолчании рига 16000 три клетки из 27 вернулись пустыми с `finish=length`. MAX_OUT = 32000 def units() -> list[dict]: """9 приколотых единиц. Манифест обязателен и уже заморожен.""" return MJ.units() def text_of(tg: str) -> str: f = MONEY.OUT / f"{tg}.json" if not f.exists(): return "" return json.loads(f.read_text(encoding="utf-8")).get("content") or "" def base_draft(uid: str) -> str: t = text_of(f"{PFX}-d0-{uid}") if not t.strip(): return "" why = C.draft_defect(t) if why: print(f" ⚠ {uid}: черновик БРАКОВАН гейтом проекта ({why}) — единица непригодна") return "" return t def base_j0(uid: str) -> str: return text_of(f"{PFX}-j0-{uid}") def wire() -> None: C.configure(PARA.JA, units_provider=units, base_draft_hook=base_draft, base_a0_hook=base_j0, max_out=MAX_OUT) def _law(src: str) -> str | None: bf = PARA.JA.bank_file return PR.law_block(PR.terms_in(src, bf), bf) def cmd_bases() -> None: wire() C.buy_bases("ФД-C", units(), PFX, "D0", "J0", DRAFT_MODEL, EDITOR, "ja-ru", _law, 0.006) def cmd_arms() -> None: wire() C.cmd_run(["J2"]) def cmd_refill() -> None: """Карантин пустых клеток и повторная покупка с поднятым бюджетом вывода.""" wire() tags = [f"{PFX}-{a}-{u['uid']}" for u in units() for a in ("d0", "j0", "j2")] n = C.quarantine_length(tags) print(f"в карантин ушло клеток: {n}") if n: cmd_bases() cmd_arms() def cmd_floor() -> None: """Свой шумовой пол оси — парой независимых генераций одного лечения. ⚠ Без него у оси нет ПОРОГА: судейская разница между армами не с чем сравнить, и любой результат читается как значимый. Пол берётся из мест смыслового критика этой же оси, обе половины — отдельные генерации, и судят их РАЗНЫЕ сессии (забота судейского рига). """ wire() C.cmd_floor() def cmd_dry() -> None: wire() us = units() have = {"D0": sum(1 for u in us if text_of(f"{PFX}-d0-{u['uid']}").strip()), "J0": sum(1 for u in us if text_of(f"{PFX}-j0-{u['uid']}").strip()), "J2": sum(1 for u in us if text_of(C.tag("J2", u["uid"])).strip())} price = {"D0": 0.0020, "J0": 0.00523, "J2": 0.00523} what = {"D0": "черновик (база)", "J0": "боевая связка — эталон", "J2": "однопроходка"} print(f"Д6 ja→ru РАЗВЕДКА · единиц {len(us)} · банк {len(PR.bank(PARA.JA.bank_file))} терминов\n") need_total = 0.0 print(f" {'арм':4s}{'есть':>6s}{'надо':>6s}{'смета':>9s} что это") for a in ("D0", "J0", "J2"): need = len(us) - have[a] need_total += need * price[a] print(f" {a:4s}{have[a]:6d}{need:6d}{need * price[a]:9.4f} {what[a]}") sp = MONEY.Guarded("ФД-C").spent() left = MONEY.CEILINGS["ФД-C"] - sp print(f"\n ФД-C: потрачено ${sp:.4f} · потолок ${MONEY.CEILINGS['ФД-C']:.2f} · " f"остаток ${left:.4f} · нужно ${need_total:.4f} → " f"{'ВЛЕЗАЕТ' if need_total <= left else f'НЕ ВЛЕЗАЕТ, не хватает ${need_total - left:.4f}'}") def cmd_selftest() -> int: bad = 0 def ck(n: str, ok: bool, d: str = "") -> None: nonlocal bad bad += not ok print(f"[{'OK ' if ok else 'ПРОВАЛ'}] {n}" + (f" {d}" if d else "")) wire() us = units() ck("единиц ровно 9 — как объявила разведка", len(us) == 9, f"их {len(us)}") ck("пара включена целиком", C.pair().key == "ja-ru") ck("теги идут в кассу ФД-C", C.tag("J2", "u").startswith("dv-c-") and C.phase_of("J2") == "ФД-C") ck("банк пары непуст", len(PR.bank(PARA.JA.bank_file)) > 0, f"терминов {len(PR.bank(PARA.JA.bank_file))}") ck("японская письменность опознаётся как исходник", bool(PARA.JA.source_script.search(us[0]["source"]))) ck("ось объявлена ОПИСАТЕЛЬНОЙ и это не отменяется арифметикой", "Д6 ja→ru разведка" in _load("power_ja", ZONE / "power.py").FORCED_DESCRIPTIVE) empty = [f"{a}-{u['uid']}" for u in us for a, t in (("D0", f"{PFX}-d0-{u['uid']}"), ("J0", f"{PFX}-j0-{u['uid']}"), ("J2", C.tag("J2", u["uid"]))) if not text_of(t).strip()] ck("клетки НЕПУСТЫ (файл ≠ годное содержимое)", not empty, f"пустых {len(empty)}: {empty[:3]}") print(f"\n{'РАЗВЕДКА ГОТОВА' if not bad else f'ПРОВАЛОВ: {bad}'}") return bad if __name__ == "__main__": a = sys.argv[1] if len(sys.argv) > 1 else "--dry" fn = {"--dry": cmd_dry, "--bases": cmd_bases, "--arms": cmd_arms, "--floor": cmd_floor, "--refill": cmd_refill, "--selftest": lambda: sys.exit(1 if cmd_selftest() else 0)}.get(a) fn() if fn else print(__doc__)