From 7737434dfc7a655d31aa9ccc38358c62ab49887c Mon Sep 17 00:00:00 2001 From: heaven Date: Fri, 11 Sep 2026 16:19:59 +0300 Subject: [PATCH] Move the shift's lessons out of private memory into the tree, re-take the row whose zeros did not reproduce, and give the new vocabulary its glossary entries --- CLAUDE.md | 65 +++++++++++++++++++++++++++ docs/BACKLOG.md | 10 ++--- docs/PROGRESS.md | 2 +- docs/architecture/15-money-path.md | 6 +-- docs/glossary.md | 5 ++- docs/orchestrator-norms-scratchpad.md | 7 ++- 6 files changed, 83 insertions(+), 12 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 50762d71..43da92fe 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -87,6 +87,41 @@ Go-бэкенд издательского художественного пер чтобы влезть в память.** Подмножество `-run` не есть пакет: базовый прогон перестаёт быть базовым, и вердикт «поймана» становится утверждением о другом предмете. **Лучше не измерить, чем измерить не то** — формулировка зоны, выбравшей честную сторону при максимальном соблазне. +- ⛔ **ФОНОВОЕ ГАСИТСЯ ПО СВОЕМУ PID, А НЕ ПО ИМЕНИ КОМАНДЫ, и норма эта — про ЧУЖУЮ ложную зелень, а не + про твою аккуратность.** `go test`, `tmctl`, `psql`, `/exe/` — имена, общие для всех зон, поэтому + `pkill -f 'go test'` есть шаблон «все, кто сейчас работает»: убитый чужой прогон мутации читается его + хозяином как «мутация выжила», то есть ложная НАХОДКА у соседа. Замерено 29.08: сессия гасила СВОЮ + мутационную кампанию (`pkill -9 -f 'go test'`, `pkill -9 -f '/exe/'`) и попала по процессам + ПАРАЛЛЕЛЬНОЙ — узнала об этом из `ps -eo pid,cmd` уже ПОСЛЕ убийства; в записи зоны платформы за тот + же день жертвы названы поимённо — шесть ревью-агентов чужой сессии в окне 01:36:20–01:37:45, включая + линзу покрытия посадками (греп «Я убила чужие процессы» в архиве журнала платформы). ⚠ Второе лицо + того же шаблона зона платформы записала у себя (`platform/docs/STACK_DECISIONS.md`, греп «Демон нельзя + убивать»): `pkill -f <путь к бинарю>` совпадает с собственной командной строкой оболочки и убивает + вызвавшего (exit 144). ⇒ запуская фоновое, ЗАПОМИНАЙ его PID (`$!`, pid-файл) и останавливай только + его; перед любым сигналом по шаблону — сперва `ps -eo pid,cmd | grep`, глазами, чьё это, и если чужое, + не трогать. Убил чужое — сразу пинг той сессии с временным окном, чтобы она пере-прогнала посчитанное: + молчание здесь дороже признания, потому что чужие числа уже испорчены, а выглядят целыми. +- ⛔ **ЗЕЛЁНАЯ БАТАРЕЯ — ЭТО ПОЛНЫЙ СПИСОК ПАКЕТОВ ПЛЮС ОТСУТСТВИЕ `FAIL`, а не отсутствие `FAIL`.** Дважды + за смену 29.08 за зелень принят прогон **20 пакетов из 21**: `FAIL` стоял в самом хвосте лога. Оборванный + прогон выглядит почти нормальным — по алфавиту дошло докуда дошло; а для мутационных посадок он вдобавок + НЕОТЛИЧИМ от не пойманной мутации, то есть обрыв читается как дыра в тестах, которой нет. ⇒ полнота + сверяется СПИСКОМ, а не чтением хвоста: `comm -23` СПИСКА `go list ./...` против вердиктов лога обязан + быть пуст. ⚠ Порядок операндов тут несущий, и перевёрнутый пуст ВСЕГДА: замер 11.09 на движке — обрыв + на 20 пакетах из 23 даёт три строки в правильном порядке и **ноль** в перевёрнутом, то есть перевёрнутый + неотличим от полного прогона. Падение в пакете, которого не трогал, проверяется развёрткой чистого `HEAD` + (`git archive`) и прогоном вперемежку в обоих деревьях: одинаковая частота падений = не твоё. + ⛔ **И `go test` — НЕ приёмка: приёмка это ЦЕЛЬ ГЕЙТА ЗОНЫ** (`battery: build vet fmt lint test` у движка, + `check` у платформы). `lint` стоит ДО `test`, поэтому «все тесты зелёные» бывает правдой, которая не значит + ничего: пак с настоящими числами `go test -race` упал на лендинге на `errorlint` в своей же новой строке + (`%v` вместо `%w`) — до тестов гейт не доходил вовсе. **Цель, падающая первой, отменяет все последующие**, + и в отчёте называется, ЧТО именно прогнано. +- ⛔ **КОД ОБЁРТКИ — НЕ КОД РАБОТЫ.** Уведомление «completed (exit code 0)» на фоновую команду вида + `(make battery > log 2>&1; echo "MAKE_EXIT=$?" >> log) & echo started` приходит через СЕКУНДУ: ноль — это + код внешней обёртки, а батарея в этот момент ещё идёт (трижды за смену 03.09; в логе стоял один линтер). + Родня — `make`, умерший на `tools-check` под `exit 0` завершающего `echo` (`D39.212` п.8): **код возврата + составной команды отвечает на свой вопрос, а не на твой.** ⇒ `&` внутри фоновой команды не ставить — + фоновость даёт сам харнесс; нужен всё же — ждать УСЛОВИЯ, а не уведомления + (`until grep -q MAKE_EXIT log; do sleep 10; done`), и вердикт читать строкой-итогом из лога. - ⛔ **ДВА СВОЙСТВА ЭТОЙ СРЕДЫ, каждое даёт ТИХИЙ ЛОЖНЫЙ НОЛЬ** (замерено 11.09, поймано двумя ролями независимо). **(а) `grep` здесь — не GNU grep, а shell-обёртка над ugrep с `--ignore-files`: она чтит `.gitignore` и НЕ ВИДИТ каталог `books/`,** то есть всё платное сырьё проекта. Замер: `grep -rl '^terms:' .` → **13** @@ -115,6 +150,26 @@ Go-бэкенд издательского художественного пер задан существующему предмету: «БД без этой таблицы: 0», «файлов прибор прочёл: 67». ⛔ Именно печатается, а не упоминается: «проверено с контрольной строкой» — утверждение О проверке, читатель видит слово вместо числа, и норма ловит замер, но не отчёт о нём (`D39.202`, `D39.217` п.2б). +- ⛔ **«НЕ ВОСПРОИЗВЕЛОСЬ» — ЭТО НЕ «НЕДОСТИЖИМО»: верный прогон при неверной гипотезе неотличим от + «дефекта нет»** (`D39.170`, `D39.174` п.в). Замер: ПЯТЬ попыток воспроизвести перерасход дали пять + «нет», и все пять прогонов были ВЕРНЫ — ошибочна была гипотеза о механизме; решало ВТОРОЕ поле, на + которое не смотрели, а условия достижимости тянули в РАЗНЫЕ стороны (естественный способ добиться + эффекта ровно им же и убивал его), поэтому перебором фикстур такое не нащупывается — только пониманием + механизма. ⇒ прежде чем писать «воспроизвести не удалось», назови ЦЕПЬ звеньев от входа к следствию и + проверь КАЖДОЕ отдельным замером, а не только то, которое кажется решающим; цепь, не проверенная + звеньями, даёт формулировку «я не нашёл условие», а НЕ «условие недостижимо». И лечить класс + структурно всё равно нужно: фикс, покрывающий класс, от того, нашлась ли фикстура, не зависит. + ⛔ **И злее того — ВЕРНЫЙ РЕЗУЛЬТАТ ПРИ НЕВЕРНОМ МЕТОДЕ: он не краснеет нигде** (11.09, полигон; нашёл + критик чисел, не автор). Строки лога делились по двум попыткам сравнением времени. Первый раз метод + сломался грубо — разделитель в колонке `ts` ПРОБЕЛ, а сравнивали с `T`, и все 33 строки ушли в первую + попытку (33/0). Разделитель починили, числа стали ПРАВИЛЬНЫМИ (16 и 17 строк из 33) — и на этом + остановились, а метод остался негодным: `ts` секундной гранулярности против `started_at` с + микросекундами, то есть все шесть подстановок формально «раньше» старта своей же попытки, и верные + числа вышли по счастливому порядку строк. ⇒ **если в данных есть поле, прямо отвечающее на вопрос, + любой ВЫВОД этого ответа — по времени, по порядку, по соседству — уже дефект метода, даже когда + сходится** (здесь ответ нёс `trace_id`: в нём стоит номер попытки). Спрашивай «чем это НАЗВАНО в самой + строке?» прежде, чем вычислять: красное заставляет чинить способ, зелёное при правильном числе не + заставляет ничего. - **Мандат самопроверки в промтах сессий (обязателен, решение владельца):** промты полигон-сессий — и вообще любых пишущих код / запросы к моделям — ДОЛЖНЫ явно требовать ревью ИСПОЛНЕНИЕМ: своего кода + сформированных запросов к моделям + полученных результатов. Сессии регулярно ошибаются и багуют, и это искажает результат; **самоотчёт «проверено» без исполнения регулярно оказывается ложным и стоит денег**. Бэкенд-промты — явный бэкенд-ревью после кода (обычно отрабатывает по опыту, но требовать явно). Пост-хок адверсариальная верификация оркестратора при лендинге — второй рубеж, НЕ замена самопроверки. ⚠ **Исполнения мало: промт заказывает адверсариальный проход сессии по СВОЕЙ готовой работе; глубину и веер сессия выбирает под предмет, промт даёт направление — что в этом паке уязвимо.** ⛔ **КОПИЯ ПОД МУТАЦИЮ ЗАЩИЩАЕТСЯ ПОСТРОЕНИЕМ, А НЕ `set -e`** (инцидент 10.09, зона назвала сама). @@ -198,6 +253,16 @@ Go-бэкенд издательского художественного пер ⛔ **МУТАЦИЯ ЗАСЧИТЫВАЕТСЯ ПО ТЕКСТУ СООБЩЕНИЯ, А НЕ ПО ФАКТУ КРАСНОТЫ.** Читай ТЕКСТ падения: говорит ли он про сломанное тобой. Правый вердикт по неправой причине — дыра, а не поимка, и от настоящей поимки отличается только тем, прочёл ли кто-нибудь текст, а не цвет (`D39.217` п.2в). + ⛔ **ФИКСТУРА ОБЯЗАНА НАЗВАТЬ ГРАНИЦУ, КОТОРУЮ ПРОШЛА: у сквозного теста граница — побочный эффект + того, как сконфигурирован прогон, а не то, что тест утверждает** (08.09, зона нашла у СЕБЯ и назвала + прямо, `D39.228` п.5). Проекция банка публикуется на ПЯТИ границах прогона, и каждая несёт свою метку + внутри самого документа; все три сквозных теста к ней открывали раннер так, что читали артефакт границ + «авто-продолжение» и «прогон закончен», а предметом была граница ПОДПИСИ — единственная, ради которой + проекция и существует. Порча «не публиковать секцию именно на границе подписи» шла ЗЕЛЁНОЙ по всей + батарее. ⇒ у артефакта больше одного момента записи — тест утверждает СНАЧАЛА, какой момент он прочёл + (сверка метки границы), и только потом содержимое; иначе зелёный тест описывает не тот момент и молчит + ровно там, где предмет. Вопрос себе: «сколько раз этот файл переписывается за прогон и какой из разов + я сейчас читаю?» ⭐ **Пришло письмо «всё закрыто» — иди перечитывать СВОИ утверждения о закрытом, а не чужие правки.** ⛔ **Fable 5 — ПОТОЛОК 1–2 АГЕНТА НА СЕССИЮ, слово владельца 11.09: «я не разрешаю больше 1-2 на сессию».** Прежняя редакция называла это рекомендацией — она отозвана. Модель задавай агенту ЯВНО и знай, сколько их у тебя работает. ⚠ И форма важнее числа: **одному агенту с ПОСТОЯННЫМ контекстом дослылают вопросы, а не поднимают второго** — контекст и есть ценность. Опус-субагенты потолком не ограничены, но тратятся так же. - **Git-координация мультисессий:** diff --git a/docs/BACKLOG.md b/docs/BACKLOG.md index 7713b16d..6d95707b 100644 --- a/docs/BACKLOG.md +++ b/docs/BACKLOG.md @@ -3,7 +3,7 @@ > **Единственный трекер проекта.** Здесь живут строки, на которые доки, промты и D-ноты ссылаются словами «строка N» / «строка бэклога N»: **ID строки стабилен навсегда**, не перенумеровывается и не переиспользуется (D39.80). Правки — только через оркестратора; каждая петля обязана иметь диспозицию: решено / отложено-с-записью / отклонено. > ⚠ **Это НЕ бэклог зоны `docs/`, а бэклог ПРОЕКТА.** У зон свои, с другими неймспейсами ID, и единый их строк не принимает (D39.84): платформа — [../platform/BACKLOG.md](../platform/BACKLOG.md) (`П-N`) и её регистр дефектов `platform/docs/DEFECT_REGISTER.md` (`PD-N`); фронт — [../frontend/docs/BACKLOG.md](../frontend/docs/BACKLOG.md) (`Ф-N`). > ⚠ **Состояние проекта — не здесь.** Очередь, курс, CURRENT-STATE, состояние паков и живая хроника — шапка [PROGRESS.md](PROGRESS.md). Здесь только долг и его диспозиции. -> - **СЧЁТ ОЧЕРЕДИ на 11.09 (скриптом по таблице — `python3 docs/scripts/counts.py`; обновлять при каждом лендинге):** всего **316** строк · зона бэкенд **151** строго / **206** широко (⚠ колонки счётчик читает С КОНЦА — испр. D39.116) · **блокеров очереди 0** (236 закрыта D39.175; **371** — актом D39.233, **360** — актом D39.232, обе 10.09), платные прогоны разблокированы · «скоро» **161** (перечень — грепом по таблице, рукописный список снят D39.126) · гейт-строка эксп-22: 153 (плюс 150 — руки владельца; ⚠ 55 из гейтов СНЯТА — D39.198 п.5); строка 5 — остаток гейчен ре-пробой 74, носитель события теперь строка 188 (аудит D39.140); остальное «когда-нибудь». ⚠ Счёт — НИЖНЯЯ граница долга, не потолок (разбор — легенда таблицы ниже). +> - **СЧЁТ ОЧЕРЕДИ на 11.09 (скриптом по таблице — `python3 docs/scripts/counts.py`; обновлять при каждом лендинге):** всего **316** строк · зона бэкенд **152** строго / **205** широко (⚠ колонки счётчик читает С КОНЦА — испр. D39.116) · **блокеров очереди 0** (236 закрыта D39.175; **371** — актом D39.233, **360** — актом D39.232, обе 10.09), платные прогоны разблокированы · «скоро» **161** (перечень — грепом по таблице, рукописный список снят D39.126) · гейт-строка эксп-22: 153 (плюс 150 — руки владельца; ⚠ 55 из гейтов СНЯТА — D39.198 п.5); строка 5 — остаток гейчен ре-пробой 74, носитель события теперь строка 188 (аудит D39.140); остальное «когда-нибудь». ⚠ Счёт — НИЖНЯЯ граница долга, не потолок (разбор — легенда таблицы ниже). > - ⚠ **Переезд 06.09 (D39.218):** таблица вынесена из `PROGRESS.md` ДОСЛОВНО и ни один ID не сдвинут — **с единственным исключением: две ячейки (строки 220 и 306) тронуты РОВНО в номере якоря `docs/scripts/counts.py:566`→`:569` и `:592`→`:595`**, потому что цель сдвинул этот же коммит; текст ячеек не менялся, длины равны. В `PROGRESS.md` на прежнем месте оставлен заголовок-указатель, поэтому ссылки «секция „Бэклог“» доезжают в один хоп. ## Бэклог (ЕДИНЫЙ, собран 26.07, актуализация 04.08 D39.99/D39.101; правки — только через оркестратора) @@ -283,7 +283,7 @@ | 353 | **КОНТРАКТ СЕКЦИИ ПРЕДЛОЖЕНИЙ В САЙДКАРЕ БАНКА ЗАПИНЕН ПО ПОЛЯМ И ПОРЯДКУ, НО НЕ ИСЧЕРПЫВАЮЩЕ — строка заведена ПРАВИЛОМ ОСТАНОВКИ, а не находкой.** Три круга приёмки `D39.225` находили в одной новой секции всё более узкие дыры: сперва семь полей без утверждений, потом `Freq` и своп списков, потом ранжирование и класс пустого `Dst`. Каждая была настоящей и предъявлена посадкой; каждый следующий круг стоил больше и покупал меньше. Сегодня запинены: все решающие поля против стоп-строки · порядок против стоп-СТРОК на двух уровнях · рефлективный страж «ни одно поле проекции не нулевое» (ловит поле, добавленное завтра и не заполненное). ⚠ **Дописка 08.09 (приёмка `D39.226`):** у поля `SettledByBank` стоп-строки нет свидетеля в списке «полей, которых сайдкар намеренно НЕ несёт» (`bankexport_test.go`) — то есть его сознательное отсутствие в проекции не утверждено ничем; закрывать вместе с первым читателем секции. ⚠ Границу называет сам гейт: поле, которое отрастил `BankStopRow` и которое СЛЕДОВАЛО бы проецировать, механически не ловится — это суждение того, кто поле добавляет. ⇒ вернуться к исчерпывающему контракту, когда у секции появится ЧИТАТЕЛЬ (платформенная половина строки **224**): пока читателя нет, расхождение ничем не судится, а в день его появления разница станет семантикой задним числом — второй ярус класса A `18-bank-ontology.md` | бэкенд + платформа | когда-нибудь (гейт: появление читателя секции, строка 224) | исчерпывающий пин контракта секции вместе с её первым потребителем | `D39.225` п.10 | | 354 | ⛔ **ОПЛАЧЕННЫЙ `2xx` С ОБОРВАННЫМ ТЕЛОМ — КЛАСС, СТОИВШИЙ 32 % ЖИВОГО ПРОГОНА, И СТРАНИЦА КВИРКОВ О НЁМ МОЛЧИТ.** Живой прогон 08.09 (10 глав, `committed=$1.259217`): два вызова редактора вернулись `2xx` с нечитаемым JSON и были ОПЛАЧЕНЫ — `$0.407606`, то есть **32 % бюджета прогона**. Движок класс ЗНАЕТ и обрабатывает штатно: `backend/internal/pipeline/disposition.go:80`=`FlagDecodeError FlagReason` `FlagDecodeError` — «2xx with an unreadable body — billed, conservatively settled, flagged». ⛔ Но `docs/experiments/00-provider-quirks.md` — страница, которую канон велит читать ПЕРЕД правкой адаптеров и вызовов, — о нём не несёт НИ СТРОКИ: греп по `decode`/`unexpected end of JSON`/«оборван» даёт **0 при 250 строках файла** (контроль: слово `provider` там встречается 3 раза, то есть спрошено существующее). ⇒ следующая сессия, читающая квирки перед платным прогоном, не узнает о поведении, которое съедает треть бюджета. ⛔ **испр. 08.09: МЕХАНИЗМ НАЗВАН ЗДЕСЬ НЕВЕРНО — это не свойство провайдера, а дефект движка, и носитель у него теперь строка 360.** Полигон замером exp-23 п.5 показал, что за подписью «нечитаемое тело» стоит ТАЙМАУТ ЧТЕНИЯ по `attempt_s`, который движок сам же выбрасывает в `_`. ⇒ эта строка остаётся ТОЛЬКО про пробел страницы квирков: она обязана предупреждать, ЧТО оператор увидит и почему, со ссылкой на 360, а не приписывать поведение вендору. ⚠ Зона — ПОЛИГОН (`docs/experiments/` по зонной таблице), живой сессии полигона нет; строка заведена оркестратором как носитель, писать в файл полигону | полигон | скоро (перед следующим платным прогоном любой зоны) | строка в `00-provider-quirks.md` с частотой, стоимостью и тем, что движок делает с классом | живой прогон 08.09, пак «правда оператору и деньги» | | 356 | **КНИГА У СВОЕГО ПОЖИЗНЕННОГО ПОТОЛКА РОЛИ НАВСЕГДА ОСТАЁТСЯ БЕЗ КОНСОЛИДИРОВАННОГО БАНКА, и ни одно сообщение не говорит именно этого.** `store/ledger.go` `RoleSpentUSD` суммирует чекпойнты роли за ВСЮ жизнь книги, предполётный срез сеет `probe := spent` и обрывается на `probe+want > budgetUSD`; при `fits == 0` цикл попыток не запускается вовсе. ⚠ Оператор ПРИ ЭТОМ извещён — `terminologist.go:936` печатает `batches_planned=N batches_running=0 batches_dropped=N spent_usd budget_usd` ДО первого вызова (сверено оркестратором 08.09), поэтому «тихо» здесь неверно, и находка приёмки в этой части ОТКЛОНЕНА доводом зоны. Верен остаток: сообщение говорит про ЭТОТ прогон, а не про то, что книга исчерпала пожизненный бюджет роли и консолидации не получит НИКОГДА, сколько её ни перезапускай. Свойство `budget_usd`, а не фильтра пака «правда оператору и деньги»: тот на решение бюджета не влияет. ⇒ решить, что показывать оператору и владельцу: отдельное сообщение «книга у пожизненного потолка роли», подъём потолка как явный акт, или сознательное молчание с записью | бэкенд | когда-нибудь (гейт: первая книга, упёршаяся в пожизненный потолок роли) | сообщение об исчерпании пожизненного бюджета либо ратифицированное молчание | приёмка `D39.226`, линза «вне карты» | -| 359 | **ТРИ ЯКОРЯ В ЧУЖИХ ЗОНАХ ПРОТУХЛИ ОТ ДВУХ ДВИЖКОВЫХ ЛЕНДИНГОВ — адреса уже найдены, править владельцам зон.** Линтер `counts.py --lint` даёт 6 проблемных якорей при 121 живом доке; три из них — фронтовые и пингнуты в `frontend/docs/frontend-PROGRESS.md` (зона ЗАМОРОЖЕНА). Остальные три, с новыми адресами, снятыми оркестратором 08.09: **(а) полигон** — `docs/experiments/23-editor-tier.md:7739` и `:7740` ссылаются на «×2 дешевле glm» в `configs/pipeline-c1.yaml:95` и `pipeline-arm-glm.yaml:6`; ⚠ цель ИСЧЕЗЛА, а не сдвинулась (греп даёт 0): долларовые числа сняты из шапки арма приёмкой `D39.226`, потому что стояли на опровергнутом ценовом базисе — значит якорь надо не пере-навести, а пере-написать по факту. **(б) бэкенд** — `backend/docs/DISCLOSURE_LAW_DESIGN.md:40` ссылается на `internal/pipeline/quality.go:233`, токен уехал на `:235`. ⚠ Оркестратор в чужие зоны не пишет; строка — носитель, чтобы адреса не искали заново | полигон + бэкенд | когда-нибудь (попутно с любым касанием этих файлов) | пере-наведённый якорь у бэкенда, пере-написанный по факту — у полигона | `counts.py --lint` 08.09 | +| 359 | ⛔ **ЯКОРНЫЙ ЛИНТ НА ГРЯЗНОМ ДЕРЕВЕ НЕ ДАЁТ ЧИСЛА: ЗА ОДИН СЕАНС 11.09 ОН ВЫДАЛ 19 → 15 → 11 НА ОДНИХ И ТЕХ ЖЕ 123 ЖИВЫХ ДОКАХ.** Ряд утверждал «6 проблемных якорей при 121 живом доке» (08.09) — протух; но сменившее его число протухало ТРИЖДЫ за час, пока его мерили. Причина названа собственным футером прибора: цели читаются из ДЕРЕВА, а дерево одновременно правят движок, платформа и контракт — чужой незакоммиченный WIP и роняет токен, и спасает его. ⇒ **норма: якорный линт судят по `HEAD` либо по ЧИСТОМУ дереву; число с грязного — снимок, а не факт, и в доке оно живёт только с датой и с этой оговоркой.** ⛔ **И развилка, которую сеанс прошёл в ОБЕ стороны — нормы нет ни одной, вопрос владельцу.** Четыре якоря зоны оркестратора (`BACKLOG.md:120`, `:127`, `:256` → `openapi.yaml:2191`/`:2367`/`:3159`; якорь в теле `D39.212` → `runs.go:479`) были ВЕРНЫ в `HEAD` и «красны» только от WIP соседа; коммит `bdc1547` по пингу зоны пере-навёл их ВПЕРЁД, на позиции ДЕРЕВА (`:2200` · `:2376` · `:3168` · `runs.go:490`), и теперь они верны в дереве и НЕВЕРНЫ в `HEAD`. Обе стратегии законны — «ждать лендинга и судить по `HEAD`» либо «наводить на то, что вот-вот сядет», — но выбрать надо ОДНУ, иначе прибор красит по очереди то одних, то других. ⭐ **Половина (б) ЗАКРЫТА:** `backend/docs/DISCLOSURE_LAW_DESIGN.md:40` пере-наведён с `:233` на `quality.go:235`; в `HEAD` `:235` ВЕРЕН, и красным его делает только WIP движка — то есть единственный сегодняшний бэкендовый ✗ ложный. **Остаток на 11.09 — 11 ✗, из них НАСТОЯЩИХ 10:** `docs/experiments/` **7** + фронт **3** (зона ЗАМОРОЖЕНА). **Восемь пере-наводятся адресом** (снято по `HEAD` `bdc1547`: `httpllm.go` 517→**739**, 528→**750** · `models.yaml` 137→**173** · `export.go` 176→**178** · `14-api-contract/README.md` 1054→**1097** · `openapi.yaml` 1606→**1624**), **два пере-писываются по факту:** `23-editor-tier.md:7739`/`:7740` — «×2 дешевле glm» в `pipeline-c1.yaml:95` и `pipeline-arm-glm.yaml:6` ИСЧЕЗЛО (файлы живы, 250 и 83 строки, греп 0; обе строки удалил коммит `7ffec51`, где они видны со знаком «−»). ⚠ **Прежняя атрибуция этого снятия к `D39.226` НЕ подтверждается телом ноты:** в нём ноль вхождений `glm`, «ценов», «дешевл» (контроль: «пак» — 5) — переписывать по ФАКТУ конфига, а не по этой ссылке. ⚠ Все адреса выше сняты по `HEAD` и протухнут при следующем лендинге — пере-снимать в момент правки, а не верить строке. ⛔ **ПОЛИГОННЫЕ 7 БЕЗ ХОЗЯИНА:** зона выведена из скоупа целиком (`D39.248` п.4), доки `docs/experiments/` остались в дереве, а перечень унаследованного другими зонами в той ноте — ряды 413·414·415·416·417·422 — ЭТОТ ряд не называет. Каталог лежит под `docs/`, то есть по умолчанию оркестратора, но зонная таблица отдавала `docs/experiments/` полигону ⇒ **сдвиг границы зоны, которого не объявляла ни одна нота, и назначать его себе молча нельзя** | фронт (3, ЗАМОРОЖЕН); полигонные 7 — БЕЗ ХОЗЯИНА; выбор нормы якорения — владельцу | когда-нибудь (8 адресов — механическое пере-наведение, попутно с касанием файлов) | выбрана ОДНА норма якорения (`HEAD` либо «вперёд») · 8 адресов пере-наведены · 2 полигонных пере-написаны по факту · хозяин `docs/experiments/` после `D39.248` назван явно | `counts.py --lint` 08.09; пере-замеры 11.09 — 19/15/11 на 123 доках, разбор по `HEAD` `bdc1547` | | 361 | **ДВА ГЕЙТА ОДНОГО ФАЙЛА ТЯНУТ ЯЧЕЙКУ В РАЗНЫЕ СТОРОНЫ: экранирование `\|` по счёту колонок ЛОМАЕТ сверку токена якоря.** Счёт ячеек требует экранировать черту в тексте ячейки; сверка якоря сравнивает токен с кодом ДОСЛОВНО, а в коде черта без слеша. ⇒ токен, внутри которого есть `|`, после законного экранирования перестаёт совпадать с целью, и линтер кричит «цель уехала» на невиновного. Замерено платформенной сессией 08.09 на `PD-422`: якорь `internal/runs/runs.go:408` держал токен `resnapshot := book.BankMoved || book.HasPriorRun`; после экранирования черт по §4.5 токен перестал совпадать, и сессия починила это УКОРОЧЕНИЕМ токена — то есть заплатила точностью якоря за форму таблицы. ⇒ следующий, кто пойдёт экранировать черты, наступит на то же и так же потеряет точность. **Направление:** `norm()` в `docs/scripts/counts.py` снимает экранирование `\|` → `|` перед сверкой — шаг детерминированный и симметричный, как и схлопывание пробелов, которое та же функция уже делает по тому же доводу; докстринг «пробельная нормализация — и только она» правится вместе с поведением, иначе останется вторым носителем. ⚠ Укороченный токен `PD-422` после починки можно вернуть к полному | оркестратор | скоро | `norm()` снимает экранирование, селф-тест на случай `a \|\| b`, докстринг переписан | находка платформенной сессии 08.09 при исполнении пака разреза приёма | | 362 | **РЕМОНТ ПРОТИВ РЕМОНТА: несколько ремонтов одного чанка покупают ДОКАЗУЕМО НЕПЕРЕСЕКАЮЩИЕСЯ спаны и вытесняют друг друга в `superseded`.** Третий член семьи строк 355/358: адрес `{глава, чанк, стадия}` предполагает, что поздний вызов ЗАМЕЩАЕТ ранний, а ремонт переписывает ОГРАНИЧЕННЫЙ спан, не весь выход стадии. ⚠ Механизм здесь НЕ пересказан — он расписан в самом коде, `backend/internal/pipeline/paidtail.go` (абзац «The repair role shares that address WITHOUT sharing that property»), и там же названо, почему очевидное лечение не работает: разведение по РОЛИ ремонты между собой не различает — «every one of them carries the same role and only the span tells them apart». ⛔ Нынешнее поведение ЗАПИНЕНО КАК НЕПОДВИНУТОЕ, а не как верное — `TestTheRoleSplitDoesNotMoveARepairsMoney`; то есть пин охраняет отсутствие тихого сдвига, а не правильность. **Цена, замер ревьюера движковой сессии 08.09: 77 % денег чанка отчитаны как «купившие ничего»** ⚠ (оркестратором НЕ пере-мерено — взято со слов замера, механизм проверен по коду). Не взято в пак «движок уже знает» сознательно: вторая денежная поверхность в одном лендинге | бэкенд | скоро | ремонты одного чанка различены по спану, а не по триплету; пин утверждает ПРАВИЛЬНОСТЬ, а не неподвинутость | приёмка пака «движок уже знает» 08.09 | | 363 | **ПОЛНЫЙ ТЕКСТОВЫЙ САЙДКАР МОЛЧИТ О НЕПОЛНОТЕ БАНКА — а баннер зовёт в него ровно тогда, когда строк больше капа.** После пака «движок уже знает» факт неполноты несут машинный сайдкар и stdout-экран; текстовый сайдкар стоп-таблицы выведен из заказа §4.1 сознательно и остался единственной поверхностью, которая о неполноте не говорит. ⚠ Цена именно в связке: stdout капирован 20 строками, и когда строк больше, баннер отправляет читателя в ПОЛНЫЙ текстовый сайдкар — то есть туда, где факта нет. ⇒ на большой книге оператор, послушавшийся баннера, теряет ровно то, что пак довозил | бэкенд | скоро | текстовый сайдкар несёт полноту наравне с двумя другими поверхностями | пинг движковой сессии, приёмка пака «движок уже знает» 08.09 | @@ -329,11 +329,11 @@ | 406 | ⛔ **КОНСИСТЕНТНОСТЬ КНИГИ НИКТО НЕ СПРАШИВАЕТ — ПРИБОРА ПО ОТГРУЖЕННОМУ ТЕКСТУ НЕТ ВОВСЕ.** Мера «сколько РАЗНЫХ передач дал один термин» ПОСТРОЕНА (`Spread`/`Variants`, `backend/internal/pipeline/mining.go:383-384`=`how many DISTINCT renderings the drafts produced`), но считается по ЧЕРНОВИКУ, на стопе майнинга, ДО редакторской волны, и читает её только человеческая таблица подписи. По ФИНАЛЬНОМУ тексту такой меры не существует ни одной. ⇒ приоритет №1 владельца («консистентные термины на всю книгу») сегодня НЕПРОВЕРЯЕМ в принципе: все четыре A/B, показавшие пользу банка, меряли ПРИСУТСТВИЕ инъектированной формы в чанке, а не отсутствие конкурирующей. **Лечение $0 и переиспользует готовое:** тот же счёт по отгружаемому тексту + строка отчёта сборки «термин X отдан тремя формами в главах 12, 340, 901». Предмет не пуст: полигонный прибор на стенде дал 13–16 % терминов с более чем одной передачей. ⚠ Это ЕДИНСТВЕННАЯ работа, которая делает качество ПРЕДЪЯВИМЫМ; без неё кривую деградации по главам снять не с чего ⛔ **ИСПОЛНЕНО ЧАСТЬЮ 11.09 ПРОГОНОМ A, и первый же результат снял мою же формулировку слепого пятна.** Прибор построен полигоном и дал по отгруженному тексту «0 терминов из 40 отданы более чем одной формой». ⚠ **Ноль держался на том, что прибор НЕ СМОТРЕЛ:** кандидаты искались регуляркой, требующей ЗАГЛАВНОЙ буквы (`[А-ЯЁ][а-яёА-ЯЁ-]+`), и склонённые строчные формы («гу-мастера», «наложницей») отпадали ДО правила сравнения. Я заказал переписать правило сравнения пословно — **заказ бил мимо**: критик применил этот рецепт к прибору на боевых данных, и не вернулся НИ ОДИН из 29 потерянных термов. Починка ГЕНЕРАЦИИ кандидатов на тех же данных даёт **48 найденных термов вместо 40** — это замер, и он стоит. ⛔ **А «шесть строк со `spread ≥ 2`» ИСПР. 11.09 — я процитировал число КРИТИКА, которое полигон ОТОЗВАЛ в том самом отчёте, что я принял актом.** Её собственный пере-замер той же починки даёт **девять**, и все девять — ШУМ: оконный поиск глотает соседние слова и считает каждое окно отдельной формой («старейшины и», «Фан не», «глава рода он»). Её формулировка дословно: «покрытие 40 → 48 — замер; счёт расхождений у починенного прибора — шум», улика — `checks/spread-candidate-fix-probe.txt`, и окну недостаёт фильтра, отвергающего лишние слова. ⇒ **числа расхождений у починенного прибора НЕТ вовсе**, и заказ следующему — сначала фильтр окна, потом счёт. ⭐ Класс моей ошибки: я взял число из отчёта, не дочитав до раздела, где его автор от него отказался. ⚠ И заголовочный «0» неустойчив к порогу складывания: под пословным правилом `沈翠` распадается на «Шэнь»/«Шэнь Цуй» и число становится 1. ⇒ остаток ряда: прибор по ФИНАЛЬНОМУ тексту с (а) генерацией кандидатов без регистрового фильтра, (б) названным порогом складывания, (в) замеренной чувствительностью к нему. ⭐ **ПРАВИЛО ВЫБОРА ПЕРВИЧНОЙ КОЛОНКИ — ратифицируется актом приёмки пака 11.09; записано здесь, чтобы пережило смену, и УЖЕ ИСПРАВЛЕНО ДВАЖДЫ.** У прибора две колонки: СТРОГАЯ (равенство стеммов, как у пост-проверки) и ЯКОРНАЯ (признаёт склонённую передачу). **Первичная — ЯКОРНАЯ, строгая идёт полом точности рядом.** ⛔ **Направления ошибок, иначе довод читается наоборот:** строгая ошибается в сторону ЛОЖНОЙ ТРЕВОГИ (форма доехала склонённой, а она объявляет нарушение); якорная — в сторону СОКРЫТИЯ (засчитывает совпадение, которого по смыслу нет). **Как детекторы нарушения на прогоне A:** строгая дала 18 сообщений, настоящих 7 ⇒ точность **0.39**; якорная дала **9** при 7 настоящих ⇒ **0.78**. ⚠ **Число ИСПР. 11.09 и было 1.00 ДО ужесточения `NearStems` до строгого префикса** — ужесточение вернуло `邪魔` («злой»/«злог» — замена, не усечение) в ложные, и это цена размена, которым закрыты три коллизии многословных передач. Вторая ложная — `话事人`, однословная передача, якорить нечем. ⇒ **каждое пятое сообщение первичной колонки ложное, и читать её надо с этой поправкой.** ⇒ основание НЕ «ложная тревога дешевле сокрытия» (так было написано, и так оно аргументирует ОБРАТНОЕ), а такое: **детектор, врущий в 61 % сообщений, не громче — его перестают читать, а непрочитанный прибор не защищает ничего.** ⛔ **Второе основание, от данных не зависящее:** писатели `decl.forms` в не-тестовом Go только сидовые (`internal/seed/normalize.go:85`=`d := Decl{Invariant: t.Decl.Invariant`, `internal/membank/memseed.go:166`=`b, mErr := json.Marshal(declInfo{`), майнер форм не пишет, а дверь `BankCorrection` контракта поля `decl`/`forms` не несёт вовсе ⇒ на дорожке продукта форм нет НИ У КОГО, и строгая колонка там вырождается в одношаговое равенство. ⚠ Иллюстрация «0 форм из 69 в банках прогона» основанием НЕ является. ⛔ **ДВА ЧИСЛА ТОЧНОСТИ, путать нельзя (замерено зоной 11.09): само ОТНОШЕНИЕ строгого префикса — 17 из 30 равномерной выборки принятых пар, ≈0.57** (`рода~родной`, `гор~горная`, `так~также` — разные леммы); **колонка в своих ограждениях — 11 из 11 на прогоне A.** ⇒ работает не отношение, а ограждения (якорь · многословное окно · границы предложения), и их эффективность замерена на ОДНОЙ книге. Названный отказ: где слово банковской передачи окажется соседом другого слова в той же позиции окна, колонка соврёт в сторону сокрытия. ⛔⛔ **ПРАВИЛО ДЕЙСТВУЕТ ПРИ УСЛОВИИ: пока прибор ФЛАГУЕТ и не отказывает.** Станет он гейтом отгрузки — ложная тревога начнёт стоить удержанного текста или пере-генерации, то есть ДЕНЕГ, асимметрия перевернётся, и порядок колонок надо решать заново. ⇒ **триггеров пере-открытия ДВА:** (1) появился МАШИННЫЙ писатель `decl.forms`; (2) **эта колонка стала гейтом** — носители: `Gates.Glossary.PostcheckGate` построен (`backend/internal/pipeline/quality.go:288`=`gateOn := r.Pipeline.Gates.Glossary.PostcheckGate`, свёрнут в снапшот) и выставлен в НУЛЕ из четырёх живых конфигов, плюс ряд **296** (точечная перегенерация по промаху — направление владельца, работы нет). ⚠ Второй триггер сегодня БЛИЖЕ первого. ⚠ Прежнее моё решение (первичная — строгая) принято и отменено 11.09 в один день; цена разворота — согласие с ручным оракулом 13/16 против 10/16, **и это n=16: направление, а не величина.** Так же и 0.57 — порядок, а не третья цифра.| бэкенд | **скоро** | счёт расхождения форм по отгруженному тексту + строка отчёта сборки | аудит банка 11.09, `research/34` §2.1 | | 407 | **ПОСТ-ПРОВЕРКА БАНКА СПРАШИВАЕТ НЕ ТО: присутствие формы ГДЕ-НИБУДЬ в чанке вместо формы НА МЕСТЕ срабатывания, и про конкурирующую передачу не спрашивает никогда.** `backend/internal/membank/mempostcheck.go` — вопрос bag-of-words по всему чанку ⇒ дрейф ВНУТРИ составного имени невидим по построению. Замерено исполнением на копии: ряд `方源`→«Фан Юань» с алиасом `古月方源`, выход «Гу Юэ Фан Юань» даёт 0 промахов при подписанном каноне `古月 → Гуюэ`; контроль рядом (форма реально отсутствует) даёт 1 промах, то есть прибор спрошен и отвечает. ⚠ **У экземпляра ДВА корня, и смена вопроса закрывает только один:** ряд `古月` съеден равнотрастовым длиннейшим матчем (`memory.go` `suppressContained`) МОЛЧА. Дешёвая половина — проверять алиас-ключ на СОБСТВЕННУЮ канонную форму (день); дорогая (детектор значения по исходнику) — ряд **286**, загейчен замером. ⚠ Класс объявлен в дереве с 06.09 (`experiments/23-editor-tier.md` §Д50.3) — новизна нулевая, ряд заводится как НОСИТЕЛЬ, которого у него не было ⛔ **ИСПР. 11.09 ПО СЛОВУ ВЛАДЕЛЬЦА — РЯД БЫЛ НАПИСАН ПО НЕСУЩЕСТВУЮЩЕЙ ОСИ.** Слово: «нет такого понятия [подписанный термин], подписан либо ВЕСЬ банк, либо он в неконсистентном состоянии; есть вариант поставить галочку скипать подпись с фронта — тогда автоподписывание». Это ратифицировано `D39.144`: подписывается банк ЦЕЛИКОМ, пер-термная подпись прямо названа НЕ моделью продукта, дефолт движка — авто-продолжение с неподписанным банком, строки едут С ПОМЕТКОЙ. ⇒ **настоящий дефект глубже, чем «прибор не видит дрейфа»: в коде живёт пер-термный автомат `auto|draft|approved` (`backend/internal/store/migrate.go:192`), и пост-проверка считает нарушением ТОЛЬКО `approved` — то есть принимает решение по ЕДИНИЦЕ, КОТОРОЙ В ПРОДУКТОВОЙ МОДЕЛИ НЕТ.** Это и есть причина нуля при 18 найденных (строка **419**): сломана не поверхность, а ОСЬ решения. Закон `D39.104` на проводе один для всех строк; состояние книги — «подписана целиком» либо «авто-продолжение», и мерить надо им. | бэкенд | скоро | вопрос пост-проверки + видимость подавления вложенного ряда | аудит банка 11.09, находка `K3` (единственная пережившая верификацию) | | 408 | **ДАННЫЕ БАНКА НЕ ДОСЕЯНЫ, И ИМЕННО ИЗ-ЗА ЭТОГО ГЕЙТ КОНСИСТЕНТНОСТИ НЕЛЬЗЯ ВКЛЮЧИТЬ.** ⛔ **ЧИСЛО ИСПР. 11.09 — ПРЕЖНЕЕ БЫЛО ДО-СТЕММЕРНОЙ БАЗОЙ, а ряд гейтил им решение владельца.** Пере-снято мною прогоном пинов размеченного корпуса (`TM_CHECKER_LABELS=1 go test ./internal/membank/ -run TestK6 -v`): **база (`metrics.json`, до стеммера и до #10) — tp=1 fp=14 ⇒ 0.0667**, и это то, что здесь стояло; **ОТГРУЗОЧНЫЙ путь СЕГОДНЯ — tp=1 fp=6 tn=251 ⇒ 0.1429**; со стеммизацией `decl`-форм — **fp=0 ⇒ 1.0000**. ⚠ И концентрация названа неверно: класса `转` на отгрузочном пути НЕТ ВОВСЕ (его снял стеммер), остаточные шесть — это `元石` ×2 и `蛊虫` ×4, то есть **ровно склонительный разрыв, лечащийся досевом форм**. ⇒ направление ряда верно, величина отставала на два улучшения, а список ложных описывал уже не тот прибор. ⭐ **И это прямо смыкает ряд с 423:** стеммизация `decl`-форм уводит точность в 1.0000, а `decl`-форм нет ни в одной машинной выгрузке — то есть «досеять данные» и есть лечение, но на дорожке продукта досевать некому. Три дыры, все в ДАННЫХ, не в Go: (а) глагольные и многословные термины засеяны с пустыми формами — один `炼化` дал 7 ложных промахов (⚠ **испр. 11.09: это число из ДРУГОГО замера** — `docs/experiments/23-editor-tier.md:7630`=`Все семь «промахов»`, не из `labels/metrics.json`; в размеченном корпусе `炼化` нет вовсе, и обе величины верны порознь, но ссылка была одна на две); (б) односимвольный ханьский ключ структурно вне автомата без `allow_short` (порог 2 знака, `membank/memory.go:72`=`minKeyLenHan = 2`), а это самый частый класс канона в китайском ранобэ (蛊, 道, 气); (в) сид-линт об этом молчит. ⚠ Владелец 05.09 отложил гейт до замера ложных срабатываний («если он ложно положительно будет стрелять — это плохо, очень плохо») — вот их источник, и он лечится досевом, а не кодом ⚠ **11.09: это один из ТРЁХ инстансов общего класса — ряд 423** (майнер эмитит только своё поле; на немайненном корпусе меры вырождаются). | бэкенд+полигон | **скоро** | досев форм · `allow_short` у односимвольных · линт сида, который об этом кричит | аудит банка 11.09, `research/34` §2.3 | -| 409 | **РЕДАКТОР — ИСТОЧНИК РАЗНОБОЯ, А НЕ СТРАХОВКА ПОВЕРХ БАНКА, и это замерено дважды.** Без закон-блока редактор ломает 5–12 из 20 уже ВЕРНЫХ клеток черновика (`experiments/18-editor-wire-probe.md` §A.1); с подключённым банком боевой редактор держит ХУДШЕЕ покрытие канона в панели — 0.882 против 0.909 у черновика, который он правит (`experiments/22` §6.2, 1124 упоминания). Два механических носителя: черновая волна выбирает по БАЗОВОМУ банку с исключением намайненного (`bankmaterialize.go:329`) ⇒ на первом прогоне книги черновик идёт вообще без добытого банка; редакторская волна, единственная с полным банком, теряет липкость МЕЖДУ правочными единицами внутри главы (`waverun.go:717`) при **86 % многоединичных глав (1962 из 2283)**. ⇒ закон-блок обязан стать инвариантом конфига, а не следствием выбора модели редактора. ⚠ Инцидентов дрейфа от потери липкости — НОЛЬ наблюдений, замерена только экспозиция: правка без замера была бы стрельбой вслепую, замер снимается прогоном A | бэкенд | скоро | закон-блок инвариантом конфига + решение по липкости между правочными единицами | аудит банка 11.09, `research/34` §2.4 | +| 409 | **РЕДАКТОР — ИСТОЧНИК РАЗНОБОЯ, А НЕ СТРАХОВКА ПОВЕРХ БАНКА, и это замерено дважды.** Без закон-блока редактор ломает 5–12 из 20 уже ВЕРНЫХ клеток черновика (`experiments/18-editor-wire-probe.md` §A.1); с подключённым банком боевой редактор держит ХУДШЕЕ покрытие канона в панели — 0.882 против 0.909 у черновика, который он правит (`experiments/22` §6.2, 1124 упоминания). Два механических носителя: черновая волна выбирает по БАЗОВОМУ банку с исключением намайненного (`bankmaterialize.go:329`) ⇒ на первом прогоне книги черновик идёт вообще без добытого банка; редакторская волна, единственная с полным банком, теряет липкость МЕЖДУ правочными единицами внутри главы (`waverun.go:717`) при **86 % многоединичных глав (1962 из 2283)**. ⇒ закон-блок обязан стать инвариантом конфига, а не следствием выбора модели редактора. ⚠ Инцидентов дрейфа от потери липкости — НОЛЬ наблюдений, замерена только экспозиция: правка без замера была бы стрельбой вслепую. ⛔ **ИСПР. 11.09: «замер снимается прогоном A» назначал работу ЗАКРЫТОМУ прогону.** Прогон A принят актом `D39.247`, зона полигона выведена из скоупа целиком (`D39.248` п.4) — ждать этого замера больше не от кого. **Что прогон A реально дал по предмету — ЭКСПОЗИЦИЯ на живой книге и совпадение при N=1:** манифест дал `docs/experiments/24-door-to-file.md:807`=`units_total 2 / chunks 2` у главы 1 при `units_total 1 / chunks 2` у глав 2 и 3, то есть **одна многоединичная глава из трёх**, и единственный термин книги, отданный ДВУМЯ формами (`开窍大典`), стоит обеими формами в ТОЙ ЖЕ главе 1 (`docs/experiments/24-door-to-file.md:329`=`ДВЕ формы, и обе в одной главе`). ⚠ **Это наблюдение, а не доказательство:** атрибуция в отчёте доведена до ГЛАВЫ, а не до правочной ЕДИНИЦЫ — переход разнобоя ЧЕРЕЗ границу единицы не показан, и N=1. ⇒ по-юнитный замер дрейфа несёт БЭКЕНД на боевой книге, а решение по липкости принимается ПО ЕГО ИТОГУ: закрытие прогона A убрало исполнителя, а не требование | бэкенд | скоро | закон-блок инвариантом конфига + по-юнитный замер дрейфа на боевой книге и решение по липкости между правочными единицами по его итогу (прогона A ждать нечего — `D39.247`) | аудит банка 11.09, `research/34` §2.4 | | 410 | ⚠ **ПЕРЕПИСАН 11.09 — ПРЕЖНЯЯ ГОЛОВА БЫЛА НЕВЕРНА. Голос НЕ «мёртв в четырёх местах»: он ПОСТРОЕН СКВОЗЬ И ВЫКЛЮЧЕН ДВУМЯ ТУМБЛЕРАМИ.** Пере-снято мною прибором 11.09. **Построено:** схема сида несёт голос (`internal/seed/seed.go:25`=`Voices []Voice`, `Voices []Voice \`yaml:"voices"\``) · загрузчик секции есть (`membank/memvoice.go:79`=`func loadVoiceSections` `loadVoiceSections`, профиль собирается на `:121`) · хранилище есть (`store.VoiceProfilesForBook`, порядок пинован `bankmaterialize.go:214`) · инъекция в банк построена и УСЛОВНА (`membank/memory.go:511`=`if !in.InjectVoice` по `BankInput.InjectVoice`) · флаггер судит ОТГРУЖЕННЫЙ текст (`pipeline/voicerun.go:42`=`runVoiceChecks runs the voice flagger`) и печатает число в отчёт качества (`pipeline/quality.go:126`=`VoiceFlags int` `voice_flags`) · у гейта есть ручка и потребитель в Go (`quality.go:492`, `voicerun.go:46` по `Gates.Voice.Enabled`). **Выключено ровно двумя вещами.** ⛔ **(1) ДАННЫХ НЕТ НИ ОДНОЙ СТРОКИ, и знаменатель прежней записи был не тот.** Пере-снято: секция `voices:` встречается в **22** файлах дерева, и все 22 ПУСТЫ (не «21 из 22») — но все 22 суть МАШИННЫЕ выгрузки (`*.mined-signature.yaml`, `*.auto-bank.yaml`), то есть их пустота лишь пересказывает «майнер профили не эмитит» и самостоятельной уликой не является. Настоящий знаменатель — **22 рукописных сида с `terms:`, и ключа `voices:` нет НИ В ОДНОМ** (контроль: прибор прочёл 47 файлов с `terms:`, из них 25 машинных отброшены по имени). ⇒ за всю историю проекта профиль голоса не написал никто. **(2) `InjectVoice` — константа `false` без ключа конфига**, и комментарий `pipeline/bankmaterialize.go:295`=`InjectVoice is FALSE and has no config knob` называет и причину (`D21` п.2 держит инъекцию до полигонного замера), и ЦЕНУ включения: «Wiring the injection means setting it and accepting a full --resnapshot». Третьим, помельче: `gates.voice` не выставлен ни в одном из четырёх живых конфигов (контроль: соседние ключи `banknote`, `terminology`, `coverage`, `sanitizer`, `regression_guard` выставлены — прибор спрошен у существующего предмета). ⭐ **ВОПРОС ВЛАДЕЛЬЦУ СНЯТ ЕГО ЖЕ СЛОВОМ 11.09: «Входит»** — голос входит в приоритет №1 наравне с терминами; **проектирует и контролирует голос старший коллега (Fable 5), исполняет опус**, и пак обязан велеть сессии обсудить имплементацию с ним. Второй вопрос связки («если не подпись профилей, то кто») тоже снят: `D39.144` — подписывается банк ЦЕЛИКОМ, пер-профильной подписи в модели продукта нет. ⇒ **строка из вопроса стала ЗАДАЧЕЙ, и она мельче, чем читалась: не «построить голос», а написать профиль, открыть ручку и заплатить ре-снапшотом.** ⚠ Числа у механизма по-прежнему нет ни одного — первый замер обязан идти ПЕРЕД включением | бэкенд/владелец | **скоро** | профиль в сид · ключ конфига вместо константы · замер флаггером по отгруженному тексту; форму проектирует Fable 5 | аудит банка 11.09 (`research/34` §2.5, §4 п.2); голова ИСПР. 11.09 пере-замером оркестратора, слово владельца 11.09 | | 411 | ⛔ **КНИГУ, КОТОРУЮ ПАЙПЛАЙН ПЕРЕВОДИТ БЕСПЛАТНО, ПЛАТФОРМА ПРОДАТЬ НЕ МОЖЕТ — и это закрывает деплой на локальном инференсе целиком.** Замерено исполнением на стенде 11.09 (фаза 0 холодного прогона A): на $0-паре `step_max_usd` выходит 0, `ingest.Manifest.priced()` отказывает при `StepMaxUSD <= 0`, старт получает **`409 not_priced`**, в логе ERROR «this book has no price projection, so it cannot be sold». ⇒ **ни одна книга не продаётся, если её перевод ничего не стоит.** Для полигона это обходится номинальной ценой локальной модели отдельным файлом моделей (объявленная девиация), но для ПРОДУКТА это утверждение о рынке: развёртывание на своём железе — а именно им продаётся приватность и дешевизна — сегодня не может принять ни одного заказа. ⚠ Класс ошибки — «ноль цены прочитан как отсутствие цены»: предикат отвечает на свой вопрос («есть ли смета»), а спрошено другое («стоит ли это денег»). Лечение — решение о том, чем платформа меряет продаваемость, а не правка предиката | платформа | скоро | различение «цена ноль» и «сметы нет»; слово о деплое на локальном инференсе | фаза 0 прогона A, 11.09 | | 412 | **ШАБЛОН КНИГИ ИЗ РЕЦЕПТА СТЕНДА РОНЯЕТ КАЖДЫЙ СТАРТ БОЕВОГО КОНФИГА — молча для доков, громко для прогона.** Замерено 11.09: без ключа `langpack_root` движок отказывает на старте с **exit 10** и текстом «gates.terminology is enabled but this book cannot mine a bank: it needs a langpack». Ключа нет ни в `backend/example/book.yaml`, ни в рецепте `platform/docs/STACK_DECISIONS.md` §«Стенд разработчика», ни в рантбуке. ⇒ любой, кто соберёт книгу по нашему же рецепту и включит `c1`, получит отказ на старте — $0 по деньгам, но на ПЛАТНОЙ книге это потерянная «холодность» эксперимента, а на боевой выкатке — невозможность стартовать. Родня строки **251** (артефакт контраста): оба требования боевого банкового контура живут в коде и не доехали до носителей, по которым разворачивают | бэкенд+платформа | скоро | ключ в примере книги и в рецепте стенда; проверка полноты шаблона на буте | фаза 0 прогона A, 11.09 | -| 413 | ⛔⛔ **ЧИТАТЕЛЬ ПЛАТИТ ПО НАШЕМУ ПИНУ, А ПИН FLASH ПРОТУХ НА 13 % — и рядом НЕ РАЗРЕШЁННЫЙ вопрос, та ли это вообще модель.** Замерено полигоном на живом платном прогоне 11.09 и пере-проверено вендор-докой дважды (`api-docs.deepseek.com/quick_start/pricing`, гардрейл «идём в официальную доку, не гадаем»): наш пин `backend/configs/models.yaml:218`=`ПИК с 16.08.2026 16:00 UTC` держит flash `$0.44 in / $1.32 out / cache-hit $0.014` от **16.08.2026**, вендорская таблица сегодня даёт **`0.30 / 1.20 / 0.006`**; у `pro` пин совпадает ТОЧНО. Арифметика движка безупречна — по нашему пину прогон сходится до нуля микро-долларов, — но по вендорским числам тот же прогон стоил бы **$0.397246 против $0.419424**, то есть **пин завышает на $0.022177 = 5.6 % книги, ×1.133 по flash**. ⇒ мы выставляем читателю СВОЁ число, и оно выше провайдерского. ⛔ **Половина, без которой цену править НЕЛЬЗЯ:** `model_requested` = `deepseek-v4-flash`, а `model_actual` = **`deepseek-flash`** на 28 строках из 33, и слага `deepseek-flash` в нашем `models.yaml` НЕТ — вендорская прайс-таблица называет модель именно так. По правилу «слаг живой ≠ модель та же» замерено, что имена разные; НЕ установлено, алиас это или другая модель. Сперва identity, потом цена. ⛔ **ДОПОЛНЕНО 11.09 ПЕРЕ-ЗАМЕРОМ ОРКЕСТРАТОРА — под рядом лежит ВТОРАЯ беда, и она про МОЛЧАНИЕ, а не про число.** Замер по всем базам машины ⚠ (контроль ИСПР. 11.09 после пере-замера через `find`: файлов `*.db` **448**, с таблицей `request_log` **405**, прочитано **58 886** строк — первый счёт был занижен `glob`-ом): ⛔ **ЧИСЛА ИСПР. 11.09 — ПРЕЖНИЕ БЫЛИ ЗАВЫШЕНЫ В 10.88 РАЗА МОЕЙ ЖЕ ЛОВУШКОЙ (ряд 428): я опубликовал свод обходом диска, не применив к нему собственную норму.** Контроль честный: баз открыто **449**, строк-экземпляров прочитано **58 886**, **УНИКАЛЬНЫХ строк 5 413** (дедуп по идентичности строки, а не по файлу). После дедупа подстановкой оплачено **70 строк**: боевых **65** — `deepseek-v4-flash` → `deepseek-flash` **28 строк, $0.188953** и `local-qwen3-8b` → `huihui_ai/qwen3-abliterated:8b` **37 строк, $0**; фикстур **5** на **$0.424277** (`m-req`→`m-act` 1, `fake-model` 4). ⚠ Прежние «365 · 344 · 21 · $2.049737 · вычесть $5.51» — все одиннадцатикратные, ни одно за результат не принимать — провайдер вернул слаг, которого в каталоге нет, — `deepseek-v4-flash` → `deepseek-flash` (296 строк, $2.049737) и `local-qwen3-8b` → `huihui_ai/qwen3-abliterated:8b` (48 строк, $0). **Сегодня это безвредно:** подстановка падает на ЗАПРОШЕННУЮ модель той же семьи, и пин верен по семье. ⛔ Опасна не подстановка, а то, что о ней **никто не узнаёт**: `PriceForResponse` (`backend/internal/ledger/pricing.go:61`=`func (p *Pricer) PriceForResponse`) пробует `actual`, потом `requested`, потом якорь, и ни одно из ТРЁХ мест вызова не различает, какая ветвь сработала. Комментарий там же охраняет РОВНО ОДНО направление («премиальный ответ не должен биться по дешёвому дефолту»); обратное — когда провайдер маршрутизирует ВНИЗ — не охраняет никто: запрошен `pro`, ответила модель дешевле, счёт идёт по пину `pro`, $3.96 за 1M выходных против $1.20 вендорских у flash = **×3.3 из кармана читателя, молча**. ⇒ лечение двухчастное: завести слаг, который провайдер РЕАЛЬНО возвращает, и сделать срабатывание подстановки ВИДИМЫМ. Носитель работы — пак «падение, которое видно» §4.5 | бэкенд+полигон | **скоро** | вендор-сверка identity слага, затем пере-пин с датой и способом в формулировке; отдельно — наблюдаемость подстановки | критик чисел прогона A, 11.09; подстановка — пере-замер оркестратора 11.09 | +| 413 | ⛔⛔ **ЧИТАТЕЛЬ ПЛАТИТ ПО НАШЕМУ ПИНУ, А ПИН FLASH ПРОТУХ НА 13 % — и рядом НЕ РАЗРЕШЁННЫЙ вопрос, та ли это вообще модель.** Замерено полигоном на живом платном прогоне 11.09 и пере-проверено вендор-докой дважды (`api-docs.deepseek.com/quick_start/pricing`, гардрейл «идём в официальную доку, не гадаем»): наш пин `backend/configs/models.yaml:218`=`ПИК с 16.08.2026 16:00 UTC` держит flash `$0.44 in / $1.32 out / cache-hit $0.014` от **16.08.2026**, вендорская таблица сегодня даёт **`0.30 / 1.20 / 0.006`**; у `pro` пин совпадает ТОЧНО. Арифметика движка безупречна — по нашему пину прогон сходится до нуля микро-долларов, — но по вендорским числам тот же прогон стоил бы **$0.397246 против $0.419424**, то есть **пин завышает на $0.022177 = 5.6 % книги, ×1.133 по flash**. ⇒ мы выставляем читателю СВОЁ число, и оно выше провайдерского. ⛔ **Половина, без которой цену править НЕЛЬЗЯ:** `model_requested` = `deepseek-v4-flash`, а `model_actual` = **`deepseek-flash`** на 28 строках из 33, и слага `deepseek-flash` в нашем `models.yaml` НЕТ — вендорская прайс-таблица называет модель именно так. По правилу «слаг живой ≠ модель та же» замерено, что имена разные; НЕ установлено, алиас это или другая модель. Сперва identity, потом цена. ⛔ **ДОПОЛНЕНО 11.09 ПЕРЕ-ЗАМЕРОМ ОРКЕСТРАТОРА — под рядом лежит ВТОРАЯ беда, и она про МОЛЧАНИЕ, а не про число.** Замер по всем базам машины ⚠ (контроль ИСПР. 11.09 после пере-замера через `find`: файлов `*.db` **448**, с таблицей `request_log` **405**, прочитано **58 886** строк — первый счёт был занижен `glob`-ом): ⛔ **ЧИСЛА ИСПР. 11.09 — ПРЕЖНИЕ БЫЛИ ЗАВЫШЕНЫ В 10.88 РАЗА МОЕЙ ЖЕ ЛОВУШКОЙ (ряд 428): я опубликовал свод обходом диска, не применив к нему собственную норму.** Контроль честный: баз открыто **449**, строк-экземпляров прочитано **58 886**, **УНИКАЛЬНЫХ строк 5 413** (дедуп по идентичности строки, а не по файлу). После дедупа подстановкой оплачено **70 строк**: боевых **65** — `deepseek-v4-flash` → `deepseek-flash` **28 строк, $0.188953** и `local-qwen3-8b` → `huihui_ai/qwen3-abliterated:8b` **37 строк, $0**; фикстур **5** на **$0.424277** (`m-req`→`m-act` 1, `fake-model` 4). ⚠ Прежние «365 · 344 · 21 · $2.049737 · вычесть $5.51» — все одиннадцатикратные, ни одно за результат не принимать — провайдер вернул слаг, которого в каталоге нет, — `deepseek-v4-flash` → `deepseek-flash` (296 строк, $2.049737) и `local-qwen3-8b` → `huihui_ai/qwen3-abliterated:8b` (48 строк, $0). **Сегодня это безвредно:** подстановка падает на ЗАПРОШЕННУЮ модель той же семьи, и пин верен по семье. ⛔ Опасна не подстановка, а то, что о ней **никто не узнаёт**: `PriceForResponse` (`backend/internal/ledger/pricing.go:61`=`func (p *Pricer) PriceForResponse`) пробует `actual`, потом `requested`, потом якорь, и ни одно из ТРЁХ мест вызова не различает, какая ветвь сработала. Комментарий там же охраняет РОВНО ОДНО направление («премиальный ответ не должен биться по дешёвому дефолту»); обратное — когда провайдер маршрутизирует ВНИЗ — не охраняет никто: запрошен `pro`, ответила модель дешевле, счёт идёт по пину `pro`, $3.96 за 1M выходных против $1.20 вендорских у flash = **×3.3 из кармана читателя, молча**. ⇒ лечение двухчастное: завести слаг, который провайдер РЕАЛЬНО возвращает, и сделать срабатывание подстановки ВИДИМЫМ. Носитель работы — пак «падение, которое видно» §4.5. ⚠ **Адресат ИСПР. 11.09: полигон выведен из скоупа, и `D39.248` п.4 называет ЭТОТ ряд работой ДРУГИХ зон поимённо** — обе половины движковые: слаг живёт в `backend/configs/models.yaml`, видимость подстановки — в `backend/internal/ledger/pricing.go` | бэкенд | **скоро** | вендор-сверка identity слага, затем пере-пин с датой и способом в формулировке; отдельно — наблюдаемость подстановки | критик чисел прогона A, 11.09; подстановка — пере-замер оркестратора 11.09 | | 414 | **ПРИЗНАК ОТКАЗА НЕ ЖИВЁТ В `err`: прогон, где четверть денег купила пустоту, читается через эту колонку как идеально чистый.** Замер 11.09 на живом прогоне: `err` пуст на ВСЕХ 33 строках `request_log`, включая четыре провальные (контроль: строк с `err <> ''` — 0). ⚠ **ИСПР. 11.09 — «единственный носитель» НЕВЕРНО, их ТРИ, и они сходятся точно.** Пере-снято мною по базе прогона (`bk_ROEHZBD46ALFI43E/project.db`, 33 строки): `ok = 0` ровно на четырёх провальных и `1` на остальных 29 · `finish_reason = 'length'` на тех же четырёх · `degraded` (`empty` ×3, `length` ×1). Каждый из трёх, просуммированный по деньгам, даёт **ровно $0.106472** — то есть провал виден тремя независимыми колонками, и `ok` из них самая очевидная. Верна ровно половина прежнего утверждения: пуст именно `err`. ⇒ любой аудит денег или отказов, написанный через `err` — а это первое, к чему потянется рука, — не увидит 25.4 % траты. Родня ряда **376**: там оплаченный обрыв не виден в оценочной паре, здесь провал не виден в колонке ошибок | бэкенд | скоро | отказ обязан быть видим тем же прибором, которым смотрят деньги | критик чисел прогона A, 11.09 | | 415 | ⛔ **ЧЕТВЕРТЬ ДЕНЕГ КНИГИ КУПИЛА ПУСТОТУ, И ПОДНЯТЫЙ ФЛОР ЭТОГО НЕ СНЯЛ — доля БОЛЬШЕ, чем у инцидента, ради которого флор поднимали.** Замер 11.09: 4 вызова из 27 вернулись без пригодного текста и стоили **$0.106472 = 25.4 %** книги; три из них вернули РОВНО 0 знаков ($0.094835 = 22.6 %), четвёртый — выброшенный обрезок. Самый дорогой одиночный вызов прогона ($0.071009, `edit`/`deepseek-v4-pro`) не дал НИЧЕГО. ⚠ Мина задокументирована (размышление съедает `max_tokens`), боевой `pipeline-c1.yaml` ставит на draft `reasoning: "low"` именно против неё — **сработала всё равно: трижды на draft и один раз на edit, где ручка не выставлена вовсе**; а `min_max_tokens: 16000` у `pro` поднят с 8000 ПОСЛЕ прошлого такого инцидента, чья цена записана рядом в комментарии как 15.5 % счёта — здесь один вызов НА ПОДНЯТОМ флоре сжёг 16 000 токенов и вернул ноль, **16.9 % счёта**. ⭐ Лечение в движке ЕСТЬ и сработало 4 раза из 4 (перевыпуск с удвоенным потолком вернул текст) — путь не рвётся, он ДОРОЖАЕТ вдвое. Вторая точка того же явления: на прогоне 08.09 было 32 % | бэкенд | **скоро** | ручка против мины на ВСЕХ платных стадиях + решение, платит ли читатель за выброшенную попытку | критик чисел прогона A, 11.09 | | 416 | **СОГЛАСИЕ НА ПЕРЕ-ОПЛАТУ, ВЫСТАВЛЕННОЕ НА ВЕСЬ БЮДЖЕТ, ПРИ ФАКТИЧЕСКОЙ ПЕРЕ-ПОКУПКЕ В 78 РАЗ МЕНЬШЕ.** Замер 11.09: на резюме после банк-стопа `runs.accept_rebill_micro = 2 241 631` — то есть согласие пере-оплатить ВЕСЬ бюджет прогона, — тогда как фактически пере-куплено $0.028742. Разрыв **78×**; от пере-покупки спасли чекпойнты, а не потолок согласия. ⇒ промахнись хэши промптов (смена провода, `memory_version`, снапшота), и черновая волна была бы куплена заново — с уже стоящим согласием читателя. Родня `D39.196` п.2а (переплата читателя запрещена): здесь запрет не нарушен, но и не охраняем ничем, кроме везения | платформа+бэкенд | скоро | согласие соразмерное тому, что реально может быть пере-куплено | критик чисел прогона A, 11.09 | @@ -342,7 +342,7 @@ | 420 | ⛔ **`unit_done` ВСТАВЛЕННОЙ ГЛАВЫ НЕ ОБЪЯВЛЯЕТСЯ ВОВСЕ — тихая потеря доставки за швом.** Найдено дизайн-паком перекроя 11.09 при инвентаре чужой стороны: ключ объявления несёт ОРДИНАЛ (`backend/internal/pipeline/events.go`, греп `once_key`), отказ молчалив (греп `outbox`), а `deliveredUnits` считает юнит доставленным. ⇒ при вставке главы читатель не получает объявления о доставке, и никто этого не замечает. **Это не перепокупка, а потеря СОБЫТИЯ**; чинится в движке. ⚠ Единственная настоящая потеря за швом из всего, что дизайн проверил: остальные четыре его подозрения оказались «уже построено» на стороне платформы | бэкенд | скоро | объявление доставки, переживающее вставку главы | дизайн-пак перекроя, 11.09 | | 421 | **ЗАМЕР, РАДИ КОТОРОГО ШЕСТОЙ ВОПРОС СНЯТ С ВЛАДЕЛЬЦА: сколько банк-батчей на боевой книге двигает ТОЛЬКО окно.** Дизайн-пак завёл вопрос о проводе банк-ролей и САМ его снял с владельца доводом «цена меняла знак ТРИЖДЫ — 11 % всегда → ноль → интервал от нуля до всего прохода; число, трижды менявшее знак, владельцу отдавать нельзя». Постановка готова: считать на боевой книге долю батчей, у которых меняется только окно `since_ch`/`until_ch`, и тем закрыть интервал. ⚠ **Ряд заведён 11.09 по находке аудита: и дизайн, и акт `D39.245` объявляли замер «ушедшим в бэклог», а в бэклоге его НЕ БЫЛО** — классический случай «заведено» со слов, без грепа по живому трекеру | бэкенд/полигон | когда-нибудь | доля батчей, двигающих только окно, числом на боевой книге | дизайн-пак перекроя 11.09, заведён аудитом смены | | 422 | ⛔ **КОЛОНКА, КОТОРОЙ СПРАШИВАЮТ «СКОЛЬКО СЪЕЛО ДУМАНЬЕ», НЕ НЕСЛА ЧИСЛА НИ РАЗУ ЗА ВСЮ ИСТОРИЮ ПРОЕКТА.** Замер 11.09 оркестратором: `request_log.reasoning_tokens > 0` — **0 строк**; контроль рядом, доказывающий, что вопрос задан существующему предмету: ⚠ **контроль ИСПР. 11.09 — мой первый счёт был занижен: `glob` пропустил ~170 баз, пере-снято через `find`** — файлов `*.db` найдено **449**, прочитано **58 886** строк-экземпляров, **УНИКАЛЬНЫХ строк 5 413** (⛔ испр. 11.09: прежний знаменатель сам был умножен копиями в 10.88 раза — ряд **428**; ноль устоял и на честном знаменателе). Колонка объявлена схемой (`backend/internal/store/migrate.go`, блок `CREATE TABLE request_log`) и присутствует во всех. ⇒ **единственная колонка, которой можно доказать «потолок съело рассуждение», структурно молчит**, и её ноль неотличим от «думанья не было». Прямо это и есть слепота в вопросе владельца «мы ждали 249 секунд и заплатили за ничего»: у DeepSeek рассуждение считается ВНУТРИ `completion_tokens` и отдельным полем не приходит, поэтому на провальных вызовах прогона A видно `completion_tokens` 8496 · 8496 · 8496 · 16000 при нуле знаков текста — то есть потолок выкуплен целиком, а чем — не сказано ничем. ⚠ Родня рядов **414** (признак отказа не в той колонке) и **415** (четверть денег за пустоту): все три — про то, что ОТКАЗ и его ПРИЧИНА не доезжают до прибора, которым смотрят деньги | бэкенд | **скоро** | поле, различающее «рассуждение съело потолок» и «рассуждения не было» — из тела ответа провайдера, а не из отсутствующего поля usage; либо явная пометка «провайдер не сообщает» | пере-замер оркестратора 11.09 по базе прогона A | -| 423 | ⛔⛔ **МАЙНЕР ЭМИТИТ ТОЛЬКО ТО ПОЛЕ, РАДИ КОТОРОГО ПОСТРОЕН, И КАЖДЫЙ МЕХАНИЗМ НИЖЕ ПО ТЕЧЕНИЮ, КОТОРОМУ НУЖНЫ ДАННЫЕ БОГАЧЕ, ТИХО ДЕГРАДИРУЕТ. Три открытых ряда оказались ОДНИМ классом.** Замер оркестратора 11.09 (контроль: прибор распарсил **47** yaml-файлов с непустым `terms:`): ненулевые `decl.forms` есть ТОЛЬКО в файлах, написанных человеком — `guzhenren-seed-v2.yaml` 42 терма из 58 · `guzhenren-seed.yaml` 35 из 49 · `rerun2` 41 из 57; **во ВСЕХ машинных выгрузках — ноль**: 0 из 142 · 0 из 102 (шесть раз) · 0 из 83 · 0 из 76 · 0 из 74 · 0 из 69 (банк платного прогона A) · 0 из 67 · 0 из 61 · 0 из 53. ⇒ **на книге без рукописного сида — то есть на нормальной дорожке продукта — пост-проверке нечем опереться, кроме глобального одношагового стеммера**, и это ровно тот механизм, который ряд **419** замерил как дающий 11 ложных тревог из 18. Три инстанса одного класса: `decl.forms` (`internal/seed/seed.go:87`=`type Decl struct`, потребитель `membank/memory.go:342`=`Parse decl forms for the post-check`) · профили голоса (ряд **410**: `voices:` пуст во ВСЕХ 22 машинных выгрузках и отсутствует во ВСЕХ 22 рукописных сидах) · формы глагольных и многословных термов (ряд **408**). ⭐ **Ценность ряда в том, что он снимает три отдельные «доработки данных» и ставит один вопрос: что банк обязан отдавать, кроме пары «исходник → передача», чтобы механизмы ниже работали не вырожденно.** ⚠ Это НЕ заказ «научить майнер всему»: часть полей модель предложить не может в принципе (склонение — да, голос — спорно), и разделение «что майнится · что сеется человеком · что вычисляется из языка» и есть предмет. ⛔ Пока ряд открыт, любой замер точности пост-проверки на РУКОПИСНОМ корпусе меряет исключение, а не правило — этим 11.09 ошибся оркестратор, решая порядок колонок прибора консистентности | бэкенд | **скоро** | разделение «майнится · сеется · выводится из языка» + носитель того, чего майнер не даёт | пере-замер оркестратора 11.09 по числу зоны `textmachine-c9` | +| 423 | ⛔⛔ **МАЙНЕР ЭМИТИТ ТОЛЬКО ТО ПОЛЕ, РАДИ КОТОРОГО ПОСТРОЕН, И КАЖДЫЙ МЕХАНИЗМ НИЖЕ ПО ТЕЧЕНИЮ, КОТОРОМУ НУЖНЫ ДАННЫЕ БОГАЧЕ, ТИХО ДЕГРАДИРУЕТ. Три открытых ряда оказались ОДНИМ классом.** Пере-замер 11.09 по `books/` (контроль: прибор распарсил **153** yaml-файла, сбоев разбора 0; непустой `terms:` у **34** файлов — 2471 терм; проходящий фильтр рядом с нулём: непустой `dst` несут **2419 из 2471** термов, то есть тела термов прибор читает): ненулевые `decl.forms` есть ТОЛЬКО там, где их писал человек, и носителей ШЕСТЬ, а не три — `guzhenren-seed-v2.yaml` 42 терма из 58 · `diag/guzhenren-seed-v2.pre-reseed.yaml` 41 из 57 · `exp15/guzhenren-seed-v2.pre-gender.yaml` 41 из 57 · `rerun2/guzhenren-seed-rerun2.yaml` 41 из 57 · `guzhenren-seed.yaml` 35 из 49 · `minirun/mined-delta.yaml` 2 из 2 (дельта mining-stop с подписью владельца — рукопись, несмотря на имя `mined-`); седьмой носитель лежит ВНЕ книг и к дорожке продукта отношения не имеет — golden-фикстура `backend/internal/pipeline/testdata/golden/glossary-seed.yaml` 4 из 5. **Во ВСЕХ 26 машинных файлах (2187 термов) — ноль, и это не разреженность, а отсутствующее поле**: 25 выгрузок `*.mined-signature.yaml`/`*.auto-bank.yaml` несут `decl: null` у ВСЕХ своих 2126 термов — 0 из 142 (два файла) · 0 из 102 (ЧЕТЫРНАДЦАТЬ файлов) · 0 из 83 · 0 из 76 · 0 из 74 · 0 из 69 (банк платного прогона A) · 0 из 53 (два файла) · 0 из 3 · 0 из 2 · 0 из 1; а сид-дельта `design11/ws3_seed_delta.yaml` (0 из 61) ключа `decl` не пишет ВООБЩЕ — её эмитит скрипт полигона `eval/design11/ws3_seeddelta.py`, и все 61 терма помечены им как `mined draft`/`mined WHICH-only auto-candidate`. Рукописных нулей два, и они ДРУГОЙ природы: `rerun2/mined-delta.yaml` 0 из 3 и `minirun-verify2/mined-delta.yaml` 0 из 1 — там `invariant: true, forms: []`, то есть поле заполнено осознанно. ⚠ Эррата к первой редакции ряда (числа не воспроизвелись, вывод устоял и усилился): «47» было числом файлов с КЛЮЧОМ `terms:` по ВСЕМУ репозиторию (35 непустых + 12 пустых `mined-delta.yaml`), а не с непустым `terms:`; «0 из 102 (шесть раз)» — на деле четырнадцать файлов; «0 из 67» носителя не имеет вовсе; носителей форм шесть, а не три. ⚠ Машинное от рукописного по ИМЕНИ файла не отличается — обманывает в обе стороны: `minirun/mined-delta.yaml` с машинным именем подписан владельцем, а `ws3_seed_delta.yaml` без машинного имени эмитирован скриптом; судить только содержимым. ⇒ **на книге без рукописного сида — то есть на нормальной дорожке продукта — пост-проверке нечем опереться, кроме глобального одношагового стеммера**, и это ровно тот механизм, который ряд **419** замерил как дающий 11 ложных тревог из 18. Три инстанса одного класса: `decl.forms` (`internal/seed/seed.go:87`=`type Decl struct`, потребитель `membank/memory.go:342`=`Parse decl forms for the post-check`) · профили голоса (ряд **410**: `voices:` пуст во ВСЕХ 22 машинных выгрузках и отсутствует во ВСЕХ 22 рукописных сидах) · формы глагольных и многословных термов (ряд **408**). ⭐ **Ценность ряда в том, что он снимает три отдельные «доработки данных» и ставит один вопрос: что банк обязан отдавать, кроме пары «исходник → передача», чтобы механизмы ниже работали не вырожденно.** ⚠ Это НЕ заказ «научить майнер всему»: часть полей модель предложить не может в принципе (склонение — да, голос — спорно), и разделение «что майнится · что сеется человеком · что вычисляется из языка» и есть предмет. ⛔ Пока ряд открыт, любой замер точности пост-проверки на РУКОПИСНОМ корпусе меряет исключение, а не правило — этим 11.09 ошибся оркестратор, решая порядок колонок прибора консистентности | бэкенд | **скоро** | разделение «майнится · сеется · выводится из языка» + носитель того, чего майнер не даёт | пере-замер оркестратора 11.09 по числу зоны `textmachine-c9` | | 424 | **ТРИНАДЦАТЬ РЯДОВ ТРЕКЕРА РЕНДЕРЯТСЯ С ЛИШНИМИ КОЛОНКАМИ — неэкранированный `\|` внутри ячейки, обычно в код-спане вида `auto\|draft\|approved`.** Замер 11.09 ТЕМ ЖЕ расщепителем, что у гейта (контроль: рядов прочитано **303**, целых **290**, сломанных **13**): 163 · 182 · 248 · 127 · 279 · 306 · 311 · 320 · 346 · 361 · 378 · 389 · 407. ⛔ **Первая редакция называла ЧЕТЫРНАДЦАТЬ и включала ряд 253 — это была ошибка ПРИБОРА, а не находка: я считал разделители наивно, а 253 их ЭКРАНИРУЕТ, и расщепитель гейта видит его целым.** Хуже: ошибка уехала В САМ ГЕЙТ — 253 попал в `SHAPE_GRANDFATHERED` и ослепил проверку на неcломанном ряде навсегда; снят 11.09. ⇒ **урок дороже ряда: контроль снимается ТЕМ ЖЕ прибором, которым судит гейт, иначе дедовщина консервирует не долг, а мой промах.** Лечение — `\|` в ячейке; работа механическая. ⭐ **Ряд заведён не ради косметики, а потому что гейт этого НЕ ВИДЕЛ, и слепота стоила инцидента:** проверка формы в `docs/scripts/counts.py` ловила только «колонок МЕНЬШЕ ожидаемого», а «больше» и «текст за последним разделителем» молчали — и ряд **406** прожил от создания до 11.09 с **1044 знаками текста ВНЕ таблицы**, при этом счётчики сходились (они читают ячейки с конца и попадали в нужные) и гейт был зелён. Проверка сделана симметричной тем же днём, эти 14 внесены в `SHAPE_GRANDFATHERED` по конвенции файла «гейт рождается зелёным на известном долге и краснеет на следующем»; три посадки на копии подтвердили, что обе новые половины краснеют ПО ТЕКСТУ, а дедовщина молчит. ⇒ закрытие ряда = экранировать 14 ячеек и вынести их из списка | оркестратор | когда-нибудь | экранирование `\|` в четырнадцати ячейках и пустой `SHAPE_GRANDFATHERED` | структурная проверка оркестратора 11.09 | | 425 | **ПРИБОР КОНСИСТЕНТНОСТИ СЛЕП ПО ПОСТРОЕНИЮ В ШЕСТИ МЕСТАХ, и ни одно не чинится матчером.** Названо зоной 11.09 на прямой вопрос «что ты знаешь и не сказала» — до вопроса была названа ОДНА. **(1)** передача, СОДЕРЖАЩАЯ форму банка целиком, и есть эта форма (`开窍大典`) — единственное расхождение с ручным оракулом, где прибор слеп структурно; **(2)** омонимы по `sense`: одно вхождение засчитывается КАЖДОМУ ряду с тем же ключом, и обе строки полисемичного терма покрытыми быть не могут (латентно: 69 различных `src` на 69 рядов); **(3)** ⛔ общеупотребительная передача вдали от своего термина маскирует настоящее отсутствие — `魔道` даёт `fired=1` при счёте 3; **сдвиг ОДНОСТОРОННИЙ, в сторону благополучия ⇒ `I2` есть НИЖНЯЯ граница, а не оценка**, и число уже печатается строкой «terms found MORE often than their key fired» (на прогоне A 9 и 7); **(4)** гранулярность — ЮНИТ, а не вхождение: «форма на месте срабатывания» требует выравнивания исходника с целью; **(5)** термин, которого в банке НЕТ, невидим вовсе — молчание неотличимо от успеха; **(6)** вторая форма НЕ НАЗЫВАЕТСЯ никогда: I1 ловится отсутствием банковской формы, а не узнаванием того, что стоит вместо неё. ⇒ **(1) и (6) закрываются ОДНИМ заказом — каналом `variants` в БД**; (3) закрыто числом рядом с `I2` | бэкенд | скоро | канал `variants` закрывает (1) и (6); прочее — объявленные свойства, пере-открывать замером | зона пака консистентности 11.09, секция «где прибор слеп и я это знаю» | | 426 | **ГРАНИЦЫ НОРМАЛИЗАЦИИ И РАВЕНСТВА — три, все с числом.** **(1)** граница АБЗАЦА не видна: `NormalizeTargetForm` сворачивает любой пробельный ряд в один пробел, поэтому разрыв абзаца без конечной пунктуации неотличим от пробела; граница ПРЕДЛОЖЕНИЯ закрыта и пинована, а видеть абзац значит завести ВТОРОЙ нормализатор, расходящийся с пост-проверкой. **(2)** строгая колонка не в точности равна `dstFormPresent` в ОБЕ стороны — слова против рун: пунктуация внутри формы (**23 расхождения на 30 000 троек**) и форма без букв; недостижимо на банке без `decl`-форм, то есть на ЛЮБОМ машинном (ряд **423**). **(3)** ⛔ **точность самого отношения `NearStems` ≈ 0.57** — 17 из 30 равномерной выборки принятых пар (`рода~родной`, `гор~горная`, `так~также` — разные леммы) ⇒ **работает не отношение, а ограждения** (якорь · многословное окно · границы предложения), и их эффективность замерена на ОДНОЙ книге; названный отказ — слово банковской передачи оказывается соседом ДРУГОГО слова в той же позиции окна, и колонка врёт в сторону сокрытия | бэкенд | скоро | (3) — вторая книга либо размеченные пары лемм; (1) и (2) — объявленные свойства | зона пака консистентности 11.09 | diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 18e88e90..0b1ec250 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -369,7 +369,7 @@ Моё число (13/16 против 10/16) поставило решение на проверку, оркестратор пере-снял своим прибором и отменил собственное. **Довод, который это решает, шире пака и его стоит запомнить:** -⛔ **Размеченный корпус, на котором решалось «якорь покупает ноль», собран на РУКОПИСНЫХ сидах — то есть у него по построению НЕТ болезни, которую якорь лечит.** Пере-замер оркестратора, контроль — 47 yaml с непустым `terms:`: рукописные сиды несут `decl` у **42 из 58** · 35 из 49 · 41 из 57; а **НИ ОДНА машинная выгрузка в дереве не несёт `decl` вообще** — 0 из 142 · 0 из 102 (шесть раз) · 0 из 83 · 0 из 76 · 0 из 74 · 0 из 69 · 0 из 67 · 0 из 61 · 0 из 53. ⇒ на боевой дорожке продукта — книга без рукописного сида, банк намайнен — **стеммеру стеммить НЕЧЕМ**, и якорное послабление остаётся единственным, что дотягивается до склонённой передачи. Вердикт на «безопасной» колонке там печатал бы дрейф, которого нет. +⛔ **Размеченный корпус, на котором решалось «якорь покупает ноль», собран на РУКОПИСНЫХ сидах — то есть у него по построению НЕТ болезни, которую якорь лечит.** Пере-замер оркестратора, контроль — 47 yaml с непустым `terms:`: рукописные сиды несут `decl` у **42 из 58** · 35 из 49 · 41 из 57; а **НИ ОДНА машинная выгрузка в дереве не несёт `decl` вообще** — 0 из 142 · 0 из 102 (шесть раз) · 0 из 83 · 0 из 76 · 0 из 74 · 0 из 69 · 0 из 67 · 0 из 61 · 0 из 53. ⚠ **Эррата оркестратора 11.09: числа этого контроля не воспроизвелись, вывод — воспроизвёлся и усилился.** «47» — это файлы с КЛЮЧОМ `terms:` по ВСЕМУ репозиторию (35 непустых + 12 пустых), а не с непустым `terms:`; в `books/` непустых **34** — 26 машинных файлов (2187 термов) и 8 рукописных (284); «0 из 102 (шесть раз)» — четырнадцать файлов; «0 из 67» носителя не имеет вовсе; «0 из 61» — сид-дельта `ws3_seed_delta.yaml`, тоже машинная (её эмитит скрипт полигона `eval/design11/ws3_seeddelta.py`); рукописных носителей форм шесть, а не три. Машинный ноль при этом сильнее заявленного: все 2126 термов 25 выгрузок несут `decl: null`, а сид-дельта ключа `decl` не пишет вовсе. Разбор и полный перечень — ряд **423** бэклога. ⇒ на боевой дорожке продукта — книга без рукописного сида, банк намайнен — **стеммеру стеммить НЕЧЕМ**, и якорное послабление остаётся единственным, что дотягивается до склонённой передачи. Вердикт на «безопасной» колонке там печатал бы дрейф, которого нет. ⇒ **Сделано: вердикт снова на якорной колонке, безопасная — вторая.** Это ровно то, что записка `target-ru.txt:231` и предлагала двумя лечениями («seed decl-form enumeration **or** an anchor-gated match»); первое на боевом пути недоступно. ⛔ **И МНОГОСЛОВНАЯ ОПАСНОСТЬ, которая теперь обязательна: ЗАКРЫТА ПРАВИЛОМ, а не оговоркой.** Раз вердикт стоит на этой колонке, «глава рода Гуюэ» ⊨ «глаза рода Гуюэ» — это ложное СОКРЫТИЕ, худшее направление. Лечение оказалось не порогом, а **смыслом самого отношения**: `Stem` УСЕКАЕТ, значит два стемма одного слова различаются лишь тем, сколько снято, и короткий обязан быть ПРЕФИКСОМ длинного. «глав»/«глаз» — это замена, а не усечение, и она отвергается. `NearStems` переписана на строгий префикс. diff --git a/docs/architecture/15-money-path.md b/docs/architecture/15-money-path.md index dc839278..f2a61ecf 100644 --- a/docs/architecture/15-money-path.md +++ b/docs/architecture/15-money-path.md @@ -1,6 +1,6 @@ # Путь денег — от гранта до settle (топикальный вход; строка 167 ЗАКРЫТА D39.200, файл живёт сам по себе) -> **Статус: топикальный ВХОД, НЕ источник истины.** Док собирает денежную тему, размазанную по D-нотам, реестру дефектов платформы, глоссарию и бэклогу, в один маршрут чтения. При конфликте с чем угодно побеждает `docs/architecture/05-decisions-log.md` (правило чтения — диета D39.125: живой файл + слайсы). Каждое утверждение здесь снабжено указателем на первичный носитель; формулы — дословно оттуда. Словарь терминов (холд · прирост · аргумент потолка · baseline · settle · leftover-reserved · SpendBound) — `docs/glossary.md` §«Деньги платформы» (`docs/glossary.md:55`=`**Деньги платформы:**`). +> **Статус: топикальный ВХОД, НЕ источник истины.** Док собирает денежную тему, размазанную по D-нотам, реестру дефектов платформы, глоссарию и бэклогу, в один маршрут чтения. При конфликте с чем угодно побеждает `docs/architecture/05-decisions-log.md` (правило чтения — диета D39.125: живой файл + слайсы). Каждое утверждение здесь снабжено указателем на первичный носитель; формулы — дословно оттуда. Словарь терминов (холд · прирост · аргумент потолка · baseline · settle · leftover-reserved · SpendBound) — `docs/glossary.md` §«Деньги платформы» (`docs/glossary.md:58`=`**Деньги платформы:**`). > > ⚠ **Форма указателей — норма этого дока (31.08, пере-проверены ВСЕ указатели: 34 уехали, 1 мёртв, 16 верны).** > **Стабильна не ЗОНА, а ЧИСТЫЙ ФАЙЛ.** Номер строки ставится только туда, где `git status <цель>` показывает файл чистым; файл с незакоммиченной правкой — чей угодно, включая `docs/` — получает греп-указатель без номера. Ось именно такая — ратифицировано **D39.179 п.4**, который уточняет D39.177 §2в и прямо объявляет зонную ось НЕВЕРНОЙ (там же: «Носитель нормы — шапка 15-money-path.md»), и зонная ось её НЕ заменяет: `docs/architecture/14-api-contract/openapi.yaml` ЛЕЖАЛ в «своей» зоне и при этом ДВИГАЛСЯ паком контракта 0.9.0 (заленджен 31.08, `0a680a3`, D39.180). @@ -44,7 +44,7 @@ 5. ⚠ **ИСПР. 06.09: формула ЖИВА дословно, сменился ИСТОЧНИК прироста.** `return m.committed + increment` стоит на месте (`platform/internal/runs/spawn.go`, греп `func (m meter) bookCap`), но `increment` приходит теперь из проекции движка, а не из «глав × ставку». Прежняя редакция историей: - **Аргумент движку: `bookCap = committed + прирост×ставка`, БЕЗ reserved — PD-158, дословно из кода: `return m.committed + increment`** (`platform/internal/runs/spawn.go`, греп `return m.committed + increment`). Обе фигуры читаются ОДНИМ вызовом `status --json` перед стартом (`bookMeter` — `platform/internal/runs/spawn.go`, греп `func (s *Service) bookMeter(`; отказы — греп `Absent is not zero`); отсутствие любой из них = отказ спавна («absent is not zero», PD-40). Почему без reserved: write-open движка занулит leftover до первой резервации, значит цифра из read-only status к моменту сравнения уже мертва; ратифицированная ранее формула с reserved переплачивала запасом ровно на leftover сверх холда — исполнено обеими формулами против гейта (D39.123 п.2б, поправка к D39.122(в)). Аргумент ≠ холд: он больше холда на committed (`docs/glossary.md:55`=`ЭТО НЕ ХОЛД — он больше холда`). Фактически ушедшее значение хранится в `run_attempts.ceiling_arg_micro_usd` (PD-144, миграция 00011); потолок уходит argv-шаблоном `{{usd}}` (шаблон — `platform/internal/config/config.go`, греп `CeilingArg`; подстановку делает `platform/internal/runner/engine.go`, греп `{{usd}}`; подстановку и рендер argv делает `platform/internal/runner/engine.go`, греп `func (t CeilingTemplate) Args(`; `platform/internal/runs/runs.go`, греп `func (s *Service) ceilingFor(` — однострочная делегация к нему; `spawn.go` потолок только передаёт); строка 145 закрыта D39.122. + **Аргумент движку: `bookCap = committed + прирост×ставка`, БЕЗ reserved — PD-158, дословно из кода: `return m.committed + increment`** (`platform/internal/runs/spawn.go`, греп `return m.committed + increment`). Обе фигуры читаются ОДНИМ вызовом `status --json` перед стартом (`bookMeter` — `platform/internal/runs/spawn.go`, греп `func (s *Service) bookMeter(`; отказы — греп `Absent is not zero`); отсутствие любой из них = отказ спавна («absent is not zero», PD-40). Почему без reserved: write-open движка занулит leftover до первой резервации, значит цифра из read-only status к моменту сравнения уже мертва; ратифицированная ранее формула с reserved переплачивала запасом ровно на leftover сверх холда — исполнено обеими формулами против гейта (D39.123 п.2б, поправка к D39.122(в)). Аргумент ≠ холд: он больше холда на committed (`docs/glossary.md:58`=`ЭТО НЕ ХОЛД — он больше холда`). Фактически ушедшее значение хранится в `run_attempts.ceiling_arg_micro_usd` (PD-144, миграция 00011); потолок уходит argv-шаблоном `{{usd}}` (шаблон — `platform/internal/config/config.go`, греп `CeilingArg`; подстановку делает `platform/internal/runner/engine.go`, греп `{{usd}}`; подстановку и рендер argv делает `platform/internal/runner/engine.go`, греп `func (t CeilingTemplate) Args(`; `platform/internal/runs/runs.go`, греп `func (s *Service) ceilingFor(` — однострочная делегация к нему; `spawn.go` потолок только передаёт); строка 145 закрыта D39.122. 6. **Baseline и списание.** `baseline = committed` книги на старте попытки (`platform/internal/runs/spawn.go`, греп `baseline, bookCap := m.committed`); списание попытки = разница счётчика с baseline; счётчик ниже baseline = подменённая БД, сеттлится в ноль с WARN — сами цифры в лог не идут (D39.84; `platform/internal/runs/reconcile.go`, греп `the book's meter reads below`). 7. ⚠ **Терминальный вердикт ОПЕРАТОРА — путь холда мимо settle (добавлено 22.08, P8-FIX/D39.154).** Прогон, чей движок не ответит уже никогда, закрывает человек: `tmplatformctl run abandon --run --reason <текст> [--release-hold]`. Команда ОТКАЗЫВАЕТ, если попытка ещё называет юнит или несёт базовую линию траты — над живым движком прогон не закрывают. Холд возвращается ЦЕЛИКОМ в обоих случаях (к abandon допускается только попытка, не дошедшая до движка, значит она ничего не потратила), а флаг решает лишь КОГДА — сразу или на ближайшем свипе. ⚠ **С пака P11 (`PD-385`) ВЕТВЕЙ ДВЕ, и абзац выше — только ЖИВАЯ** (испр. ревизией 02.09; образец — секция «Строка PHASE = settling» в `platform/deploy/README.md`). У прогона, чья попытка уже КОНЧИЛАСЬ, команда идёт второй ветвью: отказ «юнит/базовая линия» к ней НЕ применяется, к abandon допускается попытка, которая ДОШЛА до движка и ПОТРАТИЛА, холд всё равно возвращается ЦЕЛИКОМ по каждой осиротевшей попытке, а флаг `--release-hold` там ИГНОРИРУЕТСЯ; единственная защита — порог `abandonAfter` неудач расчёта (отказ `ErrSettlementNotStuck`). ⚠ **Ветвление идёт по `runs.finished_at`, а НЕ по наличию осиротевшей попытки** — ратифицированная оговорка `PD-418`. ⚠ **И вторая ветвь НЕ лечит живую:** прогон с намертво заблокированной расплатой уходит в ЖИВУЮ ветвь и закрыт отказом по юниту до сих пор — `PD-424` стоит `open` именно на этой половине. @@ -69,7 +69,7 @@ | Вопрос | Где живёт | |---|---| -| Словарь терминов | `docs/glossary.md:55`=`**Деньги платформы:**` | +| Словарь терминов | `docs/glossary.md:58`=`**Деньги платформы:**` | | Управляемый потолок: решение и форма | D39.110 (+поправка D39.112 п.3: п.1 — пересказ, не цитата) | | Максимум шкалы = Balance как есть | D39.115 п.2а; эррата — шапка D-лога, `docs/architecture/05-decisions-log.md:4`=`Balance КАК ЕСТЬ` | | Семантика `--ceiling-usd` | D39.122 п.2в; `backend/cmd/tmctl/invocation.go:142`=`the book USD ceiling in force for THIS RUN ONLY`, `backend/cmd/tmctl/main.go:260`=`--ceiling-usd is NOT a per-run budget` | diff --git a/docs/glossary.md b/docs/glossary.md index 4525f079..32b69662 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -26,7 +26,7 @@ - **⚠-баннер** — шапка «тело superseded, чему верить»; **ревью-шапка** — вердикты приёмки поверх отчёта в `archive/reports/`. - **Пак** — пакет работ одной сессии; **свип** — полная перепроверка обязательств (D39.66: 951 позиция); **добор идеала** — очередь качества после ре-пробы flash; **МАСШТАБ** — прогон целой книги. - **Строка N** — стабильный ID строки единого бэклога (`docs/BACKLOG.md`; не перенумеровывается); **вес** — блокер-очереди / скоро / когда-нибудь; **носитель** — артефакт, в котором обязательство живёт; **хвост** — незакрытый остаток; **петля** — вопрос, обязанный получить диспозицию; **слот** — зарезервированное место в будущем пакете/замере. -- **Гвоздь** — регрессионный тест, прибивающий контракт (негативный гвоздь — тест на ОТСУТСТВИЕ поведения). +- **Гвоздь / пин** — регрессионный тест, прибивающий контракт (негативный гвоздь — тест на ОТСУТСТВИЕ поведения). ⚠ Замер 11.09 по 167 живым `.md`: «пин»/«запинить»/«пин пуст» — **244** вхождения в двух главных доках (90 в `docs/BACKLOG.md`, 154 в D-логе; счёт очищен от «пинг», «пиньинь», «Репин», «спина»), тогда как «гвоздь» вне этой статьи встречается всего **4 раза в двух доках** (`docs/architecture/13-tech-debt-anchors.md`, `eval/softsign-decl/README.md`), а в `BACKLOG.md` и D-логе — НИ РАЗУ; статья держит оба имени, потому что определён был редкий синоним, а не рабочее слово. **Мутация / мутант** — намеренная порча исходника, которой проверяют, что пин ЛОВИТ; инструмент `backend/cmd/tmmutate` с каталогом `mutations.json` сажает мутацию, гоняет тесты одного пакета и возвращает исходник (110 упоминаний в тех же двух доках при нуле в глоссарии). ⛔ Мутация засчитывается по ТЕКСТУ падения, а не по факту красноты (`D39.217` п.2в); гоняется на КОПИИ дерева; пин, флейковый на мутанте, измеряет пустой сценарий, а пин, удовлетворённый ЧУЖОЙ уликой, пуст (гардрейлы `CLAUDE.md`). - **Реестр 108 / «жилец реестра»** — строка 108 единого бэклога: реестр ЗАГЕЙЧЕННЫХ ТРИГГЕРОВ (отложенных реопенов с условием «когда вернуться»); «жилец» = такой реопен; норма «каждое отложено получает строку или жильца» — D39.66/D39.90. - **Контракт 14 (API v0)** — ратифицированный контракт фронт↔платформа: `architecture/14-api-contract/` — нормативная спека OpenAPI 3.1 + компаньон-README; ⚠ **зонная копия — НЕ байт-зеркало (испр. 10.09):** равенство приостановлено на время фриза фронта (`D39.142` п.5), и расхождение сегодня измеримо — канон 3467 строк против 1444 в зоне. Прежняя формулировка: зонная копия `frontend/docs/api-contract/` — байт-зеркало (D39.99; статус зеркала и версий — карта `README.md`, здесь не пинятся). **Провенанс ✓/◆/○** — классы утверждений компаньона: выведено из кода/ратификации · предложено (подтверждает названная зона) · открыто (К-вопросы). **spectral / openapi-typescript** — линт спеки и генерация типов фронта с дрифт-тестом (⚠ 3.1-условия генератор игнорирует — К-11). - **ПТ-N** — стабильный ID требования в `product-requirements.md`; не путать со строками единого бэклога. **paused / лимиты «как Claude Code»** — статус книги при стопе по потолку + страница статуса использования в настройках (ПТ-35, D39.100) ⚠ **испр. 05.09: «сумм на экране нет» ОТОЗВАНО — D39.196**; баланс, потолок и холд показываются деньгами, запрет остался только на структуру НАШИХ расходов. @@ -38,15 +38,18 @@ - **Волны** — waveDraft (черновик) → терминолог → waveEdit (редактура); имена только полные, аббревиатуры W0/W1 запрещены (решение владельца 19.07). - **Чанк** — единица нарезки книги; **edit-unit (юнит редактуры)** — member-чанки, схлопнутые редактором в один финальный текст: гранулярность финала и экспорта пар (~1.9 юнита/главу; якорь синхронизации фронта — D39.84; draft-only-пайплайн шипит по чанкам). +- **Поверхность — слово с ТРЕМЯ смыслами, и без соседей оно не читается** (замер 11.09: 53 употребления — 22 в `docs/BACKLOG.md` и 31 в D-логе, — статьи не было ни одной). **(1) банковская** — исходное НАПИСАНИЕ термина, ключ, под которым он живёт в банке; ключ уникальности банка — `(src, sense, since, until)`, поэтому «одна поверхность ЗАКОННО несёт несколько ПОДПИСАННЫХ канонов (фамилия и направление у одного написания)» (`D39.193` п.3), а дедуп по голому `src` ронял подпись молча. **(2) продуктовая/сетевая** — внешняя грань, которой продукт повёрнут к пользователю или к соседней зоне: читающая поверхность платформы, операторская ручка, SSE-поток, «поверхностей у продукта ДВЕ, а не одна» — лендинг и IDE (`D39.239` п.1). **(3) кодовая** — место в коде, до которого прогон или тест реально добрался: «Первый живой прогон НЕ КОСНУЛСЯ поверхностей, ради которых часть кода построена» (строка 255). ⚠ Смыслы (1) и (2) сталкиваются в одних и тех же строках про банк и дверь. - **Банк (памяти)** — термины/имена/голоса книги на весь прогон; **сид** — стартовый банк книги (YAML; подпись владельца — только вкусовые поля, D39.77); **бриф** — книжные вводные; **банкнота** — канал выноса кандидатов из ответа переводчика; **майнер** — $0-извлечение кандидатов из исходника; **KWIC** — конкорданс-контекст кандидата; **терминолог** — роль перевода/подписи терминов батчами. - **Доктрина инжекта (закон)** — банк на проводе обязателен для всех ролей НЕЗАВИСИМО от статуса строки; право «перевести иначе, если сомнительно» упразднено, свобода — только оговоркой ОБЛАСТИ употребления (не-терминные пассажи: игра слов, разбор знаков); на проводе — единый закон-блок редактора, маркер ⟨проверить⟩ снят; статусы строк и подписная таблица не меняются (D39.104; ВНЕСЕНО вайр-батчем, пак принят D39.199; строка 134 закрыта). - **Гейты** — детерминированные $0-проверки перевода; **чекеры K1–K12** — классы дефектов рубрики; **DC1–DC7** — data-driven чекеры на данных пары; **репэйр** — платная петля ремонта (построена, выключена — строка 13). +- **Строгая и якорная колонка** — две колонки прибора консистентности по ОТГРУЖЕННОМУ тексту (носитель — строка 406, правило выбора там же помечено как ратифицируемое приёмкой 11.09): СТРОГАЯ требует «равенства стеммов, как у пост-проверки» и ошибается в сторону ЛОЖНОЙ ТРЕВОГИ; ЯКОРНАЯ «признаёт склонённую передачу» и ошибается в сторону СОКРЫТИЯ. **«Первичная — ЯКОРНАЯ, строгая идёт полом точности рядом»** (на прогоне A точность 0.78 против 0.39); основание НЕ «ложная тревога дешевле сокрытия» — строка 406 прямо говорит, что этот довод аргументирует ОБРАТНОЕ, — а «детектор, врущий в 61 % сообщений, … перестают читать». ⚠ Правило действует, ПОКА прибор флагует и не отказывает: станет он гейтом отгрузки — асимметрия перевернётся и порядок колонок решается заново (строка 406 называет ДВА триггера пере-открытия). ⚠ Не путать с «якорной половиной» канон-проверок (строка 339) — там слово про другое. - **Судья** — Ф2-оценка качества (gemini); **канал B** — путь чувствительного контента (Mistral+grok); **лейблы (labels)** — размеченный корпус для precision/recall чекеров, метрики заморожены числами в приёмках. - **Голден** — байт-фиксированный снапшот прогона; **маскированный дифф** — сверка голдена с маской hex/версий; **CheapGateVersion (CGVER)** — версия контракта гейтов; **парити** — `TM_MINER_PARITY=1` EXACT-сверка майнера. - **Эхо-мина** — DeepSeek без thinking эхоит вход вместо перевода; гейт `echoMineViolation` принуждает thinking-ON. - **Langpack / пар-файл** — данные языковой пары (`backend/configs/langpacks/`); книжное в пар-слое = утечка; **общность** — ревью-вопрос «заработает ли пара/вторая книга без правки Go». - **Ведро B/D** — корзины триажа карты общности D39.60 (B «пар-модуль без гейта» · D «удалить»). - **tmctl** — CLI бэкенда. Полный список глаголов — ОДИН в коде (`backend/cmd/tmctl/main.go`, `dispatchCommands`), и он же печатается в usage (паритет «список ↔ usage ↔ switch» прибит тестом `cmd/tmctl/invocation_test.go`); сверка одной командой: `grep -n -A3 "dispatchCommands = " backend/cmd/tmctl/main.go`. ⚠ Копия списка стояла здесь и трижды отставала от кода — снята: носитель один, отдельные глаголы (`build`, `bank-apply`) расшифрованы строками ниже. +- **Подстановка цены** — тихий фолбэк прайсера: провайдер вернул слаг, которого в каталоге нет, и `PriceForResponse` (`backend/internal/ledger/pricing.go:61`=`func (p *Pricer) PriceForResponse`) пробует `actual`, потом `requested`, потом якорь, а ни одно из трёх мест вызова не различает, какая ветвь сработала. Пока подмена падает внутрь той же семьи, счёт верен; опасна не подстановка, а её НЕВИДИМОСТЬ — при маршрутизации провайдера ВНИЗ это «×3.3 из кармана читателя, молча». Носитель — строка 413. ⚠ Сводя такое по диску, помнить строку 428: обход файлов `*.db` умножает трату на число КОПИЙ базы (замер 11.09 — множитель 10.88×), поэтому деньги считаются по УНИКАЛЬНОМУ `(book_id, date)` либо по одной авторитетной базе. - **COGS** — себестоимость перевода; **ре-проба** — дешёвый повторный замер провайдера после аномалии (носитель события — строка 188; исходная 74 закрыта D39.91). ### Неймспейсы номеров diff --git a/docs/orchestrator-norms-scratchpad.md b/docs/orchestrator-norms-scratchpad.md index 72af7b09..39353f37 100644 --- a/docs/orchestrator-norms-scratchpad.md +++ b/docs/orchestrator-norms-scratchpad.md @@ -113,8 +113,11 @@ UNKNOWN 1 — её, дошёл один раз до правок; десять - **Ключи прогона A:** путь выдан (`backend/.env`), файл НЕ читать; живость ключей проверяется ПЕРВЫМ платным вызовом. Отказ по авторизации — стоп сессии и мой поход к владельцу. - **Пре-рег-таблица прогона A приходит мне ДО фриза** — читаю её прежде, чем потратится первый цент. -- **Релей:** улика прогона A про многоединичную главу идёт движковой сессии ОТ МЕНЯ отдельным сообщением с - её эхо-подтверждением, не напрямую. +- ⛔ **Релей НЕ СОСТОЯЛСЯ, и сказала это не я.** Улика прогона A про многоединичную главу должна была уйти + движковой сессии ОТ МЕНЯ отдельным сообщением с её эхо-подтверждением — не ушла, и дизайн-пак записал + это у себя: `backend/docs/CHAPTER_STRUCTURE_DESIGN.md:1869`=`о многоединичной главе`. Улика найдена и положена в + трекер — ряд **409**, — чтобы не умереть вместе с этой запиской. В чужую зону я не пишу: §13.2 п.6 того + документа снимается ПИНГОМ движковой сессии, а не моей правкой. - **Кросс-зонная цена перекроя** (`unit_resolutions` платформы, экспортные id термов) придёт от движковой сессии пунктом отчёта — отнести её платформе должен я.