diff --git a/eval/dovodka/money_d.py b/eval/dovodka/money_d.py index a86d6a94..09cd6950 100644 --- a/eval/dovodka/money_d.py +++ b/eval/dovodka/money_d.py @@ -234,7 +234,12 @@ TAGS = { CEILINGS = {"ФД-A": 1.910, "ФД-B": 0.900, "ФД-C": 0.370, "ФД-D": 0.050, "ФД-E": 2.290, "ФД-F": 0.500, "ФД-G": 0.060, "ФД-H": 0.090, "ФД-I": 3.950, "ФД-J": 1.950, "ФД-K": 0.400, "ФД-L": 1.300, - "ФД-M": 2.100, "ФД-N": 2.400} + "ФД-M": 2.100, "ФД-N": 3.300} +# ⚠ ФД-N 2.400 → 3.300 по слову владельца 22.08 («Мы должны были купить гпт луну и гемини. Так? +# Короче говоря нужно закрыть баги и техдолг. Вот по нему и работай») — и по названной ему заранее +# смете `PLAN-21-08.md` §2.3: luna $0.14 · gemini-flash-lite $0.18 · две недостающие клетки `RGT` +# $0.11 · `RKT` (grok с настоящим размышлением, клетка блокера Б6) $0.25–0.30. Итого ~$0.73 при +# свободных на момент решения $0.083. Пакетный резерв держит: сумма фазовых остаётся ≤ PACK_CEILING. PACK_CEILING = 18.30 # ⚠ ТРЕТИЙ ПОДЪЁМ ФД-I — ЭТО МОЯ ОШИБКА ОЦЕНКИ, А НЕ РАСШИРЕНИЕ ЗАКАЗАННОГО, И ЗАПИСЫВАЮ ЕЁ ТАК. # Владелец санкционировал словом «Поднимай» ПЯТЬ клеток шумового пола. Три купились, две не diff --git a/eval/dovodka/rol.py b/eval/dovodka/rol.py index 753cd271..b1bfa4f5 100644 --- a/eval/dovodka/rol.py +++ b/eval/dovodka/rol.py @@ -707,9 +707,68 @@ def cmd_selftest() -> int: MONEY.M22.BUY.cost(mo, 3000, 0, 3600, 800, 7400) > 0) except Exception as e: # noqa: BLE001 ck(f"цена считается для {a} ({mo})", False, f"{type(e).__name__}: {e}") - ck("grok идёт с размышлением (D30.1: reasoning-off = no-op-редактор)", - "reasoning_effort" not in json.dumps(call_kwargs("grok-4.3", - [{"role": "user", "content": "x"}]))) + # ── ГЕЙТЫ ПОЧИНОК РЕВЬЮ 21.08. Каждый обязан УМЕТЬ УПАСТЬ на своём дефекте ──────────────── + # ⚠ Заведены после того, как пять дефектов класса «реализация не то, чем названа» прошли мимо + # всех существовавших гейтов. Здесь проверяется не «код изменён», а «поведение верное». + MARK = {"zh": ("时辰", "чэнъюй", "zh→ru"), "en": ("МЕРЫ английской традиции",), + "ja": ("ja→ru",)} + for p, cfg in PAIRS.items(): + cfg["wire"]() + src = chosen(p)[0]["source"] + sysm = "\n\n".join(x["content"] for x in C.a2_msgs(src) if x["role"] == "system") + alien = [w for q, ws in MARK.items() if q != p for w in ws if w in sysm] + # Б1: мандат склейки берётся у СВОЕЙ пары. Падал бы на прежнем коде: на `en` в промт + # уезжали 时辰/чэнъюй/«китайский паратаксис» из боевого редактора китайской пары. + ck(f"Б1 {p}: склейка НЕ несёт маркеров чужой пары", not alien, f"нашлось: {alien}") + ck(f"Б1 {p}: склейка несёт маркеры СВОЕЙ пары", + any(w in sysm for w in MARK[p]), f"ни одного из {MARK[p]}") + + # Б8: отбор глав НЕ ЗАВИСИТ от гейта годности. Первая редакция починки гасила текст в + # `base_a0`, единица выпадала из `pool()`, и `chosen()` подставлял на её место другую — + # «те же 16 глав» переставали быть теми же. Сверяем с главами УЖЕ СОБРАННЫХ панелей. + for p, tag_ in (("en", "arch2"), ("zh", "zhpanel")): + PAIRS[p]["wire"]() + now = {u["uid"][:8] for u in chosen(p)} + was = {k.stem.split(f"{tag_}-")[1] + for k in (OUT / "blind-keys-rol").glob(f"rol-KEY-{tag_}-*.json")} + ck(f"Б8 {p}: отбор глав не поехал после починок", was <= now, + f"пропали из отбора: {sorted(was - now)}") + + # Б8: гейт годности `A0` ловит известную больную единицу и молчит на здоровых. + PAIRS["zh"]["wire"]() + sick = [u["uid"] for u in chosen("zh") if not C.a0_ok(u["uid"])] + ck("Б8: гейт A0 ловит оборванную клетку", sick == ["41599f30df"], f"поймал: {sick}") + + # ⚠ ЛАТЕНТНАЯ МИНА, НАЙДЕНА 22.08 ПРИ ФАЛЬСИФИКАЦИИ ГЕЙТА Б8. В одном процессе живут НЕСКОЛЬКО + # независимых экземпляров `contour` (`rol` держит свой, `zakhod` — свой через `en_axis`), и + # `wire()` настраивает НЕ ВСЕ: после включения английской пары один экземпляр остаётся на + # китайской. Проверено, что до данных это НЕ добралось — горячие функции получают пару + # АРГУМЕНТОМ (`_pair(p)["para"]().key`), а не из глобального `pair()`, и настоящий путь покупки + # грузит верный банк (английские клетки `Z7` собраны по английскому банку — сверено). + # Поэтому здесь ПРЕДУПРЕЖДЕНИЕ, а не провал: ронять покупку из-за мины, которая не выстрелила, + # значит остановить работу по подозрению. Но любая НОВАЯ функция, читающая глобальный `pair()`, + # обязана быть проверена на этом месте — иначе арм соберётся на невключённой паре. + _inst = {id(C): ("rol.C", C), id(ZK.C): ("zakhod.C", ZK.C)} + if len(_inst) > 1: + PAIRS["en"]["wire"]() + _st = {n: c.pair().key for n, c in _inst.values()} + if len(set(_st.values())) > 1: + print(f"[⚠ МИНА] экземпляров contour {len(_inst)}, после wire(en) пары разошлись: {_st}" + " — глобальный `pair()` использовать НЕЛЬЗЯ, только пара аргументом") + + # Б6/Б7: уровень размышления объявлен для КАЖДОГО арма и уходит на провод именно он. + ck("Б6: уровень размышления объявлен для всех армов", + set(ARMS) <= set(THINK_LEVEL), f"без объявления: {sorted(set(ARMS) - set(THINK_LEVEL))}") + for a, (mo, _g) in ARMS.items(): + eb = call_kwargs(mo, [{"role": "user", "content": "x"}], a).get("extra_body") or {} + lvl = THINK_LEVEL.get(a) + if lvl in ("low", "medium", "high"): + ok, d = eb.get("reasoning_effort") == lvl, f"на проводе {eb}" + elif lvl == "vendor": # никакого НАШЕГО подавления на проводе быть не должно + ok, d = not ({"thinking", "reasoning_effort"} & set(eb)), f"на проводе {eb}" + else: + ok, d = True, "" + ck(f"Б6 {a}: на провод уходит объявленный уровень «{lvl}»", ok, d) print(f"\n{'ЗАМЕР ГОДЕН К ПОКУПКЕ' if not bad else f'ПРОВАЛОВ: {bad}'}") return bad