From bead5cc612e48727526956bb7296801fa40a6bbf Mon Sep 17 00:00:00 2001 From: "Claude (backend session)" Date: Sun, 2 Aug 2026 19:00:23 +0300 Subject: [PATCH] Close orchestrator ten: hand the unaccepted effort-handle pack to the successor, trim the bank research, open six tracker holes as rows and raise Go lint conventions to the owner --- docs/PROGRESS.md | 29 +- docs/architecture/05-decisions-log.md | 22 +- .../reports/EFFORT_HANDLE_2026-08-02.md | 435 ++++++++++++++++++ 3 files changed, 477 insertions(+), 9 deletions(-) create mode 100644 docs/archive/reports/EFFORT_HANDLE_2026-08-02.md diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 5950c7f4..aec10e37 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -1,11 +1,12 @@ # Журнал прогресса -> **⟶ ТЕКУЩЕЕ СОСТОЯНИЕ** (на 2026-08-02, голова D39.89). **Источник истины по РЕШЕНИЯМ — `architecture/05-decisions-log.md`; этот файл — ЖУРНАЛ.** +> **⟶ ТЕКУЩЕЕ СОСТОЯНИЕ** (на 2026-08-02, голова D39.90). +> - ⚠⚠ **ПЕРЕДАЧА ОТ ОРКЕСТРАТОРА №10 → №11 (D39.90). ЗАДАЧА №1 ПРЕЕМНИКА — ПРИЁМКА бэкенд-пака строк 104/46/16.** Отчёт `archive/reports/EFFORT_HANDLE_2026-08-02.md` закоммичен с баннером «коммит ≠ ратификация»; **код сессии лежит в дереве НЕЗАКОММИЧЕННЫМ** (новые `backend/internal/config/internal_call.go`, `internal_call_test.go`, `backend/internal/pipeline/synthetic_stage_seam_test.go` + 10 правленых файлов) — **дерево НЕ чистить, `reset --hard`/`checkout` поверх него НЕ делать, фронт-сессия ЖИВАЯ и коммитит сама.** Приёмка = батарея с фрозен-числами исполнением + пере-вывод $0.045095 вторым путём из сырья + адверсариал по несущим клеймам (два шва · отсутствие перекупки · гарды · парная выборка N=5) → лендинг. **НА ВЛАДЕЛЬЦЕ два решения:** развилка (а)/(б)/(в) по строке 46 (выбор сессии — (а)) и строка 107 (форма гардов + линтер/CI, первым шагом $0-замер объёма находок). **Источник истины по РЕШЕНИЯМ — `architecture/05-decisions-log.md`; этот файл — ЖУРНАЛ.** > - **Сделано (сводно; детали — D-лог и архив-слайсы):** Ф0 ✅ · Ф1-инфра ✅ · арх-ресет D39 (7 слоёв, паки 11–16) ✅ · паки 17 «канал B» · 18 «долги» · 19 «голос/состояние» · 20 «банк+терминолог» ✅ (D39.26–28/31/41–56) · мини-прогон (D39.37) и ХОЛОДНЫЙ прогон (D39.58: recall банка 0.918/0.980, банк приходит переведённым) приняты · полигон-пакеты 5–8, ToS-речек (D39.57), Р6+P4 (D39.61) закрыты · **карта языковой привязки движка (D39.60): 149 сайтов/45 файлов, книго-ось чиста (4), ja→ru безопасно без правки Go, en→ru — нет** · Р1–Р4 закрыты целиком (D39.63: Р2 = ЗНАЧЕНИЕ, Р4 = норма потолка recall) · **ФАЗА 2 ОБЩНОСТИ ✅ (D39.64: П0 эмбед-хеш · П1 цель-шов · П2 скрипт-шов, ko-баг закрыт · П3 нарезка · П4 манифест-по-каналам; голден вердикт-нейтрален 0/172, майнер-парити EXACT)** · жанровый словарь отменён как класс (D39.47) · петля ремонта построена и НЕ включена (D39.38). > - **Курс (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.89, обновлять при каждом лендинге):** всего **87** строк · зона бэкенд **45** · **блокеров очереди 1** (104) · «скоро» **8** (2·4·5·18·46·49·55·95); остальное «когда-нибудь». ⚠ **Счёт — НИЖНЯЯ граница долга, а не потолок:** трекер содержит только замеченное, и 02.08 дважды за $0 свежие глаза вытащили из кода дефекты, которых в нём не было (релей фронта → строки 99/100/102; приёмочное ревью → третий шов `repair.go:384` в 104 и честность `quality.go:436` в 105). Лента ✅ выше — про ЗАКРЫТЫЕ паки, читать её как «долга нет» неверно (разбор — вопрос владельца 02.08, D39.89). +> - **ЕДИНЫЙ БЭКЛОГ — секция «Бэклог» ниже** (одна таблица, единственный трекер; каждая петля обязана иметь диспозицию: решено / отложено-с-записью / отклонено; ведёт оркестратор). **СЧЁТ ОЧЕРЕДИ на 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). > - Архивы хроники: `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; правки — только через оркестратора) @@ -17,7 +18,7 @@ | **— ВИСИТ НА ВЛАДЕЛЬЦЕ —** | | | | | | | 2 | Четыре вопроса границы «алгоритмического идеала» (Annotator · семантический судья · ja→ru §B5 · ru-target до/после) | владелец | скоро (гейт «добора идеала» перед МАСШТАБОМ) | отдельное решение | D39.33, D39.38 | | 4 | **Ре-чек ToS по триггерам** — первый ИСПОЛНЕН 31.07, дельт вердиктов нет (D39.57); предмет Google-мониторинга перевешен на цепочку договора (PUP · Additional ToS · Google APIs ToS); следующие: квартал 25.10.2026 · первая лейблованная книга · любая правка `accepts_labels` | владелец/полигон | скоро (следующий триггер 25.10.2026) | отдельное решение (правило) | D39.32, D39.57 | -| 5 | **Судья-с-декоем/36б «второе мнение» → РАСШИРЕНО ДО АРБИТРАЖА БАНКА (D39.89), ПРОМТ ВЫДАН.** Бэкенд-стройка ЗАКРЫТА дизайном (D39.69): маршрут = полигон-ЗАМЕР нужности рецензента-другого-семейства ПОВЕРХ §1+§2 (Q2); переживёт замер → тонкая колонка наблюдаемости, не гейт. **Вход владельца 02.08 добавил в тот же замер четыре вопроса, которых в Q2 не было:** (i) калибровка САМООЦЕНКИ моделей как сигнала (числа против слов · устойчивость · **сравнимость между моделями**), (ii) взвешенный арбитраж против равноправного «консилиума без голоса», (iii) **связность системы термов как ограничение** — единица арбитража обязана быть КЛАСТЕРОМ (семья корня · серия · регистр · алиас-граф), а не строкой (по-терминный argmax возвращает классом дефект, вылеченный со-батчингом, D39.65 стр.21), (iv) инжект/фетч отдельной осью (мерить послушание и ВРЕД, не recall). Приоры против наивной формы уже есть: судья = катастроф-экран, не ранжировщик (D39.46) · канал отказа нестабилен, размах 0.375 (D39.50) · согласие прогонов слабое, Жаккар 0.077–0.40 (D39.50). Гейт всего — **голд-набор** (ядро: сид v2 53 `approved` + BANK-FULL 150 + банк coldrun-a; мини-голд алиасов §E-1 research/20 ждёт владельца с 17.07). Промт `BANK_ARBITRATION_RESEARCH_SESSION_PROMPT.md` (потолок $2.00, суб-потолки, пре-регистрация; легитимный исход — «закрыть по нужности») | полигон/ресёрч | **скоро (промт выдан D39.89; запуск — по слову владельца)** | замер → дизайн → решение | D39.50 п.6, D39.58, D39.69, D39.70 (Q2), **D39.89** | +| 5 | **Судья-с-декоем/36б «второе мнение» → РАСШИРЕНО ДО АРБИТРАЖА БАНКА (D39.89), ПРОМТ ВЫДАН.** Бэкенд-стройка ЗАКРЫТА дизайном (D39.69): маршрут = полигон-ЗАМЕР нужности рецензента-другого-семейства ПОВЕРХ §1+§2 (Q2); переживёт замер → тонкая колонка наблюдаемости, не гейт. **Вход владельца 02.08 добавил в тот же замер четыре вопроса, которых в Q2 не было:** (i) калибровка САМООЦЕНКИ моделей как сигнала (числа против слов · устойчивость · **сравнимость между моделями**), (ii) взвешенный арбитраж против равноправного «консилиума без голоса», (iii) **связность системы термов как ограничение** — единица арбитража обязана быть КЛАСТЕРОМ (семья корня · серия · регистр · алиас-граф), а не строкой (по-терминный argmax возвращает классом дефект, вылеченный со-батчингом, D39.65 стр.21), (iv) инжект/фетч отдельной осью (мерить послушание и ВРЕД, не recall). Приоры против наивной формы уже есть: судья = катастроф-экран, не ранжировщик (D39.46) · канал отказа нестабилен, размах 0.375 (D39.50) · согласие прогонов слабое, Жаккар 0.077–0.40 (D39.50). Гейт всего — **голд-набор** (ядро: сид v2 53 `approved` + BANK-FULL 150 + банк coldrun-a; мини-голд алиасов §E-1 research/20 ждёт владельца с 17.07). Промт `BANK_ARBITRATION_RESEARCH_SESSION_PROMPT.md` (потолок $2.00, суб-потолки, пре-регистрация; легитимный исход — «закрыть по нужности»). ⚠ **ЗАХОД 02.08 ЗАПУЩЕН И ДОСРОЧНО ЗАКРЫТ ВЛАДЕЛЬЦЕМ — «требуются фиксы в бэкенд» (D39.90). Артефакта в дереве НЕТ:** ни `docs/research/24-*`, ни `eval/bank_arbitration/`, ни свежих файлов в `~/books` ⇒ **находки того захода НЕ сохранены; если они ценны — их надо вынуть из истории сессии, иначе работа повторяется с нуля.** Рекомендация оркестратора №10 к пере-запуску (ПОДРЕЗАТЬ, а не гонять целиком): **держать** §3-A (критика кода, $0 — она и вскрывает нужные бэкенд-фиксы), **B1** голд (гейт всего) и **B3** формы консилиума с контролем «одна модель N раз»; **свернуть** B2 (калибровка уверенности) до под-пробы внутри B3 — как отдельная работа она дорога, а приоры D39.46/D39.50 уже сильно против неё; **отложить** §5-C (инжект/фетч) до бэкенд-доработок, потому что мерить послушание инъекции без движка нечем. Потолок с $2.00 к $1.20 | полигон/ресёрч | **скоро (пере-запуск подрезанным скоупом — по слову владельца)** | замер → дизайн → решение | D39.50 п.6, D39.58, D39.69, D39.70 (Q2), D39.89, **D39.90** | | 6 | **Строка Gemini в `accepts_labels`** — ждёт слова владельца о подписи интерпретации сужения как разрешения; ре-чек 31.07 понизил приоритет: подпись даёт ПРАВО, но не судью 18+ (фильтр неконфигурируем D22.6 + обход запрещён договором) — возвращаться при вопросе, требующем именно права | владелец | когда-нибудь | отдельное решение | D39.32, D39.57 | | 7 | Q2 «редактор под `sexually-explicit`» (grok-4.3 интерим · glm-5 после сверки ToS Z.AI · mistral вон) | владелец | когда-нибудь (перед первой explicit-книгой) | отдельное решение | D39.27 п.7 | | 8 | D22.7 пер-чанковый L3-скрин — несня­тое предусловие первой erotica-книги в проде, отдельный гейт | владелец | когда-нибудь | отдельное решение | D22.7, CURRENT-STATE (оркестратор) | @@ -31,7 +32,7 @@ | 14 | **Четыре data-инженерных флага фазы-2 общности, каждый с рекомендованным дизайном** (§5 отчёта): ё-фолд → target-данные (`char_fold`; смена сигнатуры core-примитива через вердикт-несущий банк, сдвиг `memory_version`) · segmentation-фолбэк громким (ломает контракт corridor-фолбэка `pipeline.go:839-848` + голден-фикстура на нём; лечение — объявить блок в голден-yaml) · `Fertility` per-script map (калибровка ждёт боевого токенизатора) · `source-encoding.txt` + Go-реестр декодеров | владелец | когда-нибудь (следующий пак общности) | отдельное решение | D39.64, GENERALITY_PHASE2 §5.1–5.4 | | 86 | **Мелкие открытые решения одним списком** (свип D39.66): echo-семантика дропнутого c-lite-члена (D39.18 — оставить pre-c-lite?) · magnitude-кап тяжёлой CJK-утечки (D38.3 п.4в; сейчас strip+flag) | владелец | когда-нибудь | отдельные решения | D39.66, D39.69(feed_cap закрыт §1) | | **— ХВОСТЫ ХОЛОДНОГО ПРОГОНА (исполнен достаточно, D39.58; Р7 владельца) —** | | | | | | -| 16 | Полная цена холодного старта: edit-волна не гонялась (Р7); измерено всё ДО редактуры (драфт+банкнота $0.0247/волна · терминолог $0.006–0.013/проход) | бэкенд | когда-нибудь (первый прогон добора идеала) | добор идеала | D39.58 | +| 16 | Полная цена холодного старта: edit-волна не гонялась (Р7); измерено всё ДО редактуры (драфт+банкнота $0.0247/волна · терминолог $0.006–0.013/проход). ⚠ **Прогон НЕ НАЧАТ и закрыт владельцем как неуспешный на этом этапе (02.08, D39.90)** — деньги фазы C не тронуты ($0). Свежие числа с пробы `bank-low` (10 глав, `low` на черновике И на бэнк-ролях): черновая волна 20/20 ok — $0.031639 flash + $0.010350 pro · терминолог $0.005750 · классификатор $0.004286 · **весь заход $0.045095**, леджер ≡ независимому пересчёту до нуля. Редакторская волна по-прежнему НЕ гонялась ⇒ строка жива, и она же держит оси голоса (13б/24) | бэкенд | когда-нибудь (первый прогон добора идеала — после решения по 46) | добор идеала | D39.58, **D39.90** | | 18 | **Эмиссия головы 蛊**: сид-половина = чек-лист (определяющий терм книги сидится `allow_short`, D39.50); эмиссия-КАНАЛ демотирован до ИЗМЕР-ГЕЙТА (Q7): полигон-замер «меняет ли эмиссия головы рендер композитов» — строить ТОЛЬКО по эффекту и ПОСЛЕ #10 (однознаковый пост-чек чинится чекер-паком); перед стройкой резолвить K-гейт и KWIC-грязь одиночной головы | полигон → бэкенд | скоро (санкция Q7 D39.70 — после #10, очередью с ре-пробой) | полигон-замер → решение | D39.58, D39.60, D39.69 | | 24 | **Остаток: авто-режим флага** (проект Б не гонялся) · оси голоса A–D (профили не подписаны; черновик готов — `coldrun-a/SIGN-PACKAGE.md` §3) ; + слот инъекции голоса и решение gates.voice при ненулевых осях (D39.55/D21 п.2) · слой-2 voice не строим до доказательства слоя-1 · сверить until_ch 白凝冰 при курации сида (D19.3в) | бэкенд | когда-нибудь (первый прогон добора идеала) | добор идеала | D39.40, D39.58 | | **— ТЕКУЩАЯ ОЧЕРЕДЬ (D39.59) —** | | | | | | @@ -45,7 +46,7 @@ | 82 | **Морфо-гейт РОДА** (C3: русский глагол прош. вр. при gender=hidden = механический спойлер-канал; «жалоба №1 читателей MTL»; python-сайдкар/pymorphy, связка с морфопроходом Decl из 73) | бэкенд | когда-нибудь (Ф2-гейты) | отдельный пак (с 52) | 06-реестр C3, research/12, D39.66 | | 85 | **Пилот-преп добор** (к переупаковке PACKAGE4): Bertalign GOLD-пары + zh→ru spot-check (D29.2в; GPL-тулинг отдельно) · fidelity-каскад R2 shadow с корпус-подготовкой (D25.2) · exp08 v3 пере-съём COGS до фиксации budget_usd (D21.8) | полигон | когда-нибудь (Ф2.5) | пилот-преп-промт | D25, D29, D21.8, D39.66 | | **— ПАК-21 «чекеры»: РАСТВОРЁН (D39.62); шестёрка исполнена 2/6 фазой 2 (D39.64: #11 · строка 26), остаток — ниже —** | | | | | | -| 93 | **Остатки строки 93 после пачки (D39.82):** строгий OffLanguage (36а, deferred D39.78) · 分之-разметка прежде стройки DC2 word↔word (полигон) · F4-хвост: `redrive --dry-run` обходит pre-flight, а `store.Open` мутирует SPOF-файл (миграции + recoverReservations; коммент «mutates nothing» неверен) — pre-flight и на dry-run при существующей БД либо read-only план; заодно stat-скип точной формой `fs.ErrNotExist` | бэкенд/полигон | когда-нибудь | малое касание / полигон-слот | D39.78, D39.82 | +| 93 | **Остатки строки 93 после пачки (D39.82):** строгий OffLanguage (36а, deferred D39.78) · 分之-разметка прежде стройки DC2 word↔word (полигон) · F4-хвост: `redrive --dry-run` обходит pre-flight, а `store.Open` мутирует SPOF-файл (миграции + recoverReservations; коммент «mutates nothing» неверен) — pre-flight и на dry-run при существующей БД либо read-only план; заодно stat-скип точной формой `fs.ErrNotExist`. ⚠ **Остаток НЕ однороден по гейту (сверка 02.08):** F4-хвост и строгий OffLanguage свободны, а `分之`-часть ГЕЙЧЕНА полигон-разметкой среза («строить вслепую против мандата» — якорь техдолга) ⇒ не подавать строку как «малое касание без гейта» | бэкенд/полигон | когда-нибудь | малое касание / полигон-слот | D39.78, D39.82 | | 98 | **DC7 грейд-консистентность — пере-гейчен по сид-покрытию (D39.82):** замер пачки реален (25 юнитов/93 «разряд» ≠ канон «класс» на labels-финалах), НО финалы — прогоны до/вне сид-v2-канона, а грейды 甲/乙/丙/丁等 теперь approved-записи сида с decl-формами: mempostcheck флагнёт «разряд» промахом dst; строить DC7 только если ОСТАТОК девиаций переживёт сид-покрытие — замер на первом СИДОВОМ прогоне добора идеала; дом канона при стройке = book.yaml (как register_blocklist; ратифицировано D39.82 — НЕ dc-checkers.txt, посылка D39.79 исправлена) | бэкенд | когда-нибудь (гейт: первый сидовый прогон добора идеала) | замер остатка → решение | D39.79, D39.82, SMALLPACK §5-E1 | | 28 | Банк-линт латиницы в dst или строгая форма языкового предиката (7 строк утечки алфавита проходят экран) | бэкенд | когда-нибудь (добор идеала — носитель «свежий мини-прогон» растворён D39.67, актуализация D39.79) | касание чекеров при данных добора (помнить оговорку 36а: «甲等 → класс Цзя» строгой формой не ловится) | D39.52, D39.62, D39.64, D39.79 | | 28а | **Prompt-injection-проба входного текста** ($0): сепаратор ⟦TM-BANK-v1⟧ и якорь-подобные маркеры В ТЕКСТЕ КНИГИ — поведение среза/парсера/инъекции (книга = недоверенные данные; инструментов у моделей нет, но канал банкноты читает вывод по маркеру) | бэкенд/полигон | когда-нибудь | малая проба | сводка-ревью 26.07 | @@ -67,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а) | бэкенд | когда-нибудь (после развилки 74) | отдельное решение | D39.37(10), D39.86 | +| 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** | | 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`) | бэкенд | **скоро** (условие безопасности варианта (б) строки 74 — именно в нём наблюдался класс) | отдельное решение (вердикт-двигающее) | D39.39(д), D39.86 | +| 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** | | 47 | M2-кэш / доктрина Д2 — кандидат на отдельную ратификацию | оркестратор/бэкенд | когда-нибудь | отдельное решение | D39.42 | | 48 | Направленная банкнота — вернуться по замеру покрытия терминолога | бэкенд | когда-нибудь | отдельное решение | D39.42 | | 48а | **Серийный шаринг банка** — РЕАЛИЗАЦИЯ (экспорт подписанного глоссария как сид-YAML следующей книги серии; спойлер-окна плющатся в since_ch=0); контракт round-trip держится тестом, самой фичи нет | бэкенд | когда-нибудь (перед второй книгой серии) | отдельное решение | D39.42 задел (а), PACK20_BANK_BUILD З-а | @@ -109,8 +110,18 @@ | 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` и обрыв прохода по потолку до первого вызова | бэкенд | **блокер-очереди при выборе (б)/(в′)** | правка Go с тестом + батарея (после развилки 74) | D39.86, COLDRUN_B_DEBUG §3.6/Д2 | +| 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** | | 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 | +| 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 | +## Оркестратор №10 — ЗАКРЫТИЕ СЕССИИ И ПЕРЕДАЧА №11 (D39.90), 02.08 + +**Задача №1 преемника — приёмка бэкенд-пака 104/46/16** (отчёт закоммичен с баннером «коммит ≠ ратификация», код В ДЕРЕВЕ незакоммичен — не чистить). **Главный технический результат дня:** проба банка на `low` ЗЕЛЁНАЯ — терминолог 4/5 батчей `stop`, consolidated 72, против 1/5 и 1 терма из 81 на вендор-дефолте `high`; весь заход $0.045095 из $0.10, леджер ≡ независимому пересчёту ДО НУЛЯ; провод вскрыт (35 тел, `reasoning_effort:"low"` во всех, ключей `thinking` ноль) ⇒ **гардрейл DeepSeek доказан проводом.** ⚠ `low` стену не убирает, а разрежает (упавший батч: `completion=7999`, `reasoning=7999`). **Строка 46 переоценена в МЕНЬШУЮ сторону замером:** боевой гейт уже ловит 18 из 20, остаточная дыра 0.18%, но второй рубеж (санитайзер) на черновике не стоит вовсе из-за позиционного `isFinal` — и тем же `isFinal` глушатся латинный линт, флаггер голоса и глоссарный пост-чек. Развилка (а)/(б)/(в) — на владельце. **Строка 16 закрыта владельцем как неуспешная на этом этапе**, редакторская волна снова не гонялась ⇒ оси голоса без данных. **Банк-ресёрч запущен и досрочно закрыт владельцем, артефакта в дереве НЕТ** — находки не сохранены; пере-запуск подрезанным скоупом (держать A/B1/B3, свернуть B2, отложить C; потолок $1.20). **Дыры трекера заведены строками 106–111**, снято расхождение 74↔44, уточнён гейт 93; четыре ложных «долга» сняты как закрытые решениями (резолвер слоя 7 · чистый детектор · 36б · полярность). **Владельцу подняты в решение** форма архитектурных гардов и конвенции репо (строка 107): намерение `synthetic_stage_seam_test.go` верное и окупилось (7 пойманных обходов), дом неверный — analyzer на `x/tools/go/analysis` вместо самописного обхода; `.golangci.yml`/`Makefile`/CI в репо нет вовсе, первый шаг — $0-замер объёма находок. + ## Оркестратор №10 — АРБИТРАЖ БАНКА: гипотеза владельца о консилиуме принята к ПРОВЕРКЕ, промт выдан (D39.89), 02.08 Владелец поднял банк как центральную ценность и предложил для перевода термов **«консилиум без голоса»** со скорами уверенности от моделей, с оговоркой про слом стиля/системы соседних термов; отдельно потребовал в промте секцию рекомендованных дальнейших алгоритмов и критики текущего кода. **Разобрано как гипотеза на проверку, не как ТЗ.** Ключевое: трек НЕ новый — маршрут «второе мнение» ратифицирован (D39.69 закрыл стройку, D39.70 Q2 санкционировал полигон-замер, строка 5), поэтому Q2 РАСШИРЕН четырьмя новыми вопросами вместо дубля. **Три наших замера уже бьют по наивной форме гипотезы и вписаны в промт приорами:** судья = катастроф-экран, а не ранжировщик (D39.46) · канал отказа роли нестабилен (⟦TM-NO-DST⟧ размах 0.375, выдумывание dst 77–82%, D39.50) · согласие прогонов слабое (Жаккар 0.077–0.40, D39.50). **Несущее возражение оркестратора:** единица арбитража обязана быть КЛАСТЕРОМ, а не строкой — по-терминный argmax возвращает классом ровно тот дефект, который вылечен со-батчингом серий (D39.65 стр.21), а `Neighbours` (единственный межстрочный сигнал `ScoreVariants`) работает только при уже существующей подписи, которой у автономного банка нет. **Экономическая рамка, вписанная числами:** арбитраж платится раз на книгу и насыщается по числу различных термов ($0.006–0.013/проход), инжект — на каждом чанке каждой волны каждой роли (`memory.go:523`) ⇒ расточительность законна в арбитраже и запрещена в инжекте. Промт `BANK_ARBITRATION_RESEARCH_SESSION_PROMPT.md`: работы A (критика кода, $0) · B (голд → калибровка уверенности → формы консилиума, ≤$1.40) · C (инжект/фетч, ≤$0.60) · D (рекомендации тремя корзинами, $0); потолок $2.00, пре-регистрация каждой пробы, легитимные исходы «закрыть по нужности» объявлены заранее. ⚠ Названы коллизии: `backend/` живая, coldrun-a — эталон на чтение, coldrun-b — стенд живой сессии, валидный базлайн качества банка = coldrun-a (в coldrun-b терминолог сломан транспортом). **Запуск — по слову владельца.** @@ -225,6 +236,8 @@ Q1 = П1 цель-шов санкционирован («главное бэке ## Бэкенд +**Ручка эффорта (стр.104) ✅ ЗАКРЫТА · проба банка на `low` ✅ ЗЕЛЁНАЯ · экран целевого языка (стр.46) — ДИЗАЙН ПОДАН, КОДА НЕТ · холодный прогон (стр.16) НЕ НАЧАТ и закрыт владельцем как неуспешный на этом этапе (02.08, бэкенд-сессия по `BACKEND_EFFORT_HANDLE_SESSION_PROMPT`, D39.87; $0.045095 из $0.10; прогон C — $0; НЕ закоммичено).** Отчёт: [archive/reports/EFFORT_HANDLE_2026-08-02.md](archive/reports/EFFORT_HANDLE_2026-08-02.md). **Работа A — не три патча, а ДВА ШВА:** `config.InternalCall{…}.Stage()` (новый `internal/config/internal_call.go`) — единственная деривация стадии для внутренних вызовов движка, и `Runner.attemptRequest` (`stagerun.go:406`) — единственная сборка кортежа идентичности запроса. Рукописных `config.Stage{}` в движке НЕ ОСТАЛОСЬ НИ ОДНОГО (все 4 места + live-риг через шов); все 4 сборки `RequestHash(Request{…})` схлопнулись в одну. Приёмочный вопрос «появится ПЯТАЯ стадия — унаследует или забудут?» отвечен **механикой, не обещанием**: три гарда (единственность обоих швов + рефлексия по полям `Stage`, падающая на НОВОМ поле), каждый проверен исполнением. **Ловушка хеш-оси закрыта в ОБЕ стороны и на ОБОИХ путях** (`bankCheckpointExists`, `repairCheckpointExists`): ложно-false режет резюм бюджетным пред-чеком, ложно-true обходит ролевой суб-бюджет и покупает свежий вызов под одним лишь книжным потолком. **Гранулярность решена ЗАМЕРОМ, а не заранее:** одна ручка `gates.terminology.reasoning` на обе бэнк-роли — парная выборка N=5 через боевой путь дала `low` 4/5 против `high` 5/5 (неразличимо) при цене `high` ×2.30 ⇒ вторая ручка `classify_reasoning` была построена на n=1 и СНЯТА самой сессией, когда выборка её не подтвердила. `Temperature` зафиксирована нулём осознанно (ответ ролей — разбираемая структура, не проза). **Repair получил СВОЙ ключ `gates.repair.reasoning`, наследование от чинимой стадии СНЯТО** (правка против промта и D39.87, с аргументом): `reasoning: "off"` стоит на финальной стадии у ВСЕХ шиппинг-пайплайнов ⇒ наследование двигало хеш и перекупало все оплаченные repair-вызовы; и семантически «off» — значение, чей смысл зависит от control МОДЕЛИ, а `gates.repair.model` независим от стадийного (задокументированный no-op DeepSeek стал бы живым `thinking:{type:disabled}` на glm). **§3.4 (проба банка, свой проект `reprobe/bank-low/`, эталон coldrun-a только на чтение):** терминолог **4/5 батчей `stop`, consolidated=72, unanswered=18, bad_lines=0, off_language=0** (против 1/5 и 1 терма из 81 при вендор-дефолте `high`), классификатор 5/5 `stop`, reclassified=14, черновая волна **20/20 чанков ok**. **Оба молчащих пути ИСКЛЮЧЕНЫ предъявлением, а не словами:** терминолог $0.005750 из $0.05 (11.5%), классификатор $0.004286 из $0.02, книга $0.045095 из $0.10 — и НОЛЬ строк `budget would be exceeded`/`denied by a USD ceiling` в логе. **Провод вскрыт:** 35 тел, ключи `[max_tokens, messages, model, reasoning_effort, stream, temperature]`, `reasoning_effort:"low"` во всех 35, ключей `thinking` **0**, `reasoning_content` непустой везде ⇒ гардрейл доказан проводом. Упавший батч вскрыт сырьём (`content:""`, `reasoning_tokens=7999`) — **`low` стену не убирает, а разрежает** с 4/5 до 1/5, и упавший батч не самый большой по входу ⇒ стохастика вызова (квирки п.6). Деньги двумя путями: леджер $0.045095 ≡ независимый пересчёт $0.045095, дельта $0.000000, строк `decode_error` 0. **Работа B — вердикт-двигающая ⇒ дизайн и пинг ДО кода, решения владельца нет ⇒ кода нет (легитимный исход по букве промта).** Живая улика ДОБЫТА В ЭТОМ ЗАХОДЕ: гл.8/чанк 1 — полный связный черновик НА АНГЛИЙСКОМ, `finish=stop`, `disposition=ok`, хеш `fb51e135a395` стоит в `final_hash`. ⚠ **ДВЕ ПОПРАВКИ К СОБСТВЕННЫМ ЧИСЛАМ СЕССИИ, обе пере-проверены её же кодом:** (i) подавалось «здоровый русский 0.9510, n=1306» — это СЫРОЙ текст чекпойнта, а движок классифицирует ПОСЛЕ среза банкноты (`stagerun.go:632` режет, `:636` классифицирует; срез безусловен, `banknote.go:320`); на тексте, который видит гейт, **минимум 0.9767 при n=1055** (1306 двоил бэкап-копии БД); (ii) **боевой гейт уже ловит 18 из 20 off-target событий при 0 ложных из 1055 и запасе 13×** (худший здоровый source-share 0.0117 против порога 0.15) — этого не мерил никто, включая прошлые сессии. Остаточная дыра — **ровно 2 английских чанка = 0.18% выходов**; японский черновик (`exp15/anchors/oracle_30.db`) ловится по общей с китайским письменности (доля ханьцзы 0.332). Носитель экрана — `lang.LangScripts(Book.TargetLang)`, БЕЗ нового файла в `go:embed` (`EmbeddedVersion` фолдится безусловно ⇒ новый эмбед перекупает все книги всех пар); `gates.terminology.target_script` отвергнут причиной сильнее промтовой — он ДУБЛИРУЕТ то, что данные уже знают. **Работа C НЕ НАЧАТА:** стенд coldrun-b стоит нетронутым, черновик по-прежнему на `reasoning: "off"`; строка 16 не закрыта, строка 13б снова без данных (редакторская волна не гонялась ни разу). **ПОЧИНЕНО с тестами (9):** шов+гарды · обе хеш-пары · **`ThinksOnWire` врал про ПУСТОЙ эффорт на `extra_body_disable`** (возвращал «думает», а `applyToBody` в этом же случае мержит disable ⇒ бэнк-роль на glm уезжала в thinking-off МОЛЧА; предсуществующая дыра, но пак первым на предикат оперся) · `sourceEchoExposure` расширен на внутренние вызовы · fail-open неизвестной роли · дубль `plan.model` · дефолт рига N=1→5. **АДВЕРСАРИАЛЬНОЕ РЕВЬЮ (author≠reviewer) НАШЛО 10 ДЕФЕКТОВ В МОИХ ЖЕ ПРАВКАХ**, из них 1 blocker и 3 major; топ-2 пере-проверены сессией по коду до принятия. Отдельным ресерчем вскрыто, что **первая версия гардов пробивалась 7 способами** (5 байтовых + алиас импорта `cfg "…/internal/config"` + `[]config.Stage{{…}}` с опущенным типом элемента) — причина: сравнивалось ИМЯ пакета вместо ПУТИ импорта; переписано на AST с резолвом пути, разворотом `[]T`/`map[K]T`/`*T`, исключениями полными путями и полом на число разобранных файлов (обход, не распарсивший ничего, выглядел как чистое дерево); все 7 посадок пере-проверены на живом дереве. **НАЙДЕНО и НЕ ПОЧИНЕНО (с носителями):** Д2 `detectLatinInsertion` не обусловлен `TargetScriptNonLatin()` ⇒ первая латинописьменная цель дропнет 100% чанков (одним диффом с работой B) · Д3 `SourceEchoExpected` не покрывает `roleClassifier` ⇒ **16/16 вызовов классификатора логируются `ok=0 degraded=cjk_artifact`** (данные не теряются — `reclassified=14` доказывает, но отравлен ровно тот сигнал, который говорит «провайдер плохеет») · Д4 **`gates.terminology.target_script` не сверяется с `book.target_lang`**: `target_lang: ru` + `target_script: Latin` грузится чисто и ИНВЕРТИРУЕТ банковский экран · Д5 наш enum эффорта провайдер-слеп (`medium` на DeepSeek не определён, `max`/`xhigh` недостижимы) — пер-модельная таблица = новый механизм, сознательный отказ · Д6 **`//go:embed` в `internal/lang/embedded.go:22` — ЯВНЫЙ список файлов**, новая цель требует правки Go, а `CompileCheckers` паникует при неполном файле цели ⇒ на ревью-вопрос «заработает ли пара, которой нет в репо» ответ сегодня НЕТ, и это не про язык, а про строку эмбеда · Д7 два гарда шва разной формы (мой AST против давнего байтового `TestProviderEgressSeamIsSingle`) — свести в один обход · Д8 ратифицированный порог классификатора «6/6» определён для ОДНОГО вызова, не для выборки, и на рекомендованном `low` риг красный (заявлено в тексте падения, не смягчено) · Д9 аддитивные провайдеры отказываются бэнк/repair-гейтам именно потому, что блок не несёт `reasoning_max_tokens` — новая ручка эту дыру НЕ закрывает. **РЕСЕРЧ-ЗАДЕЛ (два холодных исследования со скептиками, §5 отчёта — оставлен, чтобы следующие сессии шли по шагам):** у отказа есть имя и метрика (*off-target translation*, Zhang et al. ACL 2020; *language confusion* LPR/WPR, Marchisio et al. EMNLP 2024), рецепт поля — ровно наш, более умного serving-time метода не упущено; английский — доминирующий аттрактор (подтверждено дважды независимо и нашими 2/20); четыре режима отказа требуют РАЗНЫХ детекторов, гнать всё через один LID — ошибка проектирования. **Обещанной гарантии FPR ≤ 0.1% на этом корпусе НЕ КУПИТЬ:** правило трёх при n_eff=114 позиций даёт ≤2.594% (в 26× слабее), процедура двоит данные, а на сиблингах мощность ≈0.1% (болгарский алфавит — собственное подмножество русского, распределения совпадают) ⇒ ставить руками консервативную константу в широком пустом интервале и версионировать как контракт. **НЕ СТРОИТЬ (проверено запуском, не по README):** ни одну статистическую LID-библиотеку в путь вердикта (`lingua-go` недетерминистична 6/23 на 20k повторов + 126 МиБ эмбеда + 10–12 мс/чанк; `langid-go` даёт P(ru)<0.5 на **22.2%** реальных русских сегментов 20–40 рун и FMA-зависим от GOARCH; `whatlanggo` принимает 4–6 из 9 русских образцов за болгарский; `gocld3`/fastText — CGo, вердикт становится функцией тулчейна ВНЕ снапшот-хеша) · посегментный worst-of (умножает FPR на число сегментов и имеет НОЛЬ положительных примеров) · замыкание алфавита · функционально-словный экран · новый файл в `go:embed`. **План на 8 шагов** с единственным необратимым (бамп `classifierVersion`) последним; ключевой перенос — **`cultivation` чинить в СИДЕ, а не порогом** (86 из 1055 здоровых выходов содержат его; все 32 просевших абзаца содержат, ни один не содержит ханьцзы; правка пар-данных двигает `LangpackVersion`, который фолдится с `omitempty` ⇒ перекупка ограничена книгами ЭТОЙ пары — самый переносимый вывод цепочки: чинить на том плане, где перекупка уже). ⚠ **Качество прозы не судил никто ни в одной пробе.** Батарея после всех правок зелёная (build/vet/`vet -tags live`/`-race -count=1`/gofmt чисты · голден PASS · парити EXACT · labels-фриз 5/5). **СТОП — приёмка оркестратора.** + **coldrun-b: фаза A ✅, фаза B ✅ — БЛОКЕР СТРОКИ 74 ВОСПРОИЗВЕДЁН НА БОЕВОЙ ФОРМЕ, фаза C ЗАМОРОЖЕНА развилкой владельца (02.08, бэкенд-сессия по `BACKEND_COLDRUN_DEBUG_SESSION_PROMPT`, D39.83; фаза B $0.114378 из $0.15; НЕ закоммичено).** Отчёт: [archive/reports/COLDRUN_B_DEBUG_2026-08-02.md](archive/reports/COLDRUN_B_DEBUG_2026-08-02.md). **Фаза A:** батарея воспроизведена числами (парити EXACT · labels 5/5 фрозен · голден PASS · `-race -count=1` зелёный); сквозняк = голден-тест; CLI-читаемость проверена read-only на БОЕВОЙ БД coldrun-a (sha256 БД до/после идентичен) — сильнее локальной модели; **2 дыры наблюдаемости починены $0** (счётчики банкноты и голос-флаггера считались, но не имели НИ ОДНОЙ поверхности вывода → строки `BANKNOTE`/`VOICE` в `report` + 5 тестов, включая тесты молчания и различение «не измерено»↔«измерено, чисто»; голден/`CheapGateVersion` не тронуты; новая строка независимо воспроизвела руками добытые числа coldrun-a 182/18-из-20/parse-fail 3). Стенд `coldrun-b` собран (пустой сид, `ceilings` 5.00/5.00, `pipeline.yaml` побайтно = эталону), ключи $0-проверены. **Фаза B (носитель — САМ боевой путь `tmctl translate --verify-bank` на отдельных проектах с потолком, принуждаемым движком; девиация от «расширить live-риг» аргументирована §2 отчёта):** при боевом `max_tokens=8496` (флор 8000 + `bankTokenBudget` 496) **0 из 9 вызовов пригодны** (8 `empty`, 1 `length`); **вариант (а) флор-16000 ФАЛЬСИФИЦИРОВАН** — 4/5 пустых при 16992, сырьё показывает 15–21 тыс. симв. `reasoning_content` (модель переводит главу ВНУТРИ размышления и не доходит до ответа), удвоение потолка добавляет ~2 тыс. симв. думания и не сходится. **Вендор-сверка сделана ДО диагноза:** changelog без записей после 31.07; `guides/thinking_mode` — **«default effort being `high`»** и маппинг flash `low→low` ⇒ запись квирков 04.07 («low/medium→high») УСТАРЕЛА (правка `00-provider-quirks.md` — оркестратору, зона). **Вариант (б) `reasoning_effort:"low"` РАБОТАЕТ и достижим ПРАВКОЙ ОДНОЙ СТРОКИ ран-конфига — амендмент `echoMineViolation` НЕ НУЖЕН** (посылка строки 74 неверна: гейт инспектирует МЕХАНИЗМ `control`, у deepseek `ReasoningNone`, где `low` уходит на провод, а `off`/`""` — no-op; thinking не выключается, вендорский тумблер — другой параметр; проверено исполнением): **18 из 20 чанков отгружено, 20 из 22 свежих вызовов `finish=stop`**, волна ≈$0.0257 против $0.02474 у coldrun-a, латентность 9–44 с. **Цена (б) названа честно:** эхо 3/20 (15% против 10% у coldrun-a; на таких N неразличимо) · **1 черновик из 18 пришёл ЦЕЛИКОМ НА АНГЛИЙСКОМ и прошёл гейт как `ok`** · **терминолог (б) НЕ лечит** — 4/5 батчей `length` с `completion=8000` ровно (на coldrun-a до смены весов было 21/21 `stop`), банк консолидировал 1 терм из 81, корень: бэнк-роли строят `config.Stage` без `Reasoning` (`terminologist.go:515,568`) и у `gates.terminology` ключа нет ⇒ они ВСЕГДА едут вендор-дефолтом `high`, что бы владелец ни выбрал для черновой стадии. **Порог классификатора 6/6 ВЗЯТ** ($0.000390, `finish=stop`; честная оговорка — 元石/灵泉 стоят дословно в `classifier.md`, дискриминирующее подмножество 4/4). **Попутно доказано живыми деньгами:** нарезка · волна на 4 воркерах · classify (поймал 3/3 эха и все `length`/`empty`) · эскалация одним хопом с ре-гейтом · банкнота (129 строк на 14/20 чанков) · майнер+банк (76 кандидатов, 100% dst в кириллице, 0 утечек письма) · банк-пауза exit 3 + сайдкары · **деньги `committed ≡ Σ checkpoints` двумя путями** (независимый пересчёт провайдерского usage по вендор-ценам сошёлся до 6-го знака на optB; расхождение $0.015110 на первой пробе = **строка 78 в живом виде**, 3 билленных 2xx с нечитаемым телом) · потолок физически выстрелил на 98.7% и отказал в хопах · F4-бэкап на каждом платном старте (первый боевой клиент) · graceful SIGINT посреди волны · **$0-резюм** (20 юнитов из `chunk_status` + 5 чекпойнтов, 0 вызовов, леджер байт-в-байт). **Найдено и НЕ починено (вердикт-двигающее → СТОП+пинг):** Д1 гейт черновой стадии не ловит выход на ТРЕТЬЕМ языке (последний рубеж есть — санитайзер даёт `Latin insertion`, но стоит только на ФИНАЛЬНОЙ стадии ⇒ не тихая порча, а потеря юнита + оплаченный впустую редактор; живой носитель к строке 46) · Д2 у бэнк-ролей нет ручки reasoning (шов назван, форма предложена, строить — после выбора владельца) · Д4 роль `classifier` мис-вердиктится как `cjk_artifact` (поблажка `SourceEchoExpected` дана только терминологу; ущерб телеметрийный — текст парсится, но каждый батч светится `ok=0`; латентно, `classify_types` выключен). **Починено:** обе дыры наблюдаемости + **live-риг не собирался с D39.64** (`undefined: cjkShare` после переезда на `sourceScriptShare` ⇒ per-adapter live conformance физически не запускался). **Проба C — thinking ВЫКЛЮЧЕН (по вопросу владельца «а выключить ризонинг нельзя?»; пере-замер клейма `echoes_when_thinking_off` на весах 0731, потому что вся эмпирика по нему снята на несуществующих весах Preview; пробная копия models.yaml ВНЕ git, боевой файл и гейт не тронуты):** выключатель в OpenAI-транспорте ЕСТЬ и документирован вендором (`extra_body {"thinking":{"type":"disabled"}}`; `reasoning_effort:"none"` в OpenAI-формате НЕ существует — `none` живёт только в Responses-API-колонке). Результат на тех же 20 чанках: **0 пустых из 22 вызовов · терминолог 5/5 `stop` (единственная конфигурация, где стадия банка жива БЕЗ правки Go) · выход не на целевом языке 0/18 · весь заход $0.014932 — в 2.6× дешевле (б)**; НО **эхо-мина ЖИВА на 0731: 4/20**, гейт поймал 4 из 4, эскалация вылечила 2 по $0.0024, ещё 2 не вылечены только пробным потолком $0.03 (`escalation hop denied by a USD ceiling` — деградация, не падение). ⚠ Качество прозы не судилось НИ В ОДНОЙ из трёх проб — канон D19.1/D21.9 стоит не только на эхе, поэтому C = ИЗМЕРЕННАЯ опция, не рекомендация: её принятие = разворот ратифицированного гардрейла и требует читки качества. **Развилка владельцу:** (а) фальсифицирована · (б) работает, но требует Д2 (правка Go) и делает Д1 условием безопасности · (в) вендор молчит · **(г) сменить модель черновика на `deepseek-v4-pro`** (вендором не тронут обновлением 0731; один хоп на боевом рендере отработал `stop` за $0.008706) — **0 правок Go и гейта, ценой ~×3.1 COGS черновика; не замерен волной, замер ~$0.03**. Ручка #77 не включалась. Батарея после всех правок зелёная. **СТОП — решение владельца по строке 74, затем приёмка оркестратора.** — **ЛЕНД D39.86** (приёмка оркестратора №10: батарея и все несущие счётчики пере-выведены независимо, деньги — из сырья двумя путями [$0.114378 леджер ≡ Σ чекпойнтов во всех 4 проектах · $0.099267 независимый пересчёт · $0.015111 неизвестности]; 9-осевой refute-воркфлоу со скептиком и арбитром на каждую ось — 6 CONFIRMED / 2 PARTIALLY / 0 REFUTED. Поправки в ревю-шапке отчёта: §3.3 верно только для СТАДИЙНОЙ ручки [для бэнк-ролей посылка об амендменте жива ⇒ (б) = правка Go] · §3.1 «нет пути вообще» слишком сильно, НО «бюджет не лечит» усилено [победивший вызов уложился НИЖЕ базового потолка ⇒ лечит стохастика] · волна (б) = $0.028195, не $0.0257 · (г) ≈×8.9, не ×3.1 · Д1 недооценён и дыра цели ДВУСТОРОННЯЯ · Д2 назван на 2/3 [третий шов `repair.go:384`] · строка VOICE говорит «сконфигурирован», не «отработал». Новые вендор-факты: дефолт эффорта `high`, у pro `low→high` и объявленная смена маппинга — в quirks п.3а/п.10. Новые строки 104/105; 46 повышена; 44 сужена; 78 и 13б уточнены; 16 НЕ закрыта). **Мелкая пачка хвостов (строки 93·89·53·83 + решения D39.79) исполнена (02.08, бэкенд-сессия по `BACKEND_SMALLPACK_TAILS_SESSION_PROMPT`, D39.79, $0 — только фейк-провайдер в тестах, НЕ закоммичено; D-номер лендинга проставит оркестратор).** Отчёт: [archive/reports/SMALLPACK_TAILS_2026-08-02.md](archive/reports/SMALLPACK_TAILS_2026-08-02.md). **A (стр.93):** 8 хвостов — whole-word inner-marker вето `isSpokenChevronLine`+гвоздь · recall-потолок `speechAttribution` в контракт · негатив-ассерт `Demoted=false` (мутант убит) · stale `LatinResidueCount` коммент · CAND k4_inverse → боевое правило + REJECTED-контраст · «..»/thin-space комменты↔код · честная кана-оговорка · target-алиас NB. **B (стр.89):** ведро D — `isHeaderSeparator`→`!isHeaderContentRune` (консолидация), мёртвый `freqStratum` удалён, `minerPackVersion`/⟨проверить⟩-глиф честные комменты (парити EXACT); ведро B (6) сверено на носители (строки 35/81), бездомных нет → пинга нет. **C (стр.53):** gofmt чист (4 файла) · `editor-mono.md` DORMANT-маркер (`` strip'ается, hash-нейтрален, боевого SHA не двигает) · внутрифайловый дубль-ключ `parseDCCheckers` → fail-loud (`putUniqueDC`+тест; register_neg-список терпим) · D39.4/D23.4/D28.3(б) архео (парк/moot/уже-сделано). **D (стр.83, F4):** `tmctl backup` верб + боевой pre-flight (integrity_check + `VACUUM INTO ~/books/<книга>/backups/`); дискриминатор боевого пути = размещение в `run()`-диспетчере (тесты зовут `translate()`/Runner напрямую) — **ноль магических строк провайдеров в Go**; гвоздь «фейк-путь бэкапов не создаёт». **E (D39.79):** Q1 — канон «класс X» подтверждён (0 «разряд» в живом носителе → пинга нет); DC7-замер = **25 юнитов/93 девиации «разряд»≠канон → построй, НО** двойной стоп (книго-канон-дом vs пар-пак + >50 строк) → **СТОП+ПИНГ с дизайном, DC7 не построен** (грейд-канон = book.yaml, оркестратору). Q2 — 兩 в `shichen_re` (probe-литералы/cheng_re не тронуты) + NB-граница. Q4 — `register_neg`+жанр-msg → книжный слой (`book.yaml register_blocklist`→`CheapGateConfig`→DC6-union; `omitempty` в BriefHash → **golden brief_hash `c2021b1b…` неизменен**; пар-`register_neg`/`dc6_register` опциональны; терем-список → coldrun-a+example book.yaml; DC6-семантика та же; «вторая книга другого жанра — 0 ложных DC6, 0 правок Go» = ДА). **Приёмка:** build/vet/`-race ./...` зелёные · майнер-парити EXACT · **голден НЕ двинулся** (`CheapGateVersion` не бампнут) · labels-фрозен (k4b 10/1/36/99·k4_inverse 3/0/1/71·k2 34/1/6/51·K6 1/6/0/251·k4a 0/0/0/348, `assertBaseline` хард) · gofmt чист · греп-общность чист. **Плюс адверсариальный author≠reviewer (6-агентный refute-воркфлоу по своим правкам): 0 блокеров, 0 major; 2 CONFIRMED low-sev (диагностика/коммент) исправлены ДО отчёта** (source-neutral DC6-detail; `isTargetWordLetter`-атрибуция коммента), пост-фикс перепрогон зелёный. **СТОП — приёмка оркестратора.** — **ЛЕНД D39.82** (батарея пере-прогнана оркестратором независимо, все числа совпали; 5-осевой refute-воркфлоу: 0 блокеров/0 major против пакета — omitempty доказан пере-выводом hash, комплементарность рун — полным перебором; DC7-стоп ПОДТВЕРЖДЁН, но рекомендация пере-гейчена сид-покрытием mempostcheck → строка 98; F4-хвост dry-run-redrive → строка 93; строки 89/53/83 закрыты). diff --git a/docs/architecture/05-decisions-log.md b/docs/architecture/05-decisions-log.md index a714f210..8fc717a7 100644 --- a/docs/architecture/05-decisions-log.md +++ b/docs/architecture/05-decisions-log.md @@ -1,4 +1,4 @@ -# Журнал решений оркестратора — контракт D1–D39.89 (развязки 04.07 · пакеты 09–10.07 · приёмка/качество-первым/пивот/эмпирика 11–12.07 · арх-ресет+стройка пере-прогонного стека 13–19.07) +# Журнал решений оркестратора — контракт D1–D39.90 (развязки 04.07 · пакеты 09–10.07 · приёмка/качество-первым/пивот/эмпирика 11–12.07 · арх-ресет+стройка пере-прогонного стека 13–19.07) > **⟶ КАРТА АКТУАЛЬНОСТИ (ревизия D31, продлена до D38.2 [12.07]; исторические записи ниже НЕ переписываются — дисциплина D23.3).** Читая контракт целиком, держи под рукой, что чем перекрыто: > ⚠ **Навигация (актуализация 01.08):** карта ниже детально покрывает D1–D39.28; решения D39.29+ живут хронологически в теле файла, **свежая голова — С ХВОСТА** (новые ноты аппендятся вниз). Сводка текущей головы и очередь — CURRENT-STATE в `../PROGRESS.md`. @@ -1303,3 +1303,23 @@ API-529-долг закрыт: 8-осевой refute-by-default воркфлоу **Промт выдан — `docs/BANK_ARBITRATION_RESEARCH_SESSION_PROMPT.md`** (ресёрч+полигон сессия; зона: `docs/research/24-bank-arbitration.md` + `eval/bank_arbitration/` + секция PROGRESS; НЕ коммитит). Четыре работы: **A** критика текущего алгоритма в коде ($0, вердикт-тройки, дефекты классами сломано/хрупко/дорого/слепо) · **B** арбитраж (B1 голд — гейт остального; ядро уже есть: `guzhenren-seed-v2.yaml` 58 записей / 53 `approved` + дистилл-фикстура BANK-FULL 150 поверхностей + банк coldrun-a, смещение выборки назвать честно; B2 калибровка уверенности ≤$0.60 — разделяющая способность, числа против слов, устойчивость к повтору, **сравнимость МЕЖДУ моделями**, канал отказа, и обязательный БАР против бесплатного базиса §C2-3; B3 формы консилиума ≤$0.80 с контролем «одна модель N раз» — ответ на Q2) · **C** инжект/фетч ≤$0.60 (мерить ПОСЛУШАНИЕ и ВРЕД, не recall) · **D** рекомендованные алгоритмы тремя корзинами (строить сейчас · измерить · закрыть по нужности; последняя обязана быть непустой). Потолок **$2.00** с суб-потолками и пре-регистрацией критерия до каждой пробы. **Легитимные исходы, объявленные заранее:** «консилиум не бьёт базис — закрыть» · «уверенность не разделяет — закрыть» · «голда мало, вот точный запрос владельцу» · «рычаг в инжекте, а не в арбитраже». Мандат ревизии посылок (D39.68) и правило №4 (D39.47) вшиты. **Гигиена выдачи:** промт холодно аудирован автором перед выдачей по `file:line`/D-номерам; исправлена одна мис-атрибуция (фактура премеров — **D39.50**, отчёт `archive/reports/POLYGON_PREMEASURE_2026-07-26.md`, а не D39.71). ⚠ **Коллизия зон названа в промте:** `backend/` ЖИВАЯ (сессия строк 104/46/16), `coldrun-a` — замороженный эталон только на чтение, `coldrun-b` — стенд живой сессии; пробы гонять СВОИМ харнессом против API, не через движок. Валидный базлайн качества банка — **coldrun-a**, НЕ coldrun-b (там терминолог сломан транспортом: 1 терм из 81, D39.86) — сравнение с поломкой даст фальшивую победу консилиума и будет отклонено приёмкой. + +## D39.90 — ЗАКРЫТИЕ СЕССИИ ОРКЕСТРАТОРА №10: пак ручки эффорта отработан и ЖДЁТ ПРИЁМКИ преемника, банк-ресёрч подрезан, дыры трекера заведены строками, форма архитектурных гардов и конвенции Go-репо подняты владельцем в решение (02.08). ✅ + +**Повод — слово владельца: «эту сессию мы завершаем, дела передаёшь; главное важную инфу не потерять».** Нота собирает состояние на момент передачи; вода и хроника опущены намеренно. + +**1. Бэкенд-пак строк 104/46/16 ОТРАБОТАН, НЕ ПРИНЯТ, НЕ ЗАЛЕНДЕН.** Отчёт `archive/reports/EFFORT_HANDLE_2026-08-02.md` закоммичен с ⚠-баннером «коммит ≠ ратификация» — только чтобы артефакт пережил смену сессий. **Код лежит в дереве НЕЗАКОММИЧЕННЫМ** (новые `internal/config/internal_call.go`, `internal_call_test.go`, `pipeline/synthetic_stage_seam_test.go`; правлены `models.go`/`pipeline.go`/`capability.go`/`escalation.go`/`repair.go`/`runner.go`/`stagerun.go`/`terminologist.go`/`live_reprobe_test.go`/`capability_test.go`) — **дерево не чистить, history-rewrite и `checkout` поверх него запрещены.** Заявления сессии, которые приёмка обязана пере-проверить исполнением: работа A = ДВА шва (`config.InternalCall{…}.Stage()` + `Runner.attemptRequest`), рукописных `config.Stage{}` не осталось ни одного, все четыре сборки `RequestHash(Request{…})` схлопнуты в одну, ловушка хеш-оси закрыта в обе стороны на обоих путях; **перекупки нет** (`gates.terminology` не фолдится в снапшот, кортеж воспроизведён побайтно — `8e4495006b978ed4` в обе стороны, голден PASS без пере-захвата); гранулярность решена ЗАМЕРОМ (парная выборка N=5: `low` 4/5 против `high` 5/5 неразличимо при цене `high` ×2.30 ⇒ вторая ручка `classify_reasoning`, построенная на n=1, СНЯТА самой сессией); `Temperature` зафиксирована нулём осознанно. + +**2. Проба банка на `low` ЗЕЛЁНАЯ и это главный технический результат дня** (строка 104, §3.4 промта; хост — свой проект `reprobe/bank-low/`, эталон `coldrun-a` только на чтение): терминолог **4/5 батчей `stop`, consolidated 72, unanswered 18, $0.005750**; классификатор 5/5, reclassified 14, $0.004286; черновая волна 20/20 ok ($0.031639 flash + $0.010350 pro, 2 эскалации вылечили эхо); **весь заход $0.045095 из $0.10, леджер ≡ независимому пересчёту `usage`×цены до нуля** (строки 78 в этом заходе не было). Против вендор-дефолта `high` — 1/5 батчей и 1 терм из 81. **Оба молчащих пути исключены предъявлением** (терминолог 11.5% суб-бюджета, классификатор 21.4%, книга 45.1%, ноль WARN-строк). **Провод вскрыт: 35 тел, `reasoning_effort:"low"` во всех 35, ключей `thinking` ноль, `reasoning_content` непустой везде ⇒ гардрейл «thinking у DeepSeek не выключать» доказан ПРОВОДОМ, а не рассуждением.** ⚠ Несущий нюанс для будущего: `low` стену НЕ убирает, а разрежает — упавший батч вскрыт сырьём (`content=""`, `finish=length`, `completion=7999`, `reasoning=7999`), то есть тот же тяжёлый хвост, 1/5 вместо 4/5, и это стохастика вызова, а не размер входа. ⚠ На стенде пробы `escalation.budget_usd` сознательно понижен 0.10→0.015 ⇒ наблюдение эскалаций НЕПОЛНОЕ. ⚠ Боевой `coldrun-b/pipeline.yaml` НЕ тронут — там по-прежнему no-op `reasoning: "off"` на черновике. + +**3. Работа B (строка 46) — ДИЗАЙН ПОДАН, КОДА НЕТ, стоит на решении владельца.** Сессия исполнила букву промта («вердикт-двигающее ⇒ сначала дизайн и пинг»). Три поправки к посылке, все замером, и они МЕНЯЮТ масштаб проблемы: **боевой гейт уже ловит 18 из 20** off-target событий (`sourceScriptShare > 0.15`, 0 ложных на 1055 здоровых, запас 13×) ⇒ остаточная дыра **0.18%** (2 чанка из ~1100, оба английские; японский ловится долей ханьцзы); **второй рубеж существует, но стоит не там** — санитайзер поймал бы те байты, однако `chunkrun.go:52` требует `isFinal`, а в шиппинговой двухстадийной топологии черновик НИКОГДА не финальный, и тот же `isFinal` глушит на черновике латинный линт, флаггер голоса и глоссарный пост-чек; здоровый минимум на тексте, который РЕАЛЬНО видит гейт (после среза банкноты), = 0.9767 при n=1055, а не 0.9510 при 1306 (сессия поправила собственное число). **Развилка владельцу: (а)** предикат в `classify()` + бамп `classifierVersion` — двигает снапшот у всех книг, голден пере-захват один раз, на свежем стенде $0; **(б)** отдельный опциональный гейт — снапшот не двигает, но это второй способ сказать то же самое и он выключен по умолчанию; **(в)** языковой детектор. Выбор сессии — **(а)**. Носитель — `lang.LangScripts(Book.TargetLang)`, НОВЫЙ go:embed-файл не заводить (`EmbeddedVersion` фолдится безусловно = перекупка всех книг всех пар). Три мины наивной реализации названы (новый флаг провалился бы мимо `escalatable()`/`retryable()` ⇒ переиспользовать `FlagCJKArtifact`; классификатор флагался бы ложно 16/16; экран слеп к ПОДМНОЖЕСТВАМ письменности — чисто китайский выход для →ja наберёт 1.000). + +**4. Работа C (строка 16) НЕ НАЧАТА, закрыта владельцем как неуспешная на этом этапе; деньги фазы C не тронуты.** Редакторская волна по-прежнему не гонялась НИ РАЗУ ⇒ оси голоса (13б/24) без данных, полная цена холодного старта невыведена. + +**5. Банк-ресёрч (строка 5): заход запущен и ДОСРОЧНО ЗАКРЫТ владельцем — «требуются фиксы в бэкенд». Артефакта в дереве НЕТ** (ни `docs/research/24-*`, ни `eval/bank_arbitration/`, ни свежих файлов в `~/books` — проверено) ⇒ **находки не сохранены; если они ценны, их надо вынуть из истории той сессии, иначе работа повторяется с нуля.** Диспозиция пере-запуска — ПОДРЕЗАТЬ: держать §3-A (критика кода, $0 — она и вскрывает нужные бэкенд-фиксы), B1 голд (гейт всего) и B3 формы консилиума с контролем «одна модель N раз»; свернуть B2 (калибровка уверенности) до под-пробы внутри B3 — как отдельная работа она дорога, а приоры D39.46 (судья = катастроф-экран, не ранжировщик) и D39.50 (канал отказа нестабилен, размах 0.375) уже сильно против неё; отложить §5-C (инжект/фетч) до бэкенд-доработок — мерить послушание инъекции без движка нечем. Потолок $2.00 → $1.20. **Да, после ресёрча последуют бэкенд-работы** — их предмет и есть деливерабл §3-A и §6-D промта. + +**6. Дыры трекера закрыты строками (сверка по репозиторию, не по памяти).** Заведены: **106** слой 3 — контракт редактора остаётся full-regen при целевом diff-контракте (`09:121-126`), строки не было вовсе · **107** конвенции Go-репо (см. п.7) · **108** реестр загейченных триггеров — шесть реопенов жили только в телах D-нот, и триггер «появление Go-кода платформы» УЖЕ наступил (`platform/go.mod` заведён) · **109** требования без носителя (ПТ-6 · ПТ-7 · ПТ-22-интейк · ПТ-10-механизм) + гигиена перекрёстных ссылок реестра · **110** детектор повторов лемм / защита авторских рефренов · **111** `parseCategoryRows` молча last-wins (фикс дубль-ключа накрыл только `parseDCCheckers`). **Снято расхождение трекера:** строка 74 объявляла строку 44 закрытой — верно лишь для половины «поднять флор»; живой остаток обратный (число флора влияет на цену ретрая, не на проходимость). Уточнён гейт строки 93 (`分之`-часть гейчена полигон-разметкой, F4-хвост свободен). **Четыре пункта, поданные черновиком свода как долг, СНЯТЫ как уже закрытые решениями:** резолвер слоя 7 построен (`chunkrun.go:30-35`, D39.2 T3) · «санитайзер = чистый детектор» исполнен (D39.2 T2; остаточная мутация `StripCosmetic` — сама ратифицированная диспозиция D38.3 п.2а) · 36б — не бэкенд-стройка, а замер (D39.69) · полярность/ранг отменены D38.4, строка 2 и есть их загейченный носитель. + +**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).** diff --git a/docs/archive/reports/EFFORT_HANDLE_2026-08-02.md b/docs/archive/reports/EFFORT_HANDLE_2026-08-02.md new file mode 100644 index 00000000..29df8d70 --- /dev/null +++ b/docs/archive/reports/EFFORT_HANDLE_2026-08-02.md @@ -0,0 +1,435 @@ +# Отчёт бэкенд-сессии: ручка эффорта · экран целевого языка · холодный прогон (строки 104 · 46 · 16) + +> ⚠⚠ **ОТЧЁТ НЕ ПРИНЯТ. Коммит этого файла ≠ ратификация (оркестратор №10, 02.08, D39.90).** Файл закоммичен ТОЛЬКО чтобы артефакт не потерялся при смене сессий — приёмки не было: батарея независимо не пере-прогонялась, деньги вторым путём не пере-выводились, адверсариальный проход по правкам не гонялся. **Код сессии лежит в дереве НЕЗАКОММИЧЕННЫМ** (`backend/internal/config/internal_call.go` + `internal_call_test.go` + `pipeline/synthetic_stage_seam_test.go` — новые; `models.go`/`pipeline.go`/`capability.go`/`escalation.go`/`repair.go`/`runner.go`/`stagerun.go`/`terminologist.go`/`live_reprobe_test.go`/`capability_test.go` — правленые). **Дерево НЕ чистить, `reset --hard`/`checkout` поверх него НЕ делать.** Приёмка — задача №1 преемника: пере-прогнать батарею с фрозен-числами, пере-вывести $0.045095 вторым путём из сырья, адверсариально проверить несущие клеймы (два шва · отсутствие перекупки · гарды · парная выборка N=5), затем лендить. До приёмки числа отчёта — заявления сессии, а не ратифицированные факты. + +**Промт:** `docs/BACKEND_EFFORT_HANDLE_SESSION_PROMPT.md` (оркестратор №10, D39.87). +**Дата:** 02.08.2026. **Не коммичено** — лендит оркестратор. + +**ИСХОД ЗАХОДА:** работа A **ЗАКРЫТА**; §3.4 (платная проба банка) **ЗЕЛЁНАЯ**; работа B — **дизайн подан, кода нет**, стоит на решении владельца; работа C **НЕ НАЧАТА** и закрыта владельцем как неуспешная на этом этапе, возвращена оркестратору. Деньги: **$0.045095** из $0.10 (проба §3.4), прогон C — $0. + +--- + +## §0. Эхо-шапка + +1. Скоуп: A — ручка эффорта ролям без неё; B — экран целевого языка; C — добивка холодного прогона. +2. A: один шов деривации синтетической стадии на все 4 места + обе расщеплённые хеш-пары. +3. §3.4: своя проба `reprobe/bank-low/`, потолок $0.10, вердикт «низкий эффорт не ломает банк» — только предъявив, что ни один из двух молчащих путей не сработал. +4. B: вердикт-двигающее ⇒ дизайн и пинг ДО кода. +5. C: только после заморозки A и B. +6. Деньги: A $0 · §3.4 ≤$0.10 · B $0 · C ≤$5 (не потрачено). +7. Вне скоупа: сид · судья · DC7 · `models.yaml` capabilities/price · thinking-off · `optNoThink` · чужие файлы · коммиты. + +--- + +## §1. Работа A — ручка эффорта (строка 104). ЗАКРЫТА + +### 1.1. Форма шва + +**Корень дефекта — не «забыли ключ», а форма кода.** Четыре рукописных `config.Stage{...}` по движку, каждый молча терял поля родителя. Починка четырёх мест копипастой тиражирует дефект на пятое. + +Построено **два шва**: + +| Шов | Файл | Что закрывает | +|---|---|---| +| `config.InternalCall{...}.Stage()` | `internal/config/internal_call.go` (новый) | единственная деривация стадии для внутренних вызовов движка | +| `Runner.attemptRequest(...)` | `internal/pipeline/stagerun.go:406` | единственная сборка кортежа идентичности запроса | + +Рукописных `config.Stage{}` в движке **не осталось ни одного**. Все четыре места (`terminologist.go:515`, `:568`, `repair.go:384`, `live_reprobe_test.go:98`) едут через шов. Все четыре сборки `RequestHash(Request{...})` схлопнулись в одну. + +### 1.2. Деньги правки: перекупки НЕТ. Проверено хешами + +Ключевой вопрос любого шва, трогающего идентичность запроса: не осиротели ли уже оплаченные чекпойнты. + +- **`gates.terminology` НЕ фолдится в снапшот** (в `snapshot.go` ссылки на `Terminology` нет — это осознанное решение, см. доккоммент `config.TerminologyGate`). ⇒ добавление ключа `reasoning` **не двигает `snapshotID` и не пере-биллит ни одной волны**. +- **Кортеж идентичности для всех предсуществующих путей воспроизведён побайтно.** `RequestHash` длина-префиксует `req.Reasoning`, а опущенное поле в композитном литерале И ЕСТЬ `""` ⇒ старая и новая формы совпадают **по построению, а не по везению**. Бэнк-пробник с незаданным ключом даёт `8e4495006b978ed4` в обе стороны; эскалационный хоп — равенство; draft/edit — тот же список полей, перенесённый дословно. +- **Голден НЕ пере-захватывался** и не должен был: `classifierVersion` не бампнут (работа B не начата), `CheapGateVersion`/`SanitizerVersion` не тронуты. `TestGoldenDeterminism` PASS на исходных фикстурах — это и есть доказательство, что вердикты и провод не сдвинулись. +- **Единственное, что двигало бы хеш, — наследование эффорта у repair, и оно снято** (§1.6). + +### 1.3. Ответы на четыре приёмочных вопроса §0 промта + +**(1) Новый механизм или использование существующего?** Существующего. `Stage.Reasoning` было с самого начала, проброс на провод был, капабилити-слой различает провайдеров данными. Добавлен ОДИН конфиг-ключ `gates.terminology.reasoning` и ОДИН `gates.repair.reasoning`; новых механизмов нет. + +**(2) Появится ПЯТАЯ синтетическая стадия — унаследует сама или забудут?** Унаследует, и это **механика, а не обещание** — три гарда: + +| Гард | Что физически не даёт сделать | Проверено исполнением | +|---|---|---| +| `TestSyntheticStageSeamIsSingle` | построить `config.Stage` мимо шва | 6 посадок, все CAUGHT | +| `TestRequestIdentitySeamIsSingle` | пересобрать кортеж идентичности руками | посадка CAUGHT | +| `TestInternalCallDecidesEveryStageField` | добавить в `Stage` поле, не решив, что с ним делают внутренние вызовы | добавил поле → FAIL с именем поля | + +⚠ **Первая версия гардов была дырявой, и это найдено ревью, а не мной.** Байтовый скан пробивался пятью способами; после переписи на AST — ещё двумя (алиас импорта `cfg "…/internal/config"` и `[]config.Stage{{…}}` с опущенным типом элемента). Обе дыры я **перепроверил на живом дереве** — гард говорил `ok`. Причина: сравнивал имя пакета вместо пути импорта. Итоговая версия резолвит путь, разворачивает `[]T`/`map[K]T`/`*T`, исключения полными путями (а не именами файлов, которые расползались на одноимённые файлы по всему репо), и несёт **пол на число разобранных файлов** — обход, не распарсивший ничего, выглядел как чистое дерево. + +**(3) Заработает ли пара, которой нет в репо, без правки Go?** Да. Ключ пар-слепой, валидируется общим `ValidReasoningEffort`, Go не ветвится ни по паре, ни по книге. Вторая книга той же пары — без новых флагов (ключ ран-скоупный, в `book.yaml` и пар-пак не заходит). + +**(4) Не появилось ли второго способа сказать то же самое?** Проверено и вычищено в трёх местах: enum эффорта — один валидатор на стадии и оба гейта; `bankRolePlan.model` снят (был вторым источником правды, читался только логом); идентичность запроса — одна сборка. **Остаточный долг признаю:** в репо теперь два гарда РАЗНОЙ формы — мой на AST и давний `TestProviderEgressSeamIsSingle` на байтовом регэкспе, с другим корнем обхода и своим словарём исключений. Свести в один обход — правильно, но это правка чужого давно живущего теста; вынесено предложением (§6, Д7). + +### 1.4. Гранулярность ручки — решено ЗАМЕРОМ, не заранее + +Приор был «одна ручка на бэнк-блок; вторая появится по замеру». Замер парный, N=5 на уровень, через боевой путь: + +| Уровень | 6/6 достигнуто | completion-токены | цена 5 вызовов | +|---|---|---|---| +| `low` | 4 из 5 | 91–1278 | $0.001016 | +| `high` | 5 из 5 | 920–3104 | $0.002335 | + +4/5 против 5/5 на n=5 **неразличимо**, а `high` стоит 2.3×. ⚠ **Самопоправка:** первый вызов дал 3/6, я на этом основании построил вторую ручку `classify_reasoning` — и **снял её**, когда выборка не подтвердила разницу. Единственный промах — вызов на 91 токене, то есть модель просто не подумала; уровень тут ни при чём. + +**Итог: одна ручка на обе бэнк-роли.** Классификатор сохраняет собственную МОДЕЛЬ (`classify_model`), но не собственный эффорт. + +⚠ **Честная граница самих чисел 6/6** (унаследована от D39.86, повторяю, чтобы не читалась сильнее, чем есть): 元石 и 灵泉 стоят ДОСЛОВНО в `prompts/zh-ru/classifier.md`, то есть два из шести — припоминание, а не суждение. Дискриминирующее подмножество — 元海/蛊室/池塘/酒肆, и падение на `low` было ровно по нему (1/4 против 4/4). Читать как «4 решено + 2 припомнено». + +**Точки шва в коде после правок:** `attemptRequest` — `stagerun.go:406`; `bankRoleSettings` — `terminologist.go:534`; `bankStage` — `terminologist.go:553`; `repairStage` — `repair.go:363`. (Номера `terminologist.go:515,568`, `repair.go:384`, `live_reprobe_test.go:98` в тексте — ИСХОДНЫЕ места литералов, как их называет D39.87.) + +### 1.5. `Temperature` — зафиксирована нулём осознанно + +Ответ бэнк-роли и repair — разбираемая движком СТРУКТУРА (таблица терминов, тип, спан-замена), где разброс сэмплинга — чистый риск; температура стадии это СТИЛЕВОЙ выбор про прозу и здесь бессмысленна. Ноль — то же значение, при котором куплены все существующие бэнк-чекпойнты, так что решение ещё и не двигает хеш. Причина первая, совпадение второе. + +### 1.6. Repair — ключ СВОЙ, наследование СНЯТО + +Первая версия наследовала эффорт от чинимой стадии (так предлагал промт и D39.87). **Ревью это опровергло, я перепроверил и согласился:** + +- **Деньги:** `reasoning: "off"` стоит на финальной стадии у **всех** шиппинг-пайплайнов (`pipeline-c1.yaml:77`, `c2:51`, `arm-glm:43`, `arm-deepseek-pro:43`, стенд coldrun-b:44). Наследование двигало хеш ⇒ перекупка всех уже оплаченных repair-вызовов. +- **Семантика, и это хуже:** `reasoning` — не уровень, а значение, чьё ЗНАЧЕНИЕ зависит от control модели. Финальная стадия `deepseek-v4-pro` с `reasoning: "off"` — задокументированный no-op; `gates.repair.model: glm-5` — и тот же «off» становится живым `thinking:{type:disabled}`, то есть эхо-зоной. Родительская стадия и repair — РАЗНЫЕ модели. + +Решение: `gates.repair.reasoning` — собственный ключ. Не задан ⇒ `""` ⇒ побайтно прежнее поведение. + +### 1.7. Мульти-провайдерность — и найденная при этом дыра + +Промт требовал закрыть режим `extra_body_disable` (glm), где ПУСТОЙ эффорт означает не «дефолт провайдера», а thinking ВЫКЛЮЧЕН. Расширил `sourceEchoExposure` на внутренние вызовы движка — и **ревью показало, что этого мало**: предикат `ThinksOnWire` для этого control возвращал `reasoning != "off"`, то есть на ПУСТОМ значении отвечал «думает», расходясь с проводом, который в этом же случае мержит disable. + +Проверено исполнением: +``` +applyToBody effort="" -> wire={"max_tokens":…, "thinking":{"type":"disabled"}} +ThinksOnWire(glm-подобная, "") = true <-- врал +``` +Починено, запинено `TestThinksOnWireMirrorsTheWireForEachControl` (8 кейсов на три control). Проверил, что на старом коде тест падает. + +⚠ Это была **предсуществующая** дыра (она так же молчала про СТАДИИ на glm без ключа `reasoning`), но мой пак первым на этот предикат оперся, поэтому чиню здесь. + +### 1.8. Наш enum против вендорского — решение и явный отказ + +`ValidReasoningEffort` принимает `"" | off | low | medium | high` — НАШ провайдер-слепой набор. У DeepSeek документированы `low/high/max` (+`xhigh`): `medium` там неопределённое поведение, `max`/`xhigh` нашим конфигом недостижимы. **Валидацию против капабилити резолвнутой модели НЕ строил** — это потребовало бы пер-модельной таблицы enum'ов в `models.yaml`, которой нет, то есть НОВЫЙ механизм (нарушение §0 п.1). Дыра предсуществующая и одинаковая для `stages[].reasoning`. Записано находкой (§6, Д5), не закрыто молча. + +### 1.9. Доккомменты эхо-гейта — обязанность D39.86 п.2 / D39.87 + +Приведены в соответствие `config/models.go` (`thinkingControlExtraKeys`) и `llm/capability.go` (`ReasoningNone`). Ключевая формулировка: **запрещён не ПРЕДМЕТ, а сырой канал** — уровень эффорта через `stages[].reasoning`/`gates.*.reasoning` легален и идёт через `Capability.applyToBody`, который знает, что «off» значит для этого control; `model.extra_body` мержится дословно и потому может ВЫКЛЮЧИТЬ thinking, что и есть мина. Гейт **не ослаблен**. + +--- + +## §2. §3.4 — платная проба банка на `low`. ЗЕЛЁНАЯ + +**Хост:** `~/books/gu-zhenren/coldrun-b/reprobe/bank-low/` — свой `book_id`, своя БД, свой леджер. Эталон `coldrun-a` только на ЧТЕНИЕ (срез глав 1–10), не тронут. + +### 2.1. Числа + +``` +терминолог 4/5 батчей finish=stop · consolidated=72 · unanswered=18 + bad_lines=0 · off_language=0 · canon_conflicts=0 · $0.005750 +классификатор 5/5 stop · reclassified=14 · $0.004286 +черновая волна 20/20 чанков ok · 25 свежих вызовов · 2 эскалации вылечили эхо + $0.031639 (flash) + $0.010350 (pro) +``` +Против вендор-дефолта `high` (замер D39.86): **1 батч из 5 и 1 терм из 81**. + +### 2.2. Оба молчащих пути ИСКЛЮЧЕНЫ предъявлением + +Промт требовал: вердикт «работает/не работает» имеет право быть вынесен только предъявив, что ни ролевой суб-бюджет, ни книжный потолок не сработали. + +| | потрачено | бюджет | % | +|---|---|---|---| +| терминолог | $0.005750 | $0.05 | 11.5% | +| классификатор | $0.004286 | $0.02 | 21.4% | +| книга | $0.045095 | $0.10 | 45.1% | + +И в логе **ноль** строк `budget would be exceeded by the next batch` / `denied by a USD ceiling`. + +### 2.3. Провод вскрыт + +35 тел (25 translator + 5 terminologist + 5 classifier), ключи ровно `[max_tokens, messages, model, reasoning_effort, stream, temperature]`, `reasoning_effort:"low"` **во всех 35**, ключей `thinking` — **0**, `reasoning_content` непустой везде. **Гардрейл «thinking у DeepSeek не выключать» цел и доказан проводом, а не рассуждением.** + +Упавший батч вскрыт сырьём (требование промта — прошлая сессия этого не сделала): `content:""`, `finish=length`, `completion_tokens=7999`, `reasoning_tokens=7999`. То есть **тот же тяжёлый хвост, что при `high`, просто на 1/5 вместо 4/5** — `low` стену не убирает, а разрежает. Батч #2 не самый большой по входу (5909 симв. против 5890/5806), то есть стохастика вызова, согласуется с квирками п.6. + +### 2.4. Деньги двумя путями + +``` +леджер (Σ чекпойнтов) $0.045095 +независимый пересчёт usage×вендор-цены $0.045095 +дельта $0.000000 + +разбивка: основной заход $0.041675 + риг 6/6 (11 вызовов: 1 + 5 на low + 5 на high) $0.003420 +``` +Расхождения строки 78 (2xx с битым декодом) в этом заходе НЕ было — 0 строк `decode_error`. + +### 2.5. Правки стенда, объявленные построчно + +`~/books/gu-zhenren/coldrun-b/reprobe/bank-low/pipeline.yaml` — тело ран-конфига coldrun-b с ТРЕМЯ отличиями: +1. `stages[draft].reasoning: "low"` вместо no-op `"off"` — иначе волна упирается в стену и до банка проба не доезжает. +2. `gates.terminology.reasoning: "low"` — НОВАЯ ручка, предмет замера. +3. `escalation.budget_usd: 0.015` вместо `0.10` — **понижен сознательно**: эскалации идут ДО банка, при $0.10 они могли съесть книжный потолок раньше первого вызова терминолога, и проба ответила бы «банк не работает» на деньгах. ⚠ Это делает наблюдение эскалаций НЕПОЛНЫМ; предмет пробы не они. + +Боевой `coldrun-b/pipeline.yaml` **не тронут** (там по-прежнему `reasoning: "off"` на черновике — правка под работу C, которая не стартовала). + +--- + +## §3. Работа B — экран целевого языка (строка 46). ДИЗАЙН ПОДАН, КОДА НЕТ + +Промт: «вердикт-двигающее ⇒ сначала дизайн и пинг, потом код». Пинг подан владельцу, решения нет ⇒ кода нет. Это легитимный исход по букве промта. + +### 3.1. Живая улика, добытая в этом заходе + +**Глава 8, чанк 1 пробы bank-low:** полный связный черновик **на английском**, `finish=stop`, `disposition=ok`, и его хеш стоит в `final_hash` чанка. Хеш `fb51e135a395`, 5990 симв., 4690 букв, латиница 100%, кириллица 0.000. Второй такой же в `optB` (`4080ee8287af`, 4811 букв). Плюс полный **японский** черновик в `exp15/anchors/oracle_30.db` (`94905a7e443f`). + +### 3.2. ⚠ ПОПРАВКА К МОИМ ЖЕ ЧИСЛАМ + +Я подал владельцу «здоровый русский 0.9510–1.000, n=1306». **Это измерено на СЫРОМ тексте чекпойнта.** Движок классифицирует ПОСЛЕ среза банкноты (`stagerun.go:632` режет, `:636` классифицирует; срез безусловен для роли translator, `banknote.go:320`), то есть гейт видит другой текст. Пере-мерил его же функциями (`splitBanknote` + `checks.StripThink`): + +| | я подал | на тексте, который видит гейт | +|---|---|---| +| здоровый минимум | 0.9510 | **0.9767** | +| n | 1306 | **1055** (дедуп по хешу; 1306 двоил бэкап-копии БД) | +| off-target выходов | 26 строк | **20 событий** | + +Решения это не меняет (оба числа далеко от любого порога), но число я называл — поправляю. + +### 3.2а. Поправка к БАЗЕ отказа + +Публиковалось «~1.5% off-target». Знаменатель неверен: он пулит черновики с РЕДАКТОРСКИМИ выходами, а редактор этот отказ произвести не может (он не переводит с исходника). На черновой вызов база **≈3.0%**. Оба числа — одна книга, один жанр, по сути одна модель. + +### 3.3. ⚠ ГЛАВНАЯ ПОПРАВКА: боевой гейт уже ловит 18 из 20 + +Ни ресерч, ни я не измеряли ДО этого, что делает **уже развёрнутый** гейт. Измерил: + +``` +sourceScriptShare > 0.15 (disposition.go:224,275) + поймано: 18 из 20 off-target событий + ложных: 0 из 1055 здоровых + запас: худший здоровый 0.0117 против порога 0.15 — 13× + промах: ровно 2, оба английские, 5990 и 6078 симв. +``` + +То есть движок **не открыт настежь**. Остаточная дыра — **2 чанка из ~1100 = 0.18%**, оба английские. Японский ловится (доля ханьцзы 0.332, японский делит письменность с китайским). + +**И второй рубеж существует, но стоит не там.** Прогнал боевой санитайзер по тем самым байтам английского черновика: `total=1, cosmeticOnly=false, "Latin insertion"` — он бы его поймал. Не ловит потому, что `chunkrun.go:52` требует `isFinal`, а `isFinal := stageIdx == len(Stages)-1` (`stagerun.go:145`) ⇒ **в шиппинговой двухстадийной топологии черновик переводчика НИКОГДА не финальный**. Тот же `isFinal`-гейт глушит на черновике латинный лint, флаггер голоса и глоссарный пост-чек. Плюс он опционален (`gates.sanitizer.enabled`) и требует данных цели. + +⇒ Формулировка «ни один предикат не ловит» верна **только для черновой стадии**. На финале для русской цели с включённым санитайзером ущерб = потеря юнита + оплаченный впустую редактор, а не тихая отгрузка. Для любой другой цели слой 7 инертен по отсутствию данных и рубежа нет вовсе. + +### 3.4. Дизайн, поданный на решение + +**Носитель:** `lang.LangScripts(Book.TargetLang)` — тот же дата-план, на котором стоит эхо-детектор, тот же `data/lang-script.txt`, где `ru→cyrillic` уже объявлено. **Новый файл в `go:embed` НЕ добавляется** — это критично: `EmbeddedVersion` фолдится в снапшот БЕЗУСЛОВНО, то есть новый эмбед-файл перекупает все книги всех пар. + +⚠ `gates.terminology.target_script` как носитель **отвергнут**, но по причине сильнее промтовой: он ДУБЛИРУЕТ то, что данные уже знают, и потому это уже существующий «второй способ сказать то же самое». Промт снимал его за «нет в шиппинг-конфигах» — на деле ключ ОБЯЗАТЕЛЕН при включённом гейте (`pipeline.go:1075`). + +**Порог 0.50** — не калиброван, а сознательно консервативен: пустой интервал между 0.0000 (все 20 событий) и 0.9767 (худший здоровый) шириной 0.9767, порог поставлен в его середину. Калибровать по Нейману–Пирсону на этом корпусе нельзя (§5.2). + +**Развилка, которую промт требовал НАЗВАТЬ, а не предрешать** — подана владельцу трёхчастной: +| | Что | Цена | +|---|---|---| +| (а) | предикат внутри `classify()` + бамп `classifierVersion` | снапшот двигается у всех книг; на свежем стенде $0, голден пере-захват один раз | +| (б) | отдельный опциональный гейт вне `classify()` | снапшот не двигает, но это второй способ сказать «ответ непригоден», и он выключен по умолчанию | +| (в) | сразу языковой детектор | см. §5 | + +Мой выбор — **(а)**. + +### 3.5. Вторая половина дыры — решение + +`detectLatinInsertion` (`checks/sanitizer.go:343`) внутри санитайзера НЕ обусловлен `TargetScriptNonLatin()`, хотя доккоммент `disposition.go:302-305` объявляет именно эту защиту (реальный гард стоит только на репэйр-пути). Следствие: первая же ЛАТИНОПИСЬМЕННАЯ цель дропнет 100% чанков чистой прозы. + +**Решение: чинить здесь же, тем же диффом** — это одна работа с первой половиной. Для русской цели вердикты не меняются ни на байт (`TargetScriptNonLatin()` для ru истинно), то есть бампа `SanitizerVersion` не требуется. **Не сделано** — работа B не начата. + +### 3.6. Что бы сломалось, если бы я сделал B наивно + +Ревью и аудит нашли три мины, в которые я бы въехал: + +1. **Новый флаг провалился бы в дыру.** `escalatable()` — закрытый белый список, `retryable()` — только `{length, empty}`. Новая причина не попадает ни туда, ни туда ⇒ пойманный чанк **молча терялся бы вместо перекупки**. Правильное решение — переиспользовать `FlagCJKArtifact` (он уже escalatable и не retryable), а не заводить новую константу. +2. **Классификатор ложно флагается 16 из 16 уже сегодня** (`SourceEchoExpected: role == roleTerminologist` не покрывает `roleClassifier`). Мой экран флагнул бы его вторым способом. Экран обязан читать не роль-строку, а факт формы ответа, проставленный тем же швом работы A. +3. **Экран слеп к ПОДМНОЖЕСТВАМ письменности:** у японского набор {ханьцзы, хирагана, катакана} ⇒ чисто китайский выход для →ja книги наберёт 1.000 и пройдёт. То же для →ko. + +--- + +## §4. Работа C — НЕ НАЧАТА + +Причина по букве промта: «идёт только после того, как работы A и B ЗАКРЫТЫ И ЗАМОРОЖЕНЫ». Работа B застряла на дизайн-пинге — промт прямо называет это легитимным исходом захода. Дополнительно владелец закрыл прогон как неуспешный на данном этапе и вернул его оркестратору. + +**Стенд `~/books/gu-zhenren/coldrun-b/` стоит нетронутым:** свежая БД, сид не подключён, `pipeline.yaml` побайтно равен эталону coldrun-a кроме шапки, черновик по-прежнему на `reasoning: "off"` (правка под C не внесена — вносить её без прогона значило бы оставить стенд в промежуточном состоянии). + +Строка 16 (полная цена холодного старта включая редактуру) **НЕ закрыта**. Строка 13б (оси голоса) **без данных** — редакторская волна снова не гонялась. + +--- + +## §5. Ресерч-задел для следующих сессий + +Два холодных исследования, каждое с независимыми скептиками (author≠reviewer). Полные тела — в транскриптах воркфлоу; ниже то, что должно пережить сессию. + +### 5.1. Off-target детекция: закрыта ли задача + +**ЧАСТИЧНО, и нерешённая часть меньше, чем казалось.** + +**Устоялось (не пере-открывать):** +- У отказа есть имя и метрика: *off-target translation* (Zhang et al., ACL 2020, arXiv 2004.11867), *language confusion* LPR/WPR (Marchisio et al., EMNLP 2024, arXiv 2406.20052). Рецепт у всех один и он у нас уже реализован: детектор на выходе → сравнение с запрошенной целью → mismatch = отказ. **Более умного serving-time метода не упущено.** +- Английский — доминирующий аттрактор. Подтверждено дважды независимо (Cohere; Guerreiro et al., TACL 2023: >90% off-target галлюцинаций при переводе С английского). Совпадает с нашими 2/20 английских. +- Четыре режима отказа — практика поля, не новизна: Guerreiro использует РАЗНЫЙ детектор на режим (ALTI+ для detached, top-n-gram для oscillatory, LID только для off-target). Гнать всё через один детектор — ошибка проектирования, и мнение из обсуждения тут право. +- Abstain + пол по длине — опубликованная практика (Cohere `compute_metrics.py`: строка оценивается только при `len(tokens) >= 5`). +- Reference-free QE эту задачу не делает, и поле пишет об этом прямо. + +**Открыто у всех:** +- Близкие кириллические соседи. OpenLID-v3 на реальном пользовательском тексте: боснийский 37.21% precision, сербский-латиница 30.85% recall; 19.9% ошибок — «полная неоднозначность». Трёх девяток тут не достигает никто. +- FPR детектора на настоящей ЦЕЛЕВОЙ прозе длиной в чанк не опубликован нигде. +- Дрейф в середине генерации: нет устоявшейся статистики, гранулярности и правила агрегации. +- Ничего в этой литературе не про длинную художественную прозу. Caswell et al. 2020: >90% held-out F1 соответствовал ~5% точности по человеческой оценке «в дикой природе». + +### 5.2. Почему обещанной гарантии FPR ≤ 0.1% здесь не купить + +Правило трёх: ноль отказов на n независимых испытаний покупает `1 − 0.05^(1/n)`. Для ≤0.1% нужно n ≥ 2995. У нас **114 различных позиций (глава, чанк)** — одна книга, один жанр, одна модель — это покупает **FPR ≤ 2.594%**, в 26 раз слабее обещанного. Даже если считать все 1055 выходов независимыми — ≤0.283%. + +Плюс процедура двоит данные: «калибруй так, чтобы ложное отклонение ≤0.1%» ставит порог в эмпирическую 0.001-квантиль ТОЙ ЖЕ выборки, по которой потом заявляется граница. При n≈1000 порог определяется вторым наименьшим наблюдением. + +И третье: Нейман–Пирсон ограничивает ошибку I рода и **ничего не говорит про мощность**. На сиблингах распределения нулевой и альтернативной гипотез по доле целевого письма СОВПАДАЮТ (болгарский даёт ровно 1.0000). Односторонний срез при α=0.001 даёт мощность ≈0.1%: гарантия есть, ловли нет. + +⇒ **Ставить руками консервативную константу в широком пустом интервале и версионировать её как контракт, а не как тюнинг.** + +### 5.3. Что НЕ строить (и почему) — самая ценная часть + +1. **Никакую статистическую LID-библиотеку в путь вердикта.** Проверено запуском, не по README: `lingua-go` — НЕдетерминистична (6/23 образцов на 20 000 повторов; `GOMAXPROCS=1` не лечит — причина в обходе map при суммировании float64), +126 МиБ эмбеда безусловно, 10–12 мс/чанк против бюджета 168 мкс, и вендор документирует вердикт-двигающие апгрейды. `langid-go` — на 644 реальных сегментах русской Википедии даёт P(ru)<0.5 на **22.2%** сегментов длиной 20–40 рун; плюс FMA-зависимость от GOARCH. `whatlanggo` — 4–6 из 9 настоящих русских образцов принимает за болгарский/македонский. `getlang` — argmax флипается. `gocld3`/fastText — CGo, вердикт становится функцией тулчейна, то есть уезжает ВНЕ снапшот-хеша. +2. **Посегментный worst-of (L4 из мнения).** Умножает FPR на число сегментов ПО ПОСТРОЕНИЮ, и — решающее — **не имеет ни одного положительного примера**: самая длинная не-кириллическая цепочка в здоровом выходе 23 символа, между 0.0000 и 0.9767 не лежит ничего. На замеренных точках стоило бы 74–290 дропнутых чанков на книгу ради нуля дополнительных поимок. Цена (269 мкс) никогда не была препятствием — препятствие в калибровке и пустом классе положительных. +3. **Замыкание алфавита (L2).** Против болгарского доказуемо ноль (его алфавит — собственное подмножество русского), в остальных случаях избыточно с L1. +4. **Функционально-словный экран.** Здоровый русский p01 = 0.2433 на выход и 0.0455 на абзац — зазор крошечный, а русский закрытый класс во многом и болгарский. На этой машине нет ни одного сиблинг-текста, чтобы померить. +5. **Эхо через расстояние редактирования / n-граммное сходство.** `sourceScriptShare > 0.15` уже даёт 18/20 при 0 FP и 13× запасе. +6. **Любой новый файл в `go:embed`-манифесте** ради этой фичи. `EmbeddedVersion` фолдится БЕЗУСЛОВНО ⇒ перекупка всех книг всех пар. +7. **Hunspell в любом виде** и **GlotScript-эмбед** (stdlib `unicode` уже несёт ISO-15924-совместимые таблицы, движок к ним уже ходит). + +### 5.4. Пошаговый план для следующей сессии + +Принцип порядка: единственный необратимый шаг — бамп `classifierVersion`, он последний. Шаги 1–3 независимы. + +1. **Корпус-фикстура в репо** (~20 off-target + ~40 здоровых, с движковой предобработкой). Снапшот НЕ двигает. СТОП, если не воспроизводит 18/20 при 0 FP. +2. **Записать реальный запас боевого гейта регресс-тестом** (худший здоровый source-share 0.0117 против 0.15). Это база, которую обязано побить любое предложение, и её никто не записывал. СТОП, если запас меньше 3×. +3. **Поправить два дока-дефекта** — опубликованный диапазон 0.9510 и база 1.5% (правильно: 0.9767 на 1055 движково-чистых, и база 3.02% на ЧЕРНОВОЙ вызов, а не на все выходы, потому что редактор этот отказ произвести не может). Зона оркестратора. +4. **`targetScriptShare` чистой функцией, НЕ подключённой.** Снапшот НЕ двигает — в этом и смысл, дорогое отложено. СТОП, если хоть один здоровый ниже 0.90. +5. **Прогнать предлагаемый вердикт офлайн по всем сохранённым чекпойнтам** и сдиффить диспозиции. Ожидание: ровно **2 строки** меняются. **СТОП+эскалация, если изменилась хоть одна здоровая.** +6. **Подключить и бампнуть `classifierVersion`** — ДЕНЕЖНЫЙ шаг, только с подписью владельца. Переиспользовать `FlagCJKArtifact` (уже escalatable). Порог abstain — **200 букв** (ниже него экран воздерживается; самое короткое off-target событие — 346 букв, ниже 200 падают лишь 5 из 1055 здоровых, все со счётом 1.0000). +7. **Починить `cultivation` в сиде, а не порогом.** 86 из 1055 здоровых выходов содержат голое английское `cultivation` внутри беглого русского; ВСЕ 32 абзаца, набравшие ниже 0.90, содержат его, и НИ ОДИН не содержит ханьцзы. Это дефект глоссария, не калибровочная константа. Правка в пар-данных двигает `LangpackVersion`, который фолдится с `omitempty` ⇒ перекупка ограничена книгами ЭТОЙ пары. Это самый переносимый вывод всей цепочки: **чинить на том плане, где перекупка уже.** +8. **Записать сиблинг-угрозу непостроенной строкой с триггером.** Ни одного события не наблюдалось. Если появится — дискриминатор это плотность РУССКО-ЭКСКЛЮЗИВНЫХ букв (ы/э/ё) НИЖЕ ожидания, а не замыкание алфавита. + +### 5.5. Ресерч про механизм гардов (побочный, но применён) + +Форма «архитектурное правило как обычный тест» — **стандартная**: `go/build/deps_test.go` в самой stdlib держит так граф зависимостей («*It is a statement of policy. DO NOT CHANGE THIS DATA TO FIX BUILDS*»), `go/types/errorcalls_test.go` — буквально `ast.Inspect` по своим исходникам. Аналог в Java — ArchUnit. + +Альтернативы проверены запуском и **не проходят наше ограничение «падать на обычной батарее»**: `go test -vet=<свой анализатор>` → *«-vet argument must be a supported analyzer»*; `GOFLAGS=-vettool` при `go test` игнорируется; штатный `composites` вообще не входит в набор `go test`. `golangci-lint` — 38.7 МБ бинарь и первый в проекте `.golangci.yml`. `x/tools` в тесте тянет `x/net` 0.26.0 → 0.54.0, а `x/net/http2` — наш транспорт к провайдерам. + +`exhaustruct` — инструмент ровно под исходный класс бага, но на нашем коде даёт 16 находок, из которых 15 в тестах и одна — сам конструктор. + +--- + +## §6. Дефекты: найдено / починено / отложено + +### Починено с тестами (в этом заходе) + +| № | Дефект | Тест | +|---|---|---| +| П1 | Синтетические стадии теряли `Reasoning`/`Temperature` — 4 места | `TestSyntheticStageSeamIsSingle` + `TestInternalCallDecidesEveryStageField` | +| П2 | `bankCheckpointExists`/`repairCheckpointExists` строили кортеж БЕЗ `Temperature`/`Reasoning`, расходясь с `runAttempt` в ОБЕ стороны (ложно-false режет резюм бюджетом; ложно-true обходит ролевой суб-бюджет) | `TestRequestIdentitySeamIsSingle`, `TestBankProbeAndAttemptAddressOneCheckpoint` (3 уровня эффорта, боевой путь `Reserve`→`SettleWithCheckpoint`) | +| П3 | `ThinksOnWire` на `extra_body_disable` врал про пустой эффорт ⇒ бэнк-роль на glm уезжала в thinking-off МОЛЧА | `TestThinksOnWireMirrorsTheWireForEachControl` | +| П4 | `sourceEchoExposure` не видел внутренние вызовы движка | расширен; детерминизм порядка — `sort.Strings` | +| П5 | Гарды пробивались 7 способами (5 байтовых + алиас импорта + опущенный тип элемента) | переписаны на AST, все 7 посадок CAUGHT | +| П6 | Поведенческие тесты были вакуумны (сравнение вызова с самим собой; смена двух полей вместо одного) | переписаны на боевой денежный путь | +| П7 | `bankRoleSettings` молча отдавал бы настройки терминолога неизвестной роли | явная паника с именем роли | +| П8 | `bankRolePlan.model` — второй источник правды, читался только логом | снят | +| П9 | Риг с N=1 по умолчанию при комментарии, осуждающем n=1 | дефолт 5 | + +### Найдено, НЕ починено — с носителем + +| № | Дефект | Носитель | +|---|---|---| +| Д1 | Экран целевого языка (работа B) | решение владельца по развилке §3.4 | +| Д2 | `detectLatinInsertion` не обусловлен `TargetScriptNonLatin()` ⇒ первая латинописьменная цель дропнет 100% чанков | тем же диффом, что Д1 | +| Д3 | `SourceEchoExpected` не покрывает `roleClassifier` ⇒ 16/16 вызовов классификатора логируются `ok=0 degraded=cjk_artifact`. Данные НЕ теряются (`run.texts[i] = att.text` безусловен, `reclassified=14` доказывает), но отравлен ровно тот сигнал, который говорит «провайдер плохеет» | тем же диффом, что Д1 | +| Д4 | `gates.terminology.target_script` не сверяется с `book.target_lang`: `target_lang: ru` + `target_script: Latin` грузится чисто и **инвертирует** банковский экран | бэкенд, отдельный пак; вне снапшота ⇒ дёшево | +| Д5 | Наш enum эффорта провайдер-слеп: `medium` на DeepSeek — неопределённое поведение, `max`/`xhigh` недостижимы | решение оркестратора: нужна ли пер-модельная таблица | +| Д6 | `//go:embed` в `internal/lang/embedded.go:22` — ЯВНЫЙ список файлов, не `data/*`. Новая цель ⇒ правка Go. `CompileCheckers` паникует при неполном файле цели. На ревью-вопрос «заработает ли пара, которой нет в репо» ответ сегодня **НЕТ** — и это не про язык, а про строку эмбеда | архитектура, оркестратор | +| Д7 | Два гарда шва разной формы (AST против байтового регэкспа), с разным корнем обхода и разными словарями исключений | бэкенд; свести в один обход | +| Д8 | Ратифицированный порог классификатора «6/6» определён для ОДНОГО вызова, не для выборки. На `low` — 4/5. Риг сейчас красный на рекомендованном уровне, и это заявлено в тексте падения, а не смягчено | владелец/оркестратор | +| Д9 | Аддитивные провайдеры отказываются для бэнк- и repair-гейтов ИМЕННО потому, что блок не несёт `reasoning_max_tokens`. Новая ручка эту дыру НЕ закрывает | зафиксировано комментарием; вскрывать под отдельное решение | +| Д10 | **Шиппинговые конфиги репо всё ещё несут `reasoning: "off"` на ЧЕРНОВОЙ стадии** (`configs/pipeline-c1.yaml:49`, `c2:26,39`, `arm-mistral:30`, `arm-deepseek-pro:34`, `arm-glm:34`) — тот самый no-op, который отправил прогон в стену 0/9 при вендор-дефолте `high`. Санкция (б) по D39.87 касается и их, но правка **двигает снапшот всем, кто этими конфигами пользуется** ⇒ молча не менял | владелец/оркестратор: применять ли (б) к шиппинг-конфигам и когда платить перекупку | +| Д11 | Область правки `ThinksOnWire` — уточнение, чтобы её не переоценили: **ЯВНЫЙ `"off"` на glm предупреждался и до правки, и после** (в `pipeline-arm-glm.yaml:43` он стоит осознанно и с измеренной причиной — «таймауты ×3»). Правка меняет ровно один случай: **ключ ОТСУТСТВУЕТ**. Там предикат отвечал «думает», а провод мержил disable. Дыра предсуществующая и одинаковая для стадий и для гейтов | закрыто; строка оставлена, чтобы приёмка не искала регресса в армах | + +--- + +## §6а. Батарея числами (после ВСЕХ правок, включая пост-ревью) + +``` +go build ./... exit 0 +go vet ./... exit 0, пусто +go vet -tags live ./internal/pipeline/ exit 0, пусто +gofmt -l . пусто +go test -race -count=1 ./... все 14 пакетов ok (pipeline 82.0s, store 15.9s) +TestGoldenDeterminism PASS (голден НЕ пере-захватывался — нечему двигаться) +майнер-парити EXACT n=13618 catastrophe{方源:0 蛊:1 蛊师:2 古月:22} recall@proposed=0.9655 (56/58 GT) +labels-фриз k4b 10/1/36/99 · k4_inverse 3/0/1/71 · k2 34/1/6/51 · k4a 0/0/0/348 +K6 (membank) tp=1 fp=6 fn=0 tn=251 +``` +Все пять фрозен-чисел совпали с ратифицированными. Батарея гонялась **трижды**: после работы A, после снятия второй ручки, после пост-ревью фиксов. + +## §7. Заявление = команда + +| Число | Команда | +|---|---| +| батарея (build/vet/vet-live/race/gofmt) | `go build ./... && go vet ./... && go vet -tags live ./internal/pipeline/ && gofmt -l . && go test -race -count=1 ./...` | +| голден PASS | `go test ./internal/pipeline/ -run TestGoldenDeterminism -count=1` | +| парити EXACT `n=13618 catastrophe{方源:0 蛊:1 蛊师:2 古月:22} recall 0.9655` | `TM_MINER_PARITY=1 go test ./internal/miner/ -run Parity -count=1 -v` | +| labels-фриз k4b 10/1/36/99 · k4_inverse 3/0/1/71 · k2 34/1/6/51 · k4a 0/0/0/348 | `TM_CHECKER_LABELS=1 go test ./internal/checks/ -run Label -count=1 -v` | +| K6 1/6/0/251 | `TM_CHECKER_LABELS=1 go test ./internal/membank/ -run K6 -count=1 -v` | +| проба §3.4, все числа стадий | `LOG_LEVEL=debug LOG_LLM_BODIES=1 ./bin/tmctl translate --config ~/books/gu-zhenren/coldrun-b/reprobe/bank-low/book.yaml --verify-bank` | +| терминолог 72/18, off_language=0 | `grep "terminology finished" ~/books/gu-zhenren/coldrun-b/reprobe/bank-low/run-01.stderr.log` | +| леджер $0.045095 | `sqlite3 "file:…/guzhenren-bank-low.db?mode=ro" "SELECT SUM(cost_usd) FROM checkpoints;"` | +| независимый пересчёт $0.045095 | `SELECT SUM((prompt_tokens-cached_tokens)*0.14/1e6 + cached_tokens*0.0028/1e6 + completion_tokens*0.28/1e6) FROM request_log WHERE tm_hit=0 AND model_actual LIKE 'deepseek-v4-flash%'` + pro вручную по `models.yaml:161` | +| 35 тел с `reasoning_effort:"low"`, 0 ключей `thinking` | `grep -o 'reasoning_effort[^,}]*' run-01.stderr.log \| sort \| uniq -c; grep -c '"thinking"' run-01.stderr.log` | +| классификатор 4/5 и 5/5 парно | `TM_LIVE=1 TM_CLASSIFY6_N=5 TM_CLASSIFY6_CONFIG=…/bank-low/book.yaml go test -tags live -run TestLiveClassifierHarmSet -count=1 -v ./internal/pipeline/` (сырьё: `classifier-6of6-{low,high}.json`) | +| боевой гейт 18/20, FP 0/1055, запас 13× | временный тест в пакете pipeline через `splitBanknote`+`StripThink`+`sourceScriptShare`; удалён после снятия | +| санитайзер поймал бы английский черновик | временный тест: `CompileCheckers(nil, lang.TargetChecksFor("ru")).SanitizeOutput(…)` → `total=1 cosmeticOnly=false "Latin insertion"`; удалён | +| валидация гейта эффорта громкая | `./bin/tmctl status --config <копия с reasoning: "sorta">` → `gates.terminology.reasoning must be off\|low\|medium\|high` | +| 7 обходов гарда пойманы | посадки в `waverun.go` + `go test ./internal/pipeline/ -run SeamIsSingle`, дерево восстановлено (`git diff --stat` пуст) | + +--- + +## §8. Критик полноты против себя + +- **Качество прозы не судил никто, ни в одной пробе.** `low` мерился детерминированными осями. Черновик без глубокого размышления может быть заметно хуже как ТЕКСТ, проходя все $0-гейты. Это работа судьи Ф2, он не гонялся. +- **`low` вернул волну к жизни, но стену не убрал** — 1 батч из 5 по-прежнему упирается. При другом размере книги/батча доля может быть иной; n=5 батчей. +- **Редакторская волна не гонялась НИ РАЗУ** — ни до смены весов, ни после. Класс отказа, убивший черновик и терминолога, на редакторе не проверен, а рычага там нет (маппинг pro `low→high`). Строка 13б без данных. +- **Проба bank-low понизила `escalation.budget_usd`** — наблюдение эскалаций неполное. +- **Работа B не начата**, а её улика (английский черновик) воспроизвелась в этом же заходе. Дыра открыта. +- **Числа off-target — одна книга, один жанр, по сути одна модель.** Сиблинг-угроза не наблюдалась ни разу; всё, что про неё сказано, — арифметика алфавитов и авторские образцы, не корпус. +- **Первые версии моих гардов и тестов были дефектны**, и нашёл это ревью, а не я. Это второй за заход случай, когда я подал вывод, который не выдержал проверки (первый — 3/6 классификатора на n=1). Оба поправлены до сдачи; оба записаны здесь, а не сглажены. +- **Не проверял**, что происходит с английским черновиком в РЕДАКТУРЕ — вытащит ли редактор его обратно в русский или отредактирует как английский. Проба остановилась на банк-паузе. + +## §9. Адверсариальный проход по своим правкам + +Запущен независимым агентом (author≠reviewer, мандат CLAUDE.md 12.07) по всему диффу с явным заданием «считать сломанным, пока не доказано обратное». Вернул **10 находок**: 1 blocker, 3 major, 5 minor, 1 nit. Все разобраны; топ-2 я **перепроверил кодом сам** до принятия (`ThinksOnWire` — исполнением `applyToBody`; наследование repair — по всем шиппинг-конфигам). Проверенные им и НЕ нашедшие дефектов области: идентичность кортежа для всех предсуществующих путей (хеши совпали побайтно, бэнк-пробник с незаданным ключом → `8e4495006b978ed4` в обе стороны), полнота шва по всем 17 полям `Stage`, конкурентность (`-race` чист), общность (ветвлений по языку/паре/книге нет). + +--- + +## §10. Тронутые файлы (только своё) + +``` +M backend/internal/config/models.go ThinksOnWire + доккоммент эхо-гейта +M backend/internal/config/pipeline.go gates.terminology.reasoning, gates.repair.reasoning, валидация +M backend/internal/config/capability_test.go +TestThinksOnWireMirrorsTheWireForEachControl +M backend/internal/llm/capability.go доккоммент ReasoningNone +M backend/internal/pipeline/stagerun.go attemptRequest +M backend/internal/pipeline/escalation.go хоп через attemptRequest +M backend/internal/pipeline/terminologist.go bankStage/bankRoleSettings, пробник, смета, plan без model +M backend/internal/pipeline/repair.go repairStage, пробник, доккоммент +M backend/internal/pipeline/runner.go sourceEchoExposure на внутренние вызовы +M backend/internal/pipeline/live_reprobe_test.go N-выборка, шов, порог +?? backend/internal/config/internal_call.go ШОВ +?? backend/internal/config/internal_call_test.go полнота полей +?? backend/internal/pipeline/synthetic_stage_seam_test.go гарды швов +M docs/PROGRESS.md секция «Бэкенд», допись СВЕРХУ +?? docs/archive/reports/EFFORT_HANDLE_2026-08-02.md этот отчёт +``` +Вне git (артефакты): `~/books/gu-zhenren/coldrun-b/reprobe/bank-low/` — проект, БД, `run-01.stderr.log`, `wire-terminologist-batches.json`, `classifier-6of6-{low,high}.json`. + +Чужого не тронуто: `START_PROMT.MD`, `frontend/`, `platform/`, `.gitignore`, `docs/` кроме этого отчёта и §Бэкенд в `PROGRESS.md`. Коммитов нет. + +**СТОП — приёмка оркестратора.**