From 322007dc60ee01175214b9c3604c94228b412a15 Mon Sep 17 00:00:00 2001 From: heaven Date: Fri, 18 Sep 2026 06:54:20 +0300 Subject: [PATCH] Accept the second-pair reachability pack: the whole catalogue caught every entry, the Chinese half is provably untouched by inputs, and the English book now reaches the production config --- docs/BACKLOG.md | 8 +- docs/PROGRESS.md | 2 +- docs/README.md | 2 +- docs/architecture/05-decisions-index.md | 3 +- docs/architecture/05-decisions-log.md | 88 ++++++++++++++++++- .../BACKEND_RUN_READINESS_SESSION_PROMPT.md | 7 ++ 6 files changed, 101 insertions(+), 9 deletions(-) rename docs/{ => archive/prompts}/BACKEND_RUN_READINESS_SESSION_PROMPT.md (97%) diff --git a/docs/BACKLOG.md b/docs/BACKLOG.md index 4edabe1c..17057587 100644 --- a/docs/BACKLOG.md +++ b/docs/BACKLOG.md @@ -3,7 +3,7 @@ > **Единственный трекер проекта.** Здесь живут строки, на которые доки, промты и D-ноты ссылаются словами «строка N» / «строка бэклога N»: **ID строки стабилен навсегда**, не перенумеровывается и не переиспользуется (D39.80). Правки — только через оркестратора; каждая петля обязана иметь диспозицию: решено / отложено-с-записью / отклонено. > ⚠ **Это НЕ бэклог зоны `docs/`, а бэклог ПРОЕКТА.** У зон свои, с другими неймспейсами ID, и единый их строк не принимает (D39.84): платформа — [../platform/BACKLOG.md](../platform/BACKLOG.md) (`П-N`) и её регистр дефектов `platform/docs/DEFECT_REGISTER.md` (`PD-N`); фронт — [../frontend/docs/BACKLOG.md](../frontend/docs/BACKLOG.md) (`Ф-N`). > ⚠ **Состояние проекта — не здесь.** Очередь, курс, CURRENT-STATE, состояние паков и живая хроника — шапка [PROGRESS.md](PROGRESS.md). Здесь только долг и его диспозиции. -> - **СЧЁТ ОЧЕРЕДИ на 17.09 (скриптом по таблице — `python3 docs/scripts/counts.py`; обновлять при каждом лендинге):** всего **376** строк · зона бэкенд **202** строго / **255** широко (⚠ колонки счётчик читает С КОНЦА — испр. D39.116) · **блокеров очереди 0** (236 закрыта D39.175; **371** — актом D39.233, **360** — актом D39.232, обе 10.09), платные прогоны разблокированы · «скоро» **203** (перечень — грепом по таблице, рукописный список снят D39.126) · гейт-строка эксп-22: 153 (плюс 150 — руки владельца; ⚠ 55 из гейтов СНЯТА — D39.198 п.5); строка 5 — остаток гейчен ре-пробой 74, носитель события теперь строка 188 (аудит D39.140); остальное «когда-нибудь». ⚠ Счёт — НИЖНЯЯ граница долга, не потолок (разбор — легенда таблицы ниже). +> - **СЧЁТ ОЧЕРЕДИ на 17.09 (скриптом по таблице — `python3 docs/scripts/counts.py`; обновлять при каждом лендинге):** всего **374** строк · зона бэкенд **200** строго / **253** широко (⚠ колонки счётчик читает С КОНЦА — испр. D39.116) · **блокеров очереди 0** (236 закрыта D39.175; **371** — актом D39.233, **360** — актом D39.232, обе 10.09), платные прогоны разблокированы · «скоро» **202** (перечень — грепом по таблице, рукописный список снят D39.126) · гейт-строка эксп-22: 153 (плюс 150 — руки владельца; ⚠ 55 из гейтов СНЯТА — D39.198 п.5); строка 5 — остаток гейчен ре-пробой 74, носитель события теперь строка 188 (аудит D39.140); остальное «когда-нибудь». ⚠ Счёт — НИЖНЯЯ граница долга, не потолок (разбор — легенда таблицы ниже). > - ⚠ **Переезд 06.09 (D39.218):** таблица вынесена из `PROGRESS.md` ДОСЛОВНО и ни один ID не сдвинут — **с единственным исключением: две ячейки (строки 220 и 306) тронуты РОВНО в номере якоря `docs/scripts/counts.py:566`→`:569` и `:592`→`:595`**, потому что цель сдвинул этот же коммит; текст ячеек не менялся, длины равны. В `PROGRESS.md` на прежнем месте оставлен заголовок-указатель, поэтому ссылки «секция „Бэклог“» доезжают в один хоп. ## Бэклог (ЕДИНЫЙ, собран 26.07, актуализация 04.08 D39.99/D39.101; правки — только через оркестратора) @@ -207,7 +207,7 @@ | 265 | **Питоново зеркало полигона держит ВТОРУЮ копию таблицы плейсхолдеров движка, и она разошлась: `genre` есть, `book_id` нет.** `eval/bank_arbitration/editor_wire_probe.py` — ПЛАТНАЯ проба, читающая ШИППИНГОВЫЙ `backend/prompts/zh-ru/editor.md`, на неё ссылаются ещё **25** скриптов (`grep -rl editor_wire_probe eval --include=*.py`; ⚠ испр. 05.09, первая редакция говорила «девять»); 27 промтов под `eval/` несут `{{genre}}`, который движок ОТКАЗЫВАЕТСЯ собрать при загрузке. ⇒ замеры идут на проводе, которого в проде не существует, и это «третий путь», которого в Go больше нет. ⚠ Зона ПОЛИГОНА — чинит она, носитель заведён оркестратором пингом | полигон | скоро (перед следующим платным замером) | зеркало читает таблицу движка, а не держит копию | передано бэкенд-сессией 04.09, чужая зона | | 266 | **Правки кругов 3 и 4 петли не ревьюил НИКТО — круг свёрнут решением владельца, а не замкнут.** Замеренная база, из-за которой это долг, а не формальность: ДВАЖДЫ подряд дефект вносил фикс предыдущего круга (круг 2 объявил денежную дыру закрытой — круг 3 показал, что она открыта; ратификация оркестратора по дедупу внесла живой дефект — поймала зона). Круг 3 добавил ~2000 строк и не ревьюил из них ни одной; круг 4 — две правки, обе проверены исполнением, но не чужими глазами. ⚠ Дисциплина петли исправлена эрратой: круг крутит СЛЕДУЮЩАЯ сессия по готовому паку, а не прежняя — правило «сессия отрабатывает скоуп и завершается» бьёт норму петли | бэкенд | скоро | проход свежей сессии по диффу `c77c3ba`+`2e13cd1` | решение владельца 04.09 остановить полировку | | 268 | **Гейт версии контракта у фронта читает СВОЁ зеркало, а не канон — и потому слеп по построению.** `frontend/src/api/contract.test.ts` сверяет `${cwd}/docs/api-contract/openapi.yaml` с фикстурой, то есть копию с копией, и зелен при любом отставании; соседний тест сравнивает только МАЖОР, а он у `0.2.3` и `0.10.0` одинаков — ноль. Зеркало отстало на ВОСЕМЬ миноров. Сравнение: тот же класс гейта у платформы читает КАНОН с диска и поймал расхождение `0.9.0→0.10.0` в тот же час. ⚠ Зона фронта ЗАМОРОЖЕНА — строка ждёт разморозки, но входит в перечень первого касания | фронт | скоро (первое касание при разморозке) | перенацелить гейт на канон | находка платформенной сессии 04.09, подтверждена оркестратором | -| 272 | **ШАБЛОН КНИГИ ДЕПЛОЯ ОДИН НА ВСЕ ПАРЫ, а в нём лежит ПАР-СВЯЗАННОЕ значение — `transcription: palladius`.** Платформа рендерит `book.yaml` из единственного операторского шаблона и подставляет ровно пять ключей (`book_id · title · source_lang · target_lang · source_file`); всё остальное едет из шаблона нетронутым. Палладий — система транскрипции ДЛЯ КИТАЙСКОГО. Движок значение не валидирует (свободная строка) и подставляет прямо в промпт. ⇒ Деплой, объявивший `zh>ru,ja>ru`, отдаёт КАЖДОЙ японской книге инструкцию транскрибировать по-китайски: не отказ и не флаг, а тихо неверные имена во всей книге — ровно тот класс брака, ради которого продукт существует. ⚠ Чинить придётся не одну книгу: значение вшито в `book.yaml`, который платформа НИКОГДА не перезаписывает (`O_EXCL`) | платформа+бэкенд | скоро (гейт второй пары) | пар-связанные ключи шаблона + валидатор значения в движке | критик полноты стратегии 04.09 | +| 272 | ⚠ **ДВИЖКОВАЯ ПОЛОВИНА ЗАКРЫТА 18.09 актом `D39.268`:** пара объявляет допустимые имена политики, книга выбирает ИМЯ, Go не знает ни одного, неизвестное имя даёт громкий отказ до первой траты. **ОСТАЁТСЯ ПЛАТФОРМЕННАЯ:** пример в операторском рецепте по-прежнему учит класть пар-связанный ключ в шаблон, общий для всех пар — это пинг зоне, не блокер прогона, потому что шаблон есть артефакт ОПЕРАТОРА и прогон ставит свой. **ШАБЛОН КНИГИ ДЕПЛОЯ ОДИН НА ВСЕ ПАРЫ, а в нём лежит ПАР-СВЯЗАННОЕ значение — `transcription: palladius`.** Платформа рендерит `book.yaml` из единственного операторского шаблона и подставляет ровно пять ключей (`book_id · title · source_lang · target_lang · source_file`); всё остальное едет из шаблона нетронутым. Палладий — система транскрипции ДЛЯ КИТАЙСКОГО. Движок значение не валидирует (свободная строка) и подставляет прямо в промпт. ⇒ Деплой, объявивший `zh>ru,ja>ru`, отдаёт КАЖДОЙ японской книге инструкцию транскрибировать по-китайски: не отказ и не флаг, а тихо неверные имена во всей книге — ровно тот класс брака, ради которого продукт существует. ⚠ Чинить придётся не одну книгу: значение вшито в `book.yaml`, который платформа НИКОГДА не перезаписывает (`O_EXCL`) | платформа+бэкенд | скоро (гейт второй пары) | пар-связанные ключи шаблона + валидатор значения в движке | критик полноты стратегии 04.09 | | 273 | **ПАР-ШОВ ЛОМАЕТСЯ АСИММЕТРИЧНО: промпт-пак падает ГРОМКО, целевые ДАННЫЕ выключаются МОЛЧА — вместе с банком.** Отсутствие промптов пары — жёсткая ошибка загрузки («never silently substitute another pair's conventions»). Отсутствие ЦЕЛЕВЫХ данных — тишина в трёх местах: `lang.InjectionTextsFor` на незнакомом таргете возвращает пустое, обе банк-инъекции рендерят пустоту (`if !tx.HasData() { return "" }`), `LoadReaderWords` отдаёт значки вместо слов без ошибки. ⇒ Книга на новый таргет переводится ЦЕЛИКОМ и за ПОЛНЫЕ деньги, но БЕЗ банка-как-закона — то есть без единственного механизма, держащего термины консистентными на всю книгу, без $0-чекеров цели и с пометками из значков в выданном файле. Ни ошибки, ни варнинга, ни поля в отчёте сборки. ⚠ Строка 32 закрыта формулировкой «инертна ПО ОТСУТСТВИЮ данных» — для ЧЕКЕРОВ это хорошо, для БАНК-инъекции такого вывода не делал никто | бэкенд | скоро (гейт второй пары) | префлайт готовности таргета: банк-данные есть ⇒ работаем, нет ⇒ громко | критик полноты стратегии 04.09 | | 275 | ⚠ **ПЕРЕ-СНЯТА 05.09 СЛОВОМ ВЛАДЕЛЬЦА — прежняя формулировка «КАЧЕСТВО НЕ МОЖЕТ СТАРТОВАТЬ ВООБЩЕ» БЫЛА НЕВЕРНА (ошибка оркестратора).** Она называла четыре гейта; из них **три сняты словом владельца, четвёртый гейтом не был** (разбор — `D39.198`): **13а** веса рубрики НЕ НУЖНЫ — веса меряют РАЗНЫЕ узлы (консистентность — банк памяти, выдумки — редактор, художественность — редактор И черновик), единого веса быть не может, а одно взвешенное число измеряет, но не ДИАГНОСТИРУЕТ · **24** профили голоса — приоритет №3, подписи владельца не требуют («зачем мне это подписывать») · **149** разморозка панели не нужна: пока идут доработки, менять жильцов ролей незачем · **55** прогоняем на ТЕХ ЖЕ текстах (мастер Гу, Жан-Кристоф), оговорка про претрейн остаётся ОГРАНИЧЕНИЕМ ВЫВОДА, а не требованием новой книги. **ЧТО ОСТАЁТСЯ ЖИВЫМ В ЭТОЙ СТРОКЕ:** привязать каждый класс дефекта к УЗЛУ и мерить по узлам; поставить порог остановки для приоритетов №1 и №2 (разъехавшийся термин — стоп, выдумка — стоп, сухая фраза — не стоп). ⚠ Консистентность проверяема ДЕТЕРМИНИРОВАННО за $0 — это ГЕЙТ, а не строка рубрики; ближайший её носитель — строка **267** | полигон+бэкенд | скоро | привязка классов к узлам + пороги остановки для №1 и №2 | решение владельца 05.09, `D39.198` | | 276 | ⭐ **ФОРМА ЗАКАЗА ПЕРЕВОДА — решение владельца 05.09, ратифицировано D39.196.** На аккаунте **баланс в ДЕНЬГАХ** и он виден. Человек стартует перевод; хочет задать потолок — тянет ползунок **в деньгах**; рядом ответ на его настоящий вопрос: **хватает на полную книгу или нет**. Хочет задать объёмом — второй ползунок: **ГЛАВЫ когда книга распозналась**, **ЗНАКИ когда нет** (о нераспознавании говорим ЯВНО). Старт = **холд с баланса**. Отдельная кнопка **«перевести книгу целиком»** — за целую книгу оценка точнее, чем за произвольный кусок. ⚠ **Две ручки связаны проекцией:** объём — ЗАКАЗ (главная), деньги — ЛИМИТ (вторая); тронутая последней ограничивает, другая пересчитывается и показывается производной («5 глав ≈ $0.55, зарезервируем до $0.8»); минимум денежного ползунка = неделимый шаг движка, чтобы ползунком нельзя было выразить невозможный заказ. Не тронута ни одна ⇒ заказ = вся книга. ⚠ **Цифра на экране — ПАРА, а не точка:** «ожидаемо ≈ $1.1, зарезервируем до $1.6, спишем по факту», и закрытие фактом после прогона — проекция имеет дисперсию (редакторские вызовы 25–90 % worst-case), точечное число превратится в «сказали 1.14, списали 1.31». Главный ответ — фраза, цифра рядом и мельче. ⚠ **Запрет «денег в UI» ОТОЗВАН владельцем** (D39.196 п.2): виден баланс, потолок, холд; цены моделей и стадий — нет. «Страница» из контракта убирается совсем — владелец назвал ЗНАКИ, форматирование «≈67 стр.» это локаль фронта. Исполнение — **279–283** (⚠ испр.: 277 и 278 ПОСТРОЕНЫ лендингом `81a89e9` и сняты) | движок+платформа+фронт | скоро | решение принято и ратифицировано D39.196; исполняется **279–283** (277 и 278 закрыты) | решение владельца 05.09 + сведение с внешним рецензентом | @@ -274,7 +274,6 @@ | 343 | **`counts.py` ДЕРЖИТ РЕГИСТР ОДНИМ ПУТ�ём И НЕ ГЛОБИТ СЛАЙСЫ — предусловие нарезки `DEFECT_REGISTER.md`.** Вынос без этого молча уронит счёт открытых рядов, а гейт чисел покажет зелень: он читает ровно один файл. ⚠ План нарезки живёт в `docs/DOC_CLEANUP_PLAN.md` (Б14в) | доки | скоро | прибор читает регистр и его слайсы, счёт не меняется при выносе | вопросы платформы 07.09 | | **— ТЕХДОЛГ БЭКЕНДА: разбор research/33 (D39.224) —** | | | | | | | 346 | ⚠ **ПОЛОВИНА (а) ЗАКРЫТА 07.09 (`D39.225`): пин расхождения и паритет-тест стоят, оба под мутациями. ОСТАЁТСЯ (б) — фикс в окне перенарезки.** ⛔ **ПРАВИЛО ЗАГОЛОВКА РАЗЪЕХАЛОСЬ ПО ТРЁМ ПРЕДИКАТАМ, И «第零章» ЛОМАЕТ ПРОЛОГ — две половины с РАЗНОЙ ценой.** Страж длины живёт только в ингесте (`chunk/ingest.go:307`=`const chapterHeaderMaxRunes = 60` `chapterHeaderMaxRunes = 60`, применён `:323`; в `chunker.go` `RuneCountInString` — 0 хитов), осмысленность номера — только в чанкере (`backend/internal/chunk/chunker.go:315-317`=`v := section + num` — ⚠ испр. 16.09: было :316, где утверждение несёт строка с `||`, непригодной для ячейки таблицы `if !any || v <= 0`). Воспроизведено исполнением 07.09 (выброшенная проба на копии дерева): `第零章:序幕` ингест режет главой, а чанкер заголовок НЕ снимает — `heading=""`, сырой CJK-маркер уезжает модели; `parseSectionNumeral` на `零`/`0`/`〇` даёт `0,false` (контроль: `一`=1, `十二`=12); номера расходятся (`第一章` = `Chapter 2` при «Глава 1»); 84-рунный заголовок: ингест `false`, чанкер `ok=true`. ⚠ **Испр. 07.09 — без этой оговорки строка читается как ЛОЖНАЯ:** расхождение живёт ТОЛЬКО у заголовка С СЕПАРАТОРОМ после юнита (`第四章:…`); без сепаратора оба предиката дают `false` на любой длине, потому что такую строку отвергают и `isHeaderSeparator` ингеста, и `matchHeaderLine` чанкера. Пере-снято оркестратором на копии `d6dfc49`: с сепаратором 59 и 60 рун — оба `true`; 61 и 84 — ингест `false` при чанкере `ok=true n=4`; без сепаратора 12/55/59/60/61/84 — `false`/`false` во всех шести. Граница ровно `chapterHeaderMaxRunes` = 60. Перекрёстного теста нет ни в одном из 97 тестов `internal/chunk`. **(а) $0 СЕЙЧАС — пин ИЗВЕСТНОГО расхождения, а не паритет:** красный тест в `main` не ложится (`Makefile:58` `battery: build vet fmt lint test`), скип — класс D39.208; поэтому тест утверждает, что на `第零章` и на 61–84-рунной строке ингест и чанкер СЕГОДНЯ расходятся, назван этой строкой и краснеет ровно тогда, когда приземлится фикс (б), заставляя фиксера его перевернуть. Дизайн-пак 161 §4.5 паритет-тест ОПИСЫВАЕТ, пишет его пак стройки — пин (а) этому не мешает. **(б) В ОКНО ПЕРЕНАРЕЗКИ:** сам фикс меняет ТЕКСТ чанка ⇒ бампает `chunkerVersion` ⇒ снапшот обеих волн (`render.go:55-58` — «a deliberate re-translation»); отдельным актом он платит ту самую перепокупку, которую отменяет. ⚠ Ось «обязательность юнита» — НЕ трогать: носитель строка **303** (⚠ испр. 07.09: research/33 приписывал её `D39.207`, в теле ноты этого нет — греп по предмету 0 при 23 строках тела) | бэкенд | скоро для (а); (б) — в окне перекроя (шаг 3) | (а) пин расхождения · (б) сведение двух предикатов к ингестовским стражам внутри пака перекроя | research/33 Д3, research/27 §6 | -| 347 | **ПАР-ДАННЫЕ НЕЛЬЗЯ ЗАВЕЗТИ ПО ЧАСТЯМ: манифест требует ≥1 канал, и транслитерационный канал зашит в китайскую форму.** `backend/internal/lang/langpack.go:644`=`manifest declares no channel` — «manifest declares no channel — omit the file to ship all channels, or list at least one»; каналов два и они закрыты в Go (`source-morphology`, `transliteration`, `:108-114`), а `validate()` при `transliteration` требует ПОИМЁННО пиньинь-категории (`:533-539`); морфологический канал просит общие таблицы (`:519-529`) и в китайскую форму не зашит. Отказ жёсткий: при `gates.terminology.enabled` и `pack == nil` прогон отказывает `RefusalBadConfig` (`backend/internal/pipeline/runner.go:364`=`Gates.Terminology.Enabled` — ⚠ испр. 16.09: было :349), а в боевом `pipeline-c1.yaml:151`=`Роль ТЕРМИНОЛОГА (пак-20, D39.42 п.1)` гейт включён ⇒ вторая пара выбирает между фиктивными данными китайской формы и прогоном БЕЗ банка терминов (продуктовая цель №1). ⚠ **Триггер — первая новая ИСХОДНАЯ пара, и он РАНЬШЕ строки 115:** манифест лежит в `//` и хешируется языком-ИСТОЧНИКОМ (`backend/internal/lang/langpack.go:255`), а 115 — про новую ЦЕЛЬ; ближайшая исходная пара в трекере — ja→ru (строка **81**), цель у неё ru. ⚠ **Испр. 17.09 ЗАМЕРОМ — прежняя оговорка «пять строк снимают отказ, но банка на не-Han источнике НЕ дают» ВЕРНА ПРО МАЙНЕР И НЕВЕРНА ПРО БАНКНОТУ, и это переворачивает цену ряда.** Замер сессии пака `textmachine-main-c5` на трёх настоящих главах английской книги (934 072 руны через `chunk.IngestEncoded`), боевая цепочка `terminology.Merge` → `AttachKWIC` → `reverseSectionTerms`, знаменатель — 5 поданных поверхностей банкноты, термов майнера НОЛЬ: **в дельту доехали 4 строки** (`dior` 553 · `gabriel` 338 · `grail` 177 · `voss` 130), у каждой улика `banknote-only candidate (the miner did not surface it)`. Четыре контроля различают: живой `zh-ru` пак грузится (`langpack-v2-43b3ebed3362`) · майнер на латинице при ЖИВОМ паке даёт 0 термов · пустая банкнота даёт 0 строк · выдуманная поверхность в дельту НЕ попадает · терм в сиде исключается сам. ⇒ **банкнотный канал даёт не-Han источнику РАБОЧИЙ банк независимо от Han-only майнера**, и цена ряда меняется с «пять строк, которые ничего не покупают» на **«пять строк, открывающие единственный банк-канал не-Han источника»**. ⭐ **И контраст-корпус оказался НЕ предметом:** тот же замер с ПУСТЫМ `&miner.Contrast{}` дал те же нули майнера ⇒ чинить надо не «завезти английский частотный корпус», а **«не отказывать в контуре там, где майнер инертен по построению»**. ⚠ Границы замера названы сессией и не расширяются: померен путь «поверхности банкноты → строки дельты», а НЕ то, что модель на английском пишет годные банкнотные таблицы (это платные вызовы); живой вызов всё равно стоит под гейтом терминолога. ⚠ Побочно названо, чтобы следующий пробник не потратил ход: `miner.MineBankStats` при `pack == nil` ПАНИКУЕТ (`backend/internal/miner/miner_patterns.go:181`), в боевом пути недостижимо — `runBankMiningStop` выходит раньше. Строка **35** остаётся про МАЙНЕР и заказывается отдельно. Сегодня не оплачено ни разу: 0 `manifest.txt` в `configs/`, каталог пары один. ⚠ D39.64 П4 ратифицировала ОБРАТНОЕ намерение («источник без пиньинь-морфологии грузится без Palladius-файлов») — строка `list at least one` не дошла шаг до собственной цели | бэкенд | когда-нибудь (вход пака второй пары; триггер общий со строками 81 и 35) | разрешение нулевого числа каналов + решение по форме каналов | research/33 Д7, D39.64 П4 | | 350 | ⚠ **ИСПОЛНЕНО 07.09 (`D39.225`) КРОМЕ ОДНОГО: по каждой из шести функций назван исход — четыре получили причину жизни комментарием («NO CALLER TODAY: contract surface waiting on backlog row 12»), дубль инлайна свёрнут в `finalStageName()`. ОСТАЁТСЯ словарь родов в четырёх носителях; текст его собственной ошибки врать перестал.** **РЕФАКТОРИНГ ОБЛЕГЧЕНИЯ ВЕДЕНИЯ (санкция владельца 07.09) — снапшот-нейтрально, и заказ здесь «решить», а не «удалить».** Вызовов вне определения ноль у шести функций (греп 07.09; КОНТРОЛЬ — `SplitChunks` 34 живых вызова): `obs.SafeGo`, `text.TokenizeCyrillic`, `CheapGateResult.UnitScaleHard`/`UnitScaleSoft`, `Bank.Voices()`, `Bank.Pairs()`. ⚠ **Четыре из шести стоят НАМЕРЕННО, и слепое удаление снимет намеренное:** `UnitScaleHard/Soft` сами называют, кого ждут — `checks/cheapgates.go:155-156`=`Total() is unchanged` «for the report and a future hard gate», то есть строку **12**; `TokenizeCyrillic` — образец паттерна value-default, на который ссылаются `checks/sanitizer.go:21`=`value-default pattern, like text.TokenizeCyrillic` и `:197`; `SafeGo` — намеренный контраст к `obs/panic.go`, названный решением `backend/internal/pipeline/waverun.go:420`=`NOT obs.SafeGo` — ⚠ испр. 16.09: было :405 («NOT obs.SafeGo»), и его удаление повесит два комментария в воздухе — класс строки **299**; `Voices`/`Pairs` (`membank/memory.go:371-376`=`address-register journal (frozen for` «frozen for the job») ждут потребителя, которого держит строка **13б**. ⇒ по каждой ОДИН исход с объявлением в отчёте: удалить ЛИБО назвать причину жизни в комментарии. Плюс ИМЯ последней стадии дважды одинаковым инлайном — `r.Pipeline.Stages[n-1].Name` — ⚠ **испр. 16.09: ДУБЛЬ УСТРАНЁН, предмет закрыт кодом:** оба места берут теперь общий хелпер (`backend/internal/pipeline/export.go:281`=`lastStage := r.finalStageName()` и `quality.go:485` тем же вызовом; инлайна `Stages[n-1].Name` в обоих файлах ноль, `finalStageName` по движку 4 вхождения). Прежний адрес был `pipeline/export.go:283` и `quality.go:342` (адреса на `d6dfc49`). ⚠ **Испр. 07.09: и research/33 §7.1, и первая редакция этой строки называли здесь «готовый `finalStageWave()`» — это ДРУГАЯ функция**: она возвращает ВОЛНУ (`snapshot.go:247`, вызовов 13 — 10 прод и 3 теста), а хелпера для ИМЕНИ не существовало вовсе, и «при готовом хелпере» читалось как «работа уже сделана» и словарь родов в четырёх носителях (`membank/memory.go`, `membank/memseed.go`, `backend/internal/terminology/classify.go:40`=`Genders is the closed vocabulary` — ⚠ испр. 16.09: было :50, промт), где текст собственной ошибки врёт о принимаемом множестве. ⛔ Границы санкции: НЕ дробить `internal/pipeline` и НЕ переписывать `Runner` (`12-go-style-notes.md` §1, D39.23), ничего, что двигает снапшот / хеш запроса / ключ манифеста. ⚠ Адреса сняты research/33 на `e69902a`, а лендинг 07.09 тронул `memseed.go` и `export.go` — пере-снимать командой, не по тексту | бэкенд | когда-нибудь | попутный проход с батареей + объявление исхода по каждой функции | research/33 §7.1, санкция владельца 07.09 | | 351 | **ЛИНТ СЛОВАРЯ КЛАССИФИКАТОРА ПИНИТ ОДНО НАПРАВЛЕНИЕ: слово, УБРАННОЕ из Go, не ловит ничто.** Гейт `TestEveryClassifierPromptSpeaksTheEnginesVocabulary` (лендинг `D39.225`) утверждает «каждое слово из `terminology.Types`/`Genders` названо в промте пары» — и потому сжимается вместе со своим предметом: выкинутый класс `title` оставляет батарею зелёной (замер 07.09 на копии: 19 ok / 0 FAIL). Вырожденный предел закрыт стражем `len(classifierVocabulary()) == 0`, общий случай — нет. Настоящий дом — пин САМОГО словаря, которого в репозитории нет (research/33 Д1: 0 тестов на `terminology.Types`). ⚠ Граница названа зоной самостоятельно, в заказ пака не входила | бэкенд | когда-нибудь | пин словаря (голден или рефлексивный тест) | `D39.225`, research/33 Д1 | | 352 | **ПЯТЬ РУКОПИСНЫХ СПИСКОВ АРМ-КОНФИГОВ ЖИВУТ РЯДОМ С ДВУМЯ ГЕЙТАМИ, КОТОРЫЕ ТЕПЕРЬ ГЛОБЯТ.** `pipeline/promptlabel_test.go:45`=`pipeline-arm-glm.yaml` · `config/echoregen_shipping_test.go:35`=`pipeline-arm-glm.yaml` · `config/content_labels_test.go:529`=`pipeline-c1.yaml` и `:575` · `config/prompt_pack_test.go:239`=`pipeline-arm-mistral.yaml` перечисляют армы поимённо; новый арм автоматически попадает в `TestAnArmIsTheProductionConfigWithADifferentEditor` и `TestSwapArmConfigs` и проходит мимо всех пяти. Найдено приёмкой `D39.225`, вне заказа пака; предсуществующее | бэкенд | когда-нибудь (со следующим касанием армов) | свести пять списков к глобу | `D39.225` | @@ -408,7 +407,6 @@ | 498 | ⛔⛔ **`prompt_override` НЕ СПРАШИВАЕТ ПРО ПАРУ, И ВСЕ ЧЕТЫРЕ БОЕВЫХ КОНФИГА УЖЕ НАЦЕЛЕНЫ НА `zh-ru` ⇒ АНГЛИЙСКАЯ КНИГА ПОЕДЕТ КИТАЙСКИМ ПРОМТОМ ПЕРЕВОДЧИКА МОЛЧА.** Конвенционный путь `//.md` падает ГРОМКО на отсутствующей паре именно затем, чтобы конвенции чужой пары не подставлялись тихо; `prompt_override` проверяет только ЧИТАЕМОСТЬ файла и про пару не спрашивает никогда. Замер с контролем (`tmctl manifest` на настоящей английской книге, `source_lang: en`): override на настоящий `backend/prompts/zh-ru/translator-banknote.md` → **`EXIT=0`**, конфиг грузится и в той же сводке печатает `en→ru`; контроль — override на несуществующий файл того же каталога → `EXIT=10` «prompt_override template … is not readable». ⇒ гард есть, но он про файл, а не про принадлежность. Зашито во ВСЕХ боевых: `backend/configs/pipeline-c1.yaml:77`, `backend/configs/pipeline-arm-glm.yaml:38`, `backend/configs/pipeline-arm-mistral.yaml:42` (все `../prompts/zh-ru/translator-banknote.md`), `backend/configs/pipeline-c2.yaml:43` (`../prompts/zh-ru/judge-selector.md`). ⛔ **Цена конкретна и она в КАЧЕСТВЕ, а не в падении:** английская книга получит промт, который велит «китайский 时辰 = 2 часа», «доля 成 — десятые» и требует банкнотную таблицу по китайским правилам. ⚠ Класс — «промт проверен НАЛИЧИЕМ файла, а не тем, чему он принадлежит»; это дверь, через которую возвращается латентный баг, ради которого конвенционный путь и сделан громким. **Обход данными существует** (своя пайплайн-копия книги с override на свою пару) и применён паком английской пары — но обход прячет цену: следующая пара наступит на то же и наступит молча. **Лечение:** override обязан лежать внутри каталога пары ЭТОЙ книги, иначе громкий отказ, называющий и путь, и пару; осознанный вариант роли (`editor-mono`, банкнота) этим не ломается — он и так в каталоге своей пары. ⚠ `PromptSHA256` берётся по СОДЕРЖИМОМУ, а не по пути ⇒ пере-снапшота правка не требует (предъявить замером до правки конфигов) | бэкенд | **скоро (БЛОКЕР ратификации готовности)** | ⚠ **ИСПР. 18.09 — ПРЕЖНИЙ КРИТЕРИЙ ОПИСЫВАЛ ФОРМУ, КОТОРУЮ МЫ ОТВЕРГЛИ, И ЗАКРЫВАТЬ РЯД ПО НЕМУ НЕЛЬЗЯ.** Он предписывал «гард отказывает на override вне каталога пары книги» — а это отменило бы **ратифицированное** свойство с живым пином `TestPromptOverrideIsPairAgnostic` (`backend/internal/config/prompt_pack_test.go:119`, гоняет три пары), чей докблок объявляет черновую стадию ЕДИНСТВЕННЫМ осознанным исключением из ролевой конвенции и говорит про ключ дословно «which is exactly what the convention keeps that key for». Сессия остановилась и пингнула вместо исполнения — по условию оркестратора, и условие окупилось: разрешение гарда было ошибкой оркестратора, не проверившего ратификацию. **НОВЫЙ КРИТЕРИЙ, по построенному:** ключ `prompt_variant` резолвит вариант роли ПО КОНВЕНЦИИ (`/<пара>/<роль>-<вариант>.md`) — достройка того, что данные уже используют именами `translator-banknote.md`/`editor-mono.md`; `prompt_override` сохраняет ратифицированное пар-агностичное значение и его пин **НЕ тронут ни строкой**; все четыре боевых конфига сняты с литерального `../prompts/zh-ru/…` и переведены на вариант; пин утверждает, что КАЖДАЯ стадия КАЖДОГО боевого конфига резолвится в каталог СВОЕЙ пары, считает по (конфиг, пара) и сообщает недобор числом; записи каталога с флагом `battery` | замер `textmachine-main-c5` 17.09 на английской книге, разрешение оркестратора | | 497 | ⛔ **ПИН КВАДРАТИЧНОСТИ ФЛЕЙКУЕТ НА ЗДОРОВОМ ДЕРЕВЕ И КРАСИТ ЧУЖОЙ ЛЕНДИНГ.** `TestEvidenceWindowsDoesNotGrowQUADRATICALLYWithTheBook` (`backend/internal/terminology/evidence_test.go:77`=`linear ≈4, quadratic ≈16`; размеры входа объявлены строками выше — `measure(2000)` и `measure(8000)`) утверждает ОТНОШЕНИЕ времён, и его докблок объясняет выбор так: «IT ASSERTS A RATIO, NOT A DURATION. A wall-clock threshold on a shared machine is a flake; the shape of the curve is the property». ⛔ **Посылка опровергнута замером: отношение защищает от РОВНОЙ нагрузки и слепо к её ИЗМЕНЕНИЮ между половинами.** Обе половины меряются ПОСЛЕДОВАТЕЛЬНО, а `go test ./...` гоняет пакеты параллельно — выросла контенция между малым и большим замером, и отношение раздулось, ничего об этом не сказав. ⚠ **Улика — два вердикта на ОДНОМ коммите `871e0af`:** приёмка оркестратора дала `MAKE_EXIT=0`, входная батарея следующей сессии — `MAKE_EXIT=2` с `ratio ×16.5` при пороге 16 (малый замер прошёл на 42.5 мс против изолированных 22, то есть уже вдвое медленнее). Изолированно пять прогонов оркестратора дают 4.3 · 4.3 · 3.1 · 4.6 · 5.7 — свойство ДЕРЖИТСЯ, негоден прибор. ⇒ **зелень приёмки была везением, а не замером**, и цена дефекта не в этом тесте, а в том, что он красит лендинг чужой зоны и заставляет её доказывать невиновность. **Форма лечения названа сессией:** мерить половины ВПЕРЕМЕЖКУ (A-B-A-B, брать медиану) либо нормировать на опорный замер той же секунды — тогда общая нагрузка сокращается по-настоящему, а не по предположению. ⚠ Родня ряда про «пин, флейковый на мутанте, измеряет пустой сценарий», но здесь хуже: флейк на ЗДОРОВОМ дереве | бэкенд | скоро | пин краснеет только на настоящей квадратичности: посадка «вернуть квадратичный `window()`» краснеет им, а десять прогонов полной батареи подряд — зелёные | найдено `textmachine-main-c5` на входной батарее 17.09, пере-снято оркестратором пятью изолированными прогонами | | 499 | ⛔ **ЭПИГРАФ ПРИЕЗЖАЕТ РАССЫПАННЫМ НА ТИПОГРАФСКИЕ СТРОКИ — НО ВИНОВАТ НЕ ДВИЖОК, А КОНВЕРТЕР ИЗДАТЕЛЯ; И ВТОРАЯ ФОРМА ЯВЛЕНИЯ ДВИЖКУ ВООБЩЕ НЕ ВИДНА.** ⚠ **ЧЕТВЁРТАЯ РЕДАКЦИЯ 18.09. Три предыдущие называли РАЗНЫЕ механизмы, и все три были неверны** — это носитель того, как дорого обходится объяснение вместо замера: (1) «вложенность блочной цитаты умножает переносы» — опровергнуто: `backend/internal/chunk/chunker.go:470`=`func splitParagraphs(chapter string) []string` делит по `\n\n` и ОТБРАСЫВАЕТ пустое; (2) «`

