From 4f698106e907e650fa7a6de1cf46fc915f053efc Mon Sep 17 00:00:00 2001 From: "Claude (backend session)" Date: Mon, 10 Aug 2026 17:11:22 +0300 Subject: [PATCH] Fix silent cross-pack cash misroute: buy is a singleton and the last configurer won, so paid cells landed in another pack directory while the phase ledger read zero --- eval/dovodka/contour.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/eval/dovodka/contour.py b/eval/dovodka/contour.py index 4192c2aa..a40f4d29 100644 --- a/eval/dovodka/contour.py +++ b/eval/dovodka/contour.py @@ -51,6 +51,20 @@ BANK = _load("bank22", REPO / "eval" / "tenant_panel" / "bank.py") ROSTER = _load("roster22", REPO / "eval" / "tenant_panel" / "roster.py") ED22 = _load("editors22", REPO / "eval" / "tenant_panel" / "editors.py") +# ⚠⚠ КАССУ ПЕРЕ-НАСТРАИВАЕМ ПОСЛЕ ВСЕХ ЧУЖИХ ЗАГРУЗОК, И ЭТО НЕ ПЕДАНТИЗМ. +# Модуль `buy` — СИНГЛТОН в `sys.modules`, и побеждает тот, кто настроил его последним. `money_d` +# ставил `BUY.OUT` на каталог фазы, а грузившийся следом `panel.py` пака 23 тянул его кассу и +# перебивал обратно на `~/books/editor-tier`. Итог был бесшумным и дорогим: кэш-чек, замок и +# `finally` смотрели в каталог фазы, а РЕЗУЛЬТАТ писался в каталог чужого пака. Семь оплаченных +# клеток ушли туда, касса фазы показывала $0, а цикл покупки 20 минут ждал появления файла, +# который в её каталоге не появился бы никогда. Найдено многоагентным разбирательством 10.08. +MONEY.M22.configure(ZONE=ZONE.parent / "dovodka", OUT=MONEY.OUT, TAGS=MONEY.TAGS, + CEILINGS=MONEY.CEILINGS, PACK_CEILING=MONEY.PACK_CEILING, + GLOB_ALL="dv-*.json", ROSTER=ROSTER) +if MONEY.M22.BUY.OUT != MONEY.OUT: # ассерт, а не надежда + raise SystemExit(f"⛔ buy.OUT={MONEY.M22.BUY.OUT} против кассы {MONEY.OUT} — " + "покупки уедут в чужой каталог, СТОП") + OUT = MONEY.OUT ANCHOR = "deepseek-v4-flash" # якорный черновик FIXER = "deepseek-v4-pro" # фиксер и критик — боевой редакторский движок @@ -212,6 +226,9 @@ def cmd_selftest() -> int: tags = {tag(a, u["uid"]) for a in ARMS} ck("теги армов различны", len(tags) == len(ARMS)) ck("теги покрыты глобом кассы", all(t.startswith(("dv-a-", "dv-f-")) for t in tags)) + # ⚠ Главный ассерт этого харнесса: кэш-чек и ЗАПИСЬ результата смотрят в ОДИН каталог. + ck("buy.OUT совпадает с кассой фазы", MONEY.M22.BUY.OUT == MONEY.OUT, + f"{MONEY.M22.BUY.OUT} против {MONEY.OUT}") print(f"\n{'ХАРНЕСС ГОДЕН' if not bad else f'ПРОВАЛОВ: {bad}'}") return bad @@ -256,7 +273,11 @@ def cmd_run(which: list[str]) -> None: MONEY.purchase(led, ct, FIXER, ED22.client(FIXER), ROSTER.call_kwargs(FIXER, crit_msgs(src, draft)), role="critic", uid=uid, arm=arm) - found = json.loads((OUT / f"{ct}.json").read_text(encoding="utf-8")).get("content") or "" + cf = OUT / f"{ct}.json" + if not cf.exists(): # оплачено, но файла нет — не падать + print(f" {uid}/{arm}: критик не отдал файл — арм пропущен, объявить в отчёте") + continue + found = json.loads(cf.read_text(encoding="utf-8")).get("content") or "" places = [ln.strip("- ").strip() for ln in found.splitlines() if ln.strip().startswith("-")] if not places: print(f" {uid}/{arm}: критик не нашёл мест — фиксер не зовётся")