#!/usr/bin/env python3 """ФАЗЫ B и C. Платные, идут через кассу пака. ФАЗА B — граница `glm-5`. 16 НОВЫХ единиц (`material.units_new`), на каждой покупается ровно то, что нужно контрасту границы: якорный черновик · боевой редактор `deepseek-v4-pro` (R0) · пограничный `glm-5` (R2). n контраста R0/R2 растёт 16 → 32. ФАЗА C — панель сильного тира. Прошедшие фазу A идут редакторами поверх ТОЙ ЖЕ якорной базы эксп-22 на его 16 единицах. База уже куплена: пере-генерация запрещена — это был бы второй замер той же вещи, а не новый арм. Клетка R0 над этой базой тоже куплена эксп-22 и переиспользуется. ⚠ ПОТОЛОК ФАЗЫ C ПОДНЯТ $1.80 → $2.30 ИЗ ОБЪЯВЛЕННОГО РЕЗЕРВА ПАКА (см. `money.CEILINGS`), объявляется ДО покупок фазы. Две причины, обе замерные: пре-рег-критерий пропустил ТРОИХ, и панель по замеренным ценам фазы A стоит $1.844 вместо сметы на двоих; плюс плану нужен СВОЙ шумовой пол — вторая независимая генерация самого дешёвого арма, ещё $0.29. Пакетный потолок $4.00 (санкция владельца) НЕ двигается: смета пака $2.93. Фазовый потолок — моя разбивка внутри санкции; тихо пробить его было бы нечестно, тихо срезать панель — тем более. """ from __future__ import annotations import sys from pathlib import Path REPO = Path("/home/ubuntu/projects/textmachine") ZONE = Path(__file__).resolve().parent sys.path.insert(0, str(REPO / "eval" / "tenant_panel")) sys.path.insert(0, str(REPO / "eval" / "role_topology")) def _load(name: str, path: Path): """Чужое — только явной загрузкой (см. `screen._load`).""" import importlib.util # noqa: PLC0415 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 TP = REPO / "eval" / "tenant_panel" PR = _load("prompts22", TP / "prompts.py") P22 = _load("panel22", TP / "panel.py") MAT = _load("material_et", ZONE / "material.py") SCR = _load("screen_et", ZONE / "screen.py") import bakeoff as BO # noqa: E402 MONEY = SCR.MONEY ROSTER = SCR.ROSTER ANCHOR = "deepseek-v4-flash" # черновик боевой пары BATTLE = "deepseek-v4-pro" # R0 BORDER = "glm-5" # R2 — пограничный контраст эксп-22 FLOOR_ARM = None # заполняется survivors()[0] — самый дешёвый прошедший def survivors() -> list[str]: """Прошедшие фазу A по ПРЕ-РЕГ-критерию пака, по возрастанию замеренной цены.""" r = SCR.result() ok = [m for m, v in r.items() if v["verdict"] == "прошёл"] return sorted(ok, key=lambda m: r[m]["price_editor"] or 9) # ── ФАЗА B ──────────────────────────────────────────────────────────────────────────────────── def tag_b(kind: str, model: str, uid: str) -> str: return f"et-unit-{kind}-{model}-{uid}" def cmd_b_plan() -> None: us = MAT.units_new() r22 = ROSTER.R22 exp = {ANCHOR: 0.00130, BATTLE: 0.00545, BORDER: 0.01303} # замеры эксп-22, $/ед tot = sum(exp.values()) * len(us) print(f"фаза B: {len(us)} новых единиц × (черновик + {BATTLE} + {BORDER}) = " f"{len(us) * 3} клеток · ожидание ${tot:.3f} · потолок {MONEY.CEILINGS['ФB']:.2f}") _ = r22 if tot > MONEY.CEILINGS["ФB"]: print("⛔ смета выше потолка фазы — СТОП") raise SystemExit(1) def cmd_b_run() -> None: led = MONEY.Guarded("ФB") for u in MAT.units_new(): blk = PR.glossary_block(PR.terms_in(u["source"])) t = tag_b("draft", ANCHOR, u["uid"]) if not (MONEY.OUT / f"{t}.json").exists(): MONEY.purchase(led, t, ANCHOR, SCR.client(ANCHOR), ROSTER.call_kwargs(ANCHOR, PR.translator_msgs(u["source"], blk)), role="draft", uid=u["uid"]) d = draft_b(u["uid"]) if not d.strip(): print(f" {u['uid']}: черновика нет — редактуры пропущены") continue # ⚠ ГЕЙТ БРАКА ЧЕРНОВИКА БЫЛ НАПИСАН И НЕ ПОДКЛЮЧЁН. Фаза проверяла только «строка пуста», # поэтому эхо-мина прошла на боевую базу: `63ab55ac5c` — 1798 ханьцзы и НОЛЬ кириллицы при # `finish=stop`. Отчёт из-за этого объявлял класс «не ловится ни одним гейтом» — неверно: # `draft_reject_reason` его ловит, звать было некому. Поймано аудитом закрытия заказа. if (why := BO.draft_reject_reason(d)): print(f" {u['uid']}: черновик забракован ({why}) — редактуры НЕ покупаются") continue law = PR.law_block(PR.terms_in(u["source"])) for m in (BATTLE, BORDER): te = tag_b("edit", m, u["uid"]) if (MONEY.OUT / f"{te}.json").exists(): continue MONEY.purchase(led, te, m, SCR.client(m), ROSTER.call_kwargs(m, PR.editor_msgs(u["source"], d, law)), role="edit", uid=u["uid"]) MONEY.report() def draft_b(uid: str) -> str: import json # noqa: PLC0415 f = MONEY.OUT / f"{tag_b('draft', ANCHOR, uid)}.json" return (json.loads(f.read_text(encoding="utf-8")).get("content") or "") if f.exists() else "" def text_b(arm: str, uid: str) -> str: import json # noqa: PLC0415 m = {"R0": BATTLE, "R2": BORDER}[arm] f = MONEY.OUT / f"{tag_b('edit', m, uid)}.json" return (json.loads(f.read_text(encoding="utf-8")).get("content") or "") if f.exists() else "" # ── ФАЗА C ──────────────────────────────────────────────────────────────────────────────────── def tag_c(model: str, uid: str) -> str: return f"et-ed-{model}-{uid}" def cmd_c_plan() -> None: ok, us = survivors(), P22.M.units_zh() r = SCR.result() tot = sum((r[m]["price_editor"] or 0) * len(us) for m in ok) print(f"{'арм':6s}{'модель':16s}{'$/ед':>10s}{'×16':>10s}") for i, m in enumerate(ok, start=1): pe = r[m]["price_editor"] or 0 print(f"{'T' + str(i):6s}{m:16s}{pe:10.5f}{pe * len(us):10.3f}") print(f"{'ИТОГО':22s}{'':10s}{tot:10.3f} потолок {MONEY.CEILINGS['ФC']:.2f}") print(f"база R0 ({BATTLE} над якорным черновиком) — уже куплена эксп-22, $0") if tot > MONEY.CEILINGS["ФC"]: print("⛔ смета выше потолка фазы — СТОП") raise SystemExit(1) def cmd_c_run() -> None: led = MONEY.Guarded("ФC") for u in P22.M.units_zh(): base = P22.draft_text(ANCHOR, u["uid"]) if not base.strip(): print(f" {u['uid']}: якорной базы нет — пропуск") continue law = PR.law_block(PR.terms_in(u["source"])) for m in survivors(): t = tag_c(m, u["uid"]) if (MONEY.OUT / f"{t}.json").exists(): continue MONEY.purchase(led, t, m, SCR.client(m), ROSTER.call_kwargs(m, PR.editor_msgs(u["source"], base, law)), role="edit", uid=u["uid"]) MONEY.report() def tag_floor(uid: str, gen: int) -> str: return f"et-floor-p{gen}-{survivors()[0]}-{uid}" def cmd_floor_run() -> None: """ШУМОВОЙ ПОЛ прохода: ДВЕ независимые генерации ОДНОГО арма на одном входе. Истинная разница между ними — ноль, поэтому разброс их перевесов и есть шум одного вызова. Первая генерация уже куплена фазой C (клетка панели), докупается только вторая: пол обязан быть СВОИМ для прохода, а не заимствованным у эксп-22 — там другая панель и другой прайс. """ m = survivors()[0] led = MONEY.Guarded("ФC") for u in P22.M.units_zh(): base = P22.draft_text(ANCHOR, u["uid"]) if not base.strip(): continue t = tag_floor(u["uid"], 2) if (MONEY.OUT / f"{t}.json").exists(): continue law = PR.law_block(PR.terms_in(u["source"])) MONEY.purchase(led, t, m, SCR.client(m), ROSTER.call_kwargs(m, PR.editor_msgs(u["source"], base, law)), role="floor2", uid=u["uid"]) MONEY.report() def floor_pair(uid: str): """(генерация 1, генерация 2) самого дешёвого арма панели. ⚠ ДЕФЕКТ, ОБЪЯВЛЕННЫЙ И НЕ ПОЧИНЕННЫЙ В ЭТОМ ПАКЕ: первая половина пары — это САМА боевая клетка `T1`, а не отдельная генерация. Следствие ровно одно, и оно не в числах пола (пол считается по РАЗНОСТИ двух генераций и остаётся честным), а в контроле «БЛИЗНЕЦ»: он ловит побайтные дубли, и здесь единственным дублем оказывается пара `CTRLfloorA`≡`T1` в 16/16 — то есть контроль сравнивает `T1` с самим собой и ничего не проверяет. Чинить надо ПОКУПКОЙ отдельной первой генерации, поэтому в этом паке дефект только объявлен (отчёт §12). """ import json # noqa: PLC0415 a = text_c("T1", uid) f = MONEY.OUT / f"{tag_floor(uid, 2)}.json" b = (json.loads(f.read_text(encoding="utf-8")).get("content") or "") if f.exists() else "" return (a, b) if a.strip() and b.strip() else None def text_c(arm: str, uid: str) -> str: """Тексты армов Ф C. R0 — клетка эксп-22, переиспользуется без покупки.""" import json # noqa: PLC0415 if arm == "R0": return P22.edit_text(ANCHOR, uid) ok = survivors() m = ok[int(arm[1:]) - 1] f = MONEY.OUT / f"{tag_c(m, uid)}.json" return (json.loads(f.read_text(encoding="utf-8")).get("content") or "") if f.exists() else "" def selfcheck() -> int: bad = 0 ok = survivors() if not ok: print("[ПРОВАЛ] фазу A не прошёл никто — панели нет") bad += 1 us_b, us_c = MAT.units_new(), P22.M.units_zh() if set(u["uid"] for u in us_b) & set(u["uid"] for u in us_c): print("[ПРОВАЛ] единицы фаз B и C пересекаются") bad += 1 tags = [tag_b("draft", ANCHOR, u["uid"]) for u in us_b] + \ [tag_b("edit", m, u["uid"]) for u in us_b for m in (BATTLE, BORDER)] + \ [tag_c(m, u["uid"]) for u in us_c for m in ok] if len(tags) != len(set(tags)): print("[ПРОВАЛ] теги не уникальны") bad += 1 if not all(t.startswith(("et-unit-", "et-ed-")) for t in tags): print("[ПРОВАЛ] тег вне глобов фаз") bad += 1 if sum(MONEY.CEILINGS.values()) > MONEY.PACK_CEILING + 1e-9: print("[ПРОВАЛ] сумма фазовых потолков выше пакетного") bad += 1 print(f"панель: армов {len(ok)} ({ok}) · клеток в плане {len(tags)} · провалов {bad}") return bad if __name__ == "__main__": a = sys.argv[1:] or ["--selfcheck"] fn = {"--b-plan": cmd_b_plan, "--b-run": cmd_b_run, "--c-plan": cmd_c_plan, "--c-run": cmd_c_run, "--floor-run": cmd_floor_run, "--selfcheck": lambda: sys.exit(1 if selfcheck() else 0)}.get(a[0]) if fn: fn() else: print(__doc__)