` внутри `

` есть строка стиха» — опровергнуто ЗАМЕРОМ по самому epub ДВУМЯ независимыми приборами (сессия `textmachine-main-c5` разбором 126 документов и советчик оркестратора): тегов `

` внутри цепочек `blockquote` **НОЛЬ**; (3) «это стих» — тоже неверно. ⭐ **ЧТО В МАТЕРИАЛЕ НА САМОМ ДЕЛЕ:** цепочек `blockquote` **88**, пустых 0, и **87 из 88 содержат ровно ОДНУ строку**, медиана длины **32 знака**; подряд идущие строки складываются в СВЯЗНУЮ ПРОЗУ эпиграфа, разбитую конвертером по ширине набора, а вложенность по CSS самого файла означает типографский ОТСТУП (`margin-left`), то есть след конвертера, а не структуру. `
` в книге **0**. ⇒ движок ведёт себя верно: он получает N абзацев и отдаёт N абзацев; беда в том, что издательский epub потерял границу между СТРОКОЙ и АБЗАЦЕМ ещё до нас. ⛔ **ВТОРАЯ ФОРМА, найденная только 18.09 и невидимая прежним замерам:** гимны и песни В ТЕЛЕ глав набраны не цепочками, а **курсивными абзацами по строке** — **154 строки в 32 блоках**. Движок их не видит ВООБЩЕ, потому что курсив до чанка не доезжает (ряд **500**): в обходчике ингеста ноль веток для инлайн-разметки, текст пишется безусловно (`backend/internal/chunk/ingest.go:1230`=`body.WriteString(text)`). ⇒ **суммарно ≈242 строки, а не 88.** ⛔ **ЛЕЧЕНИЕ — НЕ ДЕТЕКТОР, и это решение консилиума:** движок НЕ выносит вердикт «это стих»; он ДОНОСИТ СТРУКТУРУ на провод (образец — `pandoc`), а решает модель. Вторая форма закрывается починкой курсива из ряда 500 сама собой: прогон коротких помеченных абзацев модель опознаёт как стих без всякого порога. Первая форма закрывается языко-слепым правилом пары «несколько коротких абзацев подряд, каждый продолжает предыдущий, и ни один не реплика». ⛔ **ОТВЕРГНУТО ДВАЖДЫ и повторно подтверждено замером:** эвристика «абзац не кончается знаком конца предложения ⇒ это строка» есть ветвление по языку (знаки у пар разные) И вдобавок меряет не то: разбор «726 рваных абзацев» дал заголовки, обрывки оглавления и реплики, оборванные тире, — стиха среди них НЕТ. ⚠ Числа двух приборов не складывать: 726 снято регекспом сессии, 573 — прибором советчика на другой популяции. ⚠ Адрес `ingest.go:614` из полигонного письма относится к ДРУГОМУ чекауту (ветка `polygon` в `textmachine`), здесь `blockTags` на `:978` — различие деревьев, не ошибка автора | бэкенд | скоро (идёт ОДНИМ паком с рядом 500: носитель обеих форм — инлайн-разметка, и чинятся они одной правкой ингеста) | структура исходника доезжает до модели разметкой, а не теряется: курсивный спан приходит помеченным, прогон коротких строк опознаваем без порога и без ветвления по языку; пин на сквозной путь «разметка в epub → маркер в чанке → тег в экспорте», а не два пина по краям | замер `textmachine-main-c5` 17.09, ПЕРЕ-СНЯТ и опровергнут дважды 18.09; четвёртая редакция стоит на двух независимых разборах epub плюс замере оркестратора по коду ингеста | -| 500 | ⚠ **ПОДОЗРЕНИЕ, А НЕ ЗАМЕР: ИНГЕСТ EPUB, ПОХОЖЕ, ТЕРЯЕТ КУРСИВ ЦЕЛИКОМ — и носитель курсива тут НЕ инлайн-тег.** `backend/internal/chunk/ingest.go:1085`=`func extractXHTML(data []byte) (string, []RubyReading, error)` пишет текстовые токены; разметка следа не оставляет. Для художественного перевода курсив несёт эмфазу, мысль героя, чужеязычное слово и эпиграф — авторское средство, и восстановить его данными нельзя: его нет на входе. ⛔ **Разметка честная: сквозного замера «курсив не доезжает до чанка» НЕ делал никто** — ни сессия, ни оркестратор; сделано только чтение кода и счёт спанов. ⚠ **И поправка к МЕХАНИЗМУ, снятая оркестратором: `` — 0, `` — 0.** Курсив в этой книге несёт **CSS-класс**, и счёт спанов расходится по популяциям: у оркестратора 4842 (`class="…ital…"`), у советчика сессии 4863. ⇒ формулировка «инлайн-теги не оставляют следа» описывает не тот носитель, и починка «читать ``/``» не сработала бы вовсе: читать надо класс. Прежде чем строить — сквозной замер на одном документе: доезжает ли хоть один курсивный спан до текста чанка | бэкенд | скоро (сперва ЗАМЕР, потом решение) | предъявлен сквозной замер «курсив на входе → курсив в чанке» с названным знаменателем; по его итогу — ряд на починку либо закрытие с доводом | подозрение сессии `textmachine-main-c5` 17.09; механизм поправлен оркестратором (класс, а не тег) | | 501 | ⚠ **АНГЛИЙСКАЯ ОСЬ ПОЛИГОНА СНЯТА НА СПЛОШНОМ БЛОКЕ: ИСКАЖЁН АБСОЛЮТНЫЙ УРОВЕНЬ, КОНТРАСТЫ АРМОВ ЦЕЛЫ.** ⛔ **Разметка: это утверждение ПОЛИГОНА (`textmachine-b5`) о собственной работе, оркестратором НЕ пере-снятое**; носителем оно стало потому, что на этих числах стоят промты боевой английской пары — то есть предмет ратификаций, а не внутреннее дело зоны. Английский экстрактор полигона (`pair_en.raw_text`) сносил из epub теги регексом вместе с `

