textmachine/eval/editor_tier/money.py

126 lines
7.7 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
"""КАССА ПАКА «СИЛЬНЫЙ ТИР». $0 сама по себе; через неё идут ВСЕ платные вызовы пака.
Не копия кассы эксп-22, а её НАСТРОЙКА. Механизм там проверенный и дорого доставшийся — фриз-гейт,
атомарный замок клетки, проекционный сторож перед каждым вызовом, два независимых пути счёта, — и
копирование размножило бы будущие расхождения вместо того, чтобы их ловить. Пак-специфика (зона
кода, каталог сырья, теги фаз, потолки, прайс-таблица) подставляется через `money.configure`.
Потолки — санкция владельца 09.08: пак ≤$4.00. Фазовые суммируются в $3.35, разница — объявленный
резерв на ре-гены эхо-мины и ретраи, а не запас «на всякий случай»: тратится он только через те же
теги и виден в отчёте.
"""
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(ZONE))
sys.path.insert(0, str(REPO / "eval" / "tenant_panel"))
sys.path.insert(0, str(REPO / "eval" / "role_topology"))
def _load(name: str, path: Path):
"""⚠ Ростер пака грузится ПО ПУТИ. `import roster` находил ростер эксп-22: три
`sys.path.insert(0, …)` подряд кладут ПОСЛЕДНИЙ вставленный первым, и своя папка оказывалась
в хвосте. Поймано печатью селфтеста — «моделей 11» вместо 15, то есть проверка «цена считается
для ВСЕХ моделей» молча проверяла только старые."""
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
# ⚠ И касса эксп-22 тоже грузится ПО ПУТИ. `import money` здесь работал лишь по счастливому
# порядку sys.path: стоило вызвать модуль из файла, который кладёт свою папку первой, как он
# находил САМ СЕБЯ и падал циклическим импортом. Правило без исключений: чужое — только _load.
M22 = _load("money22", REPO / "eval" / "tenant_panel" / "money.py")
ROSTER_ET = _load("roster_et", ZONE / "roster.py")
OUT = Path.home() / "books" / "editor-tier"
# Теги покупок по фазам. ⚠ Новый тег вписывается СЮДА тем же коммитом, что и код, который его
# заводит: расход мимо глоба невидим для кассы, и эксп-21 напоролся на это трижды.
TAGS = {
"ФA": ("et-scr-*.json",), # скрин сильного тира
"ФB": ("et-unit-*.json",), # 16 новых единиц для границы glm-5 (черновик + R0 + R2)
"ФC": ("et-ed-*.json", "et-floor-*.json"), # панель + ШУМОВОЙ ПОЛ своего прохода
}
# ⚠ Потолок ФC поднят $1.80 → $2.30 из ОБЪЯВЛЕННОГО В ПЛАНЕ резерва пака ($0.65), объявляется до
# покупок фазы. Две причины, обе замерные: пре-рег-критерий пропустил ТРОИХ (панель $1.844 вместо
# сметы на двоих) и плану нужен СВОЙ шумовой пол — вторая независимая генерация самого дешёвого
# арма панели, ещё $0.29. Пакетный потолок $4.00 (санкция владельца) НЕ двигается: смета пака $2.93.
CEILINGS = {"ФA": 1.10, "ФB": 0.45, "ФC": 2.30}
PACK_CEILING = 4.00
M22.configure(ZONE=ZONE, OUT=OUT, TAGS=TAGS, CEILINGS=CEILINGS,
PACK_CEILING=PACK_CEILING, GLOB_ALL="et-*.json", ROSTER=ROSTER_ET)
# Всё остальное берётся у настроенной кассы — своих реализаций тут нет намеренно.
Guarded, Pack, purchase, model_expect = M22.Guarded, M22.Pack, M22.purchase, M22.model_expect
def report() -> None:
print(f"{'фаза':6s}{'потрачено':>12s}{'потолок':>10s}")
tot = 0.0
for ph in TAGS:
sp = Guarded(ph).spent()
tot += sp
mark = " ⛔ ПРОБОЙ" if sp > CEILINGS[ph] + 1e-9 else ""
print(f"{ph:6s}{sp:12.6f}{CEILINGS[ph]:10.2f}{mark}")
print(f"{'ПАК':6s}{tot:12.6f}{PACK_CEILING:10.2f}")
def selftest() -> int:
"""Обязан пройти ДО первой покупки пака."""
bad = 0
# 1. касса смотрит в СВОЁ сырьё, а не в сырьё эксп-22
if M22.OUT != OUT:
print("[ПРОВАЛ] касса не пере-настроена на своё сырьё")
bad += 1
if M22.BUY.OUT != OUT:
print("[ПРОВАЛ] buy.OUT указывает мимо каталога пака — покупки уедут к соседу")
bad += 1
# 2. цена считается для ВСЕХ моделей, включая новые (эксп-22 упал тут на середине скрина)
for m in ROSTER_ET.CANDIDATES:
try:
if not M22.BUY.cost(m, 4500, 0, 2500, 1000, 8000) > 0:
raise ValueError(m)
except Exception as e: # noqa: BLE001
print(f"[ПРОВАЛ] цена не считается: {m} ({type(e).__name__}: {e})")
bad += 1
# 3. в таблице кассы ДОЛЖНЫ быть новые кандидаты — иначе подставился чужой ростер
missing = [m for m in ("gpt-5.6-terra", "kimi-k3", "grok-4.5", "glm-5.2")
if m not in ROSTER_ET.CANDIDATES]
if missing:
print(f"[ПРОВАЛ] в таблице кассы нет новых кандидатов: {missing}")
bad += 1
# 4. потолки фаз не превышают пакетный
if sum(CEILINGS.values()) > PACK_CEILING + 1e-9:
print("[ПРОВАЛ] сумма фазовых потолков выше пакетного")
bad += 1
# 5. КАЖДЫЙ тег покрыт глобом GLOB_ALL — иначе покупка невидима для `model_expect`
for globs in TAGS.values():
for g in globs:
if not g.startswith("et-"):
print(f"[ПРОВАЛ] тег вне шаблона пака: {g}")
bad += 1
# 6. фриз-гейт обязан отказывать коду вне зоны пака
import inspect # noqa: PLC0415
if M22.ZONE != ZONE:
print("[ПРОВАЛ] фриз-гейт сторожит чужую зону")
bad += 1
_ = inspect
print(f"касса: тегов {sum(len(v) for v in TAGS.values())} · моделей "
f"{len(ROSTER_ET.CANDIDATES)} · провалов {bad}")
return bad
if __name__ == "__main__":
if "--selftest" in sys.argv:
sys.exit(1 if selftest() else 0)
report()