textmachine/docs/PROGRESS.md

402 KiB
Raw Blame History

Журнал прогресса

⟶ ТЕКУЩЕЕ СОСТОЯНИЕ (на 2026-08-30, голова D39.176 — КУРС: движок и платформа до «работает и отдаёт результат», фронт ЗАМОРОЖЕН и P7 его НЕ размораживает (D39.147). ОЧЕРЕДЬ №20 (единственный носитель — здесь; роль передана 30.08, №19 закрыт нотой передачи): (1) РАЗРЫВ ЦИКЛА: книга не отдаётся файлом — ни одной стороной. Канон обещает createExport/getExport, платформа их НЕ монтирует (смонтировано 15 операций из 20; нет также getRun, updateBook, deleteBook), а движок писателя не имеет вовсе — tmctl export пишет только в stdout (JSON tm-export-v1 либо текст с аудит-баннерами). Греп epub|fb2|docx по движку даёт 21 хит, ВСЕ на стороне ингеста. Долг числится с P8 (platform/BACKLOG.md П-17), с тех пор легло пять паков и ни один его не взял. Слово «отдаёт результат» сегодня ложно по букве — ⚠ 30.08: ДВИЖКОВАЯ половина ЗАКРЫТА паком «писатель книги» (D39.175, 8adcb86): tmctl build отдаёт EPUB 3 + чистый txt с шестью состояниями честности; открытой остаётся дверь платформы (п.4) · (2) холодный прогон движка на текущем HEAD — гейт строк 202/216, слово владельца 20.08: с 27.08 легло ~15 нот (шов, стоп банка флажком, схема v16, класс отказа 15, объёмный потолок, гейт схемы) и НИ ОДНА не проверена деньгами; ≈$0.05 · (3) живой сквозной прогон через API платформы — форма манифеста, сайдкара банка и карта причин флагов сочинены платформой САМОСТОЯТЕЛЬНО и первыми настоящими данными движка не проверялись · (4) дверь выдачи — строго ПОСЛЕ (3) (⚠ слово владельца 30.08: дверь ВСЕГДА строит файл — отказ юзеру не отдаётся, неполная книга уходит с пометкой, т.е. дверь зовёт tmctl build --partial; отказ по умолчанию остаётся операторской ручкой CLI; D29.1(б) «fail-closed» читать как «никогда молча» — честность несут пометки) · (5) проводка --max-units — снятие гейта, а не стройка: механизм в движке стоит (D39.170), живое основание гейта — PD-422 · (6) разморозка фронта — ПОСЛЕ (4): зеркало отстало на четыре минора (0.4.0 против 0.8.0) и две ручки разъехались, размораживать раньше значит перегенерировать типы дважды. ⚠ ДВА ЗАГЕЙЧЕННЫХ ТРИГГЕРА НАЖАТЫ И НЕ ОТРАБОТАНЫ (13-tech-debt-anchors.md §Б-108): go.workу платформы свой модуль есть, файла в корне НЕТ; вендор-сверка маппинга эффорта deepseek-v4-pro — сработала 13.08, носители противоречат, закрывается ТОЛЬКО вендор-докой. ⚠ ЧТО В ПРЕЖНЕЙ ОЧЕРЕДИ БЫЛО НЕВЕРНО, проверено деревом 30.08: пункт про sqlc отдельной сессией ИСПОЛНЕН (D39.172, 63fcee5); «работа полигона в дереве НЕЗАКОММИЧЕНА, читать git status -- eval/» ОПРОВЕРГНУТО — она лежит коммитом 28c2d0f на ветке polygon, запушена, в main не влита, а названная команда возвращает пустоту и уводит в вывод «работы нет»; «развязка git с origin» ОПРОВЕРГНУТА — main и origin/main на одном коммите.

  • ОБЯЗАТЕЛЬСТВА ЛЕНДИНГА P9 ИСПОЛНЕНЫ — но НЕ лендингом (снято оркестратором №20 30.08, сверено статусами регистра): PD-400.2 → accepted-risk, PD-401 и PD-166fixed перевёл аудит доков D39.167 (373ccc7, 28.08), чья находка №1 и говорит: «регистр расходился с МОИМИ ЖЕ актами лендинга — четыре строки». Прежние два буллета висели здесь двое суток после исполнения, и проверочная команда одного из них сама возвращала fixed. Урок в норму приёмки: акт лендинга, объявивший закрытие строки, обязан быть сверен статусом В ТОТ ЖЕ заход.
  • ЛЕНТА КОНТРАКТА за 2728.08, свёрнуто аудитом 28.08 (D39.167): 0.5.0 — D39.161 (снос отменённой пер-термной модели подписи + дверь правок банка) · 0.6.0 — D39.162/D39.163 (сквозная полоса прогресса; Progress.stage ВТОРЫМ и последним исключением границы) · 0.7.0 — D39.166 (покупка пере-прохода членом RunRequest.re_pass). Прожитые дампы приёмки P9 и P10 вынесены в archive/PROGRESS-2026-08-backend.md и в тела нот; здесь остаётся только лента версий.
  • 27.08: ВЫДАН ПРОМТ КОНТРАКТНОГО МИНОРА (CONTRACT_MINOR_SESSION_PROMPT.md, пункт 2б очереди D39.156). ВОПРОС ЗАКРЫТ СЛОВОМ ВЛАДЕЛЬЦА 27.08 (D39.160): сквозная полоса прогресса (строка 200) из минора ИСКЛЮЧЕНА и едет с паком (2в). Причина механическая: гейт платформы требует, чтобы объявленная деплоем версия равнялась канону, поэтому канон и деплой обязаны совпасть В МОМЕНТ ЛЕНДИНГА; снос двери этому не мешает (платформа свою половину снесла 22.08), а смена семантики прогресса мешает — сервер её не считает и не будет до пака (2в), и 0.5.0 у старого прогресса был бы ровно той ложью, против которой гейт стоит. Прежнее «одним куском» покупалось тем, что иначе фронт перегенерируется дважды, — но фронт ЗАМОРОЖЕН и перегенерируется один раз независимо от числа миноров. Промт ВЫДАН: прошёл оба рубежа роли, девять находок опровергателя применены.
  • 27.08: ПАК P8-REVIEW ПЛАТФОРМЫ ПРИНЯТ (D39.159). Четыре оси прочитаны исполнением, кода не тронуто; регистр 374→398 строк, открытых 72→96 (major 1→3). Ратифицированы норма копии-с-каноном, эррата §13 и токен ОСПОРЕНО(PD-N); статусы трёх спорных строк НЕ пере-открыты. Приёмка пере-мерила батарею на движке из HEAD — шов пережил лендинг бэкенда d1eb8a9 — и подтвердила PD-376 своей посадкой. Правка гейта формы регистра ОТКЛОНЕНА замером: краснила бы семь законных строк. Новая строка бэклога 225.
  • 27.08: ВХОДНАЯ ДВЕРЬ ШВА ЗАКОНЧЕНА И ЗАЛЕНДЖЕНА (D39.158). Четыре пака зоны бэкенда приняты одним деревом: $0-глагол приёма правок банка · стоп банка стал ФЛАЖКОМ в самом движке (память предъявленного, схема хранилища v16) · единая точка фиксации отчёта (шесть исходов, v2) · полоса отказов в два яруса с классом write_incomplete/exit 15 · пути решений только конвенцией. Порядок деплоя обязателен: движок первым → tmctl migrate по каждой книге до прогонов → и только потом платформа снимает свой обход (пинг в её журнале). Строки 211/212/213/218 закрыты, 191(б)/203(з) пере-диспозиционированы (устранено, не обойдено), заведены 221224. Онтология банка записана — architecture/18-bank-ontology.md.
  • Эра №15 закрыта — семь приёмок, все ПРИНЯТЫ и залендены; лента, коммиты и разборы — D39.109123 (D-лог) и реестр нот architecture/05-decisions-index.md; снимок прежних бюллетеней этой шапки — архив-слайс -08-02-04.
  • ЖИВОЕ: полигон — фаза Д ИДЁТ (заказ 10.08; деньги санкционированы 15.08 напрямую полигону — ⚠ числа потолка в носителях расходятся, фактическую цепь сверить при лендинге петель; ja-книга enkan_no_hate_ja; при ратификации фазы Д в D-ноту: декой-правило + обязательный кросс-семейный опровергатель приёмки — одобрены 10.08; свежие фриз-коммиты полигона в дереве — НЕ трогать) · платформа и контракт — статус в строке выше, здесь НЕ дублируется (один носитель на факт) · фронт ЗАМОРОЖЕН (D39.136 п.2 + D39.147: морозится ДАЛЬШЕ лендинга P7 — слово владельца 17.08; P7 зону НЕ размораживает, S5-промт не выдаётся, разморозка отдельным словом по достижении сквозного пути; перечень первого касания зоны — синк зеркала на ТЕКУЩИЙ канон (не на «0.3.0»: канон с тех пор ушёл на 0.4.0 и уйдёт дальше строкой 200; оба минора уедут в ОДНУ перегенерацию — D39.152 п.7) + перегенерация типов + моки + гейт утечки конвейера + ФС-1..12 + Ф-63/Ф-28 + фразы В-11 по словарю кодов — не отменён, ждёт разморозки) · закрытые стройки эры — лентой нот: эмиттер D39.131 · P5/P6 D39.130/132 · migrate D39.134 · S4+0.2.3 D39.135 · DeepSeek-репин D39.137 (тела — D-лог и слайсы).
  • Открыто на владельце: после пака «писатель книги» (D39.175): лестница D25.1 — какая ступень даёт читателю копию БЕЗ пометки и что печатать на титуле/в имени файла · лейбл главы без заголовка (сейчас цифры; словесный шаблон = одна строка reader.txt после ратификации К-3) (⚠ три вопроса пака ЗАКРЫТЫ словом владельца 30.08: экспорт юзеру — всегда строить, см. п.4 очереди · модель пометок подтверждена как построена — надпись о пропуске в файле, отдельный варнинг-слой в интерфейсе НЕ строим, машинный отчёт сборки остаётся внутренним носителем (дрейф) · RTL — снят до появления право-налевой целевой пары) · ⚠ ПЛАТФОРМЕННЫЙ ЛИСТ ЗАКРЫТ СЛОВОМ ВЛАДЕЛЬЦА 30.08 (D39.176): квот нет (живём на покупке API, бонусы из админки) · продажа планируется, но не в бете · после пополнения баланса — явное действие пользователя (пункт «авто-резюм paused» СНЯТ) · фразы пользователя (В-3/К-6/Приложение А) ДЕЛЕГИРОВАНЫ проекту с требованием интернациональности: не литерал, а данные по коду причины и локали. Остался ОДИН платформенный пункт — PD-421: держит ли ОТКРЫТЫЙ поток событий сессию живой (переформулирован, ждёт слова) · развязка git с origin (локальная линия ИСТИННА, force-push его рукой; не пуллить) · Приложение А контракта (148: фразы — по словарю кодов 0.3.0, структура готова) · продуктовое слово «остановлена: лимиты» (В-3) · В-4/Ф-30 (глава без заголовка — движковая половина строка 160) · мини-проба флора 44 (одобрена, промт не выдан; число — после ре-пробы 188) · подпись денежного шага 46 · лист В-3+К-6 · схема time-based DeepSeek (доклад — архив-слайс PROGRESS-2026-08-14-15; рекомендация: пик оставить + операционное правило «прогоны в долины», scheduler не начинать без ответа вендора об отметке тарификации) · вход ратификации фазы Д: посылка «dspro дешевле glm» в пике ПЕРЕВЁРНУТА (×1.26 дороже, D39.137 п.4) · возражение Sol по проходу tier эксп-23 (⚠ расхождение носителей СНЯТО 22.08 срезкой: второй носитель — фраза «возражение снято, и владелец назвал причину» — уехал в слайс archive/PROGRESS-2026-08-10-15.md вместе с хроникой, и её довод там читается целиком: Sol судил СВОЁ семейство, что запрещено D13.3. Живым остаётся ровно этот пункт на владельце; подтвердить или снять — при лендинге петель фазы Д) · фронт-вопросы зонного журнала: В-7 (плотность; держит Ф-54) · В-8 (слово состояния в дереве) · В-9 (языки интерфейса — механизм готов, ПТ-36) · Ф-38 (вкладка «Замечания»). Закрытые пункты листа (PD-104 · В-10 · В-11-форма · Ф-56/57/61/62/63 · Ф-28 · ПТ-33-граница · 116 · 126 · 172-пин · PD-203 · санкции фазы Д · дизайн 160/161 · title) — в нотах D39.136145, здесь не держатся.
  • Сделано (сводно) — снимок ленты закрытых эр в archive/PROGRESS-2026-08-04-09.md; детали — D-лог и слайсы.
  • Курс: ОБЩНОСТЬ → КАЧЕСТВО БАНКА → ПАКЕТ-ЧЕКЕРОВ (D39.5978) → ФРОНТ-ЭРА (D39.81100: зоны живые, контракт API ратифицирован) → шов/платформа/движковые блокеры построены (D39.106123). Хвосты курса живут строками: 16 (полная цена холодного старта не измерена: у coldrun-a/coldrun-b нет НИ ОДНОГО редакторского вызова, хотя сама edit-волна отработала и оплачена — 58 вызовов волновым драйвером 2325.07 на малых прогонах, плюс 648 до драйвера; ⚠ прежняя редакция писала «не гонялась НИ РАЗУ» — абсолют ложен, испр. оркестратором №19 по леджерам ~/books/gu-zhenren/**/*.db; держит и оси голоса 13б/24) · 46 (дизайн заморожен D39.92/93, промт ждёт выдачи) · coldrun-b фаза C заморожена чекпойнтом легитимно (D39.86; эталон денег/поведения — coldrun-a, read-only); развилка 0731 решена и исполнена (D39.87/91, код 553f1a3).
  • Горизонт (D39.62/67, освежён D39.95): ДОБОР ИДЕАЛА (первым прогоном: оси голоса 24 · авто-режим · цена 16; жильцы ролей решаются ДО прогона эксп-22 — строка 149 · веса K1K12 13а · вне-претрейн чекпоинт 55; остаток арбитража банка = рецензент спорных кластеров при ре-пробе 74 — D39.102) → ВТОРАЯ ПАРА живьём (ja→ru; преп 81) → МАСШТАБ → пилот Ф2.5 (гейт резюме-строки 80; строки 6268, 85) → Ф3 ридер-IDE (6971). Стоячие: ToS-триггер 25.10 · Ш-2 до go1.27 (⚠ + x/text Unicode 17 тем же тулчейном — строка 119, реестр §Б-108 справочника якорей) · платные прогоны разблокированы (проба провода — D39.97, конфиги 112 залендены).
  • Стек (полная карта роль→модель→конфиг→квирки — STACK.md, D39.126): draft deepseek-v4-flash thinking-ON low ⚠0731 → терминолог (та же модель) → editor deepseek-v4-pro БИЛИНГВ ИНТЕРИМ (топология ПОДТВЕРЖДЕНА при неразличимости жильцов — D39.117; закон-блок ОБЯЗАТЕЛЕН — строка 134; glm-5 резерв; вахта маппинга эффорта pro — §Б-108) → судья gemini (Ф2, в движке НЕ построен — строка 33); канал B Mistral+grok; ~$0.85/ранобэ (D30.4, пере-калибровка при следующем платном прогоне). ⚠ Вендор-факты 1315.08 (пере-пин ИСПОЛНЕН и ПРИНЯТ, D39.137): таблица цен запинена ПИКОМ (flash 0.44/1.32 · pro 1.32/3.96/кэш-хит 0.044 за 1M; счёт шиппинг-c1 = 100% DeepSeek ⇒ ×4.24.4 в пике / ×2.12.2 в долине — замер по трём прогонам); ⚠ про эффорт pro НОСИТЕЛИ ПРОТИВОРЕЧАТ и это НЕ РЕШЕНО (испр. 23.08 №19: прежняя редакция утверждала здесь одну сторону — «эффорт стал настраиваемым low/high/max, квирк 3а устарел»): квирк-канон и STACK.md говорят «ручки у pro НЕТ», замера поведением после 13.08 нет ни у одной стороны, и по гардрейлу владельца такое закрывается ВЕНДОР-СВЕРКОЙ, а не выбором стороны; до неё в силе канон, разбор — STACK.md строка редактора; ⚠ ВЕСА pro сменились под тем же слагом (V4-Pro-0813, класс D39.61) — вахта-риг готов (остаток 172); ⚠ посылка интерим-редактора «dspro дешевле glm» в пике ПЕРЕВЁРНУТА (×1.26 дороже — вход ратификации фазы Д, D39.137 п.4); покупки фазы Д на deepseek до 16.08 16:00 UTC — по старым ценам. ⚠ ВЕСЬ банковый контур (банкнота+терминолог+классификатор) в shipping-c1 НЕ включён — жив ран-локальным конфигом книги (строка 140; сверка STACK.md 09.08 — факт шире прежней декларации «одна банкнота»); эскалация в shipping за budget_usd: 0 (STACK.md §примечания).
  • ЕДИНЫЙ БЭКЛОГ — секция «Бэклог» ниже (одна таблица, единственный трекер; каждая петля обязана иметь диспозицию: решено / отложено-с-записью / отклонено; ведёт оркестратор). СЧЁТ ОЧЕРЕДИ на 30.08 (скриптом по таблице — python3 docs/scripts/counts.py; обновлять при каждом лендинге): всего 181 строк · зона бэкенд 87 строго / 124 широко (175 пере-скоуплена D39.134; 176/177 заведены 15.08; 178 — D39.136; 179 ЗАКРЫТА D39.138; 180/181 — D39.137; 182 — wire-батч, аудит 15.08; 183187 — контракт-ревью 28, D39.138; 188190 — аудит бэклога, D39.140; 191/192 — модель подписи банка и пост-ридинговый цикл, D39.144; 193 — молчащие дыры выдачи, D39.147; 194196 — приёмка пака честности, D39.149; 197 — фикс-лист ФЧ, D39.150; **198204 — приёмка P7 и слова владельца 20.08, D39.153; 205 — слепота гейта якорей, аудит 21.08; 206207 — приёмка P8-FIX, D39.154; 208209 — аудит доков 22.08 (потеря глоссария на Gemini, риг живых проб); 210 — трассировка цепи банка 22.08 (род не производится авто-путём); 211213 — консилиум шва 2223.08: ключи провайдеров не доезжают до движка на SaaS (блокер 202), нестрогий загрузчик сида, дубль конвенции пути у платформы — 211 ЗАКРЫТА и 213 сужена лендингом P9 (D39.162); 214216 — разбор журнала трассировки банка: подпись не оставляет следа, $0-репин недостижим с платформы, три несущих сценария не проверены живым движком; 217218, 220 — аудит переезда машины 24.08: абсолютные пути полигона, дефолты корпуса в движке, бутстрап гейта доков чужой замороженной зоной; 219 (съехавшие line-якоря D-лога) ЗАКРЫТА тем же заходом — D39.157 п.6; 236 ЗАКРЫТА D39.175 — движковая половина построена, платформенный остаток несут очередь №20 п.4 и platform/BACKLOG.md П-17; 238239 — финальное ревью пака «писатель книги», D39.175; 240 — ревизия P9 оркестратором №20 30.08, находка Д3 без носителя) (⚠ колонки счётчик читает С КОНЦА — испр. D39.116) · блокеров очереди 0 (236 закрыта D39.175), платные прогоны разблокированы · «скоро» 55 (перечень — грепом по таблице, рукописный список снят D39.126) · гейт-строки эксп-22: 55·153 (плюс 150 — руки владельца); строка 5 — остаток гейчен ре-пробой 74, носитель события теперь строка 188 (аудит D39.140); остальное «когда-нибудь». ⚠ Счёт — НИЖНЯЯ граница долга, не потолок (разбор — легенда таблицы ниже).
  • Архивы хроники: archive/PROGRESS-2026-07-04-10.md (D31) · -10-13 (D39.6-гигиена) · -13-25 (стройка паков 1116, rerun2) · -25-31 (паки 1720 · мини-прогон · полигон-пакеты 58 · ToS · холодный прогон; D39.2658) · -08-01-02 (сессии №9/№10: общность · качество банка · coldrun-b · открытие фронта/платформы; D39.5990, срез D39.105) · -08-02-04 (сессии №11№13: ручки эффорта · стандарты · контракт API · платформа P0 · банк-арбитраж; D39.91105 + снимок шапки эры №15) · -08-04-09 (пинги закрытых паков эры №15) · -08-14-15 (закрытые бэкенд-записи №1617: эмиттер шва · migrate · пере-пин DeepSeek; вынесено D39.139). Записи ниже — живой хвост (№16+, эра D39.124+; подрезка D39.139).

📌 СОСТОЯНИЕ ПАКОВ (оркестратор №19, 29.08)

Платформенный P11 — ПРИНЯТ И ЗАЛЕНДЖЕН (D39.169) вместе с контрактным минором 0.8.0. Приёмка исполнением: моя батарея с тремя гейтами — 18 пакетов, 838 PASS, скипов 0, линтер 0 issues; живая проба PD-379 на поднятом мной стенде (отзыв → поток гаснет за секунду кадром session_ended → переподключение 401, номер кадром не потреблён); деньги сведены ТРЕМЯ путями. Единственный FAIL — TestARunIsBoundedByItsOwnCgroup, причина в хосте (PD-423), пакет диффом не тронут.

Движковый пак «деньги» — ПРИНЯТ И ЗАЛЕНДЖЕН (D39.170). Приёмка исполнением: моя батарея — 21 пакет из 21, 0 FAIL, полнота сверена списком go list против вердиктов; линтер 0 issues; четыре ключевых пина зелёные поимённо. Две мои мутационные посадки на сценарном тесте: снятие вызова пере-плана → структурный отказ адресным сообщением; снятие вызова И гарда → дефект целиком, всеми четырьмя денежными утверждениями (4 вызова при гранте 1, $0.007280 вместо $0.003640, две доставленные главы оплачены дважды и названы бесплатными). Значит тест ловит ПЕРЕОПЛАТУ, а не факт вызова.

Проводка --max-units в платформу остаётся ГЕЙЧЕНОЙ — но основание УТОЧНЕНО 30.08, прежняя формулировка протухла за сутки. Довод «с --resnapshot потолок не держит» СНЯТ: пробой пере-сидом банка вылечен структурно тем же паком (пере-план против реального снапшота + отказ волны работать с чужим планом, TestAMidRunBankMoveNeverBillsBeyondTheGrant, D39.170). Живое основание одно и оно механическое: единственный писатель bank_moved_at — дверь правок банка (platform/internal/runs/bank.go:182), а рост АВТО-банка от майнинга этого флага не ставит, поэтому майнящая книга на второй покупке идёт без --resnapshot и умирает на снапшот-гарде движка — холд взят, попытка сожжена (PD-422). Это чинится проводкой признака движения банка от майнинга, а не решением владельца.

ОТКРЫТО НА ОРКЕСТРАТОРЕ: PD-425 — денежный major (дверь коррекций пишет пост-verb факт на контексте запроса; обрыв клиента теряет факт навсегда, дальше холд берётся и попытка гибнет впустую). Отсрочка законная — дверь построена чужим паком и требует своих пинов, — но записана на меня, не на зону.

НОРМЫ, ЗАРАБОТАННЫЕ ЭТИМИ ПРИЁМКАМИ:

  • Зелёная батарея — это ПОЛНЫЙ список пакетов ПЛЮС отсутствие FAIL, а не отсутствие FAIL: обёртка подавала exit 0 при падении в хвосте (поймала сама движковая сессия).
  • Линтер якорей гоняется ПОСЛЕДНИМ шагом, после того как код замер. Он судит доки трёх зон, но зоны его не зовут; в этот заход нашёл 21 указатель на исчезнувший код, и правки сдвигали цели дважды подряд — включая мои собственные, уже после починки.
  • Якорь разрешается тем, ЧТО он утверждает, а не номером строки, на которой лежал (движковая сессия записала переезд по совпавшему номеру и промахнулась предметом).
  • Колонка «подтверждено» отчёта, пойманного на ложных подтверждениях, снимается с доверия ЦЕЛИКОМ — критерий, отличавший ошибочные строки от верных, назвать нельзя.
  • pkill по имени процесса на машине с параллельными сессиями бьёт по чужим.
  • Число или «доказано» уходит владельцу только после СВОЕГО прогона.

Бэклог (ЕДИНЫЙ, собран 26.07, актуализация 04.08 D39.99/D39.101; правки — только через оркестратора)

Закрытые строки здесь НЕ хранятся — они уходят в D-лог с номером решения. ID строки стабилен навсегда (не перенумеровывается и не переиспользуется — на «строку N» ссылаются доки и промты, D39.80). Вес: «блокер-очереди» = мешает текущему шагу · «скоро» = ближайшие 12 касания · «когда-нибудь» = записано, не потеряно. Длинная строка начинается жирным лидом — таблица сканируется по лидам; «диспозиция сверху, археология вниз», ячейка >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) — их строки сюда НЕ заходят; здесь движок/полигон/доки, включая движковые стыки фронта (зона «бэкенд», как 99102); строки 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 отвечен — семейства не окупаются (C3SC=+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) владелец когда-нибудь (после фазы 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а Веса рубрики K1K12 не выбраны (Q1: «по данным фазы B»; фаза B прошла на BWS без весов — выбор нужен к агрегатной приёмке качества книги) владелец когда-нибудь (к пилоту) Ф2.5 / отдельное решение D39.44 Q1, D39.46
13б speech-cue.txt zh НЕ шипить до замера голос-флаггера; замера НЕТ (D39.86): флаггер живёт на ФИНАЛЬНОЙ волне, редакторская волна не гонялась ⇒ оси не считались НИ РАЗУ. Гейт: первый прогон добора идеала С редакторской волной (строка 24) → решение владельца о шипе. ⚠ ФАКТ 22.08, делающий строку жёстче: флаггер выключен НЕ только тем, что волна не гонялась — gates.voice не встречается НИ В ОДНОМ шиппинг-конфиге (grep -c voice backend/configs/pipeline-c1.yaml = 0, то же в арм-конфигах), при том что сам гейт в схеме есть (internal/config/pipeline.go VoiceGate, пак-19/D39.55). То есть даже прогон С редактурой осей голоса НЕ посчитает, пока гейт не включён конфигом — отдельное касание, и его надо сделать ПЕРЕД покупкой прогона, иначе замер куплен впустую. ⚠ rules= в отчёте = «гейт СКОНФИГУРИРОВАН», не «отработал» — до фикса 105 читать по знаменателям replies=. Археология дословно — 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.15.4
86 Мелкие открытые решения одним списком (свип D39.66): echo-семантика дропнутого c-lite-члена (D39.18 — оставить pre-c-lite?) · magnitude-кап тяжёлой CJK-утечки (D38.3 п.4в; сейчас strip+flag) владелец когда-нибудь отдельные решения D39.66, D39.69(feed_cap закрыт §1)
— ХВОСТЫ ХОЛОДНОГО ПРОГОНА (исполнен достаточно, D39.58; Р7 владельца) —
16 Полная цена холодного старта: edit-волна не гонялась НА НЁМ (Р7; на малых прогонах гонялась и оплачена); цена холодного старта измерена ДО редактуры (драфт+банкнота $0.0247/волна · терминолог $0.0060.013/проход). ⚠ Прогон НЕ НАЧАТ и закрыт владельцем как неуспешный на этом этапе (02.08, D39.90) — деньги фазы C не тронуты ($0). Свежие числа с пробы bank-low (10 глав, low на черновике И на бэнк-ролях): черновая волна 20/20 ok. ⚠ АРИФМЕТИКА ИСПРАВЛЕНА 23.08 (№19) по базе прогона ~/books/gu-zhenren/coldrun-b/reprobe/bank-low/guzhenren-bank-low.db, прежняя редакция не сходилась: вся ДРАФТ-стадия $0.031639 (из них flash $0.021289 + pro $0.010350 — прежняя редакция звала «$0.031639 flash» и потом ПРИБАВЛЯЛА pro вторым слагаемым, то есть считала его дважды) · терминолог $0.005750 · классификатор $0.007706 (было «$0.004286» — расходится с базой) · весь заход $0.045095, и теперь слагаемые дают именно его (прежние давали $0.052025). Редакторская волна на ЭТОМ прогоне не гонялась (coldrun-a/b: ноль редакторских вызовов) ⇒ строка жива, и она же держит оси голоса (13б/24) бэкенд когда-нибудь (первый прогон добора идеала — после решения по 46) добор идеала D39.58, D39.90
18 Эмиссия головы 蛊: сид-половина = чек-лист (определяющий терм книги сидится allow_short, D39.50); эмиссия-КАНАЛ демотирован до ИЗМЕР-ГЕЙТА (Q7): полигон-замер «меняет ли эмиссия головы рендер композитов» — строить ТОЛЬКО по эффекту и ПОСЛЕ #10 (однознаковый пост-чек чинится чекер-паком); перед стройкой резолвить K-гейт и KWIC-грязь одиночной головы полигон → бэкенд скоро (санкция Q7 D39.70 — после #10, очередью с ре-пробой) полигон-замер → решение D39.58, D39.60, D39.69
24 Остаток: авто-режим флага (проект Б не гонялся) · оси голоса AD (профили не подписаны; черновик готов — coldrun-a/SIGN-PACKAGE.md §3) ; + слот инъекции голоса и решение gates.voice при ненулевых осях (D39.55/D21 п.2) · слой-2 voice не строим до доказательства слоя-1 · сверить until_ch 白凝冰 при курации сида (D19.3в) бэкенд когда-нибудь (первый прогон добора идеала) добор идеала D39.40, D39.58
— ТЕКУЩАЯ ОЧЕРЕДЬ (D39.59) —
78 Леджер денег = НИЖНЯЯ граница: «2xx body decode failed (call IS billed)» — провайдер списал, исходная попытка в request_log НЕ попадает (≤$0.009/сессия); дизайн фикса ГОТОВ (GENERALITY_PHASE2 §5.6: BilledDecodeFails + per-billed-attempt settle с Estimated=true), но это money/ledger-путь — не $0-хастл. Живое число (D39.86): на ре-пробе 74 — 3 таких вызова на 14, неизвестность $0.015111 при леджере $0.114378 (13% захода); движок засеттлил оценку и честно напечатал estimated-cost rows: 3 ⇒ канал ВИДЕН, но decode_error при этом ещё и терминален (не retryable, не escalatable) — 3 из 7 терминальных флагов пробы A бэкенд когда-нибудь (money-паком) отдельное решение (дизайн §5.6) D39.61, D39.64, D39.86
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 п.89, D39.66, D39.69
81 ja-преп B6-ja (сужено пост-сверкой D39.66): Поливанов-валидатор (translit_policy = «Phase 2»-заглушка, migrate.go:187/194) + kana-омограф POS/known-word гейтинг / B6-токенизатор (memory.go:1048); чек-лист 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: карточки из подписанного сида, фильтр по именительному падежу, 86112 сверок/арм — 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а Экран кодировки не видит <meta charset> без XML-объявления (епаб с gb18030-метой прочтётся как UTF-8) — до-паковая дыра, сознательно не тронута пачкой 14а (паритет со старым ридером) бэкенд когда-нибудь отдельное решение D39.54, SMALLPACK §8
35 Не-CJK майнер/банк: en-детектора не существует (hanRuns=0), ja с zh-таблицами активно неверен (0/10); нужен второй ДЕТЕКТОР (прототип mine_nonhan.py) + G1G10 требования 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) бэкенд когда-нибудь отдельное решение 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)
46 Экран целевого языка: «полный связный перевод на английский» проходит classify как ok — живой носитель класса (D39.86); дизайн пака ЗАМОРОЖЕН (D39.92 п.1 closed-set + D39.93: изолированный модуль, именованные причины), промт ждёт выдачи. Гейт-связка: мини-проба флора (44). Археология дословно (двусторонняя дыра оси цели · константы · мины реализации) — architecture/13-tech-debt-anchors.md §Б-46 владелец → бэкенд скоро (порядок §5.4: сначала 113, шаг 6 — под подпись) правка Go по плану §5.4 D39.39(д), D39.86, D39.90
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 ~на 4060% при 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
134 Дата-правка инжект-заголовков под доктрину D39.105 (единый закон-блок редактора вместо двухсекционки · оговорка ОБЛАСТИ употребления · снятие маркера ⟨проверить⟩ с провода; статусы строк и подписная таблица НЕ меняются): кандидат-тексты — §B промта пробы 18; ГЕЙТ ПАЛ (D39.108): текст = ОТПРАВЛЕННАЯ строка пробы 18 БЕЗ оговорки области (девиация №1; оговорка опровергнута §A.4 — НЕ вносить); двигает рендер → RequestHash → перекупка, цену назвать при внесении бэкенд скоро малое касание D39.104 п.2, D39.108
— ШОВ ДВИЖОК↔ПЛАТФОРМА: деньги и механизмы (D39.106/107 п.2) —
136 Write-ahead intent + состояние uncertain-эскроу + closing: холд НЕ освобождается по выходу юнита (сигнал обгоняет денежные события); spend не постится без свидетельства провайдера; расход сверх холда — полной суммой, превышение явной строкой убытка платформа/бэкенд скоро (промты по команде владельца) стройка по research/25 D39.106
137 Ночная сверка расходов с данными провайдера (в движок цены входят float64 по ручной таблице ledger/pricing.go — систематика процентная; сверка приоритетнее споров об округлении) платформа когда-нибудь (до первого платного пользователя) стройка по research/25 D39.106
— НАХОДКИ ПРИЁМКИ ЭКСПОВ 1820 (D39.108) —
140 Банковый контур в shipping-c1 НЕ включён — и это ШИРЕ прежней постановки про одну банкноту (сверка STACK.md, D39.126 п.2а): терминолог и классификатор тоже живут только ран-локальным конфигом книги (ратифицированный путь D39.42 п.4; coldrun 56/128; gates.terminology/gates.banknote в c1 = 0 вхождений); решить: включить в c1 (двигает промпт драфта → RequestHash — цену назвать) либо поправить декларацию; родня 36г владелец → бэкенд скоро СТОП-решение D39.108, exp20 §6, D39.126
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.108, D39.117
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 — свежесть цен проверять только на ПЛАТНОМ пути (03-implementation-notes:244) · cache_ttlcache_write_per_m: цена записи в кэш задана под ОДИН TTL (5 м), при другом TTL расчёт врёт (:246). Оба жили только в справочнике якорей, то есть вне единственного трекера · приёмка D39.134: ценовой гейт держит и ДЕТЕКТОР самолечения деплоя — на стенде с протухшими ценами status даёт 10, а не 13, и цикл «поймал 13 → migrate → повтор» не наступает бэкенд когда-нибудь малое касание свип доков 08.08, D39.134
147 Транспортные частичные из research/21 без носителя (свип 08.08): п.16 HTTP/1.1-escape на последней попытке как ДИАГНОСТИКА тихого усечения 28k [PARTIAL, GATED] · п.17 assistant-prefill continuation на finish=length вместо ре-рана всего вызова [PARTIAL, DEFER]. Оба помечены в ресёрче как отложенные и ни в одной строке трекера не появились бэкенд/полигон когда-нибудь замер → решение свип доков 08.08, research/21 §1617
149 Эксп-22 «панель жильцов»: профиль-скрин (pass/fail пороги ДО замера; урок эксп-21 — скрин, убивший 2 из 12, скрином не был) → панель черновиков (слот несёт ~70% эффекта финала, мерился ТОЛЬКО flash за всю историю) → панель редакторов поверх замороженных черновиков (обязательный кандидат gemini-3.1-pro — аутлаер-гипотеза эксп-04) + шумовой пол + прямой D_/A довесками; агент-судейство под капом ≤60; невиданный zh-срез — повторный жёсткий заказ полигон ИСПОЛНЕН и заленден 10.08 (приёмка №16; промт — archive/prompts/POLYGON_TENANT_PANEL_SESSION_PROMPT_2026-08-08.md); выводы заморожены до фазы Д — закрыть строку при ратификации прогон по промту → ратификация D39.117, приёмка №16
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 не трогается; не включена: цена в размере юнитов не замерена бэкенд скоро (гейт: замер размеров юнитов на первом холодном прогоне, вместе со 157) строка данных по замеру 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 велик — ослабить гард до «родство по любому члену юнита» вместо «по корню серии» бэкенд скоро (гейт: первый холодный прогон, §6 отчёта) замер → решение 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:32-35) — ревизия структуры перекупила бы хвост МОЛЧА, закрыть read-path-расширением · слой пользовательских правок отдельным сайдкаром · зонная половинка темы: Ф-30 фронта / В-4 владельца (глава без заголовка на экране — метка из ДАННЫХ, К-3) ждут ровно эту строку; heading манифеста до неё = ВРЕМЕННЫЙ рендер движка (D39.122 п.2д) бэкенд скоро (ГЕЙТ ПАЛ словом владельца 15.08, D39.136 п.3: ставится ближайшим бэкенд-паком с мандатом максимального качества; ⚠ 30.08: впереди неё стоит блокер 236 — писатель книги, очередь №20 п.1, «ближайшим» читать как «следующим после него»; тесты структуры глав — узлом будущего холодного прогона) пак 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 бэкенд когда-нибудь (до второго прогона книги) малое касание
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
166 Движковая поверхность оценки $/глава (ставка-константа платформы $0.03 из exp08 v2 — временная мера беты, П-10 зоны платформы; честная оценка по книге/паре — движковая) бэкенд когда-нибудь отдельный пак D39.123
167 Докс-пак по аудиту D39.125 — ЯДРО ИСПОЛНЕНО (D39.126): реестр всех нот architecture/05-decisions-index.md · counts.py --check полнота реестра + --lint якорей · разгрузка топ-10 строк · входы 15-money-path/16-events-emitter/STACK.md · К-статусы сведены · 09-target/product-requirements освежены. Остаток строки: статус-баннеры экспов + шапка эндпоинтов quirks (передано полигону промтом фазы Д, §Д8 п.12) (⚠ пункт «DEFECT_REGISTER секциями» СНЯТ 22.08 — исполнено зоной ещё в P5: файл секционирован по весу и по эрам, форма проверена аудитом доков) доки/полигон/платформа скоро (остаток — фаза Д полигона) пинги зонам D39.125, D39.126
168 Состав волн пайплайна = пар-конфиг (данные), не общий хардкод: вопрос владельца 10.08 «нормально ли под китайский строить весь бэкенд и конфиги?» — жильцы ролей и промпты уже конфиг/langpacks, но ТОПОЛОГИЯ волн (перепис · точечный edit-контур · без второго прохода) одна на всех пар; если фаза Д покажет разных победителей по парам (H-3/H-4: en-черновик+edit против zh-связки), состав волн уезжает в пар-конфиг данными; ревью-вопрос общности §0 12-go-style-notes.md бэкенд когда-нибудь (после данных фазы Д) замер (фаза Д) → решение владельца → малое касание слово владельца 10.08, промт фазы Д
169 Экспорт банка для чтения фронтом — ДВИЖКОВАЯ половина ПОСТРОЕНА, строка заводилась слепой к ней (испр. оркестратором 14.08): сайдкар <project_db>.bank.json — весь банк тремя статусами, стабильные id, атомарная запись — существует с D39.122 (internal/pipeline/bankexport.go; рядом bank-stop.json — полная таблица подписи для S5); прежний текст строки («артефакта экспорта нет») повторял жалобу Ф-43, снятую тем паком. ОСТАТОК: платформенная проекция сайдкаров в GET /books/{id}/bank + канал решений подписи — пак читающей поверхности платформы; без неё витрина банка фронта стоит на моке, подписной экран S5 строить не на чем ⚠ ПЛАТФОРМЕННАЯ ПОЛОВИНА: ЧТЕНИЕ ПОСТРОЕНО P7, ЗАПИСЬ СНЯТА 22.08 (D39.153, затем D39.154). Живо: проекция банка listBankTerms с агрегатами. ⚠ Приём решений submitBankDecisions удалён вместе со всей пер-термной моделью подписи (PD-370, ратификация D39.144) — прежняя редакция строки называла его существующим. Остаток строки стал ШИРЕ, а не уже: нет ни доставки решений до движка, ни самой ручки, куда их вводить; носитель — строка 199(а) [ЗАКРЫТА D39.166] плюс контрактная 206 платформа скоро (остаток = доставка, строка 199а) строка 199(а) [ЗАКРЫТА D39.166] Ф-43 фронта, D39.122, D39.127, испр. 14.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 не начинать до ответа вендора «по какой отметке времени тарифицируется вызов» — вендором НЕ задокументировано — и замера доли пика; дешёвый рычаг: операционное правило «прогоны не стартуют в 0104/0610 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, сам риг применяет её же. ⚠ Прежняя редакция строки требовала «внести порог ПЕРЕД прогоном вахты» и объявляла риг ложно-падающим — это протухло 17.08 и снято аудитом доков 22.08: работа уже сделана и предусловием платного прогона больше не является. ⚠ ИМЯ СТРОКИ ВВОДИТ В ЗАБЛУЖДЕНИЕ (испр. №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/NormVersionmanifest.go:160-169); вне батча свободен только 118 (tools/go.mod). Состав — аудит корпуса 15.08 (archive/reports/CORPUS_AUDIT_2026-08-15.md §В.г) оркестратор → бэкенд скоро (собрать к ратификации фазы Д; вносить перед первым платным прогоном добора идеала) координационная строка → промт(ы) батча аудит 15.08, D39.134/136/137
171 Число символов книги — от движка (PD-177 платформы: character_count интейка точен только для UTF-8; GB18030/UTF-16 движок декодирует сам — цифра платформы на них неверна, для UTF-16 занижена ~вдвое): счёт символов в манифест (рядом source_bytes/encoding) либо перерасчёт платформой после разбора бэкенд когда-нибудь малое касание (манифест) П-13 платформы, PD-177, приёмка P5
173 backupStamp секундной точности: два translate в одну секунду дают коллизию имени бэкапа и exit 1, маскируя класс «проект занят» (12) — метка до наносекунд/uniquify либо распознавать коллизию явно; преexisting, вскрыт ревью эмиттер-пака бэкенд когда-нибудь малое касание приёмка D39.131
175 Деплой движка «в полёте» — ДАЛЬНИЙ ОСТАТОК (ближняя половина — типизированный version-mismatch у status + money-тест — ИСПОЛНЕНА паком migrate, принята D39.134; правило свипа «мигрировать только книги БЕЗ открытых попыток» + settle ЗАПИНЕННЫМ бинарём попытки — аддендум P6, D39.132). Остаток: (а) при СЛЕДУЮЩЕМ бампе схемы проставить в файл книги application_id + min_reader_version — данные-задел под окно совместимости, ~0 логики; (б) GC бинарей: удалять не пиненные ни одной незакрытой попыткой, последние 23 релиза держать для отката; (в) окно совместимости читателей / пин уровня книги — строить ТОЛЬКО по триггерам: много тенантов · бампы схемы еженедельно+ · потребители 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): ретрай в ту же секунду после сорванного шага = 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.3.0 финален» ПРОТУХЛО — канон стоит на 0.4.0, ратифицирован D39.152 (испр. 20.08). Промт в архиве. ОСТАТОК-указатель: (а) P7 разблокированпрожито: P7 исполнен, принят и заленден 20.08 (D39.153), промт в архиве зоны; (б) зеркало frontend/docs/api-contract/ + типы + моки + гейт утечки — первое касание фронта при разморозке (расхождение канона и зеркала ВРЕМЕННО ратифицировано D39.142 п.5); (в) вопрос владельцу — BankTerm.decision — СНЯТ ОРКЕСТРАТОРОМ ещё 16.08 как стоящий на ложной посылке (D39.144 п.4), в остатке строки его быть не должно; прежний текст (D39.142 п.4, рекомендация заводить; при «да» — 4 строки схемы + 1 строка P7) оркестратор скоро (остаток = только (б) зеркало фронта при разморозке) P7 → фронт при разморозке D39.138, D39.142, D39.143
184 Жанр книги — ВЫКИНУТЬ (слово владельца 16.08). ⚠ ДВЕ ПОЛОВИНЫ ИЗ ЧЕТЫРЁХ УЖЕ ИСПОЛНЕНЫ (сверено кодом при аудите доков 22.08): поле ушло из контракта и из формы интейка батчем 0.3.0, и платформа жанра больше НЕ ЗНАЕТplatform/internal/books/render.go несёт genre шаблона нечитаемым насквозь и говорит об этом прямо. ЖИВЫМИ остаются две: (а) движковая — снять {{genre}} из промптов пары (сегодня он ещё в terminologist.md, editor-mono.md, translator-banknote.md) + поле из канона брифа: двигает BriefHash ⇒ ТОЛЬКО в общее resnapshot-окно, координировать со 161/182, дешёвое окно пока платная книга одна; (б) фронтовая — форма при разморозке; влияние жанр-строки на качество не измерено и уже не будет бэкенд (+платформа/контракт/фронт) скоро (движковая половина — resnapshot-окном) касание в окне 161/182 + батч 183 research/28 Б-23/§8 п.6, D39.138 п.2в
185 Дописывание глав в ТЕКУЩУЮ книгу («костылей не будет»): форма POST /books/{id}/parts + ответ «сколько глав добавится, что сдвинется и почём» ДО подтверждения; экономика уже позволяет В КОНЕЦ за ~$0.02 (ключ вызова позиционный, исходник вне снапшота), вставка в середину = МОЛЧАЛИВАЯ перекупка хвоста ~$911/500 глав — движковый гейт против молчания ОБЯЗАТЕЛЕН (родня дыры Р6 строки 160); платформа второй файл принять не может (re-parse нет); ja-мина: новый ruby-алиас двигает memory_version → снапшот (громкий --resnapshot, уточнение приёмки); полный $0-резюм хвоста — предусловие D15.2 (строка 49) бэкенд+платформа+контракт когда-нибудь (вместе со строками 160162 — дизайн в паке 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 у клиента; шаги 12 — платформа (её же PLATFORM_DIRECTION.md:202-205), семантика — в спеку батчем 183; транспорт НЕ менять (решение владельца по §5б) ⚠ ШАГИ 12 ПОСТРОЕНЫ И ЗАЛЕНДЕНЫ P7 (D39.153): gzip на JSON и НЕ на SSE + ETag/If-None-Match304 на коллекциях, карточке книги и /capabilities; валидатор считается от БАЙТ ответа, поэтому страница 2 и дельта той же ревизии различаются по построению. ⚠ ШАГИ 12 ПЕРЕ-ПРОВЕРЕНЫ ЗАМЕРОМ 28.08 (воркфлоу-ревью P9 на стенде, приёмка D39.162): банк 437 Б холодным → повтор с If-None-Match даёт 304 / 0 Б; юниты главы 3008 Б → 740 Б gzip (×4.1); ниже порога 1024 Б gzip честно НЕ применяется; SSE корректно не сжимается. То есть половина строки не просто заленджена, а измеренно РАБОТАЕТ. Остаток — шаги 35 платформа (+контракт/фронт) скоро (остаток: шаги 35) мидлварь/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
191 Подпись банка = ОДИН ОК всему банку (модель владельца 16.08, D39.144) — пер-термный полный набор решений НЕ гейт нигде: (а) контракт поправлен (409-полноты снят с resume, pending_decisions информационный — исполнено D39.144); (б) движок: verify_bank-пауза снимается командой resume с решениями «как есть», нерешённое едет авто-строками с пометкой — авто-провод D39.42 п.3 УЖЕ так работает, проверить/ослабить только границу самой паузы; (в) платформа: канал решений P7 строится накопительным БЕЗ гейта полноты + проводка «resume = снятие стопа» до движка; (г) пост-ридинговый цикл правок — выселен строкой 192 (носитель думания) ⚠ ДИСПОЗИЦИЯ ЛЕНДИНГА P7 (D39.153): (в) проводка «resume = снятие стопа» до движка ИСПОЛНЕНА платформой (флаг --verify-bank на resume не передаётся, пин есть); (б) граница паузы движка СВЕРЕНА чтением его кода — зависания нет, движок уходит по авто-ветке при снятом флаге. ⚠ ОСТАТКА-РАТИФИКАЦИИ НЕТ — снято 22.08 сквозной трассировкой (разбор в 203(з)). Прежняя редакция объявляла остатком «движковую половину»: пер-термный гейт полноты жив и лишь обойдён, развилка «одно из двух уступает». Опровергнуто кодом: гейт проверяет полноту ФАЙЛА решений, а не подписей, и ОДИН файл со всем банком его снимает — конфликта с моделью владельца нет. Живой остаток другой и он не решение, а работа: снять обход в платформе, когда появится доставка (строка 199(а) [ЗАКРЫТА D39.166]), эррата к атрибуции — карта шапки D-лога, запись 20.08 ⚠ ПЕРЕ-ДИСПОЗИЦИЯ 27.08 (D39.158 п.1/п.7): движковая половина УСТРАНЕНА, не обойдена. Отложенная половина пункта (б) — «ослабить границу самой паузы» — исполнена: стоп срабатывает только на кластере, которого ни один прежний стоп не предъявлял (память bank_stop_presented, схема v16), возобновление БЕЗ решений продолжает прогон. Прежняя диспозиция «остатка-ратификации нет» верифицировала СОСТАВНОЕ поведение с обходом платформы и на вопрос «работает ли флажок без обхода» не отвечала. Остаток строки — снятие обхода в платформе (её пак), и он ТОЛЬКО после лендинга движка. бэкенд+платформа скоро (остаток — движковая половина, 203з; (б) сверка границы паузы движка — внутри P7 чтением кода, правка движка при расхождении = пинг №18) (б) малое касание движка · (в) внутри P7 слово владельца 16.08, D39.144, D39.42 п.3
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
194 Деньги банковых ролей вне контура согласия (приёмка №18, клейм сессии подтверждён двумя линзами и признан ПРЕЕXISTING): UpsertChunkStatus зовётся только волновыми путями, а терминолог и классификатор чекпоинтятся под стадией terminology в главе 0 и строк chunk_status НЕ пишут ⇒ их деньги не входят НИ в число согласия, НИ в projected_book_usd, при этом на сдвиге снапшота они реально пере-покупаются. Дыра ровно того же класса, что чинила строка 181, и это вторая половина дыры Р6 (родня 160/185, 38). Паком не введено и в его заказ не входило бэкенд скоро (следующее касание денежного пути) расширение проекции на банковые роли + тест приёмка №18, отчёт сессии 17.08
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 (D39.149; тело — archive/PROGRESS-2026-08-17.md, запись приёмки №18): три НЕПРИБИТЫЕ гарантии (снятие фильтра по книге в CheckpointUsageForBook не валит ни один тест — воспроизведено оркестратором · ключ ячейки без chunk_idx съедает деньги соседнего чанка · ветка «строка не пере-оценена» не ловится на продовом пути) · два докстринга reprice.go описывают НЕ то, что делает код · 187 исполнен наполовину (тот же снятый закон в докстринге теста и backend/docs/D15.2-*.md:317) · HistoricalRows не доезжает до status/--json, второй операторский текст (--accept-rebill) без basis · ФЧ-5 РЕШЁН владельцем 17.08 (D39.150): прайсить по модели, которую стадия резолвит СЕЙЧАС, + округление вверх и оговорка в тексте согласия · Status() жёстко падает при ошибке репрайсера против соседней политики деградации · паника поверх ceiling-стопа даёт failed вместо paused (PD-113) · три стейл-докстринга. Носителя-сессии НЕТ — по слову владельца 17.08 пока только записано бэкенд скоро (следующее касание денежного пути; ФЧ-5 обязателен до первого пере-прогона со сменой модели) дофикс-промт ЛИБО попутно ближайшим паком D39.149, D39.150
198 Апгрейд движка стирает замечания и счётчики книги БЕЗВОЗВРАТНО — композиция двух половин, каждая известна по отдельности (приёмка P7, линза «вне карты», обе половины пере-прочитаны оркестратором). Платформа при смене manifest_key сносит ВСЕ unit_resolutions книги (platform/internal/pgstore/readmodel.go:164-165), рассчитывая, что поток их пере-наполнит; движок анонсирует юнит РОВНО ОДИН РАЗ за жизнь книги — ключ unit:<bookID>:<wave>:<chapter>:<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:334=ApplyHeading (испр. оркестратором №20 30.08: якорь уезжал с :230 и с :266 — код растёт) приклеивает детерминированный порядковый к экспортному тексту первой юнит-главы (ce.FinalText = chunk.ApplyHeading(...)), колонка Source при этом остаётся heading-stripped. Платформа переносит обе как есть и честно отдаёт heading: null — то есть клиент нарисует СВОЙ порядковый на языке своего интерфейса над абзацем, который уже начинается с русского «Глава N», а исходная колонка соответствующего маркера не несёт: пара визуально рассинхронизирована на каждой первой главе. Конкретное следствие открытого К-2 контракта; родня движковой строки 160 (глава без заголовка) бэкенд когда-нибудь (с 160) отдельное решение приёмка P7 (D39.153)
202 Живой перевод книги НАСКВОЗЬ через API платформы не гонялся НИ РАЗУ (obstacle сессии P7, подтверждён приёмкой): всё после «прогон стартовал и остановился» — подпись банка, halt на потолке, резюм после пополнения — покрыто батареей против живого Postgres, но с движком-заглушкой; настоящий манифест, сайдкар банка и причины флагов будут ПЕРВЫМИ данными, форму которых платформа не сочинила сама. Форма проверки (решена): только через API, как ходил бы клиент — интейк → старт → живой движок с ключами провайдера → поток событий → подпись и продолжение → чтение глав/юнитов/замечаний/банка и сверка с тем, что движок реально произвёл; качество перевода НЕ предмет (полигон). Цена ≈ $0.05 на десятиглавую книгу. Решение владельца 20.08: ПОСЛЕ холодного прогона движка — гонять одну неготовую систему против другой смысла нет платформа скоро (гейт: холодный прогон движка) короткая сессия по промту оркестратора слово владельца 20.08, D39.153
203 Хвосты контракта после синка 0.4.0 — ОТКРЫТА ЧЕТВЕРТЬ, остальное исполнено (тела релеев — platform/docs/archive/P7_ACCEPTANCE_HANDOFF_2026-08-17.md §7; сюда переписаны НЕ тела, а статус — один носитель на факт). ⚠ Сверено грепом при лендинге, потому что первая редакция этой строки уже разошлась с деревом: (б) ИСПОЛНЕН — срезанная фраза компаньона §2.14 стоит на месте (14-api-contract/README.md:556=различать причины отказа клиент не может по замыслу) · (д) ИСПОЛНЕН — клетка приложения А заполнена unspecified (README.md:1376 — ⚠ первая редакция писала :1391, это строка ДРУГОГО приложения; испр. 20.08) · (г) наполовинуunspecified ратифицирован в каноне (openapi.yaml:1784-1787), открыта только ГРАНИЦА ступеней замечаний (две ступени при девяти рангах движка) → это строка 148 · (и) закрыт полем stop_requested (D39.152) · (л)(м)(н)(о) закрыты контрактной сессией. ОТКРЫТО РЕАЛЬНО:(а) ИСПОЛНЕН 27.08 минором 0.5.0 (D39.161) — канон получил предупреждение о конверте вне /v0; открытым по строке остаётся (к). Прежний текст пункта: (а) канон-половина про /auth — компаньон поверхность описывает (§2.14), а канон говорит только «Signing in is not part of this surface» (openapi.yaml:35-36) и НЕ предупреждает, что конверт вне /v0 может прийти БЕЗ обязательного code; сгенерированный по канону клиент об это спотыкается · (з) ⚠ СНЯТО КАК РАТИФИКАЦИЯ 22.08 — конфликта моделей НЕТ, я нёс причину и следствие наоборот. Прежняя редакция писала: «D39.144 ратифицировал подпись = ОДИН акт, движок держит пер-термный гейт полноты, одно из двух должно уступить». Сквозная трассировка это опровергла КОДОМ: гейт проверяет полноту не ПОДПИСЕЙ, а ФАЙЛА решений, и ОДИН акт его снимает — loadMinedDelta штампует только Source, статус не трогает (mining.go:855-867) → опущенный статус дефолтится в approved (membank/memseed.go:96=status = "approved") → unsignedEngineSurfaces выбрасывает лишь Source=="mined" && Status!="approved" (mining.go:710-719) ⇒ промоутнутые строки остаются сид-поверхностями, дельта пустеет, стоп снимается. Шапка файла говорит это прямым текстом. Один файл со всем банком = один ОК. Обход в платформе (--verify-bank не передаётся на resume) — костыль под ОТСУТСТВУЮЩУЮ ДОСТАВКУ, а не под расхождение моделей: как только доставка появится, флаг можно просто оставить включённым. Настоящий и единственный блокер темы — владение book.yaml, строка 199(а) [ЗАКРЫТА D39.166]. Ратификации здесь НЕ нужно; остаётся снять обход одной боевой строкой (platform/internal/runs/spawn.go) и семью строками ставшего ложным обоснования — работа платформенного пака, не решение владельца · (к) ключ project_db в book.yaml: договорить, кто им владеет — шаблон оператора его не содержит, движок делает необязательным. ⚠ Следствие «на штатном деплое банк не читается» ОПРОВЕРГНУТО живым кодом (проверено при лендинге): ⚠ носитель довода СМЕНИЛСЯ лендингом P9 (D39.162): опровержение опиралось на фолбэк <book_id>.db, который платформа вычисляла сама, а он СНЕСЁН вместе с дублем конвенции (строка 213). Сегодня путь публикует ДВИЖОК конвертом артефактов, и пустой путь — ГРОМКИЙ отказ (platform/internal/runner/artifacts.go:39=the engine published no bank read-out path), то есть банк либо читается, либо деплой говорит об этом вслух; первая редакция этой строки повторила клейм хендоффа зоны, не сверив с деревом — остаток чисто договорной · (л) остаток закрытой строки 148 — Приложение А компаньона. ⚠ Сама 148 СНЯТА 21.08 по слову владельца: она держала мир, которого больше нет — «карта потеряна инцидентом 08.08, реконструкция у оркестратора №15, решить, брать ли черновиком». Реконструкция брать нечего: прежняя карта вела «причина движка → ФРАЗА», то есть предполагала, что фразу рисует СЕРВЕР, а батч 0.3.0 эту политику ОТМЕНИЛ — Note несёт машинный code, фразу рисует клиент, Note.message с провода снят (14-api-contract/README.md:1610=Карта «причина → КОД контракта). Реально пуста другая клетка: соответствие причин движка кодам замечаний, и правила её заполнения в компаньоне уже написаны (фраза по ДОККОММЕНТУ disposition.go, а не по имени константы — инверсия уже стоила двух фраз; класс 2 схлопывается в ОДИН код). Исполнитель — контрактная сессия, не оркестратор ⚠ ПЕРЕ-ДИСПОЗИЦИЯ 27.08 (D39.158 п.7): хвост (з) закрыт — «ратификации не нужно» отвечало на вопрос про один файл решений, не про флажок; движковый гейт полноты снят, не обойдён. контракт/доки скоро (следующее касание контракта, вместе с 200) контрактная сессия приёмка P7 (D39.153)
204 Движок не публикует причины флагов ДАННЫМИ — карта причин у платформы рукописная и расходится молча (релей §7(в) хендоффа P7; зона платформы в чужой бэклог не пишет и просила строку сюда — platform/docs/archive/platform-PROGRESS-P7.md:206). Сегодня platform/internal/ingest/notes.go держит рукописную копию закрытого словаря ЧУЖОЙ зоны: 15 причин движка → коды замечаний контракта, сверено побайтно на 20.08 и верно СЕЙЧАС. Импортировать движок платформе нельзя (D39.85 — разные модули), поэтому расхождение появится молча в тот день, когда движок добавит причину: платформа отдаст unspecified и напишет ERROR в лог, то есть деградация честная, но карта протухнет незаметно. Лечение: движок публикует свой словарь причин артефактом-данными (тем же классом, что манифест и сайдкары банка), платформа читает его вместо копии. ⚠ Носителем был ТОЛЬКО регистр платформы (PD-246) — то есть обязательство к зоне движка жило внутри зоны автора; поймано ревьюером полноты выгрузки при лендинге бэкенд когда-нибудь (со следующим касанием эмиссии флагов) отдельное решение приёмка P7 (D39.153), релей §7(в)
205 Гейт якорей: ИСПОЛНЕН 21.08 — сверка по содержимому, двусторонняя дельта, объявленная слепота. Был: проверял только существование файла и переполнение номера, поэтому дал ЗЕЛЁНЫЙ на четыре якоря, сломанных архивацией — а оркестратор на эту зелень опёрся вместо ручной сверки. Стало (docs/scripts/counts.py): якорь может нести ОПТ-ИН токен ожидания `путь:12-14`=`подстрока`, и такой якорь сверяется по содержимому; область расширена с docs/ на platform/docs и frontend/docs (98 доков); из хука убран быстрый выход по «коммит не трогает docs/» — он ампутировал ЦЕЛЕВУЮ сторону, а цели у нас в основном КОД, то есть главный двигатель протухания приезжал ровно тем коммитом, на котором хук молчал (проверено ТЕСТ-КОММИТОМ, не ручным прогоном — норма D39.148). ⚠ Разбор с внешним ревьюером снял три моих ошибки дизайна: (1) у дельты ДВЕ роли, и путать их нельзя — ТРЕБОВАТЬ токен можно только на затронутых строках (иначе долг блокирует всех), а ПРОВЕРЯТЬ уже написанные токены дельта ограничивать не должна вовсе: токен был истинным при записи, значит упавший — гниль по построению; corpus-wide проверка схлопывает «пропущенное окно» (коммит без хука, --no-verify, свежий клон, проигнорированный warn) из «навсегда» в «до следующего прогона»; (2) окно диапазона 80-82,243 считалось как min..max — 164 строки, и токен, случайно живущий внутри, красил зелёным; теперь ОБЪЕДИНЕНИЕ отрезков; (3) литеральная сверка токена была машиной ложных тревог — фраза, разорванная переносом строки в цели, непроверяема в принципе, а будущая пере-вёрстка абзаца кричала бы «цель уехала» на невиновного; теперь ПРОБЕЛЬНАЯ нормализация (детерминированная и симметричная), разметка остаётся литеральной. ⚠ Мой довод «неудобство и есть механизм» был неверен: мой собственный случай был FALSE POSITIVE самого гейта — токен был истинным, цель не двигалась. ОБЪЯВЛЕННАЯ СЛЕПОТА (печатается гейтом каждый прогон): якорь БЕЗ токена — только существование и длина · подмена цели файлом с тем же путём ловится только токеном · цели читаются из ДЕРЕВА, поэтому чужой незакоммиченный WIP может транзиентно и уронить токен, и спасти · токен доказывает ссылочную свежесть, НЕ истинность фразы дока о цели · в ручном прогоне «дельта» = всё незакоммиченное кем угодно, поэтому ТРЕБОВАНИЕ токена живёт только под --from-index. ОСТАТОК: миграция корпуса на токен-форму органическая — токен требуется на ЗАТРОНУТЫХ строках, поэтому счёт растёт сам с каждым касанием. Числа здесь НЕ держим (первая редакция держала «4 из ~580» и протухла за сутки): текущий счёт токенов, якорей и доков гейт печатает КАЖДЫЙ прогон — python3 docs/scripts/counts.py --lint оркестратор/доки сделано 21.08, миграция органическая исполнено; остаток гасится касаниями аудит работы №18 + разбор с внешним ревьюером, 21.08
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
210 Род НЕ ПРОИЗВОДИТСЯ авто-путём вовсе — механизм доставки построен, а данных для него нет (найдено трассировкой цепи банка 22.08, сверено кодом оркестратором; полигон вскрыл то же независимо: «в банке НЕТ ПОЛЕЙ ПОЛА»). Доставка рода на провод ПОСТРОЕНА и работает: membank/memory.go кладёт genderConstraintNote в черновую инъекцию — но ТОЛЬКО для строк со статусом Confirmed, по прямой директиве владельца D39.21 «род должен доезжать». Данных ей никто не даёт: промпт терминолога возвращает РОВНО ТРИ поля (backend/prompts/zh-ru/terminologist.md: термин · перевод · уверенность 0100) — поля рода в ответе НЕТ; майнер берёт gender исключительно из СИДА (internal/miner/miner_emit.go seedMeta, meta.gender = e.Gender), эмитируемые кандидаты его не несут. ⇒ на любой книге без ручного сида ось рода мертва по построению, и «плывущий род» — это не дефект рендера, а отсутствие входных данных. Прямо бьёт по цели №1: реестр памяти C3 называет русский глагол прош. вр. при скрытом роде «механическим спойлер-каналом» и «жалобой №1 читателей MTL» (строка 82). Развилка, которую надо назвать до стройки: добавлять ли поле рода в ответ терминолога (двигает провод ⇒ ТОЛЬКО в вайр-батч 182) ЛИБО выводить род отдельным дешёвым проходом, ЛИБО признать род сид-только свойством и гейтить им качество явно. Родня 82 (морфо-гейт рода) и 178 (калибровка sense). ⚠ ДОПОЛНЕНО 23.08 (№19): замка ДВА и они независимы — род рендерится только при Disp == Confirmed (membank/memory.go:705-713,823-827=Mirrors the editor block's confirmed-only gender), а mining.go:676 запрещает авто-банку статус approved. Род НЕ единственное осиротевшее поле: Sense/Speech/Decl тоже приходят только из сида, авто-продюсер есть лишь у Dst (терминолог) и Type (классификатор). ⚠ Поле Gender в схеме сида УЖЕ ЕСТЬ (internal/seed/seed.go:71=Gender string) — ось мертва в ПИСАТЕЛЯХ, не в формате. ⚠ И тесты слепы ПО ПОСТРОЕНИЮ (пере-проверено 23.08): все gender-кейсы конструируют род РУКАМИ, то есть зелёная батарея не отличает «производитель работает» от «производителя нет»; гейта на дрейф рода в движке нет бэкенд (+полигон на замер) скоро (цель №1; правка провода — вайр-батчем 182) развилка → решение → правка промпта/прохода + замер на прогоне с редактурой трассировка цепи банка 22.08, D39.21, C3 реестра памяти
213 ОСТАТОК — одна строка в ДЕВ-пути: супервизор зашивает "book.yaml" мимо константы ConfigFile (platform/internal/ingest/supervisor.go:142="status", "--config"). ⚠ ГЛАВНАЯ половина ЗАКРЫТА лендингом P9 (D39.162): платформа больше не парсит book.yaml нестрогим декодером и не вычисляет <project_db>.bank.json по чужой конвенции — путь берётся из конверта артефактов, который публикует движок (platform/internal/runner/artifacts.go:28-35; пустой путь — ГРОМКИЙ отказ, а не тихий недо-чит), и собственный projectDB() снесён вместе с суффиксом. Осталась ровно та тривиальность, которую строка называла рядом с дефектом. ⚠ Пере-именование банк-экспорта в фикс-имя рядом с events.jsonl — ЛОМАЮЩЕЕ, его место в окне строки 161, НЕ здесь платформа когда-нибудь (одна строка, следующим касанием зоны) правка дев-супервизора консилиум шва 22.08; главная половина — D39.162
214 Подпись банка не оставляет на банке НИ ОДНОГО следа. Единственная долговечная запись акта подписи — булев bank_released на прогоне (platform/internal/pgstore/runs.go:1180=bank_released = bank_released or $2): кто и когда подписал, что именно вошло в подписанный набор — не хранится нигде. Следствие: пост-фактум ответить «почему в книге этот перевод термина» нельзя, а при пере-нарезке или пере-прогоне восстановить намерение человека не из чего. ⚠ ЧАСТИЧНЫЙ ответ появился с дверью правок (D39.162): её документы решений — долговечная запись того, ЧТО владелец решил, и они переживают прогон. Не отвечено по-прежнему: КТО и КОГДА подписал, и что именно вошло в подписанный набор. Всплыло трассировкой цепи банка 22.08, подтверждено пере-проверкой платформа + бэкенд когда-нибудь (с трубой доставки правок, D39.156) отдельное решение о провенансе подписи трассировка цепи банка 22.08, пере-проверено №19
216 Подпись банка, halt на потолке и резюм после пополнения не проверялись против ЖИВОГО движка ни разу. Проверки этих путей в батарее платформы стоят на фейках; единственный живой прогон движка в батарее — не по этим маршрутам. То есть три несущих сценария продукта держатся на договорённости о поведении чужой стороны, а не на замере. ⚠ Гейтится тем же, чем и живой прогон книги (строка 202): холодный прогон движка платформа когда-нибудь (с 202) живой прогон по трём маршрутам трассировка цепи банка 22.08, пере-проверено №19
227 signature в квитанции двери правок считается от карты, которую переписывает ЛЮБАЯ граница майнинга (находка воркфлоу-ревью P9, 28.08): запись карты стоит ВЫШЕ решения о стопе (backend/internal/pipeline/mining.go:191=writeFileAtomic(r.signatureMapPath()), поэтому signature != null НЕ означает состоявшегося стопа подписи; surfaces/undecided дрейфуют между двумя вызовами владельца, а undecided: 0 достижим при НЕпредъявленных решениях (кап top-200 вытесняет). ⚠ Починка аддитивна и носитель для неё уже есть: карта несёт СВОЙ идентификатор (backend/internal/membank/decisions.go:955=id, err := seed.SignatureMapID(content)), а шов его не читает — отдать идентификатор в квитанцию и судить по нему. ⚠ Якорь находки был неверен (pipeline/signaturemap.go не существует) — исправлен приёмкой чтением. Цена сегодня мала (поле информационное, гейтом не служит) и растёт вместе с экраном подписи: именно он будет решать «что я подписываю» по этому числу бэкенд когда-нибудь (гейт: заказ экрана подписи) аддитивная правка квитанции воркфлоу-ревью P9, D39.162
228 Отклонённая поверхность возвращается АЛИАСОМ уцелевшей строки — движок не держит того, что канон уже обещает (находка воркфлоу-ревью P9 в форме Д1, УЗКО пере-сформулирована бэкенд-сессией 28.08 и принята приёмкой): канон говорит дословно «declining a surface removes EVERY window of that surface» (docs/architecture/14-api-contract/openapi.yaml:2051), а эмиссия майнера энтити-широка (backend/internal/pipeline/miner_emit.go, clusterTouches), тогда как фильтр авто-банка ключуется только по собственному src строки (backend/internal/pipeline/mining.go:662). ⚠ Правильная форма — снять АЛИАС со строки, а не снести строку: расширение 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 Ось «свежий/пере-делка» выведена из ПОЛНОТЫ СТРОК, а не из факта отгрузки (D39.170, находки охотника 3 и 4). Следствия ДЕНЕЖНЫЕ на слух покупателя: добавление стадии в пайплайн превращает ДОЧИТАННУЮ книгу в «3 unit(s) NEVER delivered» и приглашает купить её снова; юнит, прерванный между волнами (signature stop, денежный потолок, Ctrl-C), второй раз считается свежим и тратит слот гранта повторно — замерено 4 купленных юнита → 2 главы. Носитель у движка УЖЕ есть: реестр анонсов events_outbox.once_key (backend/internal/pipeline/events.go:396=unitOnceKey is the identity of one announcement), ключ unit:<книга>:<волна>:<глава>:<юнит>, монотонный на всю жизнь книги и переживающий и добавление стадии, и обрыв между волнами. Не хватает ЧИТАЮЩЕГО метода поверх готовой константы (backend/internal/store/outbox.go:31=SELECT 1 FROM events_outbox WHERE once_key = ? AND once_key <> '', с уже написанным объяснением, почему хвост <> '' синтаксически обязателен). ⚠ РАЗВИЛКА, которую надо назвать в промте: ключ несёт ВОЛНУ, значит «юнит отгружен» — факт per-wave. Ответ есть и он не новый механизм: отгрузкой считается волна, владеющая ОТГРУЖАЮЩЕЙ (последней) стадией — backend/internal/pipeline/snapshot.go:243=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
234 Основание платформы «не брать rebill_* через шов» УСТАРЕЛО этим же лендингом (D39.170). platform/internal/ingest/resync.go:37-43 объясняет отказ ТАЙМИНГОМ: «status проецирует СОХРАНЁННУЮ память, и сразу после bank-apply он честно читает ноль». Движковый пак это починил: foldMemoryForRead стал ПЕРВЫМ ответом читающего пути, projectStoredMemory понижена до фолбэка (backend/internal/pipeline/status.go:817-824=IT IS NO LONGER THE READ PATH'S FIRST ANSWER). Комментарий чужой зоны теперь несёт снятую посылку и будет прочитан следующей сессией как действующий довод. ⚠ Проводка полей при этом НЕ разблокирована: она гейчена вместе с --max-units платформа скоро Пинг зоне платформы + строка её регистра; проводка — после снятия гейта --max-units приёмка 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'ом вендора, а носители до сих пор ПРОТИВОРЕЧАТ (квирк-канон и STACK.md говорят «ручки у pro НЕТ»), и по гардрейлу владельца это закрывается ТОЛЬКО вендор-докой, а не выбором стороны. Держит жильца Д5 и калибровку цены редакторского арма. ⚠ Класс важнее двух пунктов: спроектированный механизм без носителя события тихо становится долгом, и никто не проверяет, не нажат ли спусковой крючок. оркестратор скоро (а) один файл в корень; (б) заказ полигону на вендор-сверку аудит очереди 30.08
238 Деньги слепы к правке исходника НА МЕСТЕ при том же снапшоте. projectRebill сверяет content-hash строки только в bank-only ветке со сдвинутым снапшотом; при том же снапшоте строка идёт как «$0 resume» без сверки — translate на такой книге перекупает юниты БЕЗ предупреждения в смете (воспроизведено финальным ревью пака: «2 units re-bought»). Экспорт эту правку теперь ВИДИТ (состояние stale, D39.175), денежная проекция status — нет бэкенд скоро адресный фикс + посадка-тест финальное ревью пака «писатель книги», D39.175 п.5
239 Status.checkWave не видит исчезнувшую из конфига стадию — то же слепое пятно, что закрыто у Export паком (строка со стадией вне текущего конфига = drift, exportConfigDrift): статус книги с удалённой edit-стадией рапортует черновики как полную книгу без дрейфа бэкенд скоро перенести правило exportConfigDrift в checkWave + тест финальное ревью пака «писатель книги», D39.175 п.5
240 Оплаченный стоп подписи банка может исчезнуть МОЛЧА — единственная находка ревью P9, прожившая двое суток БЕЗ носителя (Д3, platform/docs/platform-PROGRESS.md:1593=Потеря/порча маркера выхода; заведена оркестратором №20 30.08 при ревизии P9). Рестарт/ретрай проходит границу банка НАСКВОЗЬ: память предъявления (bank_stop_presented, схема v16) покрывает карту, движок продолжает одним WARN себе в журнал, а платформенный гард LiftBankStop (platform/internal/runs/reconcile.go:1304=LiftBankStop, писатель — platform/internal/pgstore/runs.go:1185=LiftBankStop) писан против движка ДО памяти v16 и этот путь не держит. Движковую половину бэкенд-сессия ОТКЛОНИЛА правом §9 («символ живёт в platform/, движковая половина здорова») — диспозиция принята, но платформенная половина не получила ни строки регистра, ни строки бэклога. ⚠ Узел ТОТ ЖЕ, что у снятия обхода --verify-bank (пинг №21): LiftBankStop + колонка bank_released, и пак P12 §3.7 их уже трогает — закрывать ОДНОЙ работой, не двумя платформа (+бэкенд на сверку) скоро (с §3.7 пака P12) снять гард вместе с обходом либо доказать, что память v16 делает его недостижимым — с живой пробой на стенде ревизия P9 оркестратором №20, 30.08
217 Скрипты полигона захардкодили АБСОЛЮТНЫЕ пути двух корней и не работают на этой машине вовсе. ДВА РАЗНЫХ слома. Корень репо — смена пользователя: литерал в 121 файле, из них 104 дословно REPO = Path("/home/ubuntu/projects/textmachine"), портабельных форм всего 5. Корень книгоба события порознь: литерал /home/ubuntu/books 86 файлов (пользователь), портабельный Path.home()/"books" 89 файлов (переезд каталога; на прежних машинах работал). Объединение 173 файла. Пользователь теперь ubuntu-26, книги переехали в <репозиторий>/books ⇒ ломается и то и другое, включая ЖИВОЙ гейт фазы Д eval/conformance.py:48=REPO = Path("/home/ubuntu/projects/textmachine"). Живых носителей 26 по корню книг (среди них портабельная форма преобладает 20:6) плюс корневые гейты и сборщики корпусов; остальное — скрипты закрытых эксп-1216, их владелец велел ВЫБРОСИТЬ, а не чинить (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: три эрраты за сессию убили якоря в 17-seam-inbound-law.md:120 и research/25-seam-cold-review.md:5 (оба целили в :232, тело уехало на :239). Лечение — не пере-нацеливание (оно повторится через эррату), а СМЕНА ФОРМЫ якоря: в тела D-лога целиться номером ноты (^## D39.106), который стабилен навсегда, а не строкой. ⚠ Строка ОБЪЯВЛЕНА в CURRENT-STATE 24.08 и до 27.08 в таблице НЕ СУЩЕСТВОВАЛА — очередь три дня ссылалась на носитель, которого нет; поймано свипом якорей при выдаче контрактного минора оркестратор скоро (растёт с каждой эрратой) --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:500=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-шаги миграций v8v14 не идемпотентны вопреки шапке 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-довесок исполнен частично; срез эксп-21 НЕ купил (главный zh-замер на книге 4/5, без пинга) — остаток = неконтаминированный zh-срез полигон скоро (эксп-22 Ф0 — повторный ЖЁСТКИЙ заказ, стоп при неисполнимости) эксп-22 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 · дистилляция 714B); + 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)
105 Роль classifier мис-вердиктится как эхо (verdict=cjk_artifact при bad_lines=0); ЛАТЕНТНО — classify_types выключен во всех шиппинг-конфигах. Цена фикса, знать заранее: бамп classifierVersion → перекупка чекпойнтов классификатора (центы). Поля rules=/VOICE читать по знаменателям (13б). Разбор дословно — architecture/13-tech-debt-anchors.md §Б-105 бэкенд когда-нибудь (ближайшее касание банка/наблюдаемости; (б) — дешёвая часть, вердиктов не двигает) малое касание + вердикт-двигающая половина (а) через СТОП-решение D39.86
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
113 Запас боевого гейта не зафиксирован тестом, а харнесс, давший число, УДАЛЁН (Д-хвост D39.90). Числа «18 из 20 · 0 ложных на 1055 · запас 13× (0.0117 против 0.15)» и «санитайзер поймал бы английский черновик» получены ВРЕМЕННЫМ тестом в пакете pipeline (splitBanknote+StripThink+sourceScriptShare), который сессия удалила после снятия. Число ушло в контракт (строка 46), воспроизвести его нечем. Делать: корпус-фикстура в репо (~20 off-target + ~40 здоровых, с движковой предобработкой; снапшот НЕ двигает) + регресс-тест на реальный запас — это база, которую обязано побить любое предложение по 46. СТОП, если фикстура не воспроизводит 18/20 при 0 FP, или если запас меньше 3× бэкенд скоро (перед любой правкой по строке 46) $0 фикстура + регресс-тест D39.90, EFFORT_HANDLE §5.4 шаги 12, §7
114 Конфиго-слой ручки эффорта: два дешёвых хвоста приёмки (вне снапшота, $0 прогонов). (а) Д4 отчёта: gates.terminology.target_script НЕ сверяется с book.target_langtarget_lang: ru + target_script: Latin грузится чисто и ИНВЕРТИРУЕТ банковский экран (ловит целевой, пропускает чужой); сверка при загрузке против lang.LangScripts(TargetLang) — тот же дата-план, что у экрана строки 46, громкий отказ на несовпадении. (б) Находка-2 приёмки: стейл-доккоммент capability.go:78у константы ReasoningExtraBodyDisable до сих пор «effort "" leaves the provider default», противореча проводу (applyToBody мержит disable на "", комментарий в теле arm это прямо объясняет) и починенному ThinksOnWire; однострочник тем же касанием бэкенд скоро (мелкий пак или попутно со строкой 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 заведён) · вахта маппинга эффорта 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). Делать: явные версии-свёртки + механическую сверку «таблицы↔константа» вместо совпадения бэкенд скоро правка версий-свёрток + тест D39.96 п.6, отчёт §5 находки-5/6
120 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 ВНУТРИкнижный остаток оси арбитра (заголовок исправлен 27.08 — прежний говорил «межкнижный» и инвертировал собственное тело: межкнижную гонку конвенция как раз сняла): второй конфиг ТОЙ ЖЕ книги с другим 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 Банк-экспорт на стопе ПУСТ — проекция, наиболее пустая ровно в момент, когда её читает экран подписи. Замерено: стоп с двумя предложенными термами даёт total=0, авто-банк на стопе отсутствует, потому что он пишется только в ветке авто-продолжения; при этом комментарий рядом называет стоп «границей, которую читает экран подписи», а платформа читает именно .bank.json. Член класса «проекция без контракта потребителя» (architecture/18-bank-ontology.md) бэкенд + платформа скоро (держит экран подписи вместе с 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

(Хроника сессий №11№13, 0204.08 (D39.91105: ручки эффорта · стандарты репо · archguard · S2 · контракт API v0 · платформа P0 · банк-арбитраж research/24) — в archive/PROGRESS-2026-08-02-04.md.)

(Хроника сессий №9/№10, 31.0702.08 (D39.5990: курс «общность вперёд» · свип полноты · качество банка · фикс-пак · coldrun-b · фронт/платформа открыты · шов движок↔платформа · промт арбитража банка) — в archive/PROGRESS-2026-08-01-02.md.)

(Хроника 25.0731.07 до курса D39.59 — эры №7/№8 и начало №9: паки 1620, мини-прогон, полигон-пакеты 58, ToS-речеки, пак-19, холодный прогон (лендинги D39.2658) — в archive/PROGRESS-2026-07-25-31.md.)

Бэкенд

Прожитая проза эры 2428.08 ВЫНЕСЕНА в слайс docs/archive/PROGRESS-2026-08-backend.md (аудит доков 28.08, D39.167): пять итогов сессий и их записки-планы, все паки залендены. Читать НЕ надо — там история, а не состояние.

Состояние зоны на 30.08 (после лендинга): активного промта НЕТ — пак «писатель книги» ПРИНЯТ И ЗАЛЕНДЖЕН (D39.175, 8adcb86; приёмка: 4 линзы + верификаторы, два дофикса до лендинга; промт отработан — archive/prompts/). Дерево backend/ чисто. Свободная работа зоны — строками бэклога: 238 (деньги слепы к правке исходника на месте) · 239 (checkWave не видит исчезнувшую стадию) · прежние 228 (отклонённая поверхность возвращается алиасом) · 229 (снапшот не фолдит модель внутренних гейтов) · 230 (размен «сходимость против поучения») · 141-остаток · 131 (⚠ строк 231 и 236 в таблице БОЛЬШЕ НЕТ — 231 съел пак «деньги», 236 сужена D39.175; прежняя редакция этого абзаца звала обе, испр. оркестратором №20 30.08). Диспозиция по D25.1 ратифицирована D39.175 п.2 (drift — не дыра файла; лестница — владельцу между паком и дверью). Входная дверь шва — D39.158 (d1eb8a9), пак «тихая порча» — D39.164 (7d0c6f2), пак «деньги» — D39.170, гейт схемы — D39.173.

📝 ЗАПИСКА-ПЛАН — пак «писатель книги» (промт docs/BACKEND_BOOKWRITER_PACK_SESSION_PROMPT.md, строка 236), сессия textmachine-main-fc, 30.08

Что беру (зона backend/, HEAD на старте 67c05be, дерево чисто).

  1. Прод-пакет backend/internal/bookfile (только stdlib — archive/zip, encoding/xml; без import "testing"): container.go — OCF-контейнер (mimetype первым и zip.Store, container.xml, запись entry в порядке вызовов, нулевые таймметки) — chunktest/epub.go переводится на него, его OPF-заглушка и XHTML-декой остаются тестовыми; epub.go — EPUB 3 из нейтральной модели Book{Identifier, Title, Language, Modified, Description, Chapters[]{Title, Paragraphs[]}}: dc:identifier/dc:title/dc:language/dcterms:modified, nav (properties="nav", НЕ в spine), один XHTML на главу, <h1> = заголовок главы, <p> = абзац; txt.go — чистый текст из той же модели (заголовок строкой, абзацы через пустую строку, главы через пустую строку; ни баннеров, ни флагов, ни gapMarker).
  2. Сборка из BookExportbackend/internal/pipeline/bookbuild.go: Runner.BuildBook(formats, partial)Export(false) → дыры → отказ либо файл. Запись writeFileAtomic рядом с ProjectDB (<project_db>.book.<fmt>, как .manifest.json/.bank.json), путь публикуется в StatusArtifacts.BookFiles (book_files: map формат→путь, аддитивно) — приор промта принят: платформа пути не выводит сама (17 §1). Существующий файл — перезапись: производный детерминированный артефакт, как манифест; бэкап отказывает потому, что он точка восстановления, а файл книги пересобирается из стора.
  3. Аддитивные поля tm-export-v1 (форма не меняется, все omitempty): ChunkExport.Heading (heading) — литерал u.Members[0].Heading в момент сборки записи (и у pending-юнита тоже, он из манифеста); BookExport.GhostUnits (ghost_units: [{chapter,chunk_idx}]) — ключи ghost-строк, чтобы маркер стоял в главе, а не только в счётчике; BookExport.TextModified (text_modified, CCYY-MM-DDThh:mm:ssZ) — max(chunk_status.updated_at) по финальным строкам, вошедшим в файл (колонка NOT NULL DEFAULT datetime('now'), store/migrate.go:37; в ChunkStatus дочитывается доп. полем). Это и есть dcterms:modified: последнее изменение отгруженного текста — факт стора, не часов процесса.
  4. Глагол tmctl build --config b.yaml [--format epub,txt] [--out path] [--partial] (по умолчанию оба формата; --out — только при одном формате). Stdout — JSON-конверт tm-build-v1 (пути, счётчики, complete). Новый глагол, а не флаг export: export — чистое чтение в stdout, писать файлы из него — смешать аудит-проекцию с артефактом; manifest — прецедент глагола-писателя сайдкара. dispatchCommands и usage-строка расширяются — контрактное расширение того же рода, что bank-apply (тест TestParseNoArgsUsage сам перечисляет такие расширения); чужим глаголам новые флаги ОТКАЗЫВАЮТСЯ (дисциплина --keys-file/--max-units).
  5. Отказ — новый pipeline.RefusalBookIncomplete = "book_incomplete" → exit 16 (полоса 1019; таблица тотальна по TestTheRefusalTableIsTotal); сообщение перечисляет дыры глава/юнит/причина.
  6. Читательские слова — ДАННЫЕ: <langpack_root>/<target_lang>/reader.txt (key<TAB>value, плейсхолдеры {chapter} {unit} {dropped} {holes} {total} {ghost}), читает ОТДЕЛЬНЫЙ загрузчик lang.LoadReaderWords; в Pack.Version() НЕ фолдится (пин тестом «наличие reader.txt не меняет Version()» + current_snapshot minirun до/после). Ключ — язык ЦЕЛИ, не пара: слова читает читатель целевого языка, и они не зависят от исходного. Поставляю backend/configs/langpacks/ru/reader.txt. Каталог <tgt>/ загрузчик пака не читает (Load — только <src>/ и <pair>/, langpack.go:215-330), так что канал вне фолда по построению, а не по соглашению.

Политика §3.2 — по умолчанию ОТКАЗ, --partial — файл с пометкой; довод:

  • Дыры: pending · withheld (Disposition!="pending" && FinalText=="") · incomplete (DroppedMembers>0 при непустом тексте) — арифметика render.go:573-587 выносится в общий хелпер pipeline, которым пользуется и renderExport (вывод --plaintext побайтово прежний) · ghost — тоже дыра: при укрупнении нарезки строка-лидер несёт текст ПРЕЖНЕГО, более короткого юнита, а остаток источника лежит в ghost-строках и в файл не попадает (acceptance: 57 строк → 37 юнитов, 20 ghost при pending 0 — ровно «молча полная» книга). Позиция ghost внутри главы неизвестна → маркер в конце главы с числом потерянных строк.
  • Default = отказ: D29.1(б) — reader-facing выдача fail-closed; дверь платформы получит --partial для контрактного «may be exported, finished or not» (14 §createExport).
  • --partial: пометка неполноты — первый абзац первого документа spine (то, что читатель видит, открыв книгу) + dc:description; маркер — отдельный абзац на месте КАЖДОЙ дыры (pending/withheld — вместо текста юнита; incomplete — перед текстом юнита, как gapMarker; ghost — в конце главы). Форма — из reader.txt; без пака (acceptance, runner.go:346) — несловесная: ⚠ {chapter}.{unit} у дыры, ⚠ {holes}/{total} в пометке (символ + числа, никакого словаря в Go). В FinalText/export.go маркер не попадает.
  • drift — НЕ дыра: текст файла побайтово текст прогона (export.go, комментарий к exportConfigDrift); попадает в JSON-конверт build и в WARN, в файл — нет («config drift» — операторский словарь). Следствие §4 заявляю сразу: чистого бездрейфового файла на реальной книге на этом HEAD НЕТ — чистый путь доказывается синтетикой, реальные книги — посадки на дыры.
  • Оглавление и <h1> при Heading=="" — номер главы цифрами (пустая ссылка nav невалидна; цифры — единственный лейбл, который не решает открытый К-3 «какой лейбл видит читатель у главы без заголовка»; словесный шаблон в данных — 1 строка после ратификации, вопрос владельцу в отчёте). При Heading!="" — срез известного префикса heading+"\n\n" из FinalText (chunker.go:186-192), <h1> = Heading.
  • Абзац = непустая строка FinalText. Замерено на minirun/export.json: юнит 1/0 — 14 разделителей \n\n и 7 одиночных \n, юнит 2/0 — 56 и 0: редактор чередует их без семантики, различать = выдумать различие; строка — единица абзаца исходника-вебновеллы. Круг §4 сравнивает абзацы ингеста с абзацами, которые положил писатель.
  • Метаданные: dc:title = config.Book.Title как есть (на стенде 蛊真人 — ограничение в отчёт), dc:language = TargetLang, dc:identifier = urn:textmachine:book:<book_id>, dc:creator нет (источника нет).
  • 0 юнитов — отказ sourceHasNoContent (spine без элементов невалиден); 1 юнит — обычная книга.

Что НЕ беру: платформу и дверь createExport/getExport; лестницу D25.1 в коде и в BookExport; строки 160/201 (ApplyHeading и три точки склейки не трогаю; модельные заголовки в прозе не извлекаю и не правлю); --resnapshot и любые платные вызовы; langpack_root в копию acceptance; направление письма (dir/page-progression-direction) — в internal/lang данных о направлении нет (lang-script.txt — только скрипты), RTL-цели в репо нет → вопрос в отчёт, не литерал; CSS/обложку; новые зависимости.

Чем докажу: герметично — bookfile (mimetype первым/stored, nav не в spine, детерминизм двух сборок, экранирование, 0/1 глава), pipeline (круг IngestEncoded равенством абзацев на прогоне fake-провайдера; pending через потолок; withheld через санитайзер; ghost — усадка исходника после прогона (посадки в тестах не было, строю); drift — бамп prompt_version; синтетический BookExport на incomplete), cmd/tmctl (incomplete бинарём через setupGapProject; парс флагов; exit 16 через totality-тест), lang (парс reader.txt; Version() не меняется от его наличия). На копиях книг в песочнице с переписанными путями: minirun — оракул июля 14/14 по final_text/snapshot_id/disposition, current_snapshot до/после reader.txt, cmp двух ПРОЦЕССОВ, epubcheck 5.3.0 0 fatal / 0 error, круг ингестом; acceptance — отказ с перечнем и --partial-файл с несловесными маркерами; coldrun-a — отказ 14/14 pending; git -C books status --short -- gu-zhenren до/после одинаков (снят до старта: 6 строк D …-wal/-shm). make battery + -race; в середине — субагент-ревью готовой части против критериев; в конце — адверсариальный проход по направлениям §4.

ИТОГ — пак «писатель книги» (промт docs/BACKEND_BOOKWRITER_PACK_SESSION_PROMPT.md, строка 236), сессия textmachine-main-fc, 30.08

Что построено (зона backend/, поверх 67c05be; НЕ закоммичено — дерево на лендинг оркестратору; git status: 10 изменённых + 8 новых путей в backend/, плюс этот журнал).

  • internal/bookfile/ (новый прод-пакет, только stdlib, без testing): container.go — OCF-контейнер (mimetype первым, Store, через CreateRaw — без data-descriptor, флаги 0x0000; container.xml; entry в порядке вызовов; нулевые zip-таймметки); epub.go — EPUB 3 (dc:identifier+unique-identifier, dc:title, dc:language, dcterms:modified, nav properties="nav" не в spine, XHTML на главу: <h1> + <p>); txt.go — чистый текст; model.go — модель Book/Chapter, Blocks(i) (единственное определение содержимого документа главы), CleanText (общая чистка XML-недопустимых символов для обоих форматов), экранирование.
  • internal/chunk/chunktest/epub.go переведён на bookfile.NewContainer; тест-декои (OPF-заглушка, <title>c</title><style>) остались тестовыми; 9 импортёров зелёные без правки ассертов.
  • internal/lang/reader.goLoadReaderWords(root, targetLang): <langpack_root>/<target>/reader.txt, читается ОТДЕЛЬНО от LoadPack.Version() не фолдится по построению — Load читает только <src>/ и <pair>/); DefaultReaderWords() — несловесная форма (символ + числа; тест пинит отсутствие букв). Данные: configs/langpacks/ru/reader.txt (7 ключей: hole.{pending,withheld,incomplete,stale,ghost}, notice.{holes,ghost}).
  • internal/pipeline/holes.go — ОДИН предикат дыры UnitHole/HoleCounts (порядок = renderExport); render.go считает шапку --plaintext через него (вывод побайтово прежний).
  • internal/pipeline/export.go — аддитивно (omitempty): ChunkExport.Heading (heading — литерал u.Members[0].Heading, у pending тоже), BookExport.GhostUnits (ghost_units, ключи ghost-строк, сортированы), BookExport.TextModified (text_modified — max chunk_status.updated_at по ФИНАЛЬНЫМ строкам, вошедшим в экспорт); exportConfigDrift: строка со стадией, которой нет в текущем конфиге, — drift (находка 10 ниже). store/chunkstatus.go дочитывает updated_at в ChunkStatus.UpdatedAt (колонка NOT NULL DEFAULT datetime('now'), migrate.go:37; миграции — только ADD COLUMN: у minirun text_modified = 2026-07-25T19:17:53Z, время боевого прогона, не миграции 30.08).
  • internal/pipeline/bookbuild.goRunner.BuildBook(BuildOptions{Formats, Out, Partial}): Export(false)staleUnitsassembleBook (чистая функция, возвращает список дыр) → отказ RefusalBookIncomplete (refusal.go, exit 16) либо стейдж всех форматов + общий коммит в <project_db>.book.<fmt> (не запрошенные соседи удаляются — рядом с БД лежит ОДНА сборка); StatusArtifacts.BookFiles (book_files, map формат→абс. путь; в status --json и manifest --json). --out — только НОВЫЙ файл (существующий путь любого рода, несуществующий каталог → config_invalid, exit 10). Сбой между двумя renamewrite_incomplete (exit 15) с перечнем landed/not landed.
  • cmd/tmctl: глагол build --config b.yaml [--format epub,txt] [--out path] [--partial]; stdout — JSON tm-build-v1 (files, total/pending/withheld/incomplete/stale_units, stale_unknown, ghost_rows, config_drift, complete, text_modified); чужим глаголам новые флаги отказываются, build отказывает --plaintext/--pairs/--json; usage-строка расширена (invocation_test.go — контрактное расширение по собственному комментарию теста «Every one is a deliberate contract extension»; это ЕДИНСТВЕННАЯ правка существующего теста). backend/README.md — строка cmd/tmctl дополнена build.

Политика (§3.2) как реализована — ШЕСТЬ состояний, не пять: дыры — pending · withheld (Disposition!="pending" && FinalText=="", плюс юнит, чей текст после чистки не даёт ни одного абзаца) · incomplete (DroppedMembers>0) · stale (финальная строка сделана под исходник, которого в книге уже нет: content_hash строки ≠ cachedRenderedContentHashes — тот же факт, по которому резюм перекупает юнит; считается ТОЛЬКО без дрейфа, под дрейфом stale_unknown: true, никогда не «нет») · ghost (при укрупнении нарезки строка-лидер несёт текст прежнего, более короткого юнита; остаток лежит в ghost-строках и в файл не попадает: acceptance 57→37, 20 строк при pending 0). По умолчанию — ОТКАЗ при любой дыре с перечнем chapter N unit M: <вид> (<причина>) и ghost-ключами (≤50 строк); --partial — файл с пометкой (первые абзацы первого документа spine + dc:description; в txt — после заголовка книги) и маркером на месте КАЖДОЙ дыры (pending/withheld/stale — вместо текста; incomplete — перед текстом; ghost — в конце главы, счётчиком). drift — НЕ дыра (текст файла = текст прогона): в JSON-конверте и WARN, в файле нет. Оглавление/<h1> при Heading=="" — номер главы цифрами. Абзац — непустая строка FinalText (\r\n/\r/\n). dc:titlebook.yaml как есть (на стенде 蛊真人), dc:language = target_lang (форма тега BCP 47 проверяется, иначе config_invalid), dc:identifier = urn:textmachine:book:<book_id>, автора нет.

Сверка состава против §3 (пункт → сделано → чем доказано; все команды — на копиях в песочнице <SB>/stand, бинарь go build -o <SB>/stand/tmctl ./cmd/tmctl).

§3 Сделано Доказательство
3.1 EPUB + чистый txt из BookExport, ОДИН файл на формат, из tmctl да: tmctl build<project_db>.book.epub / .book.txt build-minirun.json: 2 пути, complete: true; java -jar epubcheck-5.3.0/epubcheck.jar <book>.epub0 fatals / 0 errors / 0 warnings / 0 infos на всех трёх EPUB (minirun, acceptance --partial, coldrun-a --partial)
3.1 без аудит-баннеров/флагов/gapMarker в txt да TestTXTShape, TestBuildBookRoundTrips… (нет === CHAPTER, TEXT MISSING, pending, flagged); TestBuildRefusesTheGapAndPartialMarksIt — реальный c-lite прогон бинарём: ⚠ 1.0 1 перед уцелевшим текстом, ни INCOMPLETE, ни cjk_artifact
3.1 --plaintext не тронут да cmp вывода бинаря из git archive HEAD и нового: IDENTICAL на minirun (171932 б), acceptance (354821 б), coldrun-a (1077 б)
3.1 основа — chunktest/epub.go, OCF в прод без testing да TestEPUBFixtureMimetypeIsOCFConformant и 9 импортёров зелёные без правки; TestContainerIsOCFConformant (флаги 0, extra 0, mimetype на фиксированных смещениях)
3.1 детерминизм двумя ПРОЦЕССАМИ да cmp first/<f> <copy>/<f> — IDENTICAL для 6 файлов (две сборки в двух процессах); zip-таймметки 1980-00-00 00:00; sha256 EPUB minirun 084ff0a9…, совпал с независимой сборкой ревьюера
3.2 пять (шесть) состояний, отказ по умолчанию / --partial да acceptance: build → exit 16 «pending=0 withheld=1 incomplete=1 stale=0 ghost_rows=20 of total_units=37 (stale: UNKNOWN …) · chapter 1 unit 0: withheld (cjk_artifact) · chapter 10 unit 0: incomplete — 1 member(s)… (length) · ghost rows: 1/1 1/3 …»; --partial⚠ 2/37, ⚠ +20, ⚠ 1.0, ⚠ 10.0 1, ⚠ 10 +1…; coldrun-a: exit 16 (14 pending) / --partial со словесными маркерами из reader.txt; minirun (только drift): записан по умолчанию, config_drift: true, stale_unknown: true, в файле нет; тесты TestBuildBookRefusesAPending…, …WithheldUnitIsAHole, …GhostRowsAreAHole (посадка построена: усадка исходника после прогона), …StaleUnitsAreAHole, …DriftIsReportedNotMarked, …RemovedStageIsDrift, TestAssembleBookMarksEveryHoleKind
3.2 не в снапшот да current_snapshot minirun с ru/reader.txt и без — bb0b3b2aaf0d… оба раза (копия корня пака в песочнице); TestReaderWordsDoNotMoveThePackVersion
3.2 книга без langpack — несловесно да acceptance (langpack_root не задан): ⚠ 1.0, ⚠ 10.0 1, ⚠ 2/37; TestReaderWordsAbsentIsTheNonVerbalForm
3.2 маркер не в FinalText/export.go да JSON HEAD vs new: existing equal True, добавлены только text_modified, heading, ghost_units
3.3 ApplyHeading и три точки не тронуты; срез только известного префикса да git diff HEAD -- backend/internal/chunk/chunker.go backend/internal/chunk/ingest.go backend/internal/pipeline/waverun.go пуст; вызов ApplyHeading в export.go — контекстная строка; minirun: 10 заголовков срезаны, круг 402/402; TestAssembleBookMarksEveryHoleKind (упоминание заголовка в тексте не срезается)
3.3 Heading=="" → номер цифрами в nav и <h1> да acceptance nav 125; minirun/coldrun-a — Глава N из heading
3.3-бис пять требований EPUB 3; nav не в spine; dc:language из TargetLang да TestEPUBCarriesTheFiveRequiredThingsAndKeepsNavOutOfTheSpine; OPF minirun: urn:textmachine:book:guzhenren-minirun, 蛊真人, ru, 2026-07-25T19:17:53Z; epubcheck
3.4 место/атомарность/конверт/глагол/коды да status --json/manifest --json копии minirun: book_files: {epub, txt}; TestTheRefusalTableIsTotal, TestDispatchCommandsCoversTheSwitch, TestParseNoArgsUsage; TestBuildBookLeavesOneBuildBesideTheDatabase; TestBuildBookOutNamesANewFile
3.5 платформа не тронута; tm-export-v1 аддитивно; пары — данные; без зависимостей да git status — только backend/ и docs/PROGRESS.md; go.mod не менялся; греп читательских слов по новому Go-коду — только комментарии
§4 make battery (-race) да, 2 настоящих прогона battery-1.log (до правок ревью) и battery-3.log (после всех правок): BATTERY_EXIT=0, 18 пакетов, скипы — три прежних стендовых (TestMinerFullBookParity, TestHelperEventsRun, TestHelperKillLoop). ⚠ «Батарея №2» была ложным прогоном: make из корня репо (No rule to make target), мой echo замаскировал код — поймано по логу, перезапущено из backend/
§4 дифф ^func Test ни один не исчез git diff HEAD -- '*_test.go' | grep '^-func Test' пуст; func Test в backend/: 1017 → 1044 (+27)
§4 круг ингестом равенством да tmroundtrip (собран go build -overlay, файла в дереве нет): minirun 10/10 глав, 402 абзаца; acceptance --partial 25/25, 1568; coldrun-a --partial 10/10, 25
§4 git -C books status до/после см. obstacle 6 строк D …-wal/-shm до; после — 4: у acceptance -wal/-shm ПОЯВИЛИСЬ (идентичны трекнутым; БД не изменена)
§4 хирургия конфигов в копиях список minirun/coldrun-a book.yaml: удалены mined_delta:/mined_rejects:; acceptance pipeline-acceptance.yaml: удалены stm_depth: 2, overlap_tokens: 200, оба prompt:; добавлен acceptance/pairs/zh-ru.yaml (копия minirun/pairs с prompts_root на backend/prompts этого дерева); все абсолютные пути переписаны на песочницу/этот ворктри, греп по копиям пуст; миграции v10/v7/v14 → v16, backups/ — в песочнице
§4 промежуточное и финальное ревью субагентом да, Fable 5 ×2 ниже

Промежуточное ревью (Fable 5, исполнением) — 8 находок, все закрыты: (1) MAJOR: --format-подмножество оставляло соседний формат прежней сборки рядом с БД при равноправном book_files → стейдж всех форматов + общий коммит, не запрошенные соседи удаляются, пин TestBuildBookLeavesOneBuildBesideTheDatabase; (2) text_modified считался по всем строкам всех стадий → только по финальным строкам экспорта (acceptance 20:41:47Z20:40:00Z, coldrun-a — эпоха: ничего не отгружено); (3) пустой title → exit 1 → config_invalid с именем ключа, то же для target_lang не в форме BCP 47; (4) mimetype с data-descriptor → CreateRaw; (5) control-символы срезались только в EPUB → CleanText один раз для обоих; (6) --format epub,epub → дедуп; (7) backend/README.md без build → дополнено; таблицы exit-кодов в docs/ — пинг; (8) подтверждено верным: UnitHole = арифметика renderExport, DispOK с пустым текстом недостижим, нулевые таймметки, reader.txt вне Load.

Финальный адверсариальный проход (Fable 5; overlay-тесты, свой бинарь, epubcheck на adversarial-книгах: краевые символы, RTL, 2000 глав) — 10 находок:

  1. MAJOR — правка исходника НА МЕСТЕ (ключи (chapter, chunk_idx) уцелели, текст под ними сменился) давала файл, побайтово равный прежнему, под complete: true. Исправлено — шестое состояние stale (см. политику; пин TestBuildBookStaleUnitsAreAHole: правка главы 2 → chapter 2 unit 0: stale, глава 1 не задета; после translate — снова whole). ⚠ Побочный факт: projectRebill сверяет content-hash ТОЛЬКО при сдвинутом снапшоте (bank-only ветка), при том же снапшоте строка идёт как «$0 resume» без сверки — проекция денег status слепа к правке исходника на месте, translate при этом перекупает (ревьюер воспроизвёл: «2 units re-bought»). Не моя строка — пинг.
  2. MAJOR — --out перезаписывал что угодно, включая БД проекта («file is not a database») и исходник. Исправлено: --out только для НОВОГО файла; существующий путь / отсутствующий каталог → config_invalid; место рядом с БД по-прежнему перезаписывается. Пин TestBuildBookOutNamesANewFile (БД, исходник, чужой файл, несуществующий каталог; ни одного .tmp- после). Стенд: --out <project_db> → exit 10, БД цела.
  3. MINOR — сбой на фазе коммита второго формата оставлял смешанную сборку и exit 1. Исправлено: write_incomplete (exit 15) с перечнем landed/not landed; комментарий файла говорит правду. Тестом не покрыто («не проверено»: сбой rename в только что записанном каталоге без инъекции не воспроизводится).
  4. MINOR — юнит с непустым FinalText, дающий ноль абзацев (control-символы/U+FFFF), не был дырой. Исправлено: сборщик читает юнит по тому, что тот реально положил (ноль абзацев → withheld); счётчики отчёта — из списка дыр сборщика; HoleCounts остался ровно арифметикой renderExport.
  5. MINOR — голый \r: txt нёс его, XML нормализует → форматы расходились. Исправлено: \r\n/\r/\n — конец строки.
  6. MINOR — --out в несуществующий каталог → exit 1. Исправлено: config_invalid.
  7. NIT — build молча принимал --plaintext/--pairs/--json. Исправлено: отказ.
  8. NIT — dc:title с паддингом vs обрезанный txt. Исправлено: TrimSpace в модели и EPUB.
  9. NIT — ghost-маркер по номеру главы СТАРОЙ нарезки может встать в соседнюю главу при усадке. Не исправлено, задокументировано (assembleBook): книга всё равно помечена неполной, ложна лишь координата; иного источника координаты у ghost-строки нет.
  10. MINOR (унаследовано Export) — удаление стадии edit делало черновики «полной» книгой без дрейфа. Исправлено в exportConfigDrift: строка со стадией, которой нет в конфиге, — drift; под ним stale = unknown; пин TestBuildBookRemovedStageIsDrift. ⚠ Status (checkWave) несёт то же слепое пятно — пинг. Подтверждено проходом как верное: все посадки A (withheld при pending 0, ghost-only, исчезнувшая глава, все юниты withheld, 0 юнитов, HoleCounts = шапка renderExport на всей матрице состояний); детерминизм (нет time.Now/rand/os.Stat/map-итерации в байты; 2 процесса под TZ=Asia/Tokyo LANG=C — идентично); заголовки (срез только известного префикса; pending-первый юнит с заголовком получает заголовок; пустой заголовок недостижим — parseHeading); nav вне spine; круг на трёх стендовых книгах воспроизведён независимо + epubcheck чист на adversarial-книгах; RTL — валиден, без dir, честно неподдержан; 2000 глав — 47 мс/707 КБ, ingest 38 мс; ids/hrefs по индексу; словесных литералов в Go нет; пин Version() подлинный; exit 16 в полосе, таблица тотальна; JSON аддитивен; ApplyHeading и три точки не тронуты; ни один тест не удалён; линтер 0.

Obstacle reporting — что НЕ удалось и что осталось непроверенным.

  • Не проверено — открывается ли в читалке. Читалки на машине нет; «валиден» ≠ «открылся». Проверено ТОЛЬКО валидатором W3C (epubcheck 5.3.0, 0/0/0 ×3) и кругом через собственный ингест движка.
  • Не проверено — чистый бездрейфовый файл на реальной книге. Недостижим на этом HEAD без платного перепрогона (все три копии под config_drift: true); чистый путь доказан синтетикой (TestBuildBookRoundTripsThroughIngestAndPublishesItsPaths: complete: true, stale_unknown: false, без пометок). Следствие: stale-проверка на реальных книгах стенда не сделана (stale_unknown: true у всех трёх — под дрейфом факт неразличим), доказана только харнесом.
  • Не проверено — сбой между двумя rename (находка 3): ветка write_incomplete написана, не исполнена.
  • Не проверено — посадка на incomplete в pipeline-харнесе: реальный member-drop только через бинарь (gap-харнесс cmd/tmctl) и acceptance (10/0, length); в internal/pipeline — синтетический BookExport.
  • Не проверено — направление письма. dir/page-progression-direction не выставляются; данных о направлении в internal/lang нет; RTL-файл валиден, но выровнен слева — честно неподдержано (вопрос 4).
  • Не объяснено — read-only открытие ОРИГИНАЛЬНОЙ acceptance-БД. git -C books status --short -- gu-zhenren до: 6 строк D …-wal/-shm; после: 4 — у acceptance/guzhenren-acc-a.db -wal (0 байт, 13:47:36 +03) и -shm (32 КБ, 13:47:49 +03) появились, идентичны трекнутым (git diff пуст), сама БД (mtime 24.08) не изменена. Мои команды все шли по копиям (project_db/source_file копии — в песочнице, проверено грепом; .lock копии — от миграции 12:56); тесты дерева acceptance-БД не открывают (греп); субагент-ревьюер завершился раньше этого времени. В ListAgents живы ещё три сессии (оркестратор и две, вероятно, полигонные) — кто-то из них открыл оригинал read-only. Файлы НЕ трогал (чужой репозиторий).
  • Опровергнуто (промтом): «глава 1 minirun остаётся "" даже с правилом» — на HEAD у minirun заголовок у всех 10 глав (headings 10, nav Глава 1…Глава 10); "" у всех 25 глав acceptance — подтверждено.
  • Подтверждено: числа промта §4 (minirun 14/14 ok · drift · оракул июля 14/14 по final_text/snapshot_id/disposition; acceptance 37 юнитов · ghost 20 · withheld 1/0 · incomplete 10/0 · drift; coldrun-a 14/14 pending · drift); миграции v10/v7/v14 → v16; epubcheck приносится и работает.
  • Ограничения формы (по промту, не исправлялись): dc:title = 蛊真人 (перевод не выдумывается); автора нет; text_modified — «последняя ЗАПИСЬ» финальной строки ($0-резюм, переписавший строку без изменений, двигает штамп; между сборками детерминизм сохраняется); побайтовый детерминизм гарантирован для ОДНОГО бинаря (другой toolchain Go — иной deflate-поток при тех же документах); ghost-координата — старой нарезки (находка 9); stale под дрейфом — «неизвестно».
  • Самопойманная ошибка: ложный прогон «батареи №2» (см. таблицу).
  • Эхо §7: правок задания релеем владельца не поступало; единственное сообщение оркестратора (подтверждение адресата + напоминания) заказом не является; приор «артефакт рядом с ProjectDB + StatusArtifacts» принят с доводом.

Вопросы владельцу (гейт между этим паком и дверью платформы, D25.1):

  1. Лестница run_complete / structurally_complete / quality_reviewed / publishable: писатель различает ровно «без дыр» (complete: true) и «с дырами» (отказ / --partial с пометкой). Что из лестницы печатать на титуле и в имени файла и какая ступень даёт копию БЕЗ пометки — решение владельца; в код не внесено намеренно.
  2. Лейбл главы без заголовка (К-3): сейчас — номер цифрами. Словесный шаблон — одна строка в reader.txt, если ратифицируется; не сделано, чтобы не решать К-3 данными.
  3. Ghost и stale как дыры по умолчанию: довод — оба дают «молча полную» книгу (acceptance: 20 строк не в файле при pending 0; правка исходника на месте: старый перевод под complete: true). Если владелец хочет «предупреждение, не отказ», — по строке в BuildBook.
  4. Направление письма для RTL-цели: поле данных цели (в reader.txt или рядом), не Go — когда появится RTL-пара.

Пинги оркестратору (чужие зоны, не правил): (а) exit-код 16 book_incomplete в таблицы docs/glossary.md:64 и docs/architecture/14-api-contract/README.md:731,758; (б) docs/architecture/09-target-architecture.md: слой «писатель книги» построен; следующий шаг — дверь платформы createExport/getExport + export_formats из bookfile.Formats; дверь обязана СТРОИТЬ (tmctl build --format <f> [--partial]) и отдавать то, что построила, — не читать файл, лежащий рядом с БД (копия прежней сборки); (в) projectRebill/status слепы к правке исходника на месте при том же снапшоте (перекупка без предупреждения о деньгах) — строка бэклога; (г) Status.checkWave не видит исчезнувшую стадию (то же, что находка 10 у Export) — строка бэклога; (д) строки 160/201 не тронуты, Heading в tm-export-v1 — тот же временный рендер (D39.122 п.2д), помечено в комментарии поля.

📝 ЗАПИСКА-ПЛАН — пак «деньги» (промт docs/archive/prompts/BACKEND_MONEY_PACK_SESSION_PROMPT_2026-08-29.md, D39.165 §1б + строка 231), сессия textmachine-e4, 28.08

Скоуп: backend/ — §3.1 потолок ОБЪЁМА рядом с денежным · §3.2 смета пере-прохода без покупки. platform/ не трогаю (проводка CeilingChapters — не мой заказ, честная граница §0 промта принята).

§3.1 — В ЧЁМ МЕРИТЬ: выходной юнит (ManifestUnit), кандидат (а). Обоснование. Ровно эта гранулярность и есть то, что движок отгружает и что публикует манифест: ManifestUnit строится итерацией по r.outputUnits(chunks) (backend/internal/pipeline/manifest.go:330-357), то есть по тем же editUnit, которыми идёт волна редактуры; units_total манифеста — то самое поле, из которого интейк платформы пишет chapters.units_total (platform/internal/pgstore/readmodel.go:113,166-175, читал не правил). Значит перевод «N глав → M юнитов» у платформы ТОЧНЫЙ, а не оценочный: манифест снимается tmctl manifest за $0 и без ключей (runner.go:239-244models.CheckKeys только if forWrite) ДО первой оплаты. ⚠ Кандидат (в), chunk×stage, отвергнут именно по ловушке, названной в промте. Это биллинговая единица (rebill.go:322), и в ней «10 единиц» — разный объём книги при разной форме конвейера: на юнит приходится len(Members)*nDraftStages + nEditStages позиций (rebill.go:207). Продавая (а) и каппя (в), мы воспроизвели бы дефект §0 слоем ниже. Кандидат (б), чанк, — внутренний артефакт нарезки, покупателю не виден и манифестом не считается. ⚠ Честная оговорка, которую обязан назвать: число юнитов книги зависит от ФОРМЫ конвейера — редакторский конвейер даёт крупные editUnit, черновой-только даёт по юниту на чанк (waverun.go:67-76). Это свойство конфигурации, а не ветвление по паре; но манифест и потолок обязаны сниматься с ОДНОГО деплоя, иначе «10 юнитов» значат разное.

§3.1 — КАК СЧИТАЮТСЯ РЕПИНЫ И РЕТРАИ (прямой ответ на вопрос промта).

  • Ретрай и эскалационный хоп — НЕ считаются. Они внутри юнита: ретрай — итерация цикла попыток (stagerun.go:158-194), эскалация — отдельный runAttempt (escalation.go), но chunk_status на chunk×stage пишется ОДНА (stagerun.go:297-308). Довод по существу: объёмный потолок ограничивает ДОСТАВКУ, денежный — ТРАТУ. Хвост качества (1.5%→23% по D39.165 §1) — факт денежный, и у него уже есть свой потолок; если бы ретраи жгли объём, купивший 10 глав получал бы 8, потому что две главы заикнулись, — то есть платил бы КНИГОЙ за качественный хвост движка. Это ровно та подмена, которую пак и лечит.
  • Репины и $0-резюмы — НЕ считаются. Иначе пере-проход, пере-привязывающий 500 юнитов за $0 (rebill.go:315-320), сжёг бы потолок, не доставив ничего.
  • Правило одной строкой: потолок считает выходные юниты, по которым ЭТОТ прогон сделает хотя бы один провайдерский вызов.

§3.1 — МЕХАНИЗМ: пре-флайт скоуп, а не счётчик в воркере. Допуск считается ОДИН раз ДО волн, по состоянию стора, и даёт множество юнитов-в-работе; волны просто пропускают то, что вне скоупа. Предикат «$0-обслуживаемый» берётся из УЖЕ существующего — того же, которым считает projectRebill/repin, — чтобы объёмный стоп и денежная смета не могли разойтись двумя определениями. ⚠ Почему не счётчик со слотами в воркере (рассмотрено и отвергнуто): волна параллельна (runWave, waverun.go:236-309), и при отказе в слоте конкурентно розданные элементы пропадали бы НАВСЕГДА — при workers=8 и потолке 1 семь юнитов оказались бы пропущены, а освободившийся после $0-репина слот уже некому было бы отдать. Пре-флайт эту гонку растворяет. Грабля LiteLLM исполнена конструктивно: ни один элемент вне скоупа не НАЧИНАЕТСЯ, поэтому пере-бой на один вызов невозможен в принципе, а не по проверке. Грабля OpenHands исполнена: остановка называет свой потолок — в BookResult, в строке лога и в выводе CLI.

§3.1 — ФОРМА ОТВЕТА ЧЕРЕЗ ШОВ: беру решение оркестратора и ПОДТВЕРЖДАЮ его исполнением. Код выхода 0, замороженный словарь (main.go:115-140) не трогается. Проверил то, о чём он просил пингнуть, — не ломает: exit 0 у платформы = статус ПРОГОНА ready (platform/internal/runs/reconcile.go:703-706, читал не правил), а не «книга дочитана»; полоса книги едет событиями юнитов, поэтому дочитанной книга не объявляется и следующую покупку не блокирует. ⚠ Словарь потока НЕ трогаю в этом паке. Новое значение Finished.Outcome было бы минором по правилу runevents.go:29-40, но у платформы неизвестный ВЫХОДНОЙ код читается как отказ (ingest/exit.go:168-169), и множить развилки в чужом пакете без контрактного минора — не мой заказ (§3.3). Различение живёт в отчёте и логе, как и решил оркестратор. Ортогональность цела: --ceiling-usd остаётся кумулятивным книжным капом и судит в Reserve (ledger.go:56-72); объёмный потолок леджера не касается вовсе и живёт до волн. Денег не считает, холдов платформы не двигает.

§3.2 — ФОРМА: чинится СВЁРТКА, а не заводится глагол. Это дешевле всех трёх кандидатов промта. Слепое окно — не в том, что status пишущий, а в том, что он сворачивает НЕ ТО: projectStoredMemory (status.go:815-826) материализует СОХРАНЁННЫЙ глоссарий, то есть фолд ПРОШЛОГО прогона, тогда как ближайший translate пере-сеет банк из ФАЙЛОВ (seedGlossary) и сделает это ДО гейта согласия (bookrun.go: seedGlossary → … → checkRebillConsent). Собственное оправдание комментария — «exactly as it does for translate itself» — неверно: translate правку файла как раз ВИДИТ. Значит сегодня status НЕДО-считывает то, что translate реально выставит, и это денежный дефект, а не отсутствующая функция. Лечение: фолд тех же входов, что берёт seedGlossary (сид + рубя + мined-дельта + авто-банк), — В ПАМЯТИ, без единой записи. status при этом остаётся ЧИСТО ЧИТАЮЩИМ: он читает файлы вместо стора, а фолд не пишет никуда. Возражение оркестратора против «флага у status» снимается тем, что оно стояло на посылке «свёртка идёт через стор» — она не обязана. ⚠ Записи не будет и не может быть: status открывает стор через NewReadOnlyRunnerOpenReadOnly с PRAGMA query_only=1 (store/store.go:117-166), и на состоянии §4.3 (прогон СОСТОЯЛСЯ ⇒ база есть) фолбэк на Open не срабатывает вовсе — записей НОЛЬ, даже first-touch. Родня 124(в) закрывается тем же: status уже считает ре-билл при ЛЮБОМ дрейфе, не только банковом, — то есть после фикса он и есть «оценить пере-проход, ничего не покупая», ради которого поименован resnapshot --dry-run. ⚠ Третий кандидат (bank-apply --dry-run) рассмотрен ПЕРВЫМ, как заказано, и отклонён с доводом: он требует --decisions, а в продуктовом потоке D39.165 §3 решения к моменту продажи УЖЕ на диске — документа больше нет. Плюс он Runner-free и не держит ни статусов, ни манифеста, ни конфига (bankdecisions.go:294-314), то есть под смету пришлось бы втащить в него весь Runner. Ту же проекцию он сможет позвать позже — она будет одной функцией.

§3.2 — ТОЖДЕСТВО БЕСПЛАТНОЙ СМЕТЫ И ПЛАТНОГО ПРОГОНА: доказываю, а не предполагаю. Канонический фолд идёт через стор и там ПЕРЕ-СОРТИРУЕТСЯ: ORDER BY src, sense, since_ch, until_ch, status, dst (store/glossary.go:223). Порядок несущий дважды — MaterializeBank порядок входа НЕ трогает (membank/memory.go:283-346), а дальше он определяет и хеш версии (ComputeVersionScopedIn стримит SHA-256 по строкам в порядке итерации), и ЛИНИИ отрендеренного блока через стабильную сортировку бюджета (memory.go:608-619), которую режет токенный бюджет. Почему тождество ДОКАЗУЕМО, а не правдоподобно: таблица несёт UNIQUE (book_id, src, sense, since_ch, until_ch) (store/migrate.go:203), поэтому префикс из четырёх колонок НЕ МОЖЕТ дать ничью — порядок ТОТАЛЬНЫЙ и полностью определён значениями, а не rowid и не порядком вставки. COLLATE в схеме нет нигде ⇒ сравнение текста побайтное, как и < в Go. Алиасы читаются ORDER BY term_id, alias, внутри записи это сортировка по alias (glossary.go:247-249). glossary.id в хеш не входит намеренно (memory.go:360-363). ⇒ Фолд в памяти обязан: собрать тот же набор значений + отсортировать по (Src, Sense, SinceCh, UntilCh, Status, Dst) + отсортировать алиасы + то же для voices/pairs по их собственным ключам. Проверка — ДИФФЕРЕНЦИАЛЬНАЯ, исполнением: тест гоняет оба пути на одном состоянии и требует совпадения построчно (кроме ID), совпадения Version()/BaseVersion(), совпадения отрендеренных байтов и совпадения самого числа projectRebill. Ассерт равенства, а не «похоже». ⚠ Пишущий путь НЕ трогаю: порядок ВСТАВКИ в seedGlossary остаётся как есть, иначе поехали бы glossary.id и телеметрия injected_ids. Добавляется чистая функция упорядочения для читающей стороны.

Находки по дороге (в блате пака, называю сразу):

  1. projectRebill в status рендерит по НУЛЕВОМУ базовому банку. projectStoredMemory ставит только r.memory, r.baseMemory не ставит НИКОГДА (единственные присваивания — seeding.go:157,159), а ветка репина берёт именно его (rebill.go:167) и молча пропускает позиции при nil (repin.go:130). Следствие: при движении БАЗОВЫХ строк банка status считает всю черновую волну пере-оплатой, то есть расходится с translate — вопреки собственному обещанию status.go:206 «status can never quote a different number».
  2. При snapshot_drift у status память вообще не материализуется: projectStoredMemory зовётся под if !rep.SnapshotDrift (status.go:635), а projectRebill — безусловно при наличии строк (status.go:673), и memoryVersion() при nil отдаёт хеш ПУСТОГО банка (snapshot.go:190-195) ⇒ книга объявляется пере-оплаченной целиком.
  3. Мина omitempty подтверждена исполнением чтения: три РАЗНЫХ состояния — «не запускалось», «посчитано и ноль», «расчёт упал» (status.go:668-681 логирует и оставляет нули) — на проводе неотличимы. Это ровно цена D39.166 п.2. Первые две мой фикс §3.2 снимает по построению (фолд считается безусловно и ставит ОБА банка); третью закрываю формой поля.

НЕ делаю: калибровку $0.03 (строка 202) · цену от объёма исходника · строки 228/230/141/131 · словарь кодов выхода · словарь потока событий · platform/ · коммиты. Незакоммиченную работу полигона не касаюсь.

ИТОГ — пак «деньги» (промт docs/archive/prompts/BACKEND_MONEY_PACK_SESSION_PROMPT_2026-08-29.md, D39.165 §1б + строка 231), сессия textmachine-e4, 29.08

Батарея зоны: make battery21 пакет из 21, 0 FAIL, линтер 0 issues, test -race зелёный целиком. ⚠ Проверяю ПОЛНОТОЙ СПИСКА, а не отсутствием FAIL, и это правило стоило мне двух ложных выводов. Первый «зелёный» прогон был на 20 пакетов из 21 с FAIL в хвосте, который обёртка подала как exit code 0. Сверка: comm -23 <(go list ./...) <(grep -E "^(ok|\?)" <лог>) — пусто. ⚠ И про internal/store. Он дважды ронял батарею (TestTheSeamIsNotChargedToTheStoreOperationBudget, apply migration 14: context deadline exceeded), и я сначала списала это на память — неверно. Проверила как надо: развернула ЧИСТЫЙ HEAD через git archive и погоняла тот же тест в обоих деревьях вперемежку — моё 4/5 падений, HEAD 4/5, то есть от моих правок не зависит. Тест ужимает opTimeout до 150 мс (migrate_test.go:408-429) и под параллельной нагрузкой не укладывается; на разгруженной машине проходит 3/3, и итоговая батарея выше — с ним. Каталог internal/store я не трогала ни строкой. Оркестратору отправлено строкой. Пропущенные тесты, как требует Makefile, называю: TestMinerFullBookParity (нет стендовых данных), TestHelperEventsRun, TestHelperKillLoop (точки входа подпроцессов, вне обычного прогона). Дерево ПОСЛЕ трёх кругов: 20 отслеживаемых файлов правлено (+761/204) и 5 заведено (3106 строк); новых тестов 36 (30 в internal/pipeline, 6 в cmd/tmctl). Числа взяты командами: git diff --stat -- backend/ для правленых (новые в него не входят — они untracked), wc -l для заведённых, grep -c '^func Test' для тестов. Не коммичу — на лендинг. ⚠ Числа выше по тексту, где они расходятся с этими, относятся к ПЕРВОМУ кругу и оставлены как след, а не как состояние. Мутационных посадок 26 (11 на первом круге, 15 на втором и третьем), каждая — на свой пункт, вердикт по ТОПИЧНОСТИ упавшего теста, а не по цвету батареи: снятие сортировки фолда · потолок на единицу больше · снятие допуска в черновой волне · снятие допуска в редакторской · «свободные юниты тратят грант» · возврат к прежней терминальности (воспроизводит перерасход) · !okok && (воспроизводит перерасход) · допуск только лидера (воспроизводит усечённую главу) · фильтр согласия в тождество (воспроизводит отказ законной работе) · перестановка лога замечаний (воспроизводит потерю диагностики) · снятие отказа несогласованной форме конвейера. Все одиннадцать падают, и падает ИМЕННО адресный тест.

Таблица комплектности против §3

Пункт промта Что сделано Каким ИСПОЛНЕНИЕМ подтверждено
§3.1 потолок ОБЪЁМА рядом с денежным Флаг --max-units N у translate; единица — выходной юнит (ManifestUnit=editUnit, units_total манифеста); допуск считается ДО волн (planVolume, backend/internal/pipeline/volume.go), волны не начинают элемент вне скоупа TestTheVolumeCeilingStopsAtWhatWasBought — 5 глав, потолок 2: отгружено ровно 2, res.Volume заполнен, у глав 35 нет ни одной строки chunk_status, вызовов провайдера ровно 4 (2 юнита × 2 стадии)
§3.1 — «проверять ПЕРЕД началом единицы» (грабля LiteLLM) Свойство конструктивное: элемент вне скоупа не начинается вовсе Тот же тест, клауза (3): отсутствие строк у N+1 и точный счёт вызовов; мутация «потолок на единицу больше» (Granted <= MaxUnits) — падают 3 теста
§3.1 — «остановка НАЗЫВАЕТ свой потолок» (грабля OpenHands) BookResult.Volume (VolumeStop{MaxUnits, Delivered, Reworked, Free, LeftFresh, LeftRework} — ⚠ поля ПЕРЕСТРОЕНЫ на втором круге, см. находку 2), строка лога, строка вывода CLI TestAVolumeStopIsNotAMoneyStop — денежный стоп остаётся типизированным *CeilingHalt (exit 4), объёмный не ошибка вовсе и несёт res.Volume
§3.1 — счёт РЕПИНОВ Не считаются: считаются только юниты, по которым прогон сделает ≥1 вызов TestAResumeDoesNotSpendItsVolumeOnFreeUnits — вторая покупка 2 юнитов на книге, где 2 уже сделаны: Free=2, Delivered=2, LeftFresh=1, свежих вызовов ровно 4. Мутация «свободные тратят грант» — тест падает
§3.1 — счёт РЕТРАЕВ Не считаются: ретрай/эскалация внутри юнита TestRetriesDoNotBurnTheVolumeCeiling — провайдер отдаёт finish_reason: length на первом черновике: юнитов всё равно 2, вызовов >4
§3.1 — форма ответа через шов Решение оркестратора исполнено: код выхода 0, словарь main.go:115-140 не тронут, словарь runevents не тронут res.ExitCode()==0 в тесте; сверено чтением platform/internal/runs/reconcile.go:703-706 — exit 0 = статус ПРОГОНА ready, книга дочитанной не объявляется
§3.1 — ортогональность --max-units не касается леджера, резерваций и кумулятивной семантики --ceiling-usd TestAVolumeStopIsNotAMoneyStop; MaxUnits не входит ни в BriefHash, ни в снапшот-пейлоад
§3.2 смета БЕЗ покупки Читающие поверхности сворачивают банк в памяти из тех же входов, что seedGlossary (projectFoldedMemory), вместо СОХРАНЁННОГО глоссария TestABankEditIsVisibleToTheEstimateBeforeAnythingIsBought — прогон состоялся → bank-applyстарая проекция 0, новая ≠0 на ОДНОМ состоянии
§3.2 — $0 абсолютный Ни одного провайдерского вызова Тот же тест: rec.count() не изменился; леджер (committed/reserved) не двинулся
§3.2 — read-only сверх first-touch Ни одной записи Тот же тест: sha256 файла .db до и после совпадает; status идёт через NewReadOnlyRunnerOpenReadOnly с PRAGMA query_only=1
§3.2 — ключей не требует Путь не строит ни одного LLM-клиента (models.CheckKeys только if forWrite) Пин cmd/tmctl/keysfile_test.go не тронут и зелёный
§3.2 — тождество сметы и прогона storeOrder воспроизводит ORDER BY стора; фолд один на оба пути TestTheInMemoryFoldIsIdenticalToTheStoreRoundTripоба пути на одном состоянии: строки, voices, pairs, Version(), BaseVersion() и карта отрендеренных content-hash совпадают. Мутация «убрать сортировку» — падает с топичным «row 0 differs»
§3.2 — мина omitempty rebill_units/rebill_usd больше не omitempty; добавлено rebill_basis (pending/stored/none/failed) TestTheWireTellsFreeFromUnknown — «нечего пере-оплачивать» и «посчитано, и это ноль» на проводе различимы
§3.2 — книга остаётся инспектируемой Отказ фолда не валит чтение: фолбэк на сохранённый глоссарий + честный basis + WARN TestTheEstimateSurvivesABookWhoseFoldRefuses — сид-коллизия: status отвечает, basis=stored
§3.1 — потолок не отказывает законной работе И не даёт обойти порог дроблением Строка ПЕРЕПИСАНА после отзыва первой редакции — см. второй круг, находка 1. Порог судится по ВСЕЙ книге (дробить бесполезно); именованный кап --accept-rebill=X судится по тому, что заплатит ЭТОТ прогон (законная работа не отклоняется); прогон, который не пере-оплачивает ничего, гейта не встречает вовсе TestABoundedRunCannotOutrunTheConsentThreshold (обе стороны на одном состоянии) + TestARunThatRePaysNothingIsNotAskedForConsent (третья ветка). Мутации: порог по прогону · кап по книге · снятие ранней ветки — все три падают адресно
§3.1 — потолок не даёт перерасхода на неполном юните Терминальность = ПОКРЫТИЕ всех ожидаемых позиций (unitFullyRecorded), а не вердикт resolveChunkState TestAFlaggedMemberWithNoEditRowIsNotFree — флагнутый член + ноль edit-строк; без фикса юнит признаётся свободным и оплачивается сверх потолка
§3.1 — неопределённость всегда в сторону «платно» !ok || h != ContentHash ⇒ невоспроизводимый хеш = платно TestAnUnreproducibleHashIsNeverFree (6 состояний, включая skipped и снятую стадию)
§3.1 — допускается ВЕСЬ юнит, а не его лидер Допуск помечает каждого члена TestTheCeilingAdmitsEveryMemberOfAUnit — мелкая нарезка ⇒ 3 чанка в главе; мутация «только лидер» даёт усечённую главу
§3.1 — форма конвейера, где «юнит» двусмыслен planVolume ОТКАЗЫВАЕТ (переводчик последней стадией при живых редакторских) TestTheCeilingRefusesAPipelineWhoseUnitsAreTwoThings; без флага — поведение не меняется
§3.1 — черновой-только конвейер Та же единица, другая форма TestTheVolumeCeilingHoldsOnADraftOnlyPipeline — 1 вызов на юнит, 2 гранта = 2 вызова
§3.1 — стоп назван в выводе CLI Строка с тремя действенными числами + «это ЗАВЕРШЕНИЕ, не пауза» TestRenderTranslateNamesTheVolumeCeiling; необрезанный прогон о потолке молчит
§3.2 — «неизвестно» никогда не несёт числа Решение вынесено в чистую rebillOutcome/projectable TestAFailedBasisNeverCarriesAFigure — таблица на 5 состояний
§3.2 — падающий фолд не уносит свою диагностику Замечания в лог ДО обработки ошибки TestAFailedFoldStillReportsWhatItSkipped
§3.1 — отчёт различает ДОСТАВКУ и ПЕРЕ-ДЕЛКУ (добавлено 2-м кругом) VolumeStop раздвоен на Delivered/Reworked и LeftFresh/LeftRework; грант идёт сперва в новое; приглашение купить — только про никогда-не-доставленные TestAFullyDeliveredBookOffersNothingLeftToBuy (0 доставлено / 1 переделан / 0 к покупке) · TestAPurchaseBuysNewBookBeforeReMakingOldBook (грант уходит в новое, а не в переделку) · TestRenderTranslateNeverSellsWhatIsAlreadyOwned. Мутация «схлопнуть два прохода в один» падает
§3.1 — движок говорит ЮНИТАМИ, не главами (добавлено 2-м кругом) Все строки отчёта и CLI переведены на «units»; главы — слово платформы, конвертирует манифест TestRenderTranslateNamesTheVolumeCeiling + TestAFullyDeliveredBookOffersNothingLeftToBuy пинят формулировку
§3.2 — смета дана и в той единице, которой сайзится покупка (3-й круг) Аддитивное rebill_output_units рядом с rebill_units (chunk×stage); имя rebill_units не тронуто TestTheEstimateIsAlsoGivenInTheUnitAPurchaseIsSizedIn; фикстура специально недегенеративна; мутация «выдать Rows за юниты» падает
§3.2 — один документ = один банк (2-й круг) unsigned_bank_terms считается по ТОМУ ЖЕ банку, что и денежные поля Материализация помнит свои строки (r.bankRows); проверено батареей
§5 ось 3 — детерминизм MaxUnits не входит ни в снапшот, ни в BriefHash; байты не двигаются TestTheVolumeCeilingMovesNoRequestByte — снапшоты обеих волн не сдвинулись, каждое тело обрезанного прогона есть среди тел безпотолочного; мутация «подмешать MaxUnits в снапшот» падает
§3.3 — чего в паке нет Константу $0.03, цену от объёма исходника, строки 228/230/141/131, platform/ — не трогал

Адверсариальный проход по СВОЕЙ готовой работе — что он нашёл

Веер: шесть линз (деньги · тождество фолда · шов · регрессии пака · параллелизм/детерминизм · качество моих же тестов), тяжёлая модель — РОВНО ОДИН агент (денежная линза), остальным попроще; затем по одному независимому опровергателю на каждую находку. Сырых находок 10, после опровержения осталось 7 настоящих. Все семь внёс сам этот пак — приёмке они не видны, поэтому называю первыми.

1. ПЕРЕРАСХОД: юнит с флагнутым членом и без edit-строки считался БЕСПЛАТНЫМ. unitsServedFree спрашивал терминальность у resolveChunkState, а тот отдаёт ChunkFlagged, как только флагнута ЛЮБАЯ строка, — ДО проверки, что все ожидаемые позиции на месте. Юнит, у которого черновик одного члена флагнут, а edit-строки ещё нет (состояние после подписного стопа банка, Ctrl-C или любого обрыва в редакторской волне), признавался терминальным и свободным, проходил БЕЗ списания гранта и потом оплачивался редактором. Прогон платил за юнитов больше, чем куплено, и, поскольку остаток оставался нулём, даже не сообщал об объёмном стопе. Лечение: предикат заменён на unitFullyRecorded — покрытие ВСЕХ ожидаемых позиций строками; полнота и есть терминальность, и именно она предсказывает «вызова не будет». Доказано: TestAFlaggedMemberWithNoEditRowIsNotFree (обрыв редактора на прогоне 1 → флагнутый член + ноль edit-строк; прогон 2 с потолком 1). Возврат к прежнему предикату мутацией — тест падает с «the other unit was judged free and paid for anyway».

2. ОТКАЗ ЗАКОННОЙ РАБОТЕ: гейт согласия судил ВСЮ книгу при обрезанном прогоне. Нашёл сам, до линз. checkRebillConsent стоял ПЕРЕД planVolume и проецировал пере-оплату по всем строкам, тогда как прогон с --max-units 2 пере-оплатит максимум два юнита. Р6 требует согласия на КОНКРЕТНУЮ трату — а тут отказ (или запрос согласия) шёл на деньги, которые никто не потратит. Это ровно то, о чём предупреждает сам rebill.go: «число, которое одобрили и не списали, — это то, из-за чего такие числа перестают читать». Лечение: скоуп считается ДО гейта; СУММА сужена до допущенных юнитов, ПОРОГ оставлен книжным (5% книги — свойство книги, не покупки). Инертно без флага (scope==nil ⇒ фильтр тождественный ⇒ число байт-в-байт прежнее) — это и делает правку ратифицированного гейта безопасной. Доказано на первом круге мутацией «фильтр в тождество». ⚠ Это решение ОТОЗВАНО на втором круге (находка 1 ниже) — читать вместе с ним, а не отдельно.

3. Отказ redrive учил ЛОЖНОМУ факту об движке. Текст говорил «redrive не гоняет книжную волну, которую это могло бы ограничить» — неправда: redrive зовёт TranslateBook (status.go:984). Мой же комментарий четырьмя строками выше говорил обратное и верное. Лечение: у redrive теперь свой текст, называющий НАСТОЯЩУЮ причину (деструктивный сброс ограничен своим селектором, и потолок в юнитах ограничил бы вторую половину команды, читаясь как ограничение целого). Тест дотянут: он проверяет не только имя флага, но и что причина не врёт про адресата.

4. Рефактор seedGlossary терял диагностику падающего прогона. Замечания (пропуск ruby-алиаса по омонимии, дроп строк авто-банка) собирались в gatherBankInputs, но логировались ПОСЛЕ проверки ошибки — то есть на прогоне, который умер на более поздней проверке, они пропадали. До рефактора они писались по месту и доезжали. Лечение: замечания уходят в лог ДО обработки ошибки; gatherBankInputs для этого возвращает частичные входы вместе с ошибкой. Доказано: TestAFailedFoldStillReportsWhatItSkipped; перестановка двух блоков мутацией — тест падает.

5. rebill_basis: failed мог ехать рядом с большим ПОСЧИТАННЫМ числом. Если банк не материализовался вовсе, projectRebill всё равно запускался — против ПУСТОГО банка, поэтому все строки выглядели протухшими и на провод уезжала пере-оплата всей книги, а CLI печатал рядом «цифры ниже нули, потому что их не удалось посчитать». Базис, противоречащий собственным числам, хуже отсутствия базиса. Лечение: решение вынесено в чистую rebillOutcome (+ projectable) — проекция не запускается без банка, «неизвестно» никогда не несёт числа. Табличный тест на все пять состояний; инвариант недостижим из фикстуры (нужен одновременный отказ и фолда, и стора), поэтому он и вынесен в функцию — иначе его нечем было бы держать.

6. Потолок отказывается от формы конвейера, в которой «юнит» — два разных объекта. Если ПОСЛЕДНЯЯ стадия — переводчик, а редакторские стадии есть (конфиг такой порядок не запрещает), outputUnits отдаёт синглтон на ЧАНК, а редакторская волна всё ещё группирует их в юниты: потолок, выданный в синглтонах, допустил бы чанк одного члена, и редактор пошёл бы по юниту с недоделанным черновиком за полную цену. Лечение: planVolume на такой форме ОТКАЗЫВАЕТ громко (без флага — ничего не меняется). Тест + мутация.

7. Мои собственные тесты доказывали меньше, чем обещали — три дыры, все закрыты. (а) Мульти-членный юнит не проверялся ни одной фикстурой (все главы были однопредложенные ⇒ у каждого юнита ровно один член), поэтому цикл по u.Members в допуске был непокрыт: мутация «помечать только лидера» проходила ВСЮ батарею. Закрыто TestTheCeilingAdmitsEveryMemberOfAUnit (мелкая нарезка черновика под крупным редакторским потолком ⇒ 3 чанка в главе); мутация теперь падает с «buyer gets a truncated chapter they paid for in full». (б) Ветка «хеш не воспроизведён ВООБЩЕ» была непокрытаа это направляющий инвариант всего потолка («любая неопределённость — в сторону „платно“»). Мутация !ok || …ok && … проходила батарею. Закрыто TestAnUnreproducibleHashIsNeverFree. (в) Тест тождества фолда сравнивал ТОЛЬКО черновую волну. Путь A не гонял TranslateBook, поэтому строк chunk_status не было, и renderedContentHashes не давал ни одной edit-позиции — а edit-волна ровно та, куда попадают mined-строки фикстуры (базовый банк их исключает). То есть половина, ради которой фикстура и заводилась, не проверялась. Закрыто: перед сравнением идёт настоящий прогон, и покрытие обеих волн теперь АССЕРТИТСЯ, а не предполагается (len(hashes)!=0 от этого не защищал: две черновые карты тоже равны).

ОТДЕЛЬНОЙ СТРОКОЙ, потому что это правка РАТИФИЦИРОВАННОГО контура и она обязана быть видна в акте, а не выводиться из диффа: я тронула гейт согласия D20.2-Q2. ЧИТАТЬ ВМЕСТЕ С НАХОДКОЙ 1 ВТОРОГО КРУГА — здесь описана ПЕРВАЯ, ОТОЗВАННАЯ редакция. Она сужала СУММУ до допущенных юнитов при книжном ПОРОГЕ и защищалась доводом «инертно без флага». Довод верный и неважный: с флагом размер прогона выбирает каллер, и дробление обходило порог. Действующая редакция: порог — по всей книге (дробить бесполезно), именованный кап — по тому, что заплатит этот прогон (законная работа не отклоняется), прогон без пере-оплаты гейта не встречает. Инертность без флага сохранена и в ней: при scope == nil обе проекции — один объект, и число байт-в-байт прежнее.

Опровергнуто и НЕ чинилось (3 из 10): три находки опровергатель снял как уже вылеченные тем же проходом (я чинил по мере поступления, и опровергатели читали уже исправленный код) — они и есть пункты 3, 4 и 7(а/б) выше.

Второй круг приёмки — что нашли и что я с этим сделала

Оркестратор прогнал по паку ещё два аппарата: слепой верификатор (читал ТОЛЬКО заказ и дифф, отчёта не видел) и искателя вне карты отчёта. Плюс я прогнала свой второй код-ревью — шесть линз, тяжёлая модель один агент, по опровергателю на находку. Итог круга: двенадцать настоящих находок, все внесены паком, все вылечены — плюс одна чужая, проверенная и переданная строкой.

1. ОТЗЫВ МОЕГО ЖЕ РЕШЕНИЯ: сужение суммы гейта D20.2-Q2 открывало обход порога дроблением. Первый круг я закрыла тем, что сумму пере-оплаты считаю по допущенным юнитам, а порог оставляю книжным, и защитила это доводом «правка инертна без флага». Довод верный и НЕважный: с флагом каллер САМ выбирает, насколько мал каждый прогон, поэтому --resnapshot --max-units N в цикле пере-оплачивает книгу целиком, ни разу не перейдя порог и ни разу не спросив согласия. Измерено искателем на реальных числах: 30 глав за $0.109200, порог $0.005460, безпотолочный прогон ОТКАЗЫВАЕТ, а --max-units 1 проходит четыре раза подряд по $0.003640. Порог обхода арифметический: покупка ≤5% книги — гейт молчит; на 500-главной вебновелле «10 глав» это 2%. Лечение — разделены два РАЗНЫХ вопроса, а не один компромисс. «Надо ли вообще спрашивать человека» — политика КНИГИ, судится по всей её пере-оплате, которая от размера покупки не сжимается. «--accept-rebill=X» — инструкция каллера о ТРАТЕ, судится по тому, что этот прогон реально заплатит (платформа фондирует этот кап из холда прогона, то есть он размерен покупкой, а не книгой). Отказ печатает ОБА числа: собрать их в одно — и есть способ соврать в любую сторону. Доказано: TestABoundedRunCannotOutrunTheConsentThresholdобе стороны на одном состоянии: потолок 1 без согласия ОТКАЗЫВАЕТ (обход закрыт), а именованный кап $0.002, покрывающий собственный счёт прогона ~$0.00182, ЧЕСТЁН (законная работа не отклонена).

2. VolumeStop не различал ДОСТАВКУ и ПЕРЕ-ДЕЛКУ — и это была нехватка модели, а не сбой счётчика. Один счётчик на оба вида оплаченного юнита давал ложь, на которую оператор действует: книга переведена на 100%, банк подвинут, покупка №1 печатает «29 остались», №2 — «28», ни одной новой главы не создано, exit 0 и ready подтверждают успех. А CLI подавал остаток как «что осталось КУПИТЬ». Лечение — переделан тип, а не подлатан счёт. Юнит классифицируется тремя состояниями (unitFresh / unitFree / unitRework), и обе половины отчёта раздвоены: Delivered/Reworked и LeftFresh/LeftRework. Приглашение купить произносится ТОЛЬКО про никогда-не-доставленные юниты; покупка, целиком ушедшая в переделку, обязана это сказать. Раздвоение бесплатно: оно падает из того же теста полноты позиций, которым считается «бесплатно». Доказано: TestAFullyDeliveredBookOffersNothingLeftToBuy (0 доставлено, 1 переделан, 0 никогда-не-доставленных, остаток назван пере-проходом) + TestRenderTranslateNeverSellsWhatIsAlreadyOwned (строка CLI не предлагает купить то, чем уже владеют).

3. status/export начали читать авто-банк, который писался НЕ атомарно. Дыра, которую пак открыл в чужом файле: до него авто-банк читал только тот прогон, который его и писал, поэтому os.WriteFile с усечением был безопасен. Как только читающие поверхности стали сворачивать банк сами, файл попал в класс, ради которого существует artifact.go, — и окно усечения даёт либо ошибку разбора (покупателю устаревшие цифры), либо валидный ПРЕФИКС списка термов: фолд банка, которого не существовало, и rebill_units, который ни один прогон не выставит. Лечение: writeFileAtomic, как у трёх соседей; авто-банк вписан в перечень сайдкаров в шапке artifact.go. Доказано: TestTheAutoBankIsWrittenAtomically — инструмент inode (переименование меняет его ВСЕГДА, запись на месте — никогда; сильнее сверки байтов).

4. Пин согласия statustranslate покрывал только беспотолочный случай. Механическая правка сигнатуры протащила туда nil, и расхождение под потолком пин бы не поймал. Дописан второй ассерт: под объёмным потолком отказ гейта обязан по-прежнему цитировать КНИЖНОЕ число — то самое, которое печатает status, — потому что докстринг status.go обещает это дословно.

5. Отказ денежного потолка съедал объёмный отчёт. Когда прогон встаёт по деньгам, результата нет, и оператор не узнаёт, что ему было выдано и сколько успело доехать. Добавлена строка WARN на этом пути: стоп ниже — НЕ объёмный, вот что было выдано и что осталось недоставленным.

6. Инструмент «ничего не записано» был слеп к WAL — и, дотянутый, сразу поймал факт. Дайджест мерил только основной файл, а SQLite в WAL кладёт коммит в -wal. Дотянула — и увидела изменение. Разобрала, а не подогнала: данные не двигались (основной файл байт-в-байт), а появились ПУСТОЙ -wal и -shm: так устроен любой WAL-читатель. Поэтому ассерт теперь точный: основной файл неизменен И журнал не несёт ни одного кадра; -shm не проверяется намеренно, требовать его отсутствия значило бы требовать от SQLite невозможного. Гарантию держит query_only, дайджест — подтверждение.

Косметика того же круга: висячие ссылки на bankfold.go/bankfold_identity_test.go исправлены на реальные bankmaterialize* · backend/README.md (позиция №2 онбординга зоны) теперь знает про ВТОРОЙ потолок, его ортогональность денежному, «стоп = завершение» и предупреждение про майнящие книги · в volume.go явно записано, что нулевое значение unitClass обязано быть unitFresh (пустая карта = книга, которую не гоняли).

7. ПОТОЛОК ТРАТИЛ ПОКУПКУ НА ПЕРЕ-ДЕЛКУ ВПЕРЁД ДОСТАВКИ. Допуск шёл одним проходом в порядке книги, а после правки банка уже доставленные юниты — это как раз РАННИЕ. Воспроизведено ревью: покупка 2 юнитов на пятиглавой книге с двумя доставленными пере-делала главы 12 и не начинала главу 3 — Delivered=0, Reworked=2, LeftFresh=3. Деньги списаны, книга не сдвинулась ни на главу, а три никогда не переводившиеся главы остались нетронутыми. Лечение: грант идёт СНАЧАЛА в новое, и только потом в переделку. Безопасно потому, что байты юнита не зависят от того, какие ДРУГИЕ юниты шли: липкая выборка считается по ВСЕЙ книге до обеих волн (precomputeSticky), поэтому юнит 3 раньше юнита 1 рендерится ровно так же. Размен назван, а не спрятан: покупка, ЦЕЛЬЮ которой был пере-проход, теперь потратит грант на недоставленные главы, если они есть. Это правильное умолчание — непрочитанная глава ценнее пере-сделанной, а пере-оплату и так ограничивает гейт согласия, — но это УМОЛЧАНИЕ, и я выношу его оркестратору как выбор, а не как факт.

8. МОЯ ЖЕ СТРОКА СТОПА СООБЩАЛА ЮНИТЫ КАК ГЛАВЫ. «%d NEW chapter(s) delivered» печаталось поверх счётчика, который инкрементится на editUnit, — а глава это больше одного юнита всякий раз, когда нарезка закрывает юнит по редакторскому потолку, и много юнитов в черновом-только конвейере. То есть подмену «юнит↔глава», ради устранения которой пак и заведён, совершал отчёт самого пака — и мой же тест пинил эту формулировку как инвариант. Воспроизведено: одна глава, три юнита, потолок 2 → «2 NEW chapter(s) delivered» на книге из ОДНОЙ незавершённой главы. Лечение: движок говорит только «units», везде. Главы — слово ПЛАТФОРМЫ, и конвертирует их она, манифестом. Тесты пере-пинены на верную формулировку.

9. Один документ status описывал ДВА банка. Денежные поля (rebill_*) считались от свёртки файлов решений, а unsigned_bank_terms — по-прежнему от СОХРАНЁННОГО глоссария. Оператор, спрашивающий «есть ли что подписать, прежде чем платить дальше», получал ноль, тогда как ближайший translate уже собирался инжектить неподписанную строку из авто-банка и оплатить изменённый ею юнит. Лечение: материализация запоминает строки, из которых собрана, и счёт неподписанных идёт по ТОМУ ЖЕ банку. Один документ — один банк.

10. Цифры в отказе гейта были СМЕШАННОГО происхождения. В книжную фразу вклеивался скоупный Repinned, то есть в предложении, где все остальные числа книжные, стояло меньшее число из другой проекции. Две линзы поймали независимо — что смешанные провенансы в одном предложении и производят. Лечение: каждое число берётся из той же проекции, что и фраза; скоупная оговорка несёт скоупный ре-пин.

11. export ОТКАЧЕН — и это отказ от собственной правки, а не находка чужого. Я перевела его ConfigDrift на свёртку «за компанию» со status. Но это поле читает полигонная экстракция, и её вопрос ДРУГОЙ: «согласован ли ЭТОТ документ с прогоном, который его произвёл». Экспорт, байты которого — ровно то, что отгрузил прогон, измерим и при лежащем рядом неприменённом файле решений; свёртка помечала бы такой экспорт дрейфующим и тихо дисквалифицировала бы здоровые замеры в чужой зоне. Пере-определять чужое потребляемое поле как побочный эффект своего заказа — не моё право. Расхождение теперь ЯВНОЕ и запинено TestExportAndStatusAnswerDifferentDriftQuestions, чтобы следующий не «починил» его обратно.

12. Дыры в моих же тестах, найденные второй линзой качества: (а) ни один тест не звал CLI-translate с --max-units — то есть единственная строка, которая проводит флаг в движок (r.MaxUnits = maxUnits), была не проверена вовсе, и её удаление оставило бы всю батарею зелёной, пока tmctl translate --max-units 2 переводит книгу целиком. Закрыто TestTranslateWiresMaxUnits по образцу соседнего TestTranslateWiresAcceptRebill; мутация «убрать проводку» падает с точным сообщением. (б) ветка «прогон не пере-оплачивает ничего» не была покрыта — её удаление проходило всю батарею, а она ровно то, что не даёт гейту отказать законной работе. Закрыто TestARunThatRePaysNothingIsNotAskedForConsent (состояние строится через ResetChunkStages, как делает redrive). (в) export после правки банка не был покрыт ничем — теперь покрыт, вместе с решением о расхождении.

13. И находка НЕ из моей зоны, проверенная как положено. internal/store дважды уронил мою батарею (TestTheSeamIsNotChargedToTheStoreOperationBudget, apply migration 14: context deadline exceeded). Я этот каталог не трогала ни строкой. Развернула ЧИСТЫЙ HEAD (git archive) в отдельный каталог и погоняла тот же тест в обоих деревьях вперемежку по пять раз: моё падает 4/5, HEAD падает 4/5 — от моих правок не зависит. Причина в самом тесте: он ужимает opTimeout до 150 мс (migrate_test.go:408-429), и под параллельной нагрузкой одиночный ALTER в него не укладывается. Оркестратору отправлено строкой; сама не чиню — чужая зона. ⚠ И правило, которое из этого следует, шире случая: ЗЕЛЁНАЯ БАТАРЕЯ — ЭТО ПОЛНЫЙ СПИСОК ПАКЕТОВ ПЛЮС ОТСУТСТВИЕ FAIL, а не отсутствие FAIL. Мой первый «зелёный» прогон был на 20 пакетов из 21, с FAIL в хвосте, который обёртка подала как exit code 0. Сверяю против go list ./... теперь всегда.

И одна поправка к моему же первому отчёту. В записке-плане я написала, что предикат «бесплатно» — «тот же, которым считает projectRebill, чтобы они не разошлись двумя определениями». Это НЕВЕРНО и я поправляю: projectRebill намеренно игнорирует ось СОДЕРЖИМОГО (его собственный докблок это и говорит — правка исходника двигает content_hash, но не снапшот, и там она невидима), а предикат потолка сверяет отрендеренный хеш на КАЖДОЙ строке. То есть они расходятся, и расходятся в безопасную сторону: потолок считает платным то, что смета считает бесплатным. Предикат написан против ИСПОЛНИТЕЛЯ (runStage), а не заимствован у проекции, и в volume.go это теперь записано явно.

Третий круг — ратификация ОПУСАМИ трёх развилок, где я сама не была уверена

Владелец снял потолок на веер и назвал главное: ратификаторы — опусы, особенно на важном. Поэтому три развилки, которые я не имела права закрыть своим словом, ушли трём опус-судьям с мандатом «настаивай на своём, а не соглашайся». Плюс второй код-ревью в шесть линз с опровергателями (15 сырых находок, 4 пережили). Модель каждому агенту задавалась ЯВНО.

Развилка 1 — «капнутое согласие: дыра или согласие?» → ВЕРДИКТ: ЗДОРОВО, менять нечего. Ревьюер показал цикл: --resnapshot --max-units 1 --accept-rebill=0.002 четыре раза пере-оплачивает книгу целиком, ни разу не перейдя порог. Ратификатор воспроизвёл цикл СВОИМ прогоном и разобрал по существу: (а) каждый прогон явно называет сумму и списывает ровно её (замерено: заявлено $0.001820 — списано $0.001820); (б) каждый прогон ПИШЕТ рядом книжную цифру и порог, то есть каллеру прямо сказано, что книга выкупается по кусочку; (в) суммарно цикл не достигает ничего, чего одиночный голый --accept-rebill не достигает за один вызов; (г) кумулятивный денежный потолок дроблением не обходится. Это Р6 в чистом виде — согласие на КОНКРЕТНУЮ трату, данное явно и многократно.Его же рекомендация принята: свойство, которое делает это согласием, а не дырой, — раскрытие — раньше не было запинено ничем. Теперь есть TestAConsentedSliceIsAlwaysToldWhatTheBookCarries; мутация «убрать книжные цифры из строки согласия» падает.

Развилка 2 — «денominация двух половин пака» → ВЕРДИКТ: ДЕФЕКТ, ЧИНИТЬ. И он измерил, а не вывел: на трёхглавой фикстуре один документ status --json нёс rebill_units: 15 двумя строками ниже total_units: 6. Все остальные «units» в документе — ВЫХОДНЫЕ юниты (total_units, прогресс, chapters[].units_total), а rebill_units единственный считает chunk×stage, и коллизия сидит в самом слове. Поделить нельзя: отношение len(Members)·nDraftStages + nEditStages меняется от юнита к юниту ВНУТРИ книги, а его множители на провод не ходят вовсе. Траектория: платформа берёт смету, которую пак сам просит вернуть в аллоулист, и передаёт это число в --max-units — покупает втрое больше книги, чем собиралась. Дефект пака, воспроизведённый слоем ниже, ровно тот, ради устранения которого пак заведён. Лечение — его форма, аддитивная: rebill_units НЕ переименован (устоявшееся имя, смысл не менялся), рядом заведено rebill_output_units — та же пере-оплата в той единице, которой сайзится покупка. Человеческий рендер печатает обе с подписями. RebillProjection.OutputUnits считается по лидерам затронутых юнитов там же, где инкрементится Rows. Доказано: TestTheEstimateIsAlsoGivenInTheUnitAPurchaseIsSizedIn — фикстура специально сделана недегенеративной (правка КОНФИГА, а не банка: банковая правка двигает только редакторскую волну и обе денominации совпали бы, и тест ничего бы не доказал); мутация «выдать Rows за выходные юниты» падает.

Развилка 3 — «безопасно ли ставить доставку впереди переделки» → ВЕРДИКТ: ЗДОРОВО, и обосновано замером, а не рассуждением. Ратификатор проверил три вещи исполнением. (а) Порядок безопасен: precomputeSticky — чистая функция от (чанки, банк, бюджет), считается ДО допуска и потребляется позиционно, поэтому инъекция чанка i не зависит от того, шёл ли чанк i1; редакторская волна берёт только СВОИ члены и делает свежий Select с nil-sticky. Он прогнал книгу, где глава 4 переведена и отредактирована в прогоне, где глава 1 не запускалась вовсе, — тела запросов дословно совпали с телами прямого сплошного прогона. Проверил и остальные кандидаты на кросс-юнитную связь: стоп майнинга строит кандидатов по ВСЕМ чанкам (от скоупа не зависит), свёртка банкнот — множественная (порядок не важен), счётчики событий засеиваются книжно и инкрементятся под once-key. (б) A/B на одной книге, четыре покупки по 2 юнита: доставка-вперёд отдаёт 6/6, порядок книги — 4/6, причём при порядке книги две покупки подряд печатали «Still in the book: 4 unit(s) NEVER delivered» не сдвинувшись. (в) Дверь пере-прохода не сломана: на полностью доставленной книге доставка-вперёд ЕСТЬ порядок книги (свежих юнитов нет), то есть чистый пере-проход работает как прежде. ⚠ Его требование выполнено — и оно было существенным: это не живой дефект, а ТРОПА ГНИЕНИЯ. Схлопывание двух проходов обратно в один оставляло батарею ЗЕЛЁНОЙ, то есть следующая сессия, «прибирающая» цикл или добавляющая четвёртый класс юнита, тихо вернула бы дефект. Закрыто TestAPurchaseBuysNewBookBeforeReMakingOldBook; мутация «схлопнуть в один проход по порядку книги» падает — и падает ровно на вторичном следствии, которое ратификатор и предсказал: при порядке книги та же покупка не просто перераспределяется, а ПОЛУЧАЕТ ОТКАЗ гейта согласия.

Дополнительно из второго ревью (пережили опровержение и вылечены):тройное повторение самого дорогого расчёта. Обрезанный прогон пере-рендеривал всю книгу до трёх раз: в planVolume и в каждой из двух проекций гейта, при том что между ними ничего не менялось. Заведён мемо, срок жизни которого — жизнь БАНКА: materializeBanks его сбрасывает, потому что переживший свой банк мемо отдал бы хеши банка, которого у прогона больше нет, — ровно тот класс тихой неверности, ради устранения которого пак и существует. Мемо — скорость, а его инвалидация — корректность, поэтому запинена именно она (TestTheWireHashMemoDiesWithItsBank). — предупреждение про майнящие книги не было покрыто ничема незакрытое тестом предупреждение молча перестаёт эмититься. Закрыто, вместе с обратной стороной: на книге БЕЗ потолка оно не должно возникать.

Четвёртый круг — денежный охотник приёмки: 6 находок, 3 вылечены, 3 переданы

1. БЛОКИРУЮЩАЯ, и она пробивала саму цель пака — ВЫЛЕЧЕНА. planVolume классифицирует ДО черновой волны, но между волнами стоит стоп майнинга, который пере-сеивает банк прямо посреди прогона (mining.go, ветка авто-продолжения), после чего waverun пере-считывает edit-снапшот. А free-юниты допускаются ВНЕ гранта — потому что бесплатная работа ничего не стоит. Значит каждый из них судился по снапшоту, который прогон сам же и заменил, и любой, чьи инжектируемые байты новый банк изменил, получал свежий ПЛАТНЫЙ вызов редактора, не разрешённый никаким грантом, — а строка отчёта называла его «rode along at $0». Охотник замерил: 4 вызова при гранте 1, $0.007280 объявлены бесплатными. Лечение — не гард, а ПЕРЕ-ПЛАН: вопрос «бесплатен ли юнит» задаётся заново, против снапшота, который стал реальным, в последний момент перед редакторской волной — то есть «проверять перед единицей» по-прежнему держится. Ставший платным берёт слот, если он есть; если нет — его редактура НЕ идёт, и он честно отчитывается как доставленный-но-не-пере-сделанный. ⚠ И сделано СТРУКТУРНО, а не вызовом: волна ОТКАЗЫВАЕТСЯ работать со скоупом, спланированным против другого снапшота. Без этого удаление вызова пере-плана оставляло всю батарею зелёной, а потолок молча переставал держать — я это проверила мутацией. Теперь удаление вызова роняет прогон с адресным сообщением. Доказано: TestFreeUnitsAreReJudgedWhenTheBankMovesMidRun (снапшот не двигался → ничего не меняется; двигался → ни одного «free», ровно один слот занят, остальные удержаны и отказаны allowsUnit) + TestTheEditWaveRefusesAStalePlan. Две мутации. ⚠ Своей фикстурой конечное следствие я не воспроизвела — ПЯТЬ попыток, — и разбор этого провала оказался ценнее самих попыток. Две причины, обе названы приёмкой и обе проверены мной на своём дереве. Причина 1: я искала не на той стороне дельты. У mined-дельты две стороны. WHICH (список термов) майнится из исходника ВСЕЙ книги — он полон после первой покупки и больше не двигается; отсюда мой неверный вывод «однородный источник ничего не даст». А байты банка двигает WHATdst каждого терма, и она draft-side: складывается из банкнот, которые модель уже выдала (mining.go:109), то есть растёт с каждой покупкой ДАЖЕ при полностью однородном источнике. Я меняла ТЕКСТ глав, а надо было менять то, что ПРЕДЛАГАЮТ ЧЕРНОВИКИ. Причина 2, из-за которой попытка (5) не могла сработать в принципе, — спойлер-гейт since_ch (membank/memory.go:640-647, жёсткое chapter < since_ch). Вводя терм поздними главами, я выталкивала его since_ch за пределы уже доставленных — и он не попал бы в их инъекцию НИКОГДА, какой бы dst потом ни получил. ⚠ Условия тянут в РАЗНЫЕ стороны: естественный способ заставить дельту расти (поздние главы вводят новый терм) ровно этим и убивает достижимость. Дефекту нужна ОБРАТНАЯ асимметрия: терм присутствует в РАННЕМ исходнике, а его рендеринг приходит поздно — то есть асимметрия ПОВЕДЕНИЯ МОДЕЛИ, а не текста. Пере-проверила зондом приёмки у себя: 方源 dst="" since_ch=3dst=Фан Юань since_ch=3, банк двинулся, а content_hash главы 1 MOVED=false, вызовов ровно два. То есть мой прогон был верен, а гипотеза о причине — нет. ⚠ Диагностика на будущее, две строки: дампить авто-банк между покупками и смотреть у терма ДВА поля — что dst перешёл из пустого в непустой и что since_ch ≤ номера уже доставленной главы. Второго я не проверяла.

Сценарный тест теперь естьTestAMidRunBankMoveNeverBillsBeyondTheGrant (рецепт приёмки: четыре главы, побайтово одинаковые, различаются только банкнотами). Я пере-проверила его двумя своими посадками, а не приняла на слово: снятие вызова пере-плана падает структурным отказом; снятие вызова И гарда воспроизводит дефект целиком — 4 вызова вместо 2, $0.007280 вместо $0.003640, обе уже купленные главы пере-отредактированы, и отчёт зовёт их «2 rode along at $0». ⚠ Оба пина стоят рядом и не заменяют друг друга (различение оркестратора, точнее моего): инвариантный утверждает «пере-план вызывается», сценарный — «покупатель не платит второй раз», а платит покупатель именно за второе. ⚠ Жёсткое равенство == 2×грант оставлено намеренно: гейт терминолога в фикстуре выключен явно, счёт детерминирован, и равенство ловит не только перерасход, но и молчаливую ПОТЕРЮ оплаченной работы. ⚠ Условие достижимости УЗКОЕ, и это записано с обеих сторон: нужна конъюнкция трёх условий (терм на WHICH-списке · его dst приходит поздно · since_ch покрывает уже доставленную главу). В фикстуре приёмки два терма из трёх её не выполняют и остаются инертными. Оценку «покупка №50 переоплачивает 490 юнитов» автор находки признал ПОТОЛКОМ ТЯЖЕСТИ, когда сработало, а не ожидаемым случаем; частоту на реальной книге никто не мерил. На диспозицию не влияет — лечение структурное и покрывает класс независимо от узости входа.

2. Флагнутый юнит объявлялся доставленным — ВЫЛЕЧЕНА. Допуск решается ДО работы (этим и ограничиваются деньги), но решение ЗАПЛАТИТЬ за юнит — не факт существования главы: юнит может вернуться флагнутым и не отгрузить ничего. Отчёт печатал «2 NEW unit(s) delivered» поверх одного читаемого юнита. Лечение: счётчики выравниваются ПОСЛЕ волн, по фактическим исходам (reconcile), и заведён отдельный счётчик «оплачено, но флагнуто» с прямой формулировкой: деньги потрачены, текста нет, покупкой не чинится — это redrive. Тест + мутация.

6. Подсказка обещала то, чего грант не сделает — ВЫЛЕЧЕНА. rebill_output_units подавался как «та единица, в которой считает --max-units» — правда, и в одиночку вводит в заблуждение: грант идёт СПЕРВА в недоставленное, поэтому на книге, где оно есть, --max-units N доставит новое и не пере-сделает ничего. Оговорка была в коде, но не там, где читает оператор. Теперь в подсказке. Тест.

3 и 4 — ПОДТВЕРЖДАЮ, НЕ вылечила, и говорю почему. Обе об одном: ось «свежий/пере-делка» выведена из ПОЛНОТЫ СТРОК, а не из факта отгрузки. Добавление стадии делает доставленную книгу «никогда не доставлявшейся» (#3); юнит, прерванный между волнами, второй раз считается свежим и тратит слот повторно (#4). Правильный носитель у движка уже есть — реестр анонсов (events_outbox.once_key, unitOnceKey = книга+волна+юнит), то есть собственное определение «этот юнит был отгружен читателю», монотонное на всю жизнь книги. Но читающего метода у стора нет (есть только EnqueueOnce, который ПИШЕТ), а internal/store я не трогала ни строкой за весь пак и не считаю правильным открывать его в хвосте четвёртого круга. Это отдельный заказ на одну функцию чтения + перевод оси на неё. ПОПРАВКА к моей же формулировке, внесена оркестратором при приёмке и принята. Я написала «деньги целы: ошибается слово, а не потолок». Слишком мягко — слово тут ПРОДАЁТ. Отчёт, называющий дочитанную книгу «3 unit(s) NEVER delivered», через строку CLI приглашает их купить, и покупатель платит за уже полученное. Деньги целы В ДВИЖКЕ — потолок держит, счёт вызовов верен, — но не в том, что увидит платформа и предъявит покупателю. Диспозиция не меняется (предмет отдельный, internal/store в хвосте пака не открываю), но цена ошибки — покупательская, а не редакторская, и в строке заказа стоит именно так.

5 — цифру принимаю, договорённость в силе, но она теперь важнее. Терминолог переигрывается каждой покупкой: три покупки по 1 юниту дали три полнокнижных консолидации по usd=0.005460 каждая, при том что сам юнит дешевле. Накладные масштабируются КНИГОЙ, а не грантом — книга на 500 юнитов, проданная по одному, оплатит 500 полнокнижных проходов. Мы согласились, что место этой траты — в цене; при мелкой нарезке продажи она перестаёт быть накладной и становится основной статьёй, и цена обязана это знать.

Сверка по буллетам промта — что закрыто и чем

§3.2, «родня 124(в)» — заказано сказать ПРЯМО, говорю: да, моя форма закрывает и resnapshot --dry-run. status считает ре-билл при ЛЮБОМ дрейфе, не только банковом (status.go: проекция идёт при наличии строк, а не под ConfigDrift), поэтому после починки свёртки он И ЕСТЬ «оценить пере-проход, ничего не покупая» — ровно та способность, ради которой строка 124(в) поименована будущей дверью. Отдельного глагола resnapshot --dry-run заводить не нужно. Это удешевляет проект на один глагол и один документ.

§3.2, «ключей не требует» — закрыто структурно, а не тестом, и вот почему это правильно: models.CheckKeys вызывается ТОЛЬКО под if forWrite (runner.go:260-266), а status/export идут через NewReadOnlyRunner. Своего глагола пак не завёл, поэтому пин keysfile_test.go, перечисляющий читающие глаголы, покрывает мой путь без изменений — и он зелёный (6 тестов). Новый тест здесь ничего бы не доказал сверх пина.

§5 ось 2 («пара, которой в репо нет») — проверено: в volume.go и bankmaterialize.go ветвлений по паре/книге нет. Единственное упоминание языка — lang.TargetChecksFor(r.Book.TargetLang), и это ДАННЫЕ: лукап по встроенным файлам target-<lang>.txt (lang/embedded.go:106-118), а не свитч. Строка перенесена из seedGlossary дословно, новой пар-логики пак не вносит. Пара, которой в репо нет, работает добавлением файла данных.

§5 ось 3 (детерминизм) — была заявлена без доказательства, теперь доказана: TestTheVolumeCeilingMovesNoRequestByte — снапшоты обеих волн не двигаются от установки потолка, и КАЖДОЕ тело запроса обрезанного прогона встречается среди тел безпотолочного (в том числе когда потолок отдаёт юниты ВНЕ порядка книги). Мутация «подмешать MaxUnits в снапшот» падает с точным сообщением. Это несущее: сдвинь потолок снапшот — и передача флага пере-покупала бы всю уже оплаченную книгу.

§3.3, соседи — называю строкой, не чиню:redrive зовёт TranslateBook по ВСЕЙ книге (status.go:926): своя денежная неожиданность, была до пака. Флаг --max-units я ему сознательно не дал, отказ несёт настоящую причину. — мёртвая переменная manualSrcs в прежнем seedGlossary (писалась, не читалась никем) — исчезла при выносе гathera; ничего с ней не потерялось, проверено грепом по старой версии. — джоб-гард не отличает банк-онли-движение от смены конфига (stagerun.go:47-59): он и есть корень хвоста про майнящие книги. Ратифицированный Р6-контур, чужой предмет — не трогала.

Диспозиция ВСЕХ находок ревью — 25 сырых, ни одна не потеряна

Сведено из журналов двух ревью-воркфлоу (10 + 15 сырых находок) плюс трёх опус-ратификаций. Каждая строка — либо ВЫЛЕЧЕНА (с тестом и мутацией), либо ОТКЛОНЕНА с доводом, либо НАЗВАНА и НЕ вылечена с указанием, почему и чей это предмет. Пустых клеток нет намеренно: находка без диспозиции — это находка, которую следующая сессия найдёт заново.

# Находка Диспозиция
1 Отказ --max-units учил ЛОЖНОМУ факту про redrive свой текст с настоящей причиной + тест, проверяющий, что причина не врёт про адресата
2 Рефактор seedGlossary терял замечания падающего прогона лог ДО обработки ошибки; тест + мутация
3 Мульти-членный юнит не покрыт ни одной фикстурой мелкая нарезка (3 чанка в главе); мутация «допускать лидера» падает
4 Ветка «хеш не воспроизведён ВООБЩЕ» не покрыта TestAnUnreproducibleHashIsNeverFree, 6 состояний
5 Тест тождества сравнивал только черновую волну прогон ПЕРЕД сравнением + ассерт покрытия ОБЕИХ волн
6 Перерасход: флагнутый член без edit-строки считался бесплатным unitFullyRecorded вместо вердикта resolveChunkState; репро-тест + мутация
7 Вторая покупка на МАЙНЯЩЕЙ книге падает exit 1 НЕ вылечено, названо. Корень — джоб-гард (stagerun.go:47-59), ратифицированный Р6-контур, чужой предмет. Мною добавлен громкий WARN + тест на него; проводка гейчена оркестратором
8 Трата стопа майнинга/терминолога вне потолка и переигрывается НЕ вылечено, названо. Резать её объёмом семантически неверно (не единица доставки); место — в ЦЕНЕ, платформенная сторона
9 Форма конвейера, где «юнит» — два объекта planVolume отказывает громко; тест + мутация
10 rebill_basis: failed рядом с посчитанной цифрой решение вынесено в чистую rebillOutcome; табличный тест на 5 состояний + мутация
11 Потолок тратил покупку на переделку вперёд доставки доставка-вперёд; ратифицировано опусом (порядок безопасен, A/B 6/6 против 4/6); тест + мутация на ТРОПУ ГНИЕНИЯ
12 Объёмный стоп не доезжает машинным каналом НЕ вылечено, и это РАТИФИЦИРОВАННАЯ отсрочка: промт §3.1 сам поместил различение в отчёт/лог, а не в поток; словарь потока — зона оркестратора, он сказал «не сейчас, строкой». Названо вопросом B
13 Ветка proj.Rows == 0 не покрыта TestARunThatRePaysNothingIsNotAskedForConsent; мутация падает
14 export не покрыт после правки банка решено ОТКАТОМ export + пином осознанного расхождения
15 Нет теста на проводку --max-units через CLI TestTranslateWiresMaxUnits; мутация «убрать проводку» падает
16 Предупреждение про майнящие книги не покрыто тест на обе стороны (есть потолок / нет потолка) + мутация
17,20 Смешанное происхождение цифр в отказе гейта каждое число из своей проекции; скоупная оговорка несёт скоупный ре-пин
18 Тройное повторение самого дорогого расчёта мемо со сроком жизни БАНКА; запинена ИНВАЛИДАЦИЯ (корректность), не скорость
19 Капнутое согласие — дыра? РАТИФИЦИРОВАНО ЗДОРОВЫМ опусом (согласие, не обход); по его же рекомендации запинено РАСКРЫТИЕ, которое этим согласием и делает
21 Строка стопа сообщала ЮНИТЫ как ГЛАВЫ движок говорит только «units»; тесты пере-пинены на верную формулировку
22 Отчёт называл несуществующий тест и снятые поля таблица и §9 исправлены; отозванный пункт помечен ОТОЗВАННЫМ, а не переписан молча
23 Денominация: rebill_units (chunk×stage) против --max-units (юниты) РАТИФИЦИРОВАНО ДЕФЕКТОМ опусом (замерено 15 против 6); аддитивное rebill_output_units, rebill_units НЕ переименован; тест + мутация
24 Семантика export.ConfigDrift изменена «за компанию» ОТКАЧЕНО: чужое потребляемое поле не пере-определяется побочным эффектом; расхождение запинено, чтобы не «починили» обратно
25 Один документ status описывал ДВА банка материализация помнит свои строки; счёт неподписанных — по тому же банку

Итого: 22 вылечены с тестом и мутацией, 3 названы и не вылечены (7, 8, 12) — у каждой указан предмет и чей он.

⚠ Мой рефактор сломал ШЕСТЬ упоминаний в чужом доке — я насчитала два и ошиблась в адресе

ИСПРАВЛЕНО ПО ПРИЁМКЕ 29.08: первая редакция этого раздела была неверна дважды, и обе ошибки — метода, а не арифметики. Оставляю разбор, а не переписываю молча.

Ошибка 1 — счёт. Я насчитала ДВА сломанных якоря; сломано было ШЕСТЬ упоминаний (те же два плюс четыре про AttachRubyAliasesToManual). Причина: я взяла число из counts.py --lint, который по собственному объявлению content-сверяет только якоря С ТОКЕНОМ («без токена — несверяемы: 728»). Эту его слепоту я в этой же сессии сама и процитировала — и всё равно приняла его счёт за полный. Правильный инструмент был на расстоянии одного грепа: grep -n "seeding\.go" по доку.

Ошибка 2 — адрес. Я разрешала якорь по НОМЕРУ СТРОКИ, а надо по СОДЕРЖИМОМУ. В старом файле на :157 действительно лежала материализация базового банка, и я записала переезд туда. Но док в строке 76 говорил не о ней, а о InjectivityCollisions — warning-only диагностике, которая никуда из seeding.go не уезжала, а просто съехала со 157 на 64. На bankmaterialize.go:326, куда я её отправила, лежит r.baseMemory = membank.MaterializeBank(baseIn, …) — к этому якорю отношения не имеющее. Номер совпал, предмет — нет.

Верная таблица (сверено содержимым, каждая строка проверена грепом в дереве):

Что говорил док Было Стало
InjectVoice is FALSE… — условный фолд voice/address seeding.go:130-133 bankmaterialize.go:291-294 (текст перенесён ДОСЛОВНО)
InjectivityCollisions — warning-only диагностика dst-коллизий seeding.go:157 seeding.go:64 — из файла НЕ уезжала
AttachRubyAliasesToManual×4 упоминания seeding.go:43-50, :47 bankmaterialize.go:88-94, сам вызов на :92

Правку в доке делал оркестратор — docs/architecture/ не моя зона. Мой вклад здесь: сломала я, а нашла и починила приёмка, потому что я доверилась инструменту вместо грепа и номеру вместо содержимого. Урок годен шире этого случая: якорь разрешается тем, ЧТО он утверждает, а не тем, на какой строке лежал.

§8. Obstacle — что НЕ удалось и что НЕ проверено

0. ГЛАВНОЕ, и это НЕ вылечено: объёмный потолок на книге, которая МАЙНИТ банк, ломает вторую покупку. Найдено денежной линзой, воспроизведено дважды независимо (линзой и опровергателем, каждым на своей копии репозитория, с контролем). Механика: обрезанная покупка черновит часть книги, а стоп майнинга получает НЕобрезанный список чанков (waverun.go:154 передаёт весь chunks) и досыпает dst по мере появления новых банкнот. Значит авто-банк РАСТЁТ от покупки к покупке; следующая покупка сворачивает его в обогащённый банк, edit-снапшот съезжает, а edit-джобы ПРЕДЫДУЩЕЙ покупки к нему пришпилены. Джоб-гард (stagerun.go:47-59) банк-онли-движение не отличает от смены конфига и падает нетипизированной ошибкой ⇒ exit 1, платформа пишет failed — вместо задуманного «завершение, код 0». Контроль (без --max-units, книга целиком за один прогон, потом резюм) проходит чисто — то есть путь открывает именно обрезание. ⚠ Поправка опровергателя, важная и снижающая цену: --resnapshot пере-оплату НЕ вызывает в общем случае — после подъёма снапшота джоба работает обычный ре-пин по content_hash, и уже отредактированные главы возвращаются за $0; платит только та глава, в тексте которой новый терм реально встречается. ⚠ ПОПРАВКА к моей же оценке, найдена оркестратором при приёмке и проверена мной по коду — я ЗАНИЗИЛА область. Я написала «платформа --resnapshot уже передаёт, флагманский путь цел, бьёт по ручному вызову». Неверно: платформа передаёт его НЕ всегда, а под условием book.BankMoved (platform/internal/runs/runs.go:288, читал не правил), и этот флаг ставит только ПРАВКА банка — рост авто-банка от майнинга его не ставит (platform/internal/pgstore/books.go:985-993: «a correction landed»). Значит бьёт именно по ФЛАГМАНСКОМУ пути: майнящая книга, вторая покупка, правок не было ⇒ флага нет ⇒ гард ⇒ failed. Решение оркестратора: механизм лендится, но ПРОВОДКА --max-units на платформе гейчена до лечения. Смягчение, которое я сделал: planVolume при живом майнинге пишет громкий WARN, называя и эффект, и --resnapshot. Чего я НЕ делал: не трогал джоб-гард — это ратифицированный Р6-контур и та самая мина D39.165 §3 / эрраты 28.08-и, её лечение назначено платформенной половине. Заказывай отдельно, если хочешь, чтобы банк-онли-движение джоб-гард пропускал сам.

1. Стоп майнинга и терминолог тратят ВНЕ объёмного потолка — и переплачиваются каждой покупкой. Тоже подтверждено. Мой пункт был мягче («потолок режет юниты, книго-уровневые вызовы — только деньги»); линза дожала: кандидатное пространство терминолога зависит от набора уже отчерновленных чанков, поэтому между покупками оно МЕНЯЕТСЯ, request_hash другой, и чекпойнты не переигрываются за $0. Книга, проданная десятью покупками, платит десять книжных консолидаций там, где цельный прогон платит одну. Ограничивают это только gates.terminology.budget_usd и --ceiling-usd. Не чинил: резать терминолога объёмом семантически неверно (он не единица доставки), а переносить его за пределы обрезанного прогона — это пере-проектирование майнинга (родня строки 203(з)). Обязан быть в цене продажи, если книга майнит.

  1. Живого прогона с провайдером НЕТ. Всё исполнение — против фейкового провайдера батареи. Ни одного платного вызова я не делал и не был на это уполномочен. Значит: цифры «2 вызова на юнит» и «$0.00182 за юнит» — свойства фикстуры, а не рынка; поведение потолка на реальном материале не мерено.
  2. Прогон, обрезанный по объёму и упёршийся в подписной стоп банка, уходит с кодом 3, и res.Volume тогда не докладывается: остановка принадлежит банку, а не потолку. Поведение корректное, но пара «стоп банка + объёмный потолок» отдельным тестом НЕ покрыта.
  3. Платформенная половина не сделана и не заказана мне (§0 промта): --max-units в argv никто не передаёт. Пока платформа не научится считать главы → юниты по манифесту и передавать флаг, обещание «купил N глав — получил N глав» НЕ выполнено. Механизм есть, трубы нет.
  4. storeOrder доказан на моей фикстуре, а не на всех входах. Тождество опирается на: UNIQUE (book_id, src, sense, since_ch, until_ch) (store/migrate.go:203) ⇒ префикс ключа не даёт ничьей, и на отсутствие COLLATE в схеме ⇒ побайтное сравнение TEXT. Оба факта проверены грепом и чтением DDL. Чего я НЕ проверял: поведение при значениях с невалидным UTF-8 и при типовой аффинности SQLite, если в TEXT-колонку когда-нибудь ляжет число.
  5. Порог согласия (rebill_consent_usd) я НЕ трогал — сужена только СУММА. Если владелец считает, что при объёмной покупке должен ужиматься и порог, это отдельное решение.
  6. Батарея прогнана на make battery; make battery-stand (корпусные тесты) НЕ гонял — нет стендовых данных на этой машине.

§9. Вопросы оркестратору — пингом, не интерпретацией в свою пользу

  1. Продавать ли объёмом книги, которые МАЙНЯТ банк — до отдельного заказа? Obstacle-0: вторая покупка на такой книге падает exit 1/failed без --resnapshot, и это открывает именно обрезание (контроль без потолка проходит чисто). Платформа --resnapshot уже передаёт (D39.166), значит флагманский путь цел, но ручной вызов — нет, и цена покупки на майнящей книге включает лишнюю книжную консолидацию терминолога (Obstacle-1). Мой совет: либо не ставить --max-units на майнящих книгах до заказа по джоб-гарду, либо принять оба хвоста явно. Решать тебе — я поставил громкий WARN и не стал трогать ратифицированный Р6-контур.

  2. Форма §3.2 отличается от той, что назвала строка 231. Строка предписывает «движковый глагол ЛИБО флаг». Я не сделал ни того, ни другого: я починил СВЁРТКУ, потому что слепое окно было не в том, что status пишущий, а в том, что он сворачивал последний прогон вместо ближайшего. Это дешевле обоих кандидатов и ближе к уже ратифицированной двери D39.165 §3 («платформа читает смету из УЖЕ существующего status --json»). Нужна ратификация формы и правка формулировки строки 231.

  3. Поля шва. rebill_units/rebill_usd потеряли omitempty, добавлено rebill_basis; status_version оставлен tm-status-v1 (правка АДДИТИВНАЯ, потребителей у полей сейчас нет — они сняты с аллоулиста). Строка 231 обещает их возврат «вместе с глаголом» — глагола нет, значит возвращаются вместе с этим фиксом. Нужен контрактный минор и ре-аллоулист трёх полей. ⚠ Уточнение от платформенной сессии textmachine-c0, сверено ею по коду: пара снята с аллоулиста паком P10 по ТАЙМИНГУ (platform/internal/ingest/resync.go:37-43) — status проецировал СОХРАНЁННУЮ память, поэтому сразу после apply честно отдавал ноль, — а не «за отсутствием потребителя», как я написала сначала. Это ровно та причина, которую мой §3.2 и снимает. Риска для шва при этом нет: DecodeStatus (resync.go:76) — обычный json.Unmarshal без DisallowUnknownFields, поэтому новое поле её сторона просто не заметит. Возврат — слово оркестратора, он берёт минор на себя (пойдёт вместе с session_ended, канон 0.8.0).

  4. ЭТОТ ПУНКТ ОТОЗВАН МНОЮ ЖЕ — подтверждать его НЕ надо. Здесь стояла просьба подтвердить сужение СУММЫ гейта D20.2-Q2 объёмным скоупом с доводом «инертно без флага». Довод верный и НЕважный: с флагом каллер сам выбирает размер прогона, поэтому дробление обходило порог и пере-оплачивало книгу целиком, ни разу не спросив согласия (замерено: 30 глав, четыре прохода по $0.003640 при пороге $0.005460). Действующее решение — второй круг, находка 1: порог судится по ВСЕЙ книге; именованный кап --accept-rebill=X — по тому, что заплатит ЭТОТ прогон; прогон, не пере-оплачивающий ничего, гейта не встречает. Подтверждать надо ЭТО.

  5. redrive я флаг НЕ дал (отказ по правилу «команда, которая на флаг не действует, его отвергает»). Соседняя правда, которую называю строкой, а не чиню: redrive внутри зовёт TranslateBook по ВСЕЙ книге (status.go:926), то есть у него своя денежная неожиданность — она была и до пака.

  6. Сигнал объёмного стопа в ПОТОК событий я не завёл. По правилу runevents.go:29-40 новый тип события — это минор, и читатель незнакомые типы игнорирует; но это твоя зона и контрактный минор, а §3.3 его в пак не клал. Если он нужен платформе — заказывай отдельно.

Вопросы оркестратору после второго круга — новые и изменившиеся

A. Разблокировка майнящих книг — есть дешёвый вариант, но решение продуктовое, поэтому НЕ беру. Причина поломки второй покупки в том, что стоп майнинга досыпает авто-банк между покупками. Если на прогоне с --max-units стоп майнинга НЕ запускать вовсе, авто-банк не растёт, edit-снапшот не двигается, вторая покупка идёт чисто, и хвост №1 исчезает без правки ратифицированного джоб-гарда. Цена ровно одна и она честная: книга, продаваемая по частям, не майнит банк, пока её продают — майнинг случается на цельном прогоне. Это размен «продавать по главам ИЛИ майнить», а не техническая деталь, поэтому его выбираешь ты. Если скажешь «да» — это несколько строк и тест.

B. Различение доставки и переделки сейчас ЧИТАЕМО ЧЕЛОВЕКОМ, но не машиной. VolumeStop несёт Delivered/Reworked/LeftFresh/LeftRework, и CLI это печатает — но платформа читает поток событий и код выхода, а туда различение не идёт. Значит покупка десяти глав, целиком ушедшая в переделку, для платформы по-прежнему выглядит как успешная доставка десяти. Полное лечение — поле в терминальном кадре потока, то есть твой контрактный минор (ты уже сказал «не сейчас, строкой»). Пишу это ещё раз потому, что после второго круга это перестало быть косметикой: именно здесь пере-оплата всё ещё может продаться как доставка, просто теперь молча на проводе, а не громко в отчёте.

C. Порог согласия остаётся КНИЖНЫМ, и это теперь несущее решение, а не умолчание. После отзыва сужения порог судит всю пере-оплату книги. Следствие, которое надо принять явно: любая покупка через --max-units на сдвинутом банке встречает гейт и требует --accept-rebill. Платформа его передаёт (при BankMoved), так что путь рабочий, но «тихих» пере-проходов больше не будет ни одного — и это ровно то, чего требует Р6. Если владелец захочет, чтобы мелкие покупки проходили без вопроса, это НЕ порог надо двигать, а заводить учёт уже-данного согласия — отдельный механизм, отдельный заказ.

D. Проводка --max-units гейчена тобой — я это поддерживаю и после второго круга поддерживаю сильнее. Пока различение доставки и переделки не доезжает до платформы машинным каналом (пункт B), платформа не может отличить «купил 10 глав и получил 10» от «купил 10 глав и получил 10 переделок». Механизм готов, труба — нет, и открывать её раньше пункта B я бы не стала.

Дополнение к вопросам после третьего круга

E. Три развилки закрыты РАТИФИКАЦИЕЙ, а не моим словом — фиксирую, чтобы ты не пере-решал их заново. — «капнутое согласие» — ЗДОРОВО (согласие, а не обход; раскрытие теперь запинено); — «денominация» — был ДЕФЕКТ, вылечен аддитивным rebill_output_units; — «доставка вперёд переделки» — ЗДОРОВО, порядок безопасен (байты вне-очередного юнита дословно совпали с прямым прогоном), выигрыш замерен A/B (6/6 против 4/6). Если пере-решаешь — пере-решай явно: под каждым лежит исполнение, а не рассуждение.

F. Аллоулист: полей теперь ЧЕТЫРЕ, и четвёртое обязательно. К rebill_units/rebill_usd/rebill_basis добавилось rebill_output_units. ⚠ Возвращать rebill_units БЕЗ него нельзя: rebill_units считает chunk×stage, все прочие «units» документа — выходные юниты, отношение внутри одной книги непостоянно, и платформа, отмерившая пере-проход по rebill_units и передавшая это число в --max-units, купит кратно больше книги. Ратификатор измерил: rebill_units: 15 двумя строками под total_units: 6.

G. Про умолчание «доставка вперёд переделки» — прошу зафиксировать словом, а не молчанием. Покупка, ЦЕЛЬЮ которой был пере-проход, теперь потратит грант на недоставленные главы, если они есть. Ратификатор показал, что дверь пере-прохода этим не ломается (на дочитанной книге доставка-вперёд И ЕСТЬ порядок книги), но на ЧАСТИЧНО доставленной книге разница видна. Если продукту нужен режим «только переделывать» — это флаг, и это твой заказ, не мой.

Полигон

📌 ПИНГ ПОЛИГОНУ от оркестратора №19 (28.08, D39.164) — вендор-вердикт по Gemini для docs/experiments/00-provider-quirks.md. Материал добыт бэкенд-сессией (curl по вендор-доке, не пересказ), но файл — ВАША зона, поэтому вписываете вы, а не я. Строка 157 сегодня несёт три утверждения сильнее, чем даёт источник:

  • «слой ФИЗИЧЕСКИ не может пронести больше одного системного» — переоценка. Вендор даёт структурный факт: в GenerateContentRequest поле systemInstruction — ОДИН object (Content) (в той же таблице contents[] и tools[] несут суффикс повторяемого поля), а Content.role документирован как «Must be either 'user' or 'model'». Что делает с двумя системными OpenAI-совместимый ШИМ — вендор НЕ документирует нигде: раздел «Current limitations» молчит и в живой странице (ai.google.dev/api/generate-content, помечена 2026-08-17, снято 2026-08-28), и в снимке Wayback 2026-08-21.
  • Content.parts[] — ПОВТОРЯЕМОЕ поле, и вендорская заметка на самом systemInstruction гласит «Only text should be used in parts and content in each part will be in a separate paragraph». То есть нативный API МОЖЕТ нести N системных текстов как N частей ОДНОГО Content; вывод «уход на нативный API проблемы не решает» верен по сути (склеивать всё равно пришлось бы), но не по причине.
  • «форум Google» — НЕ вендорский источник. Тред discuss.ai.google.dev/t/86097 — два поста, оба от НЕ-сотрудников (staff=false), 30.05.2025, ответа Google нет. Сейчас читается как авторитет наравне с нашим замером. Что остаётся ОТКРЫТЫМ честно: «выживает ровно одно» против «не выживает ни одного» не разрешено. Твёрдо установлено: НЕ склеиваются (prompt_tokens схлопнулись 2994 → 535) и first-wins ложно. Причина неразрешимости — в самой пробе: маркер приписан к msgs[0], поэтому его отсутствие одинаково совместимо с обоими чтениями, а зеро-системного контроля в скрипте нет. Дешёвое решающее доизмерение, если возьмётесь: тот же скрипт, маркер на ПОСЛЕДНЕЕ системное плюс user-only базовая клетка. ⚠ Отдельная граница: проба гонялась на gemini-3.1-flash-lite, а в цепочке эскалации стоит gemini-3.1-pro-preview — слой тот же, слаг другой. Для движка это уже безразлично: склейка на нашей стороне — единственная форма, которая потерять не может, и она заленджена (D39.164); вендор-ссылка с датой вписана прямо в configs/models.yaml у провайдера gemini, чтобы следующая сессия не переоткрывала.

ИТОГ ПОЛИГОН-СЕССИИ 23.08 — ШАГ 1 ПЛАНА 22.08 ЗАКРЫТ (панель-0, $0). Отчёт — секция Д32 docs/experiments/23-editor-tier.md; фризы bedc39a, 9e33a1b. Кратко:

  • Снят блокер сборки: rol.py не знал арма E6 (клетки чужой фазы ФД-G, другая схема), и неизвестное имя молча возвращало ПУСТУЮ строку — панель собралась бы из скольких-то глав без единого слова в лог. Заведён реестр FOREIGN, гейт клетки по СОДЕРЖИМОМУ, неизвестный арм = СТОП; гейты проверены фальсификацией (обезвредил гейт — селфтест краснеет).
  • ЛАТЕНТНАЯ МИНА ДВУХ КОНТУРОВ ВЫСТРЕЛИЛА. Селфтест предупреждал с 22.08 («до данных не добралось»); 23.08 добралось: wire('en') настраивал один экземпляр, а free_text шёл в другой и вернул пустой текст английской главы. Починено в корне (rol._wire включает оба).
  • Вердикт Шага 1 (интеракция «архитектура × жилец на ИСПЫТАННЫХ жильцах», не минимакс): слабый жилец glm-5 РЕДАКТОРОМ над боевым черновиком неотличим от боевого deepseek-v4-pro в той же роли (разрыв средних мест +0.00, p=0.80; дефект-классы 0 различия; «машинных» глав 3/16 у обоих). Тот же жилец ОДНОПРОХОДКОЙ различимо хуже: +1.12 места при пороге 0.99, знаковый p=0.0042 (конъюнкция пройдена) и +13 фаталов, p=0.0312. Буфер существует и замерен.
  • Два независимых прибора сошлись на КАЖДОЙ главе: детерминированный счётчик дефект-классов (новый eval/dovodka/schet.py) и слепое чтение назвали одни и те же дефекты одними словами.
  • ДЛЯ БЭКЕНДА, находка под метавопрос: в 2 окнах из 8 с первым лицом пол рассказчика по главе НЕ УСТАНАВЛИВАЕТСЯ вовсе (эталон снят вслепую тремя независимыми чтениями на главу). Тот же голос ведёт другие главы, где пол очевиден ⇒ закрыть эти ~25% может ТОЛЬКО книжная память. А в ~/books/role-topology/bank-en.json полей пола НЕТ (25 терминов, поля dst/rx/manual/why — проверено файлом). Это смыкается с пингом №19 ниже и со строкой бэклога 210.
  • Долг В21 (сверка кассы двумя путями) ИСПОЛНЕН, результат отрицательный: сверка на диске НЕВОЗМОЖНА в принципе — cost_usd вычисляется нашим же roster.cost (buy.py:93-95), а не приходит от вендора. У четырёх вендоров из шести арифметика сходится до последнего знака (213 клеток); у DeepSeek расхождение объясняется пере-пином 16.08, а «офф-пик = ½» в записанных ценах НЕ НАБЛЮДАЕТСЯ. ⇒ вопрос владельцу: сверить $17.04 с реальным счётом DeepSeek может только он.
  • Агент-сессий: 114 из 200 (16 читателей панели-0, заняты runs.py --claim до запуска, закрыты после). Денег не потрачено: панель целиком на уже купленных клетках.

ПИНГ ОРКЕСТРАТОРА №19 — 22.08. ЖИВОЙ ДЕФЕКТ ДВИЖКА: эскалация на Gemini ТИХО ТЕРЯЕТ ГЛОССАРИЙ. Найдено полигоном живой пробой, подтверждено вендор-докой. OpenAI-совместимый слой Gemini принимает РОВНО ОДНО системное сообщение; лишние выбрасываются молча, без ошибки. Механизм назван вендором: в нативном API systemInstruction — один объект Content (ai.google.dev/api/generate-content), поэтому уход на нативный API проблемы НЕ решает — склеивать надо в любом случае. Замер (один и тот же системный текст 7970 знаков): одним сообщением → prompt_tokens 2994, маркерная инструкция ИСПОЛНЕНА; двумя → 535 токенов и инструкция НЕ исполнена, при finish=stop и внешне правильном переводе. Отказа нет — есть тихая потеря промта, невидимая гейтам годности.

Почему это ваша зона, а не наша. backend/internal/pipeline/render.go:256-258 штатно строит ВТОРОЕ системное сообщение — инъекцию банка памяти (глоссарий/STM); backend/internal/llm/httpllm.go:517-522 (toOpenAIMessages) копирует сообщения дословно; склейки под Gemini нет нигде. При этом gemini-3.1-pro-preview стоит в ратифицированной цепочке эскалации во ВСЕХ арм-конфигах (backend/configs/pipeline-c1.yaml:129, pipeline-arm-glm.yaml:61, pipeline-arm-deepseek-pro.yaml:62, pipeline-arm-mistral.yaml:61). ⇒ любой эскалационный хоп на Gemini при непустой инъекции теряет глоссарий, и книга едет без канона имён. Оговорка D22.3 «экспозиция Ф1 нулевая» держится только на том, что до Gemini в дефолте не доходят — то есть на маршруте, а не на коде. ⚠ Класс в проекте УЖЕ решён рядом: backend/internal/llm/provider_anthropic.go:169-179 сворачивает ведущий system-префикс в одно поле и падает громко на system посреди диалога. Не обобщено на Gemini. Полигон у себя починил склейкой по вендору (eval/dovodka/rol.py ONE_SYSTEM/fit_msgs); в бэкенд рукой не лезу. Квирк записан в 00-provider-quirks.md (наша зона) с механизмом и ссылками.

Тем же касанием — две поправки в квирках, обе наши прежние ошибки, уже внесены нами: (1) форма extra_body.google.thinking_config... в бюллетене НЕ доезжает через openai-SDK: вендорская форма несёт ключ extra_body на верхнем уровне тела (extra_body={'extra_body': {'google': …}}), а один уровень даёт HTTP 400 «Unknown name "google"». Из-за этой ошибки eval/providers.json:59 объявил рабочую форму багом, и проект три недели считал, что ручки размышления у Gemini нет. (2) reasoning_tokens=0 у Gemini — НОРМА слоя, а не измерение: вывод «размышление выключено» из этого поля недействителен, считать надо total prompt completion. У серии Gemini 3 размышление вообще невыключаемо (вендор, 17.08.2026).

⚠ Пинг оркестратора №18 — 20.08 (протухшие цены в квирках, чинить вашей рукой). docs/experiments/00-provider-quirks.md до сих пор утверждает, что цены после катовера НЕ изменились («flash $0.14/$0.28»). Это опровергнуто пере-пином 1315.08 (D39.137): таблица запинена ПИКОМ — flash 0.44/1.32 при кэш-хите 0.014, pro 1.32/3.96 при кэш-хите 0.044 за 1M (⚠ испр. 20.08: первая редакция пинга приписала flash кэш-хит pro — ошибка ×3.1 ровно в той клетке, ради которой пинг и писался; сверено с backend/configs/models.yaml:182,198=cached_per_m и телом D39.137 §2а), и счёт шиппинга = 100% DeepSeek ⇒ ×4.24.4 в пике. Квирки — ваша зона, рукой не трогаю; поправьте при ближайшем касании, потому что по ним считают деньги проб. ⚠ И ВТОРОЙ факт тем же касанием, он сейчас БЕЗДОМНЫЙ: у DeepSeek цена ходит окнами — пики UTC 0104 и 0610 вдвое дороже долин, платное планировать в долины. Факт куплен замером и жил в справочнике ролевого промта; я оттуда его убирал как вендор-специфику, а в квирках его НЕТ (греп по peak|долин|пики UTC = 0), то есть указатель вёл в дом, который факта не несёт. До вашего переноса держу копию в ролевом промте с явной пометкой. ⚠ Третья, и она самая дорогая по цене ошибки: eval/README.md первой врезкой держит СТОП на платные прогоны — «Платные прогоны/докупки СТОП до ре-пробы (бэклог-строка 74)». Строка 74 закрыта (D39.95), ограничение пало лендингом 112 (D39.97), pipeline-c1.yaml несёт reasoning: "low" с объяснением, а зона всё это время платно гоняет фазу Д. Врезка объявляет запрещённым то, что зона делает ежедневно, — и этим обесценивает все прочие ⚠ в файле. Живым из неё остаётся только ⚠0731 (смена весов под слагом) и стохастичность эха.

Тем же касанием — вторая протухшая клетка справочника, найденная аудитом доков 22.08: квирки утверждают, что веса deepseek-v4-pro вендором не тронуты. Это боевой РЕДАКТОР и апекс эскалации, и по нему у нас прямое расхождение двух носителей, которое до сих пор не снято: docs/STACK.md говорит «ручки эффорта у pro НЕТ (lowhigh), так говорит квирк-канон», а CURRENT-STATE — «у pro эффорт стал настраиваемым low/high/max, квирк 3а устарел». Из репозитория правая сторона НЕ выводится: замера поведением после 13.08 нет ни у одной стороны. Закрывается вендор-сверкой, а не выбором стороны — и вы это только что делали по Gemini, то есть заход дешёвый.

⚠ Прежняя редакция этого пинга просила вас сверить расхождение по «возражению Sol» — расхождение снято 22.08 срезкой хроники, второй носитель уехал в archive/PROGRESS-2026-08-10-15.md; сверять больше нечего, пункт живёт один и висит на владельце.

ПИНГ ОРКЕСТРАТОРА №20 — 22.08, ФАКТЫ О СОСТОЯНИИ ДЕРЕВА ЗОНЫ (снято командами, не решение). Аудит доков спрашивал у дерева, а не у записей, и картина такая: 13 отслеженных файлов eval/ изменены и не закоммичены (+2166/79 строк), плюс 6 неотслеженных, из них в рабочем каталоге фазы eval/dovodka/ вне git — naklon.py · ja6.py · HANDOFF-21-08.md · PLAN-16-08.md · PLAN-17-08.md · КОНТЕКСТ-ДЛЯ-КОНСУЛЬТАЦИИ.md. Почему это пинг, а не правка. Диспозиция D39.135 п.4 («полигон работал 16.08 БЕЗ записи в журнале — PLAN-16-08.md, ja6.py, naklon.py; состав выяснять при лендинге») висит шестой день, а состав за это время вырос с трёх файлов до девятнадцати. Прямое следствие, названное без оценки: из чистого клона репозитория часть фазы сегодня не воспроизводится — в частности naklon.py, гейт позиционного наклона, вне git целиком. Зона живая, приёмка фазы — у ПАРАЛЛЕЛЬНОГО оркестратора, поэтому я ничего не коммитил, не переносил и не удалял: решает владелец или он. ⚠ Тем же аудитом: eval/README.md описывает каталог dovodka/ ОДНИМ файлом runs.py, тогда как там сорок скриптов и главный инструмент фазы; docs/experiments/README.md объявляет себя сведённой «до эксп-22», а строк для 22 и 23 в ней нет ни одной. Обе правки — зонные, рукой не трогаю.

ФАЗА Д «ДОВОДКА ЭКСП-22/23» — ИДЁТ.Живое состояние фазы живёт В ЗОНЕ, не здесь (eval/dovodka/ — планы, консилиум, ревью; свежий носитель курса зона называет сама), приёмка фазы — у ПАРАЛЛЕЛЬНОГО оркестратора, деньги и цепь потолков — eval/dovodka/money_d.py (PACK_CEILING/CEILINGS), а не литералом здесь: три поколения записей в одном месте и были причиной, по которой состояние фазы стало нечитаемым.

(Хроника фазы Д — записи 10.08 (сессия №1) и 15.08 (сессия №2, сквозной аудит дуги 19→23 и пере-судейство tier) — вынесена в archive/PROGRESS-2026-08-10-15.md с тремя поправками в шапке: потолок, закрытые пункты листа владельца, протухшие «долги». Открытым на владельце из неё остаётся ОДИН пункт — возражение Sol по проходу tier.) Запись оркестратора №17, 15.08 — две передачи ПАРАЛЛЕЛЬНОМУ оркестратору (приёмка фазы Д — его зона, №17 полигон не трогает по слову владельца). (1) Просьба хендоффа фазы Д «эррата zh-канона: пере-сборка = правка закрытой оси, ратифицирует оркестратор» (POLYGON_PHASE_D_HANDOFF.md:84-86, завышение +0.0039, вердикты не двигает) — диспозиция №17: к параллельному при приёмке, не к движковому. (2) Мелочь аудита корпуса 15.08: 23-editor-tier.md:2243 цитирует «PROGRESS.md:346» для потолка $4.50 — фактически строка была :348; учесть при приёмке тел. Санкции владельца по деньгам фазы и замене ja-книги уже записаны (D39.136 п.1, CURRENT-STATE).

(Память · Голос и состояние · Ридер-IDE — ЗАКРЫТЫЕ секции (D39.125): темы исполнены/переехали в зонные журналы; хроника — в архив-слайсах. Фронт пишет ТОЛЬКО в frontend-PROGRESS.md.)