textmachine/eval/dovodka/ja_axis.py

254 lines
14 KiB
Python
Raw Permalink 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 | --j6 | --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
ROSTER, ED22 = C.ROSTER, C.ED22 # ростер и клиенты — из общего контура, не копией
DRAFT_MODEL = "deepseek-v4-flash"
EDITOR = "deepseek-v4-pro"
EDITOR2 = "glm-5" # второй редактор пары, носитель H-4
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_j6() -> None:
"""J6 — ВТОРОЙ редактор (`glm-5`) поверх той же базы. Касса ФД-H, санкция владельца 15.08.
⚠ ЗАЧЕМ, И ЧТО ЭТО НЕ ЗАКРЫВАЕТ. Гипотеза H-4 говорит о ПОРЯДКЕ жильцов между парами, а
порядок нельзя увидеть, имея на паре одного редактора: ось Д6 меряла «помогает ли редактор
вообще», а не «какой лучше». На zh панель есть (эксп-22), на en второй редактор куплен (E6,
1.31 против 2.72), на ja второго не было — требование заказа (:115) печатать сравнение
порядка между zh/en/ja поэтому не исполнялось.
⚠ Результат будет ОПИСАТЕЛЬНЫМ и никаким иным: ось объявлена разведочной ДО денег
(`power.FORCED_DESCRIPTIVE`, n=9, MDE 2.90 против цели 2.00). Покупка закрывает букву заказа
и даёт третью точку картины; несущего вывода она не даст ни при каком исходе.
⚠ `glm-5` — Z.AI, поэтому смена прайса DeepSeek 16.08 16:00 UTC этой строки не касается.
"""
wire()
# ⚠ Ожидание гарда — ЗАМЕРЕННОЕ, а не взятое с запасом: гард отказывает по ОЖИДАЕМОЙ цене,
# и завышенное ожидание останавливает покупку в середине по несуществующему перерасходу
# (в этой фазе так уже вышло трижды). Медиана клетки того же редактора на en — $0.00312
# (касса ФД-G, 16 клеток); японская единица длиннее, берётся то же 0.006, что японская ось
# использует для своих баз. 9 × 0.006 = 0.054 при потолке ФД-H 0.10.
led = MONEY.Guarded("ФД-H", default_expect=0.006)
for u in units():
uid, src = u["uid"], u["source"]
draft = base_draft(uid)
if not draft.strip():
continue
tg = f"dv-h-j6-{uid}"
if text_of(tg).strip():
continue
rec = MONEY.purchase(led, tg, EDITOR2, ED22.client(EDITOR2),
ROSTER.call_kwargs(EDITOR2,
PR.editor_msgs(src, draft, _law(src),
pair="ja-ru")),
role="editor3", uid=uid, arm="J6")
if rec.get("skipped"):
raise SystemExit(f"⛔ ГАРД ОТКАЗАЛ на {tg} — СТОП и вопрос владельцу")
MONEY.report()
def cmd_jfloor() -> None:
"""ШУМОВОЙ ПОЛ ЯПОНСКОЙ НОГИ — вторая генерация БОЕВОГО РЕДАКТОРА поверх той же базы.
⚠ ПОЧЕМУ НЕ ПЕРЕИСПОЛЬЗУЕТСЯ ПОЛ ОСИ Д6. Тот снят с ТОЧЕЧНОГО ФИКСЕРА, а фиксер правит по
короткому списку мест и потому почти детерминирован: из 8 пар на диске ЧЕТЫРЕ побайтно
одинаковы, и перекупка это не лечит (проверено фазой 15.08 — три пары вернулись теми же
текстами). Побайтная пара даёт нулевую разницу и ЗАНИЖАЕТ порог, то есть делает вердикты
смелее данных — ровно дефект «близнеца» пака 23.
⚠ И ПО СУЩЕСТВУ: панель этой ноги — ПАНЕЛЬ РЕДАКТОРОВ (`J0` против `J6`), поэтому её шум
обязан мериться повторной генерацией РЕДАКТОРА, а не фиксера. Иначе порог берётся из
операции, которой в панели нет.
"""
wire()
led = MONEY.Guarded("ФД-H", default_expect=0.006)
for u in units():
uid, src = u["uid"], u["source"]
draft = base_draft(uid)
if not draft.strip():
continue
tg = f"dv-h-jflo-{uid}"
if text_of(tg).strip():
continue
rec = MONEY.purchase(led, tg, EDITOR, ED22.client(EDITOR),
ROSTER.call_kwargs(EDITOR,
PR.editor_msgs(src, draft, _law(src),
pair="ja-ru")),
role="floor2", uid=uid, arm="JFLO")
if rec.get("skipped"):
raise SystemExit(f"⛔ ГАРД ОТКАЗАЛ на {tg} — СТОП и вопрос владельцу")
MONEY.report()
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")]
# ⚠ Покупка идёт ВСЕГДА, а не только если карантин что-то забрал этим прогоном. Прежняя
# редакция проверяла `if n:` — и уже лежавшие в карантине клетки не перекупались никогда:
# прогон печатал «в карантин ушло 0» и завершался успехом, оставив ось неполной.
n = C.quarantine_length(tags)
print(f"в карантин ушло клеток: {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, "--j6": cmd_j6, "--jfloor": cmd_jfloor,
"--selftest": lambda: sys.exit(1 if cmd_selftest() else 0)}.get(a)
fn() if fn else print(__doc__)