From 3025fd862b2a8bf2668cb51d160521aec5791378 Mon Sep 17 00:00:00 2001 From: "Claude (backend session)" Date: Sun, 2 Aug 2026 19:16:01 +0300 Subject: [PATCH] Add losses found by independent review of the handoff: shipping configs still no-op, deleted gate harness, repair deviation, design constants and two of my own overclaims retracted --- docs/PROGRESS.md | 16 +++++++++------- docs/architecture/05-decisions-log.md | 11 ++++++++++- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index aec10e37..1504253f 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -6,7 +6,7 @@ > - **Курс (D39.59–78): ОБЩНОСТЬ ✅ → КАЧЕСТВО БАНКА ✅ (D39.69/75/77) → ПАКЕТ-ЧЕКЕРОВ ✅ (D39.78: строка 25 целиком; харнесс labels В GIT 12/12; K2 r0.85 · K4b r0.22 · K6 fp 14→6; Р2 hard/soft + Р4-потолки в контрактах).** **Текущее: МЕЛКАЯ ПАЧКА ✅ ПРИНЯТА И ЗАЛЕНДЕНА (D39.82: строки 89/53/83 закрыты · 93 сужена до остатков · F4-бэкап+pre-flight построен · register/жанр → книжный слой · DC7 пере-гейчен сид-покрытием → строка 98); решения §6 исполнены (D39.79/82); **РЕ-ПРОБА + ОТЛАДОЧНЫЙ ХОЛОДНЫЙ ПРОГОН coldrun-b САНКЦИОНИРОВАНЫ (D39.83: промт выдан и холодно аудирован — 3 major вправлены; потолки $0.15 ре-проба / $5 прогон; ступени 2+8 глав, автобанк по D39.77)**; ре-проба flash (строка 74) — по слову владельца; finding-1 ЗАКРЫТ (D39.77); онбординг-оверхол доков исполнен (D39.80); **ФРОНТ ОТКРЫТ владельцем (D39.81: продукт = SaaS; зоны `frontend/` + `platform/` живые, фронт работает на моках; движковая очередь НЕ пере-упорядочена — ранняя вставка одна: строка 95 «контракт API» $0; строки 96/97 и перевесы 49/94 заведены)**; **СТЕК ФРОНТА/ПЛАТФОРМЫ ЗАПИНЕН, 8 решений владельца ратифицированы (D39.84: SEO Google-only · PWA-первый · денег в MVP-UI нет · стоп-на-банке = параметр запуска, `--verify-bank` готов · перевод НИКОГДА на индексируемый URL = ПТ-34 · якорь чтения = edit-unit, ПТ-21; работы движка под фронт = строки 99–102; фронт/платформа ведут ЗОННЫЕ бэклоги — `frontend/docs/BACKLOG.md` · `platform/BACKLOG.md`, строки 96/97 → П-1/П-2; зоны залендены, фронт-промт S0–S7 в `frontend/docs/`)**; **ШОВ ДВИЖОК↔ПЛАТФОРМА РАТИФИЦИРОВАН ПО РЕСЁРЧУ (D39.85, `research/23`): NDJSON-поток событий → материализация в Postgres → SSE; артефакты границ стадий; анти-паттерны запрещены (живой SQLite не читать · HTTP в движок не тащить · read-пакет из ядра не выносить); строка 103 заведена, входы контракта 95 зафиксированы)**.** **coldrun-b ПРИНЯТ И ЗАЛЕНДЕН (D39.86): фазы A/B исполнены за $0.114378 из $0.15, фаза C заморожена чекпойнтом — легитимный исход по D39.83.** Блокер 0731 воспроизведён на боевой форме (0 из 9 пригодных при `max_tokens=8496`); **вариант (а) флор-16000 ФАЛЬСИФИЦИРОВАН** (4/5 пустых при 16992, добавка уходит в размышление); **(б) `reasoning_effort:"low"` оживляет волну, но требует правки Go** (у бэнк-ролей ручки нет — НОВАЯ строка 104; посылка об амендменте гейта неверна только для СТАДИЙНОЙ ручки); **(в′) thinking OFF замерен карантинно — эхо-мина ЖИВА на весах 0731 (4/20)**, флаг `echoes_when_thinking_off` сохраняет основание; **(г) pro ≈×8.9, а не ×3.1**, и на pro ручка эффорта не работает (вендор `low→high`, смена маппинга объявлена «early August 2026»). Порог классификатора **6/6 взят**; две дыры наблюдаемости закрыты; live-риг не собирался с D39.64 — починен. НОВЫЕ строки **104** (ручки синтетических стадий) и **105** (мис-вердикт классификатора + честность поверхностей); **46** повышена до «скоро» с живым носителем; **16 НЕ закрыта**. ✅ **РАЗВИЛКА 74 РЕШЕНА ВЛАДЕЛЬЦЕМ (D39.87): вариант (б)** — `reasoning_effort: "low"` черновику ПЛЮС правка Go, дающая ручку эффорта ролям, у которых её нет (строка 104), ПЛЮС экран целевого языка (строка 46). Мандат владельца на исполнение — «элегантно встроить в текущее решение по коду, чтоб было чисто»: правка обязана быть использованием СУЩЕСТВУЮЩЕГО поля `Stage.Reasoning`, одним швом на все три рукописные `config.Stage`, так чтобы четвёртое такое место не могло появиться молча. **Промт выдан** — `BACKEND_EFFORT_HANDLE_SESSION_PROMPT.md` (работы A/B $0 + проба банка ≤$0.10 + добивка прогона ≤$5, закрывающая строку 16 и впервые дающая данные по осям голоса для 13б). Перекупок нет (D39.63). > - **Горизонт (D39.62/67):** ре-проба flash (74; + платный порог 6/6 классификатора + пробы 36б-замера Q2/эмиссии Q7 по слову) → **ДОБОР ИДЕАЛА** (первым прогоном: оси голоса 24 · авто-режим · итерация №2 редакторов 65 · цена 16 · веса K1–K12 13а · вне-претрейн чекпоинт 55) → ВТОРАЯ ПАРА живьём (ja→ru; преп 81) → МАСШТАБ → пилот Ф2.5 (гейт резюме-строки 80; строки 62–68, 85) → Ф3 ридер-IDE (69–71). **Стоячие:** ToS-триггер 25.10 · Ш-2 до go1.27 · строка 74 перед любым платным прогоном. > - **Стек:** draft deepseek-v4-flash thinking-ON (+банкнота) **⚠0731** → терминолог (та же модель, батчи, экран `target_script`) → editor deepseek-v4-pro БИЛИНГВ ИНТЕРИМ (вендором НЕ тронут; glm-5 резерв) → судья gemini (Ф2, полигон); канал B Mistral+grok; ~$0.85/ранобэ (D30.4) — пере-калибровка после развилки 74. -> - **ЕДИНЫЙ БЭКЛОГ — секция «Бэклог» ниже** (одна таблица, единственный трекер; каждая петля обязана иметь диспозицию: решено / отложено-с-записью / отклонено; ведёт оркестратор). **СЧЁТ ОЧЕРЕДИ на 02.08 (D39.90, обновлять при каждом лендинге; считать скриптом по таблице, не на глаз):** всего **93** строки · зона бэкенд **45** строго / **59** широко · **блокеров очереди 0** (104 → «на приёмке») · «скоро» **11** (2·4·5·18·46·49·55·95·107·108·109); остальное «когда-нибудь». ⚠ **Счёт — НИЖНЯЯ граница долга, а не потолок:** трекер содержит только замеченное, и 02.08 дважды за $0 свежие глаза вытащили из кода дефекты, которых в нём не было (релей фронта → строки 99/100/102; приёмочное ревью → третий шов `repair.go:384` в 104 и честность `quality.go:436` в 105). Лента ✅ выше — про ЗАКРЫТЫЕ паки, читать её как «долга нет» неверно (разбор — вопрос владельца 02.08, D39.89). +> - **ЕДИНЫЙ БЭКЛОГ — секция «Бэклог» ниже** (одна таблица, единственный трекер; каждая петля обязана иметь диспозицию: решено / отложено-с-записью / отклонено; ведёт оркестратор). **СЧЁТ ОЧЕРЕДИ на 02.08 (D39.90, обновлять при каждом лендинге; считать скриптом по таблице, не на глаз):** всего **95** строк · зона бэкенд **46** строго / **61** широко · **блокеров очереди 0** (104 → «на приёмке») · «скоро» **13** (2·4·5·18·46·49·55·95·107·108·109·112·113); остальное «когда-нибудь». ⚠ **Счёт — НИЖНЯЯ граница долга, а не потолок:** трекер содержит только замеченное, и 02.08 дважды за $0 свежие глаза вытащили из кода дефекты, которых в нём не было (релей фронта → строки 99/100/102; приёмочное ревью → третий шов `repair.go:384` в 104 и честность `quality.go:436` в 105). Лента ✅ выше — про ЗАКРЫТЫЕ паки, читать её как «долга нет» неверно (разбор — вопрос владельца 02.08, D39.89). > - Архивы хроники: `archive/PROGRESS-2026-07-04-10.md` (D31) · `-10-13` (D39.6-гигиена) · `-13-25` (стройка паков 11–16, rerun2) · **`-25-31` (паки 17–20 · мини-прогон · полигон-пакеты 5–8 · ToS · холодный прогон; D39.26–58)**. Записи ниже — живой хвост (эра D39.59+). ## Бэклог (ЕДИНЫЙ, собран 26.07, актуализация 02.08 D39.80; правки — только через оркестратора) @@ -59,7 +59,7 @@ | 34а | **Экран кодировки не видит `` без XML-объявления** (епаб с gb18030-метой прочтётся как UTF-8) — до-паковая дыра, сознательно не тронута пачкой 14а (паритет со старым ридером) | бэкенд | когда-нибудь | отдельное решение | D39.54, SMALLPACK §8 | | 35 | **Не-CJK майнер/банк**: en-детектора не существует (hanRuns=0), ja с zh-таблицами активно неверен (0/10); нужен второй ДЕТЕКТОР (прототип `mine_nonhan.py`) + G1–G10 требования generic-майнера (вкл. квадратичность G9 ≈4.6 ч) | бэкенд | когда-нибудь | отдельный пак generic-майнера (с ja→ru) | D39.37(8), D39.43, D39.50 п.8, POLYGON_PREMEASURE §6 | | 36 | Кластеризация майнера глотает родовые титулы (族长/学堂家老 в кластере 葛家) — закрыто на границе сборки входа, сама кластеризация не чинилась | бэкенд | когда-нибудь | отдельное решение | D39.43, D39.45 | -| 36б | **Второе мнение по банку**: рецензент ДРУГОЙ моделью, несогласия — отдельной колонкой подписной таблицы (судья-с-декоем в роли рецензента; решает владелец, D39.46-ограничение не бьёт) | бэкенд/полигон | когда-нибудь | отдельный дизайн (Р4) | D39.58, D39.51 п.4 | +| 36б | **Второе мнение по банку**: рецензент ДРУГОЙ моделью, несогласия — отдельной колонкой подписной таблицы (судья-с-декоем в роли рецензента; решает владелец, D39.46-ограничение не бьёт). ⚠ **ДИСПОЗИЦИЯ ПРИВЕДЕНА В СООТВЕТСТВИЕ (D39.90): бэкенд-стройки НЕТ** — D39.69 закрыл её по нужности, маршрут = полигон-ЗАМЕР (строка **5**, промт выдан); переживёт замер → тонкая колонка наблюдаемости, не гейт. Прежняя форма «отдельный дизайн (Р4)» в зоне бэкенда была устаревшей и завышала счёт бэкенд-очереди | полигон (замер) → бэкенд (только если переживёт) | когда-нибудь (через строку 5) | замер строки 5 → решение | D39.58, D39.51 п.4, D39.69, **D39.90** | | 36г | **Проводной формат каналов пересказан прозой в каждом пар-промпте, парсер в Go, связи нет** — формат в шаблон движка (`{{banknote_format}}`); линты держат класс, дублирование остаётся | бэкенд | когда-нибудь (со следующей правкой промптов) | отдельное решение (Р5) | D39.58 | | 37 | **Квадратичности: `AttachKWIC`** (16.8 с / 2000 кандидатов; фикс — многошаблонный поиск) + src-правило банкноты при промахе чанк-пути (строка × длина книги; на 10 главах не видна) | бэкенд | когда-нибудь | отдельное решение | D39.45, PACK20_BANK_BUILD §8.5.1, D39.58 | | 38 | Смета не видит пере-покупку прохода терминолога на каждой итерации подписи (роль не пишет `chunk_status`, не видна `projectRebill`) | бэкенд | когда-нибудь | отдельное решение | D39.45, PACK20_BANK_BUILD §8.5.2 | @@ -68,9 +68,9 @@ | 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 | **Флор — калиброванная константа без модели «thinking в completion»: МОДЕЛЬ ПОЛУЧЕНА замером (D39.86), сама строка сужена до выбора числа.** Замер боевой формы: при вендор-дефолте `high` размышление на плотном хане потолком НЕ ограничивается (8496 → 0/9 пригодных, 16992 → 1/5; вендорская норма вывода для `high` = 384K) ⇒ **флор не является рычагом против неограниченного думания — рычаг это `reasoning_effort`**; при `low` размышление 170–313 ток. и флор 8000 избыточен. Остаток строки: какое число ставить ПОСЛЕ развилки 74 (и помнить, что у `deepseek-v4-pro` эффорт не настраивается — вендор-маппинг `low→high`, quirks п.3а). ⚠ **РАСХОЖДЕНИЕ ТРЕКЕРА СНЯТО (D39.90):** строка 74 объявляла 44 «закрытой этим замером» — это верно только для ПОЛОВИНЫ «поднять флор» (фальсифицирована). Живой остаток — обратный: **опустить/пере-калибровать число по числам пробы `bank-low`**, где стена на `low` не исчезла, а разредилась (упавший батч: `content=""`, `finish=length`, `completion=7999`, `reasoning=7999` — тот же тяжёлый хвост, 1/5 вместо 4/5) ⇒ число флора влияет на цену ретрая, а не на проходимость | бэкенд | когда-нибудь (при приёмке 104) | отдельное решение | D39.37(10), D39.86, **D39.90** | +| 44 | **Флор — калиброванная константа без модели «thinking в completion»: МОДЕЛЬ ПОЛУЧЕНА замером (D39.86), сама строка сужена до выбора числа.** Замер боевой формы: при вендор-дефолте `high` размышление на плотном хане потолком НЕ ограничивается (8496 → 0/9 пригодных, 16992 → 1/5; вендорская норма вывода для `high` = 384K) ⇒ **флор не является рычагом против неограниченного думания — рычаг это `reasoning_effort`**; при `low` размышление 170–313 ток. и флор 8000 избыточен. Остаток строки: какое число ставить ПОСЛЕ развилки 74 (и помнить, что у `deepseek-v4-pro` эффорт не настраивается — вендор-маппинг `low→high`, quirks п.3а). ⚠ **РАСХОЖДЕНИЕ ТРЕКЕРА СНЯТО (D39.90):** строка 74 объявляла 44 «закрытой этим замером» — это верно только для ПОЛОВИНЫ «поднять флор» (фальсифицирована). Живой остаток — обратный: **опустить/пере-калибровать число по числам пробы `bank-low`**, где стена на `low` не исчезла, а разредилась (упавший батч: `content=""`, `finish=length`, `completion=7999`, `reasoning=7999` — тот же тяжёлый хвост, 1/5 вместо 4/5, и это стохастика вызова: батч не самый большой по входу). ⚠ **Флор при `low` НЕ варьировался ни разу** — упавший батч умер ровно на потолке 8000, так что «сколько ставить» остаётся незамеренным вопросом, а не выводом | бэкенд | когда-нибудь (при приёмке 104) | отдельное решение | D39.37(10), D39.86, **D39.90** | | 45 | `max_tokens`-упоры (две единицы) — вернутся на en-книге ; halve-chunk-on-retry (research/22 §2 №7) ОТКЛОНЁН D39.74 — вернуться сюда же при живых упорах | бэкенд | когда-нибудь | отдельное решение (с en) | D39.37(11) | -| 46 | **Экран целевого языка на выходе НЕ-ПОСЛЕДНЕЙ стадии — ЖИВОЙ НОСИТЕЛЬ ПОЛУЧЕН, класс поднят (D39.86).** Было: 38/40 дефектов латиницы живут в черновиках вне охвата гейтов (`waverun.go:486`). Стало: на ре-пробе 74 при `effort:low` **1 черновик из 18 пришёл ПОЛНЫМ связным переводом НА АНГЛИЙСКИЙ** и прошёл как `disposition=ok` — `classify` экранирует ИСХОДНУЮ письменность, пустоту, обрыв и отказ, а «не исходный и не целевой» не ловит ни один предикат (частично ловится лишь третий язык, ДЕЛЯЩИЙ письменность с источником, и ловится под ЛОЖНОЙ причиной `cjk_artifact`). ⚠ Последний рубеж УСЛОВЕН тройкой `isFinal && Gates.Sanitizer.Enabled && checkers.TargetActive()` (`chunkrun.go:52`), и **дыра на оси ЦЕЛИ двусторонняя**: (i) без данных цели слой 7 инертен ПО ОТСУТСТВИЮ (осознанный дизайн, `disposition.go:302-305`) ⇒ для не-русской цели рубежа нет вовсе; (ii) а с данными будущей ЛАТИНОПИСЬМЕННОЙ цели `detectLatinInsertion` (`checks/sanitizer.go:228`) сработает на ЧИСТОЙ целевой прозе и дропнет 100% чанков — внутри санитайзера он НЕ обусловлен `TargetScriptNonLatin()`, хотя доккоммент это объявляет (реальный гард только на репэйре — `quality.go:215`, `repair.go:208`), а частичный файл цели невозможен (`CompileCheckers` паникует). ⇒ **ревью-вопрос «заработает ли пара, которой в репо нет, без правки Go?» для →en/→de отвечается НЕТ**; кандидат фикса — тот же шов, что уже применён к репэйру. *(Контрпример «pipeline-c2.yaml — легальная сборка без санитайзера» проверен и СНЯТ: c2 неисполняем `CheckRunnable`, его санитайзер забукован строкой 33.)* Даже при включённом санитайзере худший исход — не потеря юнита, а ТИХО ОТГРУЖЕННЫЙ релейный перевод zh→en→ru, если билингв-редактор отрендерит русский с английского черновика. Область фикса — «выход любой НЕ-последней стадии», не «черновик» (`isFinal` позиционный, `stagerun.go:145`). ⚠ **ДИЗАЙН ПОДАН, КОДА НЕТ — СТОИТ НА РЕШЕНИИ ВЛАДЕЛЬЦА (D39.90).** Три поправки сессии к посылке, все замером: **(1) боевой гейт уже ловит 18 из 20** off-target событий (`sourceScriptShare > 0.15`, `disposition.go:224,275`; 0 ложных на 1055 здоровых, запас 13×) ⇒ остаточная дыра **2 чанка из ~1100 = 0.18%**, оба английские, японский ловится долей ханьцзы; **(2) второй рубеж существует, но стоит не там** — санитайзер поймал бы те самые байты («Latin insertion»), но `chunkrun.go:52` требует `isFinal`, а в двухстадийной топологии черновик НИКОГДА не финальный; тот же `isFinal` глушит на черновике латинный линт, флаггер голоса и глоссарный пост-чек; **(3)** здоровый минимум на тексте, который РЕАЛЬНО видит гейт (после среза банкноты), = 0.9767 при n=1055. **Развилка владельцу:** (а) предикат внутри `classify()` + бамп `classifierVersion` — двигает снапшот у всех книг, голден пере-захват один раз, на свежем стенде $0; (б) отдельный опциональный гейт вне `classify()` — снапшот не двигает, но это второй способ сказать «ответ непригоден», и он выключен по умолчанию; (в) языковой детектор. **Выбор сессии — (а).** Носитель данных — `lang.LangScripts(Book.TargetLang)`, НОВЫЙ go:embed-файл не заводить (`EmbeddedVersion` фолдится безусловно = перекупка всех книг всех пар); порог 0.50 не калиброван, а поставлен в середину пустого интервала. Три мины наивной реализации названы: новый флаг провалился бы мимо `escalatable()`/`retryable()` (⇒ переиспользовать `FlagCJKArtifact`), классификатор ложно флагался бы 16/16, экран слеп к ПОДМНОЖЕСТВАМ письменности (чисто китайский выход для →ja наберёт 1.000). Вторая половина дыры (`detectLatinInsertion` без `TargetScriptNonLatin()`) — чинить тем же диффом, для ru вердикты не двигаются | владелец → бэкенд | **скоро (ждёт выбора (а)/(б)/(в))** | решение владельца → правка Go | D39.39(д), D39.86, **D39.90** | +| 46 | **Экран целевого языка на выходе НЕ-ПОСЛЕДНЕЙ стадии — ЖИВОЙ НОСИТЕЛЬ ПОЛУЧЕН, класс поднят (D39.86).** Было: 38/40 дефектов латиницы живут в черновиках вне охвата гейтов (`waverun.go:486`). Стало: на ре-пробе 74 при `effort:low` **1 черновик из 18 пришёл ПОЛНЫМ связным переводом НА АНГЛИЙСКИЙ** и прошёл как `disposition=ok` — `classify` экранирует ИСХОДНУЮ письменность, пустоту, обрыв и отказ, а «не исходный и не целевой» не ловит ни один предикат (частично ловится лишь третий язык, ДЕЛЯЩИЙ письменность с источником, и ловится под ЛОЖНОЙ причиной `cjk_artifact`). ⚠ Последний рубеж УСЛОВЕН тройкой `isFinal && Gates.Sanitizer.Enabled && checkers.TargetActive()` (`chunkrun.go:52`), и **дыра на оси ЦЕЛИ двусторонняя**: (i) без данных цели слой 7 инертен ПО ОТСУТСТВИЮ (осознанный дизайн, `disposition.go:302-305`) ⇒ для не-русской цели рубежа нет вовсе; (ii) а с данными будущей ЛАТИНОПИСЬМЕННОЙ цели `detectLatinInsertion` (`checks/sanitizer.go:228`) сработает на ЧИСТОЙ целевой прозе и дропнет 100% чанков — внутри санитайзера он НЕ обусловлен `TargetScriptNonLatin()`, хотя доккоммент это объявляет (реальный гард только на репэйре — `quality.go:215`, `repair.go:208`), а частичный файл цели невозможен (`CompileCheckers` паникует). ⇒ **ревью-вопрос «заработает ли пара, которой в репо нет, без правки Go?» для →en/→de отвечается НЕТ**; кандидат фикса — тот же шов, что уже применён к репэйру. *(Контрпример «pipeline-c2.yaml — легальная сборка без санитайзера» проверен и СНЯТ: c2 неисполняем `CheckRunnable`, его санитайзер забукован строкой 33.)* Даже при включённом санитайзере худший исход — не потеря юнита, а ТИХО ОТГРУЖЕННЫЙ релейный перевод zh→en→ru, если билингв-редактор отрендерит русский с английского черновика. Область фикса — «выход любой НЕ-последней стадии», не «черновик» (`isFinal` позиционный, `stagerun.go:145`). ⚠ **ДИЗАЙН ПОДАН, КОДА НЕТ — СТОИТ НА РЕШЕНИИ ВЛАДЕЛЬЦА (D39.90).** Три поправки сессии к посылке, все замером: **(1) боевой гейт уже ловит 18 из 20** off-target событий (`sourceScriptShare > 0.15`, `disposition.go:224,275`; 0 ложных на 1055 здоровых, запас 13×) ⇒ остаточная дыра **2 чанка из ~1100 = 0.18%**, оба английские, японский ловится долей ханьцзы; **(2) второй рубеж существует, но стоит не там** — санитайзер поймал бы те самые байты («Latin insertion»), но `chunkrun.go:52` требует `isFinal`, а в двухстадийной топологии черновик НИКОГДА не финальный; тот же `isFinal` глушит на черновике латинный линт, флаггер голоса и глоссарный пост-чек; **(3)** здоровый минимум на тексте, который РЕАЛЬНО видит гейт (после среза банкноты), = 0.9767 при n=1055. **Развилка владельцу:** (а) предикат внутри `classify()` + бамп `classifierVersion` — двигает снапшот у всех книг, голден пере-захват один раз, на свежем стенде $0; (б) отдельный опциональный гейт вне `classify()` — снапшот не двигает, но это второй способ сказать «ответ непригоден», и он выключен по умолчанию; (в) языковой детектор. **Выбор сессии — (а).** Носитель данных — `lang.LangScripts(Book.TargetLang)`, НОВЫЙ go:embed-файл не заводить (`EmbeddedVersion` фолдится безусловно = перекупка всех книг всех пар); порог 0.50 не калиброван, а поставлен в середину пустого интервала. Три мины наивной реализации названы: новый флаг провалился бы мимо `escalatable()`/`retryable()` (⇒ переиспользовать `FlagCJKArtifact`), классификатор ложно флагался бы 16/16, экран слеп к ПОДМНОЖЕСТВАМ письменности (чисто китайский выход для →ja наберёт 1.000). Вторая половина дыры (`detectLatinInsertion` без `TargetScriptNonLatin()`) — чинить тем же диффом, для ru вердикты не двигаются. **Константы и хвосты дизайна, без которых подпись неполна:** порог **abstain 200 букв** (ниже экран воздерживается; самое короткое off-target событие 346 букв, ниже 200 падают лишь 5 из 1055 здоровых, все со счётом 1.0000) · ⚠ **опубликованная база «~1.5% off-target» НЕВЕРНА по знаменателю** — он пулит черновики с редакторскими выходами, а редактор такой отказ произвести не может; на ЧЕРНОВОЙ вызов база **3.02%**, то есть вдвое хуже · ⚠ **не проверено, что делает РЕДАКТОР с английским черновиком** — вытащит обратно в русский или отредактирует как английский; именно этот неизвестный решает, чем является остаточные 0.18%: потерей юнита или тихо отгруженным релейным zh→en→ru · английских черновика найдено ДВА (`fb51e135a395`, `4080ee8287af`), плюс японский в exp15 · **`cultivation` чинить в СИДЕ, а не порогом:** 86 из 1055 здоровых несут голое английское `cultivation` внутри беглого русского, и все 32 абзаца ниже 0.90 содержат именно его, ни один — ханьцзы; правка пар-данных двигает `LangpackVersion` с `omitempty` ⇒ перекупка ограничена книгами ЭТОЙ пары (чинить на плане, где перекупка уже) · Hunspell и GlotScript-эмбед — **не строить** · база замера = строка **113** | владелец → бэкенд | **скоро (ждёт выбора (а)/(б)/(в))** | решение владельца → правка Go | 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 З-а | @@ -110,11 +110,13 @@ | 101 | **Машиночитаемая таблица подписи банка**: кап 20 — только stdout (`render.go:98`), полная таблица — текстовый сайдкар `.bank-stop.txt`, JSON/структурного выхода нет (mined-signature.yaml — сид-дельта без freq/spread/evidence); нужна фронту S5; помнить ловушку «подпись ≠ UPDATE» (банк пересобирается: `seeding.go:18/110`, `glossary.go:158-162` — контракт подписи пишет в файлы-источники) | бэкенд | к подключению фронта | малое касание (форма — с контрактом 95) | релей фронта 02.08, D39.84 | | 102 | **Приём внешнего trace-контекста в tmctl**: TraceID минтится заново каждым вызовом (`main.go:67-70`; внутри вызова трасса цельная, `request_log.trace_id` есть) — прогон, запущенный платформой, должен быть одной трассой | бэкенд | когда-нибудь (Ф3, с 96) | малое касание | релей фронта 02.08, D39.84 | | 103 | **NDJSON-эмиттер прогонных событий со стабильным словарём** (машинный канал живого статуса для платформы, `research/23` §2): NDJSON-логи уже есть (`LOG_FORMAT=json`, авто-оси trace/book/chapter/stage/role — `obs/logging.go:15-54`), но сообщения прозой, version-хендшейка нет, а **событие потолка отсутствует вовсе** (деньги только в тексте ошибки `stagerun.go:472-494`); нужен словарь-enum + version-хендшейк первой строкой (образец terraform -json: минор = ignore-unknown, мажор = reject) + событие потолка; все границы — единичные call-sites в pipeline рядом с готовыми slog; человеческие логи уже на stderr — stdout-дисциплина соблюдена | бэкенд | к подключению фронта (словарь — вместе с контрактом 95) | малое касание | research/23, D39.85 | -| 104 | **У СИНТЕТИЧЕСКИХ стадий нет ручек `reasoning`/`temperature` — бэнк-роли и repair всегда едут вендор-дефолтом (Д2 coldrun-b, D39.86).** Проводной шов ОДИН — `terminologist.go:515` (`config.Stage{Name, Role, Model}`, поля `Reasoning`/`Temperature` пусты; из `:568` до провайдера читается только `st.Name`), он ОБЩИЙ для обеих бэнк-ролей (render `:289` и classify `:396`); третье такое же место — `repair.go:384`, и его доккоммент `:377-378` декларирует ровно ту посылку, которую замер фальсифицировал («no reasoning setting, so the provider default holds — thinking stays ON»). У `config.TerminologyGate` ключа нет вовсе. **Живая цена:** на весах 0731 терминолог 4/5 батчей `length` с `completion=8000` ровно и пустым телом, банк консолидировал 1 терм из 81 (было 21/21 `stop` до смены весов) ⇒ **при выборе (б) по строке 74 это ОБЯЗАТЕЛЬНАЯ правка, иначе банк не собирается**. Дизайн обязан: (i) быть мультиязычным ран-скоупным ключом (не пар-данные), (ii) накрыть ВСЕ ТРИ шва, (iii) решить `temperature` осознанно тем же диффом, (iv) держать один режим и для `control=extra_body_disable` (на glm пустой эффорт даёт thinking:disabled — не дефолт, а ВЫКЛЮЧЕНО, то есть зона эха), (v) ⚠ ловушка хеш-оси: `bankCheckpointExists` строит Request БЕЗ Temperature/Reasoning (`terminologist.go:498-501`), а `runAttempt` — с ними (`stagerun.go:403-406`, `Reasoning` входит в `RequestHash`, `render.go:308`) — сегодня оси совпадают лишь потому, что оба значения нулевые; «минимальная» правка только `:515` разведёт пробу чекпойнта и вызов ⇒ ложный `paid=false` и обрыв прохода по потолку до первого вызова. ✅ **ИСПОЛНЕНА СЕССИЕЙ 02.08, НЕ ПРИНЯТА И НЕ ЗАЛЕНДЕНА (D39.90):** построено не три патча, а **ДВА ШВА** — `config.InternalCall{…}.Stage()` (новый `internal/config/internal_call.go`) и `Runner.attemptRequest` (`stagerun.go:406`); рукописных `config.Stage{}` в движке не осталось ни одного (все 4 места + live-риг), все 4 сборки `RequestHash(Request{…})` схлопнулись в одну; ловушка хеш-оси закрыта в обе стороны на обоих путях. Перекупки НЕТ (`gates.terminology` не фолдится в снапшот; кортеж воспроизведён побайтно — бэнк-пробник `8e4495006b978ed4` в обе стороны; голден PASS без пере-захвата). Гранулярность решена ЗАМЕРОМ: одна ручка `gates.terminology.reasoning` на обе роли (парная выборка N=5: `low` 4/5 против `high` 5/5 — неразличимо при цене `high` ×2.30), вторая ручка `classify_reasoning` построена на n=1 и СНЯТА самой сессией. `Temperature` зафиксирована нулём осознанно. ⚠ Гарды шва — самописный AST-обход (`synthetic_stage_seam_test.go`), первая байтовая версия пробивалась 7 способами; форма гарда вынесена в решение владельца → **строка 107** | бэкенд | **на приёмке преемника** | приёмка (батарея + деньги двумя путями + адверсариал) → лендинг | D39.86, COLDRUN_B_DEBUG §3.6/Д2, **D39.90** | +| 104 | **У СИНТЕТИЧЕСКИХ стадий нет ручек `reasoning`/`temperature` — бэнк-роли и repair всегда едут вендор-дефолтом (Д2 coldrun-b, D39.86).** Проводной шов ОДИН — `terminologist.go:515` (`config.Stage{Name, Role, Model}`, поля `Reasoning`/`Temperature` пусты; из `:568` до провайдера читается только `st.Name`), он ОБЩИЙ для обеих бэнк-ролей (render `:289` и classify `:396`); третье такое же место — `repair.go:384`, и его доккоммент `:377-378` декларирует ровно ту посылку, которую замер фальсифицировал («no reasoning setting, so the provider default holds — thinking stays ON»). У `config.TerminologyGate` ключа нет вовсе. **Живая цена:** на весах 0731 терминолог 4/5 батчей `length` с `completion=8000` ровно и пустым телом, банк консолидировал 1 терм из 81 (было 21/21 `stop` до смены весов) ⇒ **при выборе (б) по строке 74 это ОБЯЗАТЕЛЬНАЯ правка, иначе банк не собирается**. Дизайн обязан: (i) быть мультиязычным ран-скоупным ключом (не пар-данные), (ii) накрыть ВСЕ ТРИ шва, (iii) решить `temperature` осознанно тем же диффом, (iv) держать один режим и для `control=extra_body_disable` (на glm пустой эффорт даёт thinking:disabled — не дефолт, а ВЫКЛЮЧЕНО, то есть зона эха), (v) ⚠ ловушка хеш-оси: `bankCheckpointExists` строит Request БЕЗ Temperature/Reasoning (`terminologist.go:498-501`), а `runAttempt` — с ними (`stagerun.go:403-406`, `Reasoning` входит в `RequestHash`, `render.go:308`) — сегодня оси совпадают лишь потому, что оба значения нулевые; «минимальная» правка только `:515` разведёт пробу чекпойнта и вызов ⇒ ложный `paid=false` и обрыв прохода по потолку до первого вызова. ✅ **ИСПОЛНЕНА СЕССИЕЙ 02.08, НЕ ПРИНЯТА И НЕ ЗАЛЕНДЕНА (D39.90):** построено не три патча, а **ДВА ШВА** — `config.InternalCall{…}.Stage()` (новый `internal/config/internal_call.go`) и `Runner.attemptRequest` (`stagerun.go:406`); рукописных `config.Stage{}` в движке не осталось ни одного (все 4 места + live-риг), все 4 сборки `RequestHash(Request{…})` схлопнулись в одну; ловушка хеш-оси закрыта в обе стороны на обоих путях. Перекупки НЕТ (`gates.terminology` не фолдится в снапшот; кортеж воспроизведён побайтно — бэнк-пробник `8e4495006b978ed4` в обе стороны; голден PASS без пере-захвата). Гранулярность решена ЗАМЕРОМ: одна ручка `gates.terminology.reasoning` на обе роли (парная выборка N=5: `low` 4/5 против `high` 5/5 — неразличимо при цене `high` ×2.30), вторая ручка `classify_reasoning` построена на n=1 и СНЯТА самой сессией. `Temperature` зафиксирована нулём осознанно. ⚠ Гарды шва — самописный AST-обход (`synthetic_stage_seam_test.go`), первая байтовая версия пробивалась 7 способами; форма гарда вынесена в решение владельца → **строка 107**. ⚠ **Что приёмка обязана пере-проверить отдельно, потому что это ДЕВИАЦИИ и оговорки, а не заслуги:** (i) **наследование эффорта у repair СНЯТО** — вопреки букве промта и D39.87 ключ сделан своим (`gates.repair.reasoning`); девиация может быть верной, но она не ратифицирована; (ii) починен `ThinksOnWire` на `control=extra_body_disable` — предикат врал «думает» при ПУСТОМ эффорте, то есть бэнк-роль на glm молча уезжала в thinking-off (зона эхо-мины, жёсткий гардрейл); область правки — **ровно случай «ключ отсутствует»**, явный `off` предупреждался и до, и после (в `arm-glm:43` он стоит осознанно — «таймауты ×3»), это оставлено специально, **чтобы приёмка не искала регресса в армах**; (iii) вывод «одна ручка достаточна» опирается на N=5, где **2 из 6 термов (元石/灵泉) стоят дословно в `prompts/zh-ru/classifier.md`** ⇒ это припоминание, а не суждение, и падение `low` было ровно по дискриминирующему подмножеству (1/4 против 4/4) — единственный датум ПРОТИВ одной ручки; (iv) **качество прозы не судил никто ни в одной пробе** — `low` подтверждён только по детерминированным осям | бэкенд | **на приёмке преемника** | приёмка (батарея + деньги двумя путями + адверсариал) → лендинг | D39.86, COLDRUN_B_DEBUG §3.6/Д2, **D39.90** | | 105 | **Роль `classifier` мис-вердиктится как эхо + честность двух новых строк наблюдаемости (D39.86).** (а) `classifyOutput` даёт поблажку `SourceEchoExpected` только `roleTerminologist` (`chunkrun.go:37`), а ответ классификатора по формату состоит из исходных ханьских термов ⇒ доля исходного письма 0.20–0.29 > порога 0.15 на каждом батче: живой артефакт пробы 6/6 несёт `verdict=cjk_artifact` при `bad_lines=0`. Ущерб узкий — `runBankRoleBatches` кладёт `run.texts[i] = att.text` без проверки диспозиции (`terminologist.go:603`), посчитанные эхо-ставки (`quality.go:313-321`) берутся из `chunk_status`, куда бэнк-путь не пишет ⇒ портятся только строки `tmctl report`/лога; **латентно** (`classify_types` выключен во всех шиппинг-конфигах). ⚠ Цена дисциплинированного фикса, которую надо знать заранее: бамп `classifierVersion` (литерал, сам не двигается) меняет payload снапшота → snapshot id → `RequestHash` ⇒ промах ВСЕХ чекпойнтов книги, то есть `--resnapshot` + пере-покупка. (б) тем же касанием — честность поверхностей: строка `VOICE` берёт `rules=` из конфига ВРЕМЕНИ ОТЧЁТА (`quality.go:436`), поэтому включение `gates.voice` после прогона печатает «измерено, чисто» для неизмеренной книги (воспроизведено); и она печатается при выключенном гейте, если `SpoilerLeaks>0` (дизъюнкция — поведение верное, формулировка отчёта/коммента неверна); знаменатель `BANKNOTE` = `len(states)` включая призрачные строки `retrieval_state`, тогда как соседний агрегатор их фильтрует (`quality.go:259-260`) ⇒ после пере-чанковки покрытие занижается | бэкенд | когда-нибудь (ближайшее касание банка/наблюдаемости; (б) — дешёвая часть, вердиктов не двигает) | малое касание + вердикт-двигающая половина (а) через СТОП-решение | D39.86 | | 106 | **Слой 3 НЕ достроен: контракт редактора = full-regen, а целевой — узкие мандаты + ДИФФЫ.** `09-target-architecture.md:121-126` дословно: «research/07 предписывает узкие мандаты + диффы, а не полную перегенерацию — сейчас ровно наоборот (4 мандата, full-regen), что и породило хвост инверсий»; целевой контракт — редактор правит anchored search/replace-спанами с детерминированным Go-apply (ограниченный blast-radius, дешевле, аудируемо, структурно omission-safe). Пак-16 построил петлю РЕМОНТА (починка флагнутого спана постфактум), а не diff-контракт роли ⇒ это разные вещи. **Строки не было ни одной** — дыра учёта, найденная сверкой 02.08 (грепы `diff`/`мандат`/`span` по бэклогу = 0). Смежное: арм Q4b «diff-fidelity+style редактор» (`exp15:108`) не прогонялся НИ РАЗУ, хотя трек B объявлен завершённым | владелец → бэкенд | когда-нибудь (смена контракта ролей = решение владельца) | ресёрч-арм → дизайн → крупная стройка | 09 §Слой 3, D39.90 | -| 107 | **Конвенции Go-репозитория: самописные AST-гарды → `x/tools/go/analysis`, линтер и CI (вопрос владельца 02.08).** Предмет: `backend/internal/pipeline/synthetic_stage_seam_test.go` (395 строк) — архитектурный гард, запрещающий рукописные `config.Stage{}` мимо шва; ходит по ДЕРЕВУ через `go/parser` из обычного `_test.go` пакета `pipeline`, резолвит пакет по ПУТИ импорта (не по имени), несёт пол на число разобранных файлов. Механика правильная по НАМЕРЕНИЮ и уже поймала 7 обходов (байтовая версия пробивалась 5 способами, AST-версия — ещё 2: алиас импорта и `[]config.Stage{{…}}`), но дом неправильный: **без типовой информации** (`go/packages`+`types.Info` вместо эвристики по путям), в тестовом пакете, и КАЖДЫЙ следующий инвариант породит ещё один такой обход. Индустриальная форма — analyzer на `golang.org/x/tools/go/analysis` (+`multichecker`, запуск `go vet -vettool=` и в CI), где алиас/дот-импорт закрываются ПО ПОСТРОЕНИЮ. Отдельная половина вопроса: **в репозитории нет ни `.golangci.yml`, ни `Makefile`, ни CI-воркфлоу** (проверено) — батарея гоняется руками каждой сессией. ⚠ Владелец прав в опасении: включение стандартного набора на ~200 файлах даст большой хвост находок ⇒ **первый шаг работы — $0-ЗАМЕР** (прогнать набор в report-only и посчитать находки по правилам), и только потом решать состав + режим внедрения (baseline «только новый код» против big-bang) | владелец → бэкенд | скоро (решение владельца; блокирует форму будущих гардов) | $0-замер объёма → решение состава → пак | D39.90, отчёт EFFORT_HANDLE §1.3 | -| 108 | **Реестр ЗАГЕЙЧЕННЫХ ТРИГГЕРОВ + норма закрытия «по нужности».** Шесть будущих реопенов живут только в телах D-нот и не имеют места, где их поднимут: **МАСШТАБ** (uniformity-пасс D12 · эмбеддинг A7/D2 «реопен = измеренный recall-разрыв, только batch-time лейн» · STITCH «бюджет ИЛИ измеренный эффект размера инъекции» · канон-пин серий) · **вторая пара живьём** (C-триггер softsign-decl · автономная Decl-эмиссия) · **вторая книга того же жанра** (жанровый shared-слой) · **первая traditional-книга** (probe-литералы 时辰/千万/数十万 цельным дата-батчем) · **появление Go-кода платформы** (`go.work` — ⚠ `platform/go.mod` УЖЕ заведён, триггер наступил) · **перед стройкой fix-8** (ёлочный экстрактор атрибуции + корпус-замер). Норма D39.66 «каждое отложено обязано ТЕМ ЖЕ лендингом получить строку или явное закрытие» нарушена ≥6 раз ПОСЛЕ собственной ратификации, и класс потерь узкий — теряются именно ЗАГЕЙЧЕННЫЕ РЕОПЕНЫ. Лечение: короткий реестр триггер→что вернётся→источник, сверяемый на каждом переходе горизонта (горизонт расписан до Ф3, точки сверки известны заранее) | оркестратор | скоро ($0, гигиена трекера) | завести реестр + сверку в норму лендинга | D39.66, D39.90 | +| 107 | **Конвенции Go-репозитория: самописные AST-гарды → `x/tools/go/analysis`, линтер и CI (вопрос владельца 02.08).** Предмет: `backend/internal/pipeline/synthetic_stage_seam_test.go` (395 строк) — архитектурный гард, запрещающий рукописные `config.Stage{}` мимо шва; ходит по ДЕРЕВУ через `go/parser` из обычного `_test.go` пакета `pipeline`, резолвит пакет по ПУТИ импорта (не по имени), несёт пол на число разобранных файлов. Механика правильная по НАМЕРЕНИЮ и уже поймала 7 обходов (байтовая версия пробивалась 5 способами, AST-версия — ещё 2: алиас импорта и `[]config.Stage{{…}}`), и слабое место одно: **нет типовой информации** (`go/packages`+`types.Info` вместо резолва по путям импорта), плюс каждый следующий инвариант породит ещё один такой обход. ⚠ **ТЕСТОВЫЙ ДОМ — СЛЕДСТВИЕ ЗАМЕРА, А НЕ НЕБРЕЖНОСТИ (отчёт §5.5, проверено запуском; моя формулировка «дом неверный» СНЯТА как над-клейм):** форма «архитектурное правило обычным тестом» — стандарт stdlib (`go/build/deps_test.go` держит так граф зависимостей, `go/types/errorcalls_test.go` — `ast.Inspect` по своим исходникам; аналог в Java — ArchUnit), а альтернатива **не проходит наше ограничение «падать на обычной батарее»**: `go test -vet=<свой анализатор>` → «-vet argument must be a supported analyzer», `GOFLAGS=-vettool` при `go test` игнорируется. Цена перехода на `x/tools/go/analysis` названа: он тянет `x/net` 0.26.0 → 0.54.0, **а `x/net/http2` — наш транспорт к провайдерам**. `golangci-lint` = 38.7 МБ бинарь и первый в проекте `.golangci.yml`; `exhaustruct` (инструмент ровно под исходный класс бага) даёт 16 находок, 15 из них в тестах. Настоящая развилка: принять ли бамп `x/net` ради типовой информации · заводить ли CI · остаётся ли гард тестом. Индустриальная форма — analyzer на `golang.org/x/tools/go/analysis` (+`multichecker`, запуск `go vet -vettool=` и в CI), где алиас/дот-импорт закрываются ПО ПОСТРОЕНИЮ. Отдельная половина вопроса: **в репозитории нет ни `.golangci.yml`, ни `Makefile`, ни CI-воркфлоу** (проверено) — батарея гоняется руками каждой сессией. ⚠ Владелец прав в опасении: включение стандартного набора на ~200 файлах даст большой хвост находок ⇒ **первый шаг работы — $0-ЗАМЕР** (прогнать набор в report-only и посчитать находки по правилам), и только потом решать состав + режим внедрения (baseline «только новый код» против big-bang) | владелец → бэкенд | скоро (решение владельца; блокирует форму будущих гардов) | $0-замер объёма → решение состава → пак | D39.90, отчёт EFFORT_HANDLE §1.3 | +| 112 | ⚠ **ПЯТЬ ШИППИНГ-КОНФИГОВ РЕПО ВСЁ ЕЩЁ НЕСУТ no-op `reasoning: "off"` НА ЧЕРНОВОЙ СТАДИИ — решение владельца (б) до них НЕ доехало (Д10 отчёта, D39.90).** Адреса проверены: `configs/pipeline-c1.yaml:49` · `pipeline-c2.yaml:26,39` · `pipeline-arm-mistral.yaml:30` · `pipeline-arm-glm.yaml:34` · `pipeline-arm-deepseek-pro.yaml:34`. Это ровно тот no-op, который отправил прогон в стену 0/9: на deepseek `off` = «не слать ничего» ⇒ вендор-дефолт `high`. Сессия сознательно их не трогала, потому что **правка двигает снапшот всем, кто этими конфигами пользуется** (перекупка), и вынесла вопрос наверх. ⚠ Не путать со стендом: правился только `coldrun-b/reprobe/bank-low/pipeline.yaml`, боевой `coldrun-b/pipeline.yaml` тоже НЕ тронут. **Решить: применять ли (б) к шиппинг-конфигам, каким именно, и когда платить перекупку** (на свежей книге — $0). ⚠ В `arm-glm:43` и `arm-deepseek-pro:43`/`c1:77` `off` стоит на РЕДАКТОРЕ осознанно — это другой случай, не трогать без отдельного разбора | владелец → бэкенд | скоро (иначе ратифицированное решение не действует в проде) | решение владельца → правка данных | D39.87, D39.90, EFFORT_HANDLE Д10 | +| 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 шаги 1–2, §7 | +| 108 | **Реестр ЗАГЕЙЧЕННЫХ ТРИГГЕРОВ + норма закрытия «по нужности».** ⚠ Первый жилец реестра, найденный тем же лендингом: **сиблинг-угроза экрана целевого языка** — выход на языке, БЛИЗКОМ к целевому (украинский/болгарский для ru): ни одного события не наблюдалось, но если появится, дискриминатор — плотность РУССКО-ЭКСКЛЮЗИВНЫХ букв (ы/э/ё) НИЖЕ ожидания, а НЕ замыкание алфавита (`EFFORT_HANDLE §5.4` шаг 8). Шесть остальных реопенов живут только в телах D-нот и не имеют места, где их поднимут: **МАСШТАБ** (uniformity-пасс D12 · эмбеддинг A7/D2 «реопен = измеренный recall-разрыв, только batch-time лейн» · STITCH «бюджет ИЛИ измеренный эффект размера инъекции» · канон-пин серий) · **вторая пара живьём** (C-триггер softsign-decl · автономная Decl-эмиссия) · **вторая книга того же жанра** (жанровый shared-слой) · **первая traditional-книга** (probe-литералы 时辰/千万/数十万 цельным дата-батчем) · **появление Go-кода платформы** (`go.work` — ⚠ `platform/go.mod` УЖЕ заведён, триггер наступил) · **перед стройкой fix-8** (ёлочный экстрактор атрибуции + корпус-замер). Норма D39.66 «каждое отложено обязано ТЕМ ЖЕ лендингом получить строку или явное закрытие» нарушена ≥6 раз ПОСЛЕ собственной ратификации, и класс потерь узкий — теряются именно ЗАГЕЙЧЕННЫЕ РЕОПЕНЫ. Лечение: короткий реестр триггер→что вернётся→источник, сверяемый на каждом переходе горизонта (горизонт расписан до Ф3, точки сверки известны заранее) | оркестратор | скоро ($0, гигиена трекера) | завести реестр + сверку в норму лендинга | D39.66, D39.90 | | 109 | **Продуктовые требования БЕЗ строки-носителя (сверка 02.08):** **ПТ-6** структурные традиции целевого языка (короткие zh-абзацы → читаемые ru-структуры) — держится только редакторскими мандатами в пар-промптах, поверхности измерения нет, в составе Ф2-гейтов (52) структуры абзацев нет · **ПТ-7** «слабый оригинал: подправлять художественно или быть верным» — вопрос владельца, не заведён даже в блоке «висит на владельце»; после ответа: режим параметром запуска (данные, не ветка Go) + мандат в промпте + гейт «улучшение vs отсебятина» · **ПТ-22** продуктовый ИНТЕЙК настроек (сегодня = рукописный `book.yaml`; частично покрыт 67 в части «версия исходника») · **ПТ-10** сам механизм веб-фетча (tool-calling, провенанс/кэш добытого, инжект под правилом «книга = недоверенные данные») — есть только гейт безопасности 70. Гигиена реестра тем же касанием: ПТ-24 не проставлена 101, ПТ-1/ПТ-11 не проставлена 105, ПТ-2 не проставлены 46 и 34а | оркестратор/владелец | скоро ($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 | diff --git a/docs/architecture/05-decisions-log.md b/docs/architecture/05-decisions-log.md index 8fc717a7..28ecdc04 100644 --- a/docs/architecture/05-decisions-log.md +++ b/docs/architecture/05-decisions-log.md @@ -1322,4 +1322,13 @@ API-529-долг закрыт: 8-осевой refute-by-default воркфлоу **7. Вопрос владельца, поднятый в решение (строка 107): форма архитектурных гардов и конвенции репозитория.** Предмет — `backend/internal/pipeline/synthetic_stage_seam_test.go` (395 строк): гард ходит по дереву через `go/parser` из обычного `_test.go`, резолвит пакет по ПУТИ импорта, несёт пол на число разобранных файлов. **Намерение верное и уже окупилось** (поймано 7 обходов: байтовая версия пробивалась пятью способами, AST-версия — ещё двумя, алиасом импорта и `[]config.Stage{{…}}`; сессия честно записала, что первая версия говорила `ok` на посаженном пятом сайте). **Дом неверный:** без типовой информации (`go/packages`+`types.Info` вместо эвристики по путям), в тестовом пакете, и каждый следующий инвариант породит ещё один такой обход. Индустриальная форма — analyzer на `golang.org/x/tools/go/analysis` (+`multichecker`, `go vet -vettool=`, CI), где алиас и дот-импорт закрываются ПО ПОСТРОЕНИЮ. Вторая половина вопроса: **в репозитории нет ни `.golangci.yml`, ни `Makefile`, ни CI-воркфлоу** (проверено) — батарея гоняется руками каждой сессией. Опасение владельца про хвост техдолга обоснованно ⇒ **первый шаг обязан быть $0-ЗАМЕРОМ** (набор в report-only, находки по правилам), и только потом состав + режим внедрения (baseline «только новый код» против big-bang). Решение — за владельцем, исполнение — следующей сессией оркестратора. -**8. Состояние зон на момент передачи.** `backend/` — незакоммиченный пак (п.1), сессия отработала и закрыта. `frontend/` — сессия ЖИВАЯ и коммитит сама по D39.88 (за день ушли `d8437d6`, `8d6b3f7`, `804dbc9`, `8be1e41`); правило pathspec-коммита до неё доехало только релеем владельца. `platform/` — кода нет, `go.mod` заведён. `eval/` — пусто по новому. **Очередь на момент передачи (пересчитано скриптом, не на глаз): 93 строки · зона бэкенд 45 строго / 59 широко · блокеров очереди 0 (104 переведена в «на приёмке») · «скоро» 11 (2·4·5·18·46·49·55·95·107·108·109).** +**8. Состояние зон на момент передачи.** `backend/` — незакоммиченный пак (п.1), сессия отработала и закрыта. `frontend/` — сессия ЖИВАЯ и коммитит сама по D39.88 (за день ушли `d8437d6`, `8d6b3f7`, `804dbc9`, `8be1e41`); правило pathspec-коммита до неё доехало только релеем владельца. `platform/` — кода нет, `go.mod` заведён. `eval/` — пусто по новому. **Очередь на момент передачи (пересчитано скриптом после добора п.9: 95 строк · зона бэкенд 46 строго / 61 широко · блокеров очереди 0 (104 → «на приёмке») · «скоро» 13 (2·4·5·18·46·49·55·95·107·108·109·112·113).** + +**9. ДОБОР ПОСЛЕ НЕЗАВИСИМОГО РЕВЬЮ ЛЕНДИНГА (author≠reviewer, тот же день).** Ревьюер подтвердил числовую часть (все числа пробы и строки 46 сошлись с отчётом, все `file:line` живые, счёт очереди воспроизведён скриптом, все четыре снятия «ложных долгов» обоснованы) и нашёл, что дефект передачи — **в НЕзаписанном**: просели предупреждения и адресованные наверх вопросы, у которых нет числа. Исправлено тем же лендингом: +- **Мой над-клейм СНЯТ:** «дом гарда неверный» (строка 107). Отчёт §5.5 замерил обратное: форма «архитектурное правило обычным тестом» — стандарт stdlib (`go/build/deps_test.go`, `go/types/errorcalls_test.go`), а индустриальная альтернатива **не проходит наше ограничение «падать на обычной батарее»** (`go test -vet=<свой>` не поддерживается, `GOFLAGS=-vettool` при `go test` игнорируется), и переход на `x/tools/go/analysis` тянет `x/net` 0.26.0 → 0.54.0, **где `x/net/http2` — наш транспорт к провайдерам**. Тестовый дом был осознанным следствием замера. Владельцу вопрос переформулирован честно: принять ли бамп `x/net` ради типовой информации · заводить ли CI · остаётся ли гард тестом. +- **Второй мой над-клейм СНЯТ** (строка 44): «число флора влияет на цену ретрая, а не на проходимость» — незамеренная экстраполяция. При `low` флор не варьировался ни разу, упавший батч умер ровно на потолке 8000. +- **Заведены строки на потери:** **112** — пять ШИППИНГ-конфигов (`pipeline-c1.yaml:49` · `c2:26,39` · `arm-mistral:30` · `arm-glm:34` · `arm-deepseek-pro:34`) до сих пор несут no-op `reasoning: "off"` на ЧЕРНОВОЙ стадии, то есть ратифицированное решение (б) в проде НЕ действует, а правка двигает снапшот их пользователям ⇒ вопрос владельцу, и он был бесхозным; **113** — числа «18/20 · 0 FP на 1055 · запас 13×» получены ВРЕМЕННЫМ тестом, который сессия удалила, то есть контрактное число невоспроизводимо ⇒ корпус-фикстура + регресс-тест на запас ДО любой правки по строке 46. +- **Дописано в строку 104 то, что приёмка обязана смотреть отдельно:** наследование эффорта у repair СНЯТО против буквы промта и D39.87 (девиация, не ратифицирована) · починка `ThinksOnWire` на `extra_body_disable` (предикат врал «думает» при пустом эффорте ⇒ бэнк-роль на glm молча уезжала в thinking-off; область правки — ровно случай «ключ отсутствует», явный `off` в армах предупреждался и до, и после, оставлено специально чтобы приёмка не искала регресса) · вывод «одна ручка» опирается на N=5, где 2 из 6 термов стоят дословно в промпте классификатора, и падение `low` было ровно по дискриминирующему подмножеству (1/4 против 4/4) · **качество прозы не судил никто ни в одной пробе**. +- **Дописано в строку 46:** порог abstain 200 букв · база off-target на ЧЕРНОВОЙ вызов **3.02%**, а не опубликованные ~1.5% (знаменатель пулил редакторские выходы — третья самопоправка сессии) · **не проверено, что редактор делает с английским черновиком** — от этого зависит, чем являются остаточные 0.18%: потерей юнита или тихо отгруженным релейным zh→en→ru · `cultivation` (86 из 1055 здоровых) чинить в СИДЕ, а не порогом · Hunspell/GlotScript-эмбед не строить. +- **Строка 108 получила первого жильца:** сиблинг-угроза (выход на языке, близком к целевому) с дискриминатором «плотность ы/э/ё НИЖЕ ожидания, а не замыкание алфавита». **Строка 36б приведена в соответствие** собственному снятию (зона → полигон-замер через строку 5; прежняя форма «отдельный дизайн (Р4)» завышала счёт бэкенд-очереди). +- **Норма, нарушенная этим же лендингом и потому названная вслух:** сжимая отчёт, я сохранил всё, у чего есть число, и потерял часть того, у чего числа нет. Для отчётов с секцией «пошаговый план следующей сессии» правило сверки — идти по ней ПУНКТАМИ, а не по сводке.