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