textmachine/eval/dovodka/ja_axis.py

150 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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"
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)
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_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)
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,
"--selftest": lambda: sys.exit(1 if cmd_selftest() else 0)}.get(a)
fn() if fn else print(__doc__)