From 062ad27d14f421bb6891e3ba1ba4fd5e9236f7d7 Mon Sep 17 00:00:00 2001 From: heaven Date: Tue, 4 Aug 2026 01:55:00 +0300 Subject: [PATCH] Ratify D39.96-97: standards pack and archguard dofix accepted and landed, rows 107 112 117 closed, snapshot calibration and tools module decisions recorded --- docs/ORCHESTRATOR_SESSION_PROMPT.md | 1 + docs/PROGRESS.md | 33 +- docs/README.md | 2 +- docs/architecture/05-decisions-log.md | 36 +- .../BACKEND_ARCHGUARD_DOFIX_SESSION_PROMPT.md | 48 ++ .../BACKEND_REPO_STANDARDS_SESSION_PROMPT.md | 2 + .../reports/ARCHGUARD_DOFIX_2026-08-03.md | 210 +++++++++ .../reports/EFFORT_HANDLE_2026-08-02.md | 2 +- .../reports/REPO_STANDARDS_2026-08-03.md | 436 ++++++++++++++++++ docs/experiments/16-bank-mining.md | 4 +- 10 files changed, 760 insertions(+), 14 deletions(-) create mode 100644 docs/archive/prompts/BACKEND_ARCHGUARD_DOFIX_SESSION_PROMPT.md rename docs/{ => archive/prompts}/BACKEND_REPO_STANDARDS_SESSION_PROMPT.md (93%) create mode 100644 docs/archive/reports/ARCHGUARD_DOFIX_2026-08-03.md create mode 100644 docs/archive/reports/REPO_STANDARDS_2026-08-03.md diff --git a/docs/ORCHESTRATOR_SESSION_PROMPT.md b/docs/ORCHESTRATOR_SESSION_PROMPT.md index 752ca794..398ce96a 100644 --- a/docs/ORCHESTRATOR_SESSION_PROMPT.md +++ b/docs/ORCHESTRATOR_SESSION_PROMPT.md @@ -43,6 +43,7 @@ ## Методология (продолжай как предшественники — она себя оплатила) - **Двухступенчатая верификация:** промты сессий несут мандат самопроверки ИСПОЛНЕНИЕМ (код+запросы+результаты); твоя пост-хок адверсариальная верификация при лендинге — второй рубеж, author≠reviewer, воркфлоу-инструментом, по СЫРЬЮ с пере-выводом чисел. Эра №6: рубеж-2 поймал CRITICAL-артефакт (окно судьи HEAD_CHARS) и спас контракт от трёх ложных заголовков — не ослабляй. +- **Анти-паттерны приёмки:** приёмка проверяет НАПРАВЛЕНИЕ и решения пака, не только клеймы отчёта. Шесть ловушек: след отчёта (проверяешь лишь названные автором места) · связность вместо истинности (форма отчёта убеждает сама) · соглашательство с чёткой позицией (распространенная ошибка ллм моделей склонных соглашаться с человеком) · рационализация задним числом · слепой участок общих моделей обученных на одинх и тех же данных (выводы одной модели усиливают уверенность в правильности другой) · экономия усилия на неудобном. Механика-минимум: ≥1 верификатор выносит мнение по промту+диффу ДО чтения отчёта · ≥1 ищет дефекты ВНЕ карты отчёта · экспериментальный клейм без ре-рана (хотя бы редуцированного) в D-ноте помечается «со слов сессии», не «исполнением» · «решение владельца», известное только со слов сессии, НЕ ратифицируется — список confirm/deny владельцу ДО лендинга, если решение несущее · к утверждениям самой приёмки та же дисциплина «заявление=команда» (догадку фактом не подавать) · оценочные эпитеты в ноты не писать. - **Пре-рег дисциплина полигона:** фриз коммитом ДО платных вызовов (единственный коммит сессии); изменения после = новый experiment-ID; девиации — явно в отчёте; стоп-гейты по бюджету легитимны; «если не влезает — стоп и пинг, не резать молча». - **Лендинг:** микро-дефекты доков чинишь сам с пометкой «испр. оркестратором»; отчёты получают ревью-шапку; код не правишь — находки в фикс-лист; коммиты скоуп-раздельные, стейджинг пофайловый; `git status` перед каждым коммитом (в дереве бывают ≥2 живые сессии) + **`git diff --cached` перед `commit`** — коммит уносит ВЕСЬ индекс: чужой staged `git mv` уедет в твой коммит (инцидент 77dd9b8); `add` общего файла сметает чужую секцию — diff-контент/`add -p`. **Лендинг, двигающий файлы или состав активных промтов, обновляет `docs/README.md` тем же коммитом** (норма D39.80; урок 02.08: README объявлял заленденный пак «можно запускать» с мёртвой ссылкой — поймал не процесс, а новая сессия). Статус/голову README не несёт вовсе — единственный носитель состояния = PROGRESS CURRENT-STATE. **Перед коммитом ратификации — механический чек головы:** `grep "голова D" docs/PROGRESS.md` обязан показать номер ТОЛЬКО ЧТО ратифицированной ноты (голова отставала дважды: D39.81 и D39.83 — оба раза «Текущее» обновлено, число головы забыто). - **Findings-ledger процесс (концерн 5):** каждая находка — явная диспозиция до закрытия; вопросы «к бэкенду» из ресёрчей маршрутизируются обратно; completeness-critic на границах фаз. diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 763fa2aa..c52fdd55 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -1,12 +1,12 @@ # Журнал прогресса -> **⟶ ТЕКУЩЕЕ СОСТОЯНИЕ** (на 2026-08-02, голова D39.95). -> - ⚠⚠ **ПЕРЕДАЧА ОТ ОРКЕСТРАТОРА №11 → №12 (D39.94, 02.08).** Пак 104 ПРИНЯТ и заленден `553f1a3` (строка 104 закрыта, D39.91); решения владельца ратифицированы (D39.92–93). **Задачи преемника:** (1) приёмка пака по `BACKEND_REPO_STANDARDS_SESSION_PROMPT.md`, когда бэкенд отработает (образец — D39.91; этап 0 промта = пять шиппинг-конфигов на `low`, санкция есть); (2) выдать промт пака экрана 46 — порядок и ограничения в D39.94 п.3 (фикстура 113 первой; денежный шаг ТОЛЬКО с подписью владельца). **ОТКРЫТО НА ВЛАДЕЛЬЦЕ (ответа нет):** 116 (порог «≥4/5 при N=5» подан) · строка 5 (находки прерванного банк-ресёрча или пере-запуск; промт подрезать до $1.20 ПЕРЕД выдачей) · мини-проба 44 «low+16k» (~$0.05) · подпись денежного шага 46. **Вахта:** маппинг эффорта `deepseek-v4-pro` меняется «early August 2026» (реестр 108, триггер >05.08). **Источник истины по РЕШЕНИЯМ — `architecture/05-decisions-log.md`; этот файл — ЖУРНАЛ.** +> **⟶ ТЕКУЩЕЕ СОСТОЯНИЕ** (на 2026-08-04, голова D39.97). +> - **ПАК СТАНДАРТОВ + ДОФИКС ARCHGUARD ПРИНЯТЫ И ЗАЛЕНДЕНЫ (D39.96/97, 03–04.08; семь pathspec-коммитов `e8d4ac0`…`0e64efe`). Строки 107/112/117 ЗАКРЫТЫ.** Репо на стандартах: `.golangci.yml` 0 issues · `make battery` = единая точка входа · типовые анализаторы archguard (38 посадок, 9/9 мутаций, семь осознанных пропусков — 121(д)) · x/net 0.57 (живая проба PASS 3/3, `reasoning_content` подтверждён на проводе, $0.0053) · пять шиппинг-конфигов на `low`. **Задачи №12:** (1) выдать промт пака экрана 46 — D39.94 п.3 (фикстура 113 первой; денежный шаг ТОЛЬКО с подписью владельца); (2) малый пак tools/go.mod — решение принято D39.97 п.4 (строка 118). **ОТКРЫТО НА ВЛАДЕЛЬЦЕ:** 116 (порог «≥4/5 при N=5» подан) · строка 5 (находки прерванного банк-ресёрча или пере-запуск; промт подрезать до $1.20) · мини-проба 44 «low+16k» (~$0.05) · подпись денежного шага 46. **Вахта:** маппинг эффорта `deepseek-v4-pro` «early August 2026» (реестр 108, триггер >05.08 — БЛИЗКО). **Источник истины по РЕШЕНИЯМ — `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`, так чтобы четвёртое такое место не могло появиться молча. **Пак ИСПОЛНЕН И ПРИНЯТ (D39.91, код `553f1a3`; промт заархивирован)** — работы A+проба зелёные, работа B стала паком экрана 46 (дизайн заморожен D39.92 п.1+D39.93), прогон C не стартовал ⇒ строка 16 ЖИВА и оси голоса 13б по-прежнему без данных. Текущий бэкендный промт — `BACKEND_REPO_STANDARDS_SESSION_PROMPT.md` (D39.92: линтер/CI/бампы + пять конфигов на `low`). Перекупок нет (D39.63). -> - **Горизонт (D39.62/67, освежён D39.95):** ре-проба flash ИСПОЛНЕНА и строка 74 закрыта (D39.86/91; порог 6/6 → пере-ратификация выборочным, строка 116; пробы 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 · строка 112 перед любым платным прогоном на шиппинг-конфигах (до лендинга этапа 0 промта стандартов они покупают пустые ответы). -> - **Стек:** draft deepseek-v4-flash thinking-ON (+банкнота) **⚠0731** → терминолог (та же модель, батчи, экран `target_script`) → editor deepseek-v4-pro БИЛИНГВ ИНТЕРИМ (⚠ вендор АНОНСИРОВАЛ смену маппинга эффорта pro «early August 2026» — вахта в реестре 108; glm-5 резерв) → судья gemini (Ф2, полигон); канал B Mistral+grok; ~$0.85/ранобэ (D30.4) — пере-калибровка после лендинга 112. -> - **ЕДИНЫЙ БЭКЛОГ — секция «Бэклог» ниже** (одна таблица, единственный трекер; каждая петля обязана иметь диспозицию: решено / отложено-с-записью / отклонено; ведёт оркестратор). **СЧЁТ ОЧЕРЕДИ на 02.08 (D39.90, обновлять при каждом лендинге; считать скриптом по таблице, не на глаз):** всего **95** строк · зона бэкенд **46** строго / **61** широко · **блокеров очереди 0** (104 → «на приёмке») · «скоро» **13** (2·4·5·18·46·49·55·95·107·108·109·112·113); остальное «когда-нибудь». ⚠ **Счёт — НИЖНЯЯ граница долга, а не потолок:** трекер содержит только замеченное, и 02.08 дважды за $0 свежие глаза вытащили из кода дефекты, которых в нём не было (релей фронта → строки 99/100/102; приёмочное ревью → третий шов `repair.go:384` в 104 и честность `quality.go:436` в 105). Лента ✅ выше — про ЗАКРЫТЫЕ паки, читать её как «долга нет» неверно (разбор — вопрос владельца 02.08, D39.89). +> - **Курс (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`, так чтобы четвёртое такое место не могло появиться молча. **Пак ИСПОЛНЕН И ПРИНЯТ (D39.91, код `553f1a3`; промт заархивирован)** — работы A+проба зелёные, работа B стала паком экрана 46 (дизайн заморожен D39.92 п.1+D39.93), прогон C не стартовал ⇒ строка 16 ЖИВА и оси голоса 13б по-прежнему без данных. Пак стандартов (`BACKEND_REPO_STANDARDS_SESSION_PROMPT.md`, D39.92) исполнен — приёмка и гейты лендинга в верхнем буллете (D39.96). Перекупок нет (D39.63). +> - **Горизонт (D39.62/67, освежён D39.95):** ре-проба flash ИСПОЛНЕНА и строка 74 закрыта (D39.86/91; порог 6/6 → пере-ратификация выборочным, строка 116; пробы 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 (⚠ + x/text-таблицы Unicode 17 тем же тулчейном — строка 119/реестр 108) · проба провода исполнена и 117 закрыта (D39.97), конфиги 112 залендены — платные прогоны разблокированы. +> - **Стек:** draft deepseek-v4-flash thinking-ON (+банкнота) **⚠0731** → терминолог (та же модель, батчи, экран `target_script`) → editor deepseek-v4-pro БИЛИНГВ ИНТЕРИМ (⚠ вендор АНОНСИРОВАЛ смену маппинга эффорта pro «early August 2026» — вахта в реестре 108; glm-5 резерв) → судья gemini (Ф2, полигон); канал B Mistral+grok; ~$0.85/ранобэ (D30.4) — 112 залендена (D39.97), пере-калибровка цены при следующем платном прогоне. +> - **ЕДИНЫЙ БЭКЛОГ — секция «Бэклог» ниже** (одна таблица, единственный трекер; каждая петля обязана иметь диспозицию: решено / отложено-с-записью / отклонено; ведёт оркестратор). **СЧЁТ ОЧЕРЕДИ на 04.08 (D39.97, скриптом по таблице; обновлять при каждом лендинге):** всего **101** строка · зона бэкенд **52** строго / **65** широко · **блокеров очереди 0**, платные прогоны разблокированы (117 закрыта) · «скоро» **17** (2·4·5·18·46·49·55·95·108·109·113·114·116·118·119·120·121); остальное «когда-нибудь». ⚠ **Счёт — НИЖНЯЯ граница долга, а не потолок:** трекер содержит только замеченное, и 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; правки — только через оркестратора) @@ -111,16 +111,31 @@ | 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 | | 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` вместо резолва по путям импорта), плюс каждый следующий инвариант породит ещё один такой обход. ⚠ **ТЕСТОВЫЙ ДОМ — СЛЕДСТВИЕ ЗАМЕРА, А НЕ НЕБРЕЖНОСТИ (отчёт §5.5, проверено запуском; моя формулировка «дом неверный» СНЯТА как над-клейм):** форма «архитектурное правило обычным тестом» — стандарт stdlib (`go/build/deps_test.go` держит так граф зависимостей, `go/types/errorcalls_test.go` — `ast.Inspect` по своим исходникам; аналог в Java — ArchUnit), а альтернатива **не проходит наше ограничение «падать на обычной батарее»**: `go test -vet=<свой анализатор>` → «-vet argument must be a supported analyzer», `GOFLAGS=-vettool` при `go test` игнорируется. Цена перехода на `x/tools/go/analysis` названа: он тянет `x/net` 0.26.0 → 0.54.0, **а `x/net/http2` — наш транспорт к провайдерам**. `golangci-lint` = 38.7 МБ бинарь и первый в проекте `.golangci.yml`; `exhaustruct` (инструмент ровно под исходный класс бага) даёт 16 находок, 15 из них в тестах. Настоящая развилка: принять ли бамп `x/net` ради типовой информации · заводить ли CI · остаётся ли гард тестом. Индустриальная форма — analyzer на `golang.org/x/tools/go/analysis` (+`multichecker`, запуск `go vet -vettool=` и в CI), где алиас/дот-импорт закрываются ПО ПОСТРОЕНИЮ. Отдельная половина вопроса: **в репозитории нет ни `.golangci.yml`, ни `Makefile`, ни CI-воркфлоу** (проверено) — батарея гоняется руками каждой сессией. ⚠ Владелец прав в опасении: включение стандартного набора на ~200 файлах даст большой хвост находок ⇒ **первый шаг работы — $0-ЗАМЕР** (прогнать набор в report-only и посчитать находки по правилам), и только потом решать состав + режим внедрения (baseline «только новый код» против big-bang) · **+Д7 (приёмка D39.91):** давний БАЙТОВЫЙ гард `TestProviderEgressSeamIsSingle` (свой корень обхода, свой словарь исключений) свести с AST-обходом в ОДИН тем же решением формы **02.08 вечер (D39.92): САНКЦИЯ ЦЕЛИКОМ** («по стандартам индустрии»; анти-хак-правило в промте) — промт выдан: `BACKEND_REPO_STANDARDS_SESSION_PROMPT.md` (этапы 0/A–E, три СТОП-пинга) | бэкенд | скоро (промт выдан, ждёт сессии) | пак по промту → приёмка оркестратора | D39.90, отчёт EFFORT_HANDLE §1.3 | -| 112 | ⚠ **ПЯТЬ ШИППИНГ-КОНФИГОВ РЕПО ВСЁ ЕЩЁ НЕСУТ no-op `reasoning: "off"` НА ЧЕРНОВОЙ СТАДИИ — решение владельца (б) до них НЕ доехало (Д10 отчёта, D39.90).** Адреса проверены: `configs/pipeline-c1.yaml:49` · `pipeline-c2.yaml:26,39` · `pipeline-arm-mistral.yaml:30` · `pipeline-arm-glm.yaml:34` · `pipeline-arm-deepseek-pro.yaml:34`. Это ровно тот no-op, который отправил прогон в стену 0/9: на deepseek `off` = «не слать ничего» ⇒ вендор-дефолт `high`. Сессия сознательно их не трогала, потому что **правка двигает снапшот всем, кто этими конфигами пользуется** (перекупка), и вынесла вопрос наверх. ⚠ Не путать со стендом: правился только `coldrun-b/reprobe/bank-low/pipeline.yaml`, боевой `coldrun-b/pipeline.yaml` тоже НЕ тронут. **Решить: применять ли (б) к шиппинг-конфигам, каким именно, и когда платить перекупку** (на свежей книге — $0). ⚠ В `arm-glm:43` и `arm-deepseek-pro:43`/`c1:77` `off` стоит на РЕДАКТОРЕ осознанно — это другой случай, не трогать без отдельного разбора **02.08 вечер (D39.92): САНКЦИЯ — править все пять, перекупка старых книг при следующем прогоне принята** | бэкенд | скоро (этап 0 промта `BACKEND_REPO_STANDARDS_SESSION_PROMPT.md`) | правка данных + батарея | D39.87, D39.90, EFFORT_HANDLE Д10 | | 113 | **Запас боевого гейта не зафиксирован тестом, а харнесс, давший число, УДАЛЁН (Д-хвост D39.90).** Числа «18 из 20 · 0 ложных на 1055 · запас 13× (0.0117 против 0.15)» и «санитайзер поймал бы английский черновик» получены ВРЕМЕННЫМ тестом в пакете pipeline (`splitBanknote`+`StripThink`+`sourceScriptShare`), который сессия удалила после снятия. Число ушло в контракт (строка 46), воспроизвести его нечем. **Делать:** корпус-фикстура в репо (~20 off-target + ~40 здоровых, с движковой предобработкой; снапшот НЕ двигает) + регресс-тест на реальный запас — это база, которую обязано побить любое предложение по 46. СТОП, если фикстура не воспроизводит 18/20 при 0 FP, или если запас меньше 3× | бэкенд | скоро (перед любой правкой по строке 46) | $0 фикстура + регресс-тест | D39.90, EFFORT_HANDLE §5.4 шаги 1–2, §7 | | 114 | **Конфиго-слой ручки эффорта: два дешёвых хвоста приёмки (вне снапшота, $0 прогонов).** (а) **Д4 отчёта:** `gates.terminology.target_script` НЕ сверяется с `book.target_lang` — `target_lang: ru` + `target_script: Latin` грузится чисто и **ИНВЕРТИРУЕТ** банковский экран (ловит целевой, пропускает чужой); сверка при загрузке против `lang.LangScripts(TargetLang)` — тот же дата-план, что у экрана строки 46, громкий отказ на несовпадении. (б) **Находка-2 приёмки:** стейл-доккоммент `capability.go:78` — у константы `ReasoningExtraBodyDisable` до сих пор «effort "" leaves the provider default», противореча проводу (`applyToBody` мержит disable на `""`, комментарий в теле arm это прямо объясняет) и починенному `ThinksOnWire`; однострочник тем же касанием | бэкенд | скоро (мелкий пак или попутно со строкой 46) | правка Go, снапшот не двигает | D39.91, EFFORT_HANDLE Д4 | | 115 | **`//go:embed` целевых данных — ЯВНЫЙ список файлов: новая ЦЕЛЬ требует правки Go (Д6 отчёта).** `internal/lang/embedded.go:22` перечисляет файлы поимённо, `CompileCheckers` паникует при неполном файле цели ⇒ на канон-вопрос «заработает ли пара, которой в репо НЕТ, без правки Go» ответ сегодня **НЕТ** — дыра в ратифицированной «ФАЗЕ 2 ОБЩНОСТИ ✅» (D39.64), и она не про язык, а про строку эмбеда. Решить форму: `embed data/*` (и как манифест фолдится в `EmbeddedVersion`, чтобы НЕ перекупать чужие пары) против явного списка как осознанного гейта полноты данных цели | оркестратор → бэкенд | когда-нибудь (триггер: первая новая целевая пара; учтён в реестре 108) | отдельное решение | D39.91, EFFORT_HANDLE Д6, D39.64 | | 116 | **Порог классификатора «6/6» ратифицирован для ОДНОГО вызова, не для выборки — и на рекомендованном `low` риг N=5 КРАСНЫЙ: 4/5 (Д8 отчёта).** Контракт обязан стать выборочным («≥4/5 при N=5» или иная форма — решение) ДО применения (б) к любому конфигу, иначе рекомендация `low` противоречит собственному приёмочному числу. Честная граница чисел (D39.86, подтверждена приёмкой по сырью): 2 из 6 термов (元石/灵泉) стоят дословно в промпте классификатора = припоминание; падение `low` — ровно по дискриминирующему подмножеству (1/4 против 4/4); единственный промах — вызов на 91 completion-токене (модель не подумала), уровень ни при чём **02.08 вечер: рекомендация подана владельцу — «≥4/5 прогонов N=5 достигают 6/6»** (альтернатива жёстче: 4/4 по дискриминирующему подмножеству без термов-припоминаний); ждёт слова | владелец → оркестратор | скоро (112 уже санкционирована — порог не должен отстать) | пере-ратификация порога, $0 | D39.91, EFFORT_HANDLE Д8, D39.86 | -| 108 | **Реестр ЗАГЕЙЧЕННЫХ ТРИГГЕРОВ + норма закрытия «по нужности».** ⚠ Первый жилец реестра, найденный тем же лендингом: **сиблинг-угроза экрана целевого языка** — выход на языке, БЛИЗКОМ к целевому (украинский/болгарский для ru): ни одного события не наблюдалось, но если появится, дискриминатор — плотность РУССКО-ЭКСКЛЮЗИВНЫХ букв (ы/э/ё) НИЖЕ ожидания, а НЕ замыкание алфавита (`EFFORT_HANDLE §5.4` шаг 8). Шесть остальных реопенов живут только в телах D-нот и не имеют места, где их поднимут: **МАСШТАБ** (uniformity-пасс D12 · эмбеддинг A7/D2 «реопен = измеренный recall-разрыв, только batch-time лейн» · STITCH «бюджет ИЛИ измеренный эффект размера инъекции» · канон-пин серий) · **вторая пара живьём** (C-триггер softsign-decl · автономная Decl-эмиссия) · **вторая книга того же жанра** (жанровый shared-слой) · **первая traditional-книга** (probe-литералы 时辰/千万/数十万 цельным дата-батчем) · **появление Go-кода платформы** (`go.work` — ⚠ `platform/go.mod` УЖЕ заведён, триггер наступил) · **перед стройкой fix-8** (ёлочный экстрактор атрибуции + корпус-замер). **+Два жильца приёмки D39.91:** Д5 — enum эффорта провайдер-слеп (`medium` на DeepSeek не определён, `max`/`xhigh` недостижимы; пер-модельную таблицу решено НЕ строить — механизм без носителя качества/денег, misconfig ограничен бюджетами и назван в доккомменте `ValidReasoningEffort`; триггер: первый живой инцидент кривого поведения уровня на проводе) · Д9 — аддитивные провайдеры отказываются бэнк/repair-гейтам, блок не несёт `reasoning_max_tokens` (fail-closed в лоадере; триггер: первая потребность гейта в аддитивной модели). **+Вахта D39.92:** вендор анонсировал смену МАППИНГА эффорта `deepseek-v4-pro` «early August 2026» ⇒ квирк 3а («low→high, эффорт не настраивается») может устареть (триггер: аномалия редакторского арма ИЛИ дата > 05.08 ⇒ пере-проба маппинга + сверка changelog; абсорбция в `00-provider-quirks.md` — полигоном). Норма D39.66 «каждое отложено обязано ТЕМ ЖЕ лендингом получить строку или явное закрытие» нарушена ≥6 раз ПОСЛЕ собственной ратификации, и класс потерь узкий — теряются именно ЗАГЕЙЧЕННЫЕ РЕОПЕНЫ. Лечение: короткий реестр триггер→что вернётся→источник, сверяемый на каждом переходе горизонта (горизонт расписан до Ф3, точки сверки известны заранее) | оркестратор | скоро ($0, гигиена трекера) | завести реестр + сверку в норму лендинга | D39.66, D39.90 | +| 108 | **Реестр ЗАГЕЙЧЕННЫХ ТРИГГЕРОВ + норма закрытия «по нужности».** ⚠ Первый жилец реестра, найденный тем же лендингом: **сиблинг-угроза экрана целевого языка** — выход на языке, БЛИЗКОМ к целевому (украинский/болгарский для ru): ни одного события не наблюдалось, но если появится, дискриминатор — плотность РУССКО-ЭКСКЛЮЗИВНЫХ букв (ы/э/ё) НИЖЕ ожидания, а НЕ замыкание алфавита (`EFFORT_HANDLE §5.4` шаг 8). Шесть остальных реопенов живут только в телах D-нот и не имеют места, где их поднимут: **МАСШТАБ** (uniformity-пасс D12 · эмбеддинг A7/D2 «реопен = измеренный recall-разрыв, только batch-time лейн» · STITCH «бюджет ИЛИ измеренный эффект размера инъекции» · канон-пин серий) · **вторая пара живьём** (C-триггер softsign-decl · автономная Decl-эмиссия) · **вторая книга того же жанра** (жанровый shared-слой) · **первая traditional-книга** (probe-литералы 时辰/千万/数十万 цельным дата-батчем) · **появление Go-кода платформы** (`go.work` — ⚠ `platform/go.mod` УЖЕ заведён, триггер наступил) · **перед стройкой fix-8** (ёлочный экстрактор атрибуции + корпус-замер). **+Два жильца приёмки D39.91:** Д5 — enum эффорта провайдер-слеп (`medium` на DeepSeek не определён, `max`/`xhigh` недостижимы; пер-модельную таблицу решено НЕ строить — механизм без носителя качества/денег, misconfig ограничен бюджетами и назван в доккомменте `ValidReasoningEffort`; триггер: первый живой инцидент кривого поведения уровня на проводе) · Д9 — аддитивные провайдеры отказываются бэнк/repair-гейтам, блок не несёт `reasoning_max_tokens` (fail-closed в лоадере; триггер: первая потребность гейта в аддитивной модели). **+Вахта D39.92:** вендор анонсировал смену МАППИНГА эффорта `deepseek-v4-pro` «early August 2026» ⇒ квирк 3а («low→high, эффорт не настраивается») может устареть (триггер: аномалия редакторского арма ИЛИ дата > 05.08 ⇒ пере-проба маппинга + сверка changelog; абсорбция в `00-provider-quirks.md` — полигоном). Норма D39.66 «каждое отложено обязано ТЕМ ЖЕ лендингом получить строку или явное закрытие» нарушена ≥6 раз ПОСЛЕ собственной ратификации, и класс потерь узкий — теряются именно ЗАГЕЙЧЕННЫЕ РЕОПЕНЫ. Лечение: короткий реестр триггер→что вернётся→источник, сверяемый на каждом переходе горизонта (горизонт расписан до Ф3, точки сверки известны заранее) · **(D39.96)** тулчейн go1.27 переключит x/text на таблицы Unicode 17.0.0 МОЛЧА (`xTextVersion` пинит go.mod-строку, не таблицы) — триггер: любое движение тулчейна к 1.27 ⇒ строка 119 ПЕРВОЙ · **(D39.96)** CI-воркфлоу Forgejo (удалёнка 10.0.3, раннер не подтверждён; решение владельца 03.08 — не писать) — триггер: появление раннера ⇒ файл workflow; до того точка входа `make battery` | оркестратор | скоро ($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 | +| 118 | **tools/go.mod — РЕШЕНИЕ ПРИНЯТО (D39.97 п.4): строить отдельным малым паком.** `cmd/tmvet`+`internal/archguard` → отдельный модуль (`backend/tools/`); `make battery` гоняет оба модуля; `tool`-директива Go 1.24 НЕ решает (MVS общий). Выигрыш: бамп инструментов физически не двигает x/net/x/text. Sqlite 1.55 остаётся (D39.97 п.4) | бэкенд | скоро (до следующего бампа зависимостей) | малый пак по D39.97 п.4 | D39.96 п.6, D39.97 | +| 119 | **x/text-детерминизм: вердикт-несущие вызовы НЕ свёрнуты в версии (находки-5/6 приёмки).** `SanitizerVersion` не сворачивает ничего x/text-ного, а `detectCJKLeak` зависит от `width.Fold` (`sanitizer.go:211,687`) — смена x/text перевернула бы вердикт БЕЗ смены снапшота; `ExportNormalize` меняет экспортные байты вне хешей (`sanitizer.go:709`); `xTextVersion` пинит строку go.mod, НЕ скомпилированные таблицы — тулчейн go1.27 переключит x/text на Unicode 17.0.0 МОЛЧА (`tables17.0.0.go //go:build go1.27`; жилец реестра 108). Делать: явные версии-свёртки + механическую сверку «таблицы↔константа» вместо совпадения | бэкенд | скоро | правка версий-свёрток + тест | D39.96 п.6, отчёт §5 находки-5/6 | +| 120 | **`buildCheckers` жёстко берёт `lang.Load(root,"zh","ru")`, бейзлайны ключуются по классу, не по паре (§7-8) — приезд ja-ru требует правки Go, против мандата общности §0.1.** Родня строки 115 (явный embed-список целей) — брать одним касанием | бэкенд | скоро | правка Go + тест на паре-которой-нет | D39.96 п.6, отчёт §7-8 | +| 121 | **archguard v2 (посадки приёмки D39.96 + §7-12/13 + §7-9). ⚠ Пункты (0а)/(0б) — РЕГРЕССИЯ против снесённого байт-гарда; дофикс ИСПОЛНЕН и принят D39.97 — (0а)/(0б)/(а) ЗАКРЫТЫ, плюс блокер type-param, ось имени и ложное срабатывание сверх промта; остаток строки — (б)/(в)/(г)/(д).** (0а) egressseam пропускает пакетную `llm.Complete(...)`: nil-`Selections` → молчаливый выход (`archguard.go:240-242`; фикс — fallback на `Uses`); (0б) пропускает интерфейс с llm-типами внутри композита (`Complete(ctx, []llm.LLMRequest)…` — `touchesPkg` не рекурсивен, `:79-82`); старый регекс `.Complete(` ловил обе формы; комменты «cannot be hidden» (`:250-253` и фикстура) фальсифицированы — переписать честно; (а) `runRequestSeam` обходит ТОЛЬКО `*ast.CompositeLit` (`archguard.go:197`): `var r pipeline.Request`+присваивание и `new(pipeline.Request)` проходят МОЛЧА — подтверждено на реконструкции: дыра ОБЩАЯ со старым гардом (не регрессия); фикс ~10 строк: симметрия ValueSpec/CallExpr со stage-сеамом + негативная фикстура, документирующая осознанные пропуски; (б) класс «встраивание · make+присваивание · дженерик-ноль» закрывается не свитчем, а ТИПОМ (нулевое значение `config.Stage` непригодно вне пакета); (в) политика build-тегов vet (сегодня default+live; чужой тег невидим — других в репо нет); (г) кандидат 4-й анализатор границы импортов — `backend/README.md:3` заявляет «проверяет `go list -deps`», что не автоматизировано ничем; (д) семь осознанных пропусков после дофикса 03.08 (принят D39.97; фикстуры БЕЗ want — покраснеют, когда начнут ловиться): llm.Ask-класс · пара внутри named-обёртки · встраивание/make/generic-zero · `internal/llm` исключён целиком (второй провод внутри адаптеров ловится только ревью) · внешние тест-пакеты · рефлексия (статикой не закрывается) · файлы за третьим сборочным тегом — всё, что закрываемо, закрывается типовым швом (б), не свитчем | бэкенд | скоро (дешёвая половина а) | правка анализатора + посадки | D39.96 п.2/п.6, отчёт §7-9/12/13 | +| 122 | **Гигиена пака стандартов (не-блокеры приёмки).** `TestCheckerLabelsCandidates` — ни одного ассерта (дизайн-REPL в одежде теста) · сообщение `TestMemoryVersionPinsTheUnverifiedRenderRevision` не различает «изменился рендер»/«изменилась нормализация» · Makefile: regex GO_MIN_VERSION пропускает go1.26.0–1.26.3 (патч-уровень не проверяется) · включить `unconvert` (1) и `wastedassign` (2) — дешевле уже включённых по собственному правилу конфига · `.skips.log` не в gitignore (прерванная battery оставляет мусор в дереве) · Fprint-исключение errcheck скоупить на `cmd/` (сейчас весь модуль — будущий писатель файла экспорта получит молча съеденную ошибку) · `w\.Write`-исключение ключуется ИМЕНЕМ receiver-а вопреки собственному принципу конфига · miningstop-исключение глушит текстом весь файл — якорить на функцию · provenance-числа конфига дрейфуют от дерева (293/31/93 против 294/33/91; контрпример «все прод-Close — читатели»: `chunktest/epub.go:51`) · коммент c1 «echo mine unarmed» поправлен дофиксом 03.08 (снят) · инвариант-коммент `httpllm.go:77` «zero wire bytes» — верен для полей пинга, неверен для бампа x/net, который их привёз (находка-4 D39.96) — переписать честно | бэкенд | когда-нибудь | мелкие правки | D39.96 п.6, отчёт §7-6/7, §9 хвост | +| 123 | **Полигон: `jieba==0.42.1` — build-time зависимость артефакта контраста `eval/exp16/data/jieba_dict_general_zh.txt`** (пере-собран бэкенд-сессией 03.08, полный sha256 сошёлся с пином `16-bank-mining.md`); дописать в манифест окружения полигона с пометкой «build-time, не runtime» | полигон | когда-нибудь | строка манифеста | D39.96 п.6, отчёт §7-4/§6 | + +| 124 | **Калибровка снапшота (вопрос владельца 04.08, разбор D39.97 п.5): нацеленность, не агрессивность.** Три оси одним дизайн-паком: (а) недо-чувствительность — вердикт-несущие вызовы x/text не свёрнуты (вход: строка 119); (б) пере-охват — `EmbeddedVersion` фолдит все пары разом → пер-парный хеш (родня 115/120); (в) дешёвая перекупка: `tmctl resnapshot --dry-run` — байт-сверка тел по чекпойнтам (`msgsContentHash`), идентичные юниты пере-привязываются без пере-вызова, платятся только изменившиеся. «Поведенческий отпечаток вместо строки версии» отложен (пол ≠ доказательство) | бэкенд | когда-нибудь (перед МАСШТАБОМ — когда перекупки станут реальными деньгами) | дизайн-пак по D39.97 п.5 | D39.97 | + +## Оркестратор №12 — приёмка дофикса, лендинг всего пака, ответы владельцу (D39.97), 04.08 + +Дофикс archguard + проба приняты короткой приёмкой исполнением (батарея EXIT=0 · деньги дельта $0.000000 · две СВОИ посадки вне карты отчёта, включая method expression — форма отсутствовала и в таблице, и в пропусках, поймана; негативный контроль чист). CONFIRM владельца по `@latest` записан входом приёмки. Весь пак заленден семью pathspec-коммитами (`e8d4ac0` конфиги · `5a97020` дефект-фиксы · `b155da3` механика · `cb368c0` бамп · `6356471` анализаторы · `5a81bff` линт-инфра · `0e64efe` live-проба); фронт коммитил параллельно (`ece94ef`) — pathspec исключил коллизию. Строки 107/112/117 закрыты; оба промта архивированы. Решения: tools/go.mod — строить (118, D39.97 п.4); вопрос владельца о снапшоте разобран — калибровка нацеленности вместо ослабления, три оси одним дизайн-паком (новая строка 124: недо-чувствительность 119 · пер-парный EmbeddedVersion · дешёвая перекупка байт-сверкой). Хвост `httpllm.go:77` → 122. + +## Оркестратор №12 — приёмка пака «стандарты репо» ДВУМЯ пассами (D39.96), 03.08 + +Пасс-1 — шесть верификаторов по клеймам отчёта + 7 своих посадок (нашёл дыру requestseam). Владелец вскрыл метод-дефект пасса-1 («след отчёта»: проверялась истинность названных клеймов, не направление; два экспериментальных клейма приняты со слов; пять «решений владельца» ратифицированы со слов сессии) → пасс-2 из пяти АНТИ-СЛЕДОВЫХ линз: мнение-до-отчёта · поиск вне карты · реконструкция снесённых гардов из HEAD · аудит исключений линтера по коду · независимая репликация клеймов. Итог пасса-2: **регрессия egress-паритета против снесённого байт-гарда (две исполнимые формы — снос в текущем виде нарушает букву промта)** · мисхарактеризация «порядка HPACK-заголовков» в находке-4 (рандомен под обеими версиями; реальная дельта — только SETTINGS) · клейм x/text-эквивалентности реплицирован независимо · «не регрессия requestseam» подтверждена исполнением на реконструкции. Вердикт: пак принят по качеству кода, лендинг гейчен тремя решениями владельца (проба 117 · confirm пяти санкций · развилка этапа E) — D39.96 п.7. Урок закреплён нормой «анти-паттерны приёмки» в `ORCHESTRATOR_SESSION_PROMPT.md`. Отчёт с ревью-шапкой — `archive/reports/REPO_STANDARDS_2026-08-03.md`. + ## Оркестратор №11 — ЗАКРЫТИЕ СЕССИИ И ПЕРЕДАЧА №12 (D39.94), 02.08 Итог сессии: приёмка пака ручки эффорта исполнением — принят, заленден `553f1a3`, строка 104 закрыта (D39.91); решения владельца ратифицированы: 46 → closed-set «не тот язык» изолированным пакетом с именованными причинами (D39.92 п.1 + D39.93), 107 → санкция целиком, промт `BACKEND_REPO_STANDARDS_SESSION_PROMPT.md` выдан, 112 → санкция (этап 0 промта); вендор-сверка DeepSeek: 0731 не деградация, а смена политики дефолта thinking=high; вахта на смену маппинга v4-pro (реестр 108). Преемнику: приёмка пака стандартов + выдача промта экрана 46. На владельце: 116 · строка 5 · мини-проба 44 · подпись шага 6 по 46. Очередь: 97 строк · «скоро» 15 · блокеров 0. Пост-скриптум закрытия: `0d1c08f` — коммит `START_PROMT.MD` ПО ЯВНОМУ СЛОВУ владельца (разовое исключение из гардрейла, прекоммит-гейт обойдён `--no-verify` осознанно; правило «не коммитить» в силе); V5-п.2 из диффа уже разобран как ПТ-23, невидимых требований нет. Второй речек владельца («перечитай онбординг») добил хвосты: строка 74 закрыта (её буква «закрывается приёмкой пака» исполнилась в D39.91), промт EFFORT_HANDLE заархивирован, карта README и буллеты Курс/Горизонт/Стек освежены — D39.95; очередь после закрытия 74 — 96 строк. diff --git a/docs/README.md b/docs/README.md index 9665aae1..c887a4f9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -15,7 +15,7 @@ - `experiments/` — эмпирика полигона: [00-provider-quirks.md](experiments/00-provider-quirks.md) — **читать перед любым вызовом провайдера**; [08-cost-model-v2.md](experiments/08-cost-model-v2.md) — денежная модель; [09-pilot-protocol.md](experiments/09-pilot-protocol.md) — пилот Ф2.5; остальные 01–16 — отчёты закрытых экспериментов (судьба — в баннерах/D-логе). - `research/` — фактура ресёрчей 01–22; у принятых — ревью-шапки, часть тел под ⚠ superseded: **читай баннер прежде содержимого**. Ключевые для навигации: 15 голос · 16 ридер-IDE · 17 внешняя критика · 18 рычаги качества · 19 нарезка · 20 банк-майнинг · 21 обзор транспорта · 22 доменные харнессы · 23 шов движок↔платформа (читать перед любым кодом стыка). - [PROGRESS.md](PROGRESS.md) — журнал: CURRENT-STATE + **ЕДИНЫЙ БЭКЛОГ** (единственный трекер) + живой хвост хроники. НЕ источник решений. -- Активные хендофф-промты сессий (состав обновляется при каждом лендинге — норма D39.80): [ORCHESTRATOR_SESSION_PROMPT.md](ORCHESTRATOR_SESSION_PROMPT.md) (роль/нормы; состояния не дублирует) · [POLYGON_PACKAGE4_SESSION_PROMPT.md](POLYGON_PACKAGE4_SESSION_PROMPT.md) (полигон, отложен). [BACKEND_REPO_STANDARDS_SESSION_PROMPT.md](BACKEND_REPO_STANDARDS_SESSION_PROMPT.md) (**текущий бэкендный**, D39.92: линтер/CI/Makefile · бамп зависимостей с живой пробой провода · гарды→analyzer с паритетом посадок; этап 0 = пять шиппинг-конфигов на `low`, строка 112; предшественник — ручка эффорта — исполнен, ПРИНЯТ D39.91 и заархивирован) · [BANK_ARBITRATION_RESEARCH_SESSION_PROMPT.md](BANK_ARBITRATION_RESEARCH_SESSION_PROMPT.md) (**ресёрч+полигон**, D39.89; ⚠ заход 02.08 ПРЕРВАН владельцем, находки в дерево не попали — перед пере-выдачей промт ПОДРЕЗАТЬ по D39.90 п.5: §3-A+B1+B3, B2 → под-проба, §5-C отложен, потолок $1.20; вопрос владельцу о находках прерванной сессии открыт, D39.94 п.4). Фронт-промт — в чужой зоне `frontend/docs/`. +- Активные хендофф-промты сессий (состав обновляется при каждом лендинге — норма D39.80): [ORCHESTRATOR_SESSION_PROMPT.md](ORCHESTRATOR_SESSION_PROMPT.md) (роль/нормы; состояния не дублирует) · [POLYGON_PACKAGE4_SESSION_PROMPT.md](POLYGON_PACKAGE4_SESSION_PROMPT.md) (полигон, отложен). **Бэкендного активного промта НЕТ** — пак стандартов + дофикс archguard исполнены, приняты и залендены (D39.96/97, 04.08; промты в `archive/prompts/`); следующие бэкендные: пак экрана 46 (промт ждёт выдачи по D39.94 п.3) и малый пак tools/go.mod (строка 118, D39.97 п.4) · [BANK_ARBITRATION_RESEARCH_SESSION_PROMPT.md](BANK_ARBITRATION_RESEARCH_SESSION_PROMPT.md) (**ресёрч+полигон**, D39.89; ⚠ заход 02.08 ПРЕРВАН владельцем, находки в дерево не попали — перед пере-выдачей промт ПОДРЕЗАТЬ по D39.90 п.5: §3-A+B1+B3, B2 → под-проба, §5-C отложен, потолок $1.20; вопрос владельцу о находках прерванной сессии открыт, D39.94 п.4). Фронт-промт — в чужой зоне `frontend/docs/`. - Зоны фронта (чужие, читать при касании стыка; каждая ведёт СВОЙ зонный бэклог — единый бэклог их строк не принимает, D39.84): [../frontend/](../frontend/) — веб-интерфейс: промт фронт-сессий S0–S7 + [STACK_DECISIONS.md](../frontend/docs/STACK_DECISIONS.md) (пины версий точными числами и ловушки, сверены с вебом 02.08) + [BACKLOG.md](../frontend/docs/BACKLOG.md) · [../platform/](../platform/) — SaaS control plane: README-заглушка + [BACKLOG.md](../platform/BACKLOG.md). - `archive/` — история ([правила архива](archive/README.md)): закрытые промты (`prompts/`) · отчёты с ревью-шапками (`reports/` — на них ссылаются приёмки) · исполненные арх-доки (`architecture/`) · слайсы хроники `PROGRESS-*.md`. Инструкции оттуда не исполнять. - Диаграммы: [../backend/docs/components.puml](../backend/docs/components.puml) · [../backend/docs/pipeline.puml](../backend/docs/pipeline.puml) — дом рядом с кодом (D39.80), правятся бэкендом одним коммитом с кодом; вручную НЕ рендерить (владелец смотрит PlantUML-расширением VS Code). diff --git a/docs/architecture/05-decisions-log.md b/docs/architecture/05-decisions-log.md index f670de1d..55a54848 100644 --- a/docs/architecture/05-decisions-log.md +++ b/docs/architecture/05-decisions-log.md @@ -1,4 +1,4 @@ -# Журнал решений оркестратора — контракт D1–D39.95 (развязки 04.07 · пакеты 09–10.07 · приёмка/качество-первым/пивот/эмпирика 11–12.07 · арх-ресет+стройка пере-прогонного стека 13–19.07) +# Журнал решений оркестратора — контракт D1–D39.97 (развязки 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`. @@ -1388,3 +1388,37 @@ API-529-долг закрыт: 8-осевой refute-by-default воркфлоу ## D39.95 — Пост-клоуз гигиена по речеку владельца: онбординг-хвосты добиты (02.08, ночь). ✅ Речек владельца «перечитай онбординг» вскрыл хвосты, пропущенные лендингами №11: (1) **строка 74 ЗАКРЫТА** — её собственная буква «закрывается приёмкой этого пака» исполнилась в D39.91, а строка осталась в таблице; развилка решена (б) ещё D39.87, обе половины замера исполнены (флор-фальсификация · low-оживление), остатки давно живут в именованных строках: конфиги → 112 · экран → 46 · холодный прогон → 16 · число флора → 44; очередь после закрытия — **96 строк** (счёт D39.94 «97» устарел этой нотой). (2) Промт `BACKEND_EFFORT_HANDLE` заархивирован с баннером приёмки, карта промтов README обновлена (текущий бэкендный — `BACKEND_REPO_STANDARDS`, банк-ресёрч помечен прерванным с диспозицией подрезки). (3) Буллеты CURRENT-STATE «Курс»/«Горизонт»/«Стек» освежены: ре-проба 74 — исполнена, не будущее; стоячее ограничение перед платными прогонами теперь — строка 112 (шиппинг-конфиги до лендинга покупают пустые ответы); «editor v4-pro вендором НЕ тронут» дополнено анонсом смены маппинга (вахта 108). (4) Шапка-диапазон этого файла и счётчик ролей в промте оркестратора доведены до D39.95. Урок в копилку №12: закрытие строки обязано триггерить греп по её НОМЕРУ во всех живых доках — буквы «закрывается X» в чужих строках и буллетах не закрываются сами. + +## D39.96 — ПРИЁМКА пака «стандарты репо» (строки 107 · 112 · Д7, оркестратор №12), ДВА ПАССА: пак принят по качеству кода УСЛОВНО, лендинг ГЕЙЧЕН тремя решениями владельца; найдена регрессия egress-паритета, запрещающая снос байт-гарда по букве промта (03.08). ⏳ + +**Мандат — D39.92 п.2–3, задача №1 хендоффа D39.94. Отчёт: `archive/reports/REPO_STANDARDS_2026-08-03.md` (ревью-шапка).** Приёмка шла ДВУМЯ пассами: пасс-1 (шесть верификаторов по клеймам отчёта) и — после вмешательства владельца, вскрывшего «след отчёта» как метод-дефект — пасс-2 из пяти АНТИ-СЛЕДОВЫХ линз (мнение до чтения отчёта · поиск дефектов вне его карты · реконструкция снесённых гардов из HEAD · аудит исключений линтера по коду · независимая репликация экспериментальных клеймов). Всё ниже — итог обоих пассов; расхождения пасс-1 ↔ пасс-2 названы явно как урок. + +**1. Ядро подтверждено исполнением (оба пасса, $0).** Батарея: `make tools-check` + `make battery` EXIT=0 (real 1m25s на тёплом кэше) · golangci-lint 2.12.2 **0 issues** (сырой uncapped errcheck воспроизведён точно: 413; ⚠ методологическая грабля — без `--max-issues-per-linter=0 --max-same-issues=0` no-config-режим молча режет к 50) · vet оба тег-набора с `-vettool` · 15 пакетов ok `-race` · скип ровно один. Конфиги: ровно 5 флипов черновиков; находка-1 (адрес c2:39 из промта = judge на glm-5) подтверждена кодом `models.yaml:191–194` + `capability.go:155–168`; редакторские/судейские `off` целы. Бамп: версии и lockstep-пины сверены; голден-дифф пере-выведен независимо — двигаются ТОЛЬКО хеш-поля, атрибуция установлена форензикой пасса-2: **голден сдвинут исключительно пином x/text (`norm.go:69`), не флипом конфигов и не x/net** (голден живёт на fake-model). Код-дифф: все 9 дефект-фиксов §2 подтверждены, посторонних правок нет, `//nolint` в дереве 0, зеленения-хаков нет. + +**2. Экспериментальные клеймы — РЕПЛИЦИРОВАНЫ независимо (пасс-2; пасс-1 принял их со слов отчёта — это была ошибка приёмки, вскрытая владельцем).** (а) Эквивалентность x/text 0.38↔0.40 ПОДТВЕРЖДЕНА с нуля и шире спецификации: все скаляры Unicode × {NFC, NFKC, width.Fold} + битый UTF-8 + меж-рунные пары/хангыль + энкодеры GB18030/GBK/UTF-16 (наш `ingest.go`) — три независимых SHA-256 идентичны под обеими версиями. (б) h2-фингерпринт: появление `SETTINGS_MAX_FRAME_SIZE=16384` ПОДТВЕРЖДЕНО на байтах фреймов (свой TLS+ALPN стенд, копия `keepAliveHTTPClient`); набор/значения заголовков и тело байт-идентичны. ⚠ **Поправка принятого клейма: «порядок HPACK-заголовков изменился» — МИСХАРАКТЕРИЗАЦИЯ** (отчёта И пасса-1): порядок обычных заголовков рандомен per-request под ОБЕИМИ версиями (map-итерация в net/http), стабильного «до/после» не существует — опираться на него не мог никто; стабильны псевдо-заголовки и хвост. Дельта фингерпринта = только SETTINGS-раскладка. Непроверенным осталось (честная граница редукции): прокси-туннель CONNECT, CONTINUATION/PING, TLS-слой — закрывается живой пробой (п.5). + +**3. Посадки приёмки в гарды: пасс-1 — 7 своих (6/7 CAUGHT); пасс-2 добавил реконструкцию старых гардов из HEAD и НОВЫЕ посадки вне карты отчёта. Итог по осям:** (а) **Stage-сеам — прирост без регрессий:** двойная цепь алиасов: старый гард ловил только ПЕРВОЕ звено (одна точка отказа), новый — все три узла; конверсия из 17-полевого близнеца ловится; негативные контроли чисты. (б) **Request-сеам — дыра ОБЩАЯ с предшественником, подтверждено исполнением на реконструкции:** `var r pipeline.Request`+присваивание и `new(pipeline.Request)` проходят ОБА поколения (контроль чувствительности: hoisted-литерал старый гард ловит) — клейм пасса-1 «не регрессия» оказался верен, но был записан ДО проверки, это второй урок; дыра нигде не задокументирована на Request-стороне (`runRequestSeam` — один узел CompositeLit, `archguard.go:197`, против четырёх у Stage) — носитель 121. (в) ⚠ **Egress-сеам — РЕГРЕССИЯ против снесённого байт-гарда, две исполнимые формы (посадки пасса-2, обе exit=0 у tmvet):** пакетная функция `llm.Complete(...)` (у qualified identifier `Selections[sel]` = nil → анализатор молча выходит, `archguard.go:240-242`; пакет llm исключён целиком) и потребительский интерфейс, прячущий llm-типы ВНУТРИ композита (`Complete(ctx, []llm.LLMRequest) ([]*llm.LLMResponse, error)` — `touchesPkg` не рекурсивен, `archguard.go:79-82`). Старый регекс `.Complete(` ловил ОБЕ формы. Несущий коммент «that is what cannot be hidden» (`archguard.go:250-253`) и клейм фикстуры ФАЛЬСИФИЦИРОВАНЫ. Сегодня таких форм в дереве нет (латентно), но **промт разрешал снос гардов «ТОЛЬКО после доказанного паритета» — по egress-оси паритет неполон ⇒ снос байт-гарда в текущем виде букве промта НЕ соответствует.** Развилка владельцу — п.7. + +**4. Направление и решения (линза пасса-2, мнение сформировано ДО чтения отчёта).** Состав линтера обоснован числами и анти-хак-правило соблюдено буквально; аудит исключений по коду: все классы подтверждены для СЕГОДНЯШНЕГО дерева (единственный контрпример фразе «все 33 прод-Close — читатели»: `chunktest/epub.go:51`, файл на запись в тест-фикстуре; потерю данных не прячет — zip.Writer.Close проверяется). Точностные хвосты → 122: Fprint-исключение на весь модуль вместо `cmd/` · `w\.Write`-исключение ключуется именем receiver-а вопреки собственному принципу конфига · miningstop-исключение глушит текстом весь файл · комменты-обоснования конфига — снимки настоящего времени, ничто не пере-проверяет их посылку · дрейф provenance-чисел (293/31/93 против записанных 294/33/91) · `.skips.log` не в gitignore · GO_MIN_VERSION без патч-уровня · коммент c1 «echo mine unarmed» противоречит quirks §4 («low ПЕРЕ-ВООРУЖАЕТ эхо-мину», 1/16) — сам флип ратифицирован, вреда нет, коммент поправить. Батарея против «не тормозить»: двойной прогон сьюта ради имён скипов ≈6.4s из 1m25s (~8%) — приемлемо; главный расход — архитектурные инварианты исполняются трижды (vet ×2 тег-сета + archguard-тест 17.7s LoadAllSyntax под -race) — осознанно, резать при росте модуля здесь. + +**5. Живая проба провода — единственный пункт промта, не закрытый никем; после п.2(б) её предмет сузился до реального: примут ли WAF/фронты провайдеров новую SETTINGS-раскладку и 31 минорку семантики ретраев.** Сессия пробу не провела (довод «не было санкции» неверен — потолок $0.50 ратифицирован D39.92 п.2), приёмке запуск заблокирован пермишен-слоем на `. ./.env`. Линза направления независимо назвала это главным долгом пака: «осторожный, затем полный» требовал осторожную половину именно здесь. Команда владельцу — строка 117. До пробы (или явного слова владельца) транспортный бамп НЕ лендится. + +**6. Пять mid-flight решений владельца 03.08 — НЕ ратифицированы (пасс-1 ошибочно ратифицировал «с вето-окном» — снято): известны только со слов сессии, владельцу выдан список confirm/deny.** (i) CI-воркфлоу не писать (Forgejo 10.0.3, раннер не подтверждён) → жилец 108. (ii) Охват eval/ анализатором снять (замер: три программы, ни одна не строит Stage/Request). (iii) **Бамп `@latest` вместо минимального — НЕСУЩЕЕ:** при confirm лендится текущий go.mod (x/net 0.57 + sqlite 1.55 + пере-захват голдена), при deny — минимальный бамп (x/tools@v0.45 → x/net 0.54, x/text НЕ двигается, голден БЕЗ пере-захвата; жизнеспособность доказана ревьюером сессии) и состав bump-коммита другой. (iv) Пере-захват голдена — следствие (iii). (v) Адверсариальное ревью §9 по требованию владельца — информационно. + +**7. ВЕРДИКТ И РАЗВИЛКА ЭТАПА E.** Пак **ПРИНЯТ по качеству кода** (ядро п.1, репликации п.2, аудиты п.4 — уровень высокий, самопроверка сессии реальная: 18 своих дефектов починены до сдачи). **Лендинг ГЕЙЧЕН тремя решениями владельца:** (1) проба 117 — или явная санкция лендить до пробы; (2) confirm/deny пяти решений п.6 (несущее — @latest); (3) **этап E: рекомендация оркестратора — МИКРО-ДОФИКС бэкенд-сессией ДО лендинга сноса** (~30 строк + посадки: requestseam ValueSpec/new-симметрия [п.3б] · egressseam fallback на Uses при nil-Selections [п.3в-1] · рекурсивный touchesPkg [п.3в-2] · честные комменты вместо «cannot be hidden»); альтернатива — лендить как есть с ЗАДОКУМЕНТИРОВАННОЙ регрессией по двум egress-формам и строкой 121 «скоро». **План лендинга — семь pathspec-коммитов с само-атрибуцией** (рекомендация линзы направления, форензика голдена бесплатна в истории): конфиги 112 → дефект-фиксы §2 (поведенческие, именованные) → механические линт-фиксы → бамп+пины+голден (гейт 117 в сообщении) → анализаторы+снос гардов+README → .golangci.yml+Makefile → док-лендинг. Строки 107/112 закрываются док-коммитом лендинга; носители 117–123 и жильцы 108 подготовлены в PROGRESS тем же касанием. + +**8. УРОК ПРИЁМКИ (слово владельца 03.08, оплачено этой нотой; норма — в промте оркестратора).** Пасс-1 попался на шести ловушках: след отчёта (план верификации структурирован его секциями) · связность вместо истинности (два несущих клейма приняты со слов с записью «исполнением») · соглашательство (пять «решений владельца» ратифицированы со слов сессии; оценочные эпитеты в ноте) · догадка фактом («не регрессия» до проверки) · слепой участок одной модели · экономия усилия на неудобном (направление/решения не ревьюились). Пасс-2 (анти-следовые линзы) на тех же токенах нашёл: регрессию egress-паритета, запрещающую снос по букве промта; мисхарактеризацию принятого клейма; двух исполнимых обходов вне карты отчёта. Механика-минимум закреплена нормой в `ORCHESTRATOR_SESSION_PROMPT.md` (03.08). + +## D39.97 — ПРИЁМКА дофикса archguard + живой пробы (оркестратор №12): ПРИНЯТ, весь пак стандартов ЗАЛЕНДЕН семью pathspec-коммитами, строки 107/112/117 ЗАКРЫТЫ; решение по tools/go.mod — строить; вопрос владельца о снапшоте разобран (04.08). ✅ + +**Мандат — D39.96 п.7 (дофикс до сноса — выбор владельца) + промт `BACKEND_ARCHGUARD_DOFIX`. Отчёт: `archive/reports/ARCHGUARD_DOFIX_2026-08-03.md` (ревью-шапка ПРИНЯТ).** + +**1. Приёмка исполнением (короткая, по пропорциональности; свои посадки — вне карты отчёта).** Батарея на реальном дереве EXIT=0 (1m29s, скип один). Деньги вторым путём: usage×цены `models.yaml` ≡ заявленным по всем трём вызовам и сумме, дельта $0.000000 ($0.005269 ≈ заявленным $0.0053). Свои посадки в свежей копии: значение метода `f := c.Complete` CAUGHT (клейм таблицы подтверждён независимо) · **method expression `llm.LLMClient.Complete` CAUGHT — формы нет ни в таблице отчёта, ни в списке пропусков** (SHAPE-половина берёт её по типам аргументов — гард сильнее собственной документации) · негативный контроль шва чист. Вход приёмки на месте: **CONFIRM владельца по `@latest` записан отчётом** (D39.96 п.6-iii закрыт) — проба шла на текущем go.mod. + +**2. Что принято.** Этап 1: шесть дыр закрыто (3 из промта + 3 сверх, включая блокер «вызов через параметр типа» — невидимый ОБОИМ прежним поколениям; ось имени `llm.Do`; ложное срабатывание `var s *config.Stage` снято); оба сеама на общем обходчике `seamRule`; исключения переведены с path-суффиксов на import-path (`//line`-идентичность отрезана `PositionFor(…, false)`); 9/9 мутаций ловятся, мутация M7 нашла мёртвую ветку TypeParam в самом фиксе — образец, зачем мутационная проверка обязательна; `assertGuardVocabularyIsLive` против молчаливого гниения строковых ключей; 38 want-посадок + 8 негативных контролей; ноль диагностик на боевом дереве. Этап 2: проба PASS 3/3 (`finish=stop`, новых отказов/фреймингов нет); **прямой клейм по проводу: `reasoning_content` 965 симв., `reasoning_tokens:234` ⊂ `completion:280` ⇒ `ReasoningSubset` подтверждён на проводе; механика 112 подтверждена телом запроса** (`reasoning_effort` отсутствует на `ReasoningNone`); h2-ALPN подтверждён на всех трёх эндпоинтах за $0 ⇒ новая SETTINGS-раскладка не отвергнута. Граница честная (три эндпоинта · по вызову · одна сеть) — принята. Семь осознанных пропусков — фикстурами без want (покраснеют в день, когда начнут ловиться) — носитель 121(д). Оговорка сессии о 20/43 умерших ревью-агентах — компенсирована её пере-проверкой и моими посадками. Остаток: инвариант-коммент `httpllm.go:77` («zero wire bytes» — верен для полей пинга, неверен для бампа, который их привёз) дофикс не тронул → хвост в 122. + +**3. ЛЕНДИНГ: весь пак стандартов + дофикс — семь pathspec-коммитов с само-атрибуцией** (план D39.96 п.7): `e8d4ac0` конфиги 112 · `5a97020` девять поведенческих дефект-фиксов · `b155da3` механика линта · `cb368c0` бамп+пины+голден (движутся только хеш-поля) · `6356471` анализаторы+снос старых гардов · `5a81bff` .golangci.yml+Makefile+README · `0e64efe` opt-in лога тел в live-пробе. Фронт-сессия закоммитила своё (`ece94ef`) ПАРАЛЛЕЛЬНО лендингу — pathspec-дисциплина коллизию исключила by construction. **Строки 107, 112, 117 ЗАКРЫТЫ.** Оба промта архивированы. Оставшиеся не-несущие mid-flight решения 03.08 (CI-воркфлоу не писать · охват eval/ снят) ратифицированы этой нотой — порог нормы «confirm только для несущих» соблюдён, триггеры реопена в реестре 108. + +**4. Решение по tools/go.mod (владелец 04.08: «вам решать») — СТРОИТЬ, отдельным малым паком, НЕ гейт ничему.** Форма: отдельный модуль (например `backend/tools/` со своим go.mod), куда переезжают `cmd/tmvet` + `internal/archguard` — ⚠ `tool`-директива Go 1.24 НЕ решает задачу (тулы в главном go.mod участвуют в MVS так же). Следствия, которые пак обязан удержать: `make battery` гоняет тесты ОБОИХ модулей (инвариант «падать на обычной батарее» переезжает в Makefile — он и так единственная точка входа); `shippingtree_test` живёт в tools-модуле и грузит главный. Выигрыш: бамп инструментов ФИЗИЧЕСКИ не может двинуть x/net/x/text главного модуля ⇒ класс «линтер тронул денежную ось» закрывается по построению. Туда же — решение по sqlite: оставить 1.55 (уже заленден, прогонов не было, откат = отдельное движение без выгоды). Строка 118 переформулирована под это решение. + +**5. Вопрос владельца «не слишком ли агрессивен снапшот, можно ли безопасно ослабить» — разбор.** Короткий ответ: механизм НЕ слишком агрессивен — он неточно НАЦЕЛЕН, причём в обе стороны сразу, и лечится калибровкой осей + дешёвой перекупкой, а не ослаблением. Три факта: (а) **есть недо-чувствительность** (строка 119: `SanitizerVersion` НЕ сворачивает `width.Fold` — смена x/text перевернула бы вердикт БЕЗ движения снапшота; это аргумент ПРОТИВ ослабления вслепую); (б) **есть пере-чувствительность по охвату**: `EmbeddedVersion` фолдится безусловно по ВСЕМ файлам всех пар (D39.90 п.3) — добавление ja-данных перекупает zh-книги; лечится пер-парным хешом (только файлы своей пары) — заодно шаг к мандату общности (родня 115/120); (в) **версия-строка ≠ поведение**: бамп x/text доказан поведенчески пустым на 17M+ входов, но снапшот сдвинулся, потому что фолдится СТРОКА версии. Направление фикса (в): не «фолдить меньше», а **сделать перекупку дешёвой, когда поведение не менялось** — `tmctl resnapshot --dry-run`, который по чекпойнтам сверяет БАЙТЫ тел (`msgsContentHash` уже в голдене): байт-идентичные юниты пере-привязываются к новому снапшоту без пере-вызова, платятся только реально изменившиеся; детерминизм цел (каждая пере-привязка аудируема), деньги видимы (канон §5), «тихих перепокупок» не появляется — наоборот, исчезают громкие ПУСТЫЕ перекупки. Опция «фолдить поведенческий отпечаток вместо строки версии» рассмотрена и отложена: probe-корпус = пол, не доказательство; риск тихого изменения поведения хуже цены ложной перекупки. **Заведена строка 124** (дизайн-вход: (а)+(б)+(в) одним паком, приоритет — перед МАСШТАБОМ, когда перекупки начнут стоить реальных денег; сегодня боль теоретическая — книг в работе нет). diff --git a/docs/archive/prompts/BACKEND_ARCHGUARD_DOFIX_SESSION_PROMPT.md b/docs/archive/prompts/BACKEND_ARCHGUARD_DOFIX_SESSION_PROMPT.md new file mode 100644 index 00000000..bec1191c --- /dev/null +++ b/docs/archive/prompts/BACKEND_ARCHGUARD_DOFIX_SESSION_PROMPT.md @@ -0,0 +1,48 @@ +# Промт бэкенд-сессии: дофикс паритета анализаторов + живая проба провода (строки 121-п.0 · 117; хвост пака стандартов) + +> ✅ **ИСПОЛНЕН И ПРИНЯТ (D39.97, 04.08): шесть дыр закрыто (3 промта + 3 сверх, вкл. блокер type-param), 9/9 мутаций, проба PASS 3/3 с прямым клеймом `reasoning_content` на проводе, $0.0053 из $0.50. Заленден в составе пака стандартов.** Отчёт: `../reports/ARCHGUARD_DOFIX_2026-08-03.md`. Инструкции отсюда не исполнять. + +**Мандат:** приёмка пака стандартов D39.96 (03.08): пак принят по качеству кода, но пасс-2 приёмки нашёл **регрессию egress-паритета против снесённого байт-гарда** — снос гардов в текущем виде нарушает условие исходного промта «только после доказанного паритета». Владелец выбрал дофикс ДО лендинга. Твой предшественник сделал качественный пак — ты закрываешь три конкретные дыры, найденные посадками приёмки, и добиваешь единственный неисполненный пункт (живую пробу провода). + +**Онбординг:** CLAUDE.md → `docs/README.md` → CURRENT-STATE в `docs/PROGRESS.md` → D39.96 в `05-decisions-log.md` (вся фактура приёмки там) → отчёт `archive/reports/REPO_STANDARDS_2026-08-03.md` (ревью-шапка = сводка находок). Код-факты бери из кода — file:line ниже это отправные точки, код первичен. + +## §0. Скоуп и правила + +- Зона записи: `backend/` ТОЛЬКО. НЕ коммитить — лендит оркестратор. `.env` НЕ ЧИТАТЬ (для этапа 2 сорсить шеллом — ключи в контекст/отчёт не тащить). +- Деньги: этап 1 = **$0**. Этап 2 = живая проба, потолок **$0.50** (санкция D39.92 п.2), каждый цент в отчёт. +- **Эхо-протокол:** первый деливерабл — ≤10 строк «что понял: скоуп / инварианты / не-делать» ДО работы. +- **Канал вопросов:** непонятно / конфликт промта с кодом или доками → пинг оркестратору через владельца, НЕ интерпретация. +- Дерево содержит незакоммиченный пак стандартов — это ТВОЯ база, поверх неё и работаешь. Чужого в дереве быть не должно, но `git status` перед началом сверь. + +## Этап 1 ($0): три дыры анализаторов — фикс + посадки + +Все три доказаны исполнением при приёмке (посадки exit=0 там, где обязан быть флаг). Форма фикса — «реши сам»; приоры ниже опровергаются аргументом. + +**A. egressseam пропускает пакетную функцию `llm.Complete(...)`.** `archguard.go:240-242`: у qualified identifier (функция пакета, не метод) `pass.TypesInfo.Selections[sel]` = nil → анализатор молча выходит. Пакет `internal/llm` исключён целиком, так что хелпер `func Complete(...)` в llm + вызов откуда угодно = второй egress, невидимый ничем. Приор фикса: fallback на `pass.TypesInfo.Uses[sel.Sel]` → `*types.Func` с `Pkg()` = llm. + +**B. egressseam пропускает интерфейс, прячущий llm-типы ВНУТРИ композита.** `touchesPkg` (`archguard.go:76-92`) разворачивает один уровень указателя и не смотрит внутрь элементов: `Complete(ctx context.Context, reqs []llm.LLMRequest) ([]*llm.LLMResponse, error)` проходит молча. Приор: рекурсия по Slice/Map/Chan/Array/Signature (+указатель уже есть). + +**C. requestseam ловит только литералы.** `runRequestSeam` обходит один узел `*ast.CompositeLit` (`archguard.go:197`) против четырёх у stage-сеама (`:140-165`): `var r pipeline.Request` + пополевое присваивание и `new(pipeline.Request)` из чужого пакета проходят молча (дыра общая со старым гардом — не регрессия, но и не задокументирована). Приор: симметрия ValueSpec/CallExpr со stage-сеамом. + +**D. Честные комменты.** «that is what cannot be hidden» (`archguard.go:250-253`) и клейм фикстуры (`testdata/.../egresssites/egresssites.go:33`) фальсифицированы посадками — переписать по фактическому охвату. Если что-то из A–C решишь осознанно НЕ ловить — это легитимно, но пропуск ОБЯЗАН быть назван в doc-комменте пакета и негативной фикстурой (молчащий пропуск = как раз то, что приёмка вскрыла). + +**E. Посадки.** Каждая закрытая форма — кейс `analysistest` в testdata (формы из A/B/C выше) + негативные контроли (легитимный вызов через шов; `Complete` чужого пакета с не-llm сигнатурой; `var` в exempt-местах). Плюс мутационная самопроверка: сломай каждый фикс — соответствующий кейс обязан упасть. + +**F. Батарея.** `make battery` EXIT=0; четыре поведенческих теста pipeline (`BankProbe`/`ReasoningIsPart`/`RepairStage`/`InternalCallDecidesEveryStageField`) живы. + +## Этап 2: живая проба провода (строка 117 — гейт платных прогонов) + +⚠ **ГЕЙТ: слово владельца по бампу `@latest` (D39.96 п.6-iii) — спроси ДО этапа 2, если он не передал с промтом.** + +- **Confirm @latest** → проба на текущем дереве. +- **Deny** → сначала минимальный пере-бамп (приор, доказан ревьюером исходного пака; опровергается замером): `go get golang.org/x/tools@v0.45.0` (тянет x/net v0.54.0, **x/text НЕ двигается**) + откат `modernc.org/sqlite` на v1.53.0 + откат x/text-пинов (`norm.go:69` → v0.38.0, зеркала `enclosure_test.go` и `memory_f1_test.go`) + голден обязан пройти БЕЗ пере-захвата (вернётся к HEAD-версии). Затем проба. + +Команда (ключи грузит шелл; вывод фильтруй от ключей): +``` +cd backend && set -a && . ./.env && set +a && TM_LIVE=1 go test -tags live -run TestLiveAdapterConformance -v ./internal/pipeline/ +``` +Кроет deepseek/zai/kimi (grok закомментирован — clean-prod гигиена, НЕ включать). Сверять против `docs/experiments/00-provider-quirks.md`: `finish=stop` · `reasoning_content` непустой где ожидается · нет новых отказов/фреймингов. Контекст риска: после бампа x/net у клиента новый `SETTINGS_MAX_FRAME_SIZE=16384` (семантически инертен, но меняет h2-фингерпринт для WAF). **Любое расхождение = СТОП-пинг с сырьём, откатов без слова владельца не делать.** + +## Отчёт + +`docs/archive/reports/ARCHGUARD_DOFIX_<дата>.md`, компактный: эхо-шапка · дифф этапа 1 с таблицей «форма × ловится» · итог мутационной самопроверки · результат пробы по провайдерам (finish/usage/цена; тел с ключами НЕ вставлять) · найдено-не-починено. Каждое число — с командой. **СТОП — приёмка оркестратора.** diff --git a/docs/BACKEND_REPO_STANDARDS_SESSION_PROMPT.md b/docs/archive/prompts/BACKEND_REPO_STANDARDS_SESSION_PROMPT.md similarity index 93% rename from docs/BACKEND_REPO_STANDARDS_SESSION_PROMPT.md rename to docs/archive/prompts/BACKEND_REPO_STANDARDS_SESSION_PROMPT.md index e4b7ad9f..52428292 100644 --- a/docs/BACKEND_REPO_STANDARDS_SESSION_PROMPT.md +++ b/docs/archive/prompts/BACKEND_REPO_STANDARDS_SESSION_PROMPT.md @@ -1,5 +1,7 @@ # Промт бэкенд-сессии: индустриальные стандарты репозитория — линтер · CI · бамп зависимостей · гарды-в-analyzer (строки 107 · 112 · Д7) +> ✅ **ИСПОЛНЕН, ПРИНЯТ (D39.96 двумя пассами) И ЗАЛЕНДЕН (D39.97, 04.08; семь pathspec-коммитов `e8d4ac0`…`0e64efe`). Строки 107/112/117 закрыты.** Регрессия egress-паритета, найденная приёмкой, закрыта дофикс-паком (`BACKEND_ARCHGUARD_DOFIX_SESSION_PROMPT.md` рядом); живая проба провода исполнена там же (PASS 3/3). Отчёты: `../reports/REPO_STANDARDS_2026-08-03.md` · `../reports/ARCHGUARD_DOFIX_2026-08-03.md`. ⚠ Эрратум промта: адрес `pipeline-c2.yaml:39` был ошибкой трекера (judge на glm-5, не черновик) — флипов ровно 5. Инструкции отсюда не исполнять. + **Мандат:** решение владельца 02.08 (D39.92): «делаем по стандартам индустрии: CI, линтер, бамп x/net и всех библиотек; осторожный, затем полный подход; спилить самописные AST-тест-гарды в пользу штатной формы». Ограничение владельца, равное по силе самому мандату: **стандарты не должны мешать разрабатывать, тормозить и приводить модели к хакам.** **Онбординг:** CLAUDE.md → `docs/README.md` → CURRENT-STATE в `docs/PROGRESS.md` → голова D39.91–92 в `05-decisions-log.md` → `backend/README.md` + `12-go-style-notes.md`. Контекст предмета: отчёт `archive/reports/EFFORT_HANDLE_2026-08-02.md` §1.3(2), §5.5, Д7; D39.90 п.7; строка 107 трекера. diff --git a/docs/archive/reports/ARCHGUARD_DOFIX_2026-08-03.md b/docs/archive/reports/ARCHGUARD_DOFIX_2026-08-03.md new file mode 100644 index 00000000..646ea7a3 --- /dev/null +++ b/docs/archive/reports/ARCHGUARD_DOFIX_2026-08-03.md @@ -0,0 +1,210 @@ +# Дофикс анализаторов archguard + живая проба провода (бэкенд, 03.08.2026) + +> ✅ **ПРИНЯТ приёмкой оркестратора №12 (04.08, D39.97) и заленден в составе пака стандартов (семь pathspec-коммитов).** Приёмка исполнением: батарея EXIT=0 · деньги вторым путём usage×цены — дельта $0.000000 по всем вызовам и сумме · две СОБСТВЕННЫЕ посадки вне карты отчёта: значение метода CAUGHT (клейм подтверждён независимо), **method expression `llm.LLMClient.Complete` CAUGHT — формы нет ни в таблице, ни в списке пропусков: гард сильнее собственной документации** · негативный контроль шва чист. CONFIRM владельца по `@latest` принят входом. Семь осознанных пропусков → строка 121(д); нетронутый инвариант-коммент `httpllm.go:77` → строка 122. Оговорка о 20/43 умерших ревью-агентах компенсирована пере-проверкой сессии + посадками приёмки. + +**Мандат:** `BACKEND_ARCHGUARD_DOFIX_SESSION_PROMPT.md` — хвост пака стандартов D39.96. +**Итог:** оба этапа закрыты. `make battery` EXIT=0, проба PASS 3/3, потрачено $0.0053 из потолка $0.50. +Не коммитил — лендит оркестратор. + +## Вход приёмки + +| | | +|---|---| +| Слово владельца по `@latest` (D39.96 п.6-iii) | **CONFIRM** (03.08) ⇒ проба на текущем дереве; минимальный пере-бамп не выполнялся | +| go.mod пробы | `go 1.26.4`; x/net **v0.57.0** · x/text **v0.40.0** · x/tools **v0.48.0** · yaml.v3 v3.0.1 · sqlite **v1.55.0** | +| Тулчейн | `go1.26.5 linux/amd64` | +| Пин x/text | `internal/text/norm.go:69` = `v0.40.0`, зеркала в `enclosure_test.go` и `memory_f1_test.go` | + +--- + +## Этап 1 ($0): дыры анализаторов + +Три дыры из промта закрыты, плюс три найдены и закрыты сверх него. Все шесть доказаны посадкой: +до фикса `go vet -vettool` даёт exit 0, после — exit 1. + +**A. Пакетная `llm.Complete(...)`** — `Selections` не заполняется для qualified identifier. Резолв +переведён на `Uses` по идентификатору вызова (`archguard.go:454`); попутно закрылся dot-import. + +**B. Композиты в сигнатуре** — плоский скан разворачивал один указатель и вставал, поэтому +`Complete(ctx, []llm.LLMRequest) ([]*llm.LLMResponse, error)` проходила. Заменено на `typeReaches` +(`:156`) — рекурсия по конструкторам типа с защитой от цикла. + +**C. Симметрия сеамов** — `requestseam` смотрел один вид узла против четырёх у `stageseam`. Оба +переведены на общий обходчик `seamRule` (`:249`): разъезд по видам узлов и был причиной дефекта. + +**D. Вызов через параметр типа (блокер, найден ревью).** `runEgressSeam` требовал `*types.Signature`; +у параметра типа `Underlying()` — интерфейс-ограничение, поэтому анализатор выходил до всякой проверки. +Реалистичная форма — Ф2-судья через дженерик — была невидима обоим драйверам. SHAPE-половина читает +теперь **место вызова** (типы аргументов + тип узла вызова), которое go/types резолвит в любом +написании; сигнатура нужна только provenance и может быть nil. + +**E. Именованный результат.** `func f() (s config.Stage)` — то же объявление нулевого значения, что +`var s config.Stage`. Добавлен `*ast.FuncType`, только результаты (параметр даёт вызывающий). + +**F. Исключения не были привязаны к корню модуля.** `HasSuffix` по абсолютному пути ошибался в обе +стороны: вложенная директория с тем же хвостом **наследовала** исключение, а на чекауте, где каталог +модуля назван не `backend`, целевые файлы его **теряли**. Ключ переведён на import-path + базовое имя, +позиция берётся `PositionFor(…, false)` — иначе `//line` позволяет присвоить чужую идентичность. + +Сверх этого закрыта ось **имени**: оба прежних поколения гарда ключевались на слове `Complete`, так что +`llm.Do(ctx, req)` был свободен. Гард стреляет по дизъюнкции **SHAPE** (несёт пару +`LLMRequest`→`LLMResponse`, имя не важно) ∨ **PROVENANCE** (зовётся `Complete` и принадлежит +`internal/llm` — половина паритета с байт-сканом). + +Снято ложное срабатывание: `var s *config.Stage` репортился, хотя ничего не конструирует. Разворот +указателя оставлен **только** литеральной ветви — замер показал, что для `[]*T{{…}}` он несущий. + +### Форма × ловится + +`✗` = проходила молча · `✓` = репортится · `—` = формы у поколения не было. + +| форма | байт-гард | 1-й анализатор | сейчас | +|---|---|---|---| +| **egress** | | | | +| через интерфейс / адаптер / локальный интерфейс | ✓ | ✓ | ✓ | +| пакетная `llm.Complete` | ✓ | ✗ | ✓ | +| пара в композите `[]llm.LLMRequest` | ✓ | ✗ | ✓ | +| другое имя `llm.Do` | ✗ | ✗ | ✓ | +| значение метода `f := c.Complete` | ✗ | ✗ | ✓ | +| **вызов через параметр типа** | ✗ | ✗ | ✓ | +| запрос как параметр типа (через ограничение) | ✗ | ✗ | ✓ | +| **request** | | | | +| литерал / срез / мапа / алиас- и dot-импорт | ✓ | ✓ | ✓ | +| `var r pipeline.Request` + присваивание | ✗ | ✗ | ✓ | +| `new(pipeline.Request)` | ✗ | ✗ | ✓ | +| алиас / производный тип / конверсия | ✗ | ✗ | ✓ | +| **оба сеама** | | | | +| именованный результат `func f() (s T)` | ✗ | ✗ | ✓ | +| `var p *T`, `(*T)(x)` — ложное срабатывание | — | ✗ (репортил) | ✓ молчит | + +### Мутационная самопроверка + +Девять мутаций, каждая ломает один фикс; все девять пойманы, после восстановления сьюта зелёная. + +| | ломает | упавшие кейсы | +|---|---|---| +| M1 | резолв через `Selections` | egress:41 | +| M2 | `typeReaches` стоп на срезе | egress:52,57 | +| M3 | `requestseam` только литерал | request:36,44,48,54,62,66 | +| M4 | SHAPE-половина off | egress:57,64,72,85,103 | +| M5 | PROVENANCE-половина off | egress:32,41 | +| M6 | egress требует сигнатуру | egress:85 | +| M7 | `typeReaches` без `TypeParam` | egress:103 | +| M8 | сеам не видит `FuncType` | stage:78, request:66 | +| M9 | литерал не разворачивает указатель | stage:98 | + +Мутация нашла дефект в самом фиксе: первая редакция ветки `TypeParam` была **мёртвой** — +`Constraint()` возвращает именованный тип, а обход на именованном по правилу встаёт. Исправлено на +`Constraint().Underlying()` (единственное место, где обход сознательно проходит сквозь именованный тип; +оговорка стоит в коде). + +### Закрыто молчаливое гниение + +Гарды ключуются на строках — переименование не роняет ни сборку, ни тест, а SHAPE-половина тихо +становится декорацией. `assertGuardVocabularyIsLive` требует, чтобы каждое исключение указывало на +существующий файл, а оба имени типов резолвились в `internal/llm`. Обе проверки проверены мутацией. + +Снято мёртвое исключение `render.go`: замер показал, что дерево чисто и без него, а исключение, +не покрывающее существующего кода, молча пред-одобряет следующий литерал. + +### Батарея + +``` +make battery # EXIT=0, 1m44s +golangci-lint # 0 issues +go vet (×2 тег-набора, с -vettool и без) # чисто +go test ./... -race # 15 пакетов ok, скип один (TestHelperKillLoop, прежний) +``` + +Посадок `// want`: **38** (15 stage · 13 request · 10 egress) + 5 фикстур-пропусков + 8 негативных +контролей. `TestInvariantsHoldInTheShippingTree` гоняет анализаторы по реальному модулю — **0 +диагностик**, то есть ни одна из новых веток не дала ложного срабатывания на боевом дереве. + +Четыре поведенческих теста живы: `BankProbeAndAttemptAddressOneCheckpoint`, +`ReasoningIsPartOfTheRequestIdentity`, `RepairStageTakesItsEffortFromItsOwnGate` +(`synthetic_stage_seam_test.go`), `InternalCallDecidesEveryStageField` (`internal_call_test.go`). + +--- + +## Этап 2: живая проба провода + +``` +set -a; . ./.env; set +a +TM_LIVE=1 go test -tags live -run TestLiveAdapterConformance -v ./internal/pipeline/ +``` + +PASS 3/3, 45s. grok закомментирован, не включал. + +| модель | finish | in/out | share исходника | вердикт | цена | +|---|---|---|---|---|---| +| `deepseek-v4-flash` | `stop` | 138/380 | 0.00 | ok | $0.000126 | +| `glm-5` | `stop` | 69/21 | 0.00 | ok | $0.000136 | +| `kimi-k2.6` | `stop` | 75/1214 | 0.00 | ok | $0.004927 | + +Новых finish_reason, отказов и фреймингов нет. Эхо-мина не выстрелила даже на фрагменте Лу Синя 祝福, +но это одно наблюдение: quirks:59 фиксируют, что эхо на 0731 стохастично по вызову. + +### Прямой клейм по `reasoning_content` + +Нейтральный `LLMResponse` полей thinking не несёт, поэтому взведён штатный лог сырых тел +(`LOG_LLM_BODIES=1` + `LOG_LEVEL=debug`, зеркало `tmctl`; `obs.LogLLMExchange` пишет только тела, +никогда URL и заголовки). Один повторный вызов deepseek, $0.000080: + +- `choices[0].message` = `['content', 'reasoning_content', 'role']`, **`reasoning_content` 965 символов**; +- `reasoning_tokens: 234` при `completion_tokens: 280` ⇒ **`ReasoningSubset` подтверждён на проводе**: + думание внутри completion, и наш нулевой `ReasoningTokens` — защита от двойного счёта, а не слепота; +- тело запроса — `['max_tokens','messages','model','stream','temperature']`, **`reasoning_effort` + отсутствует** ⇒ механика строки 112 подтверждена на проводе: `reasoning:"off"` на + `ReasoningNone`-модели не кладёт ничего и вызов едет на вендорском дефолте. + +### h2-фингерпринт (главный вопрос D39.96 §5) + +Клиент действительно ездит на x/net/http2 (`httpllm.go:17` + `http2.ConfigureTransports` поверх клона +`DefaultTransport`), и все три эндпоинта договариваются на h2 — снято сырым TLS-хендшейком за $0: + +``` +api.deepseek.com:443 alpn="h2" tls=0x0304 +api.z.ai:443 alpn="h2" tls=0x0304 +api.moonshot.ai:443 alpn="h2" tls=0x0304 +``` + +⇒ вызовы шли с новой раскладкой SETTINGS, и ни один фронт её не отверг. Долг строки 117 закрыт. + +**Граница:** три эндпоинта, по одному вызову, из одной сети, в один момент. Это «отказа нет сейчас +отсюда», не «отказа не будет». CONNECT-туннель, CONTINUATION и поведение под нагрузкой не проверены. + +--- + +## Найдено, не починено + +Осознанные пропуски по разрешённому промтом пути §D — назван в doc-комменте + посажен фикстурой без +ожидающего комментария (analysistest покраснеет в день, когда пропуск начнёт ловиться). **Приняты +оркестратором 03.08, носитель — строка 121(д), форма закрытия — типовой шов 121(б).** + +1. Помощник, который зовётся не `Complete` И отмывает пару типов через свои (`llm.Ask`-класс). +2. Пара внутри named-обёртки: `typeReaches` по решению встаёт на именованном типе. +3. Ось видов узла: встраивание, `make([]T,1)`+присваивание, generic-zero. +4. `internal/llm` исключён целиком — второй провод внутри пакета адаптеров ловится только ревью. +5. Внешние тест-пакеты (`llm_test`, `config_test`) исключены — следствие `inPackage`, названо в коде. +6. Рефлексия (`reflect.Value.Call`) — статическим анализом не закрывается. +7. Файлы за третьим сборочным тегом и в директориях, которые пропускает загрузчик. Реальная потеря + охвата против байт-скана; лечится строкой в Makefile на каждый новый тег. + +## Правки комментариев по факту + +| было | стало | +|---|---| +| `cmd/tmvet`: «runs the invariants **alongside** the standard vet passes» | `-vettool` их **замещает** — измерено; Makefile гоняет оба прохода | +| `inPackage`: «matching the path alone let `config_test` build Stages freely» | **инверсия**: без `TrimSuffix` посаженный `config_test` репортится (exit 1), с ним молчит (exit 0) — то есть `TrimSuffix` исключение расширяет. Поведение оставлено, цена названа | +| `content_routing_test.go`: «resolving the SELECTION» | selections больше не резолвятся; переписано по фактической механике | +| `archguard.go`: «builtins carry no signature» | встроенные с неконстантным результатом сигнатуру получают (`new(T)` → `func(T) *T`); переписано | +| `pipeline-c1.yaml`: «echo mine unarmed» | quirks §4: `low` **пере-вооружает** эхо-мину (1 из 16); флип — осознанный размен, гейт ловит хвост | + +## Оговорка о достоверности ревью + +Адверсариальное ревью диффа: 6 линз, 43 агента. **20 агентов умерли на лимите сессии, почти все на фазе +опровержения** — то есть находки вернулись неопровергнутыми, а не подтверждёнными. Всё, что попало в +этот отчёт, перепроверено исполнением отдельно; список неперепроверенного — раздел «найдено, не +починено». + +**СТОП — приёмка оркестратора.** diff --git a/docs/archive/reports/EFFORT_HANDLE_2026-08-02.md b/docs/archive/reports/EFFORT_HANDLE_2026-08-02.md index ea4cf8bd..60319686 100644 --- a/docs/archive/reports/EFFORT_HANDLE_2026-08-02.md +++ b/docs/archive/reports/EFFORT_HANDLE_2026-08-02.md @@ -317,7 +317,7 @@ sourceScriptShare > 0.15 (disposition.go:224,275) Альтернативы проверены запуском и **не проходят наше ограничение «падать на обычной батарее»**: `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 в тестах и одна — сам конструктор. +`exhaustruct` — инструмент ровно под исходный класс бага, но на нашем коде даёт 16 находок, из которых 15 в тестах и одна — сам конструктор. *(⚠ эрратум приёмки D39.96, испр. оркестратором: «16» — число, СУЖЕННОЕ до типов `config.Stage`/`pipeline.Request` (фактически 17, семнадцатый — сам шов `InternalCall.Stage()`); ГЛОБАЛЬНЫЙ exhaustruct по репо = **988** — замер пака стандартов, отчёт `REPO_STANDARDS_2026-08-03.md` §1 находка-2.)* --- diff --git a/docs/archive/reports/REPO_STANDARDS_2026-08-03.md b/docs/archive/reports/REPO_STANDARDS_2026-08-03.md new file mode 100644 index 00000000..37c22bcc --- /dev/null +++ b/docs/archive/reports/REPO_STANDARDS_2026-08-03.md @@ -0,0 +1,436 @@ +# Отчёт бэкенд-сессии: индустриальные стандарты репозитория (строки 107 · 112 · Д7) + +> ⏳ **ПРИНЯТ ПО КАЧЕСТВУ КОДА приёмкой оркестратора №12 в ДВА ПАССА (03.08, D39.96); ЛЕНДИНГ ГЕЙЧЕН тремя решениями владельца (проба провода · confirm пяти mid-flight санкций, несущее — `@latest` · развилка этапа E).** Пасс-1 — шесть верификаторов по клеймам отчёта: батарея EXIT=0 (lint 0 issues, скип ровно один), 5 флипов и находка-1 подтверждены кодом (`models.yaml:191–194`, `capability.go:155–168`), голден-дифф пере-выведен независимо (только хеши; атрибуция: двигает ИСКЛЮЧИТЕЛЬНО пин x/text, не конфиги и не x/net), 9 дефект-фиксов §2 подтверждены, 7 своих посадок в анализаторы (6/7 CAUGHT). Пасс-2 — пять АНТИ-СЛЕДОВЫХ линз (мнение до чтения отчёта · поиск вне его карты · реконструкция снесённых гардов из HEAD · аудит исключений линтера по коду · независимая репликация клеймов). +> **Итоги пасса-2, меняющие картину отчёта:** (1) ⚠ **РЕГРЕССИЯ egress-паритета против снесённого байт-гарда, две исполнимые формы:** пакетная `llm.Complete(...)` (nil-`Selections` → молчаливый выход, `archguard.go:240-242`) и интерфейс с llm-типами внутри композита (`touchesPkg` не рекурсивен, `:79-82`) — старый регекс `.Complete(` ловил обе; коммент «cannot be hidden» (`:250-253`) и клейм фикстуры фальсифицированы; **снос байт-гарда в текущем виде нарушает условие промта «только после доказанного паритета»** — развилка у владельца (D39.96 п.7), рекомендация: микро-дофикс ~30 строк до сноса. (2) ⚠ **Находка-4(б) «порядок HPACK-заголовков изменился» — мисхарактеризация:** порядок обычных заголовков рандомен per-request под ОБЕИМИ версиями x/net (map-итерация), стабильного «до/после» не существует; реальная дельта фингерпринта — только SETTINGS (`MAX_FRAME_SIZE=16384` подтверждён репликацией на байтах фреймов). (3) Клейм эквивалентности x/text 0.38↔0.40 РЕПЛИЦИРОВАН независимо и шире заявленного (скаляры+битый UTF-8+пары/хангыль+энкодеры GB18030/GBK/UTF-16; три SHA-256 идентичны). (4) Посадка P3: `var r pipeline.Request`/`new()` проходят ОБА поколения гарда — «не регрессия» подтверждена ИСПОЛНЕНИЕМ на реконструкции HEAD-гарда; дыра на Request-стороне нигде не задокументирована → строка 121. (5) Аудит исключений errcheck по коду: все классы подтверждены для сегодняшнего дерева; контрпример фразе «все прод-Close — читатели» — `chunktest/epub.go:51`; точностные хвосты (Fprint-скоуп, `w\.Write`-ключ по имени, дрейф provenance-чисел 293/31/93, `.skips.log` не в gitignore, коммент c1 против quirks §4) → строка 122. +> **Мелкие поправки отчёта:** адреса c1 съехали на −2 (флип фактически `c1:53`, редакторский `c1:81`); счёт §4 «396→143» — фактически 395→141; строка §2 про `dotenv.go` устарела (финал — §9 п.14: warns, never fails); дифф go.mod несёт также indirect `x/mod`/`x/sync`. **Живая проба провода НЕ добита никем** (приёмке запуск заблокирован пермишен-слоем на `.env`) — строка 117 = гейт; довод отчёта «не было санкции» неверен (потолок $0.50 ратифицирован D39.92 п.2). Пять mid-flight решений владельца 03.08 НЕ ратифицированы — выданы владельцу на confirm/deny (D39.96 п.6). Носители — строки 117–123 + реестр 108. + +**Промт:** `docs/BACKEND_REPO_STANDARDS_SESSION_PROMPT.md` (D39.92). **Дата:** 03.08.2026. **Зона:** `backend/` (+ этот отчёт). +**Правило отчёта:** каждое число ниже — с командой, которой оно снято. Ничего не «зеленено» обходом. + +**Эхо-шапка (что понято как задача):** привести репо к штатным для Go формам — линтер с конфигом, одна команда батареи, бамп зависимостей, архитектурные гарды на `x/tools/go/analysis` вместо самописных обходов; плюс санкционированная правка пяти шиппинг-конфигов. Ограничение владельца (стандарты не должны мешать разрабатывать и толкать модель к хакам) держится выше полноты покрытия. + +**Состояние:** этапы 0, A, B, C, E исполнены. Этап D исполнен в части бампа и $0-верификации; **живая проба провода НЕ проводилась** — см. §5. + +--- + +## §0. Строка 112 — пять шиппинг-конфигов + +Флип `stages[draft].reasoning: "off" → "low"` в пяти файлах: + +| файл | строка | стадия | модель | +|---|---|---|---| +| `pipeline-c1.yaml` | 55 | draft | deepseek-v4-flash | +| `pipeline-c2.yaml` | 28 | draft | deepseek-v4-flash | +| `pipeline-arm-mistral.yaml` | 32 | draft | deepseek-v4-flash | +| `pipeline-arm-glm.yaml` | 36 | draft | deepseek-v4-flash | +| `pipeline-arm-deepseek-pro.yaml` | 36 | draft | deepseek-v4-flash | + +**Проверено исполнением** (одноразовый пробник по `LoadPipeline` + `Capability.applyToBody`, удалён после снятия): все пять драфтов дают тело `{max_tokens, reasoning_effort:low, temperature}`, `ThinksOnWire=true`. + +### ⚠ НАХОДКА-1: адрес `pipeline-c2.yaml:39` в промте и в строке 112 ОШИБОЧЕН + +Оба документа адресуют его как «черновую стадию». Это стадия **`select`, роль `judge`, модель `glm-5`**. У glm-5 `capabilities.reasoning.control = extra_body_disable`, то есть `"off"` здесь — живой выключатель, а не отсутствие ключа. Контрфакт снят тем же пробником: + +``` +glm-5 off → {max_tokens, temperature, thinking:{type:disabled}} ThinksOnWire=false +glm-5 low → {max_tokens, temperature} ThinksOnWire=true +``` + +`on_extra_body` у glm-5 не задан, поэтому любой `low|medium|high` (`llm/capability.go` `applyToBody`, ветка `ReasoningExtraBodyDisable`) не шлёт ничего и отдаёт thinking вендор-дефолту = ON ⇒ таймауты ×3 (эмпирика полигона, `pipeline-arm-glm.yaml:10`). **Флип дал бы ровно обратное тому, ради чего заведена строка 112.** Не тронуто; в файл вписано предупреждение с причиной. **Строку 112 трекера нужно поправить — это не моя зона.** + +### Решения, принятые явно (как требовал промт) + +- **`pipeline-arm-mistral.yaml:44` (editor, mistral-large-2512) — оставлено `"off"`.** Модель несёт `ReasoningNone` и не является reasoning-моделью (`models.yaml` note) ⇒ ключ не шлётся, вендор-дефолт без размышления, стена «reasoning ест max_tokens» неприменима. `"low"` здесь = купить размышление, которого не было, без замера. Триггер пере-решения вписан в файл. +- **Редакторские `off` не тронуты:** `c1:83`, `c2:56`, `arm-glm:45`, `arm-deepseek-pro:45`. +- **Хоп эскалации наследует ручку** (`stagerun.go` `attemptRequest` берёт `st.Reasoning` и для hop-модели). На `deepseek-v4-pro` вендор маппит `low→high` (quirks §3а(ii)) ⇒ фактический эффорт хопа не меняется, меняется только тело запроса. +- **`tmctl status --config` на конфигах не гонялось** — промт предписывает это, но команда принимает **book.yaml** и открывает БД (`main.go:200` `NewReadOnlyRunner`), а не pipeline-конфиг. Верификация — существующие тесты, которые грузят все пять файлов: `config/echo_mine_test.go`, `prompt_pack_test.go`, `content_labels_test.go`. + +--- + +## §1. Этап A — замер ($0, ничего не чинилось) + +**Инструмент:** golangci-lint **2.12.2** (пиновано; бинарь в `~/.local/bin`, вне репо; sha256 тарбола сверен с опубликованным `golangci-lint-2.12.2-checksums.txt`). Дерево: **205** `.go`-файлов, из них **115** тестовых. + +``` +golangci-lint run --default=standard --enable=misspell --enable=nolintlint \ + --timeout=15m --max-issues-per-linter=0 --max-same-issues=0 ./... +``` + +**435 находок.** СТОП-порог промта (>1000) не достигнут. + +| линтер | всего | prod | test | +|---|---|---|---| +| errcheck | 413 | 124 | 289 | +| staticcheck | 17 | 5 | 12 | +| misspell | 4 | 1 | 3 | +| unused | 1 | 1 | 0 | +| govet · ineffassign · nolintlint | 0 | 0 | 0 | + +`govet 0` подтверждает базу «`go vet` чист». `nolintlint 0` — потому что `//nolint`-директив в дереве **ноль** (`grep -rn "//nolint" --include=*.go . | wc -l` → 0). + +**errcheck по классам:** `Close` **294** · `fmt.Fprint*` **91** · прочее **28** (8 prod / 20 test). То есть 93% errcheck — два идиоматических класса. + +**staticcheck по правилам:** QF1001 6 · SA1024 5 · ST1018 2 · QF1003 1 · S1021 1 · S1002 1 · QF1004 1. + +**Дополнительные замеры (кандидаты для этапа B):** + +``` +exhaustruct 988 bodyclose 0 copyloopvar 0 durationcheck 0 makezero 0 +errorlint 3 nilerr 3 rowserrcheck 2 sqlclosecheck 1 +``` + +### ⚠ НАХОДКА-2: число `exhaustruct` в §5.5 отчёта EFFORT_HANDLE — это СУЖЕННОЕ число, не глобальное + +Глобально **988**, а не 16. Суженный до двух типов, ради которых он предлагался, — **17** (`include: config\.Stage`, `pipeline\.Request`), что сходится с «16, из них 15 в тестах». Из 17 **шестнадцать — тестовые литералы, а семнадцатый — САМ ШОВ** (`config/internal_call.go:53`, `InternalCall.Stage()`), единственное разрешённое место постройки. Вывод промта («глобально не включать») подтверждён, но обоснование должно опираться на 988, а не на 16. + +--- + +## §2. Этап B — состав `.golangci.yml` (каждое правило обосновано числом) + +Файл: `backend/.golangci.yml` (первый в проекте). `golangci-lint config verify` → чисто. + +**ВКЛ:** `errcheck` 413→6 после исключений · `govet` 0 · `ineffassign` 0 · `staticcheck` 17→11 · `unused` 1 · `errorlint` 3 · `misspell` 4→0 · `nilerr` 3 · `rowserrcheck` 2 · `sqlclosecheck` 1 · `nolintlint` 0 · `bodyclose`/`copyloopvar`/`durationcheck`/`makezero` по 0 (бесплатны сегодня и не дают регрессировать; `bodyclose` сторожит провод к провайдерам). + +**ВЫКЛ с причиной (анти-хак-правило владельца: спорное правило гасится в КОНФИГЕ, а не обходом в коде):** + +- **`exhaustruct`** — 988 глобально; суженный флагует сам шов, а различать шов и обход умеет только анализатор §6. +- **`QF1001`** (6, «применить закон де Моргана») — текущая форма условий повторяет прозу над ними; переписывание ради линтера читается хуже правила, которое кодирует. Вкусовое, не класс дефектов. +- **`.Close`/`.Flush`** (294) — все 33 продовых места перечислены и проверены поштучно: это читатели и хендлы БД. Единственный в репо писатель с flush-on-Close (`chunktest/epub.go`, `zip.Writer`) свой `Close` **проверяет**, поэтому исключение не может спрятать потерянную запись. +- **`fmt.Fprint*`** (91) — рендер CLI в stdout; сломанный пайп на `tmctl status | head` не то, на что CLI может отреагировать. +- **`tx.Rollback`** (5) — идиома «откатить, если не закоммичено»; на счастливом пути ошибка = `sql.ErrTxDone` по построению. +- **`h.Write`** (2) — `hash.Hash.Write` документирован как никогда не возвращающий ошибку. +- **`initals`** — намеренная опечатка-фикстура: тесты лангпака пишут её в файл, чтобы доказать, что парсер ругается на неизвестный ключ. Исправление удалило бы тест. +- **`misspell.locale` НЕ выставлен.** Замерено: `locale: US` даёт **309** находок вместо 4 — он срабатывает на русских комментариях. + +**Режим внедрения: big-bang.** Критерий промта («всё с ≤20 находками») выполнен с запасом: после конфига остаётся **27** находок в **19** файлах, что ниже СТОП-порога «>30 файлов разом». `--new-from-rev` не понадобился. + +### Что из 27 оказалось настоящими дефектами, а не косметикой + +| место | что | почему это дефект | +|---|---|---| +| `pipeline/banknote.go:303` | `applyBanknote` мёртв | все вызовы (2 прод + 5 тест) идут в `applyBanknoteWithEntries`; удалён, док слит с живой функцией | +| `cmd/tmctl/backup.go:57` | `os.Stat` → любая ошибка = «свежая книга» | отказ по правам молча пропускал бэкап-гард перед платным прогоном. Стало `errors.Is(err, fs.ErrNotExist)` | +| `pipeline/mining.go:384` | то же на авто-банке | нечитаемый файл молча ронял намайненные строки | +| `cmd/tmctl/dotenv.go:55` | `os.Setenv` глотал ошибку | битая строка `.env` = ключ не загрузился, всплывало позже как 401 без причины. `loadDotEnv` теперь возвращает ошибку | +| `store/voice_test.go:41,44` | `raw.Query` с результатом в `_` | течёт `*sql.Rows` | +| `store/glossary.go:147` | три ручных `rows.Close()` | вынесено в `priorRenderings` — `defer` стал корректен, потому что жизнь rows теперь ограничена функцией и закрывается ДО `DELETE`-ов на том же tx | +| `lang/langpack.go:338` | `%v` вместо `%w`, и `serr` мог быть nil | разделено на два случая: нечитаемо (`%w`) и не каталог | +| `chunk/ingest.go:829` | `z.Err() != io.EOF` | обёрнутая ошибка прошла бы мимо | +| `miner/miner_alias.go:161` | `var find func(...)` + присваивание | замыкание НЕ рекурсивно (итеративное сжатие путей), так что staticcheck прав | + +**Одно место закрыто `//nolint` с причиной, а не правкой:** `synthetic_stage_seam_test.go` — `nilerr` на пропуске нечитаемого файла. Этот код удалён этапом E вместе с обходом. + +**Итог:** `golangci-lint run` → **0 issues**. + +--- + +## §3. Этап C — `make battery` + +`backend/Makefile`, цели `build · vet · fmt · lint · test · battery · battery-stand · tools-check`. + +- `battery` = герметичная часть: `build` → `vet` (оба тег-набора, с `-vettool`) → `gofmt` → `lint` → `test -race -count=1`, и в конце **НАЗЫВАЕТ пропущенные тесты** — молчаливый скип читается как покрытие. +- `battery-stand` = то же + `TM_MINER_PARITY=1 TM_CHECKER_LABELS=1`, где отсутствие данных **падает**, а не скипается. +- `fmt` проверяет ПУСТОТУ вывода `gofmt -l`: сама команда выходит с 0, даже когда перечисляет файлы. +- `tools-check` требует ровно golangci-lint 2.12.2 и не ставит его сам: находки версионно-зависимы, а гейт, меняющийся под тобой, не гейт. + +**CI-воркфлоу НЕ написан — решение владельца 03.08.** Установлено: удалёнка `ssh://git@git.vojo.chat:2222/heaven/textmachine.git` — **Forgejo 10.0.3** (`GET /api/v1/version` → `{"version":"10.0.3+gitea-1.22.0"}`), каталогов `.forgejo/` и `.github/` в репо нет, раннер не подтверждён. Файл лежал бы вне зоны `backend/`. Точка входа до появления раннера — `make battery`. + +--- + +## §4. Этап E — гарды на `x/tools/go/analysis` + +**Новое:** `backend/internal/archguard/` (три анализатора) + `backend/cmd/tmvet/` (multichecker). Запуск — `go vet -vettool=bin/tmvet ./...` из `make battery`, оба тег-набора. + +| анализатор | инвариант | +|---|---| +| `stageseam` | `config.Stage` строится только через `config.InternalCall.Stage()` | +| `requestseam` | `pipeline.Request` собирается только в `Runner.attemptRequest` | +| `egressseam` | к провайдеру ходит одно место — `stagerun.go runAttempt` (Д7) | + +### Паритет посадками (`analysistest`, `internal/archguard/testdata/`) + +| # | посадка | чем била предшественника | +|---|---|---| +| 1 | `config.Stage{…}` | — (исходные три дефектных сайта) | +| 2 | `&config.Stage{…}` | байтовый скан | +| 3 | `[]config.Stage{{…}}` | элидированный тип элемента: `CompositeLit.Type == nil` | +| 4 | `map[string]config.Stage{k:{…}}` | то же | +| 5 | `var s config.Stage` + присваивание полей | литерала нет вовсе | +| 6 | `new(config.Stage)` | то же | +| 7 | алиас импорта `cfg "…/config"` | матч по ИМЕНИ пакета | +| 8 | дот-импорт → `Stage{…}` | нет квалификатора | +| 9 | `type myStage = config.Stage` + `myStage{…}` | алиас типа | +| 10 | `type derivedStage config.Stage` | определённый тип поверх Stage | +| 11 | hoisted `req := pipeline.Request{…}` | скан по `RequestHash(Request{…})` | +| 12 | `[]pipeline.Request{{…}}` | элидированный элемент | +| 13 | алиас импорта пакета pipeline | матч по имени | +| 14 | `c.Complete(…)` через интерфейс | — | +| 15 | `h.Complete(…)` через конкретный адаптер | — | + +**Негативные контроли в тех же фикстурах** (гард, который флагует всё, бесполезен так же, как молчащий): вызов через шов `InternalCall{…}.Stage()` · `[]config.Stage` как ТИП поля/параметра · пустой `[]config.Stage{}` · `pipeline.Request` как параметр · **чужой метод с именем `Complete`** — байтовый скан ловил его, типовой не ловит. + +``` +go test ./internal/archguard/ -count=1 → ok +go vet -vettool=bin/tmvet ./... → (пусто) +``` + +**Что реально выиграно.** Не «алиасы закрываются по построению» — предшественник резолвил импорты по ПУТИ и алиас уже ловил. Выиграно два конкретных свойства: (а) `TypesInfo.TypeOf` даёт тип **элидированного** литерала, поэтому `[]T{{…}}` ловится без ручного разворачивания обёрток; (б) egress-инвариант различает НАШ `Complete` от чужого одноимённого метода — байтовый скан не мог и вынужден был исключать собственный исходник из совпадения с собственным же паттерном. + +### ⚠ Слепая зона `go/packages` — решение принято ЯВНО + +Предшественники ходили по ВСЕМУ репозиторию, доставая `eval/` — Go-файлы вне модуля, где жил исторический четвёртый дефектный сайт. Анализатор так не может: ему нужен собираемый пакет. + +**Замерено перед отказом:** в `eval/` три Go-программы — `softsign-decl/main.go`, `pkg7/termharness/main.go`, `pkg7/minerharness/main.go`. Одна (`termharness`) импортирует `internal/config` и `internal/pipeline`, но **ни одна не строит `config.Stage` или `pipeline.Request`**, и ни одна не собирается (`go.mod` в `eval/` нет: `go build` → `cannot find main module`). То есть охват сторожил ничто. + +**Решение (владелец 03.08):** охват `eval/` снят. Полигон — по CLAUDE.md чернорабочая зона; гейтить его не стоит ограничения на форму гарда. Если харнесс там когда-нибудь потребует покрытия, честная починка — `go.mod` в `eval/`, а не синтаксический обход здесь. Записано в доккомменте пакета. + +### Снесено / оставлено + +**Снесено** (после 15/15 у анализатора, последним шагом): +- `synthetic_stage_seam_test.go`: `TestSyntheticStageSeamIsSingle`, `TestRequestIdentitySeamIsSingle`, `walkGoFiles`, `fileImports`, `namedType`, `namedTypeExact`, `namedTypeLocal`, `walkedFileFloor`, `configPkgPath`, `pipelinePkgPath` — **396 → 143 строки**; +- `content_routing_test.go`: `TestProviderEgressSeamIsSingle` (байтовый гард Д7) — **−47 строк**. + +**Оставлено осознанно:** +- `TestInternalCallDecidesEveryStageField` — рефлексионный, не про обход дерева (промт прямо запрещает трогать); +- `TestBankProbeAndAttemptAddressOneCheckpoint`, `TestReasoningIsPartOfTheRequestIdentity`, `TestRepairStageTakesItsEffortFromItsOwnGate` — поведенческая половина: анализатор не отвечает на вопрос, доносит ли шов ручку до денежного пути. + +**Пол «я реально видел файлы»** (`walkedFileFloor = 50`) эквивалента не получил и не нуждается: `go vet` перечисляет пакеты сам и падает, если пакет не грузится, — обход не может тихо разобрать ноль файлов. + +--- + +## §5. Этап D — бамп зависимостей + +``` +go get golang.org/x/net@latest golang.org/x/text@latest gopkg.in/yaml.v3@latest modernc.org/sqlite@latest + golang.org/x/net v0.26.0 => v0.57.0 + golang.org/x/text v0.38.0 => v0.40.0 ← MVS тянет принудительно + golang.org/x/sys v0.44.0 => v0.47.0 + modernc.org/libc v1.73.4 => v1.74.1 + modernc.org/sqlite v1.53.0 => v1.55.0 ++ golang.org/x/tools v0.48.0 (под этап E) +``` + +### ⚠ НАХОДКА-3: бамп сдвинул денежную ось — и это был ВЫБОР, а не принуждение + +⚠ **ПОПРАВКА по адверсариальному ревью (03.08).** Изначально здесь стояло «`x/net` нельзя взять отдельно — MVS тянет `x/text` ПРИНУДИТЕЛЬНО». Это верно только для взятого мной `@latest`. Замерено ревьюером на чистой копии HEAD: `x/tools@v0.45.0` тянет `x/net v0.54.0`, чей `go.mod` требует `x/text v0.37.0` — **ниже нашего v0.38.0, то есть `x/text` НЕ двигается**, и весь стек анализатора на этой комбинации собирается и проходит. Значит перекупку снапшота вызвал мой выбор `@latest`, а не потребность этапа E. Владелец санкционировал бамп до фронтира отдельно и осознанно (03.08, книг в работе нет ⇒ цена нулевая), но формулировка «принудительно» была неверна и снята. Индустриальный способ навсегда развязать инструментальные зависимости от денежной оси — отдельный `tools/go.mod`; носитель заведён в §7. + +Второй ревьюер независимо **доказал, что бамп не меняет поведения**: NFC/NFKC байт-идентичны между x/text v0.38.0 и v0.40.0 на всех 1 112 064 скалярных значениях Unicode и на 400 000 случайных последовательностей 1–6 рун (одинаковый SHA-256 под обеими версиями). То есть сдвиг снапшота — чистая смена версионной метки. + +`x/net` при этом действительно тянет `x/text`. А `x/text` вшит в `memoryNormAlgoVersion` (`internal/text/norm.go:70`) специально ради этого случая. Сработал собственный тревожный тест проекта: + +``` +xTextVersion = "v0.38.0" but go.mod pins golang.org/x/text "v0.40.0" — bump the constant IN LOCKSTEP +``` + +Константа обновлена, следом обновлены два её зеркала: `text/enclosure_test.go:34` (полная строка версии) и `membank/memory_f1_test.go` (два хеша `ComputeVersionScoped`). + +**Заявление трекера про `x/tools` подтверждено исполнением.** Проверено на КОПИИ реального модуля: добавление `x/tools/go/analysis` поднимает `x/net 0.26.0 → 0.54.0`. (Чистый пробный модуль этого не показывает — там `x/tools` приходит один; связка возникает именно на нашем графе.) То есть этапы D и E действительно сцеплены. + +### Голден: что именно сдвинулось + +Голден пере-захвачен (`TM_UPDATE_GOLDEN=1`) — санкция владельца 03.08. **Дифф разобран механически, не глазами:** + +``` +изменённых строк: 90 +изменившихся по причине, ОТЛИЧНОЙ от hex-хеша: 0 + +content_hash идентичен n=32 disp идентичен n=68 +flag идентичен n=84 cost идентичен n=102 +finish идентичен n=86 degraded идентичен n=52 +tokens идентичен n=52 detail идентичен n=72 +escalated идентичен n=68 +``` + +`content_hash` — это `msgsContentHash`, подпись отрендеренных сообщений. Её неизменность означает, что **байты, уходящие модели, те же**. Сдвинулись только версионные идентификаторы: `memory_version` → `snapshot_*` → `RequestHash` (в него входит `SnapshotID`, `render.go:309`) → `final_hash`. **Таблицы Unicode в x/text 0.40 не изменили ни одного поведения на этой фикстуре.** + +### ⚠ НАХОДКА-4 (ревью): бамп `x/net` РЕАЛЬНО меняет байты на проводе + +Ревьюер поднял h2-слушателя с TLS+ALPN и прогнал через него дословную копию `keepAliveHTTPClient` +(`internal/llm/httpllm.go:79-99`) под обеими версиями. Два воспроизводимых расхождения: + +**(а) SETTINGS-фрейм клиента вырос 18 → 24 байта** — появился `SETTINGS_MAX_FRAME_SIZE` (id `0x0005`) = 16384: + +``` +v0.26.0 000200000000 000400400000 000600a00000 +v0.57.0 000200000000 000400400000 000500004000 000600a00000 +``` + +16384 — и так протокольный дефолт, то есть семантически инертно, но это НОВАЯ байтовая последовательность. + +**(б) Изменился ПОРЯДОК заголовков запроса** (HPACK, декодировано): + +``` +v0.26.0: :authority :method :path :scheme authorization accept x-title content-type content-length +v0.57.0: :authority :method :path :scheme accept x-title content-type authorization content-length +``` + +Набор и значения те же, регистр в обеих строчный (h2 это предписывает) — **смены регистра нет, изменился только порядок**. + +**Почему это важно.** Порядок заголовков и раскладка SETTINGS — ровно те входы, по которым фронты +бот-детекции (класса Akamai/Cloudflare) строят HTTP/2-фингерпринт клиента. Для провайдера за таким WAF +бамп меняет наш отпечаток. **Отреагирует ли конкретный провайдер — БЕЗ живого вызова не установить.** +Это не дефект, это неразрешённый вопрос — и ровно тот, ради которого промт требовал живую пробу. + +Заодно из 78 http2-коммитов в диапазоне: «do not retry RoundTrip after peer sends a stream protocol +error» · «don't PING a responsive server when resetting a stream» · «detect hung client connections by +confirming stream resets» — семантика ретраев и разрыва изменилась ПОД нашим собственным `retryLoop`. +RFC 9218 priority у нас НЕ активен: `client_priority_go126.go` возвращает `clientPriorityDisabled()=true` +для `!go1.27` именно чтобы не менять поведение при импорте. + +⚠ Это противоречит инварианту, записанному в `internal/llm/httpllm.go:75-78` («провод … не меняется, ноль +байт») — он верен для полей пинга, но не для бампа, который их привёз. Строку надо поправить. + +### ⚠ НАХОДКА-5 (ревью): вердикт-несущее использование x/text НЕ завёрнуто в версию + +Бамп x/text оказался громким **по случайности**. Единственная сворачивающая его версия — +`memoryNormAlgoVersion`, и она доезжает до снапшота только потому, что `membank.ComputeVersionScopedIn` +(`internal/membank/memory.go:390`) пишет `text.NormVersion()` безусловно. Всё остальное сворачивает +только stdlib-овский `unicode.Version` либо ничего: + +| Версия | Сворачивает | Какое x/text-поведение покрывает | +|---|---|---| +| `checks.SanitizerVersion` (`sanitizer.go:119`) | **ничего** | `width.Fold` (`:687`), `norm.NFC` (`:734`) | +| `checks.CheapGateVersion` (`cheapgates.go:99`) | `unicode.Version` | NFC-свёртку (по собственному комментарию `:59`) | +| `pipeline.chunkerVersion` (`render.go:53`) | `unicode.Version` | `text.NormalizeSource` → `norm.NFC` (`source.go:29`) | + +`detectCJKLeak` сворачивает ПЕРЕД решением (`sanitizer.go:211`), поэтому смена `width.Fold` +**переворачивает вердикт** → флаг → ремонт/эскалация → живые деньги, а `SanitizerVersion` стоит на месте. +И сама `SanitizerVersion` сворачивается только при ВКЛЮЧЁННОМ гейте (`snapshot.go:97-103`). + +Резче: `ExportNormalize` исполняется на КАЖДОМ отгружаемом финале, зависит от `width.Fold` + `norm.NFC`, +и при этом объявлена «НЕ входом снапшота/вердикта» (`sanitizer.go:709`). Смена x/text там поменяла бы +экспортируемые байты, не сдвинув ни одного хеша. Латентно, не сработало — но носитель нужен. + +### ⚠ НАХОДКА-6 (ревью): `xTextVersion` пинит строку go.mod, а НЕ скомпилированные таблицы + +`golang.org/x/text/unicode/norm` возит ДВА набора таблиц, выбираемых ТУЛЧЕЙНОМ: +`tables15.0.0.go //go:build !go1.27` и `tables17.0.0.go //go:build go1.27`. Сегодня +`go list -f '{{.GoFiles}}'` подтверждает: под go1.26.5 компилируется `tables15.0.0.go`. +**Тулчейн Go 1.27 переключит x/text на таблицы Unicode 17.0.0, не тронув `xTextVersion`.** +Комментарий `norm.go:62-68` утверждает, что константа делает собственную Unicode-редакцию x/text громкой — +она этого не делает. Вероятно спасает смежное: stdlib-овский `unicode.Version` на том же тулчейне тоже +сдвинется, а он свёрнут. Но это совпадение, а не механизм; стоит превратить в явную проверку. + +### Дифференциал нормализации: РАЗРЕШЕНО, поведение не изменилось + +Исходники `unicode/norm` действительно правились (`forminfo.go`, `iter.go`, `normalize.go`: путь +невалидного UTF-8 переписан с `sz==0 → sz=1` на явный сентинел `Properties{flags:0x80}` + маску `& 0x3f`). +Таблицы `norm` и весь пакет `width` — байт-идентичны. Прогон нормализаторов репо и всех примитивов x/text, +которые дёргает `internal/checks`, под обеими версиями: + +| корпус | входов | результат | +|---|---|---| +| каждое скалярное значение Unicode, отдельно + после 5 баз + перед 6 комб. знаками + 46 фикстур | **13 344 816** | идентично | +| невалидный/усечённый UTF-8 (все 1-байтовые, все 2/3-байтовые лиды, усечения в 7 префиксах × 5 суффиксах, оверлонги, суррогаты, вне диапазона, в CJK/кириллица/хангыль-контексте) | **263 560** | идентично | +| `~/books/gu-zhenren/labels/raw/corpus.jsonl` — значения, строки, предложения, слова, руны, пары и тройки рун | **3 561 250** входов / 12 133 355 рун / **2 568 различных кодпойнтов** | идентично | + +**Ноль расходящихся кодпойнтов.** Это несравнимо сильнее моего собственного доказательства по голдену. + +### Голден: моя проверка смотрела не на то поле + +Мой масочный дифф воспроизводится, но `content_hash/disp/flag/cost/...` — не тот набор. Поле, способное +спрятать смысловое изменение под видом хеша, это **`final_hash`**: для двух санитайзерных строк он равен +`sha256("tm-sanitized-v1\0" + reqHash + "\0" + stripped)` (`stagerun.go:355`), то есть сворачивает +ФАКТИЧЕСКИЙ экспортный текст. Изменившийся текст и смена версии в нём неразличимы. + +Вопрос закрывает то, что голден пишет и сырой текст: `final_text=%q` (`golden_test.go:217`), +`stage_text=%q` (`:223`) и 18 тел запросов (`:280`) — **эти 68 строк байт-идентичны**, проверено прямо. + +Голден НЕ записывает (`golden_test.go:174-176`) латентность, таймстемпы, пути, URL — и, не будучи +перечисленным, **заголовки запроса и фрейминг транспорта**. Поэтому находка-4 ему невидима by construction. + +### ⚠ Живая проба провода НЕ проводилась + +Промт требует после бампа `x/net` мини-вызов на КАЖДОГО провайдера (потолок $0.50) со сверкой тел, ключей, `reasoning_content`, `finish_reason` и отсутствия новых заголовков против `00-provider-quirks.md`. **Не сделано:** отдельной санкции на трату не было, а ключи провайдеров лежат в `backend/.env`, который читать запрещено. + +Чем закрыто вместо неё ($0): полная батарея под `-race` зелёная · голден разобран построчно, включая сырой текст · нормализация доказана идентичной на 17 млн входов (выше) · `sqlite` 1.55 проверен по changelog: новые DSN-сокращения нас не касаются, репо использует только канонические `_pragma(...)`/`_txlock`. + +⚠ **После находки-4 живая проба нужна СИЛЬНЕЕ, чем считал промт.** httptest говорит HTTP/1.1 без ALPN, поэтому путь h2 в тестах не исполняется вовсе, а на h2 отпечаток клиента ИЗМЕНИЛСЯ (порядок заголовков + SETTINGS). Установить реакцию провайдеров можно только вызовом. **Носитель обязателен.** + +--- + +## §6. Батарея + +``` +make battery-stand → EXIT=0 +``` + +- `golangci-lint` — **0 issues** +- `go vet` + `go vet -tags live`, оба с `-vettool=bin/tmvet` — чисто +- `gofmt -l` — пусто +- `go test ./... -race -count=1` — 14 пакетов ok, 0 FAIL, 0 DATA RACE + +**Стенд-данные на машине присутствуют**, поэтому корпусные тесты реально исполнились. Замороженные числа держатся: + +``` +PARITY: n=13618 catastrophe{方源:0 蛊:1 蛊师:2 古月:22} recall@proposed=0.9655 (56/58 GT) +K6 BASELINE: tp=1 fp=14 fn=0 tn=243 disp=2 +K6 AFTER (stemmer + #10): tp=1 fp=6 fn=0 tn=251 disp=2 +k2 92 34/1/6/51 · k4_inverse 75 3/0/1/71 · k4a 348 0/0/0/348 · k4b 146 10/1/36/99 +``` + +**Артефакт контраста восстановлен.** `eval/exp16/data/jieba_dict_general_zh.txt` отсутствовал → `TestMinerFullBookParity` скипался. Пере-собран из `jieba==0.42.1`; **полный sha256 `7197c3211ddd98962b036cdf40324d1ea2bfaa12bd028e68faa70111a88e12a8`** совпал с урезанным пином `7197c321…e12a8` в `docs/experiments/16-bank-mining.md:183`. Файл остаётся вне git (`eval/.gitignore:4`). + +В `make battery` (без стенда) скип теперь ровно один — `TestHelperKillLoop` (подпроцессный хелпер, by design). + +--- + +## §7. Найдено, не починено — нужны носители + +| # | находка | почему не мной | +|---|---|---| +| 1 | **Строка 112 трекера несёт ошибочный адрес `c2:39`** (§0) | `docs/` — зона оркестратора | +| 2 | **Живая проба провода после бампа `x/net`** (§5) | нужна санкция на трату + ключи | +| 3 | **Урезанный sha256 в `16-bank-mining.md:183`** — полный записан в §6 | зона оркестратора | +| 4 | **`jieba==0.42.1` не в `eval/requirements.txt`** — это build-time зависимость артефакта, не runtime (ни один скрипт полигона `jieba` не импортирует) | зона полигона | +| 5 | **Число `exhaustruct` в §5.5 EFFORT_HANDLE читается как глобальное** (§1) | зона оркестратора | +| 6 | **`TestCheckerLabelsCandidates` не содержит ни одного ассерта** — не может упасть; сегодня это дизайн-REPL в одежде теста | отдельная задача, не в скоупе промта | +| 7 | **`TestMemoryVersionPinsTheUnverifiedRenderRevision` не различает** «изменился рендер» и «изменилась версия нормализации» — оба двигают его литералы | пин работает, но его сообщение вводит в заблуждение | +| 8 | **`buildCheckers` жёстко берёт `lang.Load(root,"zh","ru")`**, а бейзлайны ключуются по классу, не по паре | приезд ja-ru потребует правки Go — против мандата общности | +| 9 | **`backend/README.md:3`** заявляет, что границу импортов «проверяет `go list -deps`» — не автоматизировано ничем | кандидат в четвёртый анализатор `archguard` | +| 10 | **Инструментальные зависимости в главном модуле.** `x/tools` нужен только для `cmd/tmvet`, но живёт в `backend/go.mod` и потому участвует в MVS вместе с `x/net`/`x/text`. Штатное лекарство — отдельный `tools/go.mod` (или `tool`-директива Go 1.24 в отдельном модуле): тогда линтинг физически не может двинуть снапшот | требует решения по структуре модулей | +| 11 | **`modernc.org/sqlite 1.53.0 → 1.55.0` не требовался ничем** — приехал вместе с `@latest`. Это драйвер под денежным леджером и чекпойнтами | входит в то же решение по бампу | +| 12 | **Анализатор не ловит четыре формы**, дающие тот же дефект D39.87: встраивание структуры, `make([]config.Stage, 1)` + присваивание полей, дженерик-ноль, — предшественники их тоже не ловили (не регрессия). Класс закрывается НЕ длинным switch, а типом: сделать нулевое значение `config.Stage` непригодным вне своего пакета | отдельная задача | +| 13 | **`go vet` покрывает только теги `default` и `live`.** Файл за любым другим build-тегом невидим (старый обход парсил исходники независимо от тегов). Сегодня других тегов в репо нет | политика, не свойство | + +--- + +## §8. Что осталось от промта неисполненным + +- **Живая мини-проба провода этапа D** (§5) — единственный пункт промта, не закрытый ни исполнением, ни обоснованным отказом. Нужна санкция. +- **CI-воркфлоу** — не написан по решению владельца 03.08 (§3), не по недосмотру. +- **`tmctl status --config` на пяти конфигах** — команда для этого не предназначена (§0); заменено существующими тестами загрузки. + + +--- + +## §9. Адверсариальное ревью пака (03.08, по требованию владельца) + +Четыре независимых ревьюера по диффу: корректность правок · паритет анализатора · денежная ось и детерминизм · индустриальность. Каждый проверял ИСПОЛНЕНИЕМ; двое реконструировали снесённые гарды из истории и стравили их с новым на одних подсадках. + +**Найдено и починено (всё — в моём коде):** + +| # | дефект | статус | +|---|---|---| +| 1 | `egressseam` обходился локально объявленным интерфейсом с тем же методом: `Obj().Pkg()` становился пакетом потребителя. Байтовый гард это ловил — прямая регрессия | починено сканом СИГНАТУРЫ (подставимый интерфейс обязан упоминать типы `llm`), посадка 17 | +| 2 | Исключения потеряли сегмент `/backend/` — вложенный `internal/` и второй модуль `platform/` наследовали их | восстановлен полный путь | +| 3 | Внешние тестовые пакеты (`…/config_test`) не покрывались пропуском пакета ⇒ ложные срабатывания | `inPackage()` со срезом `_test` | +| 4 | Конверсия `config.Stage(twin{…})` не ловилась — ветка `CallExpr` смотрела только на `new` | добавлена, посадка 16 | +| 5 | `new` опознавался по ИМЕНИ идентификатора, хотя репо шадовит встроенные имена в 22 местах | сверка с `types.Universe.Lookup("new")` | +| 6 | **Инвариант ушёл из `go test`** — держался только на `make vet` | `shippingtree_test.go`: те же `Analyzers()` через `checker.Analyze` по всему модулю; доказано подсадкой | +| 7 | Пол «я реально видел файлы» не был восстановлен: пустой `Analyzers()` оставлял всё зелёным | `packageFloor` + ассерт длины `Analyzers()` + проверка ошибок загрузки пакетов | +| 8 | `go vet -vettool` ЗАМЕЩАЕТ штатный набор vet, а комментарий утверждал обратное | `make vet` гоняет оба прохода; комментарий исправлен | +| 9 | Тест-исключение errcheck из-за необязательной группы в regex глушило безымянный класс во всех 115 тестах | сужено; вскрылись 12 скрытых находок — все `runToSignatureStop`, исключены точечно с причиной | +| 10 | `$(GO)fmt` — склейка строк: `make GO=go1.26.5 fmt` звал `go1.26.5fmt` | `gofmt` напрямую | +| 11 | `GO_MIN_VERSION` объявлен и не использован, шапка заявляла «тулчейн пиноват» | добавлена проверка версии Go в `tools-check` | +| 12 | Сбор скипов глушил stderr и терял свой код возврата: падение теста БЕЗ `-race` прошло бы незамеченным | падение пробрасывается | +| 13 | `loadDotEnv`: `os.Open` глотал ЛЮБУЮ ошибку (файл под 0000 = ключи молча не загружены) | различает `fs.ErrNotExist`, остальное — предупреждение | +| 14 | **Моя же регрессия:** возврат ошибки из `loadDotEnv` ронял `status`/`report`/`export` на кривой строке `.env` — против D20.4 («аудит-поверхность не требует ключей»), и последующие валидные строки не применялись | предупреждает, не падает; остальные строки грузятся | +| 15 | Обоснование `misspell.locale` было фактически неверным (не русские комментарии, а en-GB↔en-US в английской прозе; 0 против 311, а не 4 против 309) | переписано по замеру | +| 16 | Исключения `h.Write`/`tx.Rollback` ключевались на ИМЕНИ переменной — `hasher.Write` дал бы находку и толкнул к переименованию ради линтера | ключ по методу | +| 17 | Числа в комментариях конфига поданы настоящим временем, хотя всё названное уже починено | помечены как провенанс | +| 18 | Оборванный комментарий-хвост от снесённого гарда | убран | + +**Подтверждено чистым:** `analysistest` честен в обе стороны (сломанный анализатор роняет тест мутацией `isNamed`; негативные контроли ловят лишнее срабатывание) · `make battery` анализатор действительно несёт (проверено подсадкой) · ложных срабатываний на `[]config.Stage` как типе нет, и новый анализатор ЧИНИТ старое ложное срабатывание на `[]config.Stage{}` · обе правки строковых литералов байт-эквивалентны (дубль ASCII-пробела в cutset-МНОЖЕСТВЕ; `\x1f` = тот же байт) · `priorRenderings` поведенчески идентичен, пустая карта не nil, rows закрываются до `DELETE` · `preflightBackup`/`loadAutoBank` — новые ошибки возникают до любой траты · `miner_alias.go` замыкание действительно не рекурсивно · зона соблюдена, генеративность не нарушена. + +**Замеры пропущенных линтеров** (report-only, на этом дереве): gosec 250 (шум: G104 115 — дубль errcheck, G304 56, G306 53) · revive 80 · perfsprint 32 · exhaustive 11 · noctx 11 · prealloc 10 · gocritic 7 · errname 5 · **wastedassign 2** · **unconvert 1** · usestdlibvars/predeclared/nakedret 0. Ревьюер справедливо отмечает: `unconvert` (1) и `wastedassign` (2) дешевле уже включённых `errorlint` (3) и `nilerr` (3) — по собственному правилу конфига их стоит включить. Носитель — эта строка. diff --git a/docs/experiments/16-bank-mining.md b/docs/experiments/16-bank-mining.md index 0c88ace5..9a96dc9c 100644 --- a/docs/experiments/16-bank-mining.md +++ b/docs/experiments/16-bank-mining.md @@ -180,8 +180,8 @@ A1–A3+абл ($0) → алиас ($0) → A6/A6b (стенд $0) → cold-star - Код `miner-v1` (SHA256): exp16_common `92bc737a` · detectors `89059e53` · patterns `7ac8240c` · spread `5422415f` · palladius `a071295e` · arms `a5ed2ae2` · run_arms `c4e3e17d` · banknote `069ad8fe` · coldstart_gen `70c8d9c1` · alias `354172fa` · canon `e947ebf3` · reaudit_14b `8d95ad58` · length_sweep `59a60b15`. -- Словарь-артефакт (контраст): `data/jieba_dict_general_zh.txt` **sha256 `7197c321…e12a8`** (jieba 0.42.1 - `dict.txt`, общий zh word-freq; вне git — воспроизводим из jieba 0.42.1, SHA пиннится здесь). +- Словарь-артефакт (контраст): `data/jieba_dict_general_zh.txt` **sha256 `7197c3211ddd98962b036cdf40324d1ea2bfaa12bd028e68faa70111a88e12a8`** (jieba 0.42.1 + `dict.txt`, общий zh word-freq; вне git — воспроизводим из jieba 0.42.1, SHA пиннится здесь; полный хеш вместо урезанного — испр. оркестратором 03.08 по D39.96: пере-сборка бэкенд-сессией из jieba==0.42.1 сошлась с пином). - Сид `175a67ad…` · records `3de49eaf…` · translator.md `35d3ad6e…` · бэкенд HEAD `b9e62a7`. ### 1.11. Решения владельца, вшитые (17–18.07, НЕ пересматривать)