`: `eval/dovodka/podacha.py:19`=`11 447 абзацев, медиана 62 знака` — модель получала сплошной блок вместо одиннадцати тысяч абзацев. **Затронуты ВСЕ 273 английские клетки**, а не отдельные армы: восстановленную подачу получает единственный арм `RA` (`eval/dovodka/rol.py:162`=`RESTORE_ARMS = ("RA",)`), и он НЕ КУПЛЕН — 0 клеток ⇒ **цена дефекта не измерена ни разу**. ⭐ **Но контрасты держатся, и дефект был обойдён ОСОЗНАННО, а не пропущен:** вход у всех армов одинаково плоский, и довод автора стоит в самом коде (`eval/dovodka/rol.py:126`=`RA / RN — эффект ПОДАЧИ`; парная строка выше даёт `RN / ZP` как эффект ПРОМТА при одинаковом входе) ⇒ сравнение армов между собой чисто, искажён общий УРОВЕНЬ, на котором стоят все. **Уцелевает:** контрасты промтов и топологий (`RB > RC > RN`), вендорские сравнения, основание выбора формулировки владельца. **НЕ уцелевает:** любое утверждение об АБСОЛЮТНОМ качестве английского текста, о вёрстке, об абзацном строе и длине абзаца — и любой перенос английского числа на пару, где исходник абзацы не терял. **Два числа боевых промтов en-ru стоят на этом и помечены в доке зоны в месте цитирования:** вес ролевого промта 1.50/1.13 и «редактор на английском покупает» 1.22 против 2.78 ошибок на единицу — оба судейские, на английской панели, при разрешении прибора `eval/dovodka/KONSILIUM-22-08.md:159`=`разрешение 1.63 места на китайском` против 2.15 на английском. ⛔ **Починка экстрактора ретроактивно обнуляет адресацию купленного:** uid единицы есть `sha1(source.strip())`, любая правка пробелов переименовывает ВСЕ единицы — 289 оплаченных клеток на $2.64 теряют адресата вместе с судейскими ответами; поэтому диспозиция зоны (`eval/dovodka/KONSILIUM-22-08.md:141`=`Починка экстрактора абзацев`) велит чинить НА ПОДАЧЕ (`eval/dovodka/podacha.py:203`=`def restore_paragraphs`), сохраняя uid. ⚠ **Не путать с рядом 499:** там дефект ДВИЖКА (`

