# ЕДИНЫЙ БЭКЛОГ — движок · полигон · доки · процесс
> **Единственный трекер проекта.** Здесь живут строки, на которые доки, промты и 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`; обновлять при каждом лендинге):** всего **304** строк · зона бэкенд **146** строго / **198** широко (⚠ колонки счётчик читает С КОНЦА — испр. D39.116) · **блокеров очереди 0** (236 закрыта D39.175; **371** — актом D39.233, **360** — актом D39.232, обе 10.09), платные прогоны разблокированы · «скоро» **149** (перечень — грепом по таблице, рукописный список снят 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; правки — только через оркестратора)
Закрытые строки здесь НЕ хранятся — они уходят в D-лог с номером решения. **ID строки стабилен навсегда** (не перенумеровывается и не переиспользуется — на «строку N» ссылаются доки и промты, D39.80). Вес: «блокер-очереди» = мешает текущему шагу · «скоро» = ближайшие 1–2 касания · «когда-нибудь» = записано, не потеряно. Длинная строка начинается жирным лидом — таблица сканируется по лидам; «диспозиция сверху, археология вниз», ячейка >800 байт — кандидат на выселение в `architecture/13-tech-debt-anchors.md` (D39.125 п.3/D39.126). ⚠ **Счёт очереди — НИЖНЯЯ граница долга, а не потолок:** трекер содержит только замеченное, и 02.08 дважды за $0 свежие глаза вытащили из кода дефекты, которых в нём не было (релей фронта → строки 99/100/102; приёмочное ревью → третий шов в 104 и честность в 105); ленту ✅ шапки читать как «долга нет» неверно (D39.89). **Зонные бэклоги (решение владельца 02.08, D39.84):** фронт и платформа ведут СВОИ бэклоги (`frontend/docs/BACKLOG.md` · `platform/BACKLOG.md`) — их строки сюда НЕ заходят; здесь движок/полигон/доки, включая движковые стыки фронта (зона «бэкенд», как 99–102); строки 96/97 переехали в платформенный (П-1/П-2), надгробия-указатели сохранены.
| ID | Хвост (одной фразой) | Зона | Вес | Чем закрывается | Источник |
|---|---|---|---|---|---|
| **— ВИСИТ НА ВЛАДЕЛЬЦЕ —** | | | | | |
| 2 | Четыре вопроса границы «алгоритмического идеала» (Annotator · семантический судья · ja→ru §B5 · ru-target до/после) | владелец | скоро (гейт «добора идеала» перед МАСШТАБОМ) | отдельное решение | D39.33, D39.38 |
| 4 | **Ре-чек ToS по триггерам** — первый ИСПОЛНЕН 31.07, дельт вердиктов нет (D39.57); предмет Google-мониторинга перевешен на цепочку договора (PUP · Additional ToS · Google APIs ToS); следующие: квартал 25.10.2026 · первая лейблованная книга · любая правка `accepts_labels` | владелец/полигон | скоро (следующий триггер 25.10.2026) | отдельное решение (правило) | D39.32, D39.57 |
| 5 | **Арбитраж банка: замер ИСПОЛНЕН и ПРИНЯТ (research/24, D39.102).** Закрыто классом: равноправный совет · кросс-модельные веса уверенности · self-consistency · селекция из вариантов · отказ-сигнал ⟦TM-NO-DST⟧; Q2 отвечен — семейства не окупаются (C3−SC=+3 и все три добычи = один кластер; glm-соло 25/45 > совет 23/45). **ОСТАТОК СТРОКИ:** рецензент-другого-семейства ТОЛЬКО на спорных КЛАСТЕРАХ (слот при ре-пробе 74), роутинг целыми family/series-юнитами (G4), эмиссия рецензента — та же draft/⟨проверить⟩. История захода — D39.89/90/101/102 | полигон/ресёрч | **ОСТАТОК ГЕЙЧЕН ре-пробой 74** (D39.102 п.2) | замер (остаток) → решение | D39.89, **D39.102** |
| 6 | **Строка Gemini в `accepts_labels`** — ждёт слова владельца о подписи интерпретации сужения как разрешения; ре-чек 31.07 понизил приоритет: подпись даёт ПРАВО, но не судью 18+ (фильтр неконфигурируем D22.6 + обход запрещён договором) — возвращаться при вопросе, требующем именно права | владелец | когда-нибудь | отдельное решение | D39.32, D39.57 |
| 7 | Q2 «редактор под `sexually-explicit`» (grok-4.3 интерим · glm-5 после сверки ToS Z.AI · mistral вон) | владелец | когда-нибудь (перед первой explicit-книгой) | отдельное решение | D39.27 п.7 |
| 8 | D22.7 пер-чанковый L3-скрин — неснятое предусловие первой erotica-книги в проде, отдельный гейт | владелец | когда-нибудь | отдельное решение | D22.7, CURRENT-STATE (оркестратор) |
| 9 | Промпт-слой под лейблом: лейбл не доезжает до промпта — должны ли переводчик/редактор знать о свойстве контента | владелец | когда-нибудь | отдельное решение | CURRENT-STATE (владелец, из пака-17) |
| 10 | Дата создания аккаунта OpenAI (низкий приоритет, OpenAI вне цепочки) + применимость OpenAI Sharing & publication policy 2022 (quirks:128) | владелец | когда-нибудь | отдельное решение | D39.32 |
| 11 | Флип coverage-гейта (`enabled:false`, D12-Q4) — за подписью владельца ; при флипе решить судьбу v1.1 quote-absorption (D12-Q1, Python-first лок-степ) | владелец | когда-нибудь | отдельное решение | D39.34(2) |
| 12 | **`postcheck_gate` в hard-gate** — требует пере-замера recall (recall чекеров измерен и низок); ⚠ «fn=0» демоции #10 класс-вакуумен на labels (ноль одно-Han-позитивов, D39.78) — пере-замер обязан добрать одно-Han-позитивы, на «fn=0» не опираться; одно-Han-класс при gate-on вне гейта (Unverified+Demoted); тем же решением строится HARD-value-детектор 成/万 (Q3 §6 — честный hard-gate требует value-чека; либо раньше при ненулевом потоке value-дефектов добора, D39.79; **$0-прототип получен эксп-21: `battery.check_numbers`, симметричный разбор, синтетика 16/16 — D39.117**) · recall существующих гейтов печатал арм C эксп-21 на контаминированном срезе (D39.108/D39.117) | владелец | скоро (⚠ испр. 05.09: `D39.205` п.4 сделал эту строку ПРЕДУСЛОВИЕМ решения владельца по гейту глоссария — прежний вес «когда-нибудь» противоречил ратифицированному; порядок работ — строка 295) (после фазы 2) | отдельное решение | D39.34(2), D24.4+D28.1, D39.39, D39.78, D39.79 |
| 13 | **Включение платной петли ремонта + per-class исходы ремонта** (схемное решение принимается вместе) — вернуться при расширении классов детекторов и ненулевом остатке; ⚠ при включении: репэйр-гард №5 после #10 слеп на одно-Han-дифференциал (демоция в обоих прогонах ⇒ 0>0 — репэйр, стёрший верно отрендеренный одно-Han-термин, не ветируется; D39.78-ревью) | владелец | когда-нибудь | отдельное решение | D39.38, D39.39(а), D39.78, CURRENT-STATE |
| 13б | **`speech-cue.txt` zh НЕ шипить до замера голос-флаггера; замера НЕТ (D39.86) — оси не считались НИ РАЗУ.** ⚠ **Причина ПЕРЕ-НАЗВАНА: прежний довод «редакторская волна не гонялась» ПРОТУХ 31.08** (холодный прогон `coldrun-v16` её гонял и оплатил — строка 16); живой блокер — ПУСТОЙ РЕЕСТР профилей, см. ниже. ⚠ **ГЕЙТ ПЕРЕ-СНЯТ 05.09:** прежний требовал «подписанных профилей (строка 24)», а подпись владелец снял (D39.198 п.5) — значит гейтом остаётся ОДНО: первый прогон добора идеала С редакторской волной. ⛔ **Но снятие подписи открыло дыру, и её надо закрыть раньше стройки:** реестр `voices:`/`addresses:` физически заполняет только подпись (`backend/internal/config/seed.go`, греп `no miner emits them`), и если подписи нет — заполняет НИКТО. Вопрос вынесен строкой 24. ⚠ Сам гейт в схеме ЕСТЬ (`internal/config/pipeline.go` `VoiceGate`, пак-19/D39.55). ⚠ `rules=` в отчёте = «гейт СКОНФИГУРИРОВАН», не «отработал» — до фикса читать по знаменателям `replies=` — носитель **292** (испр. 05.09: 105 закрыта D39.200 только половиной (а), знаменатели уехали в 292). Археология дословно — `architecture/13-tech-debt-anchors.md` §Б-13б. ⚠ **ПОПРАВКА 23.08 (№19):** заполнить `voices:`/`addresses:` может только подпись владельца (`internal/seed/seed.go:23`=`Voices and Addresses are the two D21 record types` — «no miner emits them»), а при пустом реестре `RunVoiceChecks` выходит на `!reg.HasData()` ДО ВСЕХ осей, поэтому нулями отдаются и оси, и знаменатели — «ноль флагов» неотличим от «оси не считались». ⚠ Отдельно: `gates.voice` отсутствует в `backend/configs/`, НО в конфигах реальных прогонов (вне git) он ВКЛЮЧЁН — `~/books/gu-zhenren/coldrun-a/pipeline.yaml:68` и `coldrun-b:71`, `enabled: true`; дыра не «оператор забыл включить», а «шаблоны репозитория гейт не несут» | владелец | отложено-до-замера | первый прогон добора идеала С РЕДАКТОРСКОЙ ВОЛНОЙ (оси голоса, строка 24) → отдельное решение | D39.56, PACK19_BUILD §7.2, чат 31.07, D39.86 |
| 14 | **Четыре data-инженерных флага фазы-2 общности, каждый с рекомендованным дизайном** (§5 отчёта): ё-фолд → target-данные (`char_fold`; смена сигнатуры core-примитива через вердикт-несущий банк, сдвиг `memory_version`) · segmentation-фолбэк громким (ломает контракт corridor-фолбэка `pipeline.go:839-848` + голден-фикстура на нём; лечение — объявить блок в голден-yaml) · `Fertility` per-script map (калибровка ждёт боевого токенизатора) · `source-encoding.txt` + Go-реестр декодеров | владелец | когда-нибудь (следующий пак общности) | отдельное решение | D39.64, GENERALITY_PHASE2 §5.1–5.4 |
| 86 | **Мелкие открытые решения одним списком** (свип D39.66): echo-семантика дропнутого c-lite-члена (D39.18 — оставить pre-c-lite?) · magnitude-кап тяжёлой CJK-утечки (D38.3 п.4в; сейчас strip+flag) · ⚠ дописка 07.09: `internal/lang/data/zh/numeral.txt` отстаёт от эталона `cjk-section.txt` на `〇两兩` — намеренно или недосмотр? Потребитель — канал «числительное + ранг-слово» майнера (research/33 §7.1) | владелец | когда-нибудь | отдельные решения | D39.66, D39.69(feed_cap закрыт §1) |
| **— ХВОСТЫ ХОЛОДНОГО ПРОГОНА (исполнен достаточно, D39.58; Р7 владельца) —** | | | | | |
| 16 | **Полная цена холодного старта — ЖИВОЙ ОСТАТОК ОДИН: цена ДОВЕДЁННОЙ ДО КОНЦА книги не измерена.** Холодный прогон `coldrun-v16` 31.08 отдал 3 юнита из 14 и остановлен снапшот-гардом. ⚠ **Довод «редакторская волна не гонялась» ПРОТУХ 31.08** (испр. 02.09): она гонялась и оплачена — 4 чекпойнта `edit/editor/deepseek-v4-pro` на $0.214865; не мерена именно ПОЛНАЯ цепь одним заходом до конца книги. **Числа ДО редактуры — база прогона `~/books/gu-zhenren/coldrun-b/reprobe/bank-low/guzhenren-bank-low.db`** (10 глав, `low` на черновике И на бэнк-ролях; арифметика снята 23.08 №19): вся ДРАФТ-стадия $0.031639 (flash $0.021289 + pro $0.010350) · терминолог $0.005750 · классификатор $0.007706 · **весь заход $0.045095**, слагаемые дают именно его. ⚠ Числа в ИЮЛЬСКИХ деньгах — множитель пере-пина DeepSeek 4.47 (D39.179 п.1), сегодня тот же заход $0.2017. ⚠ Фаза C `coldrun-b` закрыта владельцем как неуспешная (02.08, D39.90), её деньги не тронуты ($0). Строка держит и оси голоса (13б/24) | бэкенд | когда-нибудь (гейт: первый ЗАВЕРШЁННЫЙ прогон) | добор идеала | D39.58, **D39.90** |
| 18 | **Эмиссия головы 蛊**: сид-половина = чек-лист (определяющий терм книги сидится `allow_short`, D39.50); эмиссия-КАНАЛ демотирован до ИЗМЕР-ГЕЙТА (Q7): полигон-замер «меняет ли эмиссия головы рендер композитов» — строить ТОЛЬКО по эффекту и ПОСЛЕ #10 (однознаковый пост-чек чинится чекер-паком); перед стройкой резолвить K-гейт и KWIC-грязь одиночной головы | полигон → бэкенд | скоро (санкция Q7 D39.70 — после #10, очередью с ре-пробой) | полигон-замер → решение | D39.58, D39.60, D39.69 |
| 24 | ⚠ **ГЕЙТОМ БОЛЬШЕ НЕ ЯВЛЯЕТСЯ — испр. 05.09 (D39.198 п.5):** прежняя редакция держала «профили голоса НЕ ПОДПИСАНЫ» как предусловие, а владелец подписи снял («зачем мне это подписывать») и вытаскивать черновик из книжного дерева не надо. Голос — приоритет №3 из трёх, то есть работа, а не блокер. **Остаток: авто-режим флага** (проект Б не гонялся) · оси голоса A–D · слот инъекции голоса и решение gates.voice при ненулевых осях (D39.55/D21 п.2) · слой-2 voice не строим до доказательства слоя-1 · сверить until_ch 白凝冰 при курации сида (D19.3в). ⚠ **ОТКРЫТЫЙ ВОПРОС, РОЖДЁННЫЙ СНЯТИЕМ ПОДПИСИ:** реестр профилей (`voices:`/`addresses:` сида) сегодня физически заполняет ТОЛЬКО подпись владельца — `backend/internal/config/seed.go`, греп `no miner emits them`. Если подписи нет, ЗАПОЛНЯЕТ КТО? Ответ нужен раньше стройки: без него строка 13б навсегда «отложено до замера» | бэкенд | когда-нибудь | работа третьего приоритета | D39.40, D39.58 |
| **— ТЕКУЩАЯ ОЧЕРЕДЬ (D39.59) —** | | | | | |
| 79 | **Граница ПЛОТНОСТИ письма для серий**: `enabled` через Go-константу `cjkScriptNames` — новый плотный скрипт требует правки Go (head-finality уже в данных script-series.txt; пре-существующая граница, D39.75). Первые два компонента строки (isCyrLetter→`isTargetWordLetter` · magnitude `SourceScripts`-гейт) исполнены пакетом-чекеров, D39.78 | бэкенд | когда-нибудь | следующий пак общности / касание чекеров | D39.64, D39.78 |
| 90 | **Ф2-кандидаты 02-mvp-плана без носителя** (свип-хвост, D39.73): CometKiwi/T-index метрики судьи · Batch API судьи (экономия) · llama-server-интеграция локали · стриминг — взять/закрыть при пилот-препе; + H16 самоулучшение (V3-п.2, ПТ-26): дизайн петли по данным судьи — тем же препом | полигон/бэкенд | когда-нибудь (Ф2.5) | пилот-преп-промт (с 85) | 02-mvp-plan, D39.66, D39.73, D39.80 |
| **— НАХОДКИ СВИПА ПОЛНОТЫ (D39.66: 951 обязательство проверено, потери возвращены в трекер) —** | | | | | |
| 80 | **Резюме-слой памяти** — проза-суммарайзер ЗАКРЫТ (D39.69); строка = ГЕЙТ ПИЛОТА Ф2.5: первый деливерабл пилота — «допускает ли автономная нарратив-состояние-строка ДЕТЕРМИНИРОВАННЫЙ верификатор (source-anchored) — или это D1-компаундинг со схемой»; не-покрытые классы (source-anchored reveal · арк-колбэки без ключа) реальны, но не измерены как дефект | Ф2.5 (Q3 подтверждён D39.70) | когда-нибудь (пилот) | Ф2.5 пре-рег | D25 п.8–9, D39.66, D39.69 |
| 81 | **ja-преп B6-ja (сужено пост-сверкой D39.66)**: Поливанов-валидатор (`translit_policy` = «Phase 2»-заглушка, `backend/internal/store/migrate.go:187`=`translit_policy TEXT` и `backend/internal/store/migrate.go:195`=`ruby_reading`) + kana-омограф POS/known-word гейтинг / B6-токенизатор (`backend/internal/membank/memory.go:1184`=`KANA and HAN are deliberately NOT boundary-checked`); чек-лист kana-алиасов сида УЖЕ построен (backend/README §ja + `AttachRubyAliasesToManual`) — остаток в нём только дизамбигуация двойных чтений (тот же B6) | бэкенд | когда-нибудь (перед ja→ru) | ja→ru-пак (рядом 35) | D16.4, D17.1, D18, D39.66 |
| 82 | **Морфо-гейт РОДА** (C3: русский глагол прош. вр. при gender=hidden = механический спойлер-канал; «жалоба №1 читателей MTL»; python-сайдкар/pymorphy, связка с морфопроходом Decl из 73). **$0-прототип получен эксп-21** (`battery.check_gender`: карточки из подписанного сида, фильтр по именительному падежу, 86–112 сверок/арм — D39.117); движковый гейт не построен | бэкенд | когда-нибудь (Ф2-гейты) | отдельный пак (с 52) | 06-реестр C3, research/12, D39.66, **D39.117** |
| 85 | **Пилот-преп добор** (к переупаковке PACKAGE4): Bertalign GOLD-пары + zh→ru spot-check (D29.2в; GPL-тулинг отдельно) · fidelity-каскад R2 shadow с корпус-подготовкой (D25.2) · exp08 v3 пере-съём COGS до фиксации budget_usd (D21.8) | полигон | когда-нибудь (Ф2.5) | пилот-преп-промт | D25, D29, D21.8, D39.66 |
| **— ПАК-21 «чекеры»: РАСТВОРЁН (D39.62); шестёрка исполнена 2/6 фазой 2 (D39.64: #11 · строка 26), остаток — ниже —** | | | | | |
| 93 | **Остатки строки 93 после пачки (D39.82):** строгий OffLanguage (36а, deferred D39.78) · 分之-разметка прежде стройки DC2 word↔word (полигон) · F4-хвост: `redrive --dry-run` обходит pre-flight, а `store.Open` мутирует SPOF-файл (миграции + recoverReservations; коммент «mutates nothing» неверен) — pre-flight и на dry-run при существующей БД либо read-only план; заодно stat-скип точной формой `fs.ErrNotExist`; **обострение приёмкой D39.134:** на устаревшей БД `--dry-run` выполняет ПОЛНУЮ миграцию схемы БЕЗ restore point (write-open без шва migrate) — воспроизведено исполнением. ⚠ **Остаток НЕ однороден по гейту (сверка 02.08):** F4-хвост и строгий OffLanguage свободны, а `分之`-часть ГЕЙЧЕНА полигон-разметкой среза («строить вслепую против мандата» — якорь техдолга) ⇒ не подавать строку как «малое касание без гейта» | бэкенд/полигон | когда-нибудь | малое касание / полигон-слот | D39.78, D39.82 |
| 98 | **DC7 грейд-консистентность — пере-гейчен по сид-покрытию (D39.82):** замер пачки реален (25 юнитов/93 «разряд» ≠ канон «класс» на labels-финалах), НО финалы — прогоны до/вне сид-v2-канона, а грейды 甲/乙/丙/丁等 теперь approved-записи сида с decl-формами: mempostcheck флагнёт «разряд» промахом dst; строить DC7 только если ОСТАТОК девиаций переживёт сид-покрытие — замер на первом СИДОВОМ прогоне добора идеала; дом канона при стройке = book.yaml (как register_blocklist; ратифицировано D39.82 — НЕ dc-checkers.txt, посылка D39.79 исправлена) | бэкенд | когда-нибудь (гейт: первый сидовый прогон добора идеала) | замер остатка → решение | D39.79, D39.82, SMALLPACK §5-E1 |
| 28 | Банк-линт латиницы в dst или строгая форма языкового предиката (7 строк утечки алфавита проходят экран); сюда же хвост закрытой 128 (D39.102: NoDst-почти-сентинел, латиница-target — дословно не переехал при закрытии, восстановлен аудитом D39.140) | бэкенд | когда-нибудь (добор идеала — носитель «свежий мини-прогон» растворён D39.67, актуализация D39.79) | касание чекеров при данных добора (помнить оговорку 36а: «甲等 → класс Цзя» строгой формой не ловится) | D39.52, D39.62, D39.64, D39.79 |
| 28а | **Prompt-injection-проба входного текста** ($0): сепаратор ⟦TM-BANK-v1⟧ и якорь-подобные маркеры В ТЕКСТЕ КНИГИ — поведение среза/парсера/инъекции (книга = недоверенные данные; инструментов у моделей нет, но канал банкноты читает вывод по маркеру) | бэкенд/полигон | когда-нибудь | малая проба | сводка-ревью 26.07 |
| **— СВИП ГИПОТЕЗ —** | | | | | |
| 30а | **Перерисовка puml-диаграмм под пост-пак-20 пайплайн** (терминолог, банкнота отдельным файлом); дом диаграмм теперь `backend/docs/` — правятся одним коммитом с кодом (D39.80); PUML НЕ рендерить (гардрейл); ловушки activity-синтаксиса, стоившие реального бага 25.07, — `12-go-style-notes` §1 (дом на онбординг-пути бэкенда; строка держит указатель, а не сам факт — носитель с запланированной смертью для долговечного факта не годится) | бэкенд | когда-нибудь | ближайший пак, касающийся pipeline | аудит доков 26.07, D39.80 |
| **— ОТДЕЛЬНЫЕ ПАКИ/РЕШЕНИЯ (бэкенд, добор идеала) —** | | | | | |
| 31 | Слой-2: извлечение дискурс-норм/few-shot из ТЕЛ промтов (форсинг = ja→ru) | бэкенд | когда-нибудь | отдельный пак (идеал D39.33) | CURRENT-STATE, D39.33 |
| 33 | **native-Gemini судья** (Ф2-механизм) ; до прод-заводки: $0.01-проба thinking⊆max_tokens на боевом слаге (D22.3) + включить sanitizer в pipeline-c2 при оживлении (D33.4б) | бэкенд | когда-нибудь | отдельный пак (идеал) | CURRENT-STATE, D39.33 |
| 34 | **Генеральность нарезки** — ОСТАТОК после фазы 2: сами per-script коэффициенты (`est_out` ja завышен ~1.7× МОЛЧА · `EstimateTokens` недосчитывает кириллицу); консолидация класса письма СДЕЛАНА (один дом `DenseScript`, D39.64) — лечение = `Fertility`-map (строка 14) + офлайн-калибровка при боевом токенизаторе | бэкенд | когда-нибудь | строка 14 + отдельный пак (с ja→ru) | D39.37(5), D39.64 |
| 34а | **Экран кодировки не видит `` без XML-объявления** (епаб с gb18030-метой прочтётся как UTF-8) — до-паковая дыра, сознательно не тронута пачкой 14а (паритет со старым ридером) | бэкенд | когда-нибудь | отдельное решение | D39.54, SMALLPACK §8 |
| 35 | **Не-CJK майнер/банк**: en-детектора не существует (hanRuns=0), ja с zh-таблицами активно неверен (0/10); нужен второй ДЕТЕКТОР (прототип `mine_nonhan.py`) + G1–G10 требования generic-майнера (вкл. квадратичность G9 ≈4.6 ч) | бэкенд | когда-нибудь | отдельный пак generic-майнера (с ja→ru) | D39.37(8), D39.43, D39.50 п.8, POLYGON_PREMEASURE §6 |
| 36 | Кластеризация майнера глотает родовые титулы (族长/学堂家老 в кластере 葛家) — закрыто на границе сборки входа, сама кластеризация не чинилась | бэкенд | когда-нибудь | отдельное решение | D39.43, D39.45 |
| 36б | **Второе мнение по банку**: рецензент ДРУГОЙ моделью, несогласия — отдельной колонкой подписной таблицы (судья-с-декоем в роли рецензента; решает владелец, D39.46-ограничение не бьёт). ⚠ **Бэкенд-стройки НЕТ** (D39.69 закрыл по нужности); замер ИСПОЛНЕН (research/24, D39.102) — остаток = строка 5: рецензент спорных КЛАСТЕРОВ при ре-пробе 74, роутинг family/series-юнитами; переживёт замер → тонкая колонка наблюдаемости, не гейт | полигон (замер) → бэкенд (только если переживёт) | когда-нибудь (слот при ре-пробе 74, остаток строки 5) | замер остатка → решение | D39.69, D39.90, **D39.102** |
| 36г | **Проводной формат каналов пересказан прозой в каждом пар-промпте, парсер в Go, связи нет** — формат в шаблон движка (`{{banknote_format}}`); линты держат класс, дублирование остаётся | бэкенд | когда-нибудь (со следующей правкой промптов) | отдельное решение (Р5) | D39.58 |
| 37 | **Квадратичности: `AttachKWIC`** (16.8 с / 2000 кандидатов; фикс — многошаблонный поиск; ⚠ опция фикс-пака 128 НЕ взята — «чисто не ложится»: автомат в `membank` неэкспортирован, вынос в общий пакет = рефакторинг слоя, `terminology` PURE не может импортировать банк-стор — отчёт пака §4 п.5, D39.118) + src-правило банкноты при промахе чанк-пути (строка × длина книги; на 10 главах не видна) | бэкенд | когда-нибудь | отдельное решение | D39.45, PACK20_BANK_BUILD §8.5.1, D39.58, D39.118 |
| 38 | Смета не видит пере-покупку прохода терминолога на каждой итерации подписи (роль не пишет `chunk_status`, не видна `projectRebill`) · хвост приёмки №13: адрес чекпойнта батча = ординал при частотной сортировке ⇒ реюз чекпойнтов прохода ~0 на инкрементальной книге — **механика ПОДТВЕРЖДЕНА КОДОМ фикс-паком (§2 отчёта, D39.118):** G1 двигает состав юнитов и те же ординалы, на первом прогоне после пака перекупаются все бэнк-батчи (центы) | бэкенд | когда-нибудь | отдельное решение | D39.45, PACK20_BANK_BUILD §8.5.2, D39.102, D39.118 |
| 39 | S12 частичен: `malformedSeparatorAt` не ловит подмену слова разделителя и обрыв токена (комментарий обещает) | бэкенд | когда-нибудь | отдельное решение | D39.45, PACK20_BANK_BUILD §8.5.3 |
| 40 | `bankTokenBudget`: worst-case зашит zh→ru (признанная утечка §0; CJK-цель недобирает вдвое) | бэкенд | когда-нибудь | отдельное решение | D39.45, PACK20_BANK_BUILD §8.5.4 |
| 41 | golden: вторая фикстура С langpack (сейчас пинится только фолбэк-путь) ; + golden-счётчики голоса (хвост D39.58) ⚠ **ПРЕДМЕТ ШИРЕ ЗАЯВЛЕННОГО, испр. 05.09 по итогу веера.** Снято у прежней формулировки: «не пинится ничем» — ЛОЖНО, zh с настоящими langpacks гоняется в пяти интеграционных тестах; дыра именно в ПОБАЙТОВОМ пине. И «побочно это фикстура общности» — вывернуто: нынешний golden И ЕСТЬ доказательство цели №2 (пара БЕЗ пакета проходит книгу end-to-end байт-в-байт), вторая фикстура служит целям детерминизма и денег. **Настоящая цена дыры:** один из фолдов снапшота — руками поддерживаемая строка `RenderFormatVersion` (`backend/internal/membank/memory.go`); забыли бампнуть при смене байтов провода — денежная ось молчит, а контент-ось перекупает затронутые чанки БЕЗ гарда и БЕЗ согласия (`rebill.go`: «the CONTENT axis … re-bills exactly the touched chunks and is invisible here»). Единственный механический подстраховщик здесь — побайтовый golden, которого на langpack-пути нет. | бэкенд | когда-нибудь | отдельное решение | D39.37(6) |
| 42 | `prompt_override` — легальный обход гарантии слоя-2, сформулировать честно | бэкенд | когда-нибудь | отдельное решение | D39.37(7) |
| 43 | `request_log` без скоупа/ретеншена + `first_flag_reason` = третье представление истории попыток (корень — неразведённые скоупы) | бэкенд | когда-нибудь | отдельное решение | D39.37(9) |
| 44 | **Флор — выбор числа ПОСЛЕ ре-пробы 74; модель «thinking в completion» ПОЛУЧЕНА замером (D39.86): рычаг против неограниченного думания = `reasoning_effort`, флор не рычаг.** Мини-проба флора одобрена владельцем, промт не выдан; у dspro эффорт не настраивается (quirks 3а). Расхождение трекера с 74 снято D39.90. Археология дословно — `architecture/13-tech-debt-anchors.md` §Б-44. ⚠ **Вводная сменилась 13.08 (вахта §Б-108 СРАБОТАЛА):** вендор дал pro/flash настраиваемые уровни low/high/max — квирк 3а («у dspro эффорт не настраивается») устарел, пере-проба маппинга ПОВЕДЕНИЕМ + абсорбция в quirks — полигоном | бэкенд | когда-нибудь (триггер «приёмка 104» НАСТУПИЛ — D39.91, ручка заленжена; «сколько ставить» остаётся НЕзамеренным — нужен вариационный замер флора при `low`) | отдельное решение | D39.37(10), D39.86, **D39.90**, вендор 13.08 |
| 45 | `max_tokens`-упоры (две единицы) — вернутся на en-книге ; halve-chunk-on-retry (research/22 §2 №7) ОТКЛОНЁН D39.74 — вернуться сюда же при живых упорах | бэкенд | когда-нибудь | отдельное решение (с en) | D39.37(11) |
| 47 | M2-кэш / доктрина Д2 — кандидат на отдельную ратификацию | оркестратор/бэкенд | когда-нибудь | отдельное решение | D39.42 |
| 48 | Направленная банкнота — вернуться по замеру покрытия терминолога | бэкенд | когда-нибудь | отдельное решение | D39.42 |
| 48а | **Серийный шаринг банка** — РЕАЛИЗАЦИЯ (экспорт подписанного глоссария как сид-YAML следующей книги серии; спойлер-окна плющатся в since_ch=0); контракт round-trip держится тестом, самой фичи нет | бэкенд | когда-нибудь (перед второй книгой серии) | отдельное решение | D39.42 задел (а), PACK20_BANK_BUILD З-а |
| 48б | **Импорт «оригинал + чужой перевод» как режим данных терминолога** (target-агностичный вход есть контрактом; сам режим + провенанс источника + юр-сторона в юр-пакете) | бэкенд/владелец | когда-нибудь | отдельное решение + Ф2.5 (юр) | D39.42 задел (б), PACK20_BANK_BUILD З-б |
| 130 | **emitRankCap × writeAutoBank — ОСТАТОК после фикс-пака (D39.118):** $0-минимум ИСПОЛНЕН (дифф старого/нового авто-файла + WARN с именами выпавших; само-исключение сырого seed закрыто `unsignedEngineSurfaces` дофиксом приёмки); остаток = накопительный мердж авто-банка / освобождение слотов seed-rejects — СТОП-решение владельца (двигает банк → memory_version); материал для решения даст WARN со ВТОРОГО прогона (§6 п.8 отчёта пака) | владелец → бэкенд | когда-нибудь (гейт: WARN второго прогона) | СТОП-решение | D39.102 п.3, **D39.118** |
| 131 | **Кап инъекции не считает маркер и гендер-ноты**: `glossaryLineTokens` бюджетирует только «src → dst» (`memory.go:518-521` против рендера `:698-708`) — авто-книга (все строки Ambiguous с ⟨проверить⟩) превышает `glossary_token_budget` ~на 40–60% при budget 800; биллинг/потолки компенсированы (резервация по фактическому рендеру, `stagerun.go:469-477`), сам кап не исполняется. Фикс двигает состав инъекций → RequestHash → перекупка волн ⇒ СТОП-решение с названной ценой. ⚠ После строки 134 (единый блок, маркер снят с провода — D39.104) превышение пере-замерить: состав рендера сменится | бэкенд | когда-нибудь | СТОП-решение | D39.102 п.3 |
| 132 | **Стойкий (пост-ретрайный) аутедж ТОЛЬКО банк-провайдера валит весь ран** вопреки коммент-контракту «optional step never aborts» (`terminologist.go:630-634` — деградация только на ceiling; транспортные ретраи гасят transient, `httpllm.go:126-160`; потерь нет — чекпойнты реплеятся за $0): решить — деградировать в «термы неконсолидированы»+WARN либо честно переписать коммент | бэкенд | когда-нибудь | малое касание через СТОП-решение | D39.102 п.3 |
| **— ШОВ ДВИЖОК↔ПЛАТФОРМА: деньги и механизмы (D39.106/107 п.2) —** | | | | | |
| 136 | **Write-ahead intent + состояние `uncertain`-эскроу + `closing`**: холд НЕ освобождается по выходу юнита (сигнал обгоняет денежные события); spend не постится без свидетельства провайдера; расход сверх холда — полной суммой, превышение явной строкой убытка | платформа/бэкенд | скоро (промты по команде владельца) | стройка по research/25 | D39.106 |
| 137 | **Ночная сверка расходов с данными провайдера** (в движок цены входят float64 по ручной таблице `ledger/pricing.go` — систематика процентная; сверка приоритетнее споров об округлении) | платформа | когда-нибудь (до первого платного пользователя) | стройка по research/25 | D39.106 |
| **— НАХОДКИ ПРИЁМКИ ЭКСПОВ 18–20 (D39.108) —** | | | | | |
| 141 | **ОСТАТОК — работа В ДЕТЕКТОРЕ, и она НЕ про потерю текста.** ⚠ **Дыра, которой строка была заведена, ЗАКРЫТА лендингом D39.164:** сноска с ханьцзы («`[1] 蛊真人 — название романа.`») мимо детектора примечаний проходит по-прежнему, но поднимает класс `CJKLeak`, он `CosmeticOnly` (`backend/internal/checks/sanitizer.go:161-163`), юнит уходит `sanitizer_stripped` — и маркер дыры выдачи, заведённый паком «тихая порча», для НЕГО правдив. То есть читатель дыру ВИДИТ. Осталось: сноска БЕЗ ханьцзы («`[1] Название романа.`») не поднимает ни одного класса (замер сессии: `total=0`) и едет как есть — но текста при этом НЕ теряет, это лишняя добавка, а не дыра, и маркер на ней ДЕЗИНФОРМИРОВАЛ бы. Ловля таких сносок — правка самого детектора, отдельный предмет | бэкенд | когда-нибудь | правка детектора + тест | D39.108 (приёмка 20); половина закрыта D39.164 |
| 142 | **Механизм «гейты флагают → точечная починка по флагу» как прод-путь**: exp20 §3.3 — $0.0002/дефект, 12/12 (при ИДЕАЛЬНОЙ детекции); механизм конкурентов (research/22:179), у нас петля пака-16 за `enabled:false` (строка 13); детекторы «выдуманное слово»/«инверсия» прототипированы эксп-21. **ДИСПОЗИЦИЯ D39.117:** ОТКЛОНЁН как замена редактора (`C2/A_law` −3.75 Holm 0.0006; «$0.0002 чинит всё» мерилось при идеальных флагах и при реальной детекции пало), ПРИНЯТ формой «механический ПРЕ-ГЕЙТ перед редактором» — брак 5 клеток против 10/23 при половинной цене ($0.00298/$0.00602); ремонт ТОЛЬКО с банком (без банка ломает канон 0.917→0.895) | владелец → бэкенд | скоро (форма решена D39.117; ⚠ **порядок задан D39.190 п.3 — стройка ПОСЛЕ шагов 0–1 полигона**, а не по первой свободной смене) | бэкенд-промт | D39.108, **D39.117**, D39.190 п.3 |
| 143 | **Абсорбция норматива судейства в `09-pilot-protocol.md`**: разброс инструмента ДО замера · объявленный порог различимости · MQM-lite/error-span первичен, pairwise только для стиля · декой обязателен · запрет судьи семейства жильца арма | полигон/оркестратор | скоро ($0) | правка дока | D39.108, exp20 §7 |
| 144 | **Вахта: grok `reasoning_tokens` ВНЕ `completion_tokens`** — формула цены харнессов может недосчитывать (до $0.0325 на exp20); вендор-сверка биллинга xAI при следующем прогоне с grok | полигон | когда-нибудь (следующий xAI-прогон) | вендор-чек | D39.108 (приёмка) |
| 146 | **Два техдолга движка без строки трекера** (свип 08.08): `prices_checked` (120 д) гейтит read-only `report` и $0-resume — свежесть цен проверять только на ПЛАТНОМ пути (`docs/architecture/03-implementation-notes.md:114`; ⚠ адрес испр. 10.09 — прежний `:244` мёртв, в файле 115 строк) · `cache_ttl` ↔ `cache_write_per_m`: ⚠ **испр. 10.09:** цена записи в кэш НЕ ЗАДАНА вовсе — `cache_write_per_m` встречается в `backend/configs/models.yaml` 11 раз и ненулевых среди них **0** (контроль: `attempt_s` — 8 вхождений); премия за длинный TTL антропиковская, а провайдера этого вида в конфиге нет ⇒ долг не может сработать, пока не появится провайдер с платной записью (`docs/architecture/03-implementation-notes.md:115`; прежний адрес `:246` мёртв). Оба жили только в справочнике якорей, то есть вне единственного трекера · **приёмка D39.134:** ценовой гейт держит и ДЕТЕКТОР самолечения деплоя — на стенде с протухшими ценами `status` даёт 10, а не 13, и цикл «поймал 13 → migrate → повтор» не наступает | бэкенд | когда-нибудь | малое касание | свип доков 08.08, D39.134 |
| 147 | **Транспортные частичные из research/21 без носителя** (свип 08.08): п.16 HTTP/1.1-escape на последней попытке как ДИАГНОСТИКА тихого усечения 2–8k [PARTIAL, GATED] · п.17 assistant-prefill continuation на `finish=length` вместо ре-рана всего вызова [PARTIAL, DEFER]. Оба помечены в ресёрче как отложенные и ни в одной строке трекера не появились | бэкенд/полигон | когда-нибудь | замер → решение | свип доков 08.08, research/21 §16–17 |
| 150 | **Sol-арбитраж — внешний контур вместо слепого чтения владельца**: пере-суд расходящихся контрастов эксп-21 (`A/F`: luna +0.84 против gemini +3.03 — расхождение 14 sd шума судьи-замены) и слепых пар эксп-22 руками владельца через подписку (третье семейство, high reasoning); пакеты готовит эксп-22 Ф0.4 (слепые метки · оба порядка · декой), транскрипты персистятся как голоса внешнего судьи; luna-клетки Sol не судит (своё семейство) | владелец + полигон | скоро (пакет арбитража — из существующего сырья) | эксп-22 Ф0.4 + руки владельца | **D39.117** |
| 151 | **Отказной режим связки**: эхо-мина черновика воспроизводима на материале (глава 11 — 3/3 попыток; частота 31% на zh), связка покрыла 9/10 подряд идущих глав против 10/10 у однопроходки — единственный довод ПРОТИВ связки во всём эксп-21; движку нужен fallback при невозможности годного черновика (вариация ре-гена · эскалация модели черновика · деградация в однопроходку) | владелец → бэкенд | когда-нибудь (до МАСШТАБА) | СТОП-решение | **D39.117**, exp21 §14 |
| 152 | **Слипание абзацев — слепое пятно детерминированного контура**: батарея на тех же текстах даёт ДРУГОЙ порядок армов (`D` — худший по судье — лучший по правилам), расхождение локализовано в слипании, которого не проверяет ни одно правило; правило в батарею полигона + кандидат в гейты движка | бэкенд/полигон | когда-нибудь | малое касание + тест | **D39.117**, exp21 §13 |
| 153 | **Чистый контраст мандата перевёрстки**: `D/D_` загрязнён (объём промта ×1.92 + вёрсточная строка + правило чэнъюй); уравненные промты и пере-гон ≈$0.35; по грязному контрасту мандат ВРЕДИТ по оси ФОРМА (−1.09 из −3.31 `D/A`) | полигон | когда-нибудь (опция эксп-22 Ф3 — реши сессия) | замер | **D39.117**, exp21 §16.3 |
| **— ХВОСТЫ ФИКС-ПАКА БАНКА (D39.118) —** | | | | | |
| 154 | **Одноруновая голова семьи** (`蛊`/`转`/`窍` едет в отдельном вызове от 12 своих поверхностей — якорь семьи обязан быть ≥2 рун) — включается ОДНОЙ строкой данных `family_containment_runes han 1`, Go не трогается; не включена: цена в размере юнитов не замерена | бэкенд | скоро — ✅ **ГЕЙТ СНЯТ 05.09: поле ПРИЕХАЛО.** Манифест публикует размер юнита в знаках — `source_chars` (плюс раздельно плотные/разрежённые), лендинг `81a89e9`, акт D39.206, **аддитивно, версию манифеста не двигало**. ⇒ «решение уровня ноты» больше не нужно, замер берётся. Ниже — археология гейта. ⚠ **ГЕЙТ ПАЛ И ОКАЗАЛСЯ НЕДОСТИЖИМ** (испр. 02.09, переведена из БЛИЖНЕГО веса): первый холодный прогон отработал 31.08, и он же показал, что назначенный замер этим путём НЕ БЕРЁТСЯ — манифест не публикует размеров юнитов В ЗНАКАХ вовсе (юнит несёт `id`/`first_*`, не длину). ⚠ Настоящее предусловие — новое поле контракта манифеста, то есть решение УРОВНЯ НОТЫ (`manifest_version`), а не строки бэклога: до него строка не гейчена ничем достижимым | строка данных по замеру | **D39.118**, отчёт §5 |
| 155 | **Скрипт-слепой резолв семей/серий**: han-правила режут кану и хангыль (синтетика: 24 катаканных имени с общим アリ → батч 8036 рун при бюджете 6000); живого вреда нет — пары в репо нет; та же слепота у серий уже в HEAD | бэкенд | когда-нибудь (преп ja→ru, с 81/120) | ja-пак | **D39.118**, отчёт §5 |
| 156 | **`banknote_truncated` — ПОЛ, а не счёт**: обрыв, срезавший сам разделитель, флага не даёт; буквальный фикс зажёг бы колонку на каждом обрыве в прогонах без канала — нужен гейт по `Gates.Banknote.Enabled` | бэкенд | когда-нибудь | малое касание | **D39.118**, отчёт §5 |
| 157 | **Пере-подтвердить `family_max_members=24` и `families_held`** на длинной книге (24 калиброван на дистилляции в 150 поверхностей; кап эмиссии 200 + реверс-секция дают другой список); если `families_held` велик — ослабить гард до «родство по любому члену юнита» вместо «по корню серии» | бэкенд | когда-нибудь — ⚠ **ГЕЙТ ПАЛ 31.08, ответ ОТРИЦАТЕЛЬНЫЙ** (испр. 02.09, переведена из БЛИЖНЕГО веса): прогон дал `families_held=0`, значит ослаблять гард не нужно. ⚠ Но замерено на ДЕСЯТИГЛАВНОЙ книге, а строка требует пере-подтверждения на ДЛИННОЙ — вывод действителен «на 10 главах» и протухнет на первой длинной книге. Указатель «§6 отчёта» заменён на греп-форму: `archive/reports/COLDRUN_V16_REPORT_2026-08-31.md`, греп `families_held` | замер → решение | **D39.118**, отчёт §7 п.7 |
| 158 | **Уверенность не гейтится данными пары**: канал снимает третью колонку у любой пары, чей промпт её попросит; у пары с ДВУХпольным промптом узкий риск «Пик␣␣99» (число ≤100 за двойным пробелом уедет в conf); при нужде — дата-декларация пары | бэкенд | когда-нибудь | дата-декларация | **D39.118**, отчёт §4 п.6/§7 п.8 |
| 159 | **Durable-имена эвиктнутых** (`retrieval_state.evicted_detail` = миграция; сегодня лог, и приёмка ратифицировала «этого достаточно») — заводить только при доказанной потребности, одним касанием с идемпотентностью миграций 49а | бэкенд | когда-нибудь (гейт: доказанная потребность) | миграция с 49а | **D39.118**, отчёт §7 п.2 |
| 160 | **Структура глав, Этап 0** ($0, wire-нейтрально): `titleRaw` в манифест (subtitle добывается `matchHeaderLine` и ПОНИЖАЕТСЯ в тело прозы (испр. D39.125), а не выбрасывается) + provenance у heading + тип chapter/fragment + вердикт структуры (бамп manifestVersion) · **дыра Р6**: projectRebill слеп к контент/позиционной оси (rebill.go:33-36) — ревизия структуры перекупила бы хвост МОЛЧА, закрыть read-path-расширением · слой пользовательских правок отдельным сайдкаром · **зонная половинка темы:** Ф-30 фронта / В-4 владельца (глава без заголовка на экране — метка из ДАННЫХ, К-3) ждут ровно эту строку; `heading` манифеста до неё = ВРЕМЕННЫЙ рендер движка (D39.122 п.2д) | бэкенд | скоро (ГЕЙТ ПАЛ словом владельца 15.08, D39.136 п.3: ставится ближайшим бэкенд-паком с мандатом максимального качества; ⚠ **испр. 05.09: блокер 236 МЁРТВ** — «писатель книги» закрыт D39.175 (30.08), и очередь его больше не держит. Живая диспозиция другая: **строка отложена ПОРЯДКОМ — D39.190 п.2**, то есть ждёт своего окна, а не предшественника; тесты структуры глав — узлом будущего холодного прогона) | пак | research/27 §6 Этап 0, D39.122 п.4, D39.136 |
| 161 | **Структура глав, Этап 1 «большой перекрой»** (единственное дешёвое resnapshot-окно — пока платная книга одна, ДО интейка): IR + формато-адаптеры (epub nav/NCX, fb2) + индуктор с валидаторами и вердиктами + третий версионный план паттернов (не в снапшот волн) + развязка чанкера от глав + банк-окна на chapter-ID + контент-адресуемый resume (долг D15.2) + формула Chapter.ID «окно» + роль title (мини-сессия названий: редакторский слот · инъекция банка · двухфазно вокруг подписи) + аддитивное расширение контракта 14; жизненный цикл дерева — research/27 §3а (решение владельца 09.08) | бэкенд (+фронт/платформа аддитивно) | скоро (постановка санкционирована D39.136 п.3: СНАЧАЛА дизайн-пак с мандатом максимального качества, стройка после ратификации дизайна; ⚠ дешёвое окно закрывается первой книгой внешнего пользователя) | дизайн-пак → ратификация → пак(и) | research/27 §3/§5/§6, D39.136 |
| 162 | **Структура глав, Этап 2**: in-band метки глав в потоке перевода (третий эшелон детекта + коррекция структуры по ходу черновой волны, §3а п.3) + канон-гейт названий ($0) + миграционные карты якорей (same/moved/split/merged/gone/new) + калибровочный корпус детекта в CI ⚠ Форма владельца 30.08: черновая модель отвечает МЕТАДАТОЙ в конец ответа, если посчитала строку фрагмента авторской разметкой главы — разметка едет попутно с черновиком без отдельного платного прохода; доверие — через фиксацию в манифесте и подтверждение спорных. | бэкенд + полигон | когда-нибудь (после Этапа 1) | пак + корпус | research/27 §5/§6 Этап 2 |
| 163 | **Версии модулей x/text|x/net двигают нарезку МИМО всех ключей** (NFC в NormalizeSource — таблицы модуля, не тулчейна; epub-токенайзер): бамп `go get -u` тихо меняет нарезку при свежих на вид манифесте/чекпойнтах/снапшоте — класс всей чекпойнт-плоскости, унаследован манифестом; вплести версии модулей (debug.ReadBuildInfo) в NormVersion/chunkerVersion либо явный запрет бампа без `--resnapshot` | бэкенд | когда-нибудь (до второго прогона книги) | малое касание | **D39.122**, приёмка (охотник №1) |
| 164 | **Rebill-проекция `status` с nil baseMemory завышает RebillUSD**: read-путь не материализует base-банк → renderedContentHashes даёт пустую инъекцию → repin недоопознан, строка считается re-pay (консервативная сторона, но противоречит комменту «status can never quote a different number than translate»); материализовать base-банк на read-пути либо смягчить клейм | бэкенд | когда-нибудь | малое касание | **D39.122**, приёмка (охотник №1); preexisting |
| 168 | **Состав волн пайплайна = пар-конфиг (данные), не общий хардкод**: вопрос владельца 10.08 «нормально ли под китайский строить весь бэкенд и конфиги?» — жильцы ролей и промпты уже конфиг/langpacks, но ТОПОЛОГИЯ волн (перепис · точечный edit-контур · без второго прохода) одна на всех пар; если фаза Д покажет разных победителей по парам (H-3/H-4: en-черновик+edit против zh-связки), состав волн уезжает в пар-конфиг данными; ревью-вопрос общности §0 `12-go-style-notes.md` | бэкенд | когда-нибудь (после данных фазы Д) | замер (фаза Д) → решение владельца → малое касание | слово владельца 10.08, промт фазы Д |
| 170 | **`tmctl init` — движок сам заводит книгу** (форма В развилки интейка): платформа зовёт $0-команду, движок пишет СВОЙ `book.yaml` — требования к полям живут там же, где проверяются (`config/book.go`); до неё бета живёт формой Б (рендер из деплой-шаблона платформой при создании книги, ратификация D39.130) | бэкенд | когда-нибудь (после беты формы Б) | малый пак | приёмка P5, **D39.130** |
| 172 | **Остаток после пере-пина DeepSeek (пин ИСПОЛНЕН и ПРИНЯТ — D39.137, `76049bb`):** (а) **схемное решение владельца по time-based** — доклад §5 отчёта вендор-сессии (рекомендация: пик оставить; scheduler-вариант строки 60 не начинать до ответа вендора «по какой отметке времени тарифицируется вызов» — вендором НЕ задокументировано — и замера доли пика; дешёвый рычаг: операционное правило «прогоны не стартуют в 01–04/06–10 UTC» — почти всё ×2 без строчки Go; гибрид «резерв пиком, сеттл по окну факта» назван) · (б) пере-калибровка ставки $0.03/глава (166/П-10; множитель счёта замерен) · (в) exp08 v3 (85) обязателен до budget_usd · (г) **вахта весов V4-Pro-0813** (класс D39.61): риг готов, порог ратифицированной ВЫБОРОЧНОЙ формы («≥4/5 прогонов N=5 достигают 6/6», D39.136 п.6б) **в риге ИСПОЛНЕН** паком честности — арифметика вынесена в `live_reprobe_threshold_test.go`, сам риг применяет её же. ⚠ **ИМЯ СТРОКИ ВВОДИТ В ЗАБЛУЖДЕНИЕ (испр. №18 17.08, сверено кодом):** названный риг меряет роль КЛАССИФИКАТОРА, а она ходит на **flash** (стендовый `pipeline.yaml:64` + артефакт прошлого прогона `model = deepseek-v4-flash`), тогда как сменившиеся веса — у **pro**, а pro у нас = РЕДАКТОР (`configs/pipeline-c1.yaml:62,76`). Владелец 17.08 санкционировал ТОЛЬКО вариант (а) — пере-съём классификаторного гейта, потолок $0.20, исполняется п.5 пака честности. **По этому прогону строку НЕ закрывать:** вопрос «сменились ли веса редактора» остаётся открытым, дешёвый вход к нему — данные фазы Д, где pro гоняется именно редактором (спросить полигон прежде, чем покупать новый замер) | владелец → бэкенд/полигон | скоро (схема — на владельце; вахта — после 16.08) | СТОП-решение (схема) + замер (вахта) | вендор 13.08, **D39.137**, строка 60, D30.4 |
| 180 | **`prices_checked` — одно поле на ВСЮ таблицу цен** (находка вендор-сессии, D39.137): бамп по факт-чеку одного вендора сдвинул 120-дневный гейт свежести остальным семи моделям (дедлайн уехал ~07.11→~13.12); лечение — пер-модельная дата проверки (правка схемы) ЛИБО ре-чек остальных вендоров отдельным заходом до исходного дедлайна | бэкенд | когда-нибудь (ре-чек вендоров — до ~07.11) | малое касание / вендор-заход | D39.137, отчёт §7.1 |
| 182 | **Wire-батч перед добором идеала — КОПИТЬ и вносить ОДНИМ касанием** (каждая правка двигает RequestHash / `memory_version` / снапшот = перекупка волн; дриблить по одной = платить пере-снапшот несколько раз): 46 экран цели (+предпосылка 113 фикстура) · 134 инжект-заголовки (гейт пал D39.108) · 131 кап инъекции · 140 банковый контур в shipping (СТОП-решение) · 105(а) вердикт-половина классификатора · 130-остаток (мердж авто-банка, гейт WARN второго прогона) · 14 ё-фолд (носитель «следующий пак общности») · **119+124(+115 пер-парный хеш EmbeddedVersion) — ОДНИМ дизайн-паком** (строка 124 требует принимать целиком; сверено кодом: `cutTag` фолдит `chunkerVersion`/`EmbeddedVersion`/`NormVersion` — `manifest.go:160-169`); вне батча свободен только 118 (tools/go.mod). Состав — аудит корпуса 15.08 (archive/reports/CORPUS_AUDIT_2026-08-15.md §В.г) ⚠ **испр. 07.09: ссылка на «105(а)» ПРОТУХЛА** — строки 105 в живом трекере нет (греп `^| 105 |` = 0 при 249 рядах), она закрыта `D39.200`; наружный состав окна читать без неё | оркестратор → бэкенд | скоро (собрать к ратификации фазы Д; вносить перед первым платным прогоном добора идеала) ⚠ **СОСТАВ ОКНА 04.09 (D39.190 п.4 ратифицировал пере-снапшот единым актом):** в выданный вайр-батч вошли **210 · 113→46 · 134 · 140 · 184(а)**; СНАРУЖИ остались и это сказано вслух, а не умолчано — **131** (кап инъекции: своя цена и своё СТОП-решение, и сама строка велит «пере-замерить ПОСЛЕ 134», то есть её очередь следующая), **105(а)** и **14** (ждут следующего окна), **119+124+115** (только одним дизайн-паком), **160** (бампает `manifestVersion`, отложена ПОРЯДКОМ — D39.190 п.2), **142** (после шагов 0–1 полигона — D39.190 п.3). | координационная строка → промт(ы) батча | аудит 15.08, D39.134/136/137 |
| 173 | **`backupStamp` секундной точности**: два `translate` в одну секунду дают коллизию имени бэкапа и exit 1, маскируя класс «проект занят» (12) — метка до наносекунд/uniquify либо распознавать коллизию явно; преexisting, вскрыт ревью эмиттер-пака | бэкенд | когда-нибудь | малое касание | приёмка D39.131 |
| 175 | **Деплой движка «в полёте» — ДАЛЬНИЙ ОСТАТОК** (ближняя половина ИСПОЛНЕНА паком migrate — D39.134; правило свипа и settle запиненным бинарём — аддендум P6, D39.132). Остаток: (а) при СЛЕДУЮЩЕМ бампе схемы проставить в файл книги `application_id` + `min_reader_version` — данные-задел под окно совместимости, ~0 логики; (б) GC бинарей: удалять не пиненные ни одной незакрытой попыткой, последние 2–3 релиза держать для отката; (в) окно совместимости читателей / пин уровня книги — строить ТОЛЬКО по триггерам: много тенантов · бампы схемы еженедельно+ · потребители `status` кроме платформы. Археология захода — ресёрч 14.08 (вывод: exact-match читателей на деньгах = осознанный fail-closed, корень не выдёргивать, приделать дверь) | платформа/бэкенд | когда-нибудь (по названным триггерам; (а) — попутно первым бампом схемы) | данные-задел + малые касания | владелец 14.08, ресёрч 14.08, строка 139, D39.134 |
| 177 | **Гигиена restore point `tmctl migrate`** (находки приёмки ВНЕ карты отчёта; фикс-лист ФМ — запись приёмки 15.08, слайс [archive/PROGRESS-2026-08-14-15.md](archive/PROGRESS-2026-08-14-15.md)): ретрай в ту же секунду после сорванного шага = exit 1 «backup already exists» вне полосы — ровно на цикле самолечения платформы · kill -9 посреди шва оставляет РВАНУЮ копию под легитимным именем (ручной откат по ней = потеря данных; лечение — temp+rename) · копии restore point не подчищаются (повтор после срыва копит их) · SIGINT/SIGTERM в migrate не прерывают (ctx не доезжает) · комментарий migrate.go «no money touched» на no-op неверен (recovery зануляет leftover reserved) | бэкенд | когда-нибудь (следующее касание migrate/бэкапа) | малое касание + тесты | D39.134, приёмка №17 |
| 178 | **Калибровка `sense` банка** — слово владельца 15.08 (D39.136 п.4б): смысл должен быть «ёмкий и достаточный на всю книгу, но не слишком подробный» (образец: «спутница главного героя»); сейчас возможно КОРОТКОВАТ; замер длины/достаточности на подписанном банке → правка промптов банкноты/терминолога (двигает провод — цену назвать при внесении) | бэкенд/полигон | когда-нибудь (касание банка) | замер → правка промптов | D39.136 п.4б |
| 183 | **Батч 0.3.0 — ОТРАБОТАН ЦЕЛИКОМ** (батч D39.142 + дофикс D39.143, `86720cf`; промт в архиве). ⚠ Номер канона в этой строке НЕ держим — канон ушёл на **0.9.0** (D39.180), лента миноров — в шапке. **ЖИВОЙ ОСТАТОК ОДИН — (б):** зеркало `frontend/docs/api-contract/` + типы + моки + гейт утечки, первое касание фронта при разморозке; расхождение канона и зеркала ВРЕМЕННО ратифицировано D39.142 п.5. Пункты (а) и (в) СНЯТЫ (D39.153; D39.144 п.4)| оркестратор ⚠ **ОЦЕНКА «ПЕРВОГО КАСАНИЯ» ЗАНИЖЕНА — измерено 05.09 веером.** Записанное «синк зеркала + перегенерация типов ОДНОЙ командой» неверно по ОБЪЁМУ: перегенерация — одна команда, но она вскрывает переписывание слоя данных. Замерено: 16 операций против 21; 40 новых имён схем в каноне и 10 МЁРТВЫХ в зеркале, на которые `src` ссылается 31 раз; две ручки, которых платформа не отдаёт вовсе. Плюс гейт версии у фронта читает СВОЁ зеркало (строка 268), то есть отставание он не увидит и после синка. | скоро (остаток = только (б) зеркало фронта при разморозке) | P7 → фронт при разморозке | D39.138, D39.142, **D39.143** |
| 185 | **Дописывание глав в ТЕКУЩУЮ книгу («костылей не будет»):** форма `POST /books/{id}/parts` + ответ «сколько глав добавится, что сдвинется и почём» ДО подтверждения; экономика уже позволяет В КОНЕЦ за ~$0.02 (ключ вызова позиционный, исходник вне снапшота), вставка в середину = МОЛЧАЛИВАЯ перекупка хвоста ~$9–11/500 глав — движковый гейт против молчания ОБЯЗАТЕЛЕН (родня дыры Р6 строки 160); платформа второй файл принять не может (re-parse нет); ja-мина: новый ruby-алиас двигает `memory_version` → снапшот (громкий `--resnapshot`, уточнение приёмки); полный $0-резюм хвоста — предусловие D15.2 (строка 49) | бэкенд+платформа+контракт | когда-нибудь (вместе со строками 160–162 — дизайн в паке 161) | дизайн-пак 161 → стройка | research/28 Б-19а/§8 п.7, D39.138 п.2г |
| 186 | **Сеть: перечитывания ничем не удешевлены** (замер 16.08: дерево 2283 глав = 250 КБ на каждый кадр `status`, фокус-рефетч 12 вкладок = 562 КБ — самый частый трафик порождает переключение вкладок, не пайплайн; гипотетический кадр банка на главу = 372 МБ/прогон; сжатия/ETag/304 нет НИГДЕ): план по эффекту — (1) gzip на текстовых ответах, НЕ на SSE (2) `ETag`/`If-None-Match`→304 на списочных GET (3) скоуп в кадре (id+версия, БЕЗ текста) (4) дельта-чтение банка/замечаний `?after_version=` (5) `staleTime` у клиента; шаги 1–2 — платформа (её же `platform/docs/PLATFORM_DIRECTION.md`, греп `Условные запросы`), семантика — в спеку батчем 183; транспорт НЕ менять (решение владельца по §5б) ⚠ **ШАГИ 1–2 ПОСТРОЕНЫ И ЗАЛЕНДЕНЫ P7 (D39.153)** — gzip на JSON и НЕ на SSE + `ETag`/`If-None-Match`→`304` на коллекциях, карточке книги и `/capabilities` — **и ПЕРЕ-ПРОВЕРЕНЫ ЗАМЕРОМ 28.08** (воркфлоу-ревью P9 на стенде, приёмка D39.162): банк 437 Б холодным → повтор с `If-None-Match` даёт **304 / 0 Б**; юниты главы 3008 Б → **740 Б gzip (×4.1)**; ниже порога 1024 Б gzip честно НЕ применяется; SSE корректно не сжимается. Остаток — шаги 3–5 | платформа (+контракт/фронт) | скоро (остаток: шаги 3–5) | мидлварь/edge платформы + батч 183 + разморозка фронта | research/28 §5б/Б-11а, D39.138 п.2д |
| 188 | **Носитель события «ре-проба 74»** (аудит D39.140: событие ждали строки 5 · 36б · 44 и шапка CURRENT-STATE, а владельца у него не было — строка 74 закрыта D39.91): дешёвая ре-проба flash при ПЕРВОМ платном прогоне добора идеала (D39.63 п.4) + слоты, подвешенные на неё: рецензент спорных кластеров банка (остаток 5) · замер второго мнения (36б) · выбор числа флора (44, после одобренной мини-пробы) · итерация №2 редакторов (D39.22/63) · выборочный порог 116 в риге (дописка 172-г) · решение о включении ре-гена перед эскалацией (экс-77, D39.64: «включение — решением при ре-пробе 74»; ручка построена, мертва во всех конфигах, ре-ген ≈7.6× дешевле эскалации) | полигон/бэкенд | скоро (гейт добора идеала — первый платный прогон) | проб-пакет при первом платном прогоне → решения по слотам | D39.63 п.4, D39.91, аудит D39.140 |
| 189 | **Мультиязычность фраз ЛОГОВ и АРТЕФАКТОВ движка — вторая половина слова владельца 15.08** (D39.136 п.4а «фразы ВСЕХ зон»; первая половина — юзерский провод — решена ревью 28 Б-1/батчем 183): фразы в `bank-stop`/статусных артефактах и логи движка вне контракта, носителя не было (research/28 §6, строка Ф-61: «носителя назвать отдельно» — аудит D39.140 подтвердил: не назван); разобрать, что из этого читает ПОЛЬЗОВАТЕЛЬ (артефакты банка — да, через проекцию платформы) и что оператор (логи — легитимно английские) | бэкенд | когда-нибудь (до второй локали интерфейса) | разбор → точечная правка | research/28 §6, D39.136 п.4а, аудит D39.140 |
| 190 | **Кросс-СЕМЕЙНЫЙ проход контракт-ревью** (не-Claude опровергатели; буква заказа владельца D39.136 п.5 «кросс-модели», исполненная в ревью только кросс-тирами Claude — ограничение честно заявлено research/28 §7/§10): проверка вердиктов доклада моделью другого семейства полигонным контуром; жила только колонкой «ЖИВОЕ» реестра нот — аудит D39.140 дал строку | полигон | когда-нибудь (после фазы Д; перед лендингом батча 183 — если владелец захочет второй рубеж) | полигон-слот с внешним провайдером | research/28 §10, аудит D39.140 |
| 192 | **Пост-ридинговый цикл правок банка — «наше подумать» владельца 16.08 (записано, чтобы не потерялось; точную механику «не продумал ещё никто и нигде» — его слово).** UX-модель целиком: юзер нажал перевод → черновая волна + майнинг вместе → на фронте появляются ЧЕРНОВОЙ перевод и ЧЕРНОВОЙ банк · подписывается ВЕСЬ банк одним ОК (D39.144) → перевод уходит в доработку · дальше юзер ЧИТАЕТ, и его опции: поправить термин в банке ЛИБО добавить свой → кнопка «поправить» → пере-генерация, которая по ВХОЖДЕНИЯМ правит запрошенное. Открытые вопросы дизайна: что именно перегенерируется (вхождения ключа · затронутые юниты · со сметой и согласием?) · нужен ли движковый ТОЧЕЧНЫЙ РЕДАКТОР (полигон над этим работает — фаза Д) · форма в контракте (ручки нет) и на экране. Уже лежит под ногами: движковый re-edit по ключу банка со сметой и $0-пере-пином ПОСТРОЕН (строка 49: `repin.go`/`rebill.go`, D39.42 п.5/D39.45) · пометка неподписанных строк · дельта-чтение банка (0.3.0). НЕ проектировать до полигонных итогов; затем дизайн-пак на их результатах → слово владельца → стройка | владелец+полигон → бэкенд/контракт/фронт | когда-нибудь (триггер: итоги фазы Д по точечному редактору) | дизайн-пак после полигона → слово владельца → стройка | слово владельца 16.08, D39.144 п.1 |
| 195 | **ОСЬ «идентичность оплаченной работы» — переселена в дизайн-пак 124 (решение владельца 17.08, вариант А; D39.151).** Как САМОСТОЯТЕЛЬНАЯ стройка ЗАКРЫТА: маркер `snapshot_id`/`run_id` на `checkpoints` отдельной колонкой НЕ строится. Причина — внешний разбор опроверг посылку «колонка = тождество»: $0-пере-пин законно переносит строку на новый снапшот со СТАРОЙ ценой (`stagerun.go:96-105`, сверено оркестратором), у старых чекпоинтов бэкфилла нет вовсе (`jobs.snapshot_id` перезаписывается каждым ре-снапшотом) ⇒ вывод-обход остаётся в коде навсегда как legacy-ветка, а колонка лишь добавляет рядом второй путь. **Настоящий корень глубже:** в сторе нет первоклассной связи «строка диспозиции ↔ вызовы, которые её оплатили»; снапшот на чекпоинте — прокси, а не примитив. ⚠ Границы семьи сужены тем же разбором: 49 и 195 — про РАЗНОЕ (49 = когда переиспользование законно, 195 = как честно посчитать будущую покупку), общий у них субстрат, не задача; из 124 родня только ось (в). **Срочности нет:** под контрактом D39.150 («направление ошибки, не точность») ни один исход не занижает молча — недостача несётся историческими деньгами С РАСКРЫТИЕМ, пойманный откат называется вслух. Остаточные нарушения контракта чинятся БЕЗ схемы: 197 и 194 | бэкенд | когда-нибудь (гейт — триггеры пака 124: дописывание глав 185 · МАСШТАБ · первый внешний потребитель числа) | ось дизайн-пака 124 | **D39.151**, внешний разбор 17.08 |
| 196 | **Остаточный класс строки 176: неперехватываемые `fatal error` Go** (конкурентная запись в map, OOM, стек-оверфлоу) по-прежнему дают exit 2, то есть читаются платформой как «завершено с флагами» — `recover` их не ловит по устройству языка (подтверждено линзой шва исполнением). Строка 176 закрыта для ПАНИК, не для fatal. Лечение — вне exit-контракта: сторож процесса у платформы либо маркер живости в артефакте прогона | бэкенд/платформа | когда-нибудь | отдельное решение | приёмка №18, линза шва |
| 197 | **Фикс-лист приёмки пака честности ФЧ-1…ФЧ-8** — восемь пунктов класса «заявленное не прибито» и «текст обещает больше числа», ни один не блокировал лендинг. **Тело списка дословно, с весами и с секцией «что НЕ проверено», — [archive/PROGRESS-2026-08-17.md](archive/PROGRESS-2026-08-17.md), запись приёмки №18** (D39.149). Здесь держим только ратифицированное: **ФЧ-5 РЕШЁН владельцем 17.08 (D39.150): прайсить по модели, которую стадия резолвит СЕЙЧАС, + округление вверх и оговорка в тексте согласия.** Носителя-сессии НЕТ — по слову владельца 17.08 пока только записано | бэкенд | скоро (следующее касание денежного пути; ФЧ-5 обязателен до первого пере-прогона со сменой модели) ⚠ **СОСТАВ ПЕРЕ-СКОУПЛЕН 04.09:** ФЧ-1/ФЧ-4/ФЧ-5 закрыты паком «число согласия» (D39.187); **ФЧ-6 по коду выглядит ЗАКРЫТЫМ** — отказ проекции репортится базисом, отчёт не валится (`backend/internal/pipeline/status.go`, греп `RebillBasisFailed`); **ФЧ-7 отдан проверкой** в вайр-батч (воспроизвести панику поверх пойманного потолка, чинить только если воспроизводится); **ФЧ-2/ФЧ-3/ФЧ-8 НЕ ПРОВЕРЕНЫ никем** и остаются живым остатком строки. | дофикс-промт ЛИБО попутно ближайшим паком | **D39.149**, **D39.150** |
| 198 | **Апгрейд движка стирает замечания и счётчики книги БЕЗВОЗВРАТНО — композиция двух половин, каждая известна по отдельности** (приёмка P7, линза «вне карты», обе половины пере-прочитаны оркестратором). Платформа при смене `manifest_key` сносит ВСЕ `unit_resolutions` книги (`platform/internal/pgstore/readmodel.go:164-165`), рассчитывая, что поток их пере-наполнит; движок анонсирует юнит РОВНО ОДИН РАЗ за жизнь книги — ключ `unit::::` БЕЗ метки нарезки (`backend/internal/pipeline/events.go:399-400`), а леджер анонсов переживает прогоны (`backend/internal/store/outbox.go:96` «already announced… by one that ran before it») ⇒ совпавшие координаты не переанонсируются НИКОГДА. Обостряется порядком: долг на материализацию ставится только на ГРАНИЦАХ работы, поэтому первая зачистка после апгрейда случается в КОНЦЕ первого пост-апгрейдного прогона и сносит замечания ТОГО ЖЕ прогона, за который заплачено. Следствия на проводе: «0 из N» на переведённой книге навсегда · шкала снова предлагает купить переведённое · замечания читателя исчезают. **Лечится с обеих сторон:** движковая половина — метка нарезки в ключе анонса (решение зоны движка), платформенная — не сносить вслепую либо восстанавливать из экспорта. ⚠ Гейт холодного прогона: смысл упражнения — гонять книгу против МЕНЯЮЩЕГОСЯ движка, то есть первый же апгрейд обнулит библиотеку | бэкенд + платформа | **скоро (до первого реального пользователя И до холодного прогона с апгрейдами)** | связка: решение по ключу анонса в движке → правка платформы | приёмка P7 (D39.153) |
| 201 | **Движковое «Глава N» доезжает читателю ВНУТРИ текста, обходя дисциплину `heading: null`** (линза шва P7, пере-прочитано оркестратором): `backend/internal/pipeline/export.go:58`=`ApplyHeading` (испр. оркестратором №20 30.08: якорь уезжал с `:230` и с `:266` — код растёт) приклеивает детерминированный порядковый к экспортному тексту первой юнит-главы (`ce.FinalText = chunk.ApplyHeading(...)`), колонка `Source` при этом остаётся heading-stripped. Платформа переносит обе как есть и честно отдаёт `heading: null` — то есть клиент нарисует СВОЙ порядковый на языке своего интерфейса над абзацем, который уже начинается с русского «Глава N», а исходная колонка соответствующего маркера не несёт: пара визуально рассинхронизирована на каждой первой главе. Конкретное следствие открытого К-2 контракта; родня движковой строки **160** (глава без заголовка) | бэкенд | когда-нибудь (с 160) | отдельное решение | приёмка P7 (D39.153) |
| 203 | **Хвосты контракта после синка 0.4.0 — ОТКРЫТ ОДИН ПУНКТ, остальное исполнено** (тела релеев — `platform/docs/archive/P7_ACCEPTANCE_HANDOFF_2026-08-17.md` §7; сюда переписан НЕ текст, а статус — один носитель на факт). **ИСПОЛНЕНЫ и сверены грепом при лендинге:** (а) минором 0.5.0 (D39.161) · (б) · (д) · (и) поле `stop_requested` (D39.152) · (л)(м)(н)(о) контрактной сессией — остаток по фразам Приложения А несёт строка **204** и лист владельца. **(г) наполовину** — `unspecified` ратифицирован в каноне (`docs/architecture/14-api-contract/openapi.yaml:2191`=`is reserved and is the server`), открыта только ГРАНИЦА ступеней замечаний (две ступени при девяти рангах движка); ⚠ её прежний носитель — строка 148 — СНЯТ 21.08 по слову владельца. **(з) СНЯТ как ратификация 22.08 сквозной трассировкой (разбор, на который ссылается строка 191):** конфликта моделей НЕТ — гейт движка проверяет полноту не ПОДПИСЕЙ, а ФАЙЛА решений, и ОДИН файл со всем банком его снимает (`loadMinedDelta` штампует только `Source`, `mining.go:855-867` → опущенный статус дефолтится в `approved`, `membank/memseed.go:130`=`status = "approved"` → `unsignedEngineSurfaces` выбрасывает лишь `Source=="mined" && Status!="approved"`, `mining.go:710-719`). Пере-диспозиция 27.08 (D39.158 п.7): движковый гейт полноты УСТРАНЁН, не обойдён; остаётся снять обход в платформе — одна боевая строка (`platform/internal/runs/spawn.go`, `--verify-bank` не передаётся на resume) плюс семь строк ставшего ложным обоснования, работа платформенного пака. **ОТКРЫТО РЕАЛЬНО — (к):** ключ `project_db` в `book.yaml`, договорить, кто им владеет: шаблон оператора его не содержит, движок делает необязательным. ⚠ Следствие «на штатном деплое банк не читается» ОПРОВЕРГНУТО живым кодом: путь публикует ДВИЖОК конвертом артефактов, пустой путь — ГРОМКИЙ отказ (`platform/internal/runner/artifacts.go:39`=`the engine published no bank read-out path`); остаток (к) чисто договорной| контракт/доки | скоро (следующее касание контракта) | контрактная сессия | приёмка P7 (D39.153) |
| 204 | **Движок не публикует причины флагов ДАННЫМИ — карта причин у платформы рукописная и расходится молча** (релей §7(в) хендоффа P7; зона платформы в чужой бэклог не пишет и просила строку сюда — `platform/docs/archive/platform-PROGRESS-P7.md:206`). Сегодня `platform/internal/ingest/notes.go` держит рукописную копию закрытого словаря ЧУЖОЙ зоны: причин движка **16** (испр. 05.09 — шестнадцатой приехала `off_target_lang` → `wrong_language` с минором 0.10.0; прежняя редакция говорила 15 и это ровно то расхождение, которое строка предсказывала) → коды замечаний контракта. Импортировать движок платформе нельзя (D39.85 — разные модули), поэтому расхождение появится молча в тот день, когда движок добавит причину: платформа отдаст `unspecified` и напишет ERROR в лог, то есть деградация честная, но карта протухнет незаметно. ⚠ **Правила заполнения контрактных фраз по этим причинам УЖЕ НАПИСАНЫ** и выводить их заново не надо — компаньон `14-api-contract/README.md`, греп `по ДОККОММЕНТУ` (фраза пишется по доккомменту `disposition.go`, а не по имени константы; класс 2 схлопывается в ОДИН код). Лечение: движок публикует свой словарь причин артефактом-данными (тем же классом, что манифест и сайдкары банка), платформа читает его вместо копии. ⚠ Класс: носителем был ТОЛЬКО регистр платформы (PD-246) — обязательство к ЧУЖОЙ зоне жило внутри зоны автора | бэкенд | когда-нибудь (со следующим касанием эмиссии флагов) | отдельное решение | приёмка P7 (D39.153), релей §7(в) |
| 207 | **Пол самосогласованности манифеста стоит только у материализатора, интейк тот же документ ПРИНИМАЕТ — и по такой книге можно ОПЛАТИТЬ прогон** (`PD-367`, вторая волна ревью P8-FIX). Манифест `{ChaptersTotal: 120, UnitsTotal: 400}` с пустым списком глав `Whole()` отвергает, а `books.Parse` заводит книгу `not_started` с `chapter_count=120` и пустым деревом; потолок считается ОТ `chapter_count`. **Очевидное лекарство опровергнуто исполнением самой зоной:** применить `Whole()` на интейке нельзя — вся батарея интейка ездит на манифестах без списка глав, контракт интейка это только счётчики. Значит решение не зонное: либо контракт интейка меняется, либо пол ставится в другом месте цепи | оркестратор → платформа | скоро | нужно решение (лекарство ломает запиненный контракт интейка) | D39.154 п.10, `PD-367` |
| 209 | **Риг живых проб не может залогировать тела запросов ни при каких env** (находка бэкенд-пака честности 17.08, оставшаяся без носителя до аудита доков 22.08): `LOG_LLM_BODIES=1`+`LOG_LEVEL=debug` объявлены носителем тел, но ключ читается из `obs.ReqInfo` контекста, а `live_reprobe_test.go` строит ctx БЕЗ `WithReqInfo` — гейт `obs/logging.go` не пропускает. Обход, которым пользовались: ручной дамп сообщений в файл. Цена — каждая живая проба, которой нужно прочитать провод глазами, платит за обход заново | бэкенд | когда-нибудь (следующее касание рига живых проб) | малое касание (`WithReqInfo` в риге) + пин | пак честности 17.08, вынесено аудитом доков 22.08 |
| 213 | **ОСТАТОК — одна строка в ДЕВ-пути: супервизор зашивает `"book.yaml"` мимо константы `ConfigFile`** (`platform/internal/ingest/supervisor.go:142`=`"status", "--config"`). ⚠ **ГЛАВНАЯ половина ЗАКРЫТА лендингом P9 (D39.162):** путь банк-экспорта берётся из конверта артефактов движка (`platform/internal/runner/artifacts.go:28-35`; пустой путь — ГРОМКИЙ отказ), нестрогий парс `book.yaml` и собственный `projectDB()` снесены. Осталась ровно та тривиальность, которую строка называла рядом с дефектом. ⚠ Пере-именование банк-экспорта в фикс-имя рядом с `events.jsonl` — ЛОМАЮЩЕЕ, его место в окне строки **161**, НЕ здесь | платформа | когда-нибудь (одна строка, следующим касанием зоны) | правка дев-супервизора | консилиум шва 22.08; главная половина — D39.162 |
| 214 | **Подпись банка не оставляет на банке НИ ОДНОГО следа — и следа НОЛЬ, а не «один булев».** ⚠ **Испр. 08.09: прежняя формулировка вела к СНЕСЁННОЙ колонке.** Строка называла единственной записью булев `bank_released` на прогоне; колонки нет — `platform/internal/pgstore/migrations/00029_drop_bank_released.sql` её дропнул, в `platform/**.go` остался 1 хит и тот комментарий-эпитафия (контроль на живом соседе `bank_moved_at` — 6 хитов). Исполнитель грепал бы пустоту. ⭐ **И рядом стоит ПУСТАЯ таблица ровно с нужными колонками:** `bank_decisions(book_id, term_id, action, dst, decided_at, decided_by)` — `migrations/00002_readmodel.sql:175-186`, с чек-констрейнтом «promote обязан нести dst»; писателей вне тестов **0**. То есть форма записи спроектирована и ратифицирована, но не пишется никем. ⇒ заказ не «спроектировать след», а «начать писать в уже стоящую таблицу»: кто и когда подписал, что именно вошло в подписанный набор — не хранится нигде. Следствие: пост-фактум ответить «почему в книге этот перевод термина» нельзя, а при пере-нарезке или пере-прогоне восстановить намерение человека не из чего. ⚠ **ЧАСТИЧНЫЙ ответ появился с дверью правок (D39.162):** её документы решений — долговечная запись того, ЧТО владелец решил, и они переживают прогон. Не отвечено по-прежнему: КТО и КОГДА подписал, и что именно вошло в подписанный набор. Всплыло трассировкой цепи банка 22.08, подтверждено пере-проверкой | платформа + бэкенд | когда-нибудь (с трубой доставки правок, D39.156) | отдельное решение о провенансе подписи | трассировка цепи банка 22.08, пере-проверено №19 |
| 227 | **`signature` в квитанции двери правок считается от карты, которую переписывает ЛЮБАЯ граница майнинга** (находка воркфлоу-ревью P9, 28.08): запись карты стоит ВЫШЕ решения о стопе (`backend/internal/pipeline/mining.go:192`=`writeFileAtomic(r.signatureMapPath()`), поэтому `signature != null` НЕ означает состоявшегося стопа подписи; `surfaces`/`undecided` дрейфуют между двумя вызовами владельца, а `undecided: 0` достижим при НЕпредъявленных решениях (кап top-200 вытесняет). ⚠ Починка аддитивна и носитель для неё уже есть: карта несёт СВОЙ идентификатор (`backend/internal/membank/decisions.go:981`=`id, err := seed.SignatureMapID(content)`), а шов его не читает — отдать идентификатор в квитанцию и судить по нему. Цена сегодня мала (поле информационное, гейтом не служит) и растёт вместе с экраном подписи: именно он будет решать «что я подписываю» по этому числу | бэкенд | когда-нибудь (гейт: заказ экрана подписи) | аддитивная правка квитанции | воркфлоу-ревью P9, D39.162 |
| 228 | **Отклонённая поверхность возвращается АЛИАСОМ уцелевшей строки — движок не держит того, что канон уже обещает** (находка воркфлоу-ревью P9 в форме Д1, УЗКО пере-сформулирована бэкенд-сессией 28.08 и принята приёмкой): канон говорит дословно «declining a surface removes EVERY window of that surface» (`docs/architecture/14-api-contract/openapi.yaml:2367`=`declining a surface removes EVERY window`; адрес пере-нацелен 02.09 — минор 0.9.0 сдвинул прежний 2051), а эмиссия майнера энтити-широка (`backend/internal/pipeline/miner_emit.go`, `clusterTouches`), тогда как фильтр авто-банка ключуется только по собственному `src` строки (`backend/internal/pipeline/mining.go:179`=`NormalizeSourceKey(m.Src)`). ⚠ **Правильная форма — снять АЛИАС со строки, а не снести строку:** расширение `decline` до энтити противоречило бы ратифицированному контракту, и именно поэтому бэкенд-сессия применила право §9 и НЕ чинила это попутно. Предмет — банковая онтология (`18-bank-ontology.md`), не тихая порча | бэкенд | скоро (гейт: заказ по читающей стороне банка) | отдельный заказ узкой формы | воркфлоу-ревью P9; форма — бэкенд-сессия 28.08, D39.164 |
| 229 | **Снапшот не фолдит модель ВНУТРЕННИХ гейтов — флип провода под неизменным `request_hash`** (самонаходка бэкенд-сессии 28.08, подтверждена приёмкой): снапшот фолдит `Capability` СТАДИЙНЫХ моделей и их эскалации (`backend/internal/pipeline/snapshot.go:316-340`), но модель `gates.terminology.model` / `gates.repair.model` (`backend/internal/config/internal_call.go:72`) не фолдится сознательно — а терминолог шлёт ДВА системных сообщения, так что смена оси `capabilities.system_messages` у провайдера, которым пользуется только гейт, меняет байты запроса при неизменном хеше: тихий false-hit класса D5.2. ⚠ **Сегодня ЛАТЕНТНА и денег не стоит — проверено приёмкой: гейта `terminology` нет НИ В ОДНОМ конфиге репозитория** (`grep -c terminology configs/pipeline-c1.yaml` = 0). Триггер починки — день, когда гейт включат с провайдером, объявляющим НЕдефолтную возможность. ⚠ Цена лечения — денежная: фолд гейт-моделей сдвигает хеши и обесценивает чекпойнты; дешёвая форма — фолдить ТОЛЬКО недефолтное (приём `omitempty`, прецедент `MinMaxTokens`), тогда сегодняшние снапшоты остаются байт-равными | бэкенд | когда-нибудь (гейт: включение внутреннего гейта либо следующее касание снапшот-контракта) | правка снапшот-контракта | самонаходка бэкенд-сессии, D39.164 |
| 230 | **Инертный `decline` подписанного сид-терма отвечает `already_applied` вместо единственной работающей инструкции** (названный размен пака «тихая порча», D39.164): сузив отказ по поверхности ради СХОДИМОСТИ повтора, движок потерял поучение в одном углу — когда отказ и записан, и по-прежнему инертен против `glossary_seed`, пользователь получает «уже применено» вместо «убери терм из сида». Сходимость сочтена более тяжёлой обязанностью (на ней стоит вся раскладка класса 15 и синхронная дверь платформы), но размен РЕАЛЕН. **Форма закрытия — поле отчёта со стоячим фактом**, то есть аддитивная правка формы шва: платформенный `BankReport` — аллоулист, лишнее поле на провод не уедет само | бэкенд + контракт | скоро (с ближайшим касанием отчёта двери) | аддитивное поле отчёта | размен пака «тихая порча», D39.164 |
| 232 | ⚠ **ЛИД ПРОТУХ — испр. 05.09: вторая половина (слот гранта на прерванном между волнами юните) ЗАКРЫТА** паком «число согласия» (`D39.187`, пин `TestAUnitInterruptedBetweenWavesTakesNoSecondSlot`; эррата 03.09-а). **Настоящий остаток** — две схемные оси («первая редакторская стадия», «прерванная пере-делка») и отложенное слово владельца о семантике переноса. **Ось «свежий/пере-делка» выведена из ПОЛНОТЫ СТРОК, а не из факта отгрузки** (D39.170, находки охотника 3 и 4). Следствия ДЕНЕЖНЫЕ на слух покупателя: добавление стадии в пайплайн превращает ДОЧИТАННУЮ книгу в «3 unit(s) NEVER delivered» и приглашает купить её снова; юнит, прерванный между волнами (signature stop, денежный потолок, Ctrl-C), второй раз считается свежим и тратит слот гранта повторно — замерено 4 купленных юнита → 2 главы. Носитель у движка УЖЕ есть: реестр анонсов `events_outbox.once_key` (`backend/internal/pipeline/events.go:427`=`unitOnceKey is the identity of one announcement`), ключ `unit:<книга>:<волна>:<глава>:<юнит>`, монотонный на всю жизнь книги и переживающий и добавление стадии, и обрыв между волнами. ⚠ **ПЕРВАЯ ПОЛОВИНА ИСПОЛНЕНА 31.08** (`bb541a8`, экземпляр A11; испр. 02.09): читающий метод `store.AnnouncedOnceKeys()` построен, его докстринг называет эту строку по номеру, предикат — `delivered[key] && unitShipped(rows)`. **ЖИВОЙ ОСТАТОК — ВТОРАЯ ПОЛОВИНА:** юнит, прерванный МЕЖДУ ВОЛНАМИ, повторно тратит слот гранта (разбор — `backend/docs/MONEY_HONESTY_REPORT.md` §4.5). ⚠ РАЗВИЛКА, которую надо назвать в промте: ключ несёт ВОЛНУ, значит «юнит отгружен» — факт per-wave. **Ответ есть и он не новый механизм:** отгрузкой считается волна, владеющая ОТГРУЖАЮЩЕЙ (последней) стадией — `backend/internal/pipeline/snapshot.go:248`=`finalStageWave is the wave that owns the SHIPPING (last) stage`; на редакторском конвейере это edit, на черновом-только — draft. Проверять надо ИМ, иначе черновой-только конвейер получит ось, которая никогда ничего не считает отгруженным (предложено движковой сессией при сдаче, сверено мной по коду) | бэкенд | скоро | Читающий метод стора + перевод оси на факт отгрузки; отдельный пак | приёмка D39.170 |
| 233 | **Трата терминолога вне объёмного потолка масштабируется КНИГОЙ, а не грантом** (D39.170). Замер: три последовательные покупки по одному юниту на четырёхглавной книге дали три полнокнижных консолидации по $0.005460 каждая — покупка одного юнита обходится в ~1.5× стоимости самого юнита. Книга на 500 юнитов, проданная по одному, оплатит 500 полнокнижных проходов. Место траты — в ЦЕНЕ, а не в потолке (решение подтверждено), но при мелкой нарезке продажи она перестаёт быть накладной и становится основной статьёй: это ВХОД В КАЛИБРОВКУ ЦЕНЫ, а не сноска | бэкенд | скоро | Учесть в модели цены при следующей калибровке; либо чекпойнт консолидации, переживающий покупку | приёмка D39.170 |
| 237 | **Два загейченных триггера НАЖАТЫ и не отработаны** (реестр `13-tech-debt-anchors.md` §Б-108, сверено 30.08). **(а) `go.work`:** условие «появление Go-кода платформы» выполнено давно — `platform/go.mod` есть, `ls go.work` в корне даёт «No such file or directory». Ратифицировано D39.85 §8 п.4 (`docs/research/23-engine-platform-seam.md:66` = `go.work — коммитить, когда у платформы появится Go-код`); цена — один файл, по тому же §6 он решает только dev-удобство и не меняет ни видимости, ни версий. **(б) вендор-сверка маппинга эффорта `deepseek-v4-pro`:** вахта D39.92 сработала 13.08 changelog'ом вендора. ⚠ **Испр. 05.09: НОСИТЕЛИ БОЛЬШЕ НЕ ПРОТИВОРЕЧАТ** — и квирки (`docs/experiments/00-provider-quirks.md` §3г), и `STACK.md` говорят одно: ручка ДОХОДИТ до модели. Прежняя редакция обвиняла оба носителя в утверждении «ручки у pro НЕТ», которого ни один из них уже не несёт, и это заставляло сессию искать спор, которого нет. Живой остаток — вендор-сверка САМОГО МАППИНГА и величина эффекта, и по гардрейлу владельца это закрывается ТОЛЬКО вендор-докой, а не выбором стороны. Держит жильца Д5 и калибровку цены редакторского арма. ⚠ **Класс важнее двух пунктов: спроектированный механизм без носителя события тихо становится долгом, и никто не проверяет, не нажат ли спусковой крючок.** | оркестратор | скоро | (а) один файл в корень; (б) заказ полигону на вендор-сверку | аудит очереди 30.08 |
| 241 | **Канон противоречит сам себе на ДОЧИТАННОЙ книге, и принятая правка банка умирает молча** (названо телом D39.165 §3 28.08, носителя не получило; заведено оркестратором №20 30.08 по находке сессии P12). Две фразы: правка банка «takes effect on the NEXT run» (`docs/architecture/14-api-contract/openapi.yaml:529`=`takes effect on the NEXT run`) против «finished work is not bought twice» + подъём потолка только у ПРИОСТАНОВЛЕННОЙ книги (`:590`=`finished work is not bought twice`). У дочитанной книги следующего прогона купить нечем: пользователь правит банк, получает квитанцию об успехе — и правка не доезжает ни до одной строки никогда. ⚠ Смежное лечение уже существует и не связано с этой дырой: пере-проход ПОКУПАЕТСЯ членом `RunRequest.re_pass` (канон 0.7.0, D39.166) — то есть механизм есть, а фраза канона его не признаёт для дочитанной книги. Решать формой: либо канон признаёт пере-проход входом для дочитанной книги, либо дверь правок отказывает такой книге ЧЕСТНО вместо ложной квитанции | контракт (+платформа) | скоро (следующее касание контракта) | контрактный минор + пин на дочитанной книге | D39.165 §3, эррата 30.08-б, находка сессии P12 |
| 242 | **Реестр D-нот: колонки «статус» и «тело» разъехались на 74 строках из 224** (замер аудита доков 30.08). У свежих нот в «статусе» стоит заметка «ЖИВОЕ: …», а слово `жив` уехало в «тело»; шапка таблицы описывает другой порядок. Гейт `counts.py --check` этот класс НЕ ловит по устройству (сверяет полноту номеров, не форму ячеек). Лечение — не ручная перекладка (дороже пользы и легко внести новую ложь), а машинное: правило формы в `counts.py` + разовый прогон приведения. Пока не сделано — в легенде реестра стоит правило чтения (испр. 30.08) | оркестратор | когда-нибудь | правило в `counts.py` + разовое приведение | аудит доков 30.08 |
| 243 | **Остаток аудита доков 30–31.08: 19 удержанных находок НЕ применены** (аудит — 5 линз + верификатор на каждую, 57 находок, 55 удержаны, 36 применены сменой №20). Перечень: ~~**arch-3**~~ **ЗАКРЫТ 31.08 — разбор телом D39.179 п.5** (был вдвое больше заявленного: 51 указатель вместо 13, и дороже адресов оказались ЛОЖНЫЕ КЛЕЙМЫ) · **arch-5** (правило языка знает две корзины, `reader.txt` — третья) · **arch-7** (§2 закона шва: дисциплина флока не описывает новый глагол-писатель) · **arch-9** (реестр загейченных триггеров не знает нажатых 30.08) · ~~**arch-10**~~ и ~~**arch-11**~~ **ЗАКРЫТЫ 02.09** (числа словаря событий сняты в пользу кода; отвергнутый ключ назван отвергнутым) · **arch-12** (шапка `09-target` сама зовёт себя неполной — строку под таблицей слоёв надо внести; ⚠ ЖИВ на 02.09: греп `D39.181` по `docs/architecture/09-target-architecture.md` — 0 хитов, греп `D39.182` — 0 хитов, то есть лендинги 31.08 в док слоёв не внесены) · **contract-8** (эррата 15.08-в в шапке D-лога указывает на промт, уехавший в архив) · **contract-10** (`Export.failure_code` «becomes an enum with the first built format» — формат построен, условие наступило) · **progress-6/7/8/10/11/12/13/14/15** (мелочь CURRENT-STATE и строк бэклога: протухшие «запушена»/«строка 200»/якорь `miner_emit.go`/дубль 238 внутри 160 и пр.). ⚠ Отчёт аудита жил в песочнице сессии №20 и умирает с ней — здесь ЕДИНСТВЕННЫЙ носитель списка; воспроизведение = повторный аудит (5 агентов, ~2 часа) | оркестратор | скоро | пройти списком | аудит доков 30–31.08, сдача смены №20 |
| 244 | **Гейт якорей на пре-коммите ломается всякий раз, когда зона правит КОД и СВОЙ реестр одним незакоммиченным деревом** — и врёт в обе стороны. Механика: хук судит ЗАКОММИЧЕННЫЙ док против РАБОЧЕГО кода, поэтому пере-нацеленные, но не залёнджённые якоря читаются как битые. Замерено на приёмке P12 31.08: у оркестратора хук напечатал 13 битых якорей `platform/docs/DEFECT_REGISTER.md`, у зоны `counts.py --lint` на том же дереве дал **0**; права зона — в HEAD `internal/runs/runs.go:323`, в рабочем `:347`, и токен по новому адресу на месте. ⚠ Обратная сторона опаснее и не замерена: якорь, ставший битым ПО-НАСТОЯЩЕМУ, тем же механизмом может оказаться зелёным. Свойство общее, не про этот пак | оркестратор | когда-нибудь | либо судить обе стороны из одного состояния (`--from-index` уже есть — проверить, покрывает ли он случай), либо печатать, что сравниваются РАЗНЫЕ состояния | приёмка P12 оркестратором №21, 31.08, разрешено командой |
| 245 | **Pathspec-форма коммита молча роняет UNTRACKED-файлы, и сломанный коммит выглядит нормальным до первого чужого прогона.** `git commit -- <пути>` обходит ИНДЕКС и берёт рабочее дерево только для ОТСЛЕЖИВАЕМЫХ путей: предварительный `git add` нового файла она игнорирует. Поймано на лендинге P12 31.08 — коммит `e1cb692` унёс `migrations.sha256`, уже ссылавшийся на три миграции, а сами миграции 00029/00030/00031 и три теста остались снаружи; починено амендом секундного неопубликованного коммита при пустом индексе (`0a680a3`). ⚠ Канон git-координации в `CLAUDE.md` объясняет про pathspec ТОЛЬКО то, что она не трогает чужой индекс — то есть учит половине правды и ровно этим создаёт ловушку. Норма, которую предлагаю вписать: новые файлы стейджить явно и проверять состав `git show --name-only`, а не доверять форме. ⚠ **ПОЛОВИНА ПОСТРОЕНА 31.08** (`94381bb`, испр. 02.09): в `docs/scripts/githooks/pre-commit` стоит warn-блок, который перед каждым коммитом печатает неотслеживаемые файлы в каталогах коммита. Живой остаток — блок ПРЕДУПРЕЖДАЕТ, но не блокирует, и на свежем клоне хук вообще не установлен (строка 220) | оркестратор | скоро (решение владельца — его канон) | одна строка в `CLAUDE.md` §«Git-координация мультисессий»; вписывает владелец или оркестратор по его слову | лендинг P12 оркестратором №21, 31.08 |
| 247 | **§2.2 закона раскрытия опровергает себя следующей же строкой — эррата зонного дока.** Формальная фраза требует «держит ОБА операнда сравнения и обязано их НАПЕЧАТАТЬ», а её собственный пример тут же говорит обратное: честная форма — НАЗВАТЬ ОСЬ («снапшот разошёлся» честно, «конфиг/промпты изменились» ложно). ⚠ **Ратифицированный текст D39.181 п.1 требования «напечатать» НЕ СОДЕРЖИТ ВОВСЕ** — оно живёт только в `backend/docs/DISCLOSURE_LAW_DESIGN.md`, значит противоречия с ратификацией нет и решает ЗОНА, не владелец. ⚠ Довод «граница прячет имена моделей и хеши» ОПРОВЕРГНУТ исполнением: эти значения уже едут по тому же stderr штатным INFO-логом, включая `memory_version=<12 hex>` — значение того самого поля. Цена бездействия на живых данных = НОЛЬ (единственная сдвинувшаяся ось — хешевая, печать дала бы две несравнимые строки SHA) | бэкенд | когда-нибудь | эррата к §2.2: операнды называются осью, а не значением | приёмка D39.182 + разведка оркестратора 31.08 |
| 248 | **Полнота самообъявления о правках чужих тестов ничем не проверяется — и трижды оказалась неполной.** P11 назвала файл, которого не трогала; P12 не назвала тест, у которого переписаны ОБА утверждения; сессия пака «деньги и честность» в первой редакции комментария утверждала неверное о силе собственной правки. ⚠ **Мой метод проверки был слабее, чем я его подал:** греп `^[-+].*t\.(Error|Fatal)` ловит строку СООБЩЕНИЯ, а утверждение — это строка СРАВНЕНИЯ, и она другая (замер: греп локализует утверждение в 1 случае из 475). Предложение разведки: warn-only гейт-детектор при лендинге — список пред-существующих тестов с изменёнными строками утвержденческой формы ВНУТРИ пред-существующих тел; прототип ~25 строк sh прогнан на двух лендингах и указал ровно на `bankfixpack_test.go`. Площадка есть — `docs/scripts/githooks/pre-commit` уже warn-only. ⚠ Ложняки измерены: целиком новый `t.Run` внутри старого `func` даёт срабатывание (1 из 6 на P12) | оркестратор | скоро | гейт-детектор warn-only + пункт чек-листа приёмки | разведка оркестратора 31.08 по вопросу владельца |
| 249 | ⚠ *(пример в теле ниже ссылается на ряд PD-246 — он ЗАКРЫТ D39.194; пример держим как археологию класса, живым рядом его не читать)* **Девять рядов бэклога потеряли слово веса, и гейт на них НЕ краснеет.** ⚠ **Лечение ПОСТРОЕНО (сверено кодом 02.09): вес судится ПРЕФИКСОМ ячейки** — `docs/scripts/counts.py`, греп `BACKLOG_WEIGHTS` (три слова: «блокер-очереди» · «скоро» · «когда-нибудь»), и «скоро» считается тем же префиксом. Этим убита ВТОРАЯ половина класса: подстрока ловила слово в ПРОЗЕ, и фраза «переведена из «скоро»» ре-добавляла ряд в счёт — число скакнуло **53 → 56** при одной новой строке (замер 02.09, пере-счёт скриптом). ⚠ Гейт рождён ЗЕЛЁНЫМ, а не красным: девять известных рядов внесены «дедовщиной» — греп `WEIGHT_GRANDFATHERED` там же, ряды **5 · 13б · 94 · 96 · 97 · 149 · 205 · 221 · 246**. **ЖИВОЙ ОСТАТОК — сами ячейки:** у 96/97 прочерк ЗАКОНЕН (надгробия строк, уехавших в зонный бэклог, D39.84), остальные семь потеряли вес молча и чинятся оркестратором — каждая починенная выходит из списка дедовщины. ⚠ Два ряда шире класса: **149** («исполнен и заленден 10.08») и **205** («сделано 21.08») объявляют себя ИСПОЛНЕННЫМИ прямо в колонке веса, хотя по правилу таблицы закрытые строки в ней не живут — это либо живой остаток без веса, либо непойманный класс C; **246** несёт самодельное «СРОЧНО», которого в словаре нет. | оркестратор | скоро ($0, гигиена трекера) | правка семи ячеек → выход из `WEIGHT_GRANDFATHERED` | ревизия доков 02.09, приёмка контролёра |
| 217 | ⚠ **ЛИД ПРЕУВЕЛИЧЕН — испр. 05.09:** «не работают вовсе / блокирует любой прогон» ложно — пользователь `ubuntu`, литерал пути РАЗРЕШАЕТСЯ, полигон покупал 30.08–02.09. Живой долг — сам захардкоженный путь, а не блокировка. **Скрипты полигона захардкодили АБСОЛЮТНЫЕ пути двух корней и не работают на этой машине вовсе.** ДВА РАЗНЫХ слома. **Корень репо** — смена пользователя: литерал в 121 файле, из них 104 дословно `REPO = Path("/home/ubuntu/projects/textmachine")`, портабельных форм всего 5. **Корень книг** — оба события порознь: литерал `/home/ubuntu/books` 86 файлов (пользователь), портабельный `Path.home()/"books"` 89 файлов (переезд каталога; на прежних машинах работал). Объединение 173 файла. Пользователь теперь `ubuntu-26`, книги переехали в `<репозиторий>/books` ⇒ ломается и то и другое, включая ЖИВОЙ гейт фазы Д `eval/conformance.py:49`=`REPO = Path("/home/ubuntu/projects/textmachine")`. Живых носителей 26 по корню книг (среди них портабельная форма преобладает 20:6) плюс корневые гейты и сборщики корпусов; остальное — скрипты закрытых эксп-12–16, их владелец велел ВЫБРОСИТЬ, а не чинить (D39.157 п.4а). Форма правки — за зоной; приор оркестратора: один модуль путей, корень резолвится МАРКЕРОМ вверх по дереву (движок так и делает — `backend/internal/miner/miner_parity_test.go:29`=`derived from the repository MARKER`), книги от него, обе ручки перекрываются env | полигон | скоро (блокирует любой прогон зоны) | пак путей полигона | переезд машины 24.08, №19 |
| 219 | **Line-якоря в тела D-лога обречены съезжать, и механизм именно в дисциплине эррат.** Эрраты вписываются в КАРТУ ШАПКИ (append-only, D23.3), то есть в начало файла, — значит каждая эррата сдвигает номера строк ВСЕХ тел ниже, и любой якорь вида `05-decisions-log.md:NNN` умирает молча. ⚠ Замерено на себе 27.08: три эрраты за сессию убили якоря в `docs/architecture/17-seam-inbound-law.md` (греп `Эррата, которую ратифицирующая нота обязана поставить`) и `docs/research/25-seam-cold-review.md:13`=`адресуем НОМЕРОМ, а не строкой` (оба целили в `:232`, тело уехало на `:239`; ⚠ 02.09 обе площадки уже переведены на форму номера ноты — прежний голый указатель `17-seam-inbound-law.md:120` показывает пустую строку). Лечение — не пере-нацеливание (оно повторится через эррату), а СМЕНА ФОРМЫ якоря: в тела D-лога целиться номером ноты (`^## D39.106`), который стабилен навсегда, а не строкой. ⚠ **Первая половина лекарства ПОСТРОЕНА:** `counts.py --lint` сверяет якоря в тела D-лога СТРУКТУРНО и без токена — владелец целевой строки (ближайший `^## D<номер>`) обязан совпасть с номером, названным рядом; остаётся перевести живые якоря на форму номера | оркестратор | скоро (растёт с каждой эрратой) | `--lint` учит форму `файл:^## D<номер>`, живые якоря в D-лог переводятся на неё | ревью доков 24.08, механизм и отсутствие носителя — 27.08, D39.160 |
| 220 | **Репо-широкий гейт доков бутстрапится пакетным менеджером ОДНОЙ зоны, и та заморожена.** Диспетчер `.git/hooks/pre-commit` зоно-нейтрален по построению (`for hook in */scripts/githooks/pre-commit`, `#!/bin/sh`, node не нужен) и судит `CLAUDE.md` + `docs/**` + `platform/docs/**` + `frontend/docs/**` (`docs/scripts/counts.py:569`=`ROOT / "CLAUDE.md"`), но единственный его УСТАНОВЩИК — `frontend/scripts/githooks/install.mjs`, вызываемый ключом `prepare` из `frontend/package.json`. Охват и бутстрап не совпадают ⇒ инструмент решает свою задачу не в полной мере. Проверено исполнением 24.08: на этой машине `.git/hooks/` содержал только `*.sample`, гейт МОЛЧАЛ, ничего не проверив, и поймал первые четыре дефекта только после ручной установки; сессия бэкенда или доков `npm install` не делает никогда. Приор: зоно-нейтральный установщик в `docs/scripts/githooks/` как ЕДИНСТВЕННЫЙ писатель диспетчера, `prepare` фронта зовёт его — фронтовая половина выписана пингом №19 в зонный журнал фронта. ⚠ Ручная установка — временная мера, пока строка открыта; записывать её как порядок работы ЗАПРЕЩЕНО (это ровно тот обход, цену которого называет шапка `CLAUDE.md`) | доки + фронт | скоро | зоно-нейтральный бутстрап + правка `prepare` при разморозке | аудит переезда 24.08, №19 |
| 49 | **Этапы Б+В спеки D15.2** (content-addressed resume / `guard_hash` — D39.31 сознательно не строил) ; этап В = tmctl export-контракт D29.1 (annot-v1 · цвет-мап+rollup · политика красных fail-closed) + операторский протокол-документ релиза гендер-твиста (D5.1): сам механизм УЖЕ построен — until_ch-правка → точечный re-edit со сметой и $0-пере-пином (`repin.go`/`rebill.go`, D39.42 п.5/D39.45) | бэкенд | скоро (ПОДТЯНУТА D39.81: annot-v1 = источник замечаний для фронта — критический путь подключения) | отдельное решение (annot-половина — по контракту 14, D39.99) | D39.34(4), D33 п.5, D39.81 |
| 49а | **ALTER-шаги миграций v8–v14 не идемпотентны вопреки шапке `migrate.go:9-11`** (полу-применённая БД не сходится; счётчик версий скрывает) — находка критика полноты пака-19 | бэкенд | когда-нибудь | отдельное решение | D39.56, PACK19_BUILD §6.9 |
| 50 | F3-остаток идемпотентности | бэкенд | когда-нибудь | отдельное решение | D39.34(4) |
| 51 | `human_override` LOCK (D29 п.1г, в коде 0 вхождений) | бэкенд | когда-нибудь | отдельное решение | D39.34(4) |
| 52 | **Ф2-гейты вне идеала**: морфо-гейты канцелярита + L1-лемматизация (python-сайдкар) · полный OpenCC · опциональный пре-перевод гейт ; состав явно: канцелярит + РОД (строка 82) + класс Ф2-гейтов карты 04-unhappy (обсцен-гейт/феминитивы/время сцены — состав решить паком) ; + класс идиоматики (свип-хвост, D39.73): сехоуюй-словарь · вэньянь-классификатор (zh) · васэй-эйго ложные друзья (к ja-паку 81) — данные пары или закрытие «банк книги покрывает» тем же паком | бэкенд | когда-нибудь | отдельное решение | D39.34(4) |
| 54 | Масштаб целой книги: волны/каденс/потолки/ETA на сотнях глав (гоняли максимум 10; книга 7,78 млн симв., ~2284 раздела). ⚠ **Дописка инвентаря №18 (D39.147 п.2г):** жёстких потолков размера в коде НЕТ, но исходник читается в память целиком (`chunk/ingest.go:98`), чтения стора беспагинационны под `opTimeout = 10s` (`store/store.go:39`) и бюджеты нарезки калиброваны на 25 главах (`config/pipeline.go:126-138`) — ни одно из трёх на 2283 главах не проверено ничем | бэкенд | когда-нибудь (последним по курсу) | МАСШТАБ | D39.33, CURRENT-STATE |
| **— ПОЛИГОН (кандидаты пакетов) —** | | | | | |
| 55 | **`dialogue_dash` мерить только на невиданном тексте** (подогнан под 蛊真人; цифры мини-прогона аргументом не считаются) ; расширено до вне-претрейн чекпоинта целиком: r-коэффициенты exp01/08 · precision чекеров · частота эха · чистовик exp15-выводов ; + arity-полоса паспорта (D29.2г): решить — dialogue_dash покрывает диалоговую половину или мерить (D39.73). **Частично закрыта эксп-21 (D39.117):** направление главного вывода воспроизведено на чистом en-материале (узнавание 1/5), $0-довесок исполнен частично; ⚠ **ПЕРЕ-СНЯТА 05.09 (D39.198 п.5): требования НОВОЙ книги здесь НЕТ.** Владелец: прогоняем на тех же текстах (мастер Гу и Жан-Кристоф), а «известность модели по претрейну» остаётся ОГРАНИЧЕНИЕМ ВЫВОДА — результат на классике читается как предварительный, и это пишется в вывод, а не покупается новой книгой. Прежняя редакция несла ЖЁСТКИЙ платный заказ полигону. **срез эксп-21 НЕ купил** (главный zh-замер на книге 4/5, без пинга) — остаток = **ОГОВОРКА В ВЫВОДЕ**, а не покупка: замер идёт на мастере Гу и Жан-Кристофе, а «модель знает текст по претрейну» пишется ограничением результата (⚠ испр. 05.09 — колонки продолжали заказывать неконтаминированный zh-срез уже ПОСЛЕ того, как шапка строки его сняла: полигон читает колонки) | полигон | когда-нибудь (оговорка вывода, не заказ) | формулировка в отчёте | D39.37(4), D39.40, D39.46, D39.108, **D39.117** |
| 56 | Ёфикатор/санитайзер-классы не размечены (§6.5 отчёта пакета-6) | полигон | когда-нибудь | полигон-пакет | D39.46, CURRENT-STATE |
| 57 | Пере-замер «контексты — главный рычаг» на трудной выборке пакета-7 с боевой сборкой (до него kwic-веса/семантику не трогать; перф-хвост AttachKWIC — строка 37: фикс-пак 128 закрыт D39.118, опция в нём не взята, семантика не менялась) — напряжение с D39.46 названо, не отменено | полигон | когда-нибудь | полигон-пакет | D39.50, D39.118 |
| 58 | **Не покрыто пакетом-8**: вторая книга/пара/модель · строка `drafts:` · ось `batch_runes` · разметчики-модели (не люди) · precision роли на «расширенном, но осмысленном» материале ; + контрастивный регрессионный сьют по каталогам режимов отказа (12-*) · чистовик exp15-выводов | полигон | когда-нибудь | полигон-пакет | POLYGON_PREMEASURE §1.8/§2.5/§3.5/§7.6 |
| 59 | **Вендор-чек префикс-кэша ZAI/GLM** (на нём стоит вся кэш-экономика W1/Q2c) ; + GLM context-overflow гард (finish=model_context_window_exceeded — NOT-do пака-12 без решения) ; + Mistral-strip гейт message-builder (research/21 §1.1: extra_forbidden на reasoning-поля; ЛАТЕНТЕН при нашем single-shot wire — гейт перед прод-путём mistral в канале B / любым multi-turn; D39.74) | полигон | когда-нибудь (до МАСШТАБА) | полигон-пакет | D39.34(6) |
| 60 | Scheduler-aware волны под peak-valley DeepSeek (прямой COGS-рычаг) | полигон/бэкенд | когда-нибудь (до МАСШТАБА) | отдельное решение | D39.34(6) |
| 61 | **Прайс/wire-гигиена**: продление `prices_checked` без правки чисел · гейтнутые платные армы (edit-единица >3200 и др.) · wire-probe temperature в thinking-канале DeepSeek | полигон | когда-нибудь | полигон-пакет | D39.34(6) |
| **— Ф2.5 / ПИЛОТ / ПРОД —** | | | | | |
| 62 | Билингв-якорь (D25 п.9 Q1) | владелец | когда-нибудь | Ф2.5 | D25 п.9, CURRENT-STATE |
| 63 | Контаминация корпуса (D27 п.4) | владелец/полигон | когда-нибудь | Ф2.5 | D27 п.4, CURRENT-STATE |
| 64 | Судья-дублёр (D22.6) | бэкенд | когда-нибудь | Ф2.5 | D22.6, CURRENT-STATE |
| 66 | Пилотные D25-гейты: publishable/waiver (п.1) · FN-bound L3 (п.4) | владелец | когда-нибудь | Ф2.5 | D25, CURRENT-STATE |
| 67 | **Прод-гигиена: юр-пакет · провенанс 12-*-доков · xAI-ключ off перед продом** (D27) ; + юрисдикционные annex-ре-чеки при новых рынках (D39.29) + поле «версия исходника» book.yaml на интейке (04-unhappy §5) | владелец | когда-нибудь | Ф2.5 | D27, CURRENT-STATE |
| 68 | Residual-тачпойнты exp16, не влитые в сид-дельту: мини-голд алиасов (ОТЛОЖЕН до первого длинного прогона — D39.103) · precision@30 (`books/gu-zhenren/exp16/`) | полигон | когда-нибудь | Ф2.5 / полигон-пакет | CURRENT-STATE |
| **— Ф3 / ПРОДУКТ —** | | | | | |
| 69 | Gemini API «под-18» обязательство на конечный продукт (независимо от лейблов) | владелец | когда-нибудь | Ф3 / отдельное решение | D39.32, D39.34(7) |
| 70 | Action-security gate перед выдачей tools/webfetch (D25 п.5) | бэкенд | когда-нибудь | Ф3 | D39.34(7) |
| 71 | **Планы research/22**: epub-tag-rewrite · Q7-леджер ; + F3-brief из D29 п.3 (chat-edit · Not-useful-петля · cost-of-fix) + Ф3-скоуп 02-mvp-plan (TMX/TBX · Bertalign · дистилляция 7–14B); + V5: фронт ВЕБ-ПЕРВЫЙ, SEO/ранжирование (куки · страницы-сироты · актуальные алгоритмы Google) — определяет выбор фреймворка (SSR vs SPA), в Ф3-дизайн ДО выбора стека (ПТ-23) | бэкенд | когда-нибудь | Ф3 | D39.34(7), START_PROMT V5, D39.80 |
| 94 | **Продукт-механика входа и прогона** (V2, ПТ-16..18): абьюз/misuse-прескрин дёшево и точно ДО трат токенов (H8) + UI-контракт отказа (проект-решение D39.80) · лимит размера входа настройкой (H7) · продукт-кнопки «стоп/продолжить» поверх построенных graceful stop и redrive, абьюзивный прогон НЕ продолжать (H10); API-форма — по контракту 0.3.0 (отказ прескрина РЕШЁН: `rejected` + грубый `content_refused`, К-9 закрыт D39.138 п.2б) | бэкенд | к подключению фронта (ПОДТЯНУТА D39.81; лимит можно раньше, к пилоту) | отдельный пак при Ф3-препе (контракт 14 ратифицирован) | START_PROMT V2, H7/H8/H10, D39.80, D39.81 |
| 96 | **→ переехала в `platform/BACKLOG.md` П-1** (зонные бэклоги, D39.84: HTTP/SSE-слой, обвязка, аутентификация, порядок деплоя); здесь остаётся ратифицированным сам ИНВАРИАНТ D39.81 — движок = процесс-на-прогон (EXCLUSIVE flock `store.go:43`), сервер в backend НЕ пишется | платформа | — | зонный бэклог | D39.81, D39.84 |
| 97 | **→ переехала в `platform/BACKLOG.md` П-2** (глобальный брокер рейт-лимитов; гейт «до второго параллельного пользователя» зафиксирован там же) | платформа | — | зонный бэклог | D39.81, D39.84 |
| 127 | **Устаревший DDL-коммент `glossary.source`** (`migrate.go:194`: «seed|ruby|auto», фактические пути записи — seed/ruby/mined, `auto` не пишет никто; фантом уже утёк во фронт-доки дважды) — поправить коммент | бэкенд | когда-нибудь (попутно любым паком store) | однострочная правка | ревью контракта 04.08, D39.99 |
| 106 | **Слой 3: целевой контракт «узкие мандаты + ДИФФЫ» против текущего full-regen — гейт «перепроверить до стройки» в силе, приоритет ПОНИЖЕН (D39.117: full-regen выигрывает у ремонта; оговорка полигона — чинил дешёвый фиксер по предложению, не сильный редактор узким мандатом).** Реактивация — только через эту строку. Археология дословно (эмпирика D39.108 · история дыры учёта) — `architecture/13-tech-debt-anchors.md` §Б-106 | владелец → бэкенд | когда-нибудь (пере-проверка «сильный редактор × узкий мандат» — перед стройкой слоя 3) | замер → решение владельца | 09 §Слой 3, D39.90, D39.108, **D39.117** |
| 114 | **Конфиго-слой ручки эффорта: два дешёвых хвоста приёмки (вне снапшота, $0 прогонов).** (а) **Д4 отчёта:** `gates.terminology.target_script` НЕ сверяется с `book.target_lang` — `target_lang: ru` + `target_script: Latin` грузится чисто и **ИНВЕРТИРУЕТ** банковский экран (ловит целевой, пропускает чужой); сверка при загрузке против `lang.LangScripts(TargetLang)` — тот же дата-план, что у экрана строки 46, громкий отказ на несовпадении. (б) **Находка-2 приёмки:** стейл-доккоммент `capability.go:78` — у константы `ReasoningExtraBodyDisable` до сих пор «effort "" leaves the provider default», противореча проводу (`applyToBody` мержит disable на `""`, комментарий в теле arm это прямо объясняет) и починенному `ThinksOnWire`; однострочник тем же касанием ⚠ **(в) дописка 07.09:** зеркало `ThinksOnWire` ↔ `applyToBody` не пиньётся ни одним кейсом (мутация арма оставляет батарею зелёной при разъехавшемся зеркале) — при следующем касании файла делегация в `Capability.SuppressesThinking`, ~40 строк, снапшот-нейтрально: `snapshot.go:535` фолдит JSON-форму `llm.Capability`, а не её методы (research/33 Д2) | бэкенд | скоро (мелкий пак или попутно со строкой 46) | правка Go, снапшот не двигает | D39.91, EFFORT_HANDLE Д4 |
| 115 | **`//go:embed` целевых данных — ЯВНЫЙ список файлов: новая ЦЕЛЬ требует правки Go (Д6 отчёта).** `internal/lang/embedded.go:22` перечисляет файлы поимённо, `CompileCheckers` паникует при неполном файле цели ⇒ на канон-вопрос «заработает ли пара, которой в репо НЕТ, без правки Go» ответ сегодня **НЕТ** — дыра в ратифицированной «ФАЗЕ 2 ОБЩНОСТИ ✅» (D39.64), и она не про язык, а про строку эмбеда. Решить форму: `embed data/*` (и как манифест фолдится в `EmbeddedVersion`, чтобы НЕ перекупать чужие пары) против явного списка как осознанного гейта полноты данных цели | оркестратор → бэкенд | когда-нибудь (триггер: первая новая целевая пара; учтён в реестре 108) | отдельное решение | D39.91, EFFORT_HANDLE Д6, D39.64 |
| 108 | **Реестр ЗАГЕЙЧЕННЫХ ТРИГГЕРОВ (триггер → что вернётся → источник) — ВЫСЕЛЕН ДОСЛОВНО в `architecture/13-tech-debt-anchors.md` §Б-108; сверять на каждом переходе горизонта (норма D39.66 «каждое отложено получает носитель» в силе).** ⚠ Живое оттуда: go.work-триггер УЖЕ наступил (`platform/go.mod` заведён) — ⚠ **тот же факт несёт строка 237(а), испр. 05.09: чинится ОДИН раз и там, здесь он ЗАПИСЬ РЕЕСТРА, а не заказ** · вахта маппинга эффорта dspro «early August 2026» · движение тулчейна к go1.27 ⇒ строка 119 ПЕРВОЙ | оркестратор | скоро ($0, гигиена трекера) | завести реестр + сверку в норму лендинга | D39.66, D39.90 |
| 109 | **Продуктовые требования без строки-носителя: ПТ-6 (структура абзацев) · ПТ-7 (слабый оригинал — вопрос владельца) · ПТ-22 (продуктовый интейк настроек) · ПТ-10 (механизм веб-фетча).** Носители заводить при первом касании тем; реестр `product-requirements.md` первичен. Разбор дословно — `architecture/13-tech-debt-anchors.md` §Б-109 | оркестратор/владелец | скоро ($0 — расписать носители) | завести строки/вопросы → диспозиции | D39.90, product-requirements |
| 110 | **Детектор повторов лемм / защита авторских рефренов** (`04-unhappy-paths.md:97,130 п.5`): $0-минимум исполнен промптом (editor.md, пакет-чекеров 02.08), механизм явно не строился — «нет размеченного класса; связка с alignment/Bertalign». Строки-носителя не было; предмет живой, потому что отличить дефектный повтор от авторского рефрена без выравнивания нельзя | бэкенд/полигон | когда-нибудь (с корпусом пилота, строка 85) | размеченный класс → решение | 04-unhappy §5, D39.90 |
| 111 | **Дубль ключа пар-файла: фикс накрыл половину.** D39.82 закрыл строку 53 через `putUniqueDC` в `parseDCCheckers`, но генерик-парсер категорий `parseCategoryRows` (`internal/lang/langpack.go:806-826`, строка `cats[f[0]][f[1]] = val`) по-прежнему МОЛЧА last-wins — а якорь техдолга указывал именно на него. Пар-данные с опечаткой-дублем тихо теряют первую строку | бэкенд | когда-нибудь (малое касание, с любой правкой langpack) | fail-loud + тест | 13-tech-debt-anchors, D39.82, D39.90 |
| 118 | **tools/go.mod — РЕШЕНИЕ ПРИНЯТО (D39.97 п.4): строить отдельным малым паком.** `cmd/tmvet`+`internal/archguard` → отдельный модуль (`backend/tools/`); `make battery` гоняет оба модуля; `tool`-директива Go 1.24 НЕ решает (MVS общий). Выигрыш: бамп инструментов физически не двигает x/net/x/text. Sqlite 1.55 остаётся (D39.97 п.4) | бэкенд | скоро (до следующего бампа зависимостей) | малый пак по D39.97 п.4 | D39.96 п.6, D39.97 |
| 119 | **x/text-детерминизм: вердикт-несущие вызовы НЕ свёрнуты в версии (находки-5/6 приёмки).** `SanitizerVersion` не сворачивает ничего x/text-ного, а `detectCJKLeak` зависит от `width.Fold` (`sanitizer.go:211,687`) — смена x/text перевернула бы вердикт БЕЗ смены снапшота; `ExportNormalize` меняет экспортные байты вне хешей (`sanitizer.go:709`); `xTextVersion` пинит строку go.mod, НЕ скомпилированные таблицы — тулчейн go1.27 переключит x/text на Unicode 17.0.0 МОЛЧА (`tables17.0.0.go //go:build go1.27`; жилец реестра 108). Делать: явные версии-свёртки + механическую сверку «таблицы↔константа» вместо совпадения ⚠ **дописка 07.09 — stdlib-половина того же класса:** `unicode.Version` вплетён в 5 версионных констант, 4 из них — в НЕрепинуемые поля снапшота (`snapshot.go:428/429/431/447`), пятая через `NormVersion` уезжает в `cutTag` (`manifest.go:264`) ⇒ апгрейд тулчейна = громкий `--resnapshot` всех незакрытых книг. ⚠ Это НАМЕРЕННО (`render.go:53` — «weaving unicode.Version makes it a loud --resnapshot»), и вопрос строки не «дыра», а нужна ли громкость на осях estimator/cheapgate, которые вердикта не двигают (research/33 §7.1) | бэкенд | скоро | правка версий-свёрток + тест | D39.96 п.6, отчёт §5 находки-5/6 |
| 120 | ⚠ **ЛИД УКАЗЫВАЕТ НА НЕСУЩЕСТВУЮЩУЮ ФУНКЦИЮ — испр. 05.09:** продового `buildCheckers` нет (`grep -rn 'buildCheckers' backend --include=*.go` → только тест-хелпер), и `lang.Load(` вне тестов не вызывается вовсе. Класс «бейзлайны ключуются по классу, не по паре» может быть жив — но искать его надо не здесь. ⚠ **Где искать (пере-снято 05.09): единственный прод-носитель бейзлайнов сегодня — `backend/internal/config/models.go`, и ключуются они по KIND ПРОВАЙДЕРА, а не по паре;** пара-специфика чекеров живёт данными `internal/lang`. ⇒ строка держится как ревью-вопрос общности («заработает ли пара, которой в репо НЕТ»), а не как известный адрес правки: **прежде чем строить — предъявить дефект на паре, которой нет.** **`buildCheckers` жёстко берёт `lang.Load(root,"zh","ru")`, бейзлайны ключуются по классу, не по паре (§7-8) — приезд ja-ru требует правки Go, против мандата общности §0.1.** Родня строки 115 (явный embed-список целей) — брать одним касанием | бэкенд | скоро | правка Go + тест на паре-которой-нет | D39.96 п.6, отчёт §7-8 |
| 121 | **archguard v2 — остаток (б)/(в)/(г)/(д); (0а)/(0б)/(а) ЗАКРЫТЫ дофиксом D39.97.** Полный фикс-лист посадок приёмки D39.96 с file:line — дословно в `architecture/13-tech-debt-anchors.md` §Б-121 | бэкенд | скоро (остаток: (б) тип вместо свитча · (в) build-теги · (г) 4-й анализатор · (д) семь пропусков) | правка анализатора + посадки | D39.96 п.2/п.6, отчёт §7-9/12/13 |
| 122 | **Гигиена пака стандартов — 11 микро-пунктов, не-блокеры приёмки (D39.96/97).** Полный список дословно — `architecture/13-tech-debt-anchors.md` §Б-122 | бэкенд | когда-нибудь | мелкие правки | D39.96 п.6, отчёт §7-6/7, §9 хвост |
| 123 | **Полигон: `jieba==0.42.1` — build-time зависимость артефакта контраста `eval/exp16/data/jieba_dict_general_zh.txt`** (пере-собран бэкенд-сессией 03.08, полный sha256 сошёлся с пином `16-bank-mining.md`); дописать в манифест окружения полигона с пометкой «build-time, не runtime» | полигон | когда-нибудь | строка манифеста | D39.96 п.6, отчёт §7-4/§6 |
| 124 | **Калибровка снапшота (вопрос владельца 04.08, разбор D39.97 п.5): нацеленность, не агрессивность.** ⚠ **Осей теперь ЧЕТЫРЕ — дописка D39.151:** (г) **идентичность оплаченной работы** («строка диспозиции ↔ вызовы, которые её оплатили») — переселена сюда из строки 195 решением владельца 17.08; родня оси (в), потому что массовое кросс-снапшотное переиспользование подрывает наивную атрибуцию по равенству снапшота; смежный носитель — §7 спеки D15.2. Прежние три оси одним дизайн-паком: (а) недо-чувствительность — вердикт-несущие вызовы x/text не свёрнуты (вход: строка 119); (б) пере-охват — `EmbeddedVersion` фолдит все пары разом → пер-парный хеш (родня 115/120); (в) дешёвая перекупка: `tmctl resnapshot --dry-run` — байт-сверка тел по чекпойнтам (`msgsContentHash`), идентичные юниты пере-привязываются без пере-вызова, платятся только изменившиеся. «Поведенческий отпечаток вместо строки версии» отложен (пол ≠ доказательство) | бэкенд | когда-нибудь (перед МАСШТАБОМ — когда перекупки станут реальными деньгами) | дизайн-пак по D39.97 п.5 | D39.97 |
| 221 | **Джойн «предложено × решено × нерешено» живёт ТОЛЬКО в движке.** Читаемый банк несёт итоги без предложений, карта подписи — предложения без решений; семантика «решено ли» (`ownerHandled`) существует в двух файлах движка и больше нигде (греп по трём зонам). Экран подписи при разморозке фронта заставит платформу пере-реализовать движковый закон у себя — дубль, запрещённый п.6 закона шва. **Фикс:** движок публикует нерешённость (секцией банк-экспорта или отдельной проекцией) — но ТОЛЬКО когда экран закажут: рефакторить под несуществующий экран не надо. Сейчас — ноль кода ⚠ **КОНСИЛИУМ 27.08 (оркестратор №19 + автор движковой двери), итог записан, чтобы его не выводили заново.** **(1) Это ОДИН дефект, а не три:** 221 и 224 — ось СОДЕРЖАНИЯ (проекция не несёт предложенное и не несёт джойн), остаток компаньона — ось СВЕЖЕСТИ (дверь пишет источники мгновенно, проекция ждёт границы прогона, которой при стоящем прогоне не наступает). Классический разрыв CQRS. Чинить порознь = три полу-лечения. **(2) Поле `BankTerm.decision` МЕРТВО СТРУКТУРНО** — довод сильнее прежнего «запрет владельца»: decline выражает себя ИСЧЕЗНОВЕНИЕМ строки, а не значением поля (`writeAutoBank` делает `continue` на `ownerHandled`, `mining.go:709+`), и негде показаться ни в одном из трёх окон; для approve поле избыточно — `status: approved` публикуется. Проверено двумя независимыми трассами. ⚠ Вопрос был СНЯТ ещё D39.144 вместе с ложной посылкой «марш к нулю, 17 из 300»; сегодняшняя потребность иная и уже — перезагруженный экран показывает СДЕЛАННЫЕ ПРАВКИ. **(3) Форма-кандидат Д′:** ДВЕ проекции, у каждой РОВНО ОДИН писатель — «решено на границе» пишет прогон рядом с картой, «решено после границы» пишет дверь при записи; экран склеивает по паре (поверхность, `map_id`), счёт приезжает ПОСЧИТАННЫМ. Правило единственного писателя остаётся буквально, поправка онтологии НЕ нужна. Конверт карты из дофикса-2 получает здесь первого потребителя. ⚠ Колонка `undecided` обязана ехать с тем же НЕ-гейтовым контрактом, что `SignatureState`, иначе пер-термная модель вернётся через новую проекцию. **(4) Подпункт «история»:** `glossary_revisions` построен наполовину — читатель вызывается только из тестов, графа `reason` заполняется литералом `seed-replace`, а ревизия пишется лишь для ОСТАВШИХСЯ строк, то есть журнал слеп к отклонениям; владельческий `note` доезжает до вида (`glossary.go:41,161`) и не публикуется ни одной проекцией. ⚠ Journal append-only: не заказать ревизии без исчезновений задним числом уже не выйдет. **Пак не заказан — ждёт слова владельца** | бэкенд | гейчена разморозкой фронта | аддитивное поле проекции | приёмка двери 27.08, D39.158 |
| 222 | **ВНУТРИкнижный остаток оси арбитра: второй конфиг ТОЙ ЖЕ книги с другим `project_db` пишет ту же пару файлов решений под ДРУГИМ локом**, мимо флока живого прогона. Достижимо по построению: пути решений считаются от каталога `book.yaml` и `book_id`, лок — от `project_db`. Рукотворная конфигурация оператора (две базы одной книге), лечение трогает ратифицированный п.2 закона (второй арбитр на идентичности файлов решений либо отказ при загрузке). ⚠ Межкнижная версия ЗАКРЫТА снятием объявляемых ключей (D39.158 п.5) | бэкенд | когда-нибудь (непропорционально: правка ратифицированного закона ради операторского футгана) | второй арбитр ЛИБО отказ при загрузке | приёмка двери 27.08, D39.158 |
| 223 | **Майнерский хвост за потолком структурно недостижим.** Потолок эмиссии (200) применяется ДО фильтров пригодности, сида и отказов, а детектор кандидатов сида и отказов не видит вовсе — репозиторий пишет это про себя дословно. Замер: 2110 ранжированных → 442 годных во всём алфавите → 117 внутри окна потолка → **325 невидимы постоянно**; отклонение всех 117 не подняло ни одного. ⚠ Решения владельца слотов НЕ освобождают, и это верно СЕГОДНЯ, а не следствие флажка; цитата «пере-предлагается once these are signed or declined» относится только к ОБРАТНОЙ секции. Двигать потолок — трогать фрозен-паритет, отдельное решение. Якорь-пин: `internal/miner/emissioncap_test.go` | бэкенд | когда-нибудь | решение о потолке, не правка | приёмка двери 27.08, D39.158 |
| 224 | ⚠ **ДВИЖКОВАЯ ПОЛОВИНА ЗАКРЫТА 07.09 (`D39.225`): стоп публикует свои предложения секцией того же сайдкара, порядок запинен мутациями. ОСТАЁТСЯ ПЛАТФОРМЕННАЯ — у секции сегодня НОЛЬ читателей** (`json:"proposed` в `platform/` — 0 хитов), и до её лендинга это сознательно заведённый класс A онтологии банка. **Банк-экспорт на стопе ПУСТ** — проекция, наиболее пустая ровно в момент, когда её читает экран подписи. Замерено: стоп с двумя предложенными термами даёт `total=0`, авто-банк на стопе отсутствует, потому что он пишется только в ветке авто-продолжения; при этом комментарий рядом называет стоп «границей, которую читает экран подписи», а платформа читает именно `.bank.json`. Член класса «проекция без контракта потребителя» (`architecture/18-bank-ontology.md`) ⚠ **ФОРМУЛИРОВКА ПРОТУХЛА, испр. оркестратором 05.09 по итогу стратегического веера:** лид говорит «экспорта на стопе нет, пишется только в ветке авто-продолжения» — сегодня `exportBank(ctx, "bank-mining/signature-stop")` НА СТОПЕ ЕСТЬ (`backend/internal/pipeline/mining.go`, греп `signature-stop`). Отсутствует не ВЫЗОВ, а НАПОЛНЕНИЕ: `exportBank` проецирует таблицу глоссария, а майненные строки попадают в неё только через `writeAutoBank`+`seedGlossary`, и оба лежат ВНУТРИ ветки `if !stopping`. ⇒ Экран подписи читает артефакт, гарантированно пустой ровно от тех строк, ради которых открыт. **Кто пойдёт чинить по прежнему тексту — будет искать несуществующий пропущенный вызов.** ⚠ **дописка 07.09 — закрывать ВМЕСТЕ с пином ПОРЯДКА, иначе фикс не сторожится ничем:** мутация «`exportBank("bank-mining/signature-stop")` раньше `writeAutoBank`/`seedGlossary`» и мутация «`exportBank("run-start/seeded")` раньше `seedGlossary`» (`bookrun.go:174/180`) обязаны краснеть; сегодня в каталоге про порядок 0 записей у `bookrun.go` и 0 из 8 у `mining.go`. Прецедент — строка **257** → пины `volumeslot_test.go`; подмножество каталога в `make battery` реально (`tmmutate -id`, `cmd/tmmutate/main.go:88`), пакет `internal/pipeline` проходит за 15 с (замер 07.09: `go test ./internal/pipeline/ -count=1` → `ok 15.053s`) (research/33 Д9) | бэкенд + платформа | скоро (держит экран подписи вместе с 221) | публиковать предложенное на стопе | приёмка двери 27.08, D39.158 |
| 225 | **Гейт «строка `open`, а лекарство уже в дереве».** При лендинге пересекать ПОЛНЫЕ пути застейдженных файлов с якорями открытых строк регистра и бэклога; совпадение — вопрос лендеру, а не находка следующего пака. Замерено прежде решения: по именам файлов 22 совпадения, почти все ложные; по полным путям 2, оба настоящие, и один из них (`PD-157`) убил мой же лендинг `d1eb8a9`. Норма-половина уже стоит в `platform/docs/ENGINEERING_STANDARDS.md` §3 п.8; здесь — машинная половина, режимом `counts.py` | оркестратор | скоро (окупился до постройки) | режим `counts.py`, берущий список путей и печатающий открытые строки, чьи якоря в них целят | приёмка пака P8-REVIEW 27.08, D39.159 п.7 |
| 226 | **История ПРЕДЪЯВЛЕННОГО не ведётся — «почему меня не остановило на этом термине» ответить нечем.** Карта и человеческая таблица стопа перезаписываются каждым прогоном, память флажка — плоское множество поверхностей без `map_id` и без времени. Это прямая расплата за то, что стоп срабатывает ОДИН раз (кластерная память, названный остаток дофикса-2), и единственная возможная диагностика спора. Кандидат в пак решённости, не заказ. ⚠ Шестое, названное консилиумом и оставленное владельцу: авторство и время решения — сегодня цена нуля (владелец один), станет нужным при мультипользовательской платформе, и тогда его захотят ЗАДНИМ ЧИСЛОМ | бэкенд | скоро (диагностики нет вовсе) | движок метит предъявленное `map_id` и временем; оверлей отвечает «что предъявлялось на прошлом стопе» | консилиум по читающей стороне банка 27.08 |
| 250 | **Заголовок глоссария на проводе ОПИСЫВАЕТ маркер, которого после пака больше нет — живая строка с висячей ссылкой.** Строка данных `ru glossary_header` (`backend/internal/lang/data/injection.txt`) дословно объясняет модели: «строки с пометкой ⟨проверить⟩ — неподтверждённые кандидаты», а пункт 3 вайр-батча снимает маркер с провода по `D39.104` п.2 ⇒ на проводе не останется НИ ОДНОЙ помеченной строки, а заголовок продолжит объяснять пометку. ⚠ Это НЕ мёртвая строка данных (те — `editor_unverified_header` и `unverified_marker`, они просто перестают читаться), это ЖИВАЯ строка, которую читает модель. По `D39.104` п.1 клаузула становится ВАКУУМНОЙ, а не ложной, вред не измерен — поэтому не блокер. ⛔ **Чинится ТОЛЬКО правкой `injection.txt`, а она двигает `EmbeddedVersion` → `cutTag` → ключ манифеста → снос `unit_resolutions` книги (строка 198).** Носитель — ближайшее ОКНО правки эмбед-данных: строка **160** идёт своим паком и всё равно бампает форму манифеста. Найдено бэкенд-сессией вайр-батча 04.09 — она правильно НЕ тронула и принесла предмет | бэкенд | скоро (в окне строки 160) | правка `injection.txt` в окне 160 | пинг бэкенд-сессии 04.09 |
| 251 | **Банковый контур в `pipeline-c1.yaml` требует АРТЕФАКТА, которого в git нет и быть не должно — первая же выкатка после лендинга откажется стартовать, если его не положили.** ⚠ **УТОЧНЕНО 08.09 живым прогоном — ЭТО ДВА РАЗНЫХ ДЕФЕКТА С РАЗНЫМ ЛЕЧЕНИЕМ, и прежняя формулировка сливала их в один.** (1) Путь `contrast_path` В КОНФИГЕ ЗАДАН, файла нет ⇒ `os.Open` (`mining.go:69`) — отказ ГРОМКИЙ, с флагом `--verify-bank` и без него; боевой c1 путь задаёт, значит это «развёртывание не поднимется». (2) ⛔ **СНЯТО 08.09 — Я СДЕЛАЛ ЭТУ СТРОКУ ХУЖЕ, ЧЕМ ОНА БЫЛА.** Вчера сюда попало «на конфиге без `contrast_path` контур МОЛЧА МЁРТВ» — неверно для конфигурации, которая одна и имеет значение: `internal/config/pipeline.go:1133` ОТКАЗЫВАЕТ загрузку, если `gates.terminology.enabled` и путь пуст, и стоит это с **04.09** (`b8154cd`) — на четыре дня раньше моей «правки»; второй вход закрыт `runner.go:349`. Тихий `return false, nil` в `mining.go:58-66` достижим только при ВЫКЛЮЧЕННОМ гейте, то есть когда контур и не заказан. Рантбук требование несёт (`platform/deploy/README.md`, 8 упоминаний). ⚠ Класс ошибки: принял формулировку зоны, проверил ОДИН путь по коду и не спросил, достижим ли он при живом конфиге. **Живой остаток строки другой** — пар-перекос: `mining.contrast_path` есть факт ИСХОДНОГО языка в пар-агностичном конфиге (задан в 3 из 5 конфигов `backend/configs/`), то есть это цель №2, а не «выкатка не поднимется». ⇒ лечение (1) — положить артефакт при выкатке; лечение (2) — сделать отсутствие контура ВИДИМЫМ без флага. Подтверждено чтением кода оркестратором и живым прогоном зонной сессии 08.09, которой пришлось воспроизводить артефакт по запиненному рецепту `docs/experiments/16-bank-mining.md` (sha сошёлся), потому что на машине его нет. Оба банк-роля живут ВНУТРИ стопа майнинга, а `runBankMiningStop` (`backend/internal/pipeline/mining.go:58`) возвращается РАНЬШЕ построения кандидатов при пустом `mining.contrast_path` ⇒ без корпуса контраста терминолог и классификатор не исполняются ВООБЩЕ, чем бы ни были заполнены их гейты. Артефакт — общечастотный словарь jieba (`.gitignore:38`: «jieba 0.42.1 dict.txt, 5MB — SHA pinned in the report, **reproducible**»), рецепт и sha256 `7197c321…` — `docs/experiments/16-bank-mining.md` (греп `jieba_dict_general_zh`). ⚠ **Риск ограничен и это ГЛАВНОЕ:** артефакт не утерян, а ВОСПРОИЗВОДИМ по запиненному рецепту; дыра в том, что требование не доехало до РАНТБУКА развёртывания (`platform/deploy/README.md` о нём не знает), и оператор узнаёт о нём только от гарда. Гарды поставлены паком и они правильные: загрузка ОТКАЗЫВАЕТ при включённом гейте с пустым ключом, наличие файла проверяется на ПИШУЩЕМ пути рядом с `CheckKeys` — то есть до оплаченной черновой волны, а не после неё. ⛔ **Что делать:** требование в рантбук платформы (её зона, пинг) + слово владельца/оператора, что файл лежит на боевой машине, ДО первой выкатки после лендинга. ⚠ **Вторая половина, вскрытая тем же включением:** корпус контраста — факт ИСХОДНОГО ЯЗЫКА, а `mining.contrast_path` живёт в конфиге пайплайна, который по построению пар-агностичен (цель проекта №2). Перекос не заведён паком, а вскрыт им; пара, которой в репо нет, потребует своего корпуса и своего ключа | бэкенд+платформа | скоро (до первой выкатки после лендинга вайр-батча) | пинг рантбуку + слово оператора; пар-перекос — отдельным решением | бэкенд-сессия вайр-батча 04.09 |
| 252 | **Две гарантии не прибиты — мутации сессии ПЕРЕЖИЛИ всю батарею** (собственные посадки бэкенд-сессии вне шести пунктов заказа, 04.09; из восьми посадок шесть красные, две выжили и НЕ чинились как вне-заказные). **(а) `StickyDepth = 2 → 1` не ловит НИКТО** — глубина окна липкости меняется молча. **(б) `priorityRank`, отбрасывающий приоритет доверия** (подтверждённые строки раньше неоднозначных в бюджете инъекции), **не ловит НИКТО** — то есть порядок, решающий, ЧТО попадёт в инъекцию при нехватке бюджета, можно перевернуть безнаказанно. ⚠ Класс тот же, что дал паку «число согласия» три неприбитых свойства: заявленное поведение без пинящего теста. Сессия правильно НЕ чинила вне заказа и принесла предмет | бэкенд | скоро (ближайшим касанием инъекции) | по тесту на гарантию + запись в `cmd/tmmutate/mutations.json` | собственные посадки бэкенд-сессии 04.09 |
| 253 | ⚠ **ДВИЖКОВАЯ ПОЛОВИНА ЗАКРЫТА 08.09 (`D39.228`): полнота консолидации доезжает до сайдкара и до stdout-экрана подписи. ОСТАЁТСЯ ПЛАТФОРМЕННАЯ — поля на `BankPage` нет, читателей у секции `consolidation` НОЛЬ**, и до её лендинга это сознательно заведённый класс A онтологии банка (⛔ бит `complete` платформа берёт ГОТОВЫМ, не выводит у себя: у движка он считается от среза РЕНДЕР-паса, а срез классификатора полноты банка не означает). ⚠ испр. 08.09: акт `D39.228` объявил строку закрытой ЦЕЛИКОМ — неверно, лечение (б) по телу ниже требует «полнота в сайдкар + поле на `BankPage`», и вторая половина не построена. Ниже — тело находки. **НА ЭКРАНЕ ПОДПИСИ БАНКА ПОДПИСЫВАТЬ НЕЧЕГО, а сам подписываемый банк НЕПОЛОН — две половины одного шва, найдены ПЕРВЫМ живым прогоном 04.09.** **(а)** ⚠ **ЭТО ТОТ ЖЕ ДЕФЕКТ, ЧТО СТРОКА 224 — испр. 05.09:** корень там уже найден и назван (майненные строки пишутся внутри ветки `if !stopping`), поэтому «разобрать порядок публикации» здесь заказывать НЕЛЬЗЯ — работа удвоится. Половина (а) закрывается лендингом 224; живой в этой строке остаётся только (б). Прогон встал `awaiting_bank`, `GET /bank` отдал `total 0, signed 0` — при том что рядом лежали `mined-signature.yaml` 49 КБ и `bank-stop.txt` 60 КБ, а движок держал 82 неразобранные поверхности; термины появились в read-модели только на СЛЕДУЮЩЕМ прогоне (`bank export refreshed … terms=83`). Платформа читает сайдкар честно: 0 значит 0 ⇒ либо сайдкар пишется не в тот момент, либо стоп наступает РАНЬШЕ публикации банка. Корень скорее движковый. **(б)** Банк, который пользователь подписывает, ЧАСТИЧНО КОНСОЛИДИРОВАН, и платформа об этом не знает вовсе: терминология урезала план под бюджет ДО первого вызова (`batches_dropped=5`, `consolidated=38 declined=0 unanswered=47` из 85), а поверхности нет ни одной — `grep -rn 'consolidat\|unanswered\|batches_dropped' platform/internal/ --include=*.go` → **0**, аллоулист сайдкара несёт только термины. ⇒ **пользователь подписывает как ПОЛНЫЙ банк то, что движок сам называет неполным.** Лечение (б) — КАНАЛ: полнота консолидации в сайдкар + поле на `BankPage`; лечение (а) — разбор порядка «стоп против публикации». ⚠ Обе половины на шве, чинятся согласованно | бэкенд+платформа | скоро (до первого внешнего пользователя) | разбор порядка публикации + канал полноты | наблюдение платформы за живым потоком 04.09, H10/H11 |
| 254 | **Шесть движковых ловушек, увиденных ПЕРВЫМ живым прогоном (04.09) и НЕ тронутых платформой — чужая зона.** ⚠ **ОДНА ИЗ ШЕСТИ РЕШЕНА ВЛАДЕЛЬЦЕМ 05.09 — остальные ПЯТЬ живы, строку не закрывать** (испр. 05.09; строка 285 закрывает ровно эту одну и не больше). ⛔ Решённая — самая дорогая: `manifest` на пустом файле даёт exit 11, а интейк на 11 УДАЛЯЕТ ЗАГРУЗКУ ⇒ пользователь, приславший пустой файл, терял его. **Лечение названо владельцем: fail fast на загрузке** — строка **285**. · `tmctl build` не читает контекст: всегда SIGKILL, staging-файл `.tmp-*` остаётся · потолок бросает летящие вызовы, они списываются нулём (`PD-441`, замер: отмены на 120756/156469/156470 мс) · терминология МОЛЧА режет план под бюджет (вход строки 253б) · сайдкар банка пуст в момент стопа (вход 253а) · **`build --format X` без `--out` удаляет соседние форматы** — ловушка для оператора с руками. ⚠ Ни один из шести не найден чтением кода за месяцы — все шесть увидены за один прогон | бэкенд | скоро (ближайшим касанием соответствующего пути) | по пунктам; часть — райдерами других паков | наблюдение платформы за живым потоком 04.09, H21 |
| 255 | **Первый живой прогон НЕ КОСНУЛСЯ поверхностей, ради которых часть кода построена — и это надо знать прежде, чем говорить «поток проверен».** **SSE-поток не открывался НИ РАЗУ** (весь прогресс читался поллингом ⇒ `platform/internal/httpapi/stream.go` живым прогоном не проверен вовсе) · читающая поверхность глав и пар не читалась · пользовательский `stop` не звался — из ТРЁХ способов кончить прогон проверены два · апгрейд движка, `books --migratable`, `run unquarantine` не трогались · всё измерено на книге **57 КБ**, на корпусной 23 МБ переносить нельзя. ⚠ Это не дефект, а ГРАНИЦА утверждения: «цикл замкнут живьём» верно ровно про ту цепь, которую прошли. Следующий платный прогон обязан закрывать этот список, а не повторять пройденное | платформа | скоро (следующий платный прогон) | список к покрытию | наблюдение платформы за живым потоком 04.09, H22 |
| 256 | **Лейбловая ветка `CheckKeys` прибита только СПИСКОМ — БЛИЗНЕЦ денежной дыры, закрытой на безлейбловой.** Безлейбловую ветку круг 3 починил определением `gateModels()` и прибил вызовом самого `CheckKeys`; лейбловая по-прежнему держится тестом на СПИСОК (`TestABankModelIsAReachableModel`) — тем самым способом, про который тот же круг записал «пин на списке не есть пин на префлайте». Посадка круга 4: лейбловая ветка собирает модели стадий вместо `ReachableModels()` — ВЕСЬ пакет зелёный. Проба предъявлена: лейблованная книга с банк-моделью на провайдере без ключа проходит префлайт целиком. Симптом денежный и тот же: покупается черновая волна, смерть на воротах. ⚠ Не чинилось только потому, что круг свёрнут решением владельца | бэкенд | скоро | пин на вызове `CheckKeys` для обеих веток + проба под лейблом | круг 4 петли, X40 |
| 257 | **Порядок `bound()` перед `reconcile` не держится ничем, и цена — исчезнувшее сообщение оператору.** Перенос блока `bound()` после `reconcile` пережил весь пакет. Проба: книга в одну главу, второй прогон под грантом 1, редактор отказывает — единственная работа вне гранта флагуется; оригинал печатает «1 PAID FOR BUT FLAGGED», под посадкой **отчёт об объёме = nil**, то есть раскрытие, ради которого он построен, пропадает целиком. ⚠ Комментарий коммита посылает читателя в юнит-тест `volumeScope`, который порядок в `waverun` увидеть не может — второй экземпляр класса «тест утверждает не то, что думает» | бэкенд | скоро | пин порядка в `waverun`, а не в `volumeScope` | круг 4 петли, X14 |
| 258 | **Конструктор `classifyInputFor` можно захардкодить на `ru`/`zh` — вся батарея зелёная, и причина СТРУКТУРНАЯ: через раннер нет ни одной фикстуры с не-ru целью.** Есть только zh→ru и ja→ru. Рефлексивный пин круга 3 ловит «поле нулевое», но не «поле взято не у книги». Пробы предъявлены: →ja книга с китайским выводом под посадкой перестаёт быть →ja. ⚠ Бьёт прямо в цель №2 (ревью-вопрос «заработает ли пара, которой в репо нет, без правки Go»): сегодня ответ на него не может дать ни один тест. Родня — 259 | бэкенд | скоро | фикстура не-ru цели ЧЕРЕЗ раннер + пин «поле взято у книги» | круг 4 петли, X1/X2/X3 |
| 259 | **Настоящей латинописьменной цели в репозитории НЕТ — `target-en.txt` не существует, и →en достижим только через пустое объявление.** Следствие: часть общности проверяется рассуждением, а не тестом, и пара, которой в репо нет, не может быть предъявлена живьём ни одним прогоном. Замер общности 04.09: ветвлений Go по конкретному языку два на обе зоны, оба — проверка на пустоту; книжной специфики в Go нет, кроме константы худшей строки банка (строка 40) | бэкенд | скоро (гейт второй пары) | минимальный langpack →en + прогон на нём | замер общности оркестратора 04.09 по требованию владельца |
| 260 | **Экран цели калиброван на ОДНОМ сянься и даёт ложный `off_target` на латинице-тяжёлом здоровом русском** (0.461 с пиньинем при пороге). ⚠ Ложный флаг ЭСКАЛИРУЕТ, то есть стоит ПЛАТНОГО хопа за здоровый текст — это деньги, а не только шум. Порог и пол улики обязаны быть пере-калиброваны на корпусе, включающем латиницу-тяжёлый русский | бэкенд | скоро | пере-калибровка на расширенном корпусе + пин границы | самоотчёт бэкенд-сессии о непокрытом, круг 3 |
| 261 | ⛔ **ОСТАТОК СНЯТОЙ СТРОКИ 277 ЖИВЁТ ЗДЕСЬ (возвращён 05.09 по ревью — при закрытии 277 он едва не потерялся): остаток `PD-441` = **261 + 262** (третья часть, строка 277, ПОСТРОЕНА и закрыта D39.206 — «одним паком» уже невозможно).** Пак «денежный стоп» (акт D39.206) снял только ОТМЕНУ допущенного; **структурный корень невидимого расхода — эта строка**, а сверх-утверждение комментария ветки отмены — строка **262**. ⇒ платформенной зоне: `PD-441` закрывать «паком денежного стопа» НЕЛЬЗЯ, он закрыт наполовину. **`BilledDecodeError` виден только когда ретрай НЕ спас: успешный ретрай стирает оплаченную попытку из леджера.** Тип заведён, чтобы оплаченный-но-нечитаемый вызов стал ВИДЕН (рантайм доседает по оценке), но `retryLoop` при успехе возвращает ответ и предыдущую ошибку выбрасывает — рантайм видит один успешный ответ и седит его `Usage`. Оплаченный 2xx перед ним не попадает никуда. ⚠ Бьёт не в отчётность, а в ЦЕЛОСТНОСТЬ потолка: допуск выдан под ОДНУ оценку, а под ней могло пройти до трёх запросов (`MaxAttempts` 3), и `Reserve` об этом не узнает. Комментарий рядом сам говорит «each retry is a new billed 2xx» — авторы знали и закрыли только детерминированный случай (усечение). ⚠ ЧАСТОТА пути НЕ измерена | бэкенд | скоро (вместе с денежным паком) | единица учёта = единица биллинга + вендор-факт по правилу квирков | чтение под вопрос, бэкенд-сессия 04.09 |
| 262 | **Комментарий ветки отмены — сверх-утверждение: «No 2xx ever arrived: nothing was billed» описывает ветку ШИРЕ, чем она есть.** Верно для отказа соединения, DNS, таймаута до первого байта и терминального 4xx; ложно для вызова, который отменили МЫ после начала генерации — он приходит в ту же ветку через `context.Canceled`. Правка отложена намеренно: ветка денежная, лечение структурное (см. 261), однострочная правка фразы разъедется с решением | бэкенд | скоро (вместе с 261) | привести ветку и её описание к одному радиусу | чтение под вопрос, бэкенд-сессия 04.09 |
| 263 | **Дизъюнкты предупреждения банкноты и `forWrite` не прибиты по отдельности** (позитивная фикстура без обоих входов, негативная — с обоими): пережили посадки «нет контраста», «нет пака», «предупреждать и на read-open». **`WB15` несёт тот же дефект ложного пина, что найденный и починенный `WB36`** — одиночный сдвиг порога под `TestGoldenDeterminism`: на чистом литерале голден не двинется и запись выживет при целой гарантии. **AST-тест исчерпаемости парсит ТОЛЬКО `disposition.go`** — `FlagReason`, объявленный в другом файле, в карту не попадёт при зелёном тесте. **Дайджест корпуса не покрывает `provenance`** — адрес пере-снятия, подмену которого дайджест не видит | бэкенд | когда-нибудь | четыре независимых пина | круг 4 петли, X11/X12/X13 · WB15 · X9 · X30 |
| 265 | **Питоново зеркало полигона держит ВТОРУЮ копию таблицы плейсхолдеров движка, и она разошлась: `genre` есть, `book_id` нет.** `eval/bank_arbitration/editor_wire_probe.py` — ПЛАТНАЯ проба, читающая ШИППИНГОВЫЙ `backend/prompts/zh-ru/editor.md`, на неё ссылаются ещё **25** скриптов (`grep -rl editor_wire_probe eval --include=*.py`; ⚠ испр. 05.09, первая редакция говорила «девять»); 27 промтов под `eval/` несут `{{genre}}`, который движок ОТКАЗЫВАЕТСЯ собрать при загрузке. ⇒ замеры идут на проводе, которого в проде не существует, и это «третий путь», которого в Go больше нет. ⚠ Зона ПОЛИГОНА — чинит она, носитель заведён оркестратором пингом | полигон | скоро (перед следующим платным замером) | зеркало читает таблицу движка, а не держит копию | передано бэкенд-сессией 04.09, чужая зона |
| 266 | **Правки кругов 3 и 4 петли не ревьюил НИКТО — круг свёрнут решением владельца, а не замкнут.** Замеренная база, из-за которой это долг, а не формальность: ДВАЖДЫ подряд дефект вносил фикс предыдущего круга (круг 2 объявил денежную дыру закрытой — круг 3 показал, что она открыта; ратификация оркестратора по дедупу внесла живой дефект — поймала зона). Круг 3 добавил ~2000 строк и не ревьюил из них ни одной; круг 4 — две правки, обе проверены исполнением, но не чужими глазами. ⚠ Дисциплина петли исправлена эрратой: круг крутит СЛЕДУЮЩАЯ сессия по готовому паку, а не прежняя — правило «сессия отрабатывает скоуп и завершается» бьёт норму петли | бэкенд | скоро | проход свежей сессии по диффу `c77c3ba`+`2e13cd1` | решение владельца 04.09 остановить полировку |
| 268 | **Гейт версии контракта у фронта читает СВОЁ зеркало, а не канон — и потому слеп по построению.** `frontend/src/api/contract.test.ts` сверяет `${cwd}/docs/api-contract/openapi.yaml` с фикстурой, то есть копию с копией, и зелен при любом отставании; соседний тест сравнивает только МАЖОР, а он у `0.2.3` и `0.10.0` одинаков — ноль. Зеркало отстало на ВОСЕМЬ миноров. Сравнение: тот же класс гейта у платформы читает КАНОН с диска и поймал расхождение `0.9.0→0.10.0` в тот же час. ⚠ Зона фронта ЗАМОРОЖЕНА — строка ждёт разморозки, но входит в перечень первого касания | фронт | скоро (первое касание при разморозке) | перенацелить гейт на канон | находка платформенной сессии 04.09, подтверждена оркестратором |
| 272 | **ШАБЛОН КНИГИ ДЕПЛОЯ ОДИН НА ВСЕ ПАРЫ, а в нём лежит ПАР-СВЯЗАННОЕ значение — `transcription: palladius`.** Платформа рендерит `book.yaml` из единственного операторского шаблона и подставляет ровно пять ключей (`book_id · title · source_lang · target_lang · source_file`); всё остальное едет из шаблона нетронутым. Палладий — система транскрипции ДЛЯ КИТАЙСКОГО. Движок значение не валидирует (свободная строка) и подставляет прямо в промпт. ⇒ Деплой, объявивший `zh>ru,ja>ru`, отдаёт КАЖДОЙ японской книге инструкцию транскрибировать по-китайски: не отказ и не флаг, а тихо неверные имена во всей книге — ровно тот класс брака, ради которого продукт существует. ⚠ Чинить придётся не одну книгу: значение вшито в `book.yaml`, который платформа НИКОГДА не перезаписывает (`O_EXCL`) | платформа+бэкенд | скоро (гейт второй пары) | пар-связанные ключи шаблона + валидатор значения в движке | критик полноты стратегии 04.09 |
| 273 | **ПАР-ШОВ ЛОМАЕТСЯ АСИММЕТРИЧНО: промпт-пак падает ГРОМКО, целевые ДАННЫЕ выключаются МОЛЧА — вместе с банком.** Отсутствие промптов пары — жёсткая ошибка загрузки («never silently substitute another pair's conventions»). Отсутствие ЦЕЛЕВЫХ данных — тишина в трёх местах: `lang.InjectionTextsFor` на незнакомом таргете возвращает пустое, обе банк-инъекции рендерят пустоту (`if !tx.HasData() { return "" }`), `LoadReaderWords` отдаёт значки вместо слов без ошибки. ⇒ Книга на новый таргет переводится ЦЕЛИКОМ и за ПОЛНЫЕ деньги, но БЕЗ банка-как-закона — то есть без единственного механизма, держащего термины консистентными на всю книгу, без $0-чекеров цели и с пометками из значков в выданном файле. Ни ошибки, ни варнинга, ни поля в отчёте сборки. ⚠ Строка 32 закрыта формулировкой «инертна ПО ОТСУТСТВИЮ данных» — для ЧЕКЕРОВ это хорошо, для БАНК-инъекции такого вывода не делал никто | бэкенд | скоро (гейт второй пары) | префлайт готовности таргета: банк-данные есть ⇒ работаем, нет ⇒ громко | критик полноты стратегии 04.09 |
| 275 | ⚠ **ПЕРЕ-СНЯТА 05.09 СЛОВОМ ВЛАДЕЛЬЦА — прежняя формулировка «КАЧЕСТВО НЕ МОЖЕТ СТАРТОВАТЬ ВООБЩЕ» БЫЛА НЕВЕРНА (ошибка оркестратора).** Она называла четыре гейта; из них **три сняты словом владельца, четвёртый гейтом не был** (разбор — `D39.198`): **13а** веса рубрики НЕ НУЖНЫ — веса меряют РАЗНЫЕ узлы (консистентность — банк памяти, выдумки — редактор, художественность — редактор И черновик), единого веса быть не может, а одно взвешенное число измеряет, но не ДИАГНОСТИРУЕТ · **24** профили голоса — приоритет №3, подписи владельца не требуют («зачем мне это подписывать») · **149** разморозка панели не нужна: пока идут доработки, менять жильцов ролей незачем · **55** прогоняем на ТЕХ ЖЕ текстах (мастер Гу, Жан-Кристоф), оговорка про претрейн остаётся ОГРАНИЧЕНИЕМ ВЫВОДА, а не требованием новой книги. **ЧТО ОСТАЁТСЯ ЖИВЫМ В ЭТОЙ СТРОКЕ:** привязать каждый класс дефекта к УЗЛУ и мерить по узлам; поставить порог остановки для приоритетов №1 и №2 (разъехавшийся термин — стоп, выдумка — стоп, сухая фраза — не стоп). ⚠ Консистентность проверяема ДЕТЕРМИНИРОВАННО за $0 — это ГЕЙТ, а не строка рубрики; ближайший её носитель — строка **267** | полигон+бэкенд | скоро | привязка классов к узлам + пороги остановки для №1 и №2 | решение владельца 05.09, `D39.198` |
| 276 | ⭐ **ФОРМА ЗАКАЗА ПЕРЕВОДА — решение владельца 05.09, ратифицировано D39.196.** На аккаунте **баланс в ДЕНЬГАХ** и он виден. Человек стартует перевод; хочет задать потолок — тянет ползунок **в деньгах**; рядом ответ на его настоящий вопрос: **хватает на полную книгу или нет**. Хочет задать объёмом — второй ползунок: **ГЛАВЫ когда книга распозналась**, **ЗНАКИ когда нет** (о нераспознавании говорим ЯВНО). Старт = **холд с баланса**. Отдельная кнопка **«перевести книгу целиком»** — за целую книгу оценка точнее, чем за произвольный кусок. ⚠ **Две ручки связаны проекцией:** объём — ЗАКАЗ (главная), деньги — ЛИМИТ (вторая); тронутая последней ограничивает, другая пересчитывается и показывается производной («5 глав ≈ $0.55, зарезервируем до $0.8»); минимум денежного ползунка = неделимый шаг движка, чтобы ползунком нельзя было выразить невозможный заказ. Не тронута ни одна ⇒ заказ = вся книга. ⚠ **Цифра на экране — ПАРА, а не точка:** «ожидаемо ≈ $1.1, зарезервируем до $1.6, спишем по факту», и закрытие фактом после прогона — проекция имеет дисперсию (редакторские вызовы 25–90 % worst-case), точечное число превратится в «сказали 1.14, списали 1.31». Главный ответ — фраза, цифра рядом и мельче. ⚠ **Запрет «денег в UI» ОТОЗВАН владельцем** (D39.196 п.2): виден баланс, потолок, холд; цены моделей и стадий — нет. «Страница» из контракта убирается совсем — владелец назвал ЗНАКИ, форматирование «≈67 стр.» это локаль фронта. Исполнение — **279–283** (⚠ испр.: 277 и 278 ПОСТРОЕНЫ лендингом `81a89e9` и сняты) | движок+платформа+фронт | скоро | решение принято и ратифицировано D39.196; исполняется **279–283** (277 и 278 закрыты) | решение владельца 05.09 + сведение с внешним рецензентом |
| 279 | ⚠ **ПРОТУХЛА — испр. 06.09: половина ИСПОЛНЕНА без пометки, половина осталась остатком без имени.** Форма `OrderOptions` (`chapters_left`, `affordable_chapters`, `verdict`) стоит в каноне с минора 0.11.0, а `shortfall` в каноне ОТСУТСТВУЕТ (ноль вхождений); тело `D39.208` строку не называет, ✅ не стоит. Класс `D39.167` п.1: акт лендинга обязан быть сверен со строками. ⇒ разделить: исполненное пометить, остаток `shortfall` назвать своим предметом. **ШАГ 3, КОНТРАКТ (минор, полоса ломающих правок мажора 0 законна): заказ объёмом.** `ceiling_chapters` → `chapters` со смыслом ОБЪЁМА (`null` = вся книга) · `CeilingBounds{min,max,default}` → `OrderOptions{chapters_left, affordable_chapters, verdict: covers_all|covers_part|covers_none, blocked}` · `PausedReason` += `run_limit_reached` (и `credit_exhausted` СТАНОВИТСЯ правдой — сегодня лжёт при 34% баланса, наблюдение H14) · `Run` += `ordered_chapters`/`delivered_chapters`. ⚠ Фразы — ДАННЫМИ по коду причины и локали, не литералом. ⚠ **ПЕРЕ-СНЯТО 05.09 под D39.196:** наружу ВЫХОДЯТ баланс, потолок заказа и холд — деньгами; контракт получает `balance`, `estimate{expected, hold}` под выбранный заказ, границы денежного ползунка `{min: неделимый шаг, max: баланс}` и `shortfall` у паузы; процент остатка остаётся СИГНАЛОМ «мало/пусто». НЕ выходят: цены моделей, стоимость стадий и вызовов, структура НАШИХ расходов. Плюс `OrderOptions` обязан нести ТРИ вида заказа (вся книга · знаки · до главы N), а не только главы. Ремедиа-таблица `resumeRun` упрощается: «Продолжить» — новый прогон ТОГО ЖЕ заказа | контракт | скоро | минор контракта одним актом с платформенной половиной | согласование 04.09 |
| 280 | ✅ **ИСПОЛНЕНО ЛЕНДИНГОМ 06.09 — акт `D39.208`.** Заказ живёт на КНИГЕ и хранится ИДЕНТИЧНОСТЬЮ (`books.ordered_through_chapter_id`), а не ординалом; холд считается от проекции движка; `--max-units` едет в argv. ⚠ **Кроме ОДНОЙ позиции, от которой зона отказалась с доводом и которая живёт отдельно:** денежный ползунок объявлен на проводе, но отправить его нечем, и оценки под ВЫБРАННЫЙ заказ нет. Прежняя редакция ряда: **ШАГ 4, ПЛАТФОРМА: заказ живёт на КНИГЕ, холд считается от проекции, `--max-units` наконец едет в argv.** `books.ordered_through_chapter` (null = вся книга) — сегодня интент живёт на ПРОГОНЕ, оттого и неловкость «поднять лимит = НОВЫЙ прогон с бо́льшим `ceiling_chapters`»; с заказом на книге «Продолжить» после пополнения тривиален, и дверь пере-прохода встаёт рядом вторым типом заказа. Холд = `min(баланс, проекция × k)`; `bookCap = committed + холд` (`PD-158` цел). В argv добавляется `--max-units` = сумма юнитов заказанных глав минус доставленные. Удаляются `DefaultPerChapter`, `Scale` и `draftWork`: план движка становится РАВЕН заказу, и «черновики на весь потолок при нуле готовых глав» исчезает структурно. Закрывает `PD-410`, `PD-440`, `PD-446`. ⚠ **ПРЕДУСЛОВИЕ, названное отдельно: `PD-422`** — `--resnapshot` передаётся УСЛОВНО, а условие ставит только правка банка; рост авто-банка от майнинга флага не ставит. Частичный заказ на майнящей книге растит банк ⇒ следующий заказ без `--resnapshot` умрёт на снапшот-гарде, холд взят, попытка сожжена. Взять В ТОТ ЖЕ пак | платформа | скоро | заказ на книге + холд от проекции + проводка `--max-units` + PD-422 | согласование 04.09 |
| 281 | **ЗАМЕР: сколько наших денег стоит тысяча ПЛОТНЫХ и тысяча РАЗРЕЖЕННЫХ знаков по стадиям и парам.** Цель — НЕ константа (D39.165 п.1г прямо запрещает ставку константой), а **дисперсия проекции**: коэффициент k для холда и честность вердикта «хватит ли». Снимать есть из чего и это $0: `find -L books` даёт 162 базы прогонов, в `request_log` лежат `chapter · chunk_idx · stage · prompt/completion_tokens · cost_usd · tm_hit`, исходник по юниту отдаёт `tmctl export --pairs` бесплатно. Метод: по юниту плотные/разреженные знаки против суммы `cost_usd` при `tm_hit=0`, по стадиям; хвост ретраев и эскалаций считать ОТДЕЛЬНО; базы до 16.08 пере-прайсить по токенам. ⚠ Гейт для коэффициента холда в строке 280 | полигон | скоро (гейт строки 280) | замер по 162 базам, $0 | согласование 04.09, вторая редакция |
| 282 | ⛔ **ЧИСЛО, ПОДПИСАННОЕ «ЗНАКОВ», СЧИТАЕТ РУНЫ ПОТОКА ЗАПИСИ ФАЙЛА — что для UTF-8 txt И ЕСТЬ знаки, а для EPUB даёт руны ZIP-АРХИВА.** ⚠ Заголовок первой редакции («считает байты») — противоположная полуправда, испр. 05.09: ложно оно для EPUB, GB18030 и UTF-16, а не всегда. Проверено оркестратором по коду: `platform/internal/books/books.go`, греп `type counter` — счёт идёт по не-продолжающим байтам UTF-8 ПОТОКА ЗАПИСИ файла, а не по тексту; там же комментарий признаёт приближение для GB18030. Наружу уходит как `character_count` (`platform/internal/httpapi/v0.go`), на экране подписано `'about.characters': 'Знаков'` (`frontend/src/i18n/ru.ts`). ⇒ Живая ложь на продуктовом экране, и она же — вторая ненадёжная единица, найденная тем же вопросом «откуда берётся число». **Основой страницы быть не может.** Лечение: переименовать в размер файла ЛИБО заменить манифестной суммой знаков движка — ✅ **источник ПОСТРОЕН**: `source_chars` по юниту в `manifest --json` (лендинг `81a89e9`, акт D39.206; строка 278 закрыта и снята). ⛔ **ПЛАТФОРМЕННАЯ ПОЛОВИНА ИСПОЛНЕНА (пере-снято 06.09 по коду, не по комментарию):** число берётся из манифеста движка — `platform/internal/httpapi/project.go:38`=`out.CharacterCountExact`, рядом с ним флаг точности в `httpapi/v0.go:211`, пин `v0_test.go:933`. Остаток строки — ТОЛЬКО подпись `'about.characters': 'Знаков'` во фронте, а зона фронта ЗАМОРОЖЕНА ⇒ строка ждёт разморозки и в платформенные паки больше не входит | фронт | скоро (первое касание при разморозке) | снять ложную подпись `'about.characters'` во фронте (источник уже манифест движка — половина исполнена) | согласование 04.09; проверено оркестратором по коду |
| 283 | **СТРУКТУРА ГЛАВ ДЛЯ ВЫДАЧИ — отдельная задача, которую «страница» НЕ отменяет, и она гейтит бету для не-CJK и EPUB.** Билдер кладёт по одному XHTML на главу движка и сам признаёт, что ридер делает главу из каждого документа spine (`backend/internal/bookfile/epub.go`) ⇒ **для не-CJK txt читатель получает книгу ОДНИМ ПОЛОТНОМ при любой единице заказа**. Состав — этап 1 `research/27`: EPUB по nav/NCX (обязательно по стандарту), FB2, индуктор оглавления для txt, разрез по ДАННЫМ ПАРЫ вместо захардкоженного CJK (сегодня асимметрия: распознавание строки-заголовка данные пары читает — `configs/langpacks/zh-ru/heading.txt`, — а РАЗРЕЗ на главы нет). ⚠ Делать в единственном окне пере-снапшота, пока платная книга одна: перекрой двигает нарезку. Пере-скоуп строк 160–162 | бэкенд | скоро (ДО открытия беты не-CJK и EPUB-входам) | этап 1 research/27 своим паком | согласование 04.09, вторая редакция |
| 284 | **НАЗВАНИЕ КНИГИ И ЗАГОЛОВКИ ГЛАВ ИДУТ ЧЕРЕЗ ТЕРМИНЫ — ОТДЕЛЬНОЙ СТАДИЕЙ (решение владельца 05.09).** ⚠ **СЮДА ЖЕ ПЕРЕЕХАЛ ОСТАТОК ЗАКРЫТОЙ СТРОКИ 274 (D39.201 п.7): доставка имени В ФАЙЛ.** Платформенная половина построена — имя вычисляется ПРИ СКАЧИВАНИИ (`platform/internal/httpapi/v0.go`, греп `exportName`), внутрь файла не пишется намеренно: движок сворачивает `title` в `BriefHash` → снапшот → каждый request-hash, то есть запись в `book.yaml` отказала бы следующему прогону недопереведённой книги и стоила бы ПЕРЕ-ОПЛАТЫ книги целиком. **ФОРМА ОПИСАНА, ПАТЧ НЕ ПРОВЕРЕН** (слово платформенной зоны, принято дословно): путь — `tmctl build --title` аргументом при спавне, прецедент `--ceiling-usd`, но НЕ предъявлено исполнением, что движок примет незнакомый флаг без правки разбора аргументов — по закону шва там громкий отказ по построению. Остаток регистра — `PD-450`. Сегодня их не переводит НИКТО: `dc:title` берётся из `book.yaml` как есть (`backend/internal/bookfile/epub.go`, греп `dc:title`), заголовок главы собирается детерминированно шаблоном из langpack (`backend/configs/langpacks/zh-ru/heading.txt`, `template Глава {n}`). ⇒ Русский EPUB приезжает в читалку с китайским названием — ломается первое, что видит человек. Владелец: «пусть едет как термины, причём отдельные, то есть как-то надо называть эту стадию». ⚠ Значит у стадии своё имя, свой бюджет и своя ПОДПИСЬ: название книги владелец утверждает так же, как утверждает термин. ⚠ Родня — строка 274 (ручка переименования у пользователя) и открытый лист владельца «что печатать на титуле и в имени файла» (D25.1): механизм строится, СЛОВО остаётся за владельцем | бэкенд | скоро | стадия перевода заголовков + подпись владельца | решение владельца 05.09 |
| 286 | ⚠ **ЧИТАТЬ ЧЕРЕЗ `D39.205`: стоп остаётся ЦЕЛЬЮ, но гейт `gates.glossary.postcheck_gate` владелец 05.09 ОТЛОЖИЛ до замера точности («Не знаю. Тут надо мерить типо?… ложные срабатывания — это плохо, очень плохо») — это отсутствие замера, а не запрет** («ложные срабатывания — это плохо, очень плохо»); предусловие — строки 295 и 12. ⚠ **Сюда же перенесён 06.09 «ДЕТЕКТОР ВЕРНОСТИ ЗНАЧЕНИЯ» из строки 318** — четвёртым носителем одного вопроса он был бы трекерной инерцией: прибор, проверяющий вложенный `dst` ПО ИСХОДНИКУ, — тот же самый, что линза строки 319 после починки, а $0-прототип уже назван строкой 12. ⇒ **строка 318 остаётся только конкретной правкой** (комментарий постчека привести к поведению плюс пин), а вопрос «чем ловить неверное ЗНАЧЕНИЕ» живёт здесь и упирается в замер точности, а не в код. ⛔ **ПРИОРИТЕТ №1 ВЛАДЕЛЬЦА («100% консистентность») НЕ ИСПОЛНЯЕТСЯ КОДОМ И ПРОТИВОРЕЧИТ ДЕЙСТВУЮЩЕМУ ПОРОГУ.** Найдено ревизией документации 05.09. Три расхождения, каждое с носителем: **(1) ПОРОГ.** `docs/architecture/02-mvp-plan.md` и реестр `D10` держат «≥98%» — владелец 05.09 сказал **100%** (`D39.198`). Два процента на книге в тысячи терминов — это десятки разъехавшихся имён. **(2) МЕХАНИЗМ.** Единственный сегодняшний носитель консистентности — флаг `glossary_miss` РАНГА 5, то есть замечание, **с которым текст ОТГРУЖАЕТСЯ** (`backend/internal/pipeline/status.go` + `disposition.go`, греп `FlagGlossaryMiss`). Владелец сказал «разъехавшийся термин — СТОП». Флаг стопом не является. **(3) СЕМАНТИКА.** Приоритет №2 («никаких выдуманных сюжетных линий и смыслов») не имеет носителя вовсе: в реестре требований такого ПТ нет, ближайшее — гейт по ДЛИНЕ, а не по смыслу; семантический судья в движке не построен (слой 5). ⇒ **Сессия качества, собранная по нынешним докам, построит от неверной цели.** ⚠ Родня: строка **267** (две конкурирующие формы одного термина доезжают до редактора) — она и есть живой экземпляр нарушения приоритета №1 | бэкенд+полигон | скоро | порог 100% в носителях · консистентность как СТОП, а не флаг · носитель для приоритета №2 | ревизия документации 05.09, `D39.198` |
| 287 | **ТЕСТ ИСЧЕРПАЕМОСТИ ФЛАГОВ СЛЕП НА ТРЕТЬЮ ЛЕГАЛЬНУЮ ФОРМУ Go — найдено ПОСАДКОЙ верификатора приёмки, не автором.** Тест читает объявления причин через `go/ast` и покрывает две формы (`X FlagReason = "…"` и `X = FlagReason("…")`), о чём говорит его собственный комментарий «BOTH GO SPELLINGS COUNT». Третья форма — типизированная спека со значением-конверсией (`const X FlagReason = FlagReason("…")`) — **ПЕРЕЖИВАЕТ посадку**: типизированная ветка ждёт `*ast.BasicLit`, получает `CallExpr`, `lit == nil` и молча продолжает. Пол `found < 15` её тоже не ловит. ⚠ **Это ГРАНИЦА, а не живая дыра:** ни одной такой формы в дереве сегодня нет (все константы в `disposition.go` типизированные) — но комментарий обещает больше, чем тест держит, а это тот самый класс «утверждение шире ветки», который пак ловил четырежды. Там же не назван и `var`-случай. | бэкенд | когда-нибудь | покрыть третью форму ЛИБО сузить комментарий до двух | верификатор приёмки 05.09, посадка вне списка автора |
| 288 | ⛔ **«ПОПРАВИЛ ЧИТАТЕЛЯ, ОСТАВИЛ ПИСАТЕЛЯ» — ЕЩЁ ОДНО ПОЛЕ РЯДОМ, и оно бьёт в цель №2.** Сессия прибила читателя `classifyInputFor` и писателя `SetSourceScripts`; СОСЕДНЯЯ строка того же `defer` в `loadLangPack` — `backend/internal/pipeline/runner.go`, греп `CompileCheckersFor(r.pack, lang.TargetChecksFor` — не прибита ничем. **Предъявлено посадкой верификатора:** подмена `TargetChecksFor(r.Book.TargetLang)` на `TargetChecksFor("ru")` оставляет ВЕСЬ пакет `pipeline` зелёным (`ok 65s`). ⇒ Книга на →ja с включённым санитайзером компилировала бы РУССКИЕ паттерны читаемости: ложные `sanitizer_defect`, а ложный флаг ЭСКАЛИРУЕТ — это платные хопы за здоровый текст. От этой строки зависят `TargetActive()`, ёфикатор и латинский гард. Пин строится тем же двухкнижным приёмом, что и у `SourceScripts` | бэкенд | скоро | пин писателя целевых чекеров двумя книгами | верификатор приёмки 05.09, посадка вне карты отчёта |
| 289 | ⛔ **ДВЕ ВЕТКИ `CheckKeys` ДАЮТ ПРОТИВОПОЛОЖНЫЙ ОТВЕТ НА ОДИН И ТОТ ЖЕ КОНФИГ, а новый тест закрепляет лейбловую на фикстуре, где её собственная посылка ЛОЖНА.** Безлейбловая ветка требует ключ хопа ТОЛЬКО при `Escal.BudgetUSD > 0` (и это ратифицировано комментарием); лейбловая берёт `ReachableModels()`, куда `ResolvedHop` попадает БЕЗУСЛОВНО. При бюджете 0 хоп в рантайме не стреляет никогда. Зонд верификатора: одна стадия с `escalate_to` на провайдере без ключа, бюджет 0 ⇒ безлейбловая `nil`, лейбловая `missing API keys`. ⚠ Что внёс `74ffe4f`: кейс «the stage's escalation hop» и `why` записи `WB65` («a labelled run CALLS its escalation hop») стоят на фикстуре БЕЗ бюджета — то есть тест ПИНИТ требование ключа для модели, которую этот прогон вызвать не может. **Зеркало класса, который пак сам и нашёл: пин на «достижима» не есть пин на «вызывается».** Лечится либо бюджетом в фикстуре, либо приведением веток к одному правилу | бэкенд | скоро | свести ветки к одному правилу ЛИБО починить посылку фикстуры | верификатор приёмки 05.09, зонд вне карты |
| 290 | **ARM 1 нового теста банкноты проходит ВАКУУМНО, если каталог пары переедет — класс `WB41`, названный самой сессией.** Тест вписывает `langpack_root`, но не проверяет, что пак ЗАГРУЗИЛСЯ (`r.pack != nil`). Предъявлено: с несуществующим корнем все три плеча зелёные, а посадка `WB58` (снятие плеча контраста) **ПЕРЕЖИВАЕТ**. То есть красный `WB58` держится не тестом, а наличием каталога на диске. Лечение — посылка о состоянии пака в самом тесте. ⚠ Тот же класс: **тест исчерпаемости флагов слеп ещё на ДВЕ формы** сверх найденной первым верификатором — `var X = FlagReason("…")` на уровне пакета и `const` ВНУТРИ тела функции: обе посадки прошли, ни пол `found < 15`, ни сверка с картой не сработали (объявлено 17, найдено 16, карта 16). Итого форм пять, тест держит две, комментарий обещает «обе» | бэкенд | скоро | посылка о загрузке пака + покрыть или сузить обещание исчерпаемости | верификаторы приёмки 05.09 |
| 291 | ✅ **РЕШЕНО ВЛАДЕЛЬЦЕМ 05.09 (`D39.204`): деградировать во ФЛАГ, отличный по причине от исчерпания регенераций; текст попытки 0 оплачен и отгружается, волна идёт дальше. Вариант «минимальная покупка ≥ `step_max_usd`» СНЯТ — он стоил бы покупателю входного порога в пять глав. ⚠ Работа СВОИМ паком движка (правка пути ошибки в `stagerun.go` + новая причина флага + пин «купленное доставлено ⇒ не `exit 4`»), в принятый пак не дописывается.** ⛔ **ОБЯЗАТЕЛЬСТВО, БЕЗ КОТОРОГО ПАК НЕПОЛОН: новая причина флага выходит ОДНИМ АКТОМ С ПЛАТФОРМЕННОЙ ПОЛОВИНОЙ.** Карта заметок платформы РУКОПИСНАЯ (`platform/internal/ingest/notes.go`) и уезжает независимо от словаря движка; цена несделанного замерена — `PD-246`/эррата 04.09-в: минор 0.10.0 сутки жил ЛОЖНЫМ на проводе, причина доезжала читателю как `unspecified`, поймала это зона своей пере-проверкой ПОСЛЕ слов оркестратора «приёмка закончена». ⇒ промт этого пака обязан назвать ОБЕ зоны, а акт — предъявить зеркало. ⚠ Записано СТРОКОЙ, а не каналом, по слову сдавшей зоны: «`/tmp/textmachine-channel` не переживает рестарт — это в него и заложено», и обязательство, живущее в переписке двух сессий, умирает вместе с ними. ⚠⚠ **НИЖЕ — ИСТОРИЧЕСКИЙ РАЗБОР, ПО КОТОРОМУ РЕШАЛИ; как ЖИВОЕ не читать.** Его фраза «ВЫБОР НЕ СДЕЛАН» противоречит голове этой же строки — выбор СДЕЛАН владельцем (`D39.204`). ⛔ И ссылка «смена `D2.3`» в нём НЕВЕРНА ДВАЖДЫ, проверено по телу ноты (`../archive/architecture/05-decisions-D1-D38.md`, греп `^## D2. Диспозиция`): **(1)** `D2` уже кончается флагом («ретрай с бо́льшим `max_tokens` до капа, потом флаг») ⇒ это ДОСТРОЙКА, а не смена; **(2)** `D2.3` — по правилу подномеров ПУНКТ 3 тела `D2`, то есть «детектор вырождения перед удвоением `max_tokens`», к деградации отказа резервации отношения не имеет. **Настоящий адресат — `D2` п.2 «Тегировать `flag_reason`»**, и он делает вывод СИЛЬНЕЕ: тегирование причины там уже ТРЕБУЕТСЯ ⇒ новая причина есть **новый тег под существующим правилом**, а требование «причина обязана отличаться от исчерпания регенераций» — не добавка к канону, а его ИСПОЛНЕНИЕ. ⚠ Голова и хвост одной строки противоречили друг другу о состоянии решения — тот же класс, что находка `F7` приёмки, только не в коде, а в бэклоге; поймала сдавшая зона движка уже после закрытия своего пака. **ОТКАЗ РЕЗЕРВАЦИИ НА РЕТРАЕ НЕ ДЕГРАДИРУЕТ И НЕ ОСТАВЛЯЕТ СЛЕДА — юнит может заклинить НАВСЕГДА, а волна не может продолжиться без дыры.** `maxTokensForAttempt` удваивает бюджет на каждой регенерации (`backend/internal/pipeline/disposition.go`, греп `maxTokensForAttempt`), так что attempt 1 резервирует вдвое больше attempt 0. Отказ ретрая уходит наверх из цикла попыток (`backend/internal/pipeline/stagerun.go`, греп `return nil, err` в цикле попыток) **РАНЬШЕ `UpsertChunkStatus`** ⇒ чекпойнт attempt 0 есть (реплей за $0), **строки `chunk_status` НЕТ**, читающие модели видят юнит как `pending`, экспорт не отдаёт ничего. **Следствия два.** (1) Если потолок покупки не вмещает attempt 1 — юнит не доделается НИКОГДА: каждый резюм реплеит attempt 0 за $0 и умирает на attempt 1, прогон уходит exit 4 при ПОЛНОСТЬЮ доставленных купленных юнитах. (2) Продолжить волну после отказа ретрая нельзя без ДЫРЫ в непрерывном префиксе — то есть цена глобальной защёлки (недодача юнитов, которые влезали; разброс резервов внутри волны замерен ×2.976) различителем «свежий/ретрай» НЕ снимается. ⚠ **Оркестратор предлагал такой различитель на посылке «ретрай оставляет ФЛАГОВАННЫЙ юнит» — посылка ЛОЖНА, опровергнута зоной по строкам.** **Два пути лечения, ВЫБОР НЕ СДЕЛАН:** (а) отказ ретрая деградирует во флаг attempt 0 — смена `D2.3`, закрывает ОБА следствия; (б) минимальная покупка платформы ≥ `step_max_usd` движка (он включает ретраи именно поэтому) — закрывает только (1) и стоит продукту минимальной покупки ~5 глав | бэкенд+платформа | скоро | выбор владельца между (а) и (б) + пин | бэкенд-сессия денежного стопа 05.09, формулировка зоны |
| 292 | ⛔ **ЧЕСТНОСТЬ ТРЁХ СТРОК НАБЛЮДАЕМОСТИ — ЖИВАЯ ПОЛОВИНА (б) ЗАКРЫТОЙ СТРОКИ 105, заведена 05.09 отдельным носителем.** Закрытие 105 сняло только половину (а) — предикат `isBankRole`; половину (б) чинить никто не заказывал, а на неё ссылались ДВА носителя как на «до фикса 105». Три дефекта, все воспроизведены: **(1)** строка `VOICE` берёт `rules=` из конфига ВРЕМЕНИ ОТЧЁТА (`backend/internal/pipeline/quality.go`, греп `rules=`), поэтому включение `gates.voice` ПОСЛЕ прогона печатает «измерено, чисто» для книги, которую никто не мерил; **(2)** та же строка печатается при ВЫКЛЮЧЕННОМ гейте, если `SpoilerLeaks>0` — поведение верное, неверна формулировка отчёта; **(3)** знаменатель `BANKNOTE` = `len(states)` вместе с призрачными строками `retrieval_state`, тогда как соседний агрегатор их фильтрует ⇒ после пере-чанковки покрытие ЗАНИЖАЕТСЯ. ⚠ Цена молчания прямая: отчёт говорит «измерено», когда не мерили, — это ложь читателю в том самом месте, куда смотрят, решая, готова ли книга. Печатает `cmd/tmctl/render.go` (греп `rules=`), пин — `render_observability_test.go`. | бэкенд | скоро | правка формулировки + знаменателя + тест на «включил гейт после прогона» | D39.86, D39.200; археология — `architecture/13-tech-debt-anchors.md` §Б-105 п.(б) |
| 293 | ⛔ **ФАЙЛ ПОД ЛЮБЫМ КАТАЛОГОМ `books/` НЕВИДИМ ДЛЯ GIT — `git status` его не показывает, `git add` молча не берёт, и сдающая зона теряет работу, не заметив.** Предъявлено 05.09 платформенной сессией и проверено оркестратором до лендинга: `git check-ignore -v platform/internal/books/counter_test.go` → `/info/exclude:9:books`. **Причина: правило `books` в `.git/info/exclude` НЕЯКОРЕНО**, а gitignore без ведущего `/` ловит каталог с этим именем на ЛЮБОЙ глубине. ⚠ Неякорность ОСМЫСЛЕННА и снимать её нельзя не думая: `books` в связанном рабочем дереве — СИМЛИНК, а трекнутое правило `/books/` матчит только каталоги (комментарий стоит там же). ⚠ **Почему это не поймал никто:** тронутые файлы того же каталога в `git status` ВИДНЫ (игнор действует лишь на неотслеживаемое), поэтому пропажа не читается глазами; а `git commit -- <путь>` untracked роняет и без игнора. Замер: без `git add -f` уехал бы 31 файл из 32. **Лечение — не «поправить exclude»:** файл ОБЩИЙ для всех рабочих деревьев клона, включая полигонное, и менять семантику игнора под живыми сессиями нельзя. Формы, между которыми выбирать: (а) якорить правило под КОНКРЕТНЫЙ симлинк (`/books` в корне дерева) и проверить, что симлинк по-прежнему игнорируется во ВСЕХ деревьях; (б) оставить как есть и завести проверку лендинга — `git status --ignored --short <зона>` перед каждым актом. | оркестратор | скоро (гигиена лендинга, $0) | выбор формы + проверка во всех воркtree | предъявлено платформенной сессией 05.09; проверено исполнением при лендинге `7e2226a` |
| 294 | ⭐ **ФОРМА «СКОЛЬКО ДОБАВИТЬ» — решение владельца 05.09, ратифицировано `D39.203`.** Наружу вместо «сколько не хватило на ЭТОТ вызов» едет **«сколько добавить, чтобы прошёл ЛЮБОЙ следующий»** = `max(shortfall, step_max − headroom)`: сегодняшняя недостача закрывает текущий вызов, а следующий может быть крупнее, и человек доплачивает дважды. ⚠ **НЕ однострочник, и объявлять его дешёвым было бы ошибкой** (зона дешевизну не подтвердила): новая величина · **ПЕРЕИМЕНОВАНИЕ поля** — `shortfall_micro_usd` станет ложным именем, кандидат `top_up_micro_usd` · минор `StreamVersion` 1.3→1.4 · зеркало словаря у платформы · пере-снятие пина белого списка кадра `ceiling`. ⚠ Построенное поле НЕ ложно, оно у́же: закрывает вызов, а не следующий шаг | бэкенд+платформа | скоро | новая величина + переименование + минор потока | **D39.203**; тензия п.(3) против п.(4) заказа найдена зоной движка |
| 295 | ⛔ **СНАЧАЛА ПОДАТЬ ПОДПИСАННЫЙ КАНОН В ПРОГОН — только потом мерить точность чекера и решать про гейт.** Живая дыра приоритета №1 владельца («100% консистентность») — НЕ порог и НЕ флаг: канон из 53 подписанных терминов **не подключён к стенду**, весь замеренный дрейф — дрейф С ОТКЛЮЧЁННЫМ каноном, а там, где его подключали, консистентность 99.3–100%. ⇒ мерить полноту чекера на прогоне без канона значит мерить не то. **Порядок:** (1) канон в прогон · (2) пере-замер точности/полноты (строка **12**, прежний замер порочен — класс одного иероглифа не имел ни одного положительного примера) · (3) решение владельца по `gates.glossary.postcheck_gate`. ⚠ Владелец 05.09: «если он ложно положительно будет стрелять это плохо, очень плохо» ⚠ **ПОЛОВИНЫ НАЗВАНЫ 06.09 по ревью напарника — прежде тут стояло «назвать или отдать», и это переезжало бы следующей смене той же инерцией.** **(а) Полигон/владелец:** подать канон в стенд-книгу — это ДАННЫЕ (сид-YAML либо решения `bank-apply`) ПЛЮС платный прогон под санкцией; у бэкенд-сессии нет ни книги, ни стенда, ни денег, поэтому половина её не является. **(б) Бэкенд — только ВОПРОСОМ, а не задачей:** умеет ли сид-путь нести подписанный статус; если нет — это пинг оркестратору, и тогда появляется бэкендовая работа. ⇒ зона ведущая — полигон. ⛔ **ИСПР. 11.09 АУДИТОМ БАНКА — ГОЛОВНАЯ ПОСЫЛКА РЯДА ВЕРНА ТОЛЬКО ПРО СТЕНД.** Пере-снято: «канон ни разу не подан в прогон» справедливо для ИССЛЕДОВАТЕЛЬСКОГО стенда (там 0 конфигов из 30 несут ключ сида), но НЕ для дерева: ключ `glossary_seed` задан в **18** конфигах (прибор — `yaml.safe_load` по 150 `.yaml` в `books/gu-zhenren`, контроль: не распарсилось 0; греп подстроки давал 25, и в шести из них ключа НЕТ). Пять прогонов держат 36–57 подписанных строк, а весь размеченный корпус (91 единица) снят с прогонов С каноном, и дрейф ПРИ каноне наблюдён живьём (`古月方源` → «Гу Юэ Фан Юань» при подписанном `古月 → Гуюэ`). ⇒ порядок работ меняется: это не «сперва подключить канон», а **«разметить класс, которого в корпусе не было»** — $0 на уже оплаченных артефактах плюс новый прогон. Носитель разбора — `docs/research/34-memory-bank-quality-audit.md`; прямая причина низкой точности названа рядом **408** (данные, не код). | полигон (бэкенд — по вопросу) | скоро | подача канона + замер | **D39.205**, D39.198 п.3-4, строка 12 |
| 296 | **ТОЧЕЧНАЯ ПЕРЕГЕНЕРАЦИЯ ПО ПРОМАХУ ГЛОССАРИЯ — направление владельца 05.09 («или флагать, или перегенерировать проблемный участок»), работы сегодня НЕТ.** Актуаторы ремонта — только `RepairLatinResidue` и `RepairBrokenWord` (`backend/internal/pipeline/repair.go`, греп `defaultRepairClasses`); `glossary_miss` нет ни там, ни в `knownRepairClasses`. Сегодняшние лекарства не точечные и обе дороги: удержать ВЕСЬ фрагмент (гейт) либо править глоссарий с `--resnapshot`, то есть ПЕРЕ-ОПЛАТИТЬ книгу. ⇒ заказ: `glossary_miss` как класс-актуатор — перегенерация участка с подписанной формой. ⚠ Гейтится строкой **295**: без замера точности перегенерация по ложному срабатыванию перепишет верный текст | бэкенд | когда-нибудь (после 295) | новый класс актуатора + пост-инвариант | **D39.205** |
| 297 | ✅ **ПЕРВАЯ ПОЛОВИНА ИСПОЛНЕНА ЛЕНДИНГОМ 06.09 (`2f65d1d`, акт `D39.210`): словарь получил четвёртое значение `delimited`**, и spine-EPUB вместе с `\f` в txt больше не выдаются за слово формата. ⛔ **ВТОРАЯ ПОЛОВИНА ТЕПЕРЬ ОБЯЗАТЕЛЬНА, А НЕ ЖЕЛАТЕЛЬНА:** временное правило платформы «`declared` вести как `none`» после лендинга начинает ОТНИМАТЬ ползунок глав у книг, чья структура объявлена настоящим `nav`/NCX — то есть молча недодавать продукт. ⚠ **Якоря прежней редакции этой строки указывали на текст, который пак УДАЛИЛ, а якорный линт этого НЕ ВИДЕЛ** — они были без токена, файл длинный, адрес «разрешался». Живая рабочая строка протухла молча; класс несёт строка **306**, и это его первый пойманный случай в рабочей строке, а не в архиве. ⚠ **Тело прежней редакции СНЯТО 06.09, а не оставлено под шапкой** — оно цитировало рекламу «how much the chapter cut can be trusted» как живую улику, а пак её УДАЛИЛ (`grep -c` → 0), и три его якоря целили в текст, которого нет: словарь уехал, а `:94-95` попал в структуру, введённую дофиксом. То есть строка утверждала про себя, что она первый пойманный случай «якорь протух молча», и одновременно продолжала им БЫТЬ; поймал это строитель пака грепом, линт был зелён. **Что стало вместо снятого:** словарь живёт на `backend/internal/chunk/ingest.go:125-149`=`WHICH PATH drew the chapter boundaries` — четыре значения, и первая же строка комментария теперь говорит про ПУТЬ, а не про доверие. Прежняя двусмысленность («поле отвечает на провенанс, а рекламирует доверие») **устранена паком, а не описана** | бэкенд+платформа | скоро (структурный пак) | недостающее значение на проводе, и `declared` означает ТОЛЬКО объявленную форматом структуру глав | **D39.202**, D39.205 |
| 298 | ⛔ **`unit_resolutions` КЛЮЧЕВАНЫ ПОЗИЦИЕЙ, И ЛЮБОЙ ПЕРЕКРОЙ ИХ СНОСИТ ЦЕЛИКОМ.** Ключ `(book_id, chapter, unit, wave)` позиционен по построению, и миграция это прямо объявляет: «keyed by the ENGINE's own ordinals» (`platform/internal/pgstore/migrations/00015_seam_ceiling_and_units.sql:50-56`); событие `unit_done` несёт номер главы и ординал юнита, синк пишет их как есть (`platform/internal/pgstore/sink.go:249`). Потому при перекрое платформа ОБЯЗАНА удалять решения — иначе они перевесятся на чужую главу. Сегодня цена нулевая: решения есть только у стенд-книги, и это окно закрывается с каждой новой платной книгой. ⇒ разрешать `(chapter, unit)` в идентификатор ПРИ ПРИЁМЕ события, пока дерево у платформы на руках, и хранить идентификатор. Платформенная половина структурного пака: миграция плюс синк. ⚠ Этой строкой НЕ закрывается одноразовая перечеканка всех id при смене смысла `cutTag` — это другой предмет и другая цена | бэкенд+платформа | скоро (структурный пак) | решения переживают перекрой, не переклеиваясь на чужую главу | **D39.202** |
| 299 | ⛔ **ИМЯ В GO-КОММЕНТАРИИ, КОТОРОЕ НИ ВО ЧТО НЕ РАЗРЕШАЕТСЯ, — И НИЧТО ЭТОГО НЕ ЛОВИТ.** ⭐ **ЗАМЕР 05.09, полностью меняющий форму ДОРОГОЙ половины (той, что сверяет имя с каталогом мутаций): она обязана писать ФАЙЛ, а не читать `stdout`.** Полный прогон каталога дал: несущих верхнеуровневых тестов **189** из 1213 тест-функций движка (**15,5 %** батареи; ⚠ испр. 06.09 автором замера: было «194 / 16,0 %» — его парсер резал вывод по запятой, а пять подтестов несут запятую В ИМЕНИ, и круглые «16,0 %» получились именно из пяти фантомов. ⚠ Числитель и знаменатель разной природы: 1213 считает только `^func Test`, а один из 189 — `Fuzz`; честно 188/1213 либо 189/1219, но не 189/1213), и **139 записей из 197 пинятся РОВНО ОДНИМ тестом** — то есть краснота атрибутируется однозначно, и долговременная запись «какие тесты несущие» реально получается. ⛔ **Но тул обрезает список имён на четырёх и печатает `+N more` — так усечены 9 записей из 197, и механизм, читающий `stdout`, насчитал бы 178 вместо 194 И НЕ УЗНАЛ БЫ ОБ ЭТОМ.** Это тот же класс «прибор ответил на свой вопрос»: величина ВЫЧИСЛЯЕТСЯ сегодня, но в поток приезжает УСЕЧЁННОЙ. ⇒ вход механизма — `-logs`, не вывод. Точный список имён воспроизводится пере-прогоном каталога с `-logs`; сохранять его отдельным артефактом не нужно. Два живых носителя, найдены верификацией 05.09 (`D39.207` п.3): **(а)** `backend/internal/runevents/runevents.go:187`=`not to a screen` цитирует **СТАРЫЙ** путь — `docs/BACKEND_MONEYSTOP_SESSION_PROMPT.md`, строка 78 (записано БЕЗ формы якоря намеренно: это УЛИКА мёртвой ссылки, а не ссылка; в форме якоря линт вечно краснел бы на предмете самой записи) — и удалён именно он (промт уведён в архив коммитом `f71c4dc`, тем же, что писал акт), а цитируемая фраза ЖИВА в архивной копии и стоит там на строке **82**. ⚠ **Испр. 06.09: клауза была заландена ПЕРЕВЁРНУТОЙ** — называла удалённым архивный файл, который цел, и приписывала комментарию цитату, которой в нём нет. Механика ошибки записана отдельно, она повторяемая: сплошная замена строки якоря при пере-наведении попала в ОПИСАНИЕ дефекта, где тот же путь был УЛИКОЙ, а не ссылкой, и превратила описание поломки в описание её отсутствия. Нашёл верификатор `textmachine-main-e6` контролем закрытия своих же находок; ⚠ приёмочный столбец строки при этом сформулирован ВЕРНО и поймал бы дефект независимо от прозы — то есть major в описании, не в гейте; **(б)** `backend/internal/config/internal_call.go:11`=`builds a Stage outside the loader` и `backend/internal/pipeline/live_reprobe_test.go:14`=`the single-egress guard` называют сторожами тесты `TestSyntheticStageSeamIsSingle` и `TestProviderEgressSeamIsSingle`, которых в дереве НЕТ — инварианты при этом реально сторожатся вет-анализаторами `StageSeam`/`EgressSeam` (`backend/internal/archguard/archguard.go:80,377`=`StageSeam, RequestSeam, EgressSeam`), то есть гарантия цела, а назначенный ей сторож ВЫДУМАН. Замер верификатора: из 2026 упомянутых в Go имён `Test…` определены 2012; из восьми неразрешающихся четыре — не дефекты (надгробия и иллюстрация), два — мелочь, два — эти. ⇒ **дешёвая половина открытого вопроса `D39.202` п.9: не «доказал ли каталог, что названный тест умеет падать» (дорого, требует интеграции с `tmmutate`), а «РАЗРЕШАЕТСЯ ли названное имя вообще» — это греп, и сегодня он находит два дефекта.** ⚠ `counts.py --lint` этого класса не видит по построению: он читает доки, а не код. ⚠⚠ **ДВА ПРАВИЛА, БЕЗ КОТОРЫХ ГЕЙТ ВЫКЛЮЧАТ НА ВТОРОЙ ДЕНЬ** (принесены верификатором вместе с находкой): **(1)** разрешением считается и ПРЕФИКС — доки и комментарии цитируют имя усечённым, как греп-цель; **(2)** НАДГРОБИЯ не дефект — комментарий, прямым текстом говорящий «удалён/заменён», законен, как и иллюстративное имя в примере. Замер, обосновывающий оба: из восьми неразрешающихся имён СЕГОДНЯ четыре — надгробия и иллюстрация, два — усечение в шапке над функцией, и лишь два — настоящие выдуманные сторожа. Гейт без этих правил краснеет 8 из 8, то есть врёт вчетверо, и его погасят — ⚠⚠ **и ЗАМЕР 06.09 показал, что для указателей `путь:строка` в Go арифметика ХУЖЕ, а потолок дешёвой половины НИЖЕ, чем считалось.** Всего таких указателей **36**; настоящий дефект среди них **ОДИН** (`runevents.go:187`, уже назван выше). Остальное: **5 целят ВНЕ репозитория** (стандартная библиотека Go, `yaml.v3`, jieba) — внутрирепозиторный линт их проверить не может в принципе; **~7 разрешаются НЕОДНОЗНАЧНО** — голое имя файла имеет от двух до восьми одноимённых кандидатов. ⇒ наивный гейт покраснел бы примерно **двенадцать раз ложно при одном настоящем дефекте**. ⛔ **ДВА правила записать ДО заказа, иначе гейт врёт впятеро и его выключат:** **(1)** внешняя цель — НЕ дефект (путь, не разрешающийся в дереве и опознаваемый как чужой, исключается); **(2)** ⛔ **у голого имени файла SOUND-ДЕФОЛТА НЕТ — гейт обязан считать его НЕПРОВЕРЯЕМЫМ (skip), а не угадывать.** ⚠ Прежняя редакция этого пункта предлагала конвенцию «сперва каталог цитирующего файла, затем модуль, затем корень» — **и она ОПРОВЕРГНУТА 06.09 её же автором**: для дока, цитирующего КОД, каталог цитирующего файла систематически неверен, потому что рядом с доком лежат другие ДОКИ. Контрпример — `PROGRESS.md:71` → `README.md:95`: конвенция даёт `docs/README.md` (41 строка) и вердикт «протух», а автор имел в виду `backend/README.md`, где строка 95 **та же, что в минуту написания**. В дереве `README.md` четырнадцать штук. ⇒ гейт с конвенцией краснел бы именно на ЖИВЫХ якорях. Хочешь проверяемости — пиши путь или токен. ⚠ И третье, важнее обоих: **НИ ОДИН из 36 не несёт токена**, поэтому ДОРОГАЯ половина упирается не в инструмент, а в то, что сверять нечего; дешёвая остаётся верным первым шагом, но её потолок теперь измерен — **один дефект на тридцать шесть**. а гейт умирает не отключением, а вытеснением из привычки (`D39.202` п.3-бис) | бэкенд | скоро | грепом: имя `Test…` и `<док>.md:<строка>` в Go разрешаются, иначе красно | **D39.207**, D39.202 |
| 300 | ⛔ **РЕПО-ШИРОКИЙ СТОРОЖ НЕ ДОТЯГИВАЕТСЯ ДО СОСЕДНЕГО ВОРКРИ НА ДРУГОЙ ВЕТКЕ — и стенд от этого УЖЕ СГНИЛ.** ⚠ Замер 05.09, вторая половина: снять пин манифеста стенд-конфигами удалось для **ОДНОГО исходника из восьми**; семь падают, и ни одно падение не про структурный пак. Причины — ретированные в `main` вещи, живые в дереве `polygon`: плейсхолдер `{{genre}}` (ретирован `D39.138` п.2в) — в моём дереве `grep -rln '{{genre}}' backend/prompts/` ПУСТ, в соседнем живёт в ШЕСТИ файлах промтов, и падают на нём 6 конфигов из 8; поля `stm_depth`/`overlap_tokens`, которых больше нет в `config.ContextAssembly` — 1 из 8; ключи `mined_delta:`/`mined_rejects:` (ретированы `D39.156` п.3) — **17 конфигов из 31**. ⭐ **Тест `genre_retired_test.go:46` предсказал этот случай дословно** («should be caught by the repository that retired it, not by a paid run») — и поймали его действительно бесплатно, но **сторож не дотянулся до соседней ветки**, где ретированное живо. ⇒ общая форма дефекта: ретирование, проведённое репо-широким гейтом, НЕ распространяется на воркри другой ветки, и стенд тихо остаётся в прошлом. **ЧАСТНЫЙ СЛУЧАЙ ТОГО ЖЕ КОРНЯ — ДАННЫЕ ПАР-ПАКА В ДВУХ ВЕТКАХ.** Замер бэкенд-сессии 05.09 по 31 конфигу `book.yaml` стенда 蛊真人: у **20** `langpack_root` указывает в СОСЕДНЕЕ РАБОЧЕЕ ДЕРЕВО `/home/ubuntu/projects/textmachine` — а оно на ветке **`polygon`**; у 9 — в `main`; 2 не объявляют его вовсе. Пока каждая ветка собирается из своего дерева, расхождения не видно. ⚠ **Структурный пак (`CHAPTER_STRUCTURE_SESSION_PROMPT.md`) выносит `marker`/`units` из `zh-ru/heading.txt` в данные ИСТОЧНИКА и учит `parseHeading` ОТВЕРГАТЬ эти ключи с переходным сообщением** ⇒ старый файл, оставшийся на `polygon`, станет невалидным, и двадцать конфигов не загрузятся вовсе (загрузка пар-пака FAIL-LOUD). **Выстрелит НЕ при лендинге в `main`, а в момент, когда полигон вольёт `main` в свою ветку** — то есть цена назначена чужой зоне и в чужой момент. ⇒ заказ: перед мержем полигон либо снимает `marker`/`units` из своего `heading.txt`, либо переводит `langpack_root` своих конфигов на `main`. ⚠ Второе дешевле и, возможно, правильнее по существу: **каталоги `configs/langpacks` в обоих деревьях сегодня БАЙТ-В-БАЙТ идентичны** (`diff -rq` пуст, sha256 `heading.txt` совпадают), а комментарии в конфигах, утверждающие «`ru/` есть только здесь», ПРОТУХЛИ — класс строки 299. То есть двадцать конфигов смотрят в чужую ветку по причине, которой больше нет | полигон | скоро (до мержа main в polygon) | конфиги грузятся после мержа, либо `langpack_root` переведён | **D39.207** |
| 301 | ⛔ **`--max-units` НЕ УМЕЕТ СКАЗАТЬ «ДОРАБОТАЙ ПЕРЕНЕСЁННОЕ И НЕ НАЧИНАЙ НОВОГО», И ЧЕЛОВЕК ЗА СВОИ ДЕНЬГИ ПОЛУЧАЕТ НЕ ТУ РАБОТУ.** Флаг бюджетирует N НОВЫХ стартов, а carried-юниты (задрафченные прошлым прогоном и не отгруженные) движок допускает СВЕРХ гранта, до N штук: `granted()` их не считает (`backend/internal/pipeline/volume.go:396-407`), и собственный тест движка это фиксирует — под `--max-units 1` при одном carried выходит `Delivered=2, Carried=1` (`volume_test.go:721`). ⇒ прогон, оборвавшийся МЕЖДУ волнами (стоп на подпись банка, деплой, краш), при респауне получает `--max-units = заказ − доставлено`, и движок оплачивает ЧЕРНОВИКИ глав, которых человек НЕ ЗАКАЗЫВАЛ, раньше редактуры заказанных. ⚠ **Это НЕ перерасход** — `--ceiling-usd` держит сумму; ломается ровно обещание «вы купили N»: за те же деньги приходит другая работа. Выразить нужное платформа не может по построению: вычесть carried значит обнулить грант, а ноль для движка = «без границы» (`planVolume` при `MaxUnits <= 0` возвращает `nil`, `volume.go:321`). ⇒ заказ: словарь скоупа обязан различать «сколько НОВЫХ начинать» и «сколько всего допускать». Живая половина **эрраты 03.09-а** (перенос юнита вне гранта, семантика НЕ ратифицирована, слово владельца «подумаем»), но со следствием более острым, чем записано в ноте: там был перерасход единиц, здесь — подмена предмета покупки | бэкенд+платформа | скоро | флагом выражается «ничего нового не начинать»; пин на респауне между волнами | **D39.207** |
| 302 | **РЕЗКА xhtml ПО ЯКОРЯМ `nav`: текст цел, ГРАНУЛЯРНОСТЬ ТЕРЯЕТСЯ.** Массовая форма EPUB — несколько глав в ОДНОМ документе, разделённых якорями, и `nav` объявляет на них отдельные цели. Структурный пак 1 такие цели СХЛОПЫВАЕТ: одна глава вместо трёх, текст не теряется (формулировка бэкенд-сессии 05.09: «текст цел, гранулярность потеряна»). ⚠ **Ложь при этом уже не едет** — тем же паком ратифицировано: схлопнулась хоть одна цель ⇒ книга НЕ `declared`, а `delimited`, плюс счёт `targets collapsed: N` в WARN. То есть провенанс честен, а разрез груб. ⇒ заказ: резать документ по якорям целей. ⛔ **Почему НЕ сделано паком 1 и почему это дорого:** это единственное место, трогающее `extractXHTML`, у которого **четыре пина байт-паритета** (`backend/internal/chunk/ingest_test.go:356 · :392 · :456 · :500` (⚠ адреса пере-сняты 11.09: стояло `:323, 359, 423, 467`, и `:323` указывал на ДРУГОЙ тест — `TestIngestEPUBVoidTagsInHeadDoNotSwallowChapter`, то есть читатель проверял бы не тот предмет) — void-теги, несбалансированный ruby, raw-text-элементы, голый амперсанд), и ошибка там ТИХАЯ. Заходить в него в конце пака, ради гранулярности, при живом гейте разреза — плохой размен. ⚠ Строкой закрывается ГРАНУЛЯРНОСТЬ, а не провенанс: продать такую книгу по главам платформа и так не предложит | бэкенд | когда-нибудь (после пака 2) | книга с тремя якорями в одном документе даёт три главы; четыре пина байт-паритета целы | **D39.207** |
| 303 | **НЕ-CJK ПУТЬ ПОСТРОЕН НАПОЛОВИНУ: чанкер безъюнитную грамматику УЖЕ УМЕЕТ, ингест по ней НЕ РЕЖЕТ.** `detectChapterUnit` итерирует `UnitOrdered` и без юнита возвращает 0 ⇒ грамматика вида «Kapitel 12» / «Chapter 12» (маркер + номер, БЕЗ юнита) книгу не режет; при этом `matchHeaderLine` чанкера юнита не требует и на это есть живой тест (`TestStripHeadingGenericLatinMarker`). То есть заголовок такой книги движок умеет СНЯТЬ, но не умеет по нему РАЗРЕЗАТЬ. ⇒ ревью-вопрос проекта «заработает ли пара, которой в репо НЕТ, без правки Go» закрыт для языков С ЮНИТОМ (доказано сквозным тестом `TestANewLanguageCutsFromItsDataFileAlone`: без файла корейская книга — одна глава, с `ko/structure.txt` — три, разница только в данных) и **ОТКРЫТ для языков без юнита**. Это названный ВХОД в пак 2, а не открытие по ходу. ⚠⚠ **ГРАНИЦА ЗАМЕРА, названная самой зоной и записанная здесь в её настоящей силе:** утверждение проверено **ПО КОДУ и ПО ТЕСТУ НА ФИКСТУРЕ**; **живая не-CJK книга через ингест НЕ прогонялась**. «На живой книге» под этой строкой НЕ стоит, и ссылаться на неё как на замер живого поведения нельзя | бэкенд | скоро (вход пака 2) | безъюнитная грамматика режет книгу; замер на живой не-CJK книге | **D39.207** |
| 304 | ⚠ **РИСК NULLABLE ДЕНЕЖНЫХ КОЛОНОК — НЕ ТЕОРЕТИЧЕСКИЙ, А ОТЛОЖЕННЫЙ, и это вскрыла ЛОЖНАЯ ПРИЧИНА в отчёте зоны.** Платформенная зона объяснила чистый `sqlc diff` тем, что новые колонки лежат «в таблицах, для которых sqlc не держит запросов» — **догадка, и неверная**: `queries/credits.sql` и `queries/exports.sql` читают `books`, `chapters` и `runs`. Верная причина: ни один из этих запросов не выбирает `*` и не называет новых колонок, поэтому сгенерированный код не двигается (греп по `*.sql.go` — ноль вхождений). ⇒ **`books` ЛЕЖИТ в мире sqlc**, значит риск NULLABLE денежных колонок наступит на ПЕРВОМ же запросе, который их выберет, — не «никогда», а «пока не спросили». ⚠ Нашла это зона САМА, четвёртым заходом по прямому вопросу владельца «нет ли чего, что ты умолчала»; ни один гейт поймать это не мог — сторожат поведение и форму, а не то, что отчёт о себе ГОВОРИТ (`D39.202` п.9) | платформа | скоро | первый запрос, выбирающий денежные колонки, не роняет генерацию | **D39.208** |
| 306 | ⛔ **СЕМЬСОТ ЯКОРЕЙ БЕЗ ТОКЕНА НЕПРОВЕРЯЕМЫ, И 59% ИЗ НИХ УЖЕ НЕ УКАЗЫВАЮТ ТУДА, КУДА УКАЗЫВАЛИ.** Замер Fable 5 06.09 (выборка 80, seed фиксирован, метод — blame-триаж: коммит последней правки СТРОКИ ДОКА → цель на том коммите → сравнение): цела **31** · уехала **25** · переписана либо исчезла **22** · не судится 2. ⇒ **59% (±11 п.п.)**. ⚠ Линт сверяет по токену 202 и честно печатает «без токена — несверяемы: 780», но ЗАГОЛОВОК «0 проблемных якорей» читается как «всё цело» — прибор отвечает на свой вопрос, а читают его как ответ на другой (`D39.202`). ⚠ **Дрейф сосредоточен там, где он ОЖИДАЕМ:** 34 из 47 сдвинувшихся — в ЗАМОРОЖЕННЫХ отчётах, чьи тела улика по `D23.3` и обязаны описывать дерево НА ДАТУ; их чинить НЕЛЬЗЯ, им нужен штамп HEAD в шапке. **Опасны 13 в ЖИВЫХ носителях**, и часть из них — в ШАПКЕ журнала, то есть в первом, что читает сессия. ⇒ заказ, тремя шагами и без велосипедов: **(1)** заголовок линта печатает ПОКРЫТИЕ («сверено N · несверяемы M · из них с изменившейся целью — K»), чтобы гейт перестал врать формой; **(2)** ОДНОРАЗОВАЯ механическая миграция тем же скриптом: «цела» → дописать токен автоматически, «уехала» с единственным попаданием → пере-навести, «исчезла» → список на руки; замороженным отчётам вместо пере-наводки штамп коммита и исключение из линта; **(3)** правило «токен при касании» остаётся удержанием линии; **(4)** ⛔ **грамматика УЛИКИ — `path:line@`**, которую линт сверяет через `git show :path`, а НЕ против HEAD (~20 строк в `counts.py`). Без неё автор, цитирующий мёртвый указатель как ПРЕДМЕТ записи, вынужден снимать форму якоря руками — я так и сделал 06.09 и объявил это в тексте, но это подгонка ЗАПИСИ под модель прибора, а не починка модели: **законно как последнее исключение, незаконно как привычка**. Та же форма закрывает и ЗАМОРОЖЕННЫЕ отчёты, которым сегодня штамп HEAD стоит прозой (`research/31`/`32`). ⚠ Сегодня без (2) правка любого дока превращается в игру «бей крота»: каждое касание вскрывает соседний голый якорь. ⚠⚠ **ПЕРЕ-ЗАМЕР 06.09 ГРАММАТИКОЙ САМОГО ЛИНТЕРА — МАСШТАБ ОКАЗАЛСЯ В РАЗЫ МЕНЬШЕ, И ЭТО МЕНЯЕТ ЗАКАЗ.** По 117 живым докам: **214 якорей с токеном** (это и есть те, про кого «0 проблемных») и **1776 без токена**; за конец файла целят 66, однозначно разрешаются 9, и семь из девяти — ВНЕШНИЕ цитаты (стандартная библиотека Go, чужой фронтовый код). ⇒ **настоящий внутрирепозиторный протухший якорь ОДИН** (испр. 06.09 автором замера): `docs/architecture/05-decisions-log.md`, греп `Эррата 28.08-и` — **в ШАПКЕ журнала, которую сессия читает первой**; цель нашлась `git log -S` по тексту якоря и пере-навёдена с токеном. ⚠ **Второй кандидат (`PROGRESS.md:71` → `README.md:95`) оказался АРТЕФАКТОМ РАЗРЕШЕНИЯ ИМЕНИ, а не дефектом** — и он же служит уликой к правилу (2) строки 299. ⭐ **Дешёвый метод для ведра «исчезла», исполненный, а не описанный:** `git log -S'<текст якоря>' -- <док> | tail -1` даёт коммит, ВВЕДШИЙ якорь; `git show <коммит>:<цель>` — что стояло в ту минуту ДОСЛОВНО; `git grep` — сегодняшний адрес. Угадывания нет ни на одном шаге. ⛔ **ОПИСАНИЕ ЧУЖОГО МЕТОДА В ЭТОЙ СТРОКЕ БЫЛО ЛОЖНЫМ — СНЯТО 06.09.** Абзац писал, что «59 % на выборке 80» получены наивным резолвингом (голое `mining.go:40` из подкаталога ищут от корня, не находят, объявляют мёртвым). **Наивный резолвинг — метод АГЕНТСКИХ чисел** («42 %», «19 из 32 мертвы»), и опровергнуты им именно они; тем же способом автор пере-замера получил «31 мёртвый из 36» и не понёс их, потому что стал сверять расхождение. Замер Fable 5 устроен иначе и так же описан в ГОЛОВЕ этой строки: берутся только ЗОННО-ПРЕФИКСНЫЕ пути, `git blame` даёт коммит последней правки СТРОКИ ДОКА, `git show <тот коммит>:<цель>` — цель на ту минуту, и сравнивается СОДЕРЖИМОЕ с HEAD. ⇒ строка противоречила сама себе: голова описывала blame-триаж, хвост объявлял его наивным резолвингом. **Класс строки 299, только внутри бэклога.** ⚠ **ДВА ЧИСЛА ОТВЕЧАЮТ НА РАЗНЫЕ ВОПРОСЫ, и потому ни одно не опровергает другое.** Пере-замер грамматикой линтера спрашивает «указывает ли якорь в СУЩЕСТВУЮЩУЮ строку HEAD и совпадает ли токен» — ответ: 214 с токеном, 1776 без, за конец файла 66, однозначно разрешаются 9, настоящий внутрирепозиторный протухший ОДИН. Замер blame спрашивает «изменилось ли СОДЕРЖИМОЕ цели с той минуты, когда строка дока была написана» — ответ: ~59 % на выборке 80. Первый вопрос про HEAD, второй про ДРЕЙФ; строка обязана нести оба, а прежняя редакция вычитала одно из другого. ⚠⚠ **И вопрос HEAD слеп ПО ПОСТРОЕНИЮ к тому самому якорю, ради которого строка заведена:** якорь шапки журнала был написан голым — `seeding.go:143-153`, без слэша, — а `docs/scripts/counts.py:595`=`"~" in rel or "/" not in rel` относит такую форму к «неразбираемым» и пропускает МОЛЧА, ДО всякой проверки файла. ⚠ **Испр. 06.09 по ревью Fable 5: файл НЕ переименовывали** — `seeding.go` жив и сегодня (128 строк), а `bankmaterialize.go` ДОБАВЛЕН `6ec9f8a` 29.08, и в него ПЕРЕЕХАЛ код. Прежняя редакция этой строки писала «переименовали», и следствие «ветвь «файла нет» не выстрелила» было лишним: голое имя до той ветви не доходит по построению. Прибор не видел ровно того случая, с которого начался заказ, — и «0 проблемных» был честен про свой вопрос и слеп про этот. ⚠ И одно слово в этой строке названо неточно: пере-замер сделан ГРАММАТИКОЙ линта (его правила разрешения путей и целей), но не самим линтом и не сверкой токенов — у голых якорей токенов нет — этот якорь линт не видит по построению, и два абзаца строки описывают РАЗНЫЕ приборы одним словом. ⚠ И у метода есть ложные срабатывания: две находки этого же прохода я проверил руками — одна («`STACK.md:11` исчезло») оказалась ЛОЖНОЙ, цель жива и точна | оркестратор | скоро | линт печатает покрытие; голых якорей в ЖИВЫХ доках нет | **D39.202** |
| 307 | ⛔ **СПАН ПОД ПОДПИСЬЮ «СКОЛЬКО ЗАКАЗАНО» — ЛОЖЬ ЯРЛЫКОМ, И ЧЕСТНАЯ ФОРМА ДРУГАЯ.** Для заказа, выраженного ЗНАКАМИ, `Run.ordered_chapters` несёт не заказанное, а **СПАН** — сколько глав заказ ЗАТРАГИВАЕТ, считая главу затронутой независимо от того, куплена ли она целиком (`pricing.QuoteUnits` ставит `Chapters: max(chapters, 1)`, вызывающий передаёт `chaptersSpanning`, и сам код называет это «coarser of the two figures»). ⚠ **Замер зоны:** заказ на ОДИН юнит из четырёх в первой главе даёт `1` — **сто процентов завышения на самом дешёвом заказе**, то есть на том, которым сервис пробуют впервые. ⇒ число под именем «ordered chapters», превышающее заказанное, — ложь ярлыком, сколь угодно последовательная. ⭐ **Разбор, снявший спор:** нужда, которую зона защищала («видно, докуда дошли деньги»), настоящая, а носитель неверный — «докуда» есть **ПОЗИЦИЯ** («достигает главы N»), а не **КОЛИЧЕСТВО** («2 главы»), и позиция у платформы УЖЕ ЕСТЬ (`Quote.ThroughChapter`, `BookOrder.ThroughUnitID`). ⚠ Спан ≠ позиция для заказа-продолжения: спан считает затронутые от текущей точки, позиция — ординал. ⇒ **честная форма:** `ordered_chapters: null` для символьного заказа (зеркало `delivered_chapters: null` — «заказано не в главах») + аддитивно `ordered_characters` (эхо запроса) + позиция ординалом, если экрану нужно «докуда». Это смена формы (поле становится нуллабельным) ⇒ минор. ⚠ **Цена смены почти пуста и это ЗАМЕРЕНО:** `ordered_chapters` вошёл в канон только `75ae6f0`, до него в файле НОЛЬ вхождений — клиент 0.10.0 поля не видел никогда, а `ceiling_chapters` тот же минор уже отвергает с 400. ⚠ Поведение менять НЕ требуется: политика «заказ выражен в знаках и меряется в них насквозь» верна и остаётся. До лендинга формы канон описывает ДЕФЕКТ с ⛔-пометкой, а не дизайн | бэкенд+платформа | скоро | `ordered_chapters` нуллабелен, размер заказа эхом, позиция отдельно | **D39.208** |
| 308 | **ВИД ПРОГОНА ЗАКОДИРОВАН НУЛ�ём, И ЭТО ЕДИНСТВЕННАЯ ЕГО МЕТКА ВО ВСЕЙ ПЛАТФОРМЕ.** Явного признака ре-прохода у `LiveRun` НЕТ: `Resnapshot` не годится — он ставится и ОБЫЧНОМУ продолжению после правки банка, а валидация `OrderedChapters == 0 && !Resnapshot` читается «ноль допустим только под пере-снапшот», то есть ре-проход ⇒ resnapshot, а не наоборот. ⇒ **вид прогона различается ЗНАЧЕНИЕМ денежного поля**, и держится это на двух вызовах `max(n, 1)` (`pricing.QuoteUnits`, `runs.chaptersSpanning`). ⚠ **Опасность растёт после лендинга формы заказа** (строка 307): снаружи символьный заказ станет `null`, и единственное место, где `max(n,1)` что-то значит, уходит ВНУТРЬ — следующий читатель колонки (отчёт, CLI) напечатает спан под старым словом и не узнает об этом. ⇒ заказ: **явный признак вида** (`RePass`) вместо кодирования вида нулём. ⛔ **Рантайм-пояса `== 0 && OrderedUnits == nil` ставить НЕЛЬЗЯ** — символьный заказ не может записать ноль ни при каких данных, а гейт от несуществующего состояния завтра прочтут как свидетельство, что состояние бывает. Честная защита до рефакторинга — **ПИН инварианта** «символьный заказ на один юнит пишет в колонку 1, никогда 0» (замер у зоны уже есть — сто процентов завышения на самом дешёвом заказе; норма `D39.209` требует превратить замер в пин) плюс одно предложение в комментарий колонки. ⚠ Это рефакторинг в ДЕНЕЖНОМ коде без дефекта сегодня — отдельным паком, не минором формы заказа | платформа | когда-нибудь (после строки 307) | вид прогона читается признаком, а не значением денежного поля | **D39.208** |
| 309 | ⛔ **ГЕЙТ ВЕРСИИ КОНТРАКТА СВЕРЯЕТ ЧИСЛА, А НЕ ФОРМЫ — И ПОТОМУ НЕ ВИДИТ ГЛАВНОГО РАСХОЖДЕНИЯ.** `TestTheAnnouncedContractVersionIsTheOneTheCanonRatified` сверяет константу сборки с `info.version` канона. Пока эти два числа равны, гейт ЗЕЛЁН — **даже если провод и документ описывают РАЗНЫЕ формы**. Замерено 06.09 трижды за сутки: канон 0.11.0 объявлял полосу «in chapters», а сборка слала юниты; обещал `ordered_chapters: 0` для символьного заказа, а приезжал спан 2; перечислял три значения словаря, а движок слал четыре. **Ни одно из трёх гейт не покраснил**, потому что число совпадало. ⇒ заказ: сверять ПОЛЯ схемы с проводом, а не только версию. ⭐ **Дешёвая форма названа Fable 5 и уже наполовину оплачена нормой:** тест платформы пишет РЕАЛЬНЫЕ ответы в `examples/*.json` (по действующему правилу «фикстуры снимать реальным бинарём»), канон несёт их в `examples:`, линт сравнивает — тогда фраза «both report 0» умерла бы о файл примера, а не о верификатора через сутки. Прозу это не ловит, ЗНАЧЕНИЯ — ловит. ⚠ Вторая половина той же нормы — **авторство**: утверждение канона о ЗНАЧЕНИИ пишет ЗОНА из своих пинов и называет пин в сообщении коммита; оркестратор ратифицирует текст, а не сочиняет его. Три сегодняшние лжи в каноне написаны тем, у кого не было прогона | оркестратор+платформа | скоро | поля схемы сверяются с проводом порождёнными примерами | **D39.208** |
| 310 | ✅ **ИСПОЛНЕНО ЛЕНДИНГОМ 06.09 — акт `D39.213`, `201363b`; замерено, что дефект успел испортить числа приёмки: общий лог дал лишний пакет и СПРЯТАЛ ДВА СКИПА.** ⛔ **БАТАРЕЯ ПРИЁМКИ УМЕЛА ВЫДАТЬ ЛОЖНУЮ ЧИСТУЮ СПРАВКУ О ТОМ, ЧЕГО НИКТО НЕ МЕРИЛ.** `make check` пишет лог в ФИКСИРОВАННЫЙ путь `platform/.check.log` и удаляет его при зелени. Два прогона в одном каталоге — а 06.09 они шли — молча уничтожают улику друг друга: грепу нечего читать, и батарея печатает **«--- every test ran: no host condition was missing ---»** при ПЯТИ скипах. ⚠ **Наблюдено, не выведено** (прогон зоны v16: трижды `grep: .check.log: No such file or directory`, следом чистая справка, `MAKE-EXIT=0`). Код возврата остаётся нулём, потому что статус берётся от `go test` ДО грепов, ⇒ наружу выходит СПРАВКА О НЕИЗМЕРЕННОМ, а это хуже отсутствия справки: она закрывает вопрос, которого никто не задавал. **Девятая форма ложной зелени** (`D39.202`) в самом приборе приёмки. ⇒ заказ: батарея ПАДАЕТ ГРОМКО, если лога нет (либо имя файла уникально на прогон); мутация «снять лог» обязана краснить `gates.TestTheBatteryNamesEveryHostConditionItsTestsRead`, а не проходить. ⚠ Обходной путь на сегодня, применённый обеими сторонами: числа снимать своим `go test ./... -race -count=1 -v` в файл ВНЕ каталога зоны, куда чужой прогон не дотянется. ⭐ Нашла платформенная зона на СЕБЕ и намеренно НЕ чинила в составе дофикса, чтобы не смешивать предметы посреди лендинга | платформа | скоро | лог не найден ⇒ батарея красная, а не «всё прогналось» | **D39.212** |
| 311 | **ПОПРОГОННЫЙ ЛОГ БАТАРЕИ КОПИТСЯ: КАЖДЫЙ УПАВШИЙ ПРОГОН ОСТАВЛЯЕТ СВОЙ ФАЙЛ НАВСЕГДА.** Прежнее ФИКСИРОВАННОЕ имя само себя ограничивало — сколько бы прогонов ни падало, оставался ОДИН несвежий файл, и следующий его перезаписывал. Починка `D39.213` сняла коллизию вместе с этим свойством: `.check.log.` не убирает никто. ⚠ **Замер:** к утру 06.09 в корне зоны лежали ЧЕТЫРЕ таких файла нулевого размера от прибитых прогонов и стаб-проб (удалены зоной как её мусор). ⛔ **Опасность НЕ в коммите** — `platform/.gitignore:3`=`.check.log*` их держит, проверено. Опасность в том, что через месяц человек не отличит «мусор от прерванных прогонов» от «лога, который рецепт НАРОЧНО сохранил при падении, чтобы его прочли», — а второе законная и нужная функция, и она тонет в первом. ⇒ заказ: перед прогоном убирать логи, чей PID УЖЕ МЁРТВ (`[ -d /proc/$p ] || rm -f`). ⛔ Голый `rm -f .check.log.*` ставить НЕЛЬЗЯ: он снова снесёт улику параллельного прогона — ровно тот дефект, из которого всё и выросло. ⚠ Привязка к `/proc` линуксовая; зона на Linux, но это оговорка, а не мелочь. ⭐ **Названо ЗОНОЙ про собственную починку уже ПОСЛЕ того, как я её принял** — то есть ценой не приёмки, а совести | платформа | когда-нибудь (следующее касание прибора) | мёртвые логи убираются, живые не трогаются | **D39.213** |
| 312 | ⚠ **ДВИЖКОВАЯ ПОЛОВИНА ЗАКРЫТА 08.09 (`D39.228`): счётчик нечитаемого оглавления уехал из лога в МАНИФЕСТ — `BookManifest.TOCUnreadable *int`, указателем, чтобы «сайдкар старше поля» отличалось от нуля; пин `TestTheManifestSaysADeclaredTableOfContentsCouldNotBeRead`. ОСТАЁТСЯ ПЛАТФОРМЕННАЯ, и она — ровно исходный вопрос Д-3: увидит ли факт ЧЕЛОВЕК.** ⛔ Замер 08.09: `toc_unreadable` даёт **0 хитов в `platform/` при 200 `.go`** — поле пишется и не читается никем; для пользователя не изменилось НИЧЕГО, книга с нечитаемым оглавлением по-прежнему продаётся по знакам без слова о причине. ⚠ **испр. 08.09: акт `D39.228` объявил строку закрытой и УДАЛИЛ её; строка возвращена суженной** — тот же класс, что 253, и в том же акте обработанный противоположно. Класс A для этого поля НЕ объявлялся (п.8 акта объявляет его только для `consolidation`) — объявляется здесь. Единственный, кто видит ключ сегодня, — оператор, руками запустивший `tmctl manifest`. **Ниже — тело исходной находки.** ЗАЯВЛЕННОЕ, НО НЕЧИТАЕМОЕ ОГЛАВЛЕНИЕ ПРОВАЛИВАЛОСЬ МОЛЧА: книга ЗАЯВИЛА оглавление, движок не смог прочесть эти байты — и тихо падал до spine, отдавая продажу ПО ЗНАКАМ, без единого слова о причине. ⛔ `toc_unresolved = 0`, потому что целей НОЛЬ — прибор честно отвечает на свой вопрос, а читается это как «всё разрешилось» (`D39.202`) | платформа | скоро | причина нечитаемого оглавления доезжает до ЧЕЛОВЕКА, а не до файла | находка ревизии 06.09, пере-открыто кросс-модельным ревью ратификаций 08.09 |
| 313 | ⚠ **НОСИТЕЛЬ ПОЯВИЛСЯ 07.09 (`D39.225`): цель `make mutations` гоняет подмножество каталога (14 из 225) на копии дерева и печатает свип якорей СО ЗНАМЕНАТЕЛЕМ (`0 of 225 rotten`) при каждом прогоне, зелёном тоже. Вне `battery` намеренно: пере-замер 07.09 дал 123 % её времени и гейт идёт без `-race`. ОСТАЁТСЯ: остальные 211 записей по-прежнему проверяются только на живость цели.** ⛔ **КАТАЛОГ МУТАЦИЙ ДОКАЗЫВАЕТ, ЧТО МУТАЦИЯ СУЩЕСТВУЕТ, А НЕ ЧТО ОНА ЛОВИТСЯ.** Из **211** записей каталога регулярно гоняются единицы (в паке структуры глав — 14, целящие в изменённое поведение); остальные проверяются только на ЖИВОСТЬ ЦЕЛИ грепом. ⇒ зелёный каталог говорит «посадка на месте», а читается как «посадка краснит». **Тот же класс, что `D39.214` п.3: доказано одно, сказано про другое.** ⚠ Носителя у этого НЕ БЫЛО ни строкой, ни рядом — проверено грепом по живому бэклогу 06.09 по прямому вопросу оркестратора; ближайшая строка 252 говорит о ДВУХ конкретных выживших посадках 04.09 и о полном прогоне не говорит ничего. ⭐ **Третий за час случай, когда находка жила только в письме** (первые два — находки платформы без рядов и нечитаемое оглавление строки 312): **находка без носителя не находится.** ⇒ заказ: либо каталог гоняется целиком по расписанию, либо его зелень перестаёт называться доказательством ловли — формулировку выбирает зона, но молча оставлять нельзя. ⚠ Назвал СТРОИТЕЛЬ про собственный пак, единственным из пяти своих сомнений, что закрыл бы ДО продажи ⚠ **Цена полного прогона ЗАМЕРЕНА 06.09, и отсрочка обоснована ею, а не удобством:** 126 записей из 211 гоняют `internal/pipeline` по ~3 минуты ⇒ полный прогон **6+ часов**. При этом 197 непрогнанных — УНАСЛЕДОВАННЫЕ, каждая краснела у заводившей смены. ⇒ это стоячая гигиена, а не крит; зона прямо отказалась изображать закрытие шестичасовым прогоном «вдруг что-то протухло» | бэкенд | когда-нибудь | зелень каталога означает пойманную мутацию, а не существующую запись | **D39.214** |
| 314 | ⛔ **РАЗРЕЗ ПРОВЕРЯЕТСЯ ТОЛЬКО НА НЕИЗМЕННОСТЬ — НА ПРАВИЛЬНОСТЬ ЕГО НЕ ПРОВЕРЯЕТ НИЧТО.** Ни один гейт, тест или замер не отвечает на вопрос «верны ли ЭТИ границы»: гейт сравнивает «до» и «после», оракул сверяет два прибора движка МЕЖДУ СОБОЙ. ⚠ **Инвариант сохранения доказывает СОХРАННОСТЬ и молчит о КОРРЕКТНОСТИ** — он считает разбиение (каждый читаемый документ либо исключён намеренно, либо ровно в одной группе) и сходится ОДИНАКОВО при верной и при неверной группировке, если та ничего не теряет. ⇒ «инвариант сошёлся на трёх живых книгах» доказывает сохранность, а читается как корректность разреза. Что 71 глава для Kristoff — ВЕРНО, не показал никто; показано лишь, что так говорит его `nav`. **Тот же класс, что `D39.214` п.3: доказано одно, сказано про другое.** ⭐ Назвал СТРОИТЕЛЬ про собственный пак, найдя это в своих же утверждениях, а не в чужих. ⚠ **Измеримая часть ЗАМЕРЕНА 06.09 и расхождения не дала:** «совпадает ли отданный разрез с тем, что книга ОБЪЯВЛЯЕТ» — по трём книгам 193 цели оглавления, **все на уровне документа, ни одной внутрь документа** (Kristoff 71 · isekai 88 · fifty_shades 34) ⇒ там, где объявленное можно сверить механически, оно сходится. **Остаётся ровно некруговая часть: верно ли то, что объявляет сам `nav`** — она требует человеческого суждения и не закрывается ни тестом, ни прибором. ⇒ **строка стоит не как задача, а как признанная ГРАНИЦА** | бэкенд | когда-нибудь | есть носитель, отвечающий «верны ли границы», а не только «не изменились ли они» | **D39.214** |
| 315 | ✅ **ЗАКРЫТА ЗАМЕРОМ 06.09 — ПРОШЛА.** Блокер («промтов пары `en-ru` нет») снят БЕЗ нарушения запрета: у пар-конфига есть ручка `prompts_root` (`backend/internal/config/pair.go:33`=`PromptsRoot string`, проверено мной), и корень промтов-заглушек собран ВНЕ репозитория — в дереве не создано ничего, промт-пака пары как не было, так и нет. **Замер зоны, `tmctl manifest`, EXIT 0, $0:** `structure: declared` · 71 глава / 351 юнит / 356 чанков · `manifest_version` НЕ сдвинут · нумерация плотная 1..71 без дыр и дублей, `number: null` — ноль · id глав уникальны · **`title_raw` на проводе 71 из 71**, настоящие · ценовая проекция на всех трёх уровнях, глав без цены ноль. ⭐ **И то, что видно только на живой НЕ-CJK книге: `heading` пуст у ВСЕХ глав** (шаблона для пары нет), **а `title_raw` заполнен** ⇒ единственное, что несёт название главы для этой книги, — поле, которое построил этот пак. Обоснование §2.5 стало замером, а не доводом. ⚠ Числа — зоны, на её стенде; механизм обхода блокера и чистоту дерева проверил я. ⛔ Прежняя формулировка: **МАНИФЕСТНАЯ ПОЛОВИНА EPUB НЕ ПРОХОДИЛА НИ РАЗУ НА ЖИВОЙ КНИГЕ.** `tmctl manifest` на EPUB владельца не идёт — промтов пар `en-ru`/`ja-ru` не существует, и пак структуры глав чинить это не заказывал. ⇒ `title_raw` на проводе, id глав и ЦЕНОВАЯ ПРОЕКЦИЯ для EPUB держатся **исключительно на фикстурах авторства самой зоны**; книги владельца мерены только на уровне ингеста. ⚠ **Первая же платная EPUB-книга пойдёт по пути, который на живой книге не проходил никогда** — и это ДЕНЬГИ, а не удобство. ⭐ Стоит в отчёте зоны §6, но отчёт не трекер: через месяц его никто не откроет — ровно довод, которым эта строка и заведена | бэкенд+полигон | скоро | манифестная половина EPUB пройдена на живой книге хотя бы раз | **D39.214** |
| 316 | **У ЭРРАТ НЕТ РЕЕСТРА, И ЧИТАТЕЛЬ НОТЫ НЕ МОЖЕТ УЗНАТЬ, КАКИЕ ИЗ НИХ К НЕЙ ОТНОСЯТСЯ, НЕ ПРОЧТЯ ВСЕ.** Замер верификатора 06.09: эррат в шапке **53**, из них 06.09-* — **10**; на `D39.212` их три, на `D39.211` две, на `D39.213` две; длина одной — **929–4020 знаков ОДНОЙ строкой**. ⇒ **чтобы прочесть `D39.212` верно, надо прочесть 7912 знаков эррат при теле акта около 5000 — корректирующего текста БОЛЬШЕ, чем корректируемого**, и цепочка уже глубиной два (`06.09-ж` правит `06.09-г`). ⚠ **Дефект НЕ в объёме правок:** след — это ровно то, ради чего смена стоила своих денег, и все сегодняшние нормы выводимы только из него (что заявлено, кем опровергнуто, чем). Дефект в том, что **у нот реестр есть (`docs/architecture/05-decisions-index.md`), а у эррат нет ничего.** ⇒ дешёвая форма, названная верификатором: строка реестра получает колонку «живые эрраты», `counts.py` её сверяет — тот же класс, что восьмой гард итога регистра: **не помнить, а проверять**. ⚠ **Отложено сознательно, а не забыто:** это седьмая правка прибора за смену, а предыдущие шесть трижды потребовали починки после приёмки; менять гейт на исходе смены — ровно та спешка, которой этот бэклог посвящён | оркестратор | скоро | к ноте один хоп даёт список живых эррат, и его сверяет гейт | **D39.202** |
| 317 | **У ЧИСЛА, СТОЯЩЕГО В КАНОНЕ, НЕТ ПРИБОРА В РЕПОЗИТОРИИ.** `D39.214` п.6 цитирует замер «сканер по 193 свойствам схем канона, три правила, семь флагов, пять ложных, два настоящих». **Сканер не закоммичен** — проверено грепом 06.09. ⇒ ни «193», ни «семь» не воспроизводимы никем, включая автора. ⛔ **ПОДОЗРЕНИЕ НА НЕПОЛНОТУ СКАНА СНЯТО 06.09 — И СНЯЛ ЕГО ТОТ, КТО ПРИНЁС.** Сначала агент верификатора пере-выполнил три правила по описанию и получил **двенадцать** флагов; это читалось как «зона что-то не досмотрела». Верификатор довёл зацепку до замера сам: **189 свойств, 9 уникальных флагов** — ровно зонные ПЯТЬ ложных плюс `Chapter.number` (настоящая находка, уже диспозиционированная) плюс три `EventStatus.*_reason`, **которые оказались дефектом ЕГО реализации**: правило читало `description` самого поля и не читало РОДИТЕЛЬСКИЙ объект, документирующий все три разом (`docs/architecture/14-api-contract/openapi.yaml:3159`=`unless its own status`). ⇒ **знание там не расщеплено, а централизовано — сказано один раз на три поля, и это лучше, чем трижды.** Семёрка зоны ВЕРНА, пропущенного нет. ⚠ И `OrderOptions.structure` прибор больше не флагует — потому что зона его починила. ⇒ **дефект этой строки — НЕВОСПРОИЗВОДИМОСТЬ числа, а не его неверность**, и срочность соответствующая. ⭐ **Та же форма, что норма «число называет ДЕРЕВО и ПОПУЛЯЦИЮ», только про ИНСТРУМЕНТ:** одноразовый скрипт, давший число в канон, обязан ехать в репозиторий вместе с числом — иначе замер неотличим от утверждения. ⇒ заказ: либо сканер ложится в `platform/` (или `docs/scripts/`) и число пере-снимается им, либо число в каноне помечается как невоспроизводимое. ⚠ Принёс верификатор ПОСЛЕ своего «ок», прямо сказав «это зацепка, а не находка, и опровержением зоны я это не считаю» | платформа+оркестратор | когда-нибудь | число в каноне пере-снимается прибором, лежащим в дереве | **D39.214** |
| 319 | ⛔ **ПРИБОР СЛЕПОГО ЧТЕНИЯ ШТРАФУЕТ РОВНО ТО ПОВЕДЕНИЕ, КОТОРОЕ САМ ЖЕ ЗАКАЗЫВАЕТ.** Судимой руке предписано `eval/dovodka/prereg-4axes/stand/editor-p9.md:5`=`Сверяй смысл черновика с исходным текстом` — то есть ОТХОДИТЬ от черновика там, где он искажает оригинал. А блокирующая линза `eval/dovodka/blind-read/PREREG-2-BLIND-READ.md:62`=`точность относительно черновика` меряет верность ЧЕРНОВИКУ, ⇒ мы велим редактору ОТХОДИТЬ от черновика там, где тот переврал оригинал, и меряем его ВЕРНОСТЬЮ черновику. ⛔ **ПРОТИВОРЕЧИЕ КОНСТРУКЦИИ ДОКАЗАНО — ВЕЛИЧИНА ИСКАЖЕНИЯ НЕ ЗАМЕРЕНА, и это разные вещи.** Прежняя редакция строки писала «прибор СИСТЕМАТИЧЕСКИ поощряет якорение» и «отход от черновика записан в ДЕФЕКТЫ»: **испр. 06.09 автором строки** — фраза «Отход от черновика» встречается в сыром судейском массиве ОДИН раз, то есть это наблюдение, а не свойство, и масштаб я выдал за факт, не посчитав. Доказано ровно одно: две бумаги в одном дереве требуют взаимоисключающего. ⇒ вывод замера **ненадёжен ПО ПОСТРОЕНИЮ** независимо от частоты, и величину надо мерить ДО любого следующего решения о тире редактора. ⚠ Задет приоритет владельца №2 («отсутствие выдумок — редактор, сверка с ИСХОДНИКОМ», `D39.198` п.2). ⭐ **Этого довода в отчётах Кодекса НЕТ — он найден консилиумом**, и он сильнее всего, что там написано. ⚠ Обвязка с исходником уже существует в том же дереве (`eval/dovodka/judge-prompts/`), то есть нужен не новый прибор, а ПЕРЕ-ПОДКЛЮЧЕНИЕ готового. ⚠ ⚠ **Три эрраты в носителях замера — ФОРМОЙ БАННЕРА, тела НЕ править** (оба документа заморожены, и пре-рег ценен именно неизменяемостью), и **горизонт у них другой: ПЕРВЫМ касанием полигона, ДО пака починки линзы** — иначе три дешёвые правки будут ждать дорогого пака. Не исполнены ни одна: «правильный ответ по построению — ничья» противоречит собственному тексту отчёта; из §8 пре-рега выпало унаследованное ограничение «опора судьи — черновик, не оригинал»; правило решения готово выдать вывод, который отчёт результата запрещает дословно | полигон | скоро | линза меряет то, что руке заказано, и носители замера не противоречат себе | **D39.198** |
| 320 | **ДВА СОВЕТА ДВИЖКА, КОТОРЫХ ДВИЖОК НЕ ИСПОЛНЯЕТ.** (а) `backend/internal/membank/memseed.go` советует оператору «mark one status: auto», а гард полисемии статус НЕ СМОТРИТ вовсе — условие `a.Src != b.Src || a.Dst == b.Dst || !windowsOverlap(...)`, и совет в пределах одного файла не сработает НИКОГДА. Одна строка плюс тест. (б) `internal/lang/data/``injection.txt` несёт заголовок «НЕПОДТВЕРЖДЁННЫЕ РАБОЧИЕ ВАРИАНТЫ», живой в сборке (`internal/lang/embedded.go:449`), тогда как `membank/memory.go` прямым текстом объявляет «NO ⟨проверить⟩ MARKER, and no fork by status at all» по `D39.104` п.2. ⚠ Правка ДАННЫХ — стоп-мир (`EmbeddedVersion` → `cutTag` → `manifest_key`), поэтому прицепом к паку строки 161, а не отдельным заходом; правка комментария (а) дешева и сегодня | бэкенд | скоро | совет и заголовок описывают то, что сборка делает | **D39.202** |
| 321 | ⛔ **РЕДАКТОР ПОДБИРАЕТ БАНК БЕЗ ПАМЯТИ О ПРЕДЫДУЩИХ ЕДИНИЦАХ, И ОПРАВДАНИЕ В КОДЕ ЛОЖНО.** Черновая волна передаёт sticky-контекст, редакторская — `nil`; комментарий рядом оправдывает это тем, что единица есть глава либо её часть, «так что внутриглавное окно липкости неприменимо». **Оправдание неверно:** глава РЕГУЛЯРНО делится на несколько правочных единиц (`assignEditUnits` жадно пакует чанки до потолка и закрывает единицу ВНУТРИ главы), а sticky сбрасывается только на границе ГЛАВЫ. ⚠ **ЗАМЕР 06.09 (Fable 5, `tmctl manifest` на `22e079e`, $0):** слайс 25 глав — 57 чанков / 37 единиц / **11 многоединичных глав**; ПОЛНАЯ книга — 2283 главы / 5071 чанк / 4276 единиц / **1962 многоединичных, то есть 86 %**. Прежнее «56 чанков» взято из архивной СИМУЛЯЦИИ, факт 57. ⛔ **И картина «черновик сохраняет — редактор теряет» верна только для СИДОВОГО банка:** на нынешнем стенде все строки mined, базовый банк ПУСТ, черновая волна банка не несёт вовсе, а редакторская — единственная с банком — не переносит между единицами. ⚠ **Экспозиция замерена, дрейф — НЕТ:** теряется 49 банковых строк на 12 единицах, из них у **4** форма перевода уже стоит в черновике (все Confirmed); инцидентов не наблюдено ни одного. ⇒ **сначала мерить на следующем платном прогоне** ($0 по хранилищу), потом строить. ⚠ Теста, фиксирующего нынешний `nil`, НЕТ ⇒ правка это багфикс, а не смена заказанного поведения. ⚠ **Sticky — это множество id БАНКОВЫХ строк, не пересказ повествования**; отчёт Кодекса описал его неверно, и это отдельно опровергнуто. ⇒ предмет: либо передавать, либо привести комментарий к правде — но молча оставлять оправдание, которое разошлось с кодом, нельзя | бэкенд | скоро | редакторская волна либо несёт перенос, либо объясняет отказ верно | **D39.215** |
| 322 | ⛔ **УКАЗАТЕЛЯ ПРИНЯТОЙ РЕДАКЦИИ НЕТ: НЕУДАЧНАЯ ПОВТОРНАЯ РЕДАКТУРА ЗАТИРАЕТ ДОСТУПНЫЙ РЕЗУЛЬТАТ.** ⛔ **ПРОДУКТОВАЯ РАМКА ЭТОЙ СТРОКИ БЫЛА НЕВЕРНА И СНЯТА 06.09 (поправка владельца):** функции «заказать вторую редактуру» у нас НЕТ. Есть **ре-проход**, законный только при СДВИНУВШЕМСЯ банке — человек исправил термин и просит пере-прогнать книгу. ⇒ верное утверждение узкое: **ре-проход пере-делывает затронутую единицу ЦЕЛИКОМ** тем же редакторским промптом (режима «правь только термин» в движке нет), **прежний текст остаётся в чекпойнтах, но без адреса** — ни одна строка статуса на него не указывает, экспорт его не видит, отката нет; **и ничто нигде не сравнивает старый вывод с новым**. ⛔ **Единственный БЕЗВОЗВРАТНЫЙ путь найден:** ре-проход флагнулся → оператор делает `redrive` → сброс стадий сносит чекпойнты **ФЛАГНУТОЙ стадии по всем снапшотам**, и прежний хороший чекпойнт РЕДАКТУРЫ в их числе. ⚠ **Испр. 06.09: стояло «ВСЕ чекпойнты чанка» — шире правды**, черновая строка уцелевает (`backend/internal/pipeline/volume.go:717`=`deletes only the FLAGGED and SKIPPED`). Довод о безвозвратности от этого не страдает: теряется именно принятая редактура. ⚠ Попутно: комментарий `backend/internal/store/chunkstatus.go:52-57` про «резюм переписывает строку» ЛОЖЕН — обычный резюм её не пишет. ⭐ Это ЯДРО гипотезы 1 отчёта `research/32`, и консилиум его ПОДТВЕРДИЛ — единственная его архитектурная часть, устоявшая целиком. ⚠ Полный revision-контур (схема, семантика `chunk_status`, экспорт, контракт, платформа) — смена курса и дизайн-пак масштаба строки 161, НЕ заказ этой строки. **Заказ здесь узкий: указатель принятой редакции**, чтобы повторная попытка не могла уничтожить принятое | бэкенд+платформа | скоро | вторая редактура не может отнять первую | **D39.215** |
| 323 | **ЧЕСТНАЯ ЦЕНА ПРАВКИ БАНКА — НЕ «ПЕРЕПОКУПКА КНИГИ», И ЭТО МЕНЯЕТ ДОВОД, КОТОРЫМ ЗАЩИЩАЛИ БЕЗДЕЙСТВИЕ.** ⛔ **ФОРМУЛА ПЕРЕПИСАНА 06.09 ПО ЗАМЕРУ — прежняя редакция была завышена в ТРЁХ местах.** Верно: подпись через `bank-apply` двигает ТОЛЬКО редакторскую волну и стоит **единицы, чей исходник содержит ключ термина внутри его окна** (плюс те, где термин перестал инжектироваться); остальное ре-пиньтся за $0 **при явном `--resnapshot`**. Правка СИДОВОГО файла двигает обе волны и добавляет черновые чанки с ключом плюс **до двух следующих чанков той же главы** (рябь переноса), а также все единицы с перекупленным черновиком — **последнего смета НЕ ВИДИТ**. ⛔⛔ **И главный денежный член был пропущен: проход терминолога перекупается НА КАЖДУЮ ПОДПИСЬ, он тратится ДАЖЕ БЕЗ `--resnapshot`, и его ПЕРЕПОКУПКА невидима смете и согласию** (⚠ испр. 06.09: стояло «невидим смете» без оговорки — шире правды: смета ПЕРВОГО прогона проход несёт потолком, `backend/internal/pipeline/priceprojection.go:317`=`BookOnceUSD: r.bookOnceUSD()`; невидима именно перепокупка на подписи, строка 38) (центы: $0.005 на четырёх главах, $0.026+$0.034 на десяти; потолок — бюджет). ⚠ Прежнее «опровергнуто кодом и тестом» тоже сильнее правды: пин доказывает игрушечный случай — две главы по чанку, mined-only, без прохода майнинга, без ряби и каскада. ⚠ Значение: «оставить как есть, потому что чинить дорого» — довод, которым закрывали вопрос неверной банковой строки, — **отпадает по цене**. Сам закон банка при этом НЕ оспаривается: доказательств против `D39.104` нет ни у одного голоса. ⚠ Оговорки названы и не спрятаны: бесплатность неполная, проход терминолога пере-покупается (строка 38), и всё это только при ЯВНОМ `--resnapshot` | оркестратор | скоро | цена правки банка названа формулой, а не страшилкой | **D39.215** |
| 324 | **ВХОД РЕНДЕРА ЗАКРЫТ: СОСЕДНЕЕ ПОВЕСТВОВАНИЕ НЕЛЬЗЯ ПОДАТЬ ДАЖЕ ПРАВКОЙ ПРОМПТА.** Шаблон принимает фиксированный набор плейсхолдеров, неизвестный `{{…}}` — жёсткая ошибка. ⇒ на дежурный ревью-вопрос «заработает ли это без правки Go» ответ здесь сегодня **«нет»**, и это признанный долг, а не дефект: пара-данные общности так и задуманы, но ИМЕННО этот вход расширяется только кодом. ⛔ **ИСПР. 06.09: сцепка со строкой 321 была МИМО ПРЕДМЕТА** — там переносятся id банковых строк по инъекционному каналу, а не через шаблон, и в шаблон это не упирается вовсе. В шаблон упирается только «дать редактору соседний ТЕКСТ», и это отдельная гипотеза. ⚠ И это НЕ долг общности: набор — движковые рантайм-значения, пар-специфики в нём нет; таблица в данных стала бы вторым носителем. ⇒ **строить не надо**, предмет переформулирован в контракт входа. Если гипотеза соседнего текста подтвердится замером — правка Go снапшот НЕ двигает, но использование в боевом промпте двигает его через хеш промпта ⇒ редакторская волна перекупается ОДИН раз | бэкенд | когда-нибудь | вход рендера расширяем данными либо отказ объявлен в носителе | **D39.215** |
| 326 | ⛔ **ПОНЯТИЯ «БЛОКЕР БЕТЫ» В ТРЕКЕРЕ НЕТ, И КРИТЕРИЯ ВПУСКА ПЕРВОГО ПОЛЬЗОВАТЕЛЯ В РЕПОЗИТОРИИ НЕ СУЩЕСТВУЕТ.** Замер 06.09: гейт печатает «блокеров очереди: 0», но этот вес — про ОЧЕРЕДЬ, а не про бету; слово «бета» в строках бэклога встречается считаное число раз и НИ РАЗУ не как критерий впуска (⚠ счёт из строки снят 06.09: я привёл «три из 236», а пере-счёт даёт 5 из 229 — оба числа были неверны, а утверждение в них не нуждается); греп по `docs/`, `platform/docs/`, `backend/docs/` на «первый пользователь / первая внешняя книга / впуск» не даёт ничего. ⇒ **вопрос «сколько ещё до беты» не читается из трекера не потому, что мало сделано, а потому что трекер никогда не нёс этого понятия.** ⚠ Практическое следствие: любой ответ о сроке беты сегодня — оценка сессии, а не состояние проекта, и проверить его нечем. ⇒ заказ: **линия остановки как ПРОВЕРЯЕМОЕ условие** (прогон на чужом файле через ту же дверь · деньги сходятся либо маржа видна пользователю · застрявший прогон видно и лечится · ни один экран не врёт о единице · вход сужен до того, что умеет выдача) — формулировку утверждает ВЛАДЕЛЕЦ, носитель заводит оркестратор | владелец → оркестратор | скоро | в дереве есть проверяемый критерий впуска первого внешнего пользователя | **D39.215** |
| 327 | ⛔ **ОСТАТОК ПОЛИГОН-ПАКЕТА №4 ЖИВЁТ ТРИ МЕСЯЦА ВНУТРИ ПРОМТА, И В НЁМ ЛЕЖИТ ДАТИРОВАННЫЙ РИСК.** ⚠⚠ **Срочное: замерный судья `memory_eval.py` работает на `gemini-2.5-flash`, у серии объявлен shutdown **16.10.2026** — около шести недель от 06.09.** Носителя у этого НЕ БЫЛО: единственное вхождение слага в бэклоге — проза про ЦЕНЫ другой модели, а не про миграцию нашего судьи (проверено грепом по предмету, не по имени). ⇒ после отключения замерный контур встанет, и узнаем мы это отказом, а не планом. Там же: двойной `extra_body` и отсутствие 404-ретрая при живом слаге. ⚠ Остальные пять пунктов остатка, тоже без носителей: матчер content-filter подстрокой + самотест · параметризация языка/жанра судейского промпта (ja/en сняты под zh-рамкой) · проба судьи-дублёра 18+ · калибровка echo-gate (`D25.7`) · minimal-pairs 100–150 для shadow fidelity (`D25.2`). ⭐ **Класс, а не случай:** промт `POLYGON_PACKAGE4_SESSION_PROMPT.md` с 12.07 стоит «частично отработан, residual ЖИВ», как отдельная сессия НЕ запускался — то есть **носителем работы служит промт, а не трекер**, и в трекере этой работы не видно вовсе. ⇒ заказ: остаток становится строками, промт уходит в архив с баннером исхода, а в ролевой промт оркестратора вносится правило выхода «residual → строка бэклога, промт в архив» — сегодня его там нет, и именно поэтому пакет №4 жив три месяца | полигон | скоро (миграция судьи — ДО 16.10) | остаток несут строки, промт в архиве, правило выхода записано | **D39.216** |
| 329 | ⚠ **ОСТАТОК АУДИТА ПАКОВ И ДОКОВ 06.09: 77 находок, закрыто лендингом `e4097cb` только то, что било по двум выданным пакам.** Доказательная база — `docs/archive/reports/PROMPT_AND_DOCS_AUDIT_2026-09-06.md`. ⛔ **Вес и формулировки там принадлежат АГЕНТАМ: веер остановлен владельцем на логической точке (расход), и опровергатель прошёл НЕ по всем** ⇒ перед исполнением каждая пере-снимается по дереву. Названные, но не разобранные кандидаты: `backend/docs/components.puml` и `pipeline.puml` (глаголов 11 против 6, `.bank-stop.json` снесён D39.158, «интерим» пака-17 закрыт) · `backend/docs/MONEYSTOP_REPORT.md:3` · `docs/architecture/12-go-style-notes.md:17` (построчный маркер снят с провода, сам ⟨проверить⟩ едет) · `docs/architecture/15-money-path.md:62` и строка бэклога **166** (платформенная половина названа дырой, а построена — 19 файлов зоны) · `platform/BACKLOG.md:25` (П-10, четыре ложных утверждения) · `platform/docs/DEFECT_REGISTER.md` `PD-458` (статус-жертва: лекарство легло тем же коммитом). ⚠ Правки в ЧУЖИХ зонах — пинги владельцам зон, не своя правка | доки | скоро | пере-снятие каждой находки по дереву + правки в своей зоне + пинги в чужие | аудит промтов 06.09 |
| 330 | ⛔ **ЧТО ДВИЖОК ДЕЛАЕТ С ПРОТИВОРЕЧИЕМ В БАНКЕ — РЕШЕНИЕ ВЛАДЕЛЬЦА, И ОНО ПРО ДЕНЬГИ.** Слово владельца (строка 267): «у неподписанного термина тоже обязан быть ОДИН перевод». Сегодня движок противоречие в лучшем случае ВИДИТ: `ApprovedSharedKeyCollisions` роняет прогон на approved×approved, `UnverifiedKeyConflicts` варнит approved×unsigned, детектор схлопывания (пак 06.09) добавит репорт. **Ни один не делает ОДИН перевод.** Два выхода требуют слова владельца, потому что оба стоят денег: (а) «варнинг→стоп» для approved×unsigned — роняет ОПЛАЧЕННЫЙ прогон, довод против записан в коде (`backend/internal/membank/memseed.go:685-688`: самострел); (б) отказ схлопывания отдавать противоречащую форму — термин остаётся несхлопнутым, банк держит прежнюю форму; это меняет СОДЕРЖИМОЕ банка ⇒ двигает `memory_version` и снапшот редакторской волны ⇒ **пере-покупка на затронутых книгах**. ⚠ Разводить (а) и (б) по разным пакам нельзя — это ОДИН вопрос «что ДЕЛАЕМ», в отличие от «видим ли» (`D39.216`). ⇒ вопрос владельцу подаётся ВМЕСТЕ с ценой, и она ЗАМЕРЕНА 06.09 бэкенд-зоной ($0, read-only, прибор в дереве — `backend/internal/pipeline/bankconflict_corpus_test.go`, opt-in по `TM_CORPUS`): **обошёл 162 файла БД, 161 с таблицей глоссария, 142 книги с непустым банком, прочитано 13 350 строк; книг с ЛЮБЫМ конфликтом — 0**. ⛔ **Ноль ЧЕСТНЫЙ, и вот три величины, которые делают его читаемым:** популяция огромна (12 257 из 13 350 строк неподписанные — approved 1093 · draft 11399 · auto 858, то есть недостающее правило покрывает 92 % банка, а не экзотику) · форма столкновения в корпусе не возникает, потому что все существующие двери роняют дубль по ПОЛНОМУ ключу `(src,sense,since_ch,until_ch)`, а разные ОКНА через них проходят · подсаженная противоречащая строка ловится на **142 из 142** книг, значит прибор мерит. ⭐ **И решающее для владельца: СТАРОЕ правило (approved × unsigned) на том же корпусе тоже даёт 0** — то есть обе половины одинаково НЕ НАБЛЮДЕНЫ, и решать он будет про класс риска, а не про частоту | владелец | скоро | решение владельца по (а) и (б) одним ответом + цена в книгах | пинги П1/П2 бэкенд-сессии 06.09, пак «закон банка честно» |
| 332 | ⛔ **СИНХРОННЫЙ РАЗРЕЗ НА ПРИЁМЕ ПРИНЯТ НАПОЛОВИНУ: ПОСТРОЕН, НО НЕ ГОТОВ — сработало правило остановки.** Из одиннадцати major пака девять легли в этот один механизм, и каждая починка открывала новую площадь ⇒ зона прекратила его чинить по решению оркестратора, а не по усталости. **ДЕСЯТЬ незакрытых пунктов — поимённо в зонном журнале** `platform/docs/platform-PROGRESS.md`, греп `СРАБОТАЛО ПРАВИЛО ОСТАНОВКИ`; здесь копии НЕТ (один носитель). Первый из них определяет форму: **граница бюджета хвоста обязана ВЫВОДИТЬСЯ ИЗ кода пути, а не перечисляться руками** — счёт выводили трижды и трижды неверно. ⚠ Ложный инвариант бюджета заландён осознанно: окно лжи 8 секунд ширины (дедлайн 26m21s–26m29s) при дефолте 10m0s, последствие — теряется идемпотентность (повтор даёт вторую книгу), а не целостность; ряд регистра несёт числа. Три пункта дописаны приёмкой: потерянный ограничитель параллелизма (`MaxWorkers: 4` был у очереди, теперь разрез живёт в HTTP-обработчике без лимитера) · маршрут молчит до 210–220 с после последнего байта, промежуточный прокси не спрошен · отказ уходит наружу только МАШИННЫМ кодом. ⚠ **испр. 08.09: прежняя редакция называла дефектом незаполненный `Detail` — это НЕВЕРНО и ведёт чинить запрещённым инструментом.** Канон дословно: `title` и `detail` пишутся для РАЗРАБОТЧИКА и лога, клиент их пользователю показывать НЕ ДОЛЖЕН; единственное исключение `localized` не несёт ни одна строка кода. При этом словарь `errors[]` ОТКРЫТ по словам канона, и обе причины отказа разреза уже едут перечислимыми (`no_book`, `no_chapter_structure` — `platform/internal/httpapi/problem.go`), а расширяется полоса через НЕ закрытый `cause.code`, тогда как новый КОРНЕВОЙ `code` есть ломающее изменение и минор. ⇒ вопрос не «как довезти», а «какая причина ещё не перечислена и рисует ли клиент фразу» | платформа | скоро | пак, забирающий разрез: вывод границы из кода + десять пунктов журнала | приёмка пака «деньги и правда» 07.09 |
| 339 | **РОЛИ НЕ ПОКАЗЫВАЮТ СУЩЕСТВУЮЩУЮ ФОРМУ ПОВЕРХНОСТИ — якорная половина канон-проверок.** `terminology.go:873` и `:941`: обе проверки пропускают пару с РАВНЫМИ источниками; проверочная половина закрыта паком 06.09, якорная — нет. ⚠ Лечение МЕНЯЕТ ЗАПРОС к модели ⇒ деньги и снапшот, поэтому отдельным решением, а не прицепом | бэкенд | скоро | показать роли существующую форму + цена в снапшоте | §5а №2 + предложение №2 зоны |
| 340 | ⛔ **СУЖЕНИЕ ВХОДА ДЕЙСТВУЕТ ТОЛЬКО НА СИНХРОННОЙ ВЕТВИ: при деплойном классе книга одним полотном попадает в библиотеку МОЛЧА.** Отказ по числу глав (`D39.221`) стоит на пути, где движок ответил; когда он недоступен, книга уходит в очередь прежним путём и сужение её не видит. ⛔ Закрыть нечем: словарь `RejectReason` закрыт четырьмя значениями, а ближайшее по смыслу `source_unreadable` ТЕРМИНАЛЬНО и УДАЛЯЕТ исходник — то есть уничтожило бы файл пользователя из-за НАШЕГО ограничения. ⇒ развилка владельцу: пятая причина отказа минором канона ЛИБО осознанное «асинхронная ветвь остаётся проницаемой до готовности структуры глав». Рекомендация оркестратора — второе: беты нет, впуск ручной, а лишнее значение в закрытом словаре переживёт надобность | владелец | скоро | слово владельца + минор канона или записанный риск | `PD-463`, вопросы платформы 07.09 |
| 341 | **ПРЕДЛОЖЕНИЕ ДВИЖКА ПРОВЕСТИ `--ceiling-usd` В `status` ВИСИТ БЕЗ ДИСПОЗИЦИИ С 09.08** (пинг №15). `backend/internal/pipeline/status.go` отвечает «a read path never carries a run-scoped override» — то есть у движка есть позиция, а решения нет ни за, ни против. ⇒ принять или отклонить, но не оставлять третий месяц | бэкенд | когда-нибудь | диспозиция оркестратора одной строкой | вопросы платформы 07.09 |
| 342 | **ВОССТАНОВЛЕНИЕ ИЗ БЭКАПА НЕ ПРЕДЪЯВЛЕНО НА МАСШТАБЕ.** Предъявлено на малых данных; не проверено на книге в сотни мегабайт, при заполненном диске и при чужих открытых соединениях. `PD-462` покрывает СОСЕДНИЙ класс, этот — нет. ⚠ Бэкап, не проверенный на условиях, в которых он понадобится, — это не бэкап, а намерение | платформа | скоро | восстановление предъявлено на большой книге, полном диске и чужих соединениях | вопросы платформы 07.09 |
| 343 | **`counts.py` ДЕРЖИТ РЕГИСТР ОДНИМ ПУТ�ём И НЕ ГЛОБИТ СЛАЙСЫ — предусловие нарезки `DEFECT_REGISTER.md`.** Вынос без этого молча уронит счёт открытых рядов, а гейт чисел покажет зелень: он читает ровно один файл. ⚠ План нарезки живёт в `docs/DOC_CLEANUP_PLAN.md` (Б14в) | доки | скоро | прибор читает регистр и его слайсы, счёт не меняется при выносе | вопросы платформы 07.09 |
| **— ТЕХДОЛГ БЭКЕНДА: разбор research/33 (D39.224) —** | | | | | |
| 346 | ⚠ **ПОЛОВИНА (а) ЗАКРЫТА 07.09 (`D39.225`): пин расхождения и паритет-тест стоят, оба под мутациями. ОСТАЁТСЯ (б) — фикс в окне перенарезки.** ⛔ **ПРАВИЛО ЗАГОЛОВКА РАЗЪЕХАЛОСЬ ПО ТРЁМ ПРЕДИКАТАМ, И «第零章» ЛОМАЕТ ПРОЛОГ — две половины с РАЗНОЙ ценой.** Страж длины живёт только в ингесте (`chunk/ingest.go:307` `chapterHeaderMaxRunes = 60`, применён `:323`; в `chunker.go` `RuneCountInString` — 0 хитов), осмысленность номера — только в чанкере (`chunk/chunker.go:316` `if !any || v <= 0`). Воспроизведено исполнением 07.09 (выброшенная проба на копии дерева): `第零章:序幕` ингест режет главой, а чанкер заголовок НЕ снимает — `heading=""`, сырой CJK-маркер уезжает модели; `parseSectionNumeral` на `零`/`0`/`〇` даёт `0,false` (контроль: `一`=1, `十二`=12); номера расходятся (`第一章` = `Chapter 2` при «Глава 1»); 84-рунный заголовок: ингест `false`, чанкер `ok=true`. ⚠ **Испр. 07.09 — без этой оговорки строка читается как ЛОЖНАЯ:** расхождение живёт ТОЛЬКО у заголовка С СЕПАРАТОРОМ после юнита (`第四章:…`); без сепаратора оба предиката дают `false` на любой длине, потому что такую строку отвергают и `isHeaderSeparator` ингеста, и `matchHeaderLine` чанкера. Пере-снято оркестратором на копии `d6dfc49`: с сепаратором 59 и 60 рун — оба `true`; 61 и 84 — ингест `false` при чанкере `ok=true n=4`; без сепаратора 12/55/59/60/61/84 — `false`/`false` во всех шести. Граница ровно `chapterHeaderMaxRunes` = 60. Перекрёстного теста нет ни в одном из 97 тестов `internal/chunk`. **(а) $0 СЕЙЧАС — пин ИЗВЕСТНОГО расхождения, а не паритет:** красный тест в `main` не ложится (`Makefile:58` `battery: build vet fmt lint test`), скип — класс D39.208; поэтому тест утверждает, что на `第零章` и на 61–84-рунной строке ингест и чанкер СЕГОДНЯ расходятся, назван этой строкой и краснеет ровно тогда, когда приземлится фикс (б), заставляя фиксера его перевернуть. Дизайн-пак 161 §4.5 паритет-тест ОПИСЫВАЕТ, пишет его пак стройки — пин (а) этому не мешает. **(б) В ОКНО ПЕРЕНАРЕЗКИ:** сам фикс меняет ТЕКСТ чанка ⇒ бампает `chunkerVersion` ⇒ снапшот обеих волн (`render.go:55-58` — «a deliberate re-translation»); отдельным актом он платит ту самую перепокупку, которую отменяет. ⚠ Ось «обязательность юнита» — НЕ трогать: носитель строка **303** (⚠ испр. 07.09: research/33 приписывал её `D39.207`, в теле ноты этого нет — греп по предмету 0 при 23 строках тела) | бэкенд | скоро для (а); (б) — в окне перекроя (шаг 3) | (а) пин расхождения · (б) сведение двух предикатов к ингестовским стражам внутри пака перекроя | research/33 Д3, research/27 §6 |
| 347 | **ПАР-ДАННЫЕ НЕЛЬЗЯ ЗАВЕЗТИ ПО ЧАСТЯМ: манифест требует ≥1 канал, и транслитерационный канал зашит в китайскую форму.** `lang/langpack.go:632` — «manifest declares no channel — omit the file to ship all channels, or list at least one»; каналов два и они закрыты в Go (`source-morphology`, `transliteration`, `:108-114`), а `validate()` при `transliteration` требует ПОИМЁННО пиньинь-категории (`:521-527`); морфологический канал просит общие таблицы (`:507-516`) и в китайскую форму не зашит. Отказ жёсткий: при `gates.terminology.enabled` и `pack == nil` прогон отказывает `RefusalBadConfig` (`pipeline/runner.go:349`), а в боевом `pipeline-c1.yaml:151` гейт включён ⇒ вторая пара выбирает между фиктивными данными китайской формы и прогоном БЕЗ банка терминов (продуктовая цель №1). ⚠ **Триггер — первая новая ИСХОДНАЯ пара, и он РАНЬШЕ строки 115:** манифест лежит в `//` и хешируется языком-ИСТОЧНИКОМ (`langpack.go:252`), а 115 — про новую ЦЕЛЬ; ближайшая исходная пара в трекере — ja→ru (строка **81**), цель у неё ru. ⚠ **Пять строк снимают отказ, но банка на не-Han источнике НЕ дают** — детектора нет (строка **35**: en-детектор не существует, ja с zh-таблицами активно неверен); заказывать вместе, иначе строка обещает больше, чем покупает. Сегодня не оплачено ни разу: 0 `manifest.txt` в `configs/`, каталог пары один. ⚠ D39.64 П4 ратифицировала ОБРАТНОЕ намерение («источник без пиньинь-морфологии грузится без Palladius-файлов») — строка `list at least one` не дошла шаг до собственной цели | бэкенд | когда-нибудь (вход пака второй пары; триггер общий со строками 81 и 35) | разрешение нулевого числа каналов + решение по форме каналов | research/33 Д7, D39.64 П4 |
| 350 | ⚠ **ИСПОЛНЕНО 07.09 (`D39.225`) КРОМЕ ОДНОГО: по каждой из шести функций назван исход — четыре получили причину жизни комментарием («NO CALLER TODAY: contract surface waiting on backlog row 12»), дубль инлайна свёрнут в `finalStageName()`. ОСТАЁТСЯ словарь родов в четырёх носителях; текст его собственной ошибки врать перестал.** **РЕФАКТОРИНГ ОБЛЕГЧЕНИЯ ВЕДЕНИЯ (санкция владельца 07.09) — снапшот-нейтрально, и заказ здесь «решить», а не «удалить».** Вызовов вне определения ноль у шести функций (греп 07.09; КОНТРОЛЬ — `SplitChunks` 34 живых вызова): `obs.SafeGo`, `text.TokenizeCyrillic`, `CheapGateResult.UnitScaleHard`/`UnitScaleSoft`, `Bank.Voices()`, `Bank.Pairs()`. ⚠ **Четыре из шести стоят НАМЕРЕННО, и слепое удаление снимет намеренное:** `UnitScaleHard/Soft` сами называют, кого ждут — `checks/cheapgates.go:155-156` «for the report and a future hard gate», то есть строку **12**; `TokenizeCyrillic` — образец паттерна value-default, на который ссылаются `checks/sanitizer.go:21` и `:197`; `SafeGo` — намеренный контраст к `obs/panic.go`, названный решением `pipeline/waverun.go:405` («NOT obs.SafeGo»), и его удаление повесит два комментария в воздухе — класс строки **299**; `Voices`/`Pairs` (`membank/memory.go:371-376` «frozen for the job») ждут потребителя, которого держит строка **13б**. ⇒ по каждой ОДИН исход с объявлением в отчёте: удалить ЛИБО назвать причину жизни в комментарии. Плюс ИМЯ последней стадии дважды одинаковым инлайном — `r.Pipeline.Stages[n-1].Name` в `pipeline/export.go:283` и `quality.go:342` (адреса на `d6dfc49`). ⚠ **Испр. 07.09: и research/33 §7.1, и первая редакция этой строки называли здесь «готовый `finalStageWave()`» — это ДРУГАЯ функция**: она возвращает ВОЛНУ (`snapshot.go:247`, вызовов 13 — 10 прод и 3 теста), а хелпера для ИМЕНИ не существовало вовсе, и «при готовом хелпере» читалось как «работа уже сделана» и словарь родов в четырёх носителях (`membank/memory.go`, `membank/memseed.go`, `terminology/classify.go:50`, промт), где текст собственной ошибки врёт о принимаемом множестве. ⛔ Границы санкции: НЕ дробить `internal/pipeline` и НЕ переписывать `Runner` (`12-go-style-notes.md` §1, D39.23), ничего, что двигает снапшот / хеш запроса / ключ манифеста. ⚠ Адреса сняты research/33 на `e69902a`, а лендинг 07.09 тронул `memseed.go` и `export.go` — пере-снимать командой, не по тексту | бэкенд | когда-нибудь | попутный проход с батареей + объявление исхода по каждой функции | research/33 §7.1, санкция владельца 07.09 |
| 351 | **ЛИНТ СЛОВАРЯ КЛАССИФИКАТОРА ПИНИТ ОДНО НАПРАВЛЕНИЕ: слово, УБРАННОЕ из Go, не ловит ничто.** Гейт `TestEveryClassifierPromptSpeaksTheEnginesVocabulary` (лендинг `D39.225`) утверждает «каждое слово из `terminology.Types`/`Genders` названо в промте пары» — и потому сжимается вместе со своим предметом: выкинутый класс `title` оставляет батарею зелёной (замер 07.09 на копии: 19 ok / 0 FAIL). Вырожденный предел закрыт стражем `len(classifierVocabulary()) == 0`, общий случай — нет. Настоящий дом — пин САМОГО словаря, которого в репозитории нет (research/33 Д1: 0 тестов на `terminology.Types`). ⚠ Граница названа зоной самостоятельно, в заказ пака не входила | бэкенд | когда-нибудь | пин словаря (голден или рефлексивный тест) | `D39.225`, research/33 Д1 |
| 352 | **ПЯТЬ РУКОПИСНЫХ СПИСКОВ АРМ-КОНФИГОВ ЖИВУТ РЯДОМ С ДВУМЯ ГЕЙТАМИ, КОТОРЫЕ ТЕПЕРЬ ГЛОБЯТ.** `pipeline/promptlabel_test.go:45` · `config/echoregen_shipping_test.go:35` · `config/content_labels_test.go:529` и `:575` · `config/prompt_pack_test.go:239` перечисляют армы поимённо; новый арм автоматически попадает в `TestAnArmIsTheProductionConfigWithADifferentEditor` и `TestSwapArmConfigs` и проходит мимо всех пяти. Найдено приёмкой `D39.225`, вне заказа пака; предсуществующее | бэкенд | когда-нибудь (со следующим касанием армов) | свести пять списков к глобу | `D39.225` |
| 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 |
| 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 |
| 364 | **ПОТОЛОК РАЗРЕЗОВ НЕ ЕСТЬ ПОТОЛОК ПРОЦЕССОВ ДВИЖКА НА ХОСТЕ — граница названа зоной, но не измерена.** Пак разреза приёма закрыл путь, у которого потолка не было ВООБЩЕ (синхронный вход: N загрузок = N процессов), и `books/limit.go` честно называет, чего он НЕ ограничивает: материализатор (`readmodel.refresh`) и рекoнсайлер (`status`) порождают процессы через тот же неограниченный `runner.readEngine`. Их держат другие границы — число воркеров очереди и последовательность свипов, — и они ЛОЖЕ. ⇒ худший случай по числу одновременных процессов движка на хосте сегодня НЕ равен `DefaultMaxCuts` и никем не посчитан. ⚠ Это не дефект поведения и не заявка на второй семафор: зона права, что ряд в РЕГИСТРЕ дефектов был бы засорением. Строка нужна затем, чтобы названная граница не прочиталась как закрытый вопрос — ровно класс `D39.202`. ⛔ И довод к тому, что вопрос не косметический: разрез идёт голым `exec.CommandContext` без cgroup и `MemoryMax`, в отличие от прогонов, которые обёрнуты в `systemd-run` | платформа | когда-нибудь | худший случай посчитан ИЛИ все пути порождения заведены под одну границу | вопрос зоны при сдаче пака разреза приёма 08.09 |
| 365 | ⛔ **ПОТОЛОК `TM_PLATFORM_UPLOAD_DEADLINE` ТИХО ОПУСТИЛСЯ, И ДЕПЛОЙ, КОТОРЫЙ ВЧЕРА СТАРТОВАЛ, СЕГОДНЯ ОТКАЖЕТ НА БУТЕ.** Пак разреза приёма поднял `UploadSettle` 210 → 220 с и добавил `ClaimGrace` третьим окном в бутовую сверку (`internal/config/config.go`, `min(sweepGrace, parseClaimGrace, idempotencyClaim)`), из-за чего самое узкое окно стало 20 мин вместо 30 ⇒ допустимый дедлайн загрузки упал с ~26 м 30 с до ~16 м 20 с. ⚠ `deploy/README.md` правило называет, но НЕ называет ни числа, ни того, что граница ПЕРЕЕХАЛА: оператор с легальным вчера `TM_PLATFORM_UPLOAD_DEADLINE=20m` получит отказ старта без апгрейд-ноты. ⇒ либо нота в рантбуке с числом и причиной, либо сообщение бута, называющее, ЧТО именно сузилось | платформа | скоро (до следующего выката) | оператор узнаёт о сужении из рантбука или из текста отказа, а не из отказа старта | охотник вне карты, приёмка пака разреза приёма 08.09 |
| 366 | **ОЖИДАНИЕ СЛОТА ЗАНИМАЕТ ВОРКЕР ОЧЕРЕДИ, А ТЕЛЕМЕТРИЯ ПОТОЛКА ПУБЛИКУЕТСЯ ЗА ПАССОМ, КОТОРЫЙ НА ЭТОТ ПОТОЛОК И БЛОКИРУЕТСЯ.** Две половины одного: **(а)** все три вида заданий (`SpawnArgs`, `ParseArgs`, `ExportArgs`) делят ОДИН пул `river.QueueDefault` размером `DefaultWorkers`, а `DefaultMaxCuts = jobs.DefaultWorkers` — числа совпадают ПО ПОСТРОЕНИЮ ⇒ четыре HTTP-загрузки, занявшие слоты, ставят четыре `tm_parse_book` в блокировку внутри `Work()`, и очередь целиком — спавн платных прогонов, сборка экспортов — стоит за ними до `deadline − reserve` = **13,5 мин**. Механизм `giveBack`/`RetryDelay 30s`, который пак и построил, при этом почти недостижим: джоба доходит до снуза, просидев эти минуты. **(б)** `CutCapacity()` → `ObserveCuts` вызывается в `one()` ПОСЛЕ пасса интейка, а тот сам может ждать слот до 13,5 мин ⇒ гейджи `cuts_in_flight`/`cuts_waiting` замирают ровно в тот момент, ради которого заведены. Комментарий `observe` закрывает случай мёртвой БД и не видит случая насыщенного потолка. ⚠ Ни граница ожидания, ни занятость общего пула не названы ни в отчёте зоны, ни в акте `D39.229` — там названа ДРУГАЯ граница (строка 364) | платформа | скоро | ожидание не занимает воркер очереди ЛИБО граница названа числом в рантбуке; телеметрия потолка публикуется независимо от блокирующего пасса | охотник вне карты, приёмка пака разреза приёма 08.09 |
| 367 | **ГАРАНТИЯ РЕЗЕРВА У ПОТОЛКА РАЗРЕЗОВ СУЩЕСТВУЕТ ТОЛЬКО ПОД КОНКУРЕНЦИЕЙ, А ТРИ КОММЕНТАРИЯ УТВЕРЖДАЮТ ОБРАТНОЕ.** `platform/internal/books/limit.go`, `takeCutSlot`: удачный `sem.TryAcquire(1)` возвращает слот СРАЗУ, не спросив `worthStarting` — то есть на свободном хосте слот выдаётся при любом остатке бюджета, хоть при миллисекундах. Проверка стоит только на пути ожидания. ⛔ Три места говорят иначе: «`reserve` is what a WON slot must still be worth» (`limit.go`), «a cut is not started … unless what remains is what this platform calls a cut's worth of time» (`parse.go`), «Below zero there is no cut to run, and it is not ATTEMPTED» (`books.go`). ⚠ Сегодня не кусает — у интейка `reserve = 0`, у очереди `JobTimeout` 15 мин, свип гарантирует запас, — но защита отсутствует ровно на пути, который проходится почти всегда, и **любой пин на неё зелёный навсегда**: он попадает только в ветку ожидания. Это тот самый класс вырожденного пина, против которого построена вся смена. ⇒ лечение скорее всего однострочное (спросить `worthStarting` ДО `TryAcquire`), но форма и цена — зоне. ⚠ Не взято дофиксом сознательно: правило остановки по этому паку объявлено ДО находки, и нарушать его задним числом значит обесценить сам механизм остановки | платформа | скоро | гарантия резерва действует на ОБОИХ путях ЛИБО три комментария приведены к правде; пин достигает быстрого пути | охотник вне карты, приёмка пака разреза приёма 08.09 |
| 368 | **ОПЕРАТОРСКИЙ ЭКРАН ЗАНИЖАЕТ ОЦЕНОЧНЫЕ ТОКЕНЫ В 5 РАЗ.** `est_tokens` в `request_log` считается `r.estOutTokens(ch.Text)` по фертильности видимого перевода, а у DeepSeek размышление сидит ВНУТРИ `completion_tokens` ⇒ на строках `decode_error` стоит 2887/2854/3162, тогда как соседние попытки тех же чанков реально дали **16 000** (`finish=length`). Занижение **5.0–5.6×**. Читатель — `cmd/tmctl/render.go` («estimated-cost rows: N … ~M est. output tok»): оператор видит впятеро меньше правды. ⚠ В `cost_usd` это число НЕ входит — деньги считаются грантом, — то есть врёт легенда, а не счёт; но врёт она ровно тому, кто по ней решает, продолжать ли платить. Класс «прибор отвечает на свой вопрос» (`D39.202`). Находка консилиума с чистым Fable 5, 08.09 | бэкенд | скоро | легенда считает то же, что считает счёт, либо честно говорит, чего не знает | консилиум по строке 360, 08.09 |
| 370 | **Anthropic-адаптер не несёт капа ретраев, который есть у общего транспорта.** `backend/internal/llm/provider_anthropic.go` возвращает `BilledDecodeError` с `retryable=true` без ограничителя `billedDecodeSeen`, который стоит в `httpllm.go` — то есть на этом адаптере оплаченный 2xx может повториться до `max_attempts`, а не один раз. ⚠ **Боевой цены сегодня НОЛЬ:** поверхность deprecated, Anthropic убран из стека 04.07, вызовов по этому пути в прогонах нет. ⇒ сознательно вынесено ИЗ пака «вызов, который оборвали мы» (строка 360) по доводу ревью: пак получил бы тесты и мутации на мёртвую поверхность. Чинить при воскрешении адаптера — тогда же и проверять, применим ли к нему признак доставки | бэкенд | когда-нибудь | адаптер получает тот же кап ЛИБО удалён вместе с поверхностью | ревью пака «вызов, который оборвали мы», 08.09 |
| 372 | **СТРАЖ ОТМЕНЫ ГЛОТАЕТ НАСТОЯЩУЮ ДЕНЕЖНУЮ ОСТАНОВКУ, когда прогон отменил не человек, а упавший сосед.** Платформа получит `failed` вместо `paused`, а книга без денег упрётся в потолок на ПЕРВОЙ резервации следующего прогона. Сессия стража оставила и была права: ратифицированный комментарий ветки `waitAborted` требует ровно этого для ОБОИХ случаев. ⇒ предмет не движковый, а **продуктовое решение о шве**: должна ли платформа отличать «остановлено человеком» от «остановлено падением соседа» ⛔ **ЗАМЕР 10.09 (движковая сессия, ЧТЕНИЕМ; пере-снят оркестратором): в дереве ЖИВЁТ УТВЕРЖДЕНИЕ, которое дерево же опровергает.** Источников отменённого контекста **ДВА**, и по `ctx.Err()` они неотличимы: человеческий сигнал (`backend/cmd/tmctl/main.go`, греп `signal.NotifyContext`) и **собственная отмена волны** — `runWave` заводит производный контекст (`backend/internal/pipeline/waverun.go`, греп `context.WithCancel(parent)`) и отменяет его из ветвей инфра-ошибки соседа и паники. При этом ДВА не-тестовых комментария прямо декларируют, что источник один: `backend/internal/pipeline/bankdecisions.go`, греп `by nothing else`, и `backend/cmd/tmctl/main.go`, греп `a cancelled run is one somebody asked to stop`. ⇒ ни `exitCode`, ни `terminal()` двух причин не различают, а комментарии учат следующего, что различать нечего. ⚠ Полный инвентарь носителей отмены (4 источника, около двадцати читателей, с адресами по HEAD) — в секции движковой зоны `docs/PROGRESS.md`; он вход любого пака про корректность остановки | бэкенд | скоро | шов различает две отмены ЛИБО объявлено, что не различает, с ценой | сдача пака «вызов, который оборвали мы» 08.09 |
| 373 | **НА HTTP/2 НАШ ДЕДЛАЙН ИНЕРТЕН, если тело запроса больше окна пира, а провайдер отвечает ранним 2xx, не дочитав его.** Замер движковой сессии: вызов длится столько, сколько держит сервер — **4 с и 8 с при дедлайне 700 мс**, — и всё уезжает в `decode_error`, ту самую дверь, которую пак 360 объявил закрытой. Механизм: запись паркуется в `awaitFlowControl` на `sync.Cond`, которую контекст НЕ будит. ⚠ Дыра ПРЕДШЕСТВУЕТ паку и требует пирa, отвечающего не дочитав тело (НЕ форма DeepSeek). Лечится `http2.Transport.WriteByteTimeout`, но его значение — НОВЫЙ порог, а пороги назначать нельзя | бэкенд | когда-нибудь | дедлайн действует и на записи тела ЛИБО класс объявлен недостижимым с замером | сдача пака «вызов, который оборвали мы» 08.09 |
| 375 | **ВЫГРУЗКА ЧИТАЕТ ОТМЕНЁННУЮ ПОЗИЦИЮ КАК ВЫПАВШИЙ КУСОК ТЕКСТА.** `memberDrops` считает строку `cancelled` выпавшим членом редакторской единицы — то есть выносит КОНТЕНТ-вердикт по факту нажатия кнопки: читателю сообщается, что из единицы пропал текст, тогда как пропала лишь незаконченная работа. Семантика экспорта, не транспорт. ⚠ Исчезает само вместе с классом `cancelled`, если денежная половина строки **360** будет урезана. Найдено критиком полноты седьмого круга; диспозиция оркестратора жила письмом и носителя не имела до `D39.231` ⚠ **ДОБАВКА 10.09 (замер движковой зоны по запросу оркестратора, подтверждён ключом БД).** Правка «применить `resolvedForResume` внутри `memberDrops`» ПОЛНА для этого пути (живой вызов один — `backend/internal/pipeline/export.go:307`) и попутно чинит артефакт порядка: внутренний цикл `status.go:538-543` оставляет ПОСЛЕДНЮЮ флагнутую черновую строку, а строки приходят `ORDER BY … stage`, поэтому при двух черновых стадиях `cancelled` может перебить контентную причину; фильтр возвращает контентную. Случай «сверху лёг `cancelled`» НЕВОЗМОЖЕН: строка апсертится по `(book_id, chapter, chunk_idx, stage)` (`backend/internal/store/chunkstatus.go:92`), а контентно флагнутая стадия не пере-выполняется (резюм-гейт `backend/internal/pipeline/stagerun.go:93`). ⛔ **НО правка меняет ЛОЖЬ на МОЛЧАНИЕ, и это не закрытие:** если единственный флаг члена — `cancelled`, после фильтра `DroppedMembers` = 0 и `DroppedReason` пуст (`export.go:320-322`), единица уходит `ok`, молча не досчитавшись текста члена. ⇒ закрывать надо ТРЕТЬИМ состоянием («единица неполна из-за остановки»), а не одним фильтром. Окно узкое: нужна комбинация «финальная строка от прежнего прогона + редрайв члена + стоп» (`export.go:174`) ⛔ **ВТОРАЯ ПОЛОВИНА, вытащенная 10.09 из отменённого пака, чтобы не умереть вместе с ним (ПОДОЗРЕНИЕ — выведено ЧТЕНИЕМ кода движковой сессией, фикстурой НЕ гонялось):** строка `chunk_status` не добавляется, а ЗАМЕЩАЕТСЯ — апсерт по ключу стадии с `DO UPDATE SET … final_hash = excluded.final_hash` (`backend/internal/store/chunkstatus.go`, греп `on conflict`), а запись отмены кладёт ПУСТОЙ `final_hash`. ⇒ прогон, который ПЕРЕ-атакует позицию с уже готовой строкой (редрайв · пере-пин с `--resnapshot` · правка исходника) и будет оборван, оставляет позицию с пустым хешем — выгрузка теряет текст, чекпойнт которого лежит на диске. То есть отмена способна стереть НАСТОЯЩИЙ вердикт, а не только пометить незаконченное. Проверяется фикстурой «готовая строка → редрайв → обрыв» ⚠ **ИСПР. 11.09 — ОДИН ИЗ ТРЁХ МАРШРУТОВ ОПРОВЕРГНУТ ЧТЕНИЕМ, и опровергла его АВТОР прежней формулировки:** через РЕДРАЙВ сценарий НЕДОСТИЖИМ. `ResetChunkStages` (`backend/internal/store/chunkstatus.go`, греп `func (s *Store) ResetChunkStages`) в ОДНОЙ транзакции удаляет и `checkpoints`, и `chunk_status` сбрасываемых стадий — пере-снято мной: две `DELETE` между `BeginTx` и `Commit`; то же говорит доккоммент `backend/internal/pipeline/volume.go` (греп `DELETES the unit`). ⇒ к моменту пере-атаки замещать нечего, прежнего вердикта уже нет. **Остаются ДВА маршрута**, оба обходят быстрый путь резюма при ЖИВОЙ прежней строке: пере-пин `--resnapshot` (снапшот уехал, признак пере-пинуемости ложен) и правка исходника или промта (не сходится хеш содержимого). Их и предъявляет фикстура; исход «недостижимо» — такой же результат | бэкенд | скоро | единица, неполная ИЗ-ЗА ОСТАНОВКИ, отличима и от выпавшего контента, и от полной: ни ложного контент-вердикта, ни молчания | седьмой круг ревью пака 360, 08.09; добавка — замер зоны 10.09 |
| 376 | **ДОСТАВЛЕННЫЙ ОБРЫВ ДО ЗАГОЛОВКОВ КНИЖИТСЯ НУЛЁМ — и мы НЕ ЗНАЕМ, у скольких провайдеров это срабатывает.** Деньги за оборванный нами вызов считаются по `answered && afterHeaders` (`backend/internal/llm/attemptcut.go`), то есть единственный оплачиваемый обрыв — пришедший через ошибку ЧТЕНИЯ ТЕЛА. Обрыв до первого байта ответа (наш дедлайн, стоп родителя, разрыв сокета) даёт **$0** и не виден даже в оценочной паре (`paidtail.go` пропускает `CostUSD <= 0`). ⚠ **Сужение СОЗНАТЕЛЬНОЕ и ратифицировано** (`D39.230`, разведение предикатов): довод замером — 3 из 25 отменённых в полёте сеттлили оценку за запрос, которого не видел ни один хендлер, то есть переплата ЧИТАТЕЛЯ, запрещённая `D39.196` п.2а. ⛔ **Открыт РАЗМЕР остатка, и он неизвестен по построению:** провайдеров **8** (замер по `configs/models.yaml`), ранний `200` задокументирован ровно у ОДНОГО (DeepSeek), а про поведение заголовков у остальных СЕМИ в репозитории не сказано НИЧЕГО — греп класса по странице квирков даёт 0 при 250 строках файла. ⇒ верное утверждение не «сломано у семи», а **«неизвестно для семи»**: если заголовки у них приходят рано, путь почти не срабатывает; если поздно — головной класс пака у них не закрыт вовсе. ⚠ Замерить без платных вызовов нельзя, и постфактум из телеметрии тоже: движок не пишет время до первого байта успешных вызовов. ⇒ первый шаг дешёвый и $0 — начать писать это время | бэкенд | скоро | время до первого байта пишется; размер остатка назван числом, а не «неизвестно» | приёмка пака «вызов, который оборвали мы» 10.09 |
| 377 | **ОПЛАЧЕННЫЙ ОБРЫВ, ЗА КОТОРЫМ РЕТРАЙ УСПЕЛ, ИСЧЕЗАЕТ БЕССЛЕДНО: $0 и ни одного следа.** `backend/internal/llm/httpllm.go` — на успешном ретрае `if err == nil { return resp, nil }`, и накопленный `owedCut` ВЫБРАСЫВАЕТСЯ. Замер приёмки: сервер спрошен ДВАЖДЫ (первый вызов доставлен, подтверждён и оборван), вызывающий получает чистый успех и о первом не узнаёт ничего — ни строки леджера, ни оценки, ни пометки. ⚠ Это ровно предмет пака (платим дважды за одну генерацию), но пак его НЕ заказывал: §4.2 требовал деньги «на исчерпании», а здесь исчерпания нет — ретрай удался. Ни одна из девяти фикстур этого пути не покрывает: `TestABrokenConnectionAfterDeliveryIsRetriedOnceAndOnlyOnce` роняет ОБЕ попытки | бэкенд | скоро | оплаченный обрыв виден в леджере независимо от исхода ретрая | приёмка пака «вызов, который оборвали мы» 10.09 |
| 378 | **ПИН «НЕ-2XX — НЕ ПОКУПКА» ЛОВИТ МУТАНТА НЕ ТЕМ АССЕРТОМ: денежные проверки в нём не исполняются ни разу.** Каталожная мутация `CUTCALL-a-non-2xx-becomes-a-purchase` (батарейная, цель — `backend/internal/llm/httpllm.go`, ветвь статуса `if resp.StatusCode < 200 || resp.StatusCode >= 300` → `if false`). Пере-снято ОРКЕСТРАТОРОМ 10.09 на копии: тест краснеет, но ТЕКСТОМ `cutcall_test.go:584: a provider failing every attempt must surface as an infra failure` — ассертом об исходе ПРОГОНА. `t.Fatal` останавливает тест ДО трёх проверок, ради которых пин написан (`committed`, `reserved`, `checkpoints`), и они не исполняются. Под мутацией движок сеттлит **$0.001056 как ОЦЕНКУ за 500-ку** — ровно ту утечку, которую доккоммент теста называет, — и текст падения об этом молчит. ⚠ Класс ратифицирован (`D39.217` п.2в, `D39.232` п.6в) — здесь открыт НОСИТЕЛЬ | бэкенд | скоро | мутант краснеет ассертом О ДЕНЬГАХ: посылка «прогон упал» проверяется так, чтобы не глотать денежные проверки | приёмка пака «вызов, который оборвали мы» 10.09 (С8) + пере-замер оркестратора |
| 379 | **ДВА ПИНА ПАКА НЕ УТВЕРЖДАЮТ СВОЕЙ ПОСЫЛКИ — названный сценарий может не состояться, и они этого не скажут.** **(а)** `backend/internal/pipeline/cutcall_test.go:402` — две строки таблицы девяти («after 2xx · cancelled by the operator» и «before headers · cancelled by the operator») разводятся ОКНОМ СТЕННЫХ ЧАСОВ: `<-srv.arrived` + `time.Sleep(50 * time.Millisecond)` против `attempt_s: 1`. По какую сторону границы заголовков сел `cancel()`, не утверждается ничем. Замер приёмки на мутанте: **2 красных из 8** — отмена обгоняла разбор заголовков, и строка сходилась «ноль к нулю» (`D39.232` п.6а). **(б)** `backend/internal/llm/attemptcut_test.go` — `TestARefusalIsNotAPurchaseEvenWhenTheReplyOutrunsTheWrite` утверждает только `err != nil` и `!errors.As(err, &cut)`; что ответ ДЕЙСТВИТЕЛЬНО обогнал запись (шестимегабайтное тело не дописалось, `WroteRequest` не сработал), не проверяет ничто — тест зелен и на сценарии, где запись успела, то есть на другом предмете | бэкенд | скоро | каждый из двух пинов ПЕЧАТАЕТ величину, доказывающую пройденную границу, и падает, когда сценарий не состоялся | приёмка пака «вызов, который оборвали мы» 10.09 (С5, С6) |
| 380 | **У ДЕНЕЖНОГО УТВЕРЖДЕНИЯ «ПЕРЕ-ДЕЛКА НЕ УДВАИВАЕТ БЮДЖЕТ» ОДИН НОСИТЕЛЬ, А НЕ ПЯТЬ.** Колонка `wantSameBudget` стоит в четырёх строках таблицы девяти (`backend/internal/pipeline/cutcall_test.go:333,340,355,361`), но осей не разводит: обжог случается ВНУТРИ `runAttempt`, а `maxTokens` считается в `runStage` ДО вызова, на итерации `attempt == 0`, где номер попытки и число удвоений равны по причине, к предмету отношения не имеющей. Пере-снято ОРКЕСТРАТОРОМ 10.09 на копии под каталожной мутацией `CUTCALL-the-redo-doubles-the-budget` (`maxTokensForAttempt(baseMaxTokens, escalations)` → `..., attempt`): таблица девяти — **0 красных из 8** (контроль: прибор запустил 10 подтестов, то есть спрашивал существующее), весь пакет `internal/pipeline` — ровно **ОДИН** красный тест, `TestABurnFollowedByARegenerationDoesNotOverBuy` (`cutcall_test.go:1435`). ⚠ Сам носитель ПОЧИНЕН паком (посылку теперь утверждает: «run 1 must leave exactly ONE checkpoint», «…is three checkpoints»), поэтому дыры сегодня нет — есть ЕДИНСТВЕННОСТЬ | бэкенд | когда-нибудь | утверждение держат ≥2 независимых носителя ЛИБО колонка `wantSameBudget` снята как ничего не меряющая, и это записано | приёмка пака «вызов, который оборвали мы» 10.09 (С3) + пере-замер оркестратора |
| 381 | ⛔ **СНЯТА 10.09 ВМЕСТЕ С ОТМЕНОЙ ПАКА «ДВЕ ОСТАНОВКИ» (`D39.240`) — предмет строки был «у человека одна кнопка и она жёсткая», а владелец решил, что жёсткой и достаточно.** Тело не воспроизводится: замеры, ради которых строка стояла, ратифицированы нотами и живут там — блокирующий `systemctl stop` без `--no-block` и инертность повторного стопа на `deactivating` (`D39.237`), коалесценция двух сигналов в один (`D39.238`), диагноз «у вопроса о трате нет единственного хозяина» (строка **385**). ⚠ **Единственная часть прежнего тела, которая пережила отмену и живёт своей жизнью, — строка 391**: из зависшего сворачивания нет выхода, кроме убийства, и оно не оставляет терминального кадра. Строка сохранена надгробием, а не удалена, потому что на неё ссылаются `D39.233`–`D39.240` | бэкенд | когда-нибудь | ссылки на 381 ведут к нотам, а не в пустоту | `D39.240` |
| 382 | ⛔ **ПОМЕТКА «ЭТО ОЦЕНКА» — УСЛОВИЕ СЛОВА ВЛАДЕЛЬЦА (`D39.230` п.1) — ПО ШВУ НЕ ЕДЕТ И ПОТРЕБИТЕЛЯ НЕ ИМЕЕТ.** Владелец разрешил списывать с читателя по ОЦЕНКЕ при условии, что пометка стоит. В движке она есть: `backend/internal/pipeline/status.go:321` — `estimated_rows` / `estimated_usd` в `status --json`. Дальше она обрывается. Замер 10.09 с контролем: в кадрах событий шва (`backend/internal/runevents/runevents.go`) слова `estimated` **0 хитов** (контроль: `committed` в том же файле — **6**; денежный кадр несёт один `committed_micro_usd`, `runevents.go:244`); в `platform/internal` вне тестов — **2 хита, оба КОММЕНТАРИИ**, причём `pgstore/credits.go:235` прямо просит эту величину: «publish the count and sum of estimated-price rows beside committed_usd, which is what would let this side say "at most Y"» (контроль: `committed_micro` — 1 хит; go-файлов вне тестов прибор прочёл **81**). ⇒ условие исполнено на ОДНОМ канале из двух, и читателя, ради которого пометка ставилась, у неё нет: платформа не может сказать пользователю «не больше Y». ⚠ Пара к строке **381**: и то и другое — признак, который обязан ехать в кадре `finished`/`spend`, а не только в `status --json` | бэкенд | скоро | платформа ЧИТАЕТ счёт и сумму оценочных строк из потока и может назвать пользователю верхнюю границу списания | акт `D39.233` п.7, замер оркестратора 10.09 по разбору чистого Fable 5 |
| 383 | **ПОТОЛОК ОЖИДАНИЯ ЖИВЁТ КОНСТАНТОЙ В ОДНОЙ ЗОНЕ, А ВЫВОДИТСЯ ИЗ КОНФИГА ДРУГОЙ — ФОРМА, КОТОРАЯ ТУХНЕТ МОЛЧА.** Платформенный грейс остановки обязан покрывать законное ожидание движка. Сегодня это число платформа ВЫВОДИТ из движкового каталога и кладёт себе константой (пак «две остановки», `D39.236` п.6): любая правка `backend/configs/models.yaml` — новый провайдер, поднятый `edit_ceiling_out`, изменённый `tok_s_floor` — делает константу ниже правды, и никто об этом не узнает: превышение грейса даёт SIGKILL, а SIGKILL не оставляет ни пометки `cancelled`, ни сеттла оценки. ⛔ **И ловушка уже названа числом, а не гипотезой (замер платформенной сессии 10.09):** `attempt_max_s` инертен у ПЯТИ провайдеров из восьми, и у беcключевых `DeadlineFor` сверху не ограничена вовсе — она растёт с бюджетом линейно. Беcключевой `zai` перерастает сегодняшний максимум 1240 с (deepseek) при бюджете ≥ **43 400** токенов, то есть при `edit_ceiling_out` ≈ **9 900** против сегодняшних **8 000**. ⇒ запас по конфигу — меньше четверти. **Нетухнущая форма, которую надо построить:** движок ПЕЧАТАЕТ свой потолок ожидания сам (он и так умеет считать его `DeadlineFor` — функция экспортирована ровно для вопроса о конфигурации), платформа читает его НА БУТЕ и отказывается стартовать с грейсом ниже. ⚠ В паке «две остановки» этого НЕТ ни в одной половине — там принята сегодняшняя форма (пин на арифметику + строка реестра + комментарий с адресом), и она честно названа тухнущей | бэкенд | скоро | грейс платформы не может молча оказаться ниже законного ожидания движка: число выводится ИЗ ДВИЖКА в рантайме, а расхождение ловится на буте, а не SIGKILL-ом | эхо-протокол платформенной сессии по паку «две остановки», 10.09 (`D39.237` п.5) |
| 384 | **ЛЕНДИНГА НЕТ — А ПРОДУКТ ПО СЛОВУ ВЛАДЕЛЬЦА СОСТОИТ ИЗ ДВУХ ПОВЕРХНОСТЕЙ.** 10.09 владелец назвал модель: «фронт — это скорее IDE для переводов; к нему нужна обёртка в виде ЛЕНДИНГА; модель такая же, как у любого ИИ-продукта — лендинг с продуктом, и IDE отдельно, с аккаунтами, оплатой и всем таким» (`D39.239` п.1). Сегодня в репозитории есть только вторая поверхность, и та наполовину: `frontend/` — две маршрутные точки и витрина компонентов (About · AddBook · Bank), зона ЗАМОРОЖЕНА словом владельца с 15.08 и разморозка — отдельным его словом. Лендинга нет ни кодом, ни требованием в `docs/product-requirements.md`, ни строкой до этой. ⚠ **Практическое следствие, из-за которого строка заведена СЕЙЧАС, а не когда дойдут руки:** когда владелец скажет размораживать фронт, надо будет знать, ЧТО размораживают — витрина относится к IDE, и склейка её с лендингом в один поток была бы ошибкой архитектуры, а не темпа | фронт | когда-нибудь | у продукта названы обе поверхности: что делает лендинг, что IDE, где проходит граница входа и оплаты — и это записано требованием, а не устной моделью | слово владельца 10.09, `D39.239` п.1 |
| 385 | ⛔ **У ДВИЖКА НЕТ ЕДИНОГО МЕСТА, ОТВЕЧАЮЩЕГО НА ВОПРОС «МОЖНО ЛИ ЕЩЁ ПОКУПАТЬ» — их ЧЕТЫРЕ, и каждая новая причина остановки протягивается руками через все.** Замер 10.09 (вопрос владельца «почему остановка задела 18 файлов — нет ли архитектурного косяка»): причин перестать тратить деньги сегодня ТРИ, и каждая живёт своим набором носителей — денежный потолок `CeilingHalt` в **6** файлах (`internal/pipeline/{events,escalation,stagerun,waverun,reservegate}.go` + `cmd/tmctl/main.go`), объёмный грант `VolumeStop` в **4** (`internal/pipeline/{volume,bookrun,waverun}.go` + `cmd/tmctl/main.go`), остановка человеком — в **7**. **Пересечение несущее:** `waverun.go` и `cmd/tmctl/main.go` несут ВСЕ ТРИ, `stagerun.go` и `events.go` — две из трёх. Причина в том, что решение «тратить или нет» принимается в ЧЕТЫРЁХ независимых точках, каждая в своём словаре: фидер волны («выдать индекс?»), денежный гейт («впустить резервацию?»), петля ретраев («начинать попытку N+1?»), попартийный приём банка («брать ещё партию?»). ⚠ **Это НЕДО-абстракция, а не оверхед:** лишнего не построено, не хватает ОДНОЙ сущности — распорядителя допуска к трате, — и за её отсутствие платит каждая новая причина, протягиваясь четырежды. Денежный потолок заплатил ту же цену раньше, чем остановка вообще появилась. ⛔ **Чинить СЕЙЧАС не надо и это часть диспозиции:** введение единого распорядителя трогает ровно те пути, где живут деньги, ради выгоды, которая проявится только на ЧЕТВЁРТОЙ причине; риск больше пользы. Делать, когда эта область откроется по другому поводу или когда причина появится четвёртая | бэкенд | когда-нибудь | у вопроса «можно ли ещё покупать» ОДИН распорядитель, а причины (потолок · грант · остановка · будущие) — его входы, а не независимые протяжки; новая причина стоит одной реализации, а не четырёх | замер оркестратора 10.09 по вопросу владельца об инвазивности пака «две остановки» |
| 386 | ⭐ **НЕСУЩЕЕ СВОЙСТВО, НЕ ЗАПИСАННОЕ НИГДЕ: контекст стора НЕЗАВИСИМ от контекста прогона, поэтому записи ПОСЛЕ отмены доходят.** `backend/internal/store/store.go`, греп `opContext` — каждая операция стора идёт на своём `context.WithTimeout(context.Background(), 10s)`; ни один метод стора к контексту прогона не привязан (`LogRequest` берёт `ctx` только ради trace-id и лога). ⇒ **корректность жёсткой остановки зависит от ПОРЯДКА записей, а не от того, переживут ли они отмену**: пометки, сеттлы и терминальный кадр доезжают. Не дефект — свойство, на которое обязан опереться любой пак про корректное завершение (`D39.240`). ⚠ Заведено строкой именно потому, что не записано: без него следующий пак начнёт с ложной тревоги «а доедут ли записи», потратит круг и придёт к тому же ответу. Найдено движковой сессией ЧТЕНИЕМ | бэкенд | скоро | свойство записано носителем, на который можно сослаться — комментарием в `store.go` или нотой, и порядок записей при остановке проверен ПРОТИВ него | улов движковой сессии перед откатом пака «две остановки», 10.09 (`D39.240` п.6) |
| 387 | ⛔ **ИНВЕРСИЯ БЛОКИРОВОК «ЭМИТТЕР ↔ СТОР» — МИНА, КОТОРАЯ СНАРУЖИ НЕ ПОХОЖА НА ДЕДЛОК.** Замерено ИСПОЛНЕНИЕМ движковой сессией: эмиттер держит свой мьютекс ПОПЕРЁК записей в стор (`project()` → журнал + `MarkAnnounced`; `enqueue` → `EnqueueEvent`), а замыкание строки расхода, отдаваемое в `SettleWithCheckpoint`, исполняется ВНУТРИ единственной пишущей транзакции стора. ⇒ всякий код, берущий мьютекс эмиттера из этого замыкания, замыкает цикл: сеттл держит пишущее соединение и ждёт мьютекс, эмиттер держит мьютекс и ждёт соединение. **Снаружи это не дедлок:** его разрывает 10-секундный таймаут стора, и симптом — `pipeline: ensure job …: context deadline exceeded` в ТРИНАДЦАТИ тестах, к правке отношения не имеющих. Сессия наступила, продиагностировала и вылечила отдельным мьютексом, который не держится поперёк ввода-вывода, — **но лечение откатывается вместе с паком, и мина остаётся заряженной**. ⚠ Правило, которое надо записать в код: не брать мьютекс эмиттера из-под сеттла; всё, что зовут из обработчика сигналов, — тем более | бэкенд | скоро | правило названо в коде рядом с обоими замками, и есть проба, которая ловит цикл раньше, чем он вылезет чужим таймаутом | улов движковой сессии, замер исполнением, 10.09 |
| 388 | **ДЕНЬГИ БАНКОВОГО ПАСА ИСЧЕЗАЮТ ИЗ ИТОГА ПРОГОНА, ЕСЛИ ПАС ОБОРВАЛИ.** `backend/internal/pipeline/mining.go`, греп `tres, err := r.runTerminologist`: на ЛЮБОЙ ошибке, включая отмену, идёт `return false, err` ДО присваивания `r.lastTerminology`; а единственный сумматор (`backend/internal/pipeline/waverun.go`, греп `t.CostUSD + t.ClassifyCostUSD`) прибавляет только когда поле не пусто. Партии при этом КУПЛЕНЫ и чекпойнтнуты. ⇒ прогон, оборванный внутри паса, недосчитывает свой расход ровно на этот пас — на той единственной строке, которую читает оператор. Найдено ЧТЕНИЕМ, обе половины | бэкенд | скоро | итог прогона включает купленное банковым пасом независимо от того, чем пас кончился | улов движковой сессии, 10.09 |
| 389 | **ОСТАНОВЛЕННЫЙ ПРОГОН НЕ ПЕЧАТАЕТ НИЧЕГО О ТОМ, ЧТО ПРОИЗВЁЛ, и ПОЗИЦИЯ ЧИСЛИТСЯ `failed`.** Две половины одной беды — человек после остановки не понимает, в каком состоянии книга. **(а)** `backend/cmd/tmctl/main.go`, `translate()`: частичный результат рендерится только для подписного стопа и потолка; на отмене результата нет вовсе, видна одна строка ошибки. **(б)** `backend/internal/pipeline/stagerun.go`: ветвь прерванного ожидания и охранник после впуска резервации обе пишут `jobs.status = failed` за позицию, которую остановил ЧЕЛОВЕК. Ничто на `jobs.status` не гейтится (файл это и говорит) ⇒ это телеметрия, но слово читает человек. ⚠ Под инвариантом `D39.240` («правильно возобновить») это поверхность, по которой понимают, откуда продолжать ⛔ **ЗНАМЕНАТЕЛЬ ПОСЧИТАН 11.09, И МОЯ СТРОКА НАЗЫВАЛА ДВА НОСИТЕЛЯ ИЗ ПЯТИ.** Движковая сессия посчитала все места, пишущие `failed` в пайплайне, и разобрала каждое по достижимости ОТМЕНОЙ. Отменой достижимы **пять**: путь оборванного вызова (`backend/internal/pipeline/cutcall.go`, греп `setJobStatus`) — несущий, остановка ходит именно через него · ветвь прерванного ожидания и охранник после впуска резервации (`backend/internal/pipeline/stagerun.go`) — те два, что называла строка · **рейт-гард** (возвращает ошибку контекста на отмене) · **транспортный отказ «запрос не ушёл»** — сюда падает отмена, случившаяся ДО записи запроса, то есть самый обычный Ctrl-C в начале вызова. Последние два не назывались ни строкой, ни отчётом сессии. Остальные — настоящие поломки, слово остаётся. ⚠ **Расхождение счёта РАЗРЕШЕНО 11.09 одним прибором: сайтов ВОСЕМЬ.** `git show HEAD:…/stagerun.go | grep -n 'setJobStatus.*failed'` → 7 строк (557 · 574 · 625 · 644 · 680 · 759 · 797) плюс `cutcall.go:151` = 8. Прежние «семь» сессия сняла по РАБОЧЕМУ дереву, где уже успела снять одну ветвь, — число было честно снято прибором, но не с того предмета, и она назвала это сама. Достижимы отменой ПЯТЬ: `cutcall:151` · `stagerun:625` (прерванное ожидание) · `:644` (охранник после впуска) · `:680` (рейт-гард) · `:759` (транспортный отказ); остальные три — настоящие поломки. Арифметика после починки закрывается на живом дереве: через сужающий контракт 5, прямых записей 3, было 8. ⭐ **Починка сделана ОДНИМ контрактом, а не пятью правками** — сужающая обёртка рядом с сеттером, с доводом в коде: пять сайтов это один вопрос («позиция сломалась или прогон кончился, пока она ждала?»), и пять `if`-ов закрыли бы три, оставив счёт неверным опять. ⛔ **Покрытие УЖЕ починки, и это назвала сама сессия:** пины ловят класс через путь оборванного вызова, отдельных пинов на рейт-гард и транспортный отказ НЕТ | бэкенд | скоро | после остановки человек видит, что куплено и что доделано, и остановленная позиция не названа упавшей | улов движковой сессии, 10.09 |
| 390 | **ПРОВАЛИВШИЙСЯ СЕТТЛ НАМЕРЕННО ОСТАВЛЯЕТ РЕЗЕРВАЦИЮ — И СЛЕДУЮЩИЙ ПОТОЛОЧНЫЙ СТОП ПРОСИТ ПОПОЛНИТЬ БОЛЬШЕ, ЧЕМ НУЖНО.** `backend/internal/pipeline/stagerun.go`, греп `THE RESERVATION IS DELIBERATELY NOT RELEASED HERE`: подметается только следующим пишущим `store.Open`. В окне между остановкой и этим открытием `reserved_usd` завышен, а нехватка для сообщения о потолке считается ИМЕННО от `reserved` ⇒ пользователю называют завышенную сумму пополнения. Решение оставить резервацию — осознанное и объявленное в коде; незаявлено ПОСЛЕДСТВИЕ | бэкенд | когда-нибудь | сумма пополнения, называемая пользователю, не зависит от того, была ли остановка между сеттлом и следующим открытием стора | улов движковой сессии, 10.09 |
| 391 | ⛔ **ИЗ ЗАВИСШЕГО СВОРАЧИВАНИЯ НЕТ ВЫХОДА, ОСТАВЛЯЮЩЕГО ТЕРМИНАЛЬНЫЙ КАДР.** `backend/cmd/tmctl/main.go`, греп `signal.NotifyContext`: горутина выходит после ПЕРВОГО сигнала, регистрация снимается только отложенным `stop()`, канал ёмкостью один ⇒ второй сигнал падает в переполненный буфер и дефолтная диспозиция НЕ восстанавливается. Складывается с `D39.238`: два сигнала в одном кванте процесс видит как ОДИН, значит «нажать ещё раз» не выход даже теоретически. Единственный способ прекратить зависшее сворачивание — убийство извне, после которого платформа не получает ни исхода, ни расчёта. ⚠ **ИСПР. 11.09 — ПРЕЖНЯЯ РЕДАКЦИЯ ЭТОЙ СТРОКИ ПРОТИВОРЕЧИЛА САМА СЕБЕ, и нашла это движковая сессия, а не я.** Она обещала лечение «около двадцати строк» (вернуть дефолтную диспозицию) при критерии приёмки «выход, ОСТАВЛЯЮЩИЙ терминальный кадр». Дешёвое лечение даёт РОВНО ОБРАТНОЕ: второй сигнал убивает процесс диспозицией по умолчанию — тот же SIGKILL, только вызванный вежливее, и кадра по-прежнему нет. ⇒ **дешёвого решения у этой строки НЕТ**: выход С кадром означает «на второй сигнал сами пишем терминальную строку и выходим», и это отдельный предмет с ценой, вплотную подходящий к отменённой лестнице (`D39.240`). Состояние стора после убийства при этом ЗАПИНЕНО и корректно (`TestKillMinus9LosesAtMostOneCall`), то есть строка про ВИДИМОСТЬ исхода для платформы, а не про консистентность | бэкенд | когда-нибудь | у зависшего сворачивания есть выход, после которого платформа получает исход и расчёт — либо признано, что его цена не стоит предмета | улов движковой сессии 10.09; противоречие критерия найдено ею же 11.09 |
| 392 | ⛔ **ОБРАБОТЧИК `/stop` ШЛЁТ СИГНАЛ ПО ИМЕНИ ЮНИТА ИЗ СВОЕЙ ЖЕ ВЫПИСКИ — окно в один тик, и всё это время пользователь видит `202`, а прогон работает.** `platform/internal/runs/reconcile.go`, греп `func (s \*Service) Stop`: имя юнита приходит из `RequestStop` и уходит в `Runner.Stop`. Если между коммитом намерения и вызовом systemd свип успел РЕСТАРТОВАТЬ попытку, сигнал уходит СТАРОМУ юниту, а живёт новый. Самолечение есть — следующий проход увидит живой юнит с намерением и пере-выдаст стоп, — но **починка приходит от свипа, а не от обработчика**. ⚠ И самолечение слабее, чем кажется: пере-выдача ИНЕРТНА на юните в `deactivating` (замер `D39.237` п.2), то есть если первый сигнал не дошёл, свип этого не чинит вовсе — юнит стоит до убийства по грейсу, до десяти минут прогона, который ничего не делает, с зарезервированным холдом ✅ **ПОЧИНЕНО 11.09 (`00d590e`), и МЕХАНИЗМ ДОСТАТОЧНОСТИ надо записать верно — моё первое объяснение было неверным.** Лечение: `select … for update of r` в одной транзакции с записью намерения (`platform/internal/pgstore/runs.go`, греп `for update of r`, единственная строка этого коммита — прежние `for update of r, a` принадлежат другим функциям и стояли до неё). Гонка ВОСПРОИЗВЕДЕНА на живой БД в обе стороны: до правки перезапуск коммитил новое имя юнита, а ответ приходил со старым; после — с новым. ⛔ **Почему замка на строке ПРОГОНА достаточно, и почему это НЕ «заперта и строка попытки»:** опасность со стороны попытки — не изменение существующей строки, а ПОЯВЛЕНИЕ новой (имя юнита ставит заявка на спавн), а строку, которой ещё нет, замком не удержать. Существующую держит УСЛОВИЕ, а не замок: `RecordSpawn` несёт в своём `where` `and exists (… r.finished_at is null and r.stop_requested_at is null)` — заявка отказывается сама, как только намерение зафиксировано. ⇒ следующий, кто пойдёт двигать `RecordSpawn`, обязан споткнуться об это, а не о ложное «там замок». ⚠ **Остаточное окно есть и оно ДРУГОЕ:** транзакция взяла замок и прочла имя юнита ПУСТЫМ → спавн коммитится (его гард ещё видит намерение незаписанным, обычный `SELECT` замка не ждёт) → намерение коммитится. Итог: имя ПУСТОЕ, а юнит живой — это не устаревшее имя из прежней формулировки. Самолечится: `finishStopped` при пустом имени и непустой базе расхода не закрывает прогон, а спрашивает systemd и останавливает юнит — ветка написана заранее под «claim was given back but its unit exists» | платформа | скоро | остановка доходит до ЖИВОГО юнита в том же действии, которым записано намерение | улов платформенной сессии, 10.09 |
| 393 | **РАСЧЁТ ПРИ ЗАВЕРШЕНИИ ИДЁТ ИЗ ДО-ДРЕНАЖНОЙ ВЫПИСКИ — класс «частично применённое состояние внутри одного прохода».** `platform/internal/runs/reconcile.go`, греп `this settlement is opportunistic`: расчёт получает ту выписку, которую проход прочитал ДО дренажа журнала; автор класс знал и закрыл ровно два поля, освежив их вручную. ⇒ любое число, которое дренаж ЭТОГО ЖЕ прохода записал в строку попытки, для расчёта невидимо. ⚠ **Честная граница, названная самой сессией: на сегодняшнем дереве это ЛАТЕНТНО, а не сломано** — расчёт не читает ни одного поля, которое пишет дренаж. Класс предъявлен исполнением только потому, что отменённый пак добавил такое поле (строка попытки видела 9 оценочных строк, выписка — 0). Пак уходит, поле уходит, **класс остаётся**. Родственник в том же файле уже стоил зоне дефекта (греп `freshRunState`) | платформа | когда-нибудь | у прохода одно состояние: расчёт не может читать выписку старше собственного дренажа | улов платформенной сессии, 10.09 |
| 394 | **ПРОГОН, УБИТЫЙ ПО НАШЕМУ ЖЕ ГРЕЙСУ, ЧИТАЕТСЯ КАК ИНФРАСТРУКТУРНЫЙ СБОЙ.** Терминального кадра у него нет вовсе, маркер несёт `timeout/killed`. Разбор: исход сперва спрашивает намерение остановки и при записанном отдаёт `stopped`; БЕЗ намерения падает в причину отказа, где `timeout` даёт `service_error`. ⇒ у класса «мы сами его убили по своему сроку» нет отдельной пометки, и оператор видит поломку там, где сработала наша политика. ⚠ Прямо на предмете `D39.240`: остановка обязана быть отличима от аварии | платформа | скоро | убийство по грейсу отличимо от сбоя и названо своим словом | улов платформенной сессии, 10.09 |
| 395 | **DEV И ПРОД РАСХОДЯТСЯ В ДВАДЦАТЬ РАЗ ПО ВРЕМЕНИ НА СВОРАЧИВАНИЕ, И ЭТО НИГДЕ НЕ ОБЪЯВЛЕНО.** `platform/internal/ingest/supervisor.go`, греп `WaitDelay` — тридцать секунд на dev-пути; `platform/internal/runner/runner.go`, греп `stopGrace` — десять минут на боевом. Один и тот же движок против тех же платных провайдеров получает на свёртку полминуты или десять минут в зависимости от пути запуска. Расхождение само по себе может быть законным, но оно НЕ НАЗВАНО, и dev-замер «успевает свернуться» ничего не говорит о боевом (и наоборот) | платформа | когда-нибудь | оба числа названы в одном месте с доводом, почему они разные, либо сведены | улов платформенной сессии, 10.09 |
| 396 | ⛔ **ГЛАВНАЯ РАЗВИЛКА «ПРАВИЛЬНОГО ВОЗОБНОВЛЕНИЯ»: платформа ПЕРЕЗАПУСКАЕТ прогон, вышедший с кодом остановки БЕЗ записанного намерения.** `platform/internal/runs/reconcile.go`, греп `interruptedBySomeoneElse`. Решение осознанное и с записанным доводом (перезагрузка хоста против ручного `systemctl stop`, асимметрия цен), поэтому строка не о дефекте. ⚠ Но инвариант `D39.240` («правильно возобновить») обязан пересмотреть эту развилку ЯВНО, а не унаследовать: сегодня она означает, что прогон, остановленный мимо продуктовой двери, будет поднят заново и продолжит тратить. Названо платформенной сессией как то, что новый пак не должен взять по умолчанию | платформа | скоро | поведение при коде остановки без намерения ПЕРЕ-решено под инвариант корректного возобновления, а не унаследовано | улов платформенной сессии, 10.09 |
| 397 | **ПЯТЬ ОТКРЫТЫХ РЯДОВ РЕЕСТРА ПЛАТФОРМЫ ПРО ХОЛДЫ И ОСТАНОВКУ — ОДИН ПРЕДМЕТ, А НЕ ПЯТЬ РАЗРОЗНЕННЫХ.** Их печатает собственный гейт зоны как тревогу. Прямо по предмету остановки и возобновления: **PD-418** (у расчётной строки живого прогона нет ручки, а рантбук обещает оператору обратное) · **PD-244** (единственный выход расчёта, оставляющий холд открытым МОЛЧА) · **PD-162** (книга с удалённым каталогом принимает прогон и заклинивает его навсегда с открытым холдом) · **PD-465** (заявка на спавн коммитится ДО подъёма юнита, третий способ уехать под доказательством не ловится) · **PD-217** (книга с незакрытым холдом блокирует апгрейд движка бессрочно). ⇒ под инвариантом `D39.240` это готовый предметный список «не оставить мусор», уже приоритизированный реестром зоны | платформа | скоро | пять рядов закрыты ОДНИМ предметом либо явно разведены как разные | улов платформенной сессии, 10.09 |
| 398 | ⛔ **ПРОГОН, ВЫШЕДШИЙ БЕЗ МАРКЕРА, ПЕРЕЗАПУСКАЕТСЯ БЕЗ ВСЯКОГО ОГРАНИЧЕНИЯ — капа попыток у платформы НЕТ.** Юнит кончился, маркера нет (сломан `ExecStopPost`, повторная перезагрузка) → после льготного окна спавна и без записанного намерения платформа считает состояние свежим и ПЕРЕЗАПУСКАЕТ: новый холд, новый спавн. На ДОЧИТАННОЙ книге движок выходит сразу и снова без маркера ⇒ цикл повторяется каждым проходом свипа. Замер: `MaxAttempts` в `platform/internal` вне тестов — **7 хитов, все в `jobs.go` и все про очередь**, ни одного про попытки прогона (контроль: слово `restart` в `platform/internal/runs/reconcile.go` есть и читается). ⚠ И тревога МОЛЧИТ: счётчик отсрочек очищается «уликой» каждого рестарта, поэтому порог зависания недостижим. ⚠ **Честная граница (Fable 5, 10.09): путь ЗАМЕРЕН чтением, сам бесконечный цикл ВЫВЕДЕН, прогоном не предъявлен** ⭐ **УСИЛЕНО пере-замером платформенной сессии 11.09: естественного ограничителя в ДЕНЬГАХ нет.** Она искала его и не нашла: перезапуск сперва РАССЧИТЫВАЕТ старую попытку, потом берёт новый холд; попытка ничего не потратила (движок выходит сразу) ⇒ холд возвращается целиком и берётся равный новый ⇒ **цикл денежно-нейтрален на итерации и балансом не останавливается**. ⚠ Но цена НЕ нулевая: каждая итерация пишет строки леджера — расчёт и холд, — то есть цикл производит именно тот мусор, против которого заведён инвариант `D39.240`. ⭐ И материал для потолка уже есть: номер попытки инкрементируется каждым пере-открытием, значит капа выражается «номер больше N» БЕЗ новой колонки (доказательство спавна для этого не годится — оно на попытку, а перезапуск открывает новую) | платформа | скоро | у перезапуска без маркера есть потолок, а его исчерпание видно оператору | разбор старшего коллеги по инварианту `D39.240`, 10.09 |
| 399 | **ПЛАТЯЩИЙ ПРОГОН МОЛЧА ЗАМИРАЕТ У ПОКУПАТЕЛЯ, КОГДА ПРОЕКЦИЯ ПАРКУЕТСЯ. ⚠ Строка ПЕРЕ-ПИСАНА 11.09: первая редакция утверждала, что у состояния «запаркована» нет носителя — ЭТО БЫЛА МОЯ ОШИБКА, носителей ЧЕТЫРЕ**, и пере-снято их платформенной сессией: столбец `run_attempts.parked_at` (миграция `00034_spawn_proof_and_park.sql`) · писатель `Store.MarkParked` (`platform/internal/pgstore/runs.go`) · чтение на выписке (`LiveRun.Parked`) · **операторский гейдж** `parked_attempts` (`platform/internal/metrics/metrics.go`), плюс операторский листинг и лимитированная по частоте строка лога (`sayParked`). Если бы строка ушла в заказ как написана, пак пошёл бы строить построенное — ровно класс «условное закрытие», который мы вычищаем из доков. **⇒ ЖИВАЯ половина — ПОЛЬЗОВАТЕЛЬСКАЯ, и только она:** оператор видит парковку четырьмя способами, а ПОКУПАТЕЛЬ видит замерший экран без объяснения. Механизм: курсор встречает чужой хендшейк и проекция останавливается до конца попытки (`platform/internal/runs/reconcile.go`, греп `ErrForeignStreamAhead`), причём комментарий там сам признаёт: «the "stranger" may be this very run, alive and writing» | платформа | скоро | пользователю сказано, что прогресс отстал, а не остановился — тем же каналом, которым он видит прогресс | разбор старшего коллеги + пере-замер платформенной сессии, 10–11.09 |
| 400 | **ПРАВКА БАНКА ЛЕГЛА, ПЛАТФОРМА УМЕРЛА ДО ЗАПИСИ О НЕЙ — СЛЕДУЮЩИЙ ПРОГОН ВОЗЬМЁТ ХОЛД И УМРЁТ НА ГАРДЕ.** `platform/internal/runs/bank.go`, греп `RecordBankMove`: ветка ошибки стора обработана (клиент пере-шлёт, сходится), а смерть ПРОЦЕССА между применением правки и записью факта канала не имеет. Цену называет собственный комментарий кода: отметка о движении банка остаётся пустой ⇒ следующий прогон допускается без пере-снапшота ⇒ умирает на снапшот-гарде уже ПОСЛЕ взятого холда (`PD-425`). ⚠ Прямо на предмете `D39.240`: «не оставить мусор» и «правильно возобновить» — это ровно оно | платформа | скоро | смерть между правкой банка и записью о ней не приводит к взятому холду и умершему прогону | разбор старшего коллеги, 10.09 |
| 401 | **МУСОР НА ДИСКЕ ПОСЛЕ ОБРЫВА: три носителя, ни один не подметается.** **(а)** артефакт сборки при смерти платформы посреди неё остаётся на месте — перечень удаляемого берёт только строки с путём (`platform/internal/exports/exports.go`, греп `Unlinked`); **(б)** временные файлы движка чистит ТОЛЬКО следующая сборка того же идентификатора, которой при обрыве не будет; **(в)** частичный бэкап движка ложится под именем, которого платформа не знает (`platform/internal/runner/backup.go`). ⚠ Отдельно, инертно, но противоречит леджеру: отметка о расчёте может остаться пустой навсегда, если расчёт прошёл, а её запись — нет; читателей столбца вне тестов **0** (греп: только писатели и комментарии) | платформа | когда-нибудь | обрыв не оставляет на диске файлов, которых никто не подметёт, и отметка о расчёте не расходится с леджером | разбор старшего коллеги, 10.09 |
| 402 | **ТРИ УТВЕРЖДЕНИЯ, КОТОРЫЕ ВЫНОС ХРОНИКИ В АРХИВ ОСТАВИЛ БЫ БЕЗ НОСИТЕЛЯ — заведены ТЕМ ЖЕ движением, что и вынос** (условие ока старшего коллеги на дифф, `D39.239` п.4). **(а) Стейл-упоминания снятого маркера `⟨проверить⟩` ВНЕ движка** — вынесенный отчёт называл `platform/internal/runs/spawn.go`, `platform/internal/runs/reconcile_test.go`, `platform/docs/DEFECT_REGISTER.md` (PD-277) и `eval/pilot/memory_eval.py`; все места живы сегодня, плюс `eval/pilot/kana_precision.py`. ⚠ **Стейл ли они — НЕ доказано:** в движке маркер стоит в **10** не-тестовых носителях и 7 тестовых, то есть снят он, судя по числам, только с провода инъекции. Проверять и чинить — чужим зонам (платформа, полигон), пинги им отправлены. **(б) Следствие ФЧ-7: прогон, который УПАЛ поверх потолка, приезжает `paused` с пустым кодом выхода** — по терминам «упал поверх потолка / ФЧ-7 / exit_code nil» носителей **0** в журнале решений, едином бэклоге и регистре платформы (PD-113 — исходный класс, не это следствие). Код платформы принимает это как конструкцию (греп `survives ANY exit`), но выбор «краш невидим за `paused`» нигде не записан как ПРИНЯТЫЙ. **(в) Две границы «не проверено» заланденного пака, у которых нет носителя нигде:** качество рода не измерено на живой книге; цена банкового контура в `c1` на реальной книге не мерена | доки | скоро | каждое из трёх либо получило носитель в своей зоне, либо признано неверным и снято | условие ока на вынос хроники 11.09 |
| 403 | **ЦЕПОЧКА «СВИП → ОСТАНОВКА → НАСТОЯЩИЙ systemd» НЕ ПРОЙДЕНА НИЧЕМ, и это объявлено ЗАРАНЕЕ, а не найдено потом.** Платформенная сессия дважды за смену упиралась в одно: пины говорят о ЮНИТЕ (живой systemd-стенд у зоны есть) либо о СТОРЕ (живой Postgres есть), а утверждения о поведении живут в СВИПЕ — и стенда, который проводит служебный обход через настоящую остановку настоящего юнита, в зоне нет. ⇒ две правки этой смены (`--no-block` в `560ca20` и ответ живым именем юнита в `00d590e`) доказаны каждая на своём уровне и НЕ доказаны сквозной цепочкой; так и записано в обеих секциях «что не удалось». ⚠ Заведено строкой по её же просьбе — чтобы следующий не открывал вопрос заново и не принял «пин зелёный» за «цепочка проверена». ⭐ Отдельно ценно, что предупреждение сделано ДО сдачи, а не после: сессия назвала границу своего доказательства сама | платформа | когда-нибудь | есть стенд, проводящий свип через настоящую остановку настоящего юнита, ИЛИ записано решение, что такой стенд не строится и почему | объявленная граница платформенной сессии, 11.09 |
| 404 | ⚠ **СТРОКА ПЕРЕ-ПИСАНА 11.09: её центральное утверждение было МОЕЙ ОШИБКОЙ.** Первая редакция говорила, что мутация с уехавшим якорем «не краснеет, перестаёт сажаться, и в отчёте „не посадилась“ неотличимо от „пережила“», и что механизма против этого НЕТ. **Механизм есть, и он в самом `tmmutate`:** запись с уехавшим якорем получает вердикт `rotted`, печатается отдельной строкой и **засчитывается как неожиданный исход — прогон завершается ненулевым кодом**; довод записан в самом инструменте (`backend/cmd/tmmutate/main.go`, греп `an entry whose anchor moved guards nothing`). Пере-снято мной по возражению движковой сессии, которая в этот класс наступила и была поймана СВОИМ ЖЕ прибором: `make mutations` дал `MAKE-EXIT=2 · RED 151 · SURVIVED 0 · ROTTED 1`, и протухшей оказалась ЧУЖАЯ запись, сломанная её правкой. ⛔ **ЖИВОЙ ОСТАТОК КЛАССА — не мутации, а ДОКИ И КАТАЛОГИ, где такого счётчика нет.** Линтер доков сверяет ПО СОДЕРЖИМОМУ только якоря опт-ин токен-формы; голый `файл:строка` он не видит по построению, и его протухание не даёт ни красноты, ни строки в выводе (замер 10.09: из 19 голых якорей живых секций реестра долга съехали 10, при 9 из 9 целых токен-формных). ⭐ И побочный урок, названный сессией: знаменатель проверки якорей надо брать ИЗ КАТАЛОГА, а не из своих правок — она проверила три свои записи и не проверила чужую, которую сломала | доки | скоро | у голых `файл:строка` в живых доках есть счётчик, дающий ненулевой выход, — либо они переведены в токен-форму | находка движковой сессии 11.09, пере-снята оркестратором |
| 405 | **РАЗМЕН ПО СТРОКЕ 375 ИМЕЕТ НАЗВАННУЮ ЦЕНУ: проекция расходится с леджером на оборванной попытке.** Починка «обрыв не стирает уже заработанный вердикт» (заландена `3084766`) оставляет позиции прежний `cost_usd`, поэтому деньги ОБОРВАННОЙ попытки в попозиционную проекцию не добавляются: **леджер полон, проекция нет**. Названо самой движковой сессией при сдаче, а не найдено потом. ⇒ тот, кто будет сверять проекцию с леджером на книге, где были обрывы поверх отгруженных позиций, увидит расхождение и не должен принять его за потерю денег — деньги в леджере. ⚠ Заведено ОТДЕЛЬНОЙ строкой намеренно: это цена размена, который оркестратор утвердил осознанно (потеря отгруженного текста хуже неточности отчёта), и она обязана стоять рядом с ним, а не всплыть через месяц | бэкенд | когда-нибудь | попозиционная проекция и леджер сходятся на книге с обрывами поверх отгруженных позиций, либо расхождение объявлено в самой проекции | сдача движковой сессии 11.09 |
| 406 | ⛔ **КОНСИСТЕНТНОСТЬ КНИГИ НИКТО НЕ СПРАШИВАЕТ — ПРИБОРА ПО ОТГРУЖЕННОМУ ТЕКСТУ НЕТ ВОВСЕ.** Мера «сколько РАЗНЫХ передач дал один термин» ПОСТРОЕНА (`Spread`/`Variants`, `backend/internal/pipeline/mining.go:383-384`), но считается по ЧЕРНОВИКУ, на стопе майнинга, ДО редакторской волны, и читает её только человеческая таблица подписи. По ФИНАЛЬНОМУ тексту такой меры не существует ни одной. ⇒ приоритет №1 владельца («консистентные термины на всю книгу») сегодня НЕПРОВЕРЯЕМ в принципе: все четыре A/B, показавшие пользу банка, меряли ПРИСУТСТВИЕ инъектированной формы в чанке, а не отсутствие конкурирующей. **Лечение $0 и переиспользует готовое:** тот же счёт по отгружаемому тексту + строка отчёта сборки «термин X отдан тремя формами в главах 12, 340, 901». Предмет не пуст: полигонный прибор на стенде дал 13–16 % терминов с более чем одной передачей. ⚠ Это ЕДИНСТВЕННАЯ работа, которая делает качество ПРЕДЪЯВИМЫМ; без неё кривую деградации по главам снять не с чего | бэкенд | **скоро** | счёт расхождения форм по отгруженному тексту + строка отчёта сборки | аудит банка 11.09, `research/34` §2.1 | ⛔ **ИСПОЛНЕНО ЧАСТЬЮ 11.09 ПРОГОНОМ A, и первый же результат снял мою же формулировку слепого пятна.** Прибор построен полигоном и дал по отгруженному тексту «0 терминов из 40 отданы более чем одной формой». ⚠ **Ноль держался на том, что прибор НЕ СМОТРЕЛ:** кандидаты искались регуляркой, требующей ЗАГЛАВНОЙ буквы (`[А-ЯЁ][а-яёА-ЯЁ-]+`), и склонённые строчные формы («гу-мастера», «наложницей») отпадали ДО правила сравнения. Я заказал переписать правило сравнения пословно — **заказ бил мимо**: критик применил этот рецепт к прибору на боевых данных, и не вернулся НИ ОДИН из 29 потерянных термов. Починка ГЕНЕРАЦИИ кандидатов на тех же данных даёт **48 найденных вместо 40 и шесть строк со `spread ≥ 2`** там, где печатался ноль. ⚠ И заголовочный «0» неустойчив к порогу складывания: под пословным правилом `沈翠` распадается на «Шэнь»/«Шэнь Цуй» и число становится 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, находка `K3` (единственная пережившая верификацию) | ⛔ **ИСПР. 11.09 ПО СЛОВУ ВЛАДЕЛЬЦА — РЯД БЫЛ НАПИСАН ПО НЕСУЩЕСТВУЮЩЕЙ ОСИ.** Слово: «нет такого понятия [подписанный термин], подписан либо ВЕСЬ банк, либо он в неконсистентном состоянии; есть вариант поставить галочку скипать подпись с фронта — тогда автоподписывание». Это ратифицировано `D39.144`: подписывается банк ЦЕЛИКОМ, пер-термная подпись прямо названа НЕ моделью продукта, дефолт движка — авто-продолжение с неподписанным банком, строки едут С ПОМЕТКОЙ. ⇒ **настоящий дефект глубже, чем «прибор не видит дрейфа»: в коде живёт пер-термный автомат `auto|draft|approved` (`backend/internal/store/migrate.go:192`), и пост-проверка считает нарушением ТОЛЬКО `approved` — то есть принимает решение по ЕДИНИЦЕ, КОТОРОЙ В ПРОДУКТОВОЙ МОДЕЛИ НЕТ.** Это и есть причина нуля при 18 найденных (строка **419**): сломана не поверхность, а ОСЬ решения. Закон `D39.104` на проводе один для всех строк; состояние книги — «подписана целиком» либо «авто-продолжение», и мерить надо им.
| 408 | **ДАННЫЕ БАНКА НЕ ДОСЕЯНЫ, И ИМЕННО ИЗ-ЗА ЭТОГО ГЕЙТ КОНСИСТЕНТНОСТИ НЕЛЬЗЯ ВКЛЮЧИТЬ.** Точность глоссарного класса чекера — **0,067: одно верное срабатывание на 14 ложных (n=258)**, и ложные сконцентрированы: `转` ×6, `蛊虫` ×4, `元石` ×2 (`books/gu-zhenren/labels/metrics.json`). Три дыры, все в ДАННЫХ, не в Go: (а) глагольные и многословные термины засеяны с пустыми формами — один `炼化` дал 7 ложных промахов; (б) односимвольный ханьский ключ структурно вне автомата без `allow_short` (порог 2 знака, `membank/memory.go:71`), а это самый частый класс канона в китайском ранобэ (蛊, 道, 气); (в) сид-линт об этом молчит. ⚠ Владелец 05.09 отложил гейт до замера ложных срабатываний («если он ложно положительно будет стрелять — это плохо, очень плохо») — вот их источник, и он лечится досевом, а не кодом | бэкенд+полигон | **скоро** | досев форм · `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 |
| 410 | **ГОЛОСА — УЗЕЛ БЕЗ ПРОВОДА: мёртв в четырёх местах сразу, и ни одного числа за всю историю проекта.** Нет данных (0 непустых секций `voices:` из 47 сид-файлов дерева, 21 пустая из 22), нет производителя (майнер профили не эмитит), нет инъекции (`InjectVoice` — константа `false` без ручки, `bankmaterialize.go:295`), проверка не запущена (`gates.voice` — 0 в конфигах, флаггер объявлен «PURE observability»). ⚠ **И это ВОПРОС ВЛАДЕЛЬЦУ, а не задача:** ратифицированный список 05.09 ставит в приоритет №1 ТОЛЬКО термины (голос — №3), а канон проекта говорит «термины/голоса» — пока это не одно требование, сессия, собранная по такой формулировке, будет строить от неверной цели. Второй вопрос в связке: подпись профилей владелец снял, а реестр физически заполняла только она — если не подпись, то кто | бэкенд/владелец | скоро | ⚠ сначала СЛОВО ВЛАДЕЛЬЦА о месте голоса в приоритете, форма после него | аудит банка 11.09, `research/34` §2.5 и §4 п.2 |
| 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` держит 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, потом цена | бэкенд+полигон | **скоро** | вендор-сверка identity слага, затем пере-пин с датой и способом в формулировке | критик чисел прогона A, 11.09 |
| 414 | **ПРИЗНАК ОТКАЗА НЕ ЖИВЁТ В `err`: прогон, где четверть денег купила пустоту, читается через эту колонку как идеально чистый.** Замер 11.09 на живом прогоне: `err` пуст на ВСЕХ 33 строках `request_log`, включая четыре провальные (контроль: строк с `err <> ''` — 0). Единственный носитель — `degraded` (`empty` ×3, `length` ×1). ⇒ любой аудит денег или отказов, написанный через `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 |
| 417 | ⛔ **ЗАКОН БАНКА НА ПРОВОДЕ НЕ ВИДЕН В ОТГРУЖЕННОМ ТЕКСТЕ, И СПРОСИТЬ БД «ДОЕХАЛ ЛИ ОН» НЕЧЕМ.** Замерено на живом платном прогоне 11.09 и открыто глазами по каждому попаданию: движок сам объявил на стопе майнинга **9 разошедшихся терминов из 69** (`bank-stop.txt`, распределение `spread`: 1→60 · 2→6 · 3→2 · 4→1). Из девяти **четыре отданы ОДНОЙ формой, и это форма терминолога** (`甲等资质` 6 вхождений при трёх конкурентах по 0 — черновик давал «дар цзя», «дарование первого ранга», «талант класса А»); **одна отдана ДВУМЯ** (`开窍大典` ×9 плюс развёрнутая ×1); ⛔ **и четыре отданы одной формой, которая НЕ БАНКОВСКАЯ**: `高脚吊楼` — банк несёт «дом на сваях», в файле **«свайный дом» ×4 и «дом на сваях» ×0**; `家老` — банк «старейшина рода», в файле «старейшины» ×13 без «рода»; `舅母` — банк «жена дяди по матери», в файле «тётя» ×16. ⇒ **`D39.104` (строка на проводе есть ЗАКОН для каждой роли) в этих юнитах не исполнен, и почему — не установлено:** доехал ли банк до промпта редактора, по БД ответить НЕЛЬЗЯ. ⛔ **ИСПР. 11.09 — формулировка уточнена ЗАМЕРОМ, прежняя была неверна: счётчики инъекции ЕСТЬ и они богатые** (`retrieval_state`: `n_exact_hits` · `n_sticky` · `n_ambiguous_flagged` · `n_spoiler_blocked` · `n_evicted` · `n_postcheck_miss` · `injected_ids` JSON, `backend/internal/store/migrate.go:239-255`, и код сам называет их «механизмом, превращающим тихую деградацию в громкую»). **Дефект в КЛЮЧЕ: `PRIMARY KEY (book_id, chapter, chunk_idx)` — строка ОДНА НА ЧАНК, а не на чанк×СТАДИЮ.** Черновая и редакторская волны инъектируются РАЗНЫМИ выборками (черновик — базовый банк без намайненного, редактор — обогащённый), и их следы складываются в одну строку ⇒ вопрос «что видел РЕДАКТОР» неразрешим по построению схемы, а не по отсутствию прибора. ⇒ первый шаг — не «завести счётчик», а **развести ключ по стадии**, и он же дешёвый: таблица пере-считывается детерминированно каждый прогон ($0, матчер бесплатный) и само-восстанавливается на резюме. Замерено РАСХОЖДЕНИЕ формы; место его возникновения — открытый вопрос, и первый шаг к нему $0: счётчик инъекций на редакторской стадии. ⚠ Не путать с рядом **407** (пост-проверка спрашивает присутствие вместо формы на месте): там прибор не видит дрейфа, здесь дрейф ВИДЕН и не объяснён | бэкенд | **скоро** | счётчик подтверждённых инъекций у редактора; затем объяснение четырёх случаев | критик полноты прогона A, 11.09 |
| 419 | ⛔⛔ **СТЕММЕР СНИМАЕТ ОДНО ОКОНЧАНИЕ, И ИЗ 18 ПРОМАХОВ ЖИВОГО ПЛАТНОГО ПРОГОНА **11 — ЛОЖНЫЕ**: банковская форма ДОЕХАЛА до читателя в том же юните, склонённая, а пост-проверка её не увидела.** Замерено бэкенд-сессией по-юнитно на копии базы прогона A 11.09 (контроль: 84 показано − 66 последовало = 18, столько же записей в `postcheck_detail`). Механизм один: `TargetStemmer.Stem` снимает РОВНО ОДНО окончание, а двум падежным формам нужны окончания РАЗНОЙ длины ⇒ стеммы выходят разной длины, `SameStem` требует равенства (`backend/internal/lang/stemmer.go:70`), и во всех одиннадцати один стемм — строгий ПРЕФИКС другого с разницей в ОДИН знак («путь»/«пут» · «ветвь»/«ветв» · «крепость»/«крепост» · «злой»/«злог»). Примеры ложных: `正道` «праведный путь» → в тексте «школы праведного пути»; `白家寨` «крепость рода Бай» → «крепости рода Бай» ×2. **Настоящих расхождений 7**, и `家老`/`舅父` из ручного оракула прогона среди них. ⭐ **КЛАСС БЫЛ ПРЕДСКАЗАН, И ЛЕЧЕНИЕ НАЗВАНО В САМОМ ДЕРЕВЕ:** пять из одиннадцати — мягкий знак, исключённый из `decl_suffix` НАМЕРЕННО (`backend/internal/lang/data/target-ru.txt:231`, `D39.71`: иначе «Синь»/«Линь» схлопнутся на стеммы «синий»/«линия»), и записка там же говорит — «the soft-sign nominative gap needs seed decl-form enumeration or an **anchor-gated match**, not this global suffix». Пинг стоял; **цена его не была замерена до сегодня**. ⛔ Следствия: (1) число «18 расхождений» в акте `D39.247` завышено в 2.5 раза — эррата 11.09-б; (2) прибор консистентности, переиспользующий банковское равенство, НАСЛЕДУЕТ дыру и врёт примерно в 60 % строк — поэтому пак печатает ДВА числа (по равенству и по якорному послаблению), а разница есть цена стеммера; (3) точность глоссарного чекера **0.067** (ряд 408) — вероятно ТОТ ЖЕ механизм, а не данные сида; проверяется по `fp_ids` | бэкенд | **скоро** | якорное послабление на БОЕВОМ пути `dstFormPresent` — отдельным паком, после замера прибором на размеченном корпусе | пак консистентности, 11.09 |