textmachine/eval/dovodka/money_d.py

325 lines
35 KiB
Python
Raw Permalink 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, а её НАСТРОЙКА через `configure` — тот же приём, которым пользовался пак
23. Механизм там проверенный и дорого доставшийся: фриз-гейт (покупка отказывает коду, который не
закоммичен или отличается от закоммиченного), атомарный замок клетки `O_CREAT|O_EXCL`, проекционный
сторож перед КАЖДЫМ вызовом по цене ИМЕННО ЭТОЙ модели, два независимых пути счёта. Копирование
размножило бы будущие расхождения вместо того, чтобы их ловить.
ПОТОЛОК ФАЗЫ — САНКЦИЯ ВЛАДЕЛЬЦА $6.85 (15.08, дословно: «Подтверждаю подъём расходов, сколько тебе
нужно»; число назвала сессия и записала здесь, чтобы санкция была проверяема).
⚠ ЦЕПЬ ПОДЪЁМОВ, ИЗ КОТОРОЙ ЭТА ЦИФРА ВЫРОСЛА — ЧИТАТЬ ЦЕЛИКОМ, ЭТО НАХОДКА АУДИТА, А НЕ ХРОНИКА.
Промт называл $10.00 → владелец при запуске сказал $4.00 → поднял до $4.50 под починку дизайна
(приёмка нашла, что фаза не отвечает на H-1 и H-4; починка $0.48) → 11.08 ревью 82 находок
показало, что смета занижала фиксера в 2.41×, и владелец поднял до $5.40 → далее ФД-B поднимался
14.08 и 15.08, ФД-C — трижды, и `PACK_CEILING` дорос до 6.74 БЕЗ отдельного слова владельца в
каком-либо файле. Сквозной аудит 15.08: последняя цифра, приписанная слову владельца в тексте
репозитория, — $4.50 (`docs/PROGRESS.md:346`); фактический расход $6.002420 превышал её на
$1.502420 (33%). Санкция 15.08 покрывает расход задним числом — это НЕ делает цепь легитимной
ретроспективно, и она объявлена в отчёте отдельной строкой девиации (Д14).
⚠ ФРИЗ-ГЕЙТ ЭТУ ЦЕПЬ НЕ ЛОВИЛ И НЕ ПОЙМАЕТ: он сверяет с git ПОКУПАЮЩИЙ файл в стеке, а не кассу
(`_refuse_unfrozen` берёт первый не-кассовый кадр). Потолки правятся в рабочем дереве и действуют
немедленно — этим фаза и воспользовалась на ФД-C ($0.334774 против закоммиченных $0.300).
Пока гейт не сторожит САМ файл кассы, «покупает только закоммиченный код» о потолках не говорит.
РЕЗЕРВ ФАЗЫ $0.00 — и это объявлено риском ДО покупок ВТОРОЙ раз. При $4.50 резерв был $0.03,
и первый же промах сметы остановил ось Д4 на 22 клетках из 32. При $5.40 остатка нет вовсе:
честная смета остатка $4.277 плюс потраченные $1.140 дают $5.417, то есть уже $0.017 сверх
санкции, и Д1 добирает 15 клеток вместо 16 именно поэтому. Резерв 8% на ре-гены (история паков
22/23 — до +16%) потребовал бы $5.85. Сказано ДО покупок, а не после.
Поэтому правило исполнения жёсткое и записано здесь, а не в прозе:
**срабатывание проекционного гарда = СТОП и вопрос владельцу.** Резать ось, панель или кандидата
решением сессии ЗАПРЕЩЕНО заказом; поднимать потолок себе — тем более (пак 23 так и сделал, и это
стоило ему пункта CONFIRM/DENY).
Запуск: money_d.py [--report|--selftest]
"""
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 money` находил кассу эксп-22 или сам себя, смотря по
порядку `sys.path.insert`; пак 23 напоролся на это четырежды, и один раз молча."""
import importlib.util
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
M22 = _load("money22", REPO / "eval" / "tenant_panel" / "money.py")
ROSTER = _load("roster22", REPO / "eval" / "tenant_panel" / "roster.py")
OUT = Path.home() / "books" / "dovodka"
# Теги покупок по фазам. ⚠ Новый тег вписывается СЮДА тем же коммитом, что и код, который его
# заводит: расход мимо глоба невидим для кассы, и эксп-21 напоролся на это трижды, а последний
# раз гейт заниженное число ещё и СЕРТИФИЦИРОВАЛ.
TAGS = {
"ФД-A": ("dv-a-*.json",), # Д4 edit-контур zh: A1 A2 A3 A4 + свой шумовой пол
"ФД-B": ("dv-b-*.json",), # Д3 en→ru несущая ось: банк, контам, армы, пол
"ФД-C": ("dv-c-*.json",), # Д6 ja→ru разведка
"ФД-D": ("dv-d-*.json",), # Д7 микро-проба самооценки
"ФД-E": ("dv-e-*.json",), # Д1 добивка gemini-3.1-pro-preview
"ФД-F": ("dv-f-*.json",), # H-1: A6 dspro-черновик + оба контура
"ФД-G": ("dv-g-*.json",), # H-4: E6 второй редактор на en
"ФД-H": ("dv-h-*.json",), # H-4: японская нога — второй редактор glm-5 на ja
"ФД-I": ("dv-i-*.json",), # Д17: заход под починенную рубрику, китайская пара
"ФД-J": ("dv-j-*.json",), # Д17: заход под починенную рубрику, английская пара
"ФД-K": ("dv-k-*.json",), # Д22: подача входа критику, китайская пара
"ФД-L": ("dv-l-*.json",), # Д22: подача входа критику, английская пара
"ФД-M": ("dv-m-*.json",), # Д23: однопроходка как РОЛЬ, китайская пара
"ФД-N": ("dv-n-*.json",), # Д23: однопроходка как РОЛЬ, английская пара
}
# ⚠ Потолки фаз = смета `plan.py` плюс МИНИМАЛЬНЫЙ запас, так чтобы их СУММА не превышала
# пакетный потолок. Первая редакция округляла каждый вверх до цента и дала сумму 4.54 > 4.50 —
# то есть фазовые гарды в совокупности разрешали пробить пакетный. Поймано селфтестом кассы
# ДО первой покупки; ровно этот класс («касса охраняет не ту границу») стоил эксп-21 денег трижды.
#
# ⚠⚠ ПЕРЕ-РАСКЛАДКА 11.08 ПОД САНКЦИЮ $5.40. Прежняя раскладка стояла на смете, где фиксер положен
# в 0.60× переписа, а замерен в 2.41× (`plan.py` сверяет прогноз с фактом и печатает расхождение).
# Из-за этого ФД-A исчерпалась на 22 клетках арма A4 из 32, а арм A2 не куплен ни разу. Новая
# раскладка считана по ЗАМЕРЕННЫМ ценам 148 купленных клеток фазы, а не по прогнозу.
#
# ⚠ ПРИОРИТЕТ ВНУТРИ ФД-A ОБЪЯВЛЯЕТСЯ ЗДЕСЬ: ПЕРВЫМ покупается СВОЙ ШУМОВОЙ ПОЛ. Причина не
# бухгалтерская, а решающая: при заимствованном прайоре sd 2.12 и честном квантиле Стьюдента все
# три первичных контраста оси Д4 НЕДОМОЩНЫ (MDE 1.67…2.32 против цели 1.50). Несущей ось делает
# только СВОЙ пол — при sd ≤ 1.91 контрасты A1/A0 и A3/A0 становятся несущими. Покупать армы,
# не зная пола, значит рисковать всей сметой оси, которая может не дать вывода ни при каком исходе.
#
# ⚠ ПОТОЛОК ПОДНЯТ ДО $6.00 (санкция владельца 11.08). При $5.40 за борт выходила 16-я клетка
# gemini, а пре-рег Д0.3 говорит прямо: несущей ось Д1 делают ПОЛНЫЕ 16. При $6.00 влезает всё
# заказанное, включая расширение базы H-1 на новые единицы (без него носитель H-1 при n=16
# недомощен по построению — эррата Э-2/Э-3), и остаётся резерв 3.2%.
#
# ⚠ СУДЕЙСТВО СТОИТ $0 И ЗДЕСЬ НЕ ЗАЛОЖЕНО НИ ЦЕНТА — это норма заказа, подтверждённая владельцем
# 11.08 дословно: «НИКАКИХ ВЫЗОВОВ ПО АПИ, всё локально у нас на харнесах». Судей двое и оба
# бесплатны: агент-сессии (кап 80, `runs.py`) и локальный харнесс Sol 5-6 владельца — второе
# мнение о МОЁМ судействе и моей слепоте. Появление платного судьи в смете = дефект, не оптимизация.
#
# ⚠ ФД-D = РОВНО $0.05, а не $0.055. Заказ несёт единственный явный денежный кэп на платный пункт
# («Д7 — микро-проба самооценки ≤$0.05», промт :119), и прежний запас 10% его пробивал, тогда как
# на всех прочих фазах запас 0.11.1%. Поймано ревью 11.08.
# ⚠ ФД-A 1.660 → 1.680 (санкция владельца 11.08, одна строка «Добро»). Гард отказал на ПОСЛЕДНЕЙ
# клетке арма A1B: свободно было $0.0154 при резервируемом ожидании $0.0159 — не хватило половины
# цента. Причина промаха названа: A1B вышел вдвое дороже A1 ($0.0136 против $0.0069), а смета
# закладывала 1.30× (мест 181 против 74 — промт длиннее, и множитель недооценён на 52%).
# Это ПЕРЕКЛАДКА внутри санкционированного пакета, пакетный потолок $6.00 не двигается; сумма
# фазовых потолков 5.83 ≤ 6.00. Спрошено потому, что срабатывание гарда = вопрос владельцу по
# заказу, а пак 23 потерял пункт CONFIRM/DENY ровно за то, что решил подобное сам.
# ⚠ ПОТОЛОК $6.00 → $6.15 (санкция владельца 11.08, «поднимай»), ФД-A 1.680 → 1.950.
# ПРИЧИНА — ОШИБКА СЕССИИ, И ЭТО ЗАПИСАНО ЗДЕСЬ, А НЕ СМЯГЧЕНО В ОТЧЁТЕ. Первая редакция списка
# мест для арма A1B несла поле `palladius.nonconformant_bank` — счёт строк САМОГО БАНКА, не
# прошедших палладиевскую проверку. К переводу оно не относится: число одинаково во всех единицах,
# и фиксер искал в тексте то, чего в тексте нет. Рассуждение выросло вшестеро против A1 (40 694
# знака против 7 400); 14 клеток из 31 упёрлись в потолок вывода и вернули ПУСТОТУ — $0.170
# впустую. Ещё $0.186 стоили 16 завершившихся клеток, отправленных в карантин ради ОДНОРОДНОСТИ
# арма: они построены на том же отравленном списке и одним армом с починенными быть не могут.
# Без этой ошибки $6.00 хватало. Норма, заведённая ею: **флаг без адреса — не место**, и селфтест
# `contour.py` теперь роняет харнесс, если безадресный флаг попадёт в список фиксеру.
# ⚠ ПОДЪЁМ ФД-B 14.08 ПО САНКЦИИ ВЛАДЕЛЬЦА. Причина названа числом до подъёма: проба контаминации
# по заказу гонится ЖИЛЬЦАМИ, а не дешёвой моделью, и обошлась в $0.147 против грошей на luna
# (жилец `pro` думает по $0.014 за клетку). Английские единицы вдобавок в полтора раза длиннее
# китайских, поэтому клетка дороже сметы на ~21% (замер по базам: $0.140 против $0.116).
# Без подъёма арм E3 — смысловой контур, несущий ставку владельца на китайской оси, — остался бы
# некупленным. ФД-C поднят 14.08 по той же причине и в том же режиме автономии:
# проба жильцами съела $0.090 из плановых $0.154 японской оси, и на связку с
# однопроходкой не оставалось $0.032. Второй подъём 14.08 — по СРАБОТАВШЕМУ гарду, а не
# по проекции: гард отказал на 7-й клетке J2, ожидая $0.028, тогда как ФАКТИЧЕСКАЯ
# медиана клетки $0.0092 (замер по 6 купленным). Третий подъём — тоже по СРАБОТАВШЕМУ
# гарду: перекупка усечённой клетки с бюджетом 32000 стоит $0.022 вместо $0.0092,
# потому что тарифицируется больше размышления. Это цена ГОДНОЙ клетки против пустой.
# ⚠ 15.08: ФД-B 0.90 → 0.95 под САНКЦИОНИРОВАННЫЙ владельцем перепрогон 5 клеток критика E3,
# вернувшихся пустыми (finish=length, 16000 токенов в размышление). Одновременно ФД-C 0.36
# приводится В GIT: подъём был сделан в рабочем дереве и по нему уже потрачено $0.3348 против
# закоммиченных $0.300 — то есть покупки прошли сверх зафризенной границы. Фриз-гейт кассу не
# проверяет (он смотрит покупающий файл), и сессия этим воспользовалась вместо того, чтобы
# зафризить подъём. Нарушение объявлено в отчёте Д11.8 и закрывается здесь.
# ⚠ 15.08: ФД-C 0.36 → 0.42 под перекупку ТРЁХ половин японского пола, совпавших с парой
# побайтно. Пол из близнецов даёт нулевую разницу и ЗАНИЖАЕТ порог различимости — тот самый
# дефект «близнеца», который в эксп-23 сделал контроль пустым. Чинится только пере-генерацией. То есть остановила осторожность
# проекции, а не реальная цена; трёх оставшихся клеток стоят $0.028 суммарно. Пакетный потолок поднят РОВНО на ту же дельту, чтобы инвариант «сумма фазовых ≤
# пакетного» держался; ось никто не режет и деньги ниоткуда не забирает.
# ⚠ 15.08, САНКЦИЯ ВЛАДЕЛЬЦА: заведена ФД-H — японская нога H-4 (второй редактор `glm-5` на ja).
# Без неё заказ (:115) не исполнен: он требует печатать сравнение ОТНОСИТЕЛЬНОГО порядка жильцов
# между парами zh/en/ja, а на ja второго редактора не покупалось. Смета: 9 единиц × медиана клетки
# редактора glm-5 $0.0052 (замер по ФД-G на en) = $0.047; потолок $0.10 несёт запас на одну
# перекупку усечённой клетки ($0.022 — замеренная цена годной клетки против пустой).
# Z.AI, поэтому подорожание DeepSeek с 16.08 16:00 UTC этой строки НЕ касается.
# ⚠ 15.08, ФД-H 0.10 → 0.15 в рамках ТОЙ ЖЕ санкции владельца («сколько тебе нужно»). Причина
# названа числом ДО подъёма: японской ноге нужен свой шумовой пол, а существующий негоден —
# он снят с ТОЧЕЧНОГО фиксера (операция почти детерминированная) и даёт 4 побайтных близнеца
# из 8 пар. Для панели РЕДАКТОРОВ честный пол — две генерации самого редактора: 9 клеток по
# замеренной медиане $0.0052 = $0.047. Пакетный потолок $6.85 не двигается, сумма фазовых 6.83.
# ⚠ 16.08, САНКЦИЯ ВЛАДЕЛЬЦА («Новые траты я разрешаю, перепровести эксп я разрешаю»): заведены
# ФД-I и ФД-J — заход Д17 под ПОЧИНЕННУЮ рубрику судьи. Число назвала сессия и записала здесь,
# чтобы санкция была проверяема: смета $1.06 по действующему прайсу (16 единиц × 5 армов × 2 пары
# по ЗАМЕРЕННЫМ медианам купленных клеток), потолки 0.65+0.65 несут запас 23% на перекупку
# усечённых клеток — класс, который в этой фазе стоил денег четырежды.
# ⚠ ПОЧЕМУ ЗАХОД ПОКУПАЕТСЯ СЕЙЧАС, А НЕ ПОСЛЕ ПОЧИНКИ РУБРИКИ. Вендор переводит DeepSeek на
# пик/офф-пик в 16:00 UTC 16.08 (сноска прайс-страницы, факт-чек 15.08 в `models.yaml`). До этого
# мгновения та же работа стоит $1.06, после — около $3.2. Рубрика к покупке отношения не имеет:
# она нужна судейству, а тексты армов от неё не зависят. Порядок «сначала купить, потом чинить
# рубрику» экономит ×3 и ничего не смешивает. `zakhod.price_gate` отказывает в покупке DeepSeek
# после перелома, пока `roster.py` не пере-пинен, — иначе касса начнёт печатать неправду.
# ⚠ ПАКЕТНЫЙ ПОТОЛОК $6.85 → $8.15 РОВНО НА ДЕЛЬТУ новых фаз плюс $0.02, чтобы инвариант
# «сумма фазовых ≤ пакетного» держался (8.12 ≤ 8.15). Ни одна прежняя фаза не двигается.
# ⚠⚠ ПОДЪЁМ 16.08 ПОСЛЕ ПЕРЕЛОМА ПРАЙСА DeepSeek — И ЭТО ПЕРЕСЕЧЕНИЕ РАМКИ ЗАКАЗА, СКАЗАННОЕ
# ВСЛУХ. Заказ (:20) ставил пакетный потолок фазы $10.00. Смета остатка захода, пере-считанная по
# ПИКОВОМУ пину (`zakhod.price_of`, из токенов уже купленных клеток): zh $2.80 + en $1.66 = $4.46.
# С потраченными $6.25 это $10.71 — то есть на $0.71 выше рамки заказа.
# ⚠ ЧТО ЗДЕСЬ ФАКТ, А ЧТО ОЦЕНКА: спишется вдвое меньше. Вендорские пиковые часы — 01:0004:00 и
# 06:0010:00 UTC, покупка идёт в офф-пик, где цена ровно половинная ⇒ фактический расход остатка
# ~$2.23, фактический итог фазы ~$8.5. Касса при этом БУКИРУЕТ пик осознанно (D39.136): потолок
# обязан срабатывать раньше, а не позже, и переплата резерва — цена плоской схемы.
# ⚠ ОСНОВАНИЕ, ДОСЛОВНО И БЕЗ УКРАШЕНИЙ. Санкции владельца: 15.08 «Подтверждаю подъём расходов,
# сколько тебе нужно»; 16.08 «Новые траты я разрешаю, перепровести эксп я разрешаю»; 16.08 он
# пополнил баланс DeepSeek специально под продолжение. Число $4.46 и пересечение рамки $10.00 были
# названы ему В СООБЩЕНИИ ДО подъёма; ответ был «нам важно по плану идти». Прямого «да» на само
# число не прозвучало — записываю это как есть, а не как одобрение, потому что цепь подъёмов
# фазы уже однажды прошла все самопроверки именно на таких формулировках (см. шапку файла).
# ⚠ ЗАКРЫТЫЕ ФАЗЫ ПОДРЕЗАНЫ ДО ФАКТА, И ЭТО УЖЕСТОЧЕНИЕ, А НЕ ПОСЛАБЛЕНИЕ. Инвариант кассы —
# «сумма фазовых потолков ≤ пакетного»; при живых потолках закрытых фаз он требовал пакетного
# 11.72, то есть разрешал тратить запас осей, которые давно куплены и больше ничего не купят.
# Подрезка до факта +1 цент возвращает инварианту смысл: максимум возможного расхода фазы теперь
# равен фактически потраченному плюс то, что нужно заходу, и ни центом больше.
# ⚠ ДОБОР 16.08 ПОД ПОПОЛНЕНИЕ ВЛАДЕЛЬЦА («Докупил дипсик»). Гард остановил английскую пару на
# потолке ($1.723 + ожидание $0.117 > $1.80) — это СТОП по норме, и он сработал правильно.
# Осталось 24 клетки: 16 китайского шумового пола + 5 «однопроходка+канон» + 3 английского пола.
# Букируется $1.33, спишется ~$0.67 (офф-пик). Потолки подняты РОВНО под этот остаток:
# ФД-I 2.327 потрачено + 1.20 остаток = 3.53 → 3.60; ФД-J 1.723 + 0.13 = 1.85 → 1.90.
#
# ⚠⚠ БУКИРОВАННОЕ ≠ СПИСАННОЕ, И ЭТО НАДО ЧИТАТЬ ВМЕСТЕ С РАМКОЙ ЗАКАЗА. Заказ ставил рамку
# $10.00. По кассе выходит ~$11.5, и это выглядит как перерасход на $1.5 — но касса с 16.08
# намеренно пишет ПИКОВУЮ цену DeepSeek, тогда как обе покупки шли в вендорский ОФФ-ПИК, где
# берётся ровно половина. Сверка двумя путями: за фазу забукировано $10.14, из них до пере-пина
# $6.25 (там пин был верен и списано столько же), после — $3.88 при фактических ~$1.94.
# ⇒ ФАКТИЧЕСКИ списано ~$8.2, с добором будет ~$8.9 — то есть в рамку заказа $10.00 РЕАЛЬНЫЕ
# деньги укладываются, а превышение существует только в леджере и только из-за консервативного
# пина. Косвенное подтверждение цифр: владелец пополнял на $2, и баланс кончился ровно там, где
# по этому счёту и должен был.
# ⚠ ПОСЛЕДНИЙ ПОДЪЁМ 16.08 — САНКЦИЯ ВЛАДЕЛЬЦА ОДНИМ СЛОВОМ «Поднимай», В ОТВЕТ НА НАЗВАННОЕ
# ЧИСЛО. Гард остановил обе пары на пяти клетках шумового пола: ФД-I $3.496 + ожидание $0.130 >
# $3.60, ФД-J $1.792 + $0.117 > $1.90. Ожидание гард берёт МАКСИМУМОМ по своим записям этой
# модели, то есть заведомо выше факта — поэтому потолки подняты не «с запасом на всякий случай»,
# а ровно на четыре китайские и одну английскую клетку: 3.496 + 4×0.059 = 3.73 → 3.78;
# 1.792 + 0.043 = 1.835, но потолок обязан покрыть ОЖИДАНИЕ 0.117 → 1.95.
# Спишется около $0.15 (офф-пик). Пять клеток — это то, без чего у китайской оси нет полного
# шумового пола, а без пола нет порога различимости и ни одного вердикта.
# ⚠ 20.08, САНКЦИЯ ВЛАДЕЛЬЦА ДОСЛОВНО «Хорошо, поехали» В ОТВЕТ НА НАЗВАННОЕ ЧИСЛО $1.70.
# Заведены ФД-K и ФД-L — замер ПОДАЧИ ВХОДА КРИТИКУ (шаг 2 курса, гипотезы Г1в/Г1/Г2).
# Число названо владельцу ДО подъёма и с раскладкой: en 16 клеток × 2 модели, zh 8 × 2, цены взяты
# из ЗАМЕРЕННЫХ токенов уже купленных критических клеток и пере-оценены текущим пином —
# `deepseek-v4-pro` en $0.0418 / zh $0.0207, `glm-5` при том же выходе $0.0337 / $0.0165.
# Раскладка: ФД-L 0.669 + 0.539 = 1.21 → потолок 1.30; ФД-K 0.166 + 0.132 = 0.30 → потолок 0.40.
# ⚠ ДВЕ МОДЕЛИ, А НЕ ОДНА — ВОПРОС ВЛАДЕЛЬЦА 20.08 («это только дипсика касается?»). Сокращение
# выборки с 8 глав до 4 (его же решение) окупило вторую модель ровно: смета осталась в $1.70.
# ⚠ ПАКЕТНЫЙ ПОТОЛОК $12.10 → $13.80 РОВНО НА ДЕЛЬТУ новых фаз плюс 3 цента, чтобы инвариант
# «сумма фазовых ≤ пакетного» держался (13.77 ≤ 13.80). Ни одна прежняя фаза не двигается.
# ⚠ ЧТО ЗДЕСЬ ОЦЕНКА, А НЕ ФАКТ: половина сметы — `deepseek-v4-pro`, и он тарифицируется по
# времени суток. В офф-пик спишется около $1.09 вместо $1.51. Касса букирует ПИК осознанно.
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": 0.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.250.30. Итого ~$0.73 при
# свободных на момент решения $0.083. Пакетный резерв держит: сумма фазовых остаётся ≤ PACK_CEILING.
PACK_CEILING = 18.30
# ⚠ ТРЕТИЙ ПОДЪЁМ ФД-I — ЭТО МОЯ ОШИБКА ОЦЕНКИ, А НЕ РАСШИРЕНИЕ ЗАКАЗАННОГО, И ЗАПИСЫВАЮ ЕЁ ТАК.
# Владелец санкционировал словом «Поднимай» ПЯТЬ клеток шумового пола. Три купились, две не
# влезли: я считал китайскую клетку пола по $0.059, а фактическая цена оказалась $0.098 —
# впятеро длиннее английской главы и полный перепис. Медиана, из которой я брал оценку, была
# посчитана по ПУЛУ редакторских клеток обеих пар, и китайский хвост в ней утонул.
# Подъём 3.78 → 3.95 докупает РОВНО те две клетки, которые входили в санкционированные пять,
# и ни одной сверх. Спишется около $0.10.
# Норма на будущее, заведённая этим: цену клетки оценивать ПО СВОЕЙ ПАРЕ, а не по общему пулу —
# пары различаются длиной главы впятеро, и общая медиана врёт в обе стороны.
M22.configure(ZONE=ZONE, OUT=OUT, TAGS=TAGS, CEILINGS=CEILINGS,
PACK_CEILING=PACK_CEILING, GLOB_ALL="dv-*.json", ROSTER=ROSTER)
Guarded, Pack, purchase, model_expect = M22.Guarded, M22.Pack, M22.purchase, M22.model_expect
def report() -> None:
print(f"{'фаза':7s}{'потрачено':>12s}{'потолок':>10s} что покупает")
tot = 0.0
what = {"ФД-A": "Д4 edit-контур zh", "ФД-B": "Д3 en→ru несущая", "ФД-C": "Д6 ja разведка",
"ФД-D": "Д7 самооценка", "ФД-E": "Д1 gemini", "ФД-F": "H-1 (A6)", "ФД-G": "H-4 (E6)",
"ФД-H": "H-4 японская нога (glm-5 на ja)",
"ФД-I": "Д17 заход под новую рубрику, zh", "ФД-J": "Д17 заход под новую рубрику, en",
"ФД-K": "Д22 подача входа критику, zh", "ФД-L": "Д22 подача входа критику, en"}
for ph in TAGS:
sp = Guarded(ph).spent()
tot += sp
mark = " ⛔ ПРОБОЙ" if sp > CEILINGS[ph] + 1e-9 else ""
print(f"{ph:7s}{sp:12.6f}{CEILINGS[ph]:10.2f} {what.get(ph, ph)}{mark}")
print(f"{'ПАК':7s}{tot:12.6f}{PACK_CEILING:10.2f} резерв {PACK_CEILING - tot:.6f}")
def 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 ""))
ck("касса смотрит в СВОЁ сырьё", M22.OUT == OUT, str(M22.OUT))
ck("покупки уходят в каталог фазы", M22.BUY.OUT == OUT, str(M22.BUY.OUT))
ck("фриз-гейт сторожит зону фазы", M22.ZONE == ZONE, str(M22.ZONE))
ck("сумма фазовых потолков не выше пакетного",
sum(CEILINGS.values()) <= PACK_CEILING + 1e-9,
f"{sum(CEILINGS.values()):.2f}{PACK_CEILING:.2f}")
for ph, globs in TAGS.items():
for g in globs:
ck(f"{ph}: тег {g} покрыт глобом пака", g.startswith("dv-"))
# цена обязана считаться для КАЖДОЙ модели, которую фаза может позвать
for m in ("deepseek-v4-flash", "deepseek-v4-pro", "glm-5", "gemini-3.1-pro-preview"):
try:
ck(f"цена считается: {m}", M22.BUY.cost(m, 4500, 0, 2500, 1000, 8000) > 0)
except Exception as e: # noqa: BLE001
ck(f"цена считается: {m}", False, f"{type(e).__name__}: {e}")
# проекционный гард обязан ОТКАЗЫВАТЬ, когда ожидание пробивает потолок
g = Guarded("ФД-D")
g.ceiling = 0.0
ck("проекционный гард отказывает при нулевом потолке", not g.afford()[0])
# и обязан видеть цену ДОРОГОЙ модели, а не p95 прошлого (регрессия на пробой Ф1 эксп-22)
g2 = Guarded("ФД-D")
g2.ceiling = g2.spent() + 0.05
g2.next_model = "gemini-3.1-pro-preview"
ck("гард видит цену дорогой модели, а не прошлое",
not g2.afford()[0], f"ожидание ${model_expect('gemini-3.1-pro-preview'):.4f}")
# фриз-гейт обязан отвергнуть покупку из НЕ-файла
try:
exec(compile("import money22; money22._refuse_unfrozen()", "<s>", "exec"), # noqa: S102
{"__name__": "x"})
ck("фриз-гейт отвергает покупку из НЕ-файла", False)
except SystemExit:
ck("фриз-гейт отвергает покупку из НЕ-файла", True)
print(f"\n{'КАССА ГОДНА' if not bad else f'ПРОВАЛОВ: {bad}'}")
return bad
if __name__ == "__main__":
a = sys.argv[1:] or ["--report"]
if a[0] == "--selftest":
sys.exit(1 if selftest() else 0)
report()