textmachine/docs/PROGRESS.md

520 lines
143 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Журнал прогресса
## 2026-07-04 — Старт проекта (MVP-сессия)
- Прочитан стартовый бриф `START_PROMT.MD` (37 пунктов идей).
- Осмотрена кодовая база `/home/ubuntu/projects/vojo/apps/ai-bot`: Go-сервис с адаптерами LLM-провайдеров (gemini, xai, local), роутером, каскадом, фейловером, прайсингом и телеметрией — кандидат на переиспользование.
- Запущен мультиагентный исследовательский воркфлоу (10 направлений параллельно + критик полноты + добор пробелов):
1. Рынок и спрос → `research/01-market.md`
2. Конкуренты и существующие решения → `research/02-competitors.md`
3. Научные работы по agentic/document-level MT → `research/03-academic-agentic-mt.md`
4. LLM API: цены/качество/цензура → `research/04-api-providers.md`
5. Память и глоссарий (банк памяти книги) → `research/05-memory-glossary.md`
6. Локальные модели на 8GB VRAM → `research/06-local-models.md`
7. Методология профессионального худ. перевода → `research/07-translation-methodology.md`
8. Юридические аспекты → `research/08-legal.md`
9. Модель стоимости перевода книги → `research/09-cost-model.md`
10. Ревью vojo/ai-bot на переиспользование → `research/10-vojo-ai-bot-review.md`
- Добор пробелов от критика → `research/11-gap-*.md`
### Исследования завершены (04.07, ~2 млн токенов, 16 агентов)
Все 15 документов в `research/`. Ключевые развязки:
- Статья «про судью-селектора, март 2026» найдена: arXiv:2603.20324 «When Agents Disagree» — но перевода среди её задач нет; на zh→ru/ja→ru нужен собственный пилот (см. `research/11-gap-3.md`).
- MemPalace существует, но форкать нельзя (метрики не подтверждаются) — банк памяти пишем сами: SQLite + спека SillyTavern World Info + память DelTA.
- «Ru-нишу никто не обслуживает» — опровергнуто: Rulate AI-раздел 14,4 тыс. работ, MLate, VseGPT «Нейропереводчик» 999 ₽/мес. Дифференциация — издательское качество, память серии, 18+.
- Экономика сходится: COGS тома ранобэ ~$24 при марже 7096%; главные рычаги — prompt caching (до 98% input) и Batch API (50%).
- OpenAI adult mode заморожен бессрочно — NSFW-канал: Grok / open-weights / DeepSeek / локальная abliterated. Anthropic — только «стерильные» роли.
- RU-сегмент: BYOK-модель (агрегаторы ProxyAPI/VseGPT/AITunnel или прямой DeepSeek), не перепродавать западные токены.
### Синтез (04.07)
- `architecture/01-decisions.md` — 10 решений (Р1 Go-бэкенд на базе vojo/ai-bot; Р2 конфигурируемое ядро пайплайна + пилот 4 рук; Р3 банк памяти на SQLite; Р4 модельный стек и NSFW-роутинг; Р5 экономика вызовов; Р6 durable jobs; Р7 телеметрия/качество; Р8 юр-позиция «инструмент, не платформа»; Р9 прайсинг-гипотеза; Р10 риски).
- `architecture/02-mvp-plan.md` — фазы 03 с критериями приёмки.
- `architecture/components.puml` + `pipeline.puml` (+ отрендеренные .svg) — провалидированы PlantUML.
- `PARALLEL_SESSION_PROMPT.md` — промт для второй сессии («Полигон»: токен-замеры, refusal-бенчмарк, локальный стенд, пилотный корпус, эмбеддинги).
- Проведено адверсариальное ревью синтеза тремя критиками (техархитектура, экономика, red-team): 2 critical + ~15 major находок, все внесены в v2 документов. Главные исправления:
- экономика разделена на контуры «чей ключ» (прямые ключи / ru-агрегаторы ×26 на флагманы / BYOK) — премиум-микс с Sonnet в ru-контуре недоступен;
- разрешён конфликт «кэшируемый префикс vs селективный глоссарий» (зафиксирована раскладка промпта) и «modernc.org/sqlite vs sqlite-vec» (в MVP — brute-force KNN, без C-расширений);
- Фаза 1 получила интерим-правило 18+ (SFW-приёмка, исключение Anthropic при 18+ в brief) — до этого 18+ книги шли бы через Anthropic до появления NSFW-роутера;
- resume пересобран на чанк-чекпоинты (kill -9 теряет максимум один вызов);
- пилот вынесен в отдельную Фазу 2.5, горизонт MVP честно сдвинут до 1011 недель;
- baseline метрики качества заменён с «сырой DeepSeek» на «DeepSeek+глоссарий» (уровень VseGPT), порог — статистический;
- в план добавлены режим онгоинга и series-bible-lite (сегмент «ИИ-фабрик» и проверка рода/ты-вы).
### Следующие шаги
- [ ] Фаза 01 бэкенда — **передана отдельной сессии «Бэкенд»** (промт: `BACKEND_SESSION_PROMPT.md`; шаг 0 — перевалидация решений, финал фаз — агентное селфревью). Оркестратор делает внешнее ревью её кода.
- [x] Параллельная сессия «Полигон» запущена (эксперименты 0103 идут).
- [ ] Сессия «Редакция» (промпты ролей) — после фиксации формата конфига в Фазе 0.
- [x] Сессия «Валидация банка памяти» — завершена (вердикт GO на схему+гейты; реестр `architecture/06`; ставка гейтится in-house eval'ом в пилоте Ф2.5).
- [ ] Пилот 4 рук для выбора ядра пайплайна + **in-house memory-eval** (Фаза 2.5).
- Роли сессий: «Бэкенд» → `backend/`; «Полигон» → `eval/` + `docs/experiments/`; оркестратор → доки, ревью, синхронизация, дозаправки ресёрча.
- [x] **Дозаправка ресёрча выполнена (04.07, оркестратор)**: 5 документов `research/12-*.md` (~70 режимов отказа: ja, zh, ru-сторона; отзывы потребителей по продуктам; академические таксономии DITING/BlonDe/LitEval/LAIT) + верификация (3 minor: неточная ссылка поправлена; 2 пробела — числительные/меры CJK и западные имена через катакану — включены в карту как дыры с действиями). Итоговая карта «проблема → механизм бэкенда» → `architecture/04-unhappy-paths.md`; в ней раздел «Следствия для плана» — 7 изменений (пре-пасс Annotator в Фазе 2, расширение схемы глоссария, 4 новых дешёвых гейта Фазы 1, судья-анкета с MQM-весами, alignment-защита рефренов, эскалация по цене правки, регрессионный сьют из примеров).
## Бэкенд
### 2026-07-04 — Сессия 1: шаг 0 (перевалидация) завершён
- Донорский код vojo сверен построчно + воркфлоу из 4 критиков (консистентность, Go-исполнимость, донор, онлайн-фактчек цен). Вердикт: **архитектура v2 исполнима, кодить можно**; блокеров нет. Полный вердикт и контракты Фазы 0 → [architecture/03-implementation-notes.md](architecture/03-implementation-notes.md).
- Главные находки валидации (упущения передачи): в `Usage` донора нет cache-write Anthropic (×1.25/×2 — тот же класс ошибки, что недоучёт reasoning 3044%); в транспорте донора скрытый захардкоженный per-attempt таймаут 60 с (полигон видел только 45 с ноги failover); `http.Client{}` донора уйдёт в webshare-прокси на не-loopback локальных адресах (172.x); **Grok 4.1 Fast retired 15.05.2026** — слаги молча редиректят на grok-4.3 с ценой ×9, таблица Р4 устарела; store.go на SQLite — переписывание по семантике, не «адаптация <20%».
- Окружение: git-репо инициализирован, Go 1.26.4 установлен (~/sdk/go, PATH в .bashrc).
**[НУЖНО РЕШЕНИЕ]** (детали в 03-implementation-notes §5):
1. Формула премиум-бюджета Р5 «≤2×» после токен-калибровки неоднозначна реализую конфигурируемый $-потолок, формулу уточнить.
2. Политика инвалидации TM сверх brief_hash (prompt_version в ключе? модель? перечанкование?) реализую консервативный вариант, нужно подтверждение.
3. Канал B остался без дешёвого Grok (4.1 Fast retired, grok-4.3 дороже ×9) перевыбрать модель канала B к Фазе 2.
4. Стриминг: эмпирика полигона требует его как keep-alive транспорта (не SSE-фронт) предлагаю перенести из Фазы 3 в Фазу 12; в Фазе 0 закрываю длинными таймаутами.
5. Оркестратору, не блокирует: цифры Р5 устарели ~2× против эксп. 01; задача «cache-hit агрегаторов» задвоена (Фаза 0 бэкенда бэклог полигона предлагаю отдать полигону); мелкие фазовые пометки в диаграммах.
Вопросы владельцу: ключи провайдеров для `backend/.env` (DeepSeek минимум на нём приёмка Фазы 0 с реальным вызовом; Anthropic для проверки cache_control). Не блокируюсь: тесты на httptest-моках.
> **Ответ оркестратора на [НУЖНО РЕШЕНИЕ] (04.07).** Отличный шаг 0 — фактчек Grok и cache-write Anthropic особенно ценны. Решения:
> 1. **Премиум-бюджет**: подтверждаю $-потолок; формула зафиксирована в Р5 (`clamp(price_target × (1 target_margin) est_base_cogs, 0, hard_cap)`, дефолты $5/том, $30/вебновелла-500). «≤2×» — только прикидочная эвристика доков.
> 2. **TM-инвалидация**: консервативный ключ подтверждён и зафиксирован в Р6: `(chunk_src_hash, lang_pair, model_id, prompt_version, brief_hash, context_snapshot_hash)`; перечанкование инвалидирует by design.
> 3. **Канал B**: Р4 обновлён — интерим до Фазы 2: DeepSeek офиц. + локальная abliterated; Grok 4.3 только как дорогая эскалация; перевыбор дешёвого пермиссивного тира — по результатам refusal-бенчмарка полигона.
> 4. **Стриминг**: перенос одобрен — транспортный keep-alive-стриминг в Фазу 12 (без SSE-фронта), зафиксировано в плане; в Фазе 0 — длинные per-роль таймауты.
> 5. **Р5 обновлён** сноской на токен-калибровку (×1.41.75 для zh→ru); задача «cache-hit агрегаторов» снята с Фазы 0 — она в бэклоге полигона.
> **Новая вводная**: готова карта режимов отказа [architecture/04-unhappy-paths.md](architecture/04-unhappy-paths.md) (~70 режимов → механизмы). Перед фиксацией схемы store/глоссария Фазы 1 прочитай раздел «Следствия для плана»: расширение полей глоссария (alias-граф, ranked-set, gender=hidden, first_person, translit_policy), ruby-парсер в спеку импорта, дешёвые детерминированные гейты Фазы 1 (линтер прямой речи, блок-лист транслит-междометий, ёфикатор, число-гейт 万/億), словарь тегов ошибок с MQM-весами в request_log с первого дня. Пороги coverage-гейта уже сняты полигоном (см. его секцию, эксперимент 02).
### 2026-07-04 — Сессия 2: Фаза 0 (каркас) ЗАВЕРШЕНА
Каркас `backend/` собран, приёмка Фазы 0 продемонстрирована **исполняемо**: `tmctl translate --config book.yaml`
гоняет чанк draftedit с полным учётом $ по стадиям в request_log; повторный запуск обслуживается из
чекпоинтов за $0 (ledger неизменен); `kill -9`-тест настоящим SIGKILL подтверждает инвариант
`committed == SUM(checkpoints)` (деньги чекпоинты). `go test ./...`, `go vet`, `-race` зелёные.
- **Порт vojo internal/llm|ledger|obs**: нейтральные типы (+`CacheCreationTokens`, `CacheBoundary`,
`FinishReason`); общий OpenAI-совместимый транспорт (таймауты-параметры per-провайдер, Retry-After с капом,
overflow-safe backoff, LimitReader, оба варианта cache-полей DeepSeek); **нативный Anthropic-адаптер**
(Messages API, `cache_control`, суммирование usage-инварианта, sampling не шлётся); local-адаптер с no-proxy
транспортом (грабли стенда 172.x); failover с анти-flapping брейкером; ledger с cache-write и `PriceForResponse`.
- **internal/store (SQLite, modernc, CGO-free)**: идемпотентные миграции; reserve/settle с потолками книга/день;
**settle+checkpoint одной транзакцией** (закрыта дыра двойной оплаты); flock-владение проектным файлом;
recovery зависших резервов; request_log.
- **internal/config (fail-fast)**: models.yaml (цены с датой проверки, `CheckKeys` preflight), pipeline C1+C2
(граница «конфиг vs код» Р2, `CheckRunnable` guard на механику Фазы 2), book.yaml + brief_hash.
- **internal/pipeline**: детерминированный однопроходный рендер (инвариант §3.1), request-hash (length-prefix,
attempt-измерение), snapshot-pinning с `--resnapshot`, нормализация источника (BOM/CRLF/NFC), мини-раннер
draftedit с resume; cmd/tmctl (translate/report); черновики промптов ролей.
- **Финал агентное селфревью**: `/code-review` (8 линз) + воркфлоу-критики (4 линзы задания) с адверсариальной
верификацией; подтверждённые находки исправлены двумя волнами (детали и остаточный техдолг
[03-implementation-notes §6](architecture/03-implementation-notes.md)). Коммиты: `dc6ea8e` каркас
`a32ec2e` волна 1 волна 2.
Учтено из ответа оркестратора: ключ TM `(chunk_src_hash, lang_pair, model_id, prompt_version, brief_hash,
context_snapshot_hash)` совпадает с составом моего snapshot-payload (prompt_version+model+PromptSHA256 per-role,
brief_hash, chunker/estimator version); перечанкование инвалидирует by design (chunkerVersion в snapshot).
Карту 04-unhappy-paths заберу в схему store/глоссария при старте Фазы 1.
**Остаток техдолга Фазы 0** (осознанные ограничения, не блокеры; детали §6): дневной потолок пер-книжный;
timeout-путь «оплачено-но-потеряно» (≤1 вызов, укладывается в Р6); cache_ttlcache_write под один TTL (5m);
гонка `Runner.clients` (безопасна при последовательном проходе, мьютекс к fan-out Фазы 12).
**Ключи: бэкенд заводится на ДВУХ ключах** (`DEEPSEEK_API_KEY` + `ZAI_API_KEY`) по замечанию владельца сузил
`CheckKeys`: модели стадий проверяются всегда, модели эскалационных цепочек только если включён хоть один гейт
(эскалация запускается по провалу гейта; в Фазе 0 гейты off цепочки недостижимы ключи Anthropic/Kimi не
нужны). Проверено на боевых конфигах: с 2 ключами прогон доходит до сетевого вызова DeepSeek. `.env.example`
размечен «нужны сейчас / Фаза 1+ опционально». Anthropic/Kimi для Фазы 0 не требуются.
### Вопросы от бэкенда — сессии «Полигон» и оркестратору (04.07)
Владелец резонно заметил: бэкенд не должен коммититься в модели, которых полигон не гонял. Прежде чем в Фазе 1
включать эскалацию и фиксировать редактора-дефолт, нужны замеры:
1. **Полигону — Anthropic на «стерильном» канале (SFW).** Sonnet 5 как SFW-эскалация/судья **не валидирован**:
в refusal-бенчмарке Anthropic исключён намеренно (гигиена NSFW-аккаунта, gap-2 §3), но сам эксп. 02 отметил
«уровень L0L1 можно добавить отдельным конфигом для проверки стерильного канала». Можно ли прогнать
Sonnet-5 (промо $2/$10) на чистых SFW-фрагментах качество ru-редактуры/суждения чтобы знать, окупает ли
он цену как эскалация? Если не приоритет бэкенд держит Anthropic **вне** дефолтной цепочки и берёт
валидированную дешёвую модель.
2. **Полигону — качество редактора ru-стиля.** Эксп. 02 мерил роль ЧЕРНОВИКА (отказы/вырезания), но не роль
РЕДАКТОРА. Дефолт C1 GLM-5 на редактуре стоит на утверждении Р4, без замера. Планируется ли маленькое
сравнение GLM-5 vs Kimi-K2.6 (vs Sonnet-5, если будет ключ) по ru-редактуре на нескольких SFW-фрагментах?
От этого зависит дефолт редактора Фазы 1.
3. **Оркестратору — эскалационный дефолт в RU-контуре.** Оставить Anthropic Sonnet дефолтом эскалации или в
RU-контуре взять GLM-5.1/Gemini (Sonnet только прямой контур, где per-book-премиум оправдан)? Это правка
Р4/экономики; бэкенд только исполнитель конфига.
4. **Оркестратору — per-role provider-fallback?** Для batch-джобы (не live-бот) провайдер-недоступность
естественно закрывается durable jobs + чекпоинтами (лёг пауза resume без переоплаты), поэтому
мгновенный fallback на другого провайдера nice-to-have, не блокер. Добавлять ли простой список фоллбеков
на роль (`draft: [deepseek, glm]`) для длинных ночных прогонов, или полагаться на pause/resume? Решение за
оркестратором (владеет Р4/экономикой).
Не блокирует Фазу 0 (принята на DeepSeek+Z.ai); ответы нужны к старту Фазы 1 (эскалация, дефолты ролей).
### Внешнее ревью Фазы 0 — принято (04.07)
Независимая сессия провела построчное ревью `backend/` + исполняемую приёмку + адверсариальный воркфлоу.
**Вердикт: Фаза 0 принята, блокеров ноль.** Детали и диспозиция находок [03-implementation-notes §6](architecture/03-implementation-notes.md).
Кратко: F1 (CheckKeys) уже был закрыт до ревью; F2/F5/F7/F8 исправлены этой волной (local-оверрайды в snapshot;
fail-loud на включённый гейт в Фазе 0; поправка §3.4 под подтверждённый ключ TM; `*.db.lock` в .gitignore);
F3/F4/F6 в техдолг (F3: граница timeout-недоучёта уточнена до `MaxAttempts1`, не «≤1»; честный фикс
idempotency-ключ, отложено). Дизайн-вопросы к владельцу/оркестратору D1D3 (монолингвальный редактор Фазы 1;
per-chunk skip+flag вместо падения; структурный запрет Anthropic в канале B при подключении failover)
зафиксированы в §6, все Фаза 12.
Следующее: Фаза 1 (перевод книги целиком) чанкер, банк памяти v1, гейты (пороги полигона готовы), режим онгоинга.
### Реальная приёмка на живых ключах — PASS (04.07, ревьюер)
Первый реальный прогон провайдеров (раньше всё было на моках главный незакрытый пробел ревью). `tmctl translate`
на `example/book.yaml` (draft=deepseek-v4-flash edit=glm-5, один чанк 264 симв., потолок $1.00):
- **Деньги сходятся до цента**: draft $0.000219 (453·0.14+556·0.28/1e6 ✓), edit $0.001277 (672·1.0+189·3.2/1e6 ✓);
`committed == Σстадий == $0.001496`, `reserved=0`. Порядок величин совпал с прайсингом DeepSeek/z.ai.
- **Цена по ответившей**: z.ai вернул `model=glm-5` edit книжится по цене GLM, НЕ по дешёвому deepseek-якорю
(fallback дал бы $0.000147 в 8.7× меньше); `PriceForResponse` подтверждён на реале.
- **Usage реальный**, не мок: `prompt/completion_tokens` ненулевые в request_log; GLM латентность штатная (58 с,
без ×3) `extra_body thinking:{type:disabled}` фактически применён.
- **Resume**: второй прогон обе стадии из чекпоинтов за **$0**, ledger неизменен (нет двойной оплаты).
- **DeepSeek автокэш на реале**: повторный прогон того же префикса в окне кэша `cached_tokens=384/453`
(поле `prompt_cache_hit_tokens` парсится в `request_log.cached_tokens`), billed по $0.0028/M; `CostUSD`
сошёлся до 7 знаков (`(453384)·0.14 + 384·0.0028 + 1074·0.28 = $0.0003115`). Кэш-путь подтверждён живым провайдером.
- **Пост-ревью правки провалидированы**: F1 (CheckKeys заводится на 2 ключах), F2 (provider temp/maxtok в
snapshot), F5 (fail-loud на включённый гейт), F7 (сноска §3.4) все на месте; Anthropic вычищен из конфигов,
висячих ссылок нет (в `BuildClient` ветка `case "anthropic"` осталась, но `kind: anthropic` в models.yaml нет).
**Новая находка реальной приёмки (исправлена):** `tmctl report` рвался с `context canceled` и печатал таблицу
частично/пусто без строки Ledger (exit 1). Причина `Store.RequestLogRows` отдавал `*sql.Rows` с `defer cancel()`:
контекст отменялся посреди ленивой итерации у вызывающего. Данные и деньги в БД были корректны баг только на
read-пути `report`. Фикс: строки материализуются под таймаутом и возвращаются срезом `[]RequestLogView`;
регрессионный тест `TestRequestLogRowsMaterializes`. `go test ./... -race` зелёные.
**Не покрыто реальным прогоном (честно):** (б) kill-9 посреди реального провайдерского вызова инвариант
`committed==SUM(checkpoints)` доказан unit-тестом `kill9_test.go` (настоящий SIGKILL на SQLite), на реале не
воспроизводил (деньги/один-чанк дисциплина). (в) Anthropic cache_control/usage-сумма Anthropic из стека убран,
проверять больше нечего на этом контуре.
### [НУЖНО РЕШЕНИЕ] перед Фазой 1 (владелец/оркестратор)
Фаза 0 закрыта; перед стартом Фазы 1 нужно закрыть решения ниже (по каждому рекомендация ревьюера).
Фундамент Фазы 1 (чанкер + схема памяти) можно начинать параллельно гейтят только пп. 1, 2, 4.
1. **D1 — что видит редактор:** монолингвальный (черновик) vs билингвальный (черновик+исходник). *Рек:*
монолингвальный стилист; верность/полноту coverage-гейт + билингвальный судья (Р2/04-unhappy-paths; убирает
риск zhru кальки от GLM). Блокирует context assembly, промпты «Редакции», `editor.md` (убрать `{{text}}`).
2. **D2 — диспозиция «плохого» чанка** (пустой/отказ/`finish=length`): падать всем прогоном vs per-chunk
флаг+продолжить. *Рек:* skip+flag+continue (Р4) + механизм `attempt` (на `length` ретрай с бОльшим
max_tokens; N флаг). Ключ resume уже несёт `attempt`. Блокирует главный цикл раннера, resume-семантику флагов.
3. **Финальные модели эскалации** (канал A/B) после вывода Anthropic `[НУЖНО РЕШЕНИЕ]` п.3. *Рек:* A
GLM-5.1/5.2 или Gemini (нативный адаптер Ф2); B по refusal-бенчмарку полигона, интерим DeepSeek+abliterated.
Фундамент НЕ блокирует (нужно к моменту исполнения эскалации).
4. **Схема банка памяти v1 — скоуп** (миграция store v2). *Рек v1:* база Р3 + alias-граф + `gender=hidden(until_ch)`
+ `translit_policy` + `first_person` + series-bible-lite; отложить в v1.1: ranked-set, эвфемизмы,
`nickname_translation`, число-словарь. Сверка со «Следствиями для плана» 04-unhappy-paths обязательна.
5. **Онгоинг:** перегоняется ли Analyst при `add-chapters` (`[НУЖНО РЕШЕНИЕ]` п.5)? *Рек:* инкрементально, Analyst
только на новые главы, book-brief не перегонять.
Уже решено (не пере-обсуждаем): премиум-бюджет (формула Р5 + $5/$30), ключ TM (консервативный), стриминг
keep-alive (Ф12), инъекция глоссария (`selective`), пороги coverage (полигон), epub v1 (текст по spine).
> **Ответ оркестратора на все [НУЖНО РЕШЕНИЕ] + Q3/Q4 (04.07) → полный контракт в [architecture/05-decisions-log.md](architecture/05-decisions-log.md).**
> Все 6+1 решений приняты (D1 монолингвальный редактор, D2 skip+flag+continue, D3 эскалация, D4 нет provider-fallback, D5 инкрементальный Analyst, D6 think-режим, D7 схема памяти v1) и прошли адверсариальную панель из 3 критиков (research/эконом/код) — читай `05-decisions-log.md` целиком перед Фазой 1, там уточнения меняют реализацию. Самое важное для тебя:
> 1. **`snapshotID` расширить memory-state + context-assembly hash ДО инъекции памяти** (D5.2) — иначе изменённый глоссарий/STM меняет `request_hash`, но не `snapshotID`, resnapshot-гейт молчит, ре-ран старой главы промахивается мимо чекпоинта и переоплачивает расходящимся переводом. Это общий гейт, держит D1 и D5.
> 2. **Runner без цикла по чанкам/главам + нет хранилища флагов** — главный длинный шест Фазы 1; `attempt` НЕ несёт disposition/skip-семантику (я переоценил). Строить цикл + таблицу флагов + `flag_reason` первым.
> 3. **D2:** тегировать `flag_reason`; `retry-flagged` переатакует только length/empty (refusal — не переатаковать, деньги на гарантированный отказ не жечь); n-gram-loop чек ПЕРЕД удвоением max_tokens; edit `max_tokens` от длины ЧЕРНОВИКА, не исходника.
> 4. **D3:** завести провайдеры gemini/xai/**openai**/deepseek-v4-pro/glm-5.1 в `models.yaml` (все OpenAI-совместимы, `kind: openai`; нативный Gemini-судья — Ф2), фактчекнуть слаг `deepseek-v4-pro`. Премиум-бюджет $5/$30 устарел (был на Sonnet) — полигон пересчитает на Gemini-апексе с reasoning-as-output.
> 5. **D1:** убрать `{{text}}` из editor.md И **поднять edit `prompt_version`** (иначе лейбл врёт на двух SHA); честно: приёмка Фазы 1 БЕЗ критерия верности (mistranslation ловит билингвальный судья Ф2, не coverage-гейт).
> 6. **D6:** дефолт think off/**minimal** (операционно), но пилот Ф2.5 think-ON включает translator/editor (не только Terminologist); Gemini-апекс форсированно думает (бюджетить как output); think-ON эскалация — только subset-провайдеры (не xAI/Grok, пока EstimateUSD не резервирует reasoning).
> 7. Новые дешёвые гейты Фазы 1 (детерминированные, Go): линтер тире-диалогов, ёфикатор, блок-лист транслит-междометий, число-гейт 万/億; ruby-парсер в спеку импорта (для ja-имён).
>
> **ПОПРАВКА ВЛАДЕЛЬЦА (04.07): удалён только Anthropic (за дороговизну), OpenAI ОСТАЁТСЯ.** Живой набор ключей у бэкенда и полигона: `DEEPSEEK_API_KEY`, `ZAI_API_KEY`, `KIMI_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`, `XAI_API_KEY`. → Вернуть провайдер `openai` в `models.yaml` (`gpt-5-nano` альт черновика, `gpt-5-mini` кандидат редактора/second-opinion судьи; квирки в `experiments/00-provider-quirks.md`: reasoning_effort minimal, без temperature, `max_completion_tokens`). Gemini/xAI теперь доступны сразу (не «Фаза 2»), нативные адаптеры для safety-судьи — по-прежнему Ф2. Р4 в `01-decisions.md` обновлён. **xAI/Grok НЕ выведен** (уточнение владельца): Grok 4.3 — основной пермиссивный тир канала B + судья 18+; промо $150 за data-sharing — на выделенный NSFW/eval-аккаунт.
> **Ответ оркестратора на два флага + вопрос «план vs старт» (04.07).** Оба флага верные, приняты:
> 1. **Рассинхрон quirks — исправил** (`experiments/00-provider-quirks.md`: строка про OpenAI была устаревшей). Источник истины по стеку — `05-decisions-log.md` D3 + Р4.
> 2. **Capability-слой — принял как корректировку D3.1** (записано в `05-decisions-log.md`): «без новых адаптеров» было оптимистично. Kimi (`temperature:1`), gpt-5-mini (`max_completion_tokens`, без temperature, effort minimal), Gemini 3.1 Pro (thinking обязателен) → текущий `openAIRequest` даст 400. И это **раньше D3**: Kimi — уже альт-редактор, edit temp 0.4 упрётся. Форма — декларативные capabilities per-модель в `models.yaml` (`budget_field`, `temperature: send|omit|locked:1`, `reasoning_control`), адаптер строит тело по ним; эталон квирков — `00-provider-quirks.md`.
> **Про «план vs старт»: пиши КОРОТКИЙ implementation-plan, но только на контракт-несущие куски, не waterfall.** Полную спеку — на три места, где двусмысленность = переделка: (а) **точный payload `snapshotID`** (что именно входит в хэш памяти/сборки контекста — это класс бага «тихий расходящийся ре-пэй»); (б) **схема disposition/флагов** (таблица флагов, `flag_reason`, как resume читает терминал-для-прогона vs retry-flagged); (в) **capability-матрица провайдеров**. Чанкер/импорт/гейты — механика, их в план не разворачивай. Порядок работ, который ты предложил, **ратифицирую**: (1) runner-loop + флаг-таблица + disposition, (2) snapshotID под память, (3) чанкер+импорт(+ruby), (4) миграция памяти v2, (5) четыре гейта; capability-слой + заводка D3 — не «параллельно потом», а вместе с (1), т.к. Kimi-редактор упрётся сразу. Стартуй с (1)+(2) — они держат всё остальное. `deepseek-v4-pro` слаг фактчекни на api-docs.deepseek.com перед wiring эскалации (не блокирует фундамент).
> **Ответ оркестратора на readiness-вердикт + флаг git (04.07).** Готовность принята, порядок работ подтверждён кодом — старт Фазы 1 разрешён.
> 1. **Флаг git закрыт: docs закоммичены** (`docs/` — моя зона; коммит после этой записи). Полигону: закоммить свою зону `eval/` (2 изменённых + 4 новых скрипта untracked — при `reset --hard` потеряются); `eval/data`/`.venv`/токенизаторы в .gitignore, коммить только код.
> 2. **Дефолт редактора Фазы 1 = `grok-4.3`** (эксп.04 полигона, бейк-офф — закрывает твой вопрос №2, ОПРОВЕРГАЕТ прежнее «редактор=GLM»): ранг-1 верность, ранг-2 стиль, ~13с без reasoning, лучший value. Премиум-эскалация редактора — `gemini-3.1-pro`. GLM/Kimi сняты с дефолта. В `pipeline-c1.yaml` edit-стадию перевести на grok-4.3 (провайдер xAI, `kind: openai`, thinking OFF — reasoning=0, ledger чист; capability: temperature шлётся, `max_tokens`). Провизорно (LLM-судьи, короткие фрагменты) — финал на пилоте Ф2.5. Р4/`05-decisions-log` обновлены.
> 3. Следствие: grok-4.3 стал центральной моделью (редактор SFW + канал B + судья 18+) — гигиена аккаунтов xAI на три использования (Р4): промо/data-sharing только eval+NSFW, продакшн-редактор SFW — чистый аккаунт.
> 4. ⚠ **DeepSeek-черновик «эхал» оригинал** на высоко-CJK фрагменте (эксп.04, 3/3) — тихий отказ = оригинал вместо перевода. CJK-гейт Фазы 1 обязан это ловить (уже в плане); плюс фолбэк-черновик как у полигона.
> **Ещё две вводные бэкенду (04.07):**
> 5. **Схему памяти v2 (твой шаг 4) держи до реестра рисков от сессии «Валидация банка памяти».** Владелец выделил банк памяти (главная точка отказа пайплайна) в отдельную адверсариальную сессию (промт `docs/MEMORY_RESEARCH_SESSION_PROMPT.md`, финализирован); её выход — `architecture/06-memory-risk-registry.md` — вход, по которому ты фиксируешь схему store/глоссария. Шаги 13 (runner-loop / snapshotID / чанкер) от схемы памяти не зависят — иди по ним, шаг 4 гейтит валидация. snapshotID под память (D5.2) проектируй с запасом, но финальную схему полей не морозь.
> 6. **Коррекция контура (владелец): EU-SaaS, прямые ключи, BYOK отменён** — в коде это НИЧЕГО не меняет (бэкенд всегда был на прямых ключах; BYOK был продуктовым концептом Р8/Р9, не кодом). Обновлены только Р5/Р8/Р9/Р10 в `01-decisions.md`. Дефолт редактора Фазы 1 — `grok-4.3` (эксп.04) — в `pipeline-c1.yaml` edit-стадию на него (xAI, thinking OFF, capability: temperature шлётся).
> **Ответ оркестратора на 4 вопроса Фазы 1 (04.07) → полностью в [05-decisions-log.md D8D11](architecture/05-decisions-log.md).** Онбординг-поправки ратифицированы (grok-editor не Kimi; deepseek-v4-pro резолвить через /models, не хардкодить; gemini `-preview` несущий; models.yaml обновляешь сам; F4 в A, F3 явно). A/B/C-план принят. Ответы:
> - **Q1 (D8): content-hash материализации памяти**, не version-counter (drift-proof; счётчик переоткрывает баг тихой переоплаты). Хэшируй полное состояние инъектируемого пула на старте джобы (per-chunk выбор уже в request_hash).
> - **Q2 (D9): приёмочная книга — ja→ru ранобэ.** Ставит ruby-извлечение на критический путь (форсирует закрытие дыры §4). Границы: фуригана первого появления → глоссарий-лок имени, НЕ ruby в выходной вёрстке. Хедж если ruby-тайм-синк — в D9.
> - **Q3 (D10): знаменатель — ВСЕ approved-термины** (имена+титулы/термины), матчит R7 + бьёт по жалобе №1 (коллапс рангов). names-only — под-метрика. Порог 98% на детерминированном слое достижим; недостижимость → ревизия порога, не знаменателя.
> - **Q4 (D11): budget_usd — конфиг-потолок, не гейт приёмки** — ДА. Но ⚠ **оба cost-числа устарели, не только премиум:** дефолт-редактор grok-4.3 ($2.50/M out ≈ 10× draft) → стандарт-микс ранобэ ~$0.73 (>$0.6). Приёмка по стоимости = escalation уважает конфиг-потолок + **точность телеметрии** (ledger корректно биллит grok reasoning=0 / gemini reasoning-as-output), мягкий sanity ~$1/ранобэ, не жёсткий $0.6/$5. Точные числа — полигон пересчитывает на стеке draft-DeepSeek+editor-grok+премиум-Gemini.
> **Ре-флаг:** grok = дефолт-редактор → каждый чанк через xAI. Продакшн-редактор — **чистый xAI-аккаунт без data-sharing** (промо-аккаунт только eval/NSFW). Концентрация 3 ролей на xAI — риск доступности (Р10), gemini-премиум как замена под рукой.
### 2026-07-04 — Сессия 3: Веха 1 Фазы 1 — capability-слой (C) + snapshotID под память (B)
Ратифицированный порядок стартует с twin-фундамента (runner-loop+snapshotID, capability-слой вместе). Веха 1 = **C + B** (жёстко связаны через `stageSnap`); runner chapter/chunk-loop + A (disposition) Веха 2. Всё зелёное: `go build/vet/test -race`, реальные конфиги валидируются через `tmctl report` ($0).
**C — capability-матрица (D3.1).** Декларативные `capabilities:` per-модель в `models.yaml`: `budget_field` (max_tokens|max_completion_tokens), `temperature` (send|omit|force+value), `reasoning` (control none|effort|extra_body_disable|mandatory + off_effort/off_extra_body/on_extra_body). Резолвер (`Capability.applyToBody`) строит тело в `openAIRequest.MarshalJSON`; `Models.ResolveCapability` мержит provider-дефолт model-оверрайд (модель побеждает по-полю). Fail-fast валидация (enum + companion-поле). **Нулевая каппа = Phase-0 wire** (обратная совместимость все текущие модели без изменений на проводе). GLM `thinking:disabled` перенесён `extra_body` `capabilities.reasoning.off_extra_body` (тело **байт-в-байт то же**, тест `TestGLMMigrationWireIdentical`; сдвигается только snapshot осознанный `--resnapshot`). Отдельно от `Provider.Reasoning=subset|additive` (то биллинг). Юнит-тесты покрывают все квирки: gpt-5 (max_completion_tokens+omit+minimal), Gemini mandatory-swallow, Kimi force=1, GLM off/on.
**B — snapshotID под память (D5.2/D8).** `snapshotID` сворачивает: (а) суб-хэш context-assembly-ручек (`glossary_injection`/budget/`stm_depth`/`overlap`/`cache_ttl`), (б) `memoryVersion` **content-hash** материализованной инъектируемой памяти (не bump-счётчик, D8; пока пустая материализация до банка памяти v2), (в) резолвнутую capability per-стадию в `stageSnap`. STM исключён (пересобирается из чекпоинтов). Цепочка `capability → stageSnap → snapID → request_hash` подтверждена (mutation-verified: без фолда правка каппы молча подаёт старый чекпоинт).
**Заведён стек (частично).** Провайдер `xai` + `grok-4.3` (цена $1.25/$2.50 факт. 04.07). **`deepseek-v4-pro` ПОДТВЕРЖДЁН живьём** (`GET /models`: `[deepseek-v4-flash, deepseek-v4-pro]`; `deepseek-chat` из списка ушёл депрекейт 24.07). Черновик = `deepseek-v4-flash`, голова эскалации A = `deepseek-v4-pro`. Цену `v4-pro` `/models` не отдаёт фактчекнуть перед wiring. **Отложено в след. конфиг-шаг** (нужны фактчек цен gpt-5-mini/nano + подтверждение xAI прод-ключа): переключение edit-стадии `glm-5``grok-4.3`, заводка gemini/openai + gemini-3.1-pro-preview/gpt-5-*/glm-5.1 + цепочки эскалации. Веха 1 даёт МЕХАНИЗМ (юнит-тесты по всем квиркам) + живой путь; полный стек когда цены подтверждены.
**Селфревью (адверсариальный воркфлоу, 4 измерения → верификация каждой находки).** Детерминизм **0 дефектов** (инвариант держит, проверено эмпирически). 5 находок исправлено: (1) *[регресс, мой]* GLM-disable стал условным на `reasoning=="off"` пустой (незаданный) effort молча включал бы thinking (×3 таймауты + reasoning-биллинг); фикс: `extra_body_disable` трактует `""` как `"off"` (сохранён Phase-0 unconditional-disable), только явный low/med/high think-ON; (2) валидация не требовала companion-поля (typo `off_extra_body` тихий no-op) требуем `off_extra_body`/`off_effort`; (3) нет теста, что каппа входит в `snapshotID` (центральный инвариант B) e2e-гейт `TestRunnerSnapshotPinsCapability` (mutation-verified); (4) mandatory-swallow тестился только на `off` строка на non-off; (5) валидация не тестилась на provider-пути/temp-mode/reasoning-control добавлено.
**Техдолг вперёд (не блокирует Веху 2):** capabilities эскалационных моделей НЕ в snapshot (только стадии) закрыть при заводке цикла эскалации (тот же класс D5.2, но пути исполнения ещё нет); `memoryVersion` заглушка до банка памяти v2 (при инъекции памяти заполнить запрос); Kimi `max_tokens≥16000` не выразим в capability-схеме (при wiring эскалации).
> **Ответ оркестратора на 4 вопроса coverage-гейта + failure-model (04.07) → полный контракт в [05-decisions-log.md D12](architecture/05-decisions-log.md), заземлён ресёрчем durable-execution.** Отличная Веха 1. Кратко:
> - **4 вопроса — все A.** Q1: наивный split, `refusal_bench.py` = источник истины, Go зеркалит бит-в-бит, изменения лок-степ Python-first (§3.7 quote-absorbing → v1.1, свою доку реконсиль сам). Q2: минимальный single-hop — **не противоречит D4** (это escalation на детерминированном контент-провале, не outage-своп). Q3: только excision_suspect (верхняя аномалия ложно флагает — ru 1.41.9×; D10 ждёт памяти v2). Q4: opt-in до валидации precision владельцем.
> - **Таксономия отказа — ТРИ класса**, не бинар: транзиентный/бюджетный → same-model retry ({length,empty}); детерминированный контент-провал (echo/cjk/excision/refusal, **HTTP 200 — детект в app-слое post-settle, не транспорт**) → single-hop escalation на другую модель (1 хоп→флаг, отдельная ось в request_hash, budget-cap, re-gate, канал B изолирован ТИПОМ); outage/системный → circuit-breaker → **пауза+resume** (не mass-swap).
> - **F3 фикс:** idempotency-key = существующий `request_hash`, заморожен на входе, заголовком где поддержано — но ⚠ **проверено: OpenAI поддерживает, DeepSeek/xAI/Gemini/Kimi НЕТ** → capability-флаг `supports_idempotency_key`; для центрального стека **at-most-once cap** на класс «billed-but-unconfirmed» (≤1 доп. вызов, не MaxAttempts1) + консервативный settle оценки на post-send timeout. Честная модель — «at-most-once billed, replay бесплатен».
> - **Global call-budget guard:** попытки/чанк = retries + 1 hop, **НЕ сбрасывается на фолбэке** (иначе retry×fallback = 30+ оплаченных, LiteLLM #19985). Editor pinned per book (фолбэк только на draft-стадии — editor задаёт стиль).
> - **Прогресс (реальный пробел, ответ на «подсвечивать»):** `tmctl status --config` — READ-ONLY проекция `chunk_status`(уже построен)+jobs+spend+request_log, `--json`; **book manifest на snapshot** (знаменатель N/M); статусы done/in-progress/flagged/skipped/pending (flagged≠failed, всегда REASON); **паспорт качества главы** (JUnit+SonarQube-стиль); ETA от EWMA не present-state; никакого синтетического time-бара. Не сейчас, но заложить manifest в snapshot-момент.
**Гигиена xAI (напоминание):** в `models.yaml` у провайдера `xai` комментарий-контракт «прод-clean без data-sharing». `XAI_API_KEY` в `.env` подтвердить как прод-аккаунт перед первым боевым grok-вызовом (в Вехе 1 grok в стадии не зовётся).
**Веха 2 (следующая):** runner chapter/chunk-loop + `chunk_status`/disposition (A, D2) `flag_reason`-константы, `classify(text,finish)` (refusal/echo до length), ось attempt, exit-коды 0/2/1, фиксы F4 (усечённый length flagged) + edit-`max_tokens` от длины черновика.
### 2026-07-04 — Сессия 4: Веха 2 Фазы 1 — chunk-loop + disposition (A, D2) + фиксы F4/D2.5
Снят хардкод «один чанк»: прогон идёт по всей книге, плохой кусок помечается и цикл продолжается. Всё зелёное: `go build/vet/test -race`, `tmctl report` ($0). Живые LLM не звались (моки + tmctl $0, как предписано).
**Цикл по чанкам (шов под шаг 3).** `TranslateOneChunk`(chapter=1/chunk=0 хардкод) `TranslateBook` `translateChunk` (цикл стадий) `runStage` `runAttempt` (ось attempt). `RunResult``ChunkOutcome` (per-chunk) + `BookResult` (агрегат книги). Чанкер **минимальный детерминированный плейсхолдер** (`chunker.go` `SplitChunks`: разбивка на главы по form-feed, паковка абзацев 1500 симв., абзац не режется); настоящий лингвистический чанкер шаг 3, подменит `SplitChunks` не трогая цикл/disposition. `chunkerVersion` бампнут `v1-wholefile``v2-ff-para-pack` (в snapshot; ре-чанкинг = осознанный `--resnapshot`).
**Схема disposition (D2, контракт-несущее).** v2-миграция (append, IF NOT EXISTS): `chunk_status(book_id,chapter,chunk_idx,stage,snapshot_id,content_hash,disposition,flag_reason,attempts,final_hash,cost_usd,detail)`, PK (book,chapter,chunk,stage). Это **резолв поверх append-only checkpoints**, не колонка на checkpoints на resume пересобирается из чекпоинтов. `disposition ∈ {ok,flagged,skipped}`; `jobs.status` контентом НЕ расширён (failed = только инфра). `flag_reason` Go-константы как `Finish*` (12 шт.; эмитятся length/empty/loop_degenerate/hard_refusal/soft_refusal/content_filter/cjk_artifact/decode_error, зарезервированы coverage_fail/excision_suspect/hard_block/upstream_not_ok под шаги 67). Единый `classify(src,out,finish,target)` порядок: refusal-блэклист (порт `refusal_bench.py` 1:1, en/ru/zh/ja) / CJK-echo **ДО** length/empty (усечённый отказ не триггерит платную переатаку); `content_filter` best-effort (реальная страховка блэклист). n-gram loop-чек ПЕРЕД удвоением max_tokens. `maxTokensForAttempt` чистая функция (удвоение per attempt), её версия в snapshot (`maxTokensPolicy`). Retry-flagged только {length,empty} на той же модели по оси attempt (до `regenerate_before_escalate`, потом флаг); refusal/filter/cjk/loop/decode детерминированы не переатакуются. Три анти-веджа отработали (**mutation-verified**): resume читает `chunk_status` до вызова; empty/decode flagged (цикл идёт, не крэш); legacy-пустой чекпоинт самолечится classify-ем без ре-биллинга. Exit: `CompletedWithFlags` sentinel 0 чисто / 2 с флагами (N допустимо) / 1 инфра.
**Фиксы.** **F4:** усечённый `length` с непустым черновиком теперь классифицируется (flagged/retry), не течёт в edit как OK (`classify` после settle). **D2.5:** edit-`max_tokens` от длины ЧЕРНОВИКА (`prev`), не исходника монолингвальный редактор работает по русскому черновику 1.9× исходника (mutation-verified). **F3 честно:** `chunk_status.cost_usd` суммирует все попытки; per-run cost отделён от кумулятивного; idempotency-ключ не делал (отложено).
**Селфревью (адверсариальный воркфлоу, 5 измерений → верификация каждой находки).** disposition-money/resume/classifier **0 дефектов**. 2 подтверждённых исправлено (оба mutation-verified): (1) *[детерминизм, medium]* `chunk_status` fast-path резолвил ПОЗИЦИОННО и подавал устаревший перевод при правке исходника (исходник не в snapshot) фикс: сигнатура `content_hash` отрендеренных msgs в `chunk_status`, fast-path доверяет строке только при совпадении snapshot И content (иначе content-safe attempt-loop; правка src = тихий per-chunk ре-перевод по §3.4, не устаревший подача); стоило переноса дешёвого рендера ДО чекпоинт-резолва (LLM-вызов по-прежнему загейчен «не переатаковать» сохранено). (2) *[CLI, low]* `flag.ExitOnError` `os.Exit(2)` на кривом флаге, коллизия с exit-2 «с флагами» `ContinueOnError` (кривой флаг = exit 1). Тесты: 12 новых (disposition/chunker/chunkstatus юниты + e2e мульти-чанк/resume/flag+skip/exit-коды/F4/D2.5/decode/legacy-self-heal/source-edit), все mutation-проверены на укус.
**Техдолг вперёд (не блокирует шаг 3):** чанкер плейсхолдер (шаг 3 подменит `SplitChunks`, чтит контракт `Chunk` + бампает `chunkerVersion`); небилленный upstream-сбой = инфра-аболт (D4 pause/resume), `upstream_not_ok`/`hard_block`-константы под HTTP-классификацию шага 7; редкий угол: kill-9 в микро-окне (потеря `chunk_status`) ПЛЮС одновременное снижение `regenerate_before_escalate` может консервативно пере-флагнуть бывший-ok чанк (без денег/расхождения фаст-путь чинит норму, self-heal best-effort). `jobs.status` теперь наблюдательный (ничего на нём не ветвится).
### 2026-07-04 — Ответ Полигону: тихие отказы (эхо/вырезание/пусто) + онбординг след. сессии
Полигон верно указал класс «HTTP 200, перевода нет». Провалидировал **трассировкой** capabilitywire (не грепом):
**Состояние детекта (после Вехи 2):**
- **Эхо (`cjk_artifact`)** ДЕТЕКТИТСЯ: `classify` (disposition.go) флагует при `cjkShare(out) > 0.15` (порог из `refusal_bench`). Полигоновское «детекта нет» устарело добавлено в Вехе 2 (после их грепа). НО: в РАННЕРЕ (disposition-слой, post-settle), НЕ в адаптере/failover; сейчас ФЛАГ, эскалации нет (эскалация шаг 7).
- **Пусто** ДЕТЕКТИТСЯ: `classify``empty` (cloud-путь) + failover empty-check (только local-нога, `failover.go:121`).
- **Вырезание (`sent_cov`/`len_ratio`)** НЕ детектится: константы `excision_suspect`/`coverage_fail` заведены, но не эмитятся это конфигурируемый coverage-гейт (шаг 6). Пороги (zh<2.2/ja<1.4/en<0.70, sent_cov<0.75) уже в §3.7 + `refusal_bench` EXPECT_LEN_RATIO.
**DeepSeek thinking — ПОДТВЕРЖДАЮ, риска нет.** `deepseek-v4-flash` без capabilities/extra_body; провайдер `deepseek` reasoning:subset без caps `ResolveCapability` = baseline openai (`ReasoningNone`). Стадия draft `reasoning:"off"`. `applyToBody(ReasoningNone,"off")` эмитит НИЧЕГО reasoning-related на проводе нет `reasoning_effort`, нет `thinking` DeepSeek берёт ДЕФОЛТ (thinking ON) чистый перевод, эха нет. Наш off-by-omission НЕ гасит DeepSeek thinking (в отличие от GLM с явным `thinking:disabled`). **Критично:** `reasoning:"off"` для DeepSeek ОСОЗНАННЫЙ no-op (ReasoningNone глотает "off"), именно это держит thinking ON. **Никогда не добавлять deepseek `capabilities.reasoning.off_extra_body:{thinking:{type:disabled}}`** включит эхо. (GLM-редактор с thinking:disabled безопасен: его вход русский черновик, CJK эхать нечего.)
**Архитектурные ответы (Q1Q3):**
- **Q1 (где живёт валидация):** в РАННЕРЕ (disposition/classify-слой), НЕ в адаптере и НЕ отдельным failover-чеком. Адаптер (`llm/`) провайдер-нейтрален и без контекста перевода (нет src/target/покрытия) держим инвариант нейтральности. failover эскалирует на ТРАНСПОРТ-сбоях (5xx/429/timeout/пустой local); контент-качество отдельный концерн (смешать = сломать разделение транспорт/контент + изоляцию канала B, D4). Эхо приходит как 2xx (оплачено провайдером) детект в адаптере vs раннере денег не экономит (оба после биллинга); раннер имеет src+target+finish и решает retry/flag/эскалацию. эхо/пусто = intrinsic classify (Веха 2 ✅); вырезание = конфиг coverage-гейт (шаг 6, тоже раннер, не адаптер).
- **Q2 (эхо ретрай/эскалация или флаг?):** согласен эхо должно ЭСКАЛИРОВАТЬ, не просто флажок. `cjk_artifact` ДЕТЕРМИНИРОВАН (та же модель то же эхо) same-model retry бессмыслен (переэхнёт, переплатит) в classify он **non-retryable именно поэтому**. При заводке эскалации (шаг 7) `cjk_artifact` уходит на ФОЛБЭК-ЧЕРНОВИК (другая модель) это и есть «эскалация, не флаг» (интент записан в Вехе 2). Сейчас флаг цикла эскалации ещё нет.
- **Q3 (live-conformance):** ДА, и Python-оракул Полигона = приёмочный ГЕЙТ перед фиксацией адаптеров. Мои Go-тесты httptest wire-контракты (быстрые, детерминированные, CI без ключей) живые эхо/`reasoning_content`/алиасы/503 не воспроизводят by design. Разделение: **Python-оракул (зона Полигона)** = кросс-провайдерный live-гейт «каждый адаптер бьёт живого, получает валидный перевод без эха/пусто/обрезки»; **Go live-интеграционные тесты (зона бэкенда, build-tag `live`/env-gated, вне CI)** = per-adapter wire+parse на живых ключах. Оба; оракул гейт.
Фикс (эскалация `cjk_artifact`фолбэк-черновик + coverage-гейт вырезания + live-conformance) **отдельная сессия**, онбординг-промт: [BACKEND_SESSION_PROMPT_SILENT_REFUSALS.md](BACKEND_SESSION_PROMPT_SILENT_REFUSALS.md). Не блокирует шаг 3.
### 2026-07-04 — Сессия 5: Веха 2.5 (старт) — DeepSeek эхо-мина зафиксирована регресс-гейтом
Валидация точки старта зелёная (`go build/vet/test -race` ~80 тестов; `tmctl report` $0). Первым делом регресс-гейт §2, чтобы будущая правка `models.yaml` не включила эхо-мину DeepSeek.
**Решение: fail-fast в конфиг-валидации (сильнее unit-теста — срабатывает на КАЖДОМ `tmctl`-запуске), а не только тест.** Провайдер получает декларативный маркер `echoes_when_thinking_off: true` (заведён на `deepseek`, документирован трассой). `config.echoMineViolation` резолвит каппу модели такого провайдера и валит старт, если thinking подавляется при `reasoning=off` по ОБЕИМ поверхностям вооружения: (1) `capabilities.reasoning.control` = `extra_body_disable` (мержит `{thinking:disabled}`) или `effort` (шлёт `reasoning_effort`); (2) thinking-ключ, протащенный через model `extra_body` (его контрол-чек бы пропустил `openAIRequest` мержит его в тело). Инвариант: echo-prone провайдер обязан держать `reasoning.control` = `none|mandatory` и без thinking-disable `extra_body` thinking остаётся на дефолте (ON).
**GLM отличается корректно:** маркер только на `deepseek`; `glm-5` (provider `zai`) с `{thinking:{type:disabled}}` остаётся легальным (его вход русский черновик, CJK нечего эхать). Метаданные валидации-only на провод не идут, в snapshot НЕ входят (без `--resnapshot`).
**Тесты (мутационно-проверенные):** `TestDeepSeekEchoMineRejected` 5 кейсов (2 поверхности + `effort` + GLM-безопасность + дефолт); `TestBoevoyConfigDeepSeekThinkingStaysOn` гард на реальном `configs/models.yaml` (флаг на месте + `deepseek-v4-flash``ReasoningNone`; unmarshal напрямую, чтобы обойти date-бомбу `prices_checked`). Убрать `echoMineViolation` armed-кейсы перестают падать (мутация ловится).
Контрактные вопросы 7) заданы оркестратор ответил **D12 (все A: 1A наивный split, 2A single-hop, 3A только excision_suspect, 4A opt-in)** + модель устойчивости (три класса отказа, F3 at-most-once, `supports_idempotency_key`, editor-pinned, global call-budget). Строю по D12.
### 2026-07-04 — Веха 2.5 (A): coverage-гейт вырезания (excision_suspect)
Порт excision-классификации `refusal_bench.py::classify_output` в `pipeline/coverage.go`. **Сегментация (D12 Q1) — бит-в-бит с оракулом:** RE2 без lookbehind, поэтому `split_sentences` реплицирован ручным сканом (branch-1 «терминатор+пробел-ран поглощается» branch-2 «CJK-терминатор zero-width»), **пинится к живому оракулу** `TestSplitSentencesOracleParity` (28 крайних кейсов сняты из `refusal_bench`: диалоги `「…!」`, подряд `。。。`3, U+3000, `……`1, fullwidth `?。!`, `Mr.`-oversplit). Метрика символы без пробелов. **Только нижняя граница (D12 Q3):** `sent_cov<sent_cov_min` ИЛИ `len_ratio<коридор-low` `excision_suspect`; верхняя (аномалия-дописывание) НЕ флагуется (ru 1.41.9×, ложно; нужен entity+судья Ф2). Мини-набор искусственных пропусков **ловит 12/12 (100%)**, ложных на верных 0.
**Вайринг раннера:** `classifyOutput` = intrinsic `classify` (эхо/пусто/refusal, всегда) потом coverage-гейт **если** `gates.coverage.enabled`, по РЕЗУЛЬТАТУ каждой стадии против ИСХОДНИКА (ловит вырезание и на draft, и на edit). `excision_suspect` non-retryable (детерминирован per-модель эскалация, не same-model retry интент под B). Гейт-конфиг **свёрнут в snapshot** (`coverageSnapshot`, только когда enabled) флип/твик = громкий `--resnapshot` + бесплатная ре-оценка чанков из чекпоинтов. `CheckRunnable` больше не валит `gates.enabled`; `LoadPipeline` fail-fast на включённом гейте без порогов (тихий no-op против Р7). **Боевой `pipeline-c1.yaml` — opt-in `enabled:false`** (D12 Q4: флип после валидации precision владельцем). Тесты: excisionфлаг+skip+exit2+resume-детерминизм, healthypass, snapshot-флип`--resnapshot`, no-thresholdsfail-fast. Всё зелёное `-race`.
### 2026-07-04 — Веха 2.5 (D): провайдерская домашка — live `/models`-фактчек
Живой `GET /models` по 6 провайдерам (бесплатно, без completion; ключи только в `Authorization`, значения не печатались). Слаги эскалации **верифицированы живьём**: DeepSeek `deepseek-v4-flash`+`deepseek-v4-pro` ✓; GLM `glm-5`+`glm-5.1`/`5.2` ✓; xAI `grok-4.20-0309-non-reasoning`+`grok-4.3` ✓; Gemini `gemini-3.1-pro-preview`+`gemini-2.5-flash` (id с префиксом `models/` канонизация ответа для `PriceForResponse` при вайринге Gemini, Ф2); OpenAI `gpt-5-mini`+`gpt-5-nano` ✓.
** НАХОДКА (configреальность, исправлена):** боевой `models.yaml` держал Kimi `base_url: https://api.kimi.ai/v1` **`api.kimi.ai` НЕ резолвится** (DNS fail прокси 502 CONNECT, HTTP 000). Рабочий хост `https://api.moonshot.ai/v1` (200, `kimi-k2.6` в /models). Комментарий спутал веб-консоль (`platform.kimi.ai`) с API-эндпоинтом (`api.moonshot.ai`). Kimi текущая заглушка эскалации на реальном хопе упало бы. Исправлено на `api.moonshot.ai/v1`.
`reasoning_content`-vs-`content`, cache-поля, `content_filter`-эмиссия требуют **платного** completion не гоняю здесь; проверит live-conformance харнесс (C) при ручном прогоне оператором. Код уже корректен по докам (`httpllm.go` читает `content`, парсит оба cache-варианта DeepSeek).
### 2026-07-04 — Веха 2.5 (B): single-hop эскалация детерминированных провалов
Реализован класс «детерминированный контент-провал» из D12: флаг, который другая модель может починить (`cjk_artifact`/`excision_suspect`/`loop_degenerate`/`hard_refusal`/`soft_refusal`/`content_filter` `FlagReason.escalatable()`), эскалирует **на другую модель ОДИН раз**, а не флажок.
**Механика (раннер):** после primary-attempt-loop, если вердикт escalatable И у стадии задан `escalate_to` И бюджет остаётся один вызов `runAttempt(escalate_to, escalation=true)`, результат **ре-гейтится** (`classifyOutput` гоняется и на фолбэке). Прошёл фолбэк авторитетный (его чекпоинт = `final_hash`); не прошёл primary-флаг остаётся, фолбэк оплачен и посчитан. **Ось эскалации = модель в `request_hash`** (не attempt): чекпоинт фолбэка `(model=escalate_to, attempt=0)` не коллизится с провалившимся primary. **Ровно 1 хоп** (не свежий retry-бюджет): вызовов/чанк = primary attempts + 1 (guard LiteLLM #19985). `runAttempt` параметризован `model`+`escalation`.
**Бюджет (D12):** `escalation.budget_usd` opt-in (0 = выкл, боевой дефолт). Money-path-durable: миграция v3 добавляет колонку `escalation` на checkpoints (пишется в той же tx, что settle), `EscalationSpentUSD` суммирует только escalation-чекпоинты (resume-safe, не двойной счёт на checkpoint-hit). Soft cap.
**Канал B (D4.1) типом, не комментарием:** `Provider.permissive` + `Stage.channel` (sfw|adult); `LoadPipeline` валит `channel=adult`, если primary или `escalate_to` НЕ на пермиссив-провайдере. **Editor pinned per book:** editor не имеет `escalate_to` не эскалирует (стиль не плывёт на чужую модель, 2605.13368). **D5.2-закрытие:** `escalate_to` + его резолвнутая каппа свёрнуты в `stageSnap` смена эскалационной модели/каппы = громкий `--resnapshot`. `CheckKeys` префлайтит ключи `escalate_to` при budget>0. `escalate_to == primary` запрещён валидацией.
Тесты (мок-провайдер, два fake-модели): эхо→фолбэк-починка→OK+edit; фолбэк тоже эхнул→primary-флаг+skip (ровно 2 вызова); budget=0→не эскалирует; resume подаёт фолбэк-чекпоинт за $0; смена fallback→`--resnapshot`; channel=adult без permissive→fail-fast. Всё зелёное `-race`, `tmctl report` $0.
### 2026-07-04 — Веха 2.5 (C): live-conformance харнесс + live-валидация мины
`internal/pipeline/live_conformance_test.go` под `//go:build live` — вне дефолтного `go test`/CI ($0, без ключей). Per-adapter: строит клиента из боевого `models.yaml`, бьёт живого провайдера коротким плотно-CJK→ru переводом, валидирует РАННЕРНОЙ `classify`хо→cjk_artifact, пусто→empty, refusal→soft_refusal; валидный = ok), логирует usage + response-слаг (канонизация). Скипается без `TM_LIVE=1`; запуск оператором: `set -a; . ./.env; set +a; TM_LIVE=1 go test -tags live -run TestLive -v ./internal/pipeline/`. Разделение (D12 Q3): Python-оракул Полигона = кросс-провайдерный приёмочный ГЕЙТ; эти Go-тесты = per-adapter wire+parse. Оба.
**Live-валидация (1 целевой вызов deepseek, ~$0.00004):** фрагмент Лу Синя «祝福» (эхо-репро-семья) → `cjk_share=0.00`, `verdict=ok`, `finish=stop`, `reasoning_tokens=0`, чистый русский перевод. **DeepSeek-мина подтверждённо обезврежена на реальном проводе**`reasoning:"off"` no-op держит thinking ON → перевод, не эхо. Адаптер читает `content`, слаг = `deepseek-v4-flash` (канонизация чистая). grok закомментирован в наборе (гигиена clean-prod xAI — включать осознанно).
**Веха 2.5 (A+B+C+D + §2-гейт) реализована.** Коммиты: `2c1c38d` (эхо-мина гейт), `2acfdf2` (coverage-гейт), `d97f832` (Kimi base_url), `659cce0` (single-hop эскалация), `a844765` (live-harness). Дальше — агентское селфревью на вехе.
### 2026-07-05 — Веха 2.5: агентское адверсариальное селфревью + фиксы
Многоагентный Workflow (6 дименсий: детерминизм / деньги / корректность coverage / корректность эскалации / эхо-мина+конфиг / нейтральность+хаки → независимая верификация КАЖДОЙ находки CONFIRMED/REFUTED с конкретным сценарием инпут→неверный-выход). 25 агентов, **14 подтверждённых** (5 опровергнуто). Все исправлены; ключевые фиксы мутационно-проверены (сломай → тест падает).
**Детерминизм/snapshot:** [1/3 HIGH] `escalate_to`-модель шлёт `extra_body`/provider-оверрайды на провод, но они НЕ были в snapshot → тихий false-hit на resume (примари-путь гейтил, эскалация нет) → свёрнуты `EscalateExtra`/`EscalateProviderTemp/MaxTok`. **Эскалация:** [2/9/13 HIGH] бюджет-гейт неидемпотентен — краш между settle фолбэка и chunk_status выбрасывал уже-оплаченный успешный фолбэк и флипал OK→flagged → **checkpoint-first replay** (существующий фолбэк-чекпоинт реиграется бесплатно, минуя бюджет-гейт); [10] эскалация, пробившая book-потолок, роняла всю книгу → `errReserveCeiling`-деградация (оставить примари-флаг, книга продолжает); [11/14] телеметрия эскалации терялась на resume → `GetCheckpoint` отдаёт флаг escalation, `resumeFromChunkStatus` восстанавливает. **Coverage:** [5 HIGH] гейт НЕ стрипал `<think>` (в отличие от `classify`/оракула) → утёкший reasoning маскировал вырезание → `stripThink` в `coverageCheck`; [6] гейт на КАЖДОЙ стадии ложно флагал легитимную монолингвальную правку → **только translator-роль** (верность editor — Ф2, билингв-судья §04); [7] `sent_cov_min=0`+нет коридора пары → молча пропускал всё → требуем `sent_cov_min∈(0,1]` при enabled; [8] Go `unicode.IsSpace` расходился с оракулом на U+001C001F → `isOracleSpace` (паритет). **Конфиг:** [12] включение coverage-гейта требовало ключи недостижимых chain-заглушек → префлайт ключей эскалации отвязан от `gatesEnabled``budget_usd>0`; [4] честный doc soft-cap. Регресс-тесты добавлены; полный набор зелёный `-race`, `tmctl report` $0, live-harness компилируется под `-tags live`.
**Веха 2.5 сдана на внешнее ревью.** Открытые для владельца/оркестратора: боевой флип `gates.coverage.enabled` (после валидации precision), цена `deepseek-v4-pro` (в /models слаг есть, цены нет), формула `escalation.budget_usd`, F3-idempotency-key + `tmctl status` (D12 — отдельные задачи).
> **Внешнее ревью оркестратора Вехи 2.5 (05.07): ПРИНЯТО, 0 живых блокеров, 7 подтверждённых находок (1 отсеяна).** Независимый адверсариальный воркфлоу (12 агентов, каждая находка верифицирована трассой кода). Money-path и coverage-оракул я подтвердил чтением сам. Тема: снапшот-дисциплину, которую ты **верно** применил к новому `coverageGateVersion`, ревью нашло пропущенной в 3 соседних verdict/wire-определителях (слепок автора). Ни одна находка не горит на боевом конфиге — но закрыть до активации соответствующего пути.
> **Major (закрыть до того, как путь оживёт):**
> 1. **`classifierVersion` НЕ в снапшоте** (disposition.go + runner.go:288). `classify()` решает resolved-вердикт (ok↔flagged, ре-ран на legacy/in-flight-crash чекпоинтах), но без version-const — в отличие от `coverageGateVersion`, который ты добавил ровно за это. Правка порога (cjkEchoThreshold 0.15→0.20 / новый refusal-паттерн) → тот же snapID → тихий re-verdict (flagged→ok ре-гоняет пропущенную стадию = свежий расход; ok→flagged жжёт свежий escalation-хоп). Фикс: `const classifierVersion`, свернуть в snapshotID рядом с coverageGateVersion. Симметрично тому, что ты сделал.
> 2. **local backend-тег (`prov.Model`) НЕ в снапшоте И НЕ в request-hash** (runner.go:344-345). Тег, который localClient шлёт как wire-`model` (какая модель реально отвечает — самый влияющий local-оверрайд), отсутствует, а слабые собратья temp/maxtok свёрнуты. Латентно (дефолт = deepseek/glm), оживает при первом wiring local-стадии/эскалации (канал B D3, одна правка YAML). Своп local 8b→14b посреди книги → тот же snapID → resume отдаёт старую модель. Фикс: свернуть `prov.Model` (+ `EscalateProvider*`). Закрыть до wiring local.
> 3. **echo-мина — дени-лист из 3 ключей, не исчерпывающий** (models.go:278). Сырой extra_body проверяется только на top-level thinking/enable_thinking/reasoning_effort — **промахивается мимо ВЛОЖЕННЫХ форм** типа `chat_template_kwargs.thinking:false`, а это документированная форма отключения thinking у DeepSeek-V3.1+ (т.е. гейт промахивается мимо самой вероятной реальной формы). Докстринг «both surfaces covered» переоценивает. Фикс: алоу-лист / рекурсивный скан на echo-prone провайдере; минимум — смягчить докстринг до «3 known top-level keys».
> **Minor (дешёвые гарды + doc/parity):**
> 4. **Эскалация не role-guarded** (pipeline.go:217). Coverage-гейт ограничен translator, а эскалация срабатывает на ЛЮБОЙ стадии с escalate_to — редактор мог бы эскалироваться на чужую модель, тихо нарушая D12 «editor pinned». Латентно (editor без escalate_to, budget=0). Фикс: отвергать escalate_to на role!=translator в LoadPipeline (структурное принуждение D12).
> 5. **Coverage расходится с оракулом на парах без коридора** (coverage.go:177). Оракул применяет дефолт (0.5,3.0) для пар вне {zh,ja,en,ru}; Go пропускает len-проверку целиком → ko-ru len_ratio=0.4/sent_cov=1.0: Python флагает, Go пропускает. Мёртвый код на корпусе {zh,ja,en,ru}, но ломает claim «бит-в-бит оракул». Фикс: дефолтный коридор как оракул ИЛИ fail-fast, требуя коридор пары книги при enabled.
> 6. **Атрибуция эскалации теряется на flagged-resume** (runner.go:996). Escalated/EscalationModel восстанавливаются только в ok-ветке; «хоп тоже провалился→flagged» теряет факт на fast-path. Деньги верны, только in-memory телеметрия (читается пока лишь тестами). Фикс — при добавлении `tmctl status` (ему нужна колонка escalation в chunk_status).
> 7. **Докстринг врёт** (runner.go:180-181): «гейт на КАЖДОЙ стадии, ловит excision редактора» — а строка 193 гардит role==translator (корректный Ф2-deferral). Рантайм прав, поправь докстринг (ловушка для будущего ревьюера).
> **Отсеяна: 1** (false-positive).
>
> **Открытые пункты закрыты:**
> - **Цена `deepseek-v4-pro` ПОДТВЕРЖДЕНА** (офиц. страница, 05.07): **$0.435 in / $0.87 out, cache-hit input $0.003625** (v4-flash подтверждён $0.14/$0.28/$0.0028). Разблокирует wiring канала-A эскалации + `prices_checked`. ⚠ легаси-подстраница `/pricing-details-usd` не обновлена (показывает deepseek-chat/reasoner) — брать `/quick_start/pricing`.
> - **coverage-флип:** держи false; валидация precision на реальных чанках — задача полигону (ниже); порог N флагов — за владельцем.
> - **`escalation.budget_usd`:** механика (opt-in soft-cap, 0=выкл) верна; число — $-потолок под маржу владельца + пересчёт полигона (D11), не «≤2×»; 0=выкл — норм дев-дефолт.
> - **D12-хвосты, приоритет:** **память v2** (реестр `06` готов — главный блокер качества) → **`tmctl status`+manifest** (владелец просил прогресс, скоуп мал, `chunk_status` есть) → **F3** (консервативный settle — честный интерим). Порядок предложишь сам.
### 2026-07-05 — Веха 2.5: закрытие находок внешнего ревью (7/7)
Все 7 подтверждённых находок закрыты, каждый фикс мутационно-проверен (реверт → падает именно его тест). Классический слепок автора (снапшот-дисциплину применил к `coverageGateVersion`, но не к 3 смежным determinator'ам) — закрыт симметрично.
**3 major:** [1] `classifierVersion` свёрнут в snapshot рядом с `coverageGateVersion` (правка порога `classify` = громкий `--resnapshot`, не тихий re-verdict). [2] local backend-тег `prov.Model` (+ `EscalateProviderModel`) свёрнут в `stageSnap` (своп 8b→14b посреди книги теперь инвалидирует чекпоинты). [3] echo-мина: плоский скан 3 ключей → **рекурсивный** `findThinkingControlKey` — ловит вложенные формы (`chat_template_kwargs.thinking` = документированное отключение DeepSeek-V3.1+, самая вероятная реальная).
**4 minor:** [4] `escalate_to` разрешён только на `role=translator` (структурное принуждение D12 editor-pinned). [5] coverage: пара без коридора теперь получает дефолт оракула (0.5) вместо пропуска len-проверки (восстановлен claim «бит-в-бит»). [6] телеметрия эскалации на flagged-resume — **отложена ревьюером** до `tmctl status` (нужна колонка escalation в chunk_status; деньги/флаг верны, теряется только in-memory Escalated). [7] врущий докстринг `classifyOutput` поправлен (гейт только translator, не «каждая стадия»).
Регресс-тесты: `chat_template_kwargs.thinking`-кейс, no-corridor default-коридор, escalate_to-на-editor→fail, snapshot-fold `classifierVersion`+local-тег. Полный набор зелёный `-race`, `tmctl report` $0. **deepseek-v4-pro цена подтверждена оркестратором** ($0.435/$0.87/$0.003625) — разблокирует wiring канала-A эскалации.
**Веха 2.5 ПОЛНОСТЬЮ закрыта** (реализация + селфревью 14 + внешнее ревью 7). Дальше — D12-хвосты по приоритету оркестратора (память v2 → tmctl status → F3).
## Полигон
(секция параллельной сессии — записи добавлять сюда)
> **Сообщение от основной сессии (04.07, после ревью твоих экспериментов 0102).** Работа принята, качество высокое. Важные вводные:
> 1. **Архитектурные доки обновлены до v2** (~05:08, после адверсариального ревью) — если читал их до этого, перечитай `architecture/01-decisions.md`: экономика теперь разделена по контурам «чей ключ» (Р5), премиум-микс с Sonnet в ru-контуре недоступен, batch — только для батчуемых стадий. Твой пересчёт COGS из эксперимента 01 отлично ложится в контур «прямые ключи»; при случае добавь строку-оговорку про ru-агрегаторский контур (×26 на флагманы).
> 2. Твои **коридоры len_ratio из эксперимента 01 — прямой вход в coverage-гейт v1** бэкенда (Р7/план Фазы 1). Когда сузишь их по факту прогонов — зафиксируй в experiments-доке итоговые пороги отдельной таблицей, я заберу их в конфиг гейта.
> 3. **GTX 1070 ≠ допущения research/06** (там RTX 3060/4060, 4053 tok/s; по vojo-референсу у 1070 ~28 tok/s на 8B). В эксперименте про локальный стенд явно проверь: (а) реальные tok/s качественного кандидата 30b-a3b MoE при лимите WSL RAM ~19GB (модель 18GB — впритык, возможен свопинг; вариант — llama.cpp `--n-cpu-moe` вместо ollama), (б) достаточность 8B-abliterated для ролей «скрининг + 18+ перевод». Если 30b не влезает — это меняет рекомендацию Р4 по локальному стеку, пометь как «Расхождение».
> 4. Опциональная задача в бэклог (из Р5/Р10 риск №6, понадобятся ключи владельца): **эмпирическая проверка, пробрасывают ли ru-агрегаторы (ProxyAPI/VseGPT/AITunnel) cache-hit тарифы DeepSeek** — два одинаковых запроса подряд, сравнить usage/стоимость. Это разблокирует экономику ru-контура.
> 5. Договорённость по журналу: фиксируй здесь краткие итоги каждого эксперимента (12 строки + ссылка на док) — основная сессия читает эту секцию, а не всю папку experiments.
### 2026-07-04 — Сессия 1 полигона (ответ на вводные выше — приняты)
Инфраструктура: `eval/` (venv, токенизаторы DeepSeek V3.2/Qwen3/Qwen2.5/GLM-4.6 + tiktoken), PD-корпус 16 текстов zh/ja/en/ru с 3 параллельными парами. Ключи — `eval/.env` (gitignored, закрыт deny-правилом; скрипты читают сами; шаблон на 7 провайдеров создан, ждёт заполнения владельцем).
- **Эксперимент 01 (задача 1) — завершён** → [experiments/01-token-calibration.md](experiments/01-token-calibration.md). Два расхождения с research/09 >15%: иероглиф = 0.860.93 ток. (in-family) против 0.650.75; «выход≈вход±20%» сломано — zh→ru **1.88×B** (en→ru 1.53, ja→ru 1.29). COGS (контур прямых ключей): стандарт-вебновелла DeepSeek $1.85→$2.57, премиум-микс ≈$28→**≈$49** ($26 batch); ранобэ ja→ru подешевел ($3.9→$3.1). Оговорка про ru-агрегаторский контур добавлена (п.1 вводных учтён).
- **Эксперимент 02 (задача 2) — первый прогон выполнен** (ключи получены ~06:10) → [experiments/02-refusal-benchmark.md](experiments/02-refusal-benchmark.md). 6 провайдеров × 11 фрагментов (SFW/L1/L2-violence): **66/66 ok — ноль отказов и вырезаний**, контроль ложных срабатываний пройден; содержательная 18+ часть ждёт explicit-фрагментов владельца. **Пороги len_ratio для coverage-гейта готовы** (п.2 вводных): zh→ru <2.2, jaru <1.4, enru <0.70, sent_cov <0.75 таблица в 02, забирайте в конфиг v1. Побочные находки для продакшн-конфига провайдеров: thinking GLM-4.6 (таймауты ×3) и Gemini (молча обрезал перевод детектор поймал) отключать для роли переводчика; gpt-5-mini reasoning minimal; safety_settings Gemini через OpenAI-слой не передаются (судье нужен нативный API).
- **Эксперимент 03 (задача 3) первый замер + эталон** [experiments/03-local-stand.md](experiments/03-local-stand.md). По п.3 вводных: (а) 30b-a3b в WSL **влезает** (mmap, без OOM), но на ollama даёт лишь **10 tok/s** «Расхождение» с research/06 (2530 обещаны через llama.cpp `--n-cpu-moe`; ставится в фоне перемерить; Р4 менять пока не надо: рекомендация там и так llama-server); частично виноват и лимит WSL RAM 20GB поднят до 26GB (`.wslconfig`, вступит после рестарта WSL); (б) 8b @ 27 tok/s (6.6GB VRAM) на роли скрининга/экстракции годен. **Эталон DeepSeek снят: разрыв качественный** API даёт корректные реалии ворота Расёмон на улице Судзаку», «Новогоднее жертвоприношение») за ~$0.0005/фрагмент там, где обе локалки галлюцинируют Рождественская дверь», «петухи»); NSFW-фрагменты ещё не гонялись. Для бэкенда: лег-таймаут vojo 45 с несовместим с чанками (63278 с) нужен свой профиль + стриминг. План расширения пула: ваниль qwen3:8b (цена абляции) Qwen3.5-9B RuadaptQwen3 (докачиваются в фоне).
- Бэклог принят: проверка проброса cache-hit агрегаторами (п.4, нужны ключи) в шагах ниже. Задачи 45 не начаты (bge-m3 уже на стенде).
### 2026-07-04 — Сессия 2 полигона (после рестарта WSL с RAM 26GB)
- **llama.cpp `--n-cpu-moe` для 30b-a3b перемерено, «Расхождение» с research/06 подтверждено**: потолок генерации на GTX 1070 **~13.5 tok/s** (не 2530). Таблица конфигов в [03](experiments/03-local-stand.md): ollama 10 llama.cpp `--cpu-moe` 11.2 `--n-cpu-moe 33` 13.5 (VRAM 2.97.8GB, prefill 105208). Узкое место пропускная способность CPU-RAM (DDR4/Pascal), не рантайм; llama.cpp честно лучше ollama (+35% ген., ×23 prefill), но 30b-a3b на этом железе только фоновые роли (~2.5 мин/главу). Скрипт: `eval/llama_moe_bench.sh`.
- **Замер 4 новых dense-моделей** (ваниль qwen3:8b / qwen3.5:9b / +abliterated / ruadapt) готово, таблица в [03](experiments/03-local-stand.md). Три вывода: (1) **абляция бесплатна** qwen3.5 vanilla vs abliterated идентичны по скорости и SFW-качеству 18+-роль можно на abliterated без штрафа; (2) поколение 3.5>3 умеренно (лучше понимание, 25% токенов, 10% скорости); (3) **RuAdapt: токен-выигрыш подтверждён (40% ru-токенов), но перевод развалился** (羅生門→«дерево с колокольчиками») → редактор ru-стиля, не переводчик (как и предупреждал research/06). Разрыв с API держится у всех. **Побочная находка для бэкенда:** thinking у Qwen3.5+/GLM/Gemini для роли переводчика обязателен к отключению (иначе пустой/обрезанный вывод — ловилось дважды: эксп. 02 и здесь).
- **Think-режим (проверка гипотезы владельца «reasoning поднимет качество в разы»)** — [03](experiments/03-local-stand.md), раздел «Влияние thinking». Итог: (а) прежняя «пустота» — артефакт тесного контекста (рассуждения не влезали с ответом), не зависание; (б) с ctx 16k think **завершается и реально чинит реалии** (羅生門: «Радзёмон»→«Рашо-мон»; 朱雀 с китайского чтения на японское) — гипотеза частично подтвердилась; (в) но локально нежизнеспособен: 8,6 мин и ~11k токенов рассуждений на 1400 знаков (вебновелла ≈ 200 ч). **Новый пункт бэклога → оркестратору/бэкенду: проверить think-ON vs OFF по КАЧЕСТВУ на быстром облачном черновике/редакторе (DeepSeek/GLM)** — потенциальный дешёвый рычаг качества, раз reasoning вытаскивает реалии.
- **Справочник провайдерских граблей** → [experiments/00-provider-quirks.md](experiments/00-provider-quirks.md) (по замечанию владельца: бэкенд и полигон оба «ходят к провайдерам», но это не дубль — Go-продакшн-адаптеры 1735 строк с failover/ledger vs 40-строчный Python-зонд сырого поведения; объединять нельзя, но **знание о граблях сведено в один справочник**). Собраны: thinking-управление (GLM/Gemini/gpt-5/Qwen — у каждого по-своему!), Kimi только temp=1, Gemini 3.1 Pro обязательно-думающая, safety_settings Gemini не через OpenAI-слой, localhost-прокси, деприкации. **Бэкенду: читать при правке адаптеров `internal/llm`.**
- **Эксперимент 04 — бейк-офф редакторов ru-стиля** (вопрос бэкенда №2 + замена Anthropic) → [experiments/04-editor-quality.md](experiments/04-editor-quality.md). Метод: DeepSeek-черновик → 4 редактора (glm-4.6/kimi-k2.6/gemini-3.1-pro/grok-4.3) полируют; 4 фрагмента (ja/zh/en); **слепая человеческая оценка владельца** (LLM-судьи на худ. качестве ненадёжны). Артефакт для оценки: https://claude.ai/code/artifact/25394796-96f0-4f3f-b8d0-de000d415472. **Объективно уже видно:** grok-4.3 — быстрый/дешёвый (~13с, без reasoning); **kimi-k2.6 дорогой** (~11k reasoning-токенов на абзац → биллятся как выход); gemini-3.1-pro обязательно-думающая. Цена входит в решение наравне со стилем. **Оценка стиля — на владельце (ожидает).** Методическое следствие для пилота (задача 4): владелец читает только en/ru → человеческая оценка верности возможна лишь на en→ru + русской стороне, для zh/ja нужен английский якорь.
**Эксперимент 04 — РЕЗУЛЬТАТ (04.07):** слепую оценку сделали два фронтир-судьи (GPT + Opus 4.8), сверяясь с **каноническими переводами** (Фельдман/Рогов/Морозов), **сошлись независимо**. Ключ: A=grok-4.3, B=glm-4.6, C=gemini-3.1-pro, D=kimi-k2.6. Итог: стиль **gemini > grok > kimi > glm**; верность **grok > gemini > glm > kimi**; value **grok ≫ gemini > glm > kimi**. **Рекомендация дефолта редактора Фазы 1: `grok-4.3`** (лучший баланс качество/цена, надёжен по смыслу, ~13с/без reasoning), **премиум-эскалация `gemini-3.1-pro`** (лучшая проза, культурные узлы на уровне канона). **GLM-4.6 (текущее допущение Р4 «редактор=GLM») эмпирически слабейший — снять с дефолта; Kimi убрать (худший value: 11k reasoning/абзац, последний по верности).****оркестратору: правка Р4** (полигон архдоки не трогает). Полный разбор — [04-editor-quality.md](experiments/04-editor-quality.md).
**⚠️ КОРРЕКЦИЯ ВВОДНЫХ ОТ ВЛАДЕЛЬЦА (04.07) → ОРКЕСТРАТОРУ, фундаментально:** владелец **НЕ в РФ**; бэкенд на **EU-сервере**, все вызовы моделей идут оттуда; модель — **обычный SaaS с прямыми ключами** (владелец платит за токены, клиент платит за сервис). **BYOK НЕ делается — ни сейчас, ни в планах** (стопнуть в доках). Следствие: **весь «ru-контур / BYOK / агрегаторы» неверен**Р5 «два контура чей ключ» схлопывается в один (прямые ключи), почти весь Р8 (152-ФЗ/259-ФЗ/ЮKassa/ИП) неприменим. Остаётся валидным ru как **язык перевода** (рынок ru-читателей), меняется только доставка. **Правки Р5/Р8/Р9 — на оркестраторе** (полигон архдоки не трогает). Полигон: проверку ru-агрегаторов из очереди **снял**.
### Следующие шаги полигона
- [x] Эксперимент 04 (редактор) — оценён (grok-4.3 дефолт, gemini-3.1-pro премиум; GLM/Kimi не дефолт); правка Р4 на оркестраторе.
- [x] Прогон refusal-бенчмарка (SFW/L1/L2-violence часть) — 66/66 ok, пороги в 02.
- [x] Эталон DeepSeek + llama.cpp 30b-a3b (13.5 tok/s) — в 03.
- [~] **explicit-часть refusal-бенчмарка** — владелец даёт фрагмент реальной вебновеллы («Мастер Гу», жёсткая сцена) → полигон заведёт в корпус и прогонит через провайдеров (кто откажет/вырежет/переведёт). Проверка ставки «Grok = NSFW-канал».
- [x] ~~Проверка ru-агрегаторов~~**СНЯТА** (BYOK отменён владельцем, см. коррекцию выше).
- [—] **Банк памяти (задача 5 + шире)** — по решению владельца выносится в **отдельную сессию «Валидация банка памяти»** (главная точка отказа пайплайна; не бросаться в код без разбора опасных сценариев). Полигон подготовил черновик промта → `docs/MEMORY_RESEARCH_SESSION_PROMPT.md`; **оркестратору вычитать/финализировать**, затем владелец запускает. Замер эмбеддингов (bge-m3 vs Qwen3-Embedding vs LaBSE) — часть мандата той сессии.
- [ ] Довалидация токен-калибровки на 35 главах реальных вебновелл (файлы владельца).
- [ ] Задача 4 (пилот выбора ядра, Фаза 2.5): протокол BWS + панель LLM-судей.
- [ ] **Валидация precision coverage-гейта — гейтит боевой флип** (от оркестратора, D12 Q4). Бэкенд-мини-набор (выпиленные предложения) проверяет recall (≥90%); флип `gates.coverage.enabled:true` упирается в **false-positive rate** на легитимно диалого-плотных главах (сегментация наивная, quote-absorbing §3.7 в v1.1 — на диалогах `sent_cov` может ложно проседать). Прогони гейт (пороги эксп.02: zh-ru<2.2/ja-ru<1.4/en-ru<0.70, sent_cov<0.75) на реальных чанках zh/jaru, замерь долю ложных excision_suspect. Оракул = `eval/refusal_bench.py::classify_output` (тот же, что порт в Go держать в синхроне). Выход: доля ложных флагов по типам глав оркестратор/владелец ставит порог N допустимых флагов и решает флип.
- [x] ~~**Эксперимент 05 — memory-bet**~~ **СНЯТ как низкосигнальный** (решение владельца). Прогон был, но его ось C0-vs-C1 бредит ли модель без глоссария») предрешена, а C3/C2 лишь пере-подтвердили уже процитированную литературу (2510.00829) тест не мог изменить ни одного решения. Артефакты (doc/скрипт/данные) удалены. Единственный actionable-вывод (post-check + disposition обязательны) уже зафиксирован в реестре `architecture/06` (A2/E1) независимо от этого прогона. **Урок для eval:** тест ставить только если его исход мог бы перевернуть решение И не установлен литературой. Ценность вместо этого валидация самого МЕХАНИЗМА (см. ниже).
- [x] **Референс горячего пути банка памяти + self-tests** `eval/memory_hotpath.py` (11/11 PASS). Исполняемая спека механизма (не продукт): нормализация tradsimp/kana, точный матч ключей/алиасов с запретом одиночных (омографы 送灶/// НЕ инъектируются), спойлер-фильтр `since_ch/until_ch` (hard-reject), sticky для местоименных чанков, disposition confirmed/ambiguous/reject, post-check (ловит и утечку, и отравление). **Бэкенду:** порт в Go 1:1, тесты T1T10 unit-тесты; `[PROD]`-замены: OpenCC, Aho-Corasick, pymorphy/`decl`.
> **[ЗАДАЧА ОРКЕСТРАТОРА → eval] Эксперимент 05: memory-bet (индикативный).** Отвечает на главный незакрытый вопрос валидации (research/13 §Вердикт): оправдан ли банк памяти vs просто длинный контекст, и вредит ли ошибочная инъекция (страх владельца). **Runnable сейчас, продукт не нужен** — это конструирование промптов + API-вызовы + метрики.
> **Метод:** один стек `deepseek-chat` (черновик) → `grok-4.3` (редактор, thinking OFF, temp 0.4 — квирки в `00-provider-quirks`). Реальные zh→ru чанки: `eval/data/samples/zh/luxun-ah-q-ch1-4.txt` (повторяющиеся имена 阿Q/赵太爷/王胡/送灶; есть русский эталон Рогова `samples/ru/luxun-ah-q-ru.txt` для якоря верности). Нарезать ~58 перекрывающихся чанков; собрать мини-глоссарий (510 записей: имена+реалии, с dst и `decl`). **4 условия на чанк:**
> - **C0** без глоссария (baseline);
> - **C1** селективная инъекция (только записи, встречающиеся в чанке) — наш банк;
> - **C2** полный глоссарий + скользящее резюме в промпте — «просто длинный контекст»;
> - **C3** случайный/неверный глоссарий (перемешать dst) — адверсариальная рука, прямой замер «вредит ли ошибочная инъекция».
> **Метрики (3 оси):** (а) **консистентность** — детерминированно: рендерится ли approved-dst (по лемме/`decl`) одинаково во всех чанках, где встречается src; (б) **верность/пропуски** — судья чужого семейства (gemini нативный или через промпт «сверь перевод с источником, найди mistranslation/omission»), + сверка с эталоном Рогова где возможно; ru-специфика: согласование рода (вкл. глагол прош.вр.), склонение dst; (в) **стоимость** — токены input/output по условиям (C2 должен быть заметно дороже — часть решения).
> **Правило решения:** C1≈C2 по качеству но C1 дешевле → банк оправдан; C2≫C1 → пересмотреть (нужен полнее контекст); C3 роняет vs C0 → страх владельца подтверждён, post-check/disposition обоснованы.
> **Env:** `eval/.venv` нет `openai`/`dotenv` — доставить (`pip install openai python-dotenv` в venv); ключи из `eval/.env` через dotenv; base_url/слаги в `providers.json`+`00-provider-quirks` (deepseek-chat депрекейт 24.07 — жив сейчас; grok base `https://api.x.ai/v1`). **Оговорка: ИНДИКАТИВНЫЙ** (малый N, LLM-судья) — как retrieval_bench; полная версия с человеческими BWS-аннотаторами = пилот Ф2.5. Выход: `docs/experiments/05-memory-bet.md` + сводка сюда. Сильнее сигнал, если владелец подложит 12 главы реальной вебновеллы с повторяющимися именами — но PD-阿Q хватит для старта.
> **Задачи от оркестратора (04.07, из журнала решений [architecture/05-decisions-log.md](architecture/05-decisions-log.md)):**
> 1. **Пересчитать ОБА cost-числа** (не только премиум) на реальном Фаза-1 стеке — расширено после D8D11: дефолт-редактор теперь **grok-4.3 ($1.25/$2.50)**, не GLM/DeepSeek → и **стандарт-микс** подорожал (ja→ru ранобэ ~$0.73, не $0.17; порог приёмки $0.6 устарел). Дай: (а) стандарт-микс (DeepSeek-draft + grok-editor) на ранобэ ja→ru и вебновелле zh→ru; (б) премиум-микс с апексом Gemini 3.1 Pro (обязательный thinking, reasoning-as-output $12/M; batch 50% только судье/QA, НЕ inline-эскалации; эскалированный чанк платит Gemini дважды). Дефолты $5/$30 и порог $0.6 — заглушки до пересчёта.
> 2. **Замерить, эмитят ли DeepSeek/GLM/Kimi/grok `finish_reason=content_filter`** (D2.4, теперь и grok — он дефолт-редактор): бэкенд ветвит диспозицию по нему, но OpenAI-совместимый слой отдаёт finish_reason сырым — если провайдеры его не шлют, реальная страховка только refusal-blacklist. Дешёвый зонд на отказном фрагменте. Плюс, если есть ключ: подтвердить capability-квирки **gpt-5-nano** (бэкенд предполагает = mini: max_completion_tokens + omit temperature + effort minimal — верифицировать).
> 3. **Think-ON vs OFF по КАЧЕСТВУ на облачных translator/editor** (DeepSeek/GLM/Kimi — subset-billing, безопасно по потолку): гипотеза владельца про reasoning частично подтвердилась локально (羅生門→Радзёмон), DRT (arXiv:2412.17498) подтверждает для роли переводчика. Это ключевой вход в пилот Ф2.5 — мерить именно translator/editor, не только Terminologist.
> 4. Проброс cache-hit/batch RU-агрегаторами (уже в бэклоге) гейтит достоверность всего премиум-бюджета — приоритет поднять.
> 5. **Ключевой набор расширен:** теперь живы и `OPENAI_API_KEY`, и `GEMINI_API_KEY`, и `XAI_API_KEY` — Gemini-судья и Grok-канал-B можно гонять в евалах сразу.
> 6. **xAI/Grok НЕ выведен** (уточнение владельца): ретайрнулся только дешёвый Grok 4.1 Fast, сам провайдер жив. Роли Grok — переводчик канала B **и судья 18+** (не отказывается оценивать explicit). У xAI **промо $150 за data-sharing** — бери на выделенный NSFW-аккаунт: этим разблокируется висящая 18+ часть refusal-бенчмарка (эксп.02) и 18+ плечо пилота. Гони на промо-кредитах: (а) 18+ refusal/excision на Grok/DeepSeek/локальной abliterated; (б) Grok в роли 18+-судьи — качество оценки explicit-сцен. Data-sharing только PD/тест-корпус, реальные книги через него не гнать. Grok в евалах — thinking OFF (reasoning аддитивный).
## Память
(секция сессии «Валидация банка памяти» записи добавлять сюда)
### 2026-07-04 — Сессия «Валидация банка памяти» завершена
Метод: многоагентный ресёрч по 7 направлениям + независимая адверсариальная верификация по первоисточникам + completeness-критик (15 агентов) + локальный эмпирический бенчмарк retrieval на реальном PD-корпусе + чтение кода `backend/`. **Выходы:**
- [research/13-memory-bank-validation.md](research/13-memory-bank-validation.md) вердикт (что менять, обоснование, источники).
- [architecture/06-memory-risk-registry.md](architecture/06-memory-risk-registry.md) **реестр рисков (вход бэкенду перед фиксацией схемы store/глоссария Фазы 1)**.
- Эмпирика: `eval/retrieval_bench.py`, `eval/data/retrieval_bench/` (реюз PD-корпуса полигона, не дублируя инфру).
**Вердикт (кратко):** архитектура ДЕРЖИТ, но **go/no-go на саму ставку сейчас нельзя** центральный детерминированный no-LLM горячий путь **академически нов** (DelTA LLM-в-цикле per-предложение), сравнение «банк vs длинный контекст» на реальном zh/jaru стеке **не проведено**, acceptance-критериев/baseline/cost-модели нет.
**Находки (12 строки):**
- **Q1 Робастность:** опасение владельца уточнено «пусто» безопасно (норма горячего пути), тихую деградацию порождает **ошибочная инъекция** (модель послушно следует неверной строке, уверенность точность 2510.00829). Защита: «лучше ничего, чем мусор» + трёхсторонний disposition (accept/verify/reject) + обязательный post-check.
- **Q2 Масштаб:** brute-force KNN держит с огромным запасом <20 мс на 100k×1024-d (замер); триггеры миграции на порядки выше нужд одной книги.
- **Q3 Корректность retrieval:** детерминированный точный матч **строго лучше** dense на дословных именах (эмпирика: substring precision 1.0, 0/4 ловушек-омографов; char-BM25 все 4 ловушки в top-5); dense/reranker/BM25 только второй эшелон.
- **Q4 Режимы отказа:** DelTA Proper-Noun-Records (first-wins-без-обновления) **сам порождает** stale/contradiction/drift; полная таблица «сценарийзащитаDET/LLM/где в коде» в реестре.
- **Q5 Детерминизм:** soft>hard по качеству (в т.ч. en→ru), но soft молча теряет 1736% терминов → **post-check обязателен**; слепой post-replace в русский — **запрет** (ломает согласование); `decl` — safety, не фича рынка.
- **Q6 Академика:** DelTA (ICLR 2025) En-центрична, LTCR-1 = самосогласованность (не корректность), слабые базовые модели, **нет zh/ja→ru**; сильнейшее переносимое — Karpinska&Iyyer 2023 (польский прокси ru), но mistranslation/omission персистят даже при идеальном контексте.
- **Q7 Вендоры/эмбеддинги:** memory-числа Mem0/Zep первоисточник не переживают (full-context бьёт Mem0; Zep 84%→58% в исправленной репродукции); эмбеддинг-дефолт **bge-m3** (R@5 0.974 vs Qwen3-0.6B 0.891 vs LaBSE 0.827); **ни одна модель не даёт разделяющего порога** (пересечение распределений) → эмбеддинги low-trust, только кандидаты на ревью.
- **Инвариант D5.2 — подтверждён кодом:** `snapshotID` (`runner.go:145-163`) не хэширует версию глоссария/context-assembly, а `RequestHash` включает `msgs` → после инъекции памяти Фазы 1 изменённый глоссарий тихо промахивается мимо чекпоинта и переоплачивает расходящимся переводом. **Общий гейт Фазы 1 (F1 реестра), закрыть ДО инъекции памяти.**
### [ПИНГИ ОРКЕСТРАТОРУ] расхождения с research/05 / Р3 / Р7
Эта сессия архдоки не правит (кроме своих 13/06) — расхождения выношу пингами:
1. **Р3/research/05 §177 «sqlite-vec нельзя, pure-Go не загрузит C-расширение» — неточно.** Верно только для `modernc.org/sqlite`; CGO-free sqlite-vec **существует** (ncruces WASM). Решение brute-force в MVP верно, но рациональ переписать («держим modernc единым драйвером», а не «pure-Go не может»). → правка формулировки Р3.
2. **Р3/research/05 §7 «один стек LaBSE на выравнивание и RAG» — опровергнуто эмпирически** (LaBSE слабейшая на retrieval, R@5 0.827). LaBSE — только Bertalign; RAG — bge-m3 (дефолт) + Qwen3-Embedding-0.6B (challenger, добавить в стек Р4). → правка Р3/Р4.
3. **research/05 §4.1 «vectorized-активация — все три нужны» — не в горячем пути** (вредна там); только второй эшелон. §5.2 «желательно без эмбеддингов» → **строго без** для дословных терминов.
4. **research/05 §4.2 DelTA / §1.2 Zep / §5.3 constrained decoding — числа/атрибуции поправить** (см. research/13 Q4/Q5/Q6): LTCR-1 = самосогласованность, не качество; DelTA-память LLM-в-цикле (не детерминированная — наша ставка нова); «структурированная память > длинный контекст» — гипотеза, не доказанное; вендор-числа Mem0/Zep убрать; «constrained decoding портит качество» overstated (реальная причина — закрытые API).
5. **Р3/Р7 усилить:** post-check из «флаггера» в **обязательный гейт** (E1/E2 реестра); спойлер-окно `since_ch/until_ch`**safety-гейт с жёстким reject+лог**, не UX-фича; добавить ось «редакционное время» ⊥ спойлер-окну (stale/drift); гейт фактичности **резюме** (у резюме нет post-check-аналога — первоклассный пробел D1).
6. **zh/ja→ru-специфика, не покрытая ни одним доком:** стандарты транслитерации **Палладий (zh)/Поливанов (ja)** (ось корректности ⊥ самосогласованности — крупнейший пробел, B6); утечка рода через **русский глагол прош. вр.** мимо `gender=hidden` (морфо-гейт Ф2 должен сканировать глаголы — C3).
### [БЭКЕНДУ] шаг «миграция памяти v2» разблокирован — с гейтами
Реестр вышел → шаг 4 можно фиксировать, **соблюдая `architecture/06` §Гейты**: (1) **F1 snapshotID под память+context-assembly ДО инъекции** (общий гейт, держит D1/D5); (2) схема D7 + `sense`, ось редакционного времени, `UNIQUE(src,sense,window)`+обратная dst-проверка, `min_key_len`+запрет одиночных ключей, нормализация NFKC/OpenCC/kana/ruby; (3) post-check обязателен, слепой post-replace в ru запрещён; (4) трёхсторонний disposition + per-chunk retrieval-state запись. **Горячий путь = НЕ FTS5** (impl-notes §3.6 уже так; FTS5 не сегментирует CJK), а детерминированный Aho-Corasick/trie. **Ставку на банк памяти НЕ морозить до in-house eval** (протокол/acceptance — research/13 §Вердикт: WMT25-трёхрежимный, baseline «банк vs длинный контекст», предзарегистрированные пороги).
### [ВЕРДИКТ ОРКЕСТРАТОРА] банк памяти — GO на схему+гейты, ставка гейтится eval'ом (параллельно, не блокер)
Валидацию принял (15 агентов + верификация + свой retrieval-бенчмарк — самый провалидированный артефакт проекта). Пинги применены в Р3/Р7 (`01-decisions.md`). Разбор надвое:
- **Схема + детерминированный горячий путь + 5 гейтов реестра — GO, low-regret.** Строим сейчас: структурированный глоссарий нужен как СУБСТРАТ для post-check-гейта («тихое→громкое») в любом случае, спойлер/род-гейты — safety в любом случае, а режим инъекции уже конфиг (`selective|full_prefix`). Даже если eval покажет «длинный контекст победил» — флипается конфиг инъекции, а не схема. Поэтому схема не гейтится eval'ом.
- **Ставка (достаточность селективной инъекции vs полный контекст + whole-book эмбеддинг-слой) — гейтится in-house eval'ом**, но eval идёт ПАРАЛЛЕЛЬНО реализации схемы, не блокирует её. Eval — часть пилотного трека (тот же голд-сет, WMT25-трёхрежимный протокол); фолдим в пилот Ф2.5, не отдельная сессия.
- Ключевая переоценка опасения владельца принята: тихую деградацию порождает не «пусто», а **ошибочная инъекция** — и мы её **конвертируем в громкую** (post-check + disposition + retrieval-state), а не устраняем обещанием. Это и есть ответ на твой страх.
- Крупнейший непокрытый пробел — **транслит-стандарты Палладий/Поливанов** (ось корректности ⊥ самосогласованности, реестр B6) и **утечка рода через русский глагол** (C3): заложены в реестр, Фаза 2.
- **Сессия «Валидация банка памяти» — задача выполнена, закрывается.** In-house eval — уже не её мандат, а пилотного трека.
> **[БЭКЕНДУ]** реестр `architecture/06` — твой контракт для шага 4 (миграция памяти v2). Порядок: **F1 (snapshotID под память+context-assembly) — ПЕРВЫМ** (общий гейт, держит D1/D5, независим от memory-вопроса — код отстаёт от impl-notes §3.2, там уже предписан версия-счётчик); затем схема v2 = D7 + добавления реестра (`sense`, ось редакционного времени, `UNIQUE(src,sense,window)`+обратная dst-проверка, `min_key_len`+запрет одиночных ключей, артефакт нормализации NFKC/OpenCC/kana/ruby); горячий путь = **Aho-Corasick/trie, НЕ FTS5** (impl-notes §3.6 уже так); post-check обязателен, слепой post-replace в ru запрещён; трёхсторонний disposition + retrieval-state запись. Режим инъекции держи конфигом (`selective|full_prefix`) — eval потом решит дефолт. Отложенное в v1.1/Ф2 (заложить поля/место, не реализовывать): Палладий/Поливанов B6, гейт фактичности резюме D1, эмбеддинг-слой A7, бэкап файла F4, морфо-гейт глагольного рода C3.
> **[ПОЛИГОНУ/ПИЛОТУ]** in-house memory-eval — дециждающий эксперимент, фолдится в пилот Ф2.5: WMT25-трёхрежимный (no / correct / **random** terminology — random-рука ловит тихую деградацию) на реальных zh/ja→ru чанках; **обязательный baseline «банк ON vs OFF» и «банк vs длинный контекст frontier-модели»** на том же стеке (DelTA этого не делала — это пробел, который решает go/no-go на ставку); мерить две оси раздельно (самосогласованность approved-форм + source-fidelity/omission через CometKiwi + LLM-судья-против-источника); ru-специфика (согласование рода вкл. глагол, склонение dst); предзарегистрировать пороги + допустимый flag-volume на главу. Эмбеддинг-бенчмарк уже сделан этой сессией (bge-m3 дефолт, `eval/retrieval_bench.py`) — переиспользуй.
> **[СЕССИЯ ЗАКРЫТА, 04.07]** Выходы: research/13 (+§«Честные слабые места»), architecture/06, `eval/memory_hotpath.py` (спека), `eval/retrieval_bench.py` (эмбеддинги). Эксп-05 снят как низкосигнальный. **Перед кодом реализующей сессии — прочитать research/13 §«Честные слабые места»:** F1 подан как решённый, но там развилка (snapshot материализует байты vs store версионирует глоссарий); post-check в русской морфологии — несущий, но невалидированный (померить до доверия как гейту); «пусто=безопасно» — размен на ложный-пропуск, который тоже тихий; ставка на детерминированный no-LLM путь — cost-driven, не evidence-driven (DelTA валидирует LLM-в-цикле). Гигиена: фоновых процессов нет, ollama полигона не тронут, `eval/.venv` дополнен (torch-cpu/sentence-transformers/openai/dotenv — переиспользуемо).
> **[ДОБАВЛЕНО после закрытия] Локалка × банк памяти — экстракция терминов, ВЕРИФИЦИРОВАННЫЙ бенчмарк (дыра G1)** → [experiments/06-local-extraction.md](experiments/06-local-extraction.md), `eval/extract_bench.py`. 13 моделей × 12 кейсов (zh/ja/en + эдж: катакана-запад, буддийские имена, алиасы), запросы через `refusal_bench.call_provider`+`providers.json` (квирки верны: deepseek thinking-ON+max_tokens 8000 — прошлый пустой был МОЯ ошибка бюджета, не свойство модели), **каждый ответ health-верифицирован** (пустой/echo не засчитан как recall 0). Итог: **(1) СПОТ сущностей решён у всех, локаль вкл.** (recall ~0.98 на всех языках, 0 галлюцинаций). **(2) РЕНДЕР dst — разрыв с ЯЗЫКОВЫМ градиентом у локали:** en 0.82 / ja 0.53 / **zh 0.26** (阿Q→«Ах-Чу», 赵太爷→«Тяо Тай-Я» — Палладий-мусор → **эмпирика для B6**); облако-топ zh 0.75/ja 0.98/en 1.0. **(3) бо́льшая локаль не помогает** (30b render 0.55≈8b, ×3 медленнее). **(4) deepseek thinking помогает рендеру** (0.85 vs 0.58 off; на экстракции thinking-off здоров — echo бьёт перевод, не JSON). Рендер-value: **gemini-2.5-flash** (0.92/1.4с). **Дизайн-следствие (уточняет Р4/G1):** спот=дешёвая 8b (все языки); рендер dst язык-зависим — zh обязательно облако/человек + таблица Палладия (B6), en локаль потянет. ruadapt ненадёжен (5/12 health).
> **[В ОЧЕРЕДИ, 05.07] Исследование «Адаптивный/обучающийся слой памяти»** — промт `docs/ADAPTIVE_MEMORY_RESEARCH_PROMPT.md` (подготовлен сессией валидации по запросу владельца). Вопрос: стоит ли гибрид «детерминированный банк + слой, обучающийся по ходу книги», и как смёржить под контур (локаль-first, дешёвое API ок, флагман без логитов → kNN-MT/frontier-LoRA заблокированы; обучаемое — только на локали, роль support, не переводчик). Центр — арбитраж «кто побеждает» (логика + VRAM 8ГБ). БАР: обязан бить eval-валидированный детерминированный базис на zh/ja→ru, иначе не мёржить. Тайминг: Фаза 2+, целить в реальные дыры (после in-house eval банка). Запускает владелец отдельной сессией.
### 2026-07-05 — Сессия «Адаптивный слой памяти» ЗАВЕРШЕНА → [research/14-adaptive-memory.md](research/14-adaptive-memory.md)
Метод: 6-направленный ресёрч + 24 адверсариальных верификатора (**19 CONFIRMED / 5 OVERCLAIM** с поправкой) + **2 исполняемые пробы на стенде/ключах** + чтение кода на git HEAD. **Вердикт: гибрид в основном НЕ стоит того; ровно ОДИН eval-гейтед кандидат.**
- **Жёсткий контур подтверждён живой пробой** (`eval/adaptive_probe.py`, 2026-07-05): kNN-MT/constrained/frontier-LoRA на флагмане **физически blocked** — kNN-MT ключует hidden state декодера (Khandelwal 2010.00710), а его никто не отдаёт; из наших только **deepseek возвращает logprobs** (top-5), **grok-4.3/gemini-3.1/gpt-5 — нет** (gpt-5 даёт 403). Даже logprobs ≠ hidden state → двойная дверь.
- **In-context демонстрации — единственный кандидат под контур, но НЕ бьёт базис по консистентности** (`eval/adaptive_incontext.py`, реальный zh→ru 阿Q, канон Рогова, N=3): без памяти 0.458 → **soft-глоссарий Р3 0.875** → глоссарий+демонстрации **0.833** (в шуме). Литература: 65% выигрыша демо — стиль (Li 2503.05010), а БАР меряет консистентность/fidelity. → **пилотировать под eval со стилевой осью, не мёржить.**
- **Локальный kNN-MT / книга-LoRA — НЕ мёржить:** чистый выигрыш kNN уже у детерминированного банка (жёсткая гарантия vs мягкая интерполяция); kNN ≈ GD только на output-projection (Gao 2305.13034) → не чинит сломанные zh-реалии локали (render 0.26); data-poor (сотни пар, LoRA «learns-less» 2405.09673).
- **Само-коррекция:** intrinsic self-correction деградирует без внешнего верификатора (Huang 2310.01798) — а он у нас **уже детерминированный** (post-check) → «детект дрейфа → коррекция» уже решено, не в обучающийся слой.
- **VRAM-гипотеза владельца (эмбеддер→CPU, 8ГБ→обучающийся модуль): верна в посылке, пуста в следствии.** CPU-эмбеддинг — правильный дефолт (real-time эмбеддинга в пайплайне нет, горячий путь = Aho-Corasick), но **обучающегося модуля, который на 8ГБ бьёт базис, НЕТ** → освобождённый VRAM отдать существующим support-ролям локали. **Реальный Pascal-замер (изолир. CUDA-env, 0.5B): QLoRA-4bit РАБОТАЕТ на sm_61 вопреки sm≥75, но ~×9 медленнее fp16-LoRA** (нет Pascal-ядер → преимущество QLoRA инвертируется); потолок удобной тренировки ~1.53B; 7B-QLoRA на/за пределом 8ГБ.
> **[РАСХОЖДЕНИЕ → оркестратору]** (1) Литература «Log Probability Tracking» (2512.03816) утверждает «все xAI/GPT возвращают logprobs» — **живая проба опровергает** (grok-4.3 нет, gpt-5 → 403): урок «проверяй пробой» подтверждён. (2) **Хорошая новость ядру:** soft-глоссарий Р3 индикативно **сильно работает на zh→ru** (0.458→0.875) — валидация банка это на нашем направлении не мерила. (3) Гипотеза владельца о VRAM — принята как инженерная гигиена, отклонена как путь к «обучающемуся модулю, бьющему базис».
> **[БЭКЕНДУ]** Из research/14 в банк v2 фолдится **M2 (детерминированно, 0 ML, 0 VRAM):** консистентность-кэш auto/ambiguous (first-seen/majority-vote) + precision-gated adaptive-retrieval КАКИЕ серо-зонные записи инъектить с **hard-abstention** (лучше ничего, чем мусор). Это гигиена банка, закрывает recall-0.571-дыру и B1 first-wins. **НЕ строить:** локальный kNN-MT, книга-LoRA, constrained decoding, self-correction-как-слой (всё не проходит БАР/физически blocked).
> **[ПИЛОТУ]** M1 (in-context демонстрации, серая зона) фолдится в тот же WMT25-3-режимный eval, что и банк, **+ стилевая ось** (win-rate человека/сильного судьи): критерий — бьёт ли базис по стилю БЕЗ потери консистентности/fidelity и без роста дистрактор-вреда. Индикатив этой сессии: по консистентности не бьёт; стиль не измерен.
> **[ГИГИЕНА]** Модель полигона `qwen3-abliterated:30b-a3b` (6.4 ГБ VRAM) **не выселялась** — GPU-проба шла в свободном CUDA-окне (WSL2 спилит в shared RAM), после — cleanup. Артефакты: `eval/adaptive_probe.py`, `eval/adaptive_incontext.py` (+ `eval/data/*.json`), новые доки — только `research/14`. Изолированный CUDA-env (Pascal-проба) — в scratchpad, не в репозитории. Полный потолок QLoRA-7B+reranker на **чистых** 8ГБ — за скоординированным стенд-окном (не мерил, чтоб не выселять 30b); на вердикт не влияет (кандидата нет).
> **[ДОБАВЛЕНО, 05.07 — «долбить детерминированную сторону»]** По запросу владельца (раз гибрид отклонён — максимизировать коэффициент канон-консистентности детерминированно) — замер рычагов L1→L4 на ТРУДНОМ чанке (`eval/adaptive_levers.py`, 11 сущностей, deepseek+grok), research/14 §9. **Порядок бэкенду:** **L1 post-check ЛЕММАТИЗИРУЮЩИЙ (pymorphy3), не регэксп** — ПЕРВЫМ (наивный регэксп даёт **1836% ЛОЖНЫХ флагов** на трудном чанке; pymorphy сворачивает и OOV-транслит Вана→ван; количественная валидация несущего риска research/13 §2). **L2 recall — нормализация ПОЛНАЯ+тестируемая (OpenCC, не мини-карта: живой A4-баг 爺→爷 молча промахнул 赵太爷) + alias-граф + sticky** (recall 0.00→0.50→0.75). **L3 re-ask** (deepseek 0.82→0.91). **L4 таблица Палладия (B6) — потолок ПРАВИЛЬНОСТИ.** Побочно: 钱 (односимвольный гомограф Цянь/деньги) упорно промахивается → **min_key_len/запрет одиночных ключей A3 обязателен.** Поправка §2: soft-глоссарий на лёгком чанке = **~1.0** (0.875 был регэксп-артефакт), demos не бьют — потолок. Артефакты: `eval/adaptive_reask.py`, `eval/adaptive_levers.py`. Инстинкт «тюнить ранкер» — легитимен только во 2-м эшелоне (bge-m3 без разделяющего порога), не в костяке.