` внутри `

` читается как абзац прозы), здесь — дефект ПОЛИГОННОГО экстрактора (регексп снёс `

`); одной правкой не чинятся и в один ряд не сливаются. ⚠ **Третья оговорка автора, без которой ряд придётся переписывать:** после починки ингеста движка старые полигонные числа станут НЕСОПОСТАВИМЫ с новыми движковыми — они сняты на разном тексте, и следующая смена иначе сравнит несравнимое. Китайская пара не затронута вовсе: исходник txt, абзацы не терялись, арма `RA` у неё «нет и быть не может» | полигон (носитель — оркестратор) | скоро (гейт: перед любым ПЕРЕНОСОМ английского числа полигона в ратификацию) | ⚠ **КРИТЕРИЙ ПЕРЕ-РЕШЁН 18.09 ПО ВОЗРАЖЕНИЮ АВТОРА НАХОДКИ, и прежний был слабее:** я ставил закрытием «носить пометку», то есть документировал предмет бессрочно вместо того, чтобы его закрыть. Пометка не несёт МАСШТАБА — из неё нельзя узнать, искажение это два процента или полтора места, — и потому обесценивает чистые числа ровно настолько же, насколько защищает грязные. **Закрывается:** куплен арм `RA` (16 единиц, промт и жилец как у `RN`, отличие ТОЛЬКО в подаче) и контраст `RA/RN` даёт число цены подачи. ⛔ **Ограничение покупки, без которого она бесполезна:** `RA` берётся на ТОМ ЖЕ жильце и с ТЕМ ЖЕ уровнем усилия, что `RN` (`eval/dovodka/rol.py:623`=`dspro: вендор-дефолт high` — оба на вендор-дефолте), иначе контраст смешает подачу с усилием и родит второй такой же ряд вместо закрытия первого. **До покупки** каждое английское число полигона в носителях несёт пометку «абсолютный уровень искажён, контраст чист, **величина искажения НЕ измерена**»; пометка ВРЕМЕННАЯ и снимается или уточняется величиной по итогу `RA/RN`. ⚠ **Цена — вход владельцу, а не санкция:** ≈$0.45–0.51 (сумма купленных клеток `RB` $0.5089 и `RN` $0.4454 — пере-снято оркестратором, сошлось до цента; ⚠ знаменатель расходится по провенансу: 16 ЕДИНИЦ против 32 ФАЙЛОВ, у каждой единицы есть спутник `.ERROR.json`, и медиана по файлам вчетверо ниже медианы по единицам). ⚠ **История оси несёт 402, но единиц НЕ теряла — пере-снято оркестратором 18.09 по артефактам:** английских записей об ошибке 52, ненулевых по цене среди них 0, по роду — 44 × `APIStatusError 402 Insufficient` (упор в баланс провайдера), 5 × `RateLimitError 429`, 2 × `APIConnectionError`, 1 × `BadRequestError 400`. ⛔ **Но у КАЖДОЙ ошибочной единицы есть та же единица с содержимым** (пересечение uid: `RB` 16/16, `RC` 16/16, `RN` 14/14, `RGT` 5/5), потерянных единиц НОЛЬ, и у всех тринадцати армов ровно по 16 единиц с содержимым ⇒ риг ретраил и добирал состав полностью. ⇒ **опасение «покупка потребует второго захода» замером НЕ поддержано**, а требование считать контраст по пересечению непустых остаётся верным по другой причине: у `RN` одна из 16 единиц несёт ПУСТОЕ содержимое (класс «доставленная пустота», ряды 414–415). ⚠ Провенанс счёта: «273 английские клетки» есть ФАЙЛЫ (включая спутники `.ERROR.json`), единиц с содержимым по 16 на арм. Зона полигона выведена из скоупа словом владельца 11.09 ⇒ покупку решает ОН | утверждение `textmachine-b5` 18.09; все пять адресов пере-проверены оркестратором | -| 502 | ⛔ **УПОР В БАЛАНС ПРОВАЙДЕРА НЕ ИМЕЕТ СОБСТВЕННОГО ИСХОДА: ПРОВОД КЛАССИФИЦИРУЕТ ЕГО ВЕРНО, А ОПЕРАТОР ПОЛУЧАЕТ ОБЫЧНОЕ ТЕРМИНАЛЬНОЕ ПАДЕНИЕ СТАДИИ.** ⚠ Разметка честная: **снято ЧТЕНИЕМ КОДА, живого 402 не исполнял** — движок в этом состоянии не гонялся. **Что построено и работает:** `backend/internal/llm/httpllm.go:691`=`func retryableStatus(status int, body []byte) bool` есть ЕДИНСТВЕННЫЙ источник раздела «повторять/терминально» и стережётся дрейф-гардом; 402 терминален по умолчанию (`:698`=`terminal 4xx (incl. 402 Payment Required)`), а 429 с телом об исчерпанных кредитах тоже терминален — узкий набор маркеров `:710`=`insufficient_quota` / `quota_exceeded`, и довод стоит рядом: повтор под удержанной резервацией жжёт только время, потому что «the operator must top up». ⇒ **денег на пустые ретраи мы не тратим, и это важно сказать первым.** ⛔ **Дыра выше провода:** типизированный `HTTPStatusError` (`backend/internal/llm/httpllm.go:717`) не покидает пакет `llm` — 7 упоминаний, ВСЕ в `internal/llm`, в конвейере ноль; ошибка едет наверх обёрнутым текстом (`%w`), а перечислимых причин в `backend/internal` **43**, и **ни одна** не про кредиты провайдера (контроль: строк со словом `reason` — 943; единственный хит шаблона «причина + кредиты» — посторонний комментарий `backend/internal/pipeline/rebill.go:269`). ⇒ «у провайдера кончились деньги» и «стадия упала терминально» на уровне ИСХОДА неразличимы; тело ответа провайдера доезжает до человека только внутри текста обёрнутой ошибки. ⛔ **Почему это гейт готовности, а не гигиена:** предстоят ДВЕ книги по 20 глав ПАРАЛЛЕЛЬНО, и прогон, встретивший 402 на середине, останавливается наполовину купленным; оператору нужно за секунды отличить «пополни счёт» от «движок сломался», а сегодня он это читает из текста ошибки. ⚠ **Событие не гипотетическое:** на английской оси полигона 44 записи об ошибке из 52 — ровно `APIStatusError 402 Insufficient` (ряд **501**), то есть провайдер уже упирался в баланс, и заметили это постфактум, разбирая артефакты. | бэкенд | **скоро (кандидат в блокеры ратификации готовности к эксперименту двух переводов)** | у исчерпания кредитов провайдера есть НАЗВАННЫЙ исход, отличимый от обычного терминального падения стадии, и он виден оператору прогона; пин краснеет, когда тело с 402 превращается в родовую причину | замер оркестратора 18.09 чтением кода; повод — находка `textmachine-b5` о 44 отказах по балансу на английской оси | +| 502 | ⚠ **ПОЛОВИНА ЗАКРЫТА 18.09 актом `D39.268`:** имя исчерпания средств провайдера печатается человеку — в последней строке прогона и в записи об ошибке. **ОСТАЁТСЯ ПРОГРАММНАЯ ПОЛОВИНА:** нового кода возврата и нового слова в словаре кадров НЕ добавлено намеренно — словарь есть замороженный шов, и его расширение является решением, а не правкой пака. ⛔ **УПОР В БАЛАНС ПРОВАЙДЕРА НЕ ИМЕЕТ СОБСТВЕННОГО ИСХОДА: ПРОВОД КЛАССИФИЦИРУЕТ ЕГО ВЕРНО, А ОПЕРАТОР ПОЛУЧАЕТ ОБЫЧНОЕ ТЕРМИНАЛЬНОЕ ПАДЕНИЕ СТАДИИ.** ⚠ Разметка честная: **снято ЧТЕНИЕМ КОДА, живого 402 не исполнял** — движок в этом состоянии не гонялся. **Что построено и работает:** `backend/internal/llm/httpllm.go:691`=`func retryableStatus(status int, body []byte) bool` есть ЕДИНСТВЕННЫЙ источник раздела «повторять/терминально» и стережётся дрейф-гардом; 402 терминален по умолчанию (`:698`=`terminal 4xx (incl. 402 Payment Required)`), а 429 с телом об исчерпанных кредитах тоже терминален — узкий набор маркеров `:710`=`insufficient_quota` / `quota_exceeded`, и довод стоит рядом: повтор под удержанной резервацией жжёт только время, потому что «the operator must top up». ⇒ **денег на пустые ретраи мы не тратим, и это важно сказать первым.** ⛔ **Дыра выше провода:** типизированный `HTTPStatusError` (`backend/internal/llm/httpllm.go:717`) не покидает пакет `llm` — 7 упоминаний, ВСЕ в `internal/llm`, в конвейере ноль; ошибка едет наверх обёрнутым текстом (`%w`), а перечислимых причин в `backend/internal` **43**, и **ни одна** не про кредиты провайдера (контроль: строк со словом `reason` — 943; единственный хит шаблона «причина + кредиты» — посторонний комментарий `backend/internal/pipeline/rebill.go:269`). ⇒ «у провайдера кончились деньги» и «стадия упала терминально» на уровне ИСХОДА неразличимы; тело ответа провайдера доезжает до человека только внутри текста обёрнутой ошибки. ⛔ **Почему это гейт готовности, а не гигиена:** предстоят ДВЕ книги по 20 глав ПАРАЛЛЕЛЬНО, и прогон, встретивший 402 на середине, останавливается наполовину купленным; оператору нужно за секунды отличить «пополни счёт» от «движок сломался», а сегодня он это читает из текста ошибки. ⚠ **Событие не гипотетическое:** на английской оси полигона 44 записи об ошибке из 52 — ровно `APIStatusError 402 Insufficient` (ряд **501**), то есть провайдер уже упирался в баланс, и заметили это постфактум, разбирая артефакты. | бэкенд | **скоро (кандидат в блокеры ратификации готовности к эксперименту двух переводов)** | у исчерпания кредитов провайдера есть НАЗВАННЫЙ исход, отличимый от обычного терминального падения стадии, и он виден оператору прогона; пин краснеет, когда тело с 402 превращается в родовую причину | замер оркестратора 18.09 чтением кода; повод — находка `textmachine-b5` о 44 отказах по балансу на английской оси | | 503 | ⛔ **ЗАБОР РЕ-ПИНА ПРОПУСКАЕТ ТОЛЬКО ОДНУ ОСЬ, ПОЭТОМУ КАЖДОЕ СЛЕДУЮЩЕЕ ОБЪЯВЛЕНИЕ ПАРЫ БУДЕТ ПЕРЕПОКУПАТЬ БАЙТ-ИДЕНТИЧНЫЕ КНИГИ.** Движок УЖЕ умеет исход «снапшот двинулся, а байты нет — $0»: это ре-пин (`backend/internal/pipeline/repin.go:61`=`func classifySnapshotMove`). Но забор пускает в него ровно ОДНУ ось — банк памяти; любое иное расхождение полей классифицируется как «прочее» и требует полной перепокупки. ⇒ когда пара объявит опциональный пар-файл (любой из контракта `ABSENT → inert, PRESENT → байты фолдятся`), версия её пакета сдвинется у ВСЕХ её книг, включая те, чей ТЕКСТ не изменился ни на байт — например текстовые книги, для которых новая возможность недостижима по построению. ⚠ **Это ЛОЖНАЯ перепокупка, то есть безопасная сторона ошибки: она видна в проекции согласия и не портит текст.** Но это деньги, и с каждой новой парой их будет больше. ⛔ **Направление лечения названо советчиком и НЕ спроектировано:** расширить забор на «wire-нейтральные оси» — ход, при котором отличаются только оси, чьё действие целиком лежит в отправляемых сообщениях (нарезка · встроенные данные · нормализация · пакет пары), И при этом контент-хеш совпал; вердикт-несущие оси (классификатор · дешёвые гейты · экран цели) остаются «прочим». ⚠ Граница «ось лежит целиком в сообщениях» доказывается ПО КАЖДОЙ оси отдельно — это дизайн, а не правка условия. ⛔ **И почему это НЕ делается перед прогоном:** `repin.go` есть денежно-критичный путь, а ошибка в заборе даёт исход, противоположный нынешнему — тихую НЕ-перепокупку там, где заплатить надо. Прогон идёт с нынешним поведением, цена названа вслух. | бэкенд | скоро (после прогона; до него — ТОЛЬКО назвать цену в акте, не трогать) | забор ре-пина различает wire-нейтральный ход от вердикт-несущего, граница каждой оси доказана отдельно, и пин краснеет на попытке пропустить вердикт-несущую ось как нейтральную | разбор советчика 18.09 при ратификации условного фолда маркера разметки; несущие утверждения пере-сняты оркестратором (контент-гард `backend/internal/pipeline/stagerun.go:92`=`cs.ContentHash == contentHash`; образец — коммит `2f91b04`, 207 строк в нарезчик при нетронутой константе версии) | diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 83f666ac..b1a2e421 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -1,6 +1,6 @@ # Журнал прогресса -> **⟶ ТЕКУЩЕЕ СОСТОЯНИЕ** (на 2026-09-18, голова D39.267 — КУРС: движок и платформа до «работает и отдаёт результат», фронт ЗАМОРОЖЕН и P7 его НЕ размораживает (D39.147). **ОЧЕРЕДЬ №23** (единственный носитель — здесь; роль передана 06.09, №22 закрыт нотой передачи D39.217; ⚠ испр. 06.09: коммит передачи `c992ee5` бампнул голову и НЕ тронул номер — гейта на номер очереди нет вовсе, `counts.py` сверяет только голову, поэтому носитель разошёлся молча). ⚠ **ЗАКАЗ ВЛАДЕЛЬЦА 01.09 — ИСПОЛНЕН, испр. 08.09 (висел как «первым» неделю после исполнения):** (0а) ревизия документации на протухшее ОТРАБОТАНА 01.09 воркфлоу `docs-staleness-revision-A` (15 срезов), провенанс находок — `D39.185`; (0б) планы доработок в бэкенд и платформу — исполняются ПАКАМИ, за 07–08.09 закрыты два движковых (`D39.225`, `D39.226`); (0в) вынос неактуального в архив идёт батчами `DOC_CLEANUP_PLAN.md` (Б14/Б15/Б17 живы). ⇒ строка ниже — не заказ, а история: (0а) ревизия документации на ПРОТУХШЕЕ — по всем зонам; (0б) планы доработок в БЭКЕНД и ПЛАТФОРМУ; (0в) вынос неактуального в АРХИВ (`docs/archive/`, `platform/docs/archive/`) — за сутки 31.08 закрыто много, и часть носителей стала историей. ⚠ Трезвость по масштабу (пере-считано 02.09): **95** живых доков в `docs/` (⚠ испр. 17.09 вечером: стояло **98**, и это был ЛОЖНЫЙ литерал, а не потеря файлов — сверка дерева со срезом головы предписанной здесь же командой дала 95 в ОБЕИХ сторонах, ни одного файла не ушло и не пришло; ошибся сам пере-счёт, а прибор это число не сторожит и потому ложь прожила день. В 95 уже входит промт выдачи №14; пере-счёт после выноса каталога консилиума; прежние 97 разошлись с фактом 144 и это заметил ревизор, а не гейт) (пере-счёт 04.09: `find docs -name '*.md' -not -path 'docs/archive/*' | wc -l`), 8 в `platform/docs`, **12** в `backend/docs`, **7** в `frontend/docs` (испр. 17.09: стояло 9) — ⚠ ⚠ испр. 11.09: из 97 ВРЕМЕННЫХ **три** (`DOC_CLEANUP_PLAN`, живой до закрытия батчей Б14/Б15/Б17); два прежних временных уехали в `archive/reports/` 02.09; счёт бэклога — бюллетенем ниже, открытых рядов регистра платформы — 109 (major 0), всего рядов 469 (пере-счёт `python3 docs/scripts/counts.py`; с 04.09 оба числа под гардом `--check`, прежние 95/3 разошлись молча) ⚠ (ревизией 02.09 ряды **154** и **157** переведены из «скоро» в «когда-нибудь»: их гейтом стоял первый холодный прогон, он ОТРАБОТАЛ 31.08 и оба предусловия оказались другими — разбор в самих ячейках, ни одна НЕ закрыта). ⚠ Числа доков `counts.py` НЕ сторожит — при переносе файлов пере-считывать руками командой `find docs -name '*.md' -not -path 'docs/archive/*' | wc -l`. ⚠ И предупреждение о МЕТОДЕ, купленное сменой №21: «выглядит протухшим» ≠ «протухло». Три факта оркестратора опровергнуты ЗАМЕРОМ сессий, а якоря `15-money-path.md` в девяти случаях из двенадцати РОДИЛИСЬ верными и сгнили дрейфом — то есть ревизия обязана быть исполнением, а не чтением. ⚠ **ОЧЕРЕДЬ, унаследованная от №21** (три лендинга 31.08 — секция «СОСТОЯНИЕ ПАКОВ» ниже): **(1) ~~РАЗРЫВ ЦИКЛА~~ ЗАМКНУТ ЖИВЬЁМ 04.09** — пользователь получил EPUB настоящего ПЛАТНОГО перевода ЧЕРЕЗ API, `epubcheck` 5.3.0 на СКАЧАННОМ файле 0/0/0/0 (книга `bk_SS5VES2JELESJSTR`, потрачено $0.278319 из гранта $0.60 при потолке пака $1.5, санкция D39.189). Дверь выдачи построена и проверена исполнением: `202`+`Location`, поллинг с `Retry-After`, Range 206 · второй клиент 200 · аноним 401 · чужая книга 404, TTL с GC, идемпотентность третьего создающего вызова. Все ТРИ сценария строки 216 предъявлены живьём (подпись банка · halt на потолке с exit 4 · `409 run_not_resumable/ceiling_reached` и лечение новым прогоном). +> **⟶ ТЕКУЩЕЕ СОСТОЯНИЕ** (на 2026-09-18, голова D39.268 — КУРС: движок и платформа до «работает и отдаёт результат», фронт ЗАМОРОЖЕН и P7 его НЕ размораживает (D39.147). **ОЧЕРЕДЬ №23** (единственный носитель — здесь; роль передана 06.09, №22 закрыт нотой передачи D39.217; ⚠ испр. 06.09: коммит передачи `c992ee5` бампнул голову и НЕ тронул номер — гейта на номер очереди нет вовсе, `counts.py` сверяет только голову, поэтому носитель разошёлся молча). ⚠ **ЗАКАЗ ВЛАДЕЛЬЦА 01.09 — ИСПОЛНЕН, испр. 08.09 (висел как «первым» неделю после исполнения):** (0а) ревизия документации на протухшее ОТРАБОТАНА 01.09 воркфлоу `docs-staleness-revision-A` (15 срезов), провенанс находок — `D39.185`; (0б) планы доработок в бэкенд и платформу — исполняются ПАКАМИ, за 07–08.09 закрыты два движковых (`D39.225`, `D39.226`); (0в) вынос неактуального в архив идёт батчами `DOC_CLEANUP_PLAN.md` (Б14/Б15/Б17 живы). ⇒ строка ниже — не заказ, а история: (0а) ревизия документации на ПРОТУХШЕЕ — по всем зонам; (0б) планы доработок в БЭКЕНД и ПЛАТФОРМУ; (0в) вынос неактуального в АРХИВ (`docs/archive/`, `platform/docs/archive/`) — за сутки 31.08 закрыто много, и часть носителей стала историей. ⚠ Трезвость по масштабу (пере-считано 02.09): **95** живых доков в `docs/` (⚠ испр. 17.09 вечером: стояло **98**, и это был ЛОЖНЫЙ литерал, а не потеря файлов — сверка дерева со срезом головы предписанной здесь же командой дала 95 в ОБЕИХ сторонах, ни одного файла не ушло и не пришло; ошибся сам пере-счёт, а прибор это число не сторожит и потому ложь прожила день. В 95 уже входит промт выдачи №14; пере-счёт после выноса каталога консилиума; прежние 97 разошлись с фактом 144 и это заметил ревизор, а не гейт) (пере-счёт 04.09: `find docs -name '*.md' -not -path 'docs/archive/*' | wc -l`), 8 в `platform/docs`, **12** в `backend/docs`, **7** в `frontend/docs` (испр. 17.09: стояло 9) — ⚠ ⚠ испр. 11.09: из 97 ВРЕМЕННЫХ **три** (`DOC_CLEANUP_PLAN`, живой до закрытия батчей Б14/Б15/Б17); два прежних временных уехали в `archive/reports/` 02.09; счёт бэклога — бюллетенем ниже, открытых рядов регистра платформы — 109 (major 0), всего рядов 469 (пере-счёт `python3 docs/scripts/counts.py`; с 04.09 оба числа под гардом `--check`, прежние 95/3 разошлись молча) ⚠ (ревизией 02.09 ряды **154** и **157** переведены из «скоро» в «когда-нибудь»: их гейтом стоял первый холодный прогон, он ОТРАБОТАЛ 31.08 и оба предусловия оказались другими — разбор в самих ячейках, ни одна НЕ закрыта). ⚠ Числа доков `counts.py` НЕ сторожит — при переносе файлов пере-считывать руками командой `find docs -name '*.md' -not -path 'docs/archive/*' | wc -l`. ⚠ И предупреждение о МЕТОДЕ, купленное сменой №21: «выглядит протухшим» ≠ «протухло». Три факта оркестратора опровергнуты ЗАМЕРОМ сессий, а якоря `15-money-path.md` в девяти случаях из двенадцати РОДИЛИСЬ верными и сгнили дрейфом — то есть ревизия обязана быть исполнением, а не чтением. ⚠ **ОЧЕРЕДЬ, унаследованная от №21** (три лендинга 31.08 — секция «СОСТОЯНИЕ ПАКОВ» ниже): **(1) ~~РАЗРЫВ ЦИКЛА~~ ЗАМКНУТ ЖИВЬЁМ 04.09** — пользователь получил EPUB настоящего ПЛАТНОГО перевода ЧЕРЕЗ API, `epubcheck` 5.3.0 на СКАЧАННОМ файле 0/0/0/0 (книга `bk_SS5VES2JELESJSTR`, потрачено $0.278319 из гранта $0.60 при потолке пака $1.5, санкция D39.189). Дверь выдачи построена и проверена исполнением: `202`+`Location`, поллинг с `Retry-After`, Range 206 · второй клиент 200 · аноним 401 · чужая книга 404, TTL с GC, идемпотентность третьего создающего вызова. Все ТРИ сценария строки 216 предъявлены живьём (подпись банка · halt на потолке с exit 4 · `409 run_not_resumable/ceiling_reached` и лечение новым прогоном). > ⛔ **ПЯТЬ ПОТОКОВ РАБОТЫ — состояние на 07.09 (пере-снято лендингами смены №23).** > **(1) ПОЛИГОН — «ремонт прибора»** (`docs/POLYGON_INSTRUMENT_REPAIR_SESSION_PROMPT.md`, строки 319 · 300 · 265 · 143): > ⚠ **ЕДИНСТВЕННЫЙ ПОТОК, НЕ СДВИНУВШИЙСЯ ЗА СМЕНУ — сессия по промту так и не стартовала.** Блокирующая линза diff --git a/docs/README.md b/docs/README.md index bd5b101c..4a8b1522 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,7 +24,7 @@ - **Активные хендофф-промты — какой файл ТВОЙ** (состав обновляется при каждом лендинге, D39.80; хроника, причины и статусы РАБОТ — CURRENT-STATE и D-лог): | Роль | Активный промт | Статус | |---|---|---| -| **Бэкенд · ДОСТИЖИМОСТЬ ПАР-ДАННЫХ (готовность к прогону)** | [BACKEND_RUN_READINESS_SESSION_PROMPT.md](BACKEND_RUN_READINESS_SESSION_PROMPT.md) | **ВЫДАН 18.09** свежей сессии `textmachine-main-c8`. Предмет — не «убрать китайское из Go» (ветвлений там почти не осталось: 6 упоминаний кодов языка при контроле 154 файла, живых два и оба законны), а **недостижимость данных второй пары**: английская книга сегодня ГРОМКО отказывает на боевом конфиге до первого цента. Шесть пунктов, порядок ФИКСИРОВАН — §4.1 первым, иначе остальные нечем предъявить. Редакция 2: первая переписана после опровергателя (8 мажоров), пяти верификаторов и ревью сдавшей сессии — три якоря целили не туда, один пункт вынут замером (гейт латиницы: на этом прогоне не меняет ничего, что видит модель, а бамп версии двигает снапшот ОБЕИХ книг), а §4.2 был сформулирован так, что его можно было закрыть честно и НЕ сделать работу. Оба рубежа пройдены: механическая сверка 13 блоков (13 якорей, битых 0, коротких 0, голых адресов 0) и субагент-опровергатель | +| Бэкенд · ДОСТИЖИМОСТЬ ПАР-ДАННЫХ | активного НЕТ | пак ОТРАБОТАН и **ПРИНЯТ 18.09** — акт **`D39.268`**, лендинг `9defda4` (38 файлов, 1855/66, $0) + `e6f9a3b`; промт в `archive/prompts/` с баннером. Кампания **336/336 поймано, 0 выживших, 0 НЕ ИЗМЕРЕНО**. ⭐ Предмет пере-определён замером ДО выдачи: языковых ветвлений в Go шесть при контроле 154 файла, живых два и оба законны ⇒ остаточная зависимость есть НЕДОСТИЖИМОСТЬ ДАННЫХ. **Английская книга доезжает на боевом конфиге** и встаёт на потолке до первого вызова. Ряды 347 и 500 закрыты, 272 и 502 половинами | | Бэкенд · АНГЛИЙСКАЯ ПАРА en→ru | активного НЕТ | пак ОТРАБОТАН и **ПРИНЯТ 18.09** — акт **`D39.267`**, лендинг `ddadb3e` (32 файла, 1356/127, $0) + `63e3a0d`; промт в `archive/prompts/` с баннером-исходом. Кампания **327/327 поймано, 0 выживших, 0 НЕ ИЗМЕРЕНО**, сумма исходов = составу гейта. ⭐ Пак заменил защиту, державшуюся ОТСУТСТВИЕМ второго промт-пакета, на механизм, и нашёл это у себя сам. Живое продолжение предмета — пак достижимости пар-данных | | Платформа · ПРОГОН НЕ ВРЁТ О СЕБЕ | активного НЕТ | пак ОТРАБОТАН и **ПРИНЯТ 17.09** — акт **D39.265** (32 пути, $0, контрактный минор **0.17.0**); промт в [archive/prompts/](archive/prompts/PLATFORM_RUN_TELLS_THE_TRUTH_SESSION_PROMPT.md) с баннером-исходом. Ряды **398** · **399** · **400** · **486** закрыты работой, **394** и **396** — ПЕРЕ-РЕШЕНИЕМ (четвёртое значение в клиентский словарь не идёт: «мы сами перестали перезапускать» — другая ось, чем «стоит ли повторять», и границу между осями стережёт новый гейт на три носителя), **416** — платформенной половиной. Кампания пере-снята приёмкой: 26 записей · поймано 25 · выжила 1, объявленная ДО прогона · неизмеренных 0. ⛔ Гейт зоны красен на экземпляре ряда **484** (фикстурный бюджет записи под нагрузкой; оба упавших теста живут в чистом `HEAD`) — названо границей, а не зеленью. ⚠ Две ошибки приёмки названы в акте: оркестратор взял себе правку канона (откачена) и неточно сформулировал §4.1 промта. Живое — ряды **416** (движковая половина) · **484** · **493** · **494** | | Бэкенд · РЕШЁННОЕ НЕ ПЕРЕ-СПРАШИВАЕТСЯ | активного НЕТ | пак ОТРАБОТАН и **ПРИНЯТ 17.09** — акт **`D39.266`** (`d25e418`, 32 пути, $0); промт в [archive/prompts/](archive/prompts/BACKEND_SETTLED_STAYS_SETTLED_SESSION_PROMPT.md) с баннером-исходом. Решённая строка переживает покупку: носитель — таблица `bank_basis`, миграция v19, аддитивная. Ряд **490** закрыт по трём условиям, **130** получил ТРЕТИЙ исход (замысел достигнут другим механизмом, стоп-решение за владельцем), два отказа с замером, заведён **496**. Числа приёмки оркестратора: кампания **315/315 поймано, выживших 0, неизмеренных 0**; M1 — **67 из 69** и **64 из 66** обслужено из памяти. ⛔ Приёмка нашла две дыры ОДНОГО класса — не неверное число, а отсутствующее утверждение — и купила норму «сверять перечень заказа по СПИСКУ ЗАКАЗЧИКА». Выдавался 17.09 сессии `textmachine-main-57` (свежая: паков не брала, контекст пуст — проверено опросом, а не списком). ⚠ Свежих нашлось ДВЕ; вторая (`textmachine-main-78`) оставлена нетронутой, ей сказано не читать промт и не занимать зону — один промт на зону. Предмет: движок на каждой покупке заново платит банк-ролям за решённые термины — 12 из 69 и 14 из 66 смен передачи при неизменной улике у 25 из 26 строк; потолки ролей ПОЖИЗНЕННЫЕ. Строит базис решённого (ряд **130**) и стража разрыва окон (ряд **490**). Два рубежа пройдены: механическая сверка 13 блоков (27 якорей, все живы) и субагент-опровергатель — **12 находок, 9 денежных, все внесены**, включая мою ложь «текста в коде нет» о живой строке и материал замера, из которого предмет не строился. $0 | diff --git a/docs/architecture/05-decisions-index.md b/docs/architecture/05-decisions-index.md index b2809253..ef522b41 100644 --- a/docs/architecture/05-decisions-index.md +++ b/docs/architecture/05-decisions-index.md @@ -1,4 +1,4 @@ -# Реестр D-нот — карта актуальности v2 (D1–D39.267; титул — носитель головы, бампать при каждом аппенде) +# Реестр D-нот — карта актуальности v2 (D1–D39.268; титул — носитель головы, бампать при каждом аппенде) > ⚠ **Колонку «тело» `counts.py --check` НЕ сторожит по устройству:** он сверяет полноту НОМЕРОВ, а не > место тела, поэтому колонка держится дисциплиной лендинга. Не нашёл тело по колонке — иди в слайсы, @@ -326,3 +326,4 @@ | D39.265 | 17.09 | **ПРИЁМКА ПЛАТФОРМЕННОГО ПАКА «ПРОГОН НЕ ВРЁТ О СЕБЕ»** — 32 пути, $0, контрактный минор **0.17.0** (`Run.progress_lagging` и `Run.rebill_consent_micro_usd`). Закрыты работой ряды **398** · **399** · **400** · **486**, ПЕРЕ-РЕШЕНИЕМ — **394** (четвёртое значение в клиентский словарь не идёт: «мы сами перестали перезапускать» — другая ось, чем «стоит ли повторять», и границу стережёт гейт на три носителя) и **396** («оставить, с капом как условием»), половиной — **416**. Кампания пере-снята оркестратором: 26 записей · поймано 25 · выжила 1 (объявлена до прогона) · неизмеренных 0. ⛔ Гейт зоны красен на экземпляре ряда **484** (фикстурный бюджет записи под нагрузкой), оба теста живут в чистом `HEAD`. Находки приёмки: канон описывал происхождение денежного согласия у́же кода · всегда-посылаемый член вне `required` · харнесс читает пустой шаблон как выжившую. ⚠ Две мои ошибки: взял себе правку канона (откачена) и неточная посылка §4.1 промта | приёмка | `docs/archive/prompts/PLATFORM_RUN_TELLS_THE_TRUTH_SESSION_PROMPT.md` | | D39.266 | 17.09 | **ПРИЁМКА БЭКЕНД-ПАКА «РЕШЁННОЕ НЕ ПЕРЕ-СПРАШИВАЕТСЯ»** — `d25e418`, 32 пути, $0. Решённая движком строка переживает покупку: носитель — таблица `bank_basis` (миграция v19, аддитивная, `memory_version` не двигает). РАТИФИЦИРОВАНЫ смена поведения (первый прогон после появления базиса платит ОДИН раз за переупаковку хвоста батчей: run1/run2 по `$0.001820`, run3/run4 по нулю) и пятая роль онтологии — ПАМЯТЬ РЕШЕНИЙ со второй петлёй защиты подписанного. Ряды: **490** закрыт по трём условиям (страж · живой путь · посадка), **130** получил ТРЕТИЙ исход — замысел достигнут другим механизмом, механизм ряда не построен намеренно, стоп-решение остаётся за владельцем, остаток сужен до двух предметов; **447** и сторож растущей книги — отказы с замером; заведён **496**. Числа приёмки сняты оркестратором: батарея `MAKE_EXIT=0` 24=24 при 11 названных скипах, пять корпусных тестов предъявлены исполнением, кампания **315/315 поймано, выживших 0, неизмеренных 0** с полнотой в обе стороны, M1 — **67 из 69** и **64 из 66** обслужено из памяти при верности реконструкции без расхождений. ⛔ Приёмка нашла в отчёте две дыры ОДНОГО класса — не неверное число, а отсутствующее утверждение (прибор, не названный прибором; заказанный ряд без исхода), и купила норму: **собственные проверки не находят отсутствующее, потому что знаменателем им служит свой же текст** ⇒ сверять перечень заказа по СПИСКУ ЗАКАЗЧИКА. ⚠ Шесть ошибок оркестратора названы в теле, включая два ложных ноля по `books/` от двух РАЗНЫХ приборов | приёмка | `docs/archive/prompts/BACKEND_SETTLED_STAYS_SETTLED_SESSION_PROMPT.md` | | D39.267 | 18.09 | **ПРИЁМКА БЭКЕНД-ПАКА «АНГЛИЙСКАЯ ПАРА en→ru»** — `ddadb3e` (32 файла, 1356/127, $0) + `63e3a0d` (отчёт зоны). Кампания **327/327 поймано, 0 выживших, 0 НЕ ИЗМЕРЕНО**, сумма исходов = составу гейта, корень сверен с `ddadb3e:backend` после кампании (0 расхождений). Ратифицирована замена защиты, державшейся ОТСУТСТВИЕМ, на механизм: пакет пары убирал пустоту, из-за которой английская книга отказывалась, и книга поехала бы китайским промтом молча. Веер 57 находок, 9 — дефекты собственной работы зоны. Решение владельца «данные работают там, где явления нет» исполнено подъёмом правила до КЛАССА. Ряды 501·502·503 заведены, 499 переписан четвёртой редакцией. ⚠ Мои ошибки: выдал следующий пак в НЕосвобождённую зону (норма через «я» слепа к делегированию) и пять ложных нулей прибора | приёмка | +| D39.268 | 18.09 | **ПРИЁМКА БЭКЕНД-ПАКА «ДОСТИЖИМОСТЬ ПАР-ДАННЫХ»** — `9defda4` (38 файлов, 1855/66, $0) + `e6f9a3b`. Кампания **336/336 поймано, 0 выживших, 0 НЕ ИЗМЕРЕНО**, сумма = составу гейта. ⭐ Предмет ПЕРЕ-ОПРЕДЕЛЁН замером до выдачи: языковых ветвлений в Go шесть при контроле 154 файла, живых два и оба законны ⇒ остаточная зависимость есть НЕДОСТИЖИМОСТЬ ДАННЫХ, а не грязь в коде. Ратифицированы условный фолд как ФОРМА (три условия, прецедент — пак заголовков) и пар-скоупный лейбл промта. Китайская половина неподвижна — доказано ВХОДАМИ (0 тронутых, 0 версий-констант), а не совпадением хешей. Два отказа зоны приняты с замером. Ряды 347 и 500 ЗАКРЫТЫ, 272 движковой половиной, 502 половиной, 303 не тронут. **Английская книга доезжает на боевом конфиге — вход прогона открыт** | приёмка | diff --git a/docs/architecture/05-decisions-log.md b/docs/architecture/05-decisions-log.md index bc141e1f..2b58acb7 100644 --- a/docs/architecture/05-decisions-log.md +++ b/docs/architecture/05-decisions-log.md @@ -1,4 +1,4 @@ -# Журнал решений оркестратора — контракт D1–D39.267 (живой файл: карта · эрраты · живые тела · голова D39.124+ (подрезка D39.139); тела закрытых эр — в слайсах `docs/archive/architecture/`, указатель ниже; реестр всех нот — `05-decisions-index.md`) +# Журнал решений оркестратора — контракт D1–D39.268 (живой файл: карта · эрраты · живые тела · голова D39.124+ (подрезка D39.139); тела закрытых эр — в слайсах `docs/archive/architecture/`, указатель ниже; реестр всех нот — `05-decisions-index.md`) > **⟶ КАРТА АКТУАЛЬНОСТИ (ревизия D31, продлена до D38.2 [12.07]; исторические записи ниже НЕ переписываются — дисциплина D23.3).** Работая с контрактом (греп номера: живой файл → слайсы, целиком НЕ читать — D39.125), держи под рукой, что чем перекрыто: > ⚠ **Эррата 09.08 (D39.125):** D39.111 п.1 предписывал промту S3 «максимум = баланс МИНУС открытые холды» — формула ОШИБОЧНА (вычитание дважды), исправлена D39.115 п.2(а): максимум = Balance КАК ЕСТЬ; тело D39.111 — в слайсе `../archive/architecture/05-decisions-D39-106-123.md` (испр. 05.09: прежнее «живёт ниже в этом файле» протухло подрезкой D39.139) (голова D39.106+). @@ -4829,3 +4829,89 @@ env-гейченных прибора вместо одного: две проб ключом реестра лейблов безвредны сегодня, и **условие протухания названо заранее: первая же покупка на английской книге**. Вторая форма стиха (гимны курсивными абзацами) её правилом не накрыта — носитель не доезжает до чанка, забрано следующим паком. Два примера редактора на боевом пути модель не видит. + +## D39.268 — ПРИЁМКА БЭКЕНД-ПАКА «ДОСТИЖИМОСТЬ ПАР-ДАННЫХ»: ПРИНЯТ (18.09) ✅ + +**1. Что заландено.** `9defda4` — **38 файлов, 1855 вставок, 66 удалений, $0**. Отдельным коммитом `e6f9a3b` +отчёт зоны в её секции журнала (239 вставок, **0 удалений**). Построено: манифест умеет объявить НОЛЬ каналов +явной строкой · пар-пак английского с четырьмя ключами сайзинга · перенос инлайновой разметки из EPUB на +провод · пар-скоупный лейбл промта · имя исчерпания средств провайдера для человека. + +**2. ПРЕДМЕТ ПАКА ПЕРЕ-ОПРЕДЕЛЁН ЗАМЕРОМ ДО ВЫДАЧИ, и это главное методическое приобретение.** Заказывался +он как «убрать зависимость от китайского из Go». Перепись дала **шесть упоминаний кодов языка при контроле +154 не-тестовых файла, живых ветвлений два, оба законны и обоснованы на месте**. ⇒ остаточная зависимость +движка от одной пары есть **НЕДОСТИЖИМОСТЬ ДАННЫХ**, а не грязь в коде, и пак был переписан под это. Без +замера он бы полировал то, чего нет. + +**3. ЧИСЛА, У КАЖДОГО НАЗВАН ПРИБОР.** +**Мой:** полная мутационная кампания на отдельном корне — **336 поймано, 0 выживших, 0 НЕ ИЗМЕРЕНО**, +`MUT_EXIT=0`, сумма исходов **равна составу гейта** (336). Третий класс не выстрелил: строк `premise` · +`connection reset` · `not green` — по нулю. Корень снят с дерева сдачи, расхождений при заморозке 0, после +кампании копия вернулась байт-идентичной. +**Зоны:** батарея `MAKE_EXIT=0`, полнота списком — 24 пакета против 24 вердиктов, встречная сверка пуста в обе +стороны, линтер чист, **скипов 6 поимённо**, все корпусные. Её девять посадок — 9 из 9 красных, и **все +девять введены в гейт** (каталог 538 → 547, в гейте 336): это рубеж проекта, а не разовый прогон смены. + +**4. КИТАЙСКАЯ ПОЛОВИНА НЕПОДВИЖНА, И ЭТО ДОКАЗАНО ВХОДАМИ, А НЕ СОВПАДЕНИЕМ ХЕШЕЙ.** Пере-снято +оркестратором: тронутых входов, сворачивающихся в ключ манифеста, **ноль** — ни пар-данные `zh-ru`, `zh`, +`ru`, ни промты `zh-ru`, ни встроенные таблицы ядра; и **ноль** правок у трёх безусловных версий-констант. +⇒ ключу двигаться нечему по построению. Три свидетеля зоны (неподвижный ключ манифеста · зелёные голдены без +ре-капчура · дифф реестра лейблов из трёх строк, все английские) с этим согласны. + +**5. РАТИФИЦИРУЕТСЯ УСЛОВНЫЙ ФОЛД КАК ФОРМА, А НЕ КАК ОБХОД.** Правка ингеста по конвенции бампает версию +нарезки, а та фолдится БЕЗУСЛОВНО — то есть перекупила бы китайскую книгу за возможность, которой та не +видела. Принята форма: **возможность включается пар-данными, фолдится через версию пакета, а та условна**. +Прецедент найден в истории: пак заголовков добавил **207 строк** в нарезчик и константу версии не тронул. +**Три условия, без любого из которых это обход:** файл **утверждает** глиф как контракт с промтами пары, а не +служит флагом · нейтральность для необъявивших пар доказана **байт-равенством на EPUB-фикстуре с курсивом** · +остаток назван: правка самого алгоритма при уже объявившихся парах не двигает ни файла, ни версии. +⚠ **И мой страх был направлен в не тот предмет.** Я боялся «чекпойнт найдётся, а чанки другие» — такого +исхода нет: строку выдаёт только совпадение И снапшота, И контент-хеша +(`backend/internal/pipeline/stagerun.go:92`=`cs.ContentHash == contentHash`), а устаревшая по содержимому +строка игнорируется и пере-выводится. Версии стерегут СОГЛАСИЕ на пере-оплату, текст стережёт хеш. Риск здесь +денежный, а не качественный. + +**6. РАТИФИЦИРУЕТСЯ ПАР-СКОУПНЫЙ ЛЕЙБЛ ПРОМТА — находка зоны, которой в паке не было.** Лейбл фолдится в +снапшот (`backend/internal/pipeline/snapshot.go:310`=`PromptVersion string`, фолд на `:495`), а ран-конфиг +объявляет его ПО СТАДИИ, не по паре. ⇒ правка промтов одной пары ставила перед выбором: бампнуть общий лейбл +и перекупить чужую книгу за правку, которой она не видела, — либо держать одно имя над двумя разными +текстами. Лечение: пара заменяет СВОЙ лейбл, ран-конфиг по-прежнему обязан свой назвать. Предъявлено диффом +реестра: три строки, все английские, ни одной китайской. + +**7. ДВА ОТКАЗА ЗОНЫ ПРИНЯТЫ, ОБА С ЗАМЕРОМ, И ОБА — ПРАВИЛЬНЫЕ.** +**(а) Файл заголовков НЕ заведён.** Шаблон рендерится только при совпадении ДВУХ половин — пар-шаблон И +грамматика заголовка источника, — а у латинского источника второй нет. Завести файл значило бы построить +артефакт без смены поведения, то есть ровно ту ложную победу, о которой промт её предупреждал. ⭐ Она не +взяла её, хотя отчитаться было бы легко и приёмка бы приняла. +**(б) Go-гард регистровых склеек НЕ построен.** Обе детерминированные дороги двигают ГЛОБАЛЬНУЮ ось, и цена +любой — перекупка КИТАЙСКОЙ книги за дефект, которого у неё нет по построению. Предложена форма, глобальную +ось не двигающая: гард на СБОРКЕ банка, где версия есть хеш строк. Решение о судьбе коллизионного термина — +владельческое, в пак не входит. + +**8. ИСХОДЫ РЯДОВ.** **347 ЗАКРЫТ** — критерий «разрешение нулевого числа каналов плюс решение по форме» +исполнен явной строкой, и форма выбрана с доводом: молчаливое превращение пустого манифеста в инертный пак +сделало бы тихо инертным и **обрезанный** файл, то есть аварию. ⚠ Попутный факт из тела ряда переезжает сюда, +чтобы не умереть с ним: сбор статистики банка при пустом паке **паникует** +(`backend/internal/miner/miner_patterns.go:181`); в боевом пути недостижимо, потому что раньше стоит отказ +терминолога. **500 ЗАКРЫТ** — сквозной замер предъявлен со знаменателем: **4842 носителя курсива доезжают до +чанка**, счётчик живёт в нотах ингеста (`backend/internal/chunk/ingest.go:140`=`italic_carriers`), экспорт +отображает маркер обратно на ОБЕИХ поверхностях. **272** — движковая половина закрыта, платформенная остаётся +пингом: пример в операторском рецепте учит пар-связанному ключу. **502** — половина: человек имя получил, +программа нет; словарь кадров есть замороженный шов, и расширение его — отдельное решение. **303 НЕ ТРОНУТ**, +и именно поэтому английская книга не получает детерминированного заголовка главы. Заведён **503** (забор +ре-пина пускает одну ось). Предложены два новых предмета: гард склеек на сборке банка и маркеры в окне +терминолога — завести после прогона, когда будут числа. + +**9. АНГЛИЙСКАЯ КНИГА ДОЕЗЖАЕТ НА БОЕВОМ КОНФИГЕ — вход холодного прогона открыт.** Предъявлено прогоном на +свежем проекте без единой правки конфига: пак грузится, ингест 71 глава / 386 чанков, началась черновая +волна, и прогон встал на денежном потолке книги **до первого вызова** — `TOTAL: $0.000000`, ноль обращений +к провайдеру. ⚠ Цепь «исходник → маркер → чанк → экспорт» измерена; **поведение МОДЕЛИ на маркерах не +измерено ничем** и станет известно только на прогоне. Первую главу английского перевода читать глазами +именно на это. + +**10. МОИ ОШИБКИ.** Выдал этот пак в зону, **не заландив предыдущий** — слот освобождается актом, а не +сдачей; поймала сдавшая зона, остановил до первой правки. В §4.1 промта написал, что заголовок главы +открывается даром, — опровергнуто зоной. Числа курсива в первой редакции промта промахивались в 2–4.5 раза, +а описание разметки было прямо ложным («курсивные абзацы» при нуле таковых). Контроль ссылок на закрываемые +ряды сперва дал ноль по форме «строка N», которой проект не пользуется, — **негодный контроль доказывает что +угодно**, пере-снял формой «ряд N» и получил 7 и 1. diff --git a/docs/BACKEND_RUN_READINESS_SESSION_PROMPT.md b/docs/archive/prompts/BACKEND_RUN_READINESS_SESSION_PROMPT.md similarity index 97% rename from docs/BACKEND_RUN_READINESS_SESSION_PROMPT.md rename to docs/archive/prompts/BACKEND_RUN_READINESS_SESSION_PROMPT.md index 870cec34..a5807c13 100644 --- a/docs/BACKEND_RUN_READINESS_SESSION_PROMPT.md +++ b/docs/archive/prompts/BACKEND_RUN_READINESS_SESSION_PROMPT.md @@ -1,3 +1,10 @@ +> ⛔ **ПАК ОТРАБОТАН И ПРИНЯТ 18.09 — акт `D39.268`.** Лендинг `9defda4` (38 файлов, 1855/66, $0) плюс `e6f9a3b` (отчёт зоны). +> Числа приёмки: кампания **336/336 поймано, 0 выживших, 0 НЕ ИЗМЕРЕНО**, сумма исходов равна составу гейта. +> ⭐ Главный итог: **английская книга доезжает на БОЕВОМ конфиге** и встаёт на денежном потолке до первого вызова — вход холодного прогона открыт. +> ⚠ **Инструкции отсюда НЕ ИСПОЛНЯЮТСЯ** — файл сохранён как история замысла. +> ⚠ Два моих утверждения в нём ОПРОВЕРГНУТЫ исполнением зоны: заголовок главы «даром» не открывается (нужны ОБЕ половины), +> и числа курсива в §4.3 промахивались в 2–4.5 раза при прямо ложном описании разметки. + # Промт бэкенд-сессии: ДОСТИЖИМОСТЬ ПАР-ДАННЫХ — ЗАКРЫТЬ ДО ХОЛОДНОГО ПРОГОНА > Выдан оркестратором очереди №23. Пак $0 по умолчанию. Зона записи — `backend/`.