textmachine/docs/PROGRESS.md

125 KiB
Raw Blame History

Журнал прогресса

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 — перевалидация решений, финал фаз — агентное селфревью). Оркестратор делает внешнее ревью её кода.
  • Параллельная сессия «Полигон» запущена (эксперименты 0103 идут).
  • Сессия «Редакция» (промпты ролей) — после фиксации формата конфига в Фазе 0.
  • Сессия «Валидация банка памяти» — завершена (вердикт GO на схему+гейты; реестр architecture/06; ставка гейтится in-house eval'ом в пилоте Ф2.5).
  • Пилот 4 рук для выбора ядра пайплайна + in-house memory-eval (Фаза 2.5).
  • Роли сессий: «Бэкенд» → backend/; «Полигон» → eval/ + docs/experiments/; оркестратор → доки, ревью, синхронизация, дозаправки ресёрча.
  • Дозаправка ресёрча выполнена (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.
  • Главные находки валидации (упущения передачи): в 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 (~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 гоняет чанк draft→edit с полным учётом $ по стадиям в 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), мини-раннер draft→edit с resume; cmd/tmctl (translate/report); черновики промптов ролей.
  • Финал — агентное селфревью: /code-review (8 линз) + воркфлоу-критики (4 линзы задания) с адверсариальной верификацией; подтверждённые находки исправлены двумя волнами (детали и остаточный техдолг — 03-implementation-notes §6). Коммиты: 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_ttl↔cache_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. Кратко: 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; убирает риск zh→ru кальки от 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. Все 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. Онбординг-поправки ратифицированы (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_bodycapabilities.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), (б) memoryVersioncontent-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-5grok-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, заземлён ресёрчем 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 хардкод) → TranslateBooktranslateChunk (цикл стадий) → runStagerunAttempt (ось attempt). RunResultChunkOutcome (per-chunk) + BookResult (агрегат книги). Чанкер — минимальный детерминированный плейсхолдер (chunker.go SplitChunks: разбивка на главы по form-feed, паковка абзацев ≤1500 симв., абзац не режется); настоящий лингвистический чанкер — шаг 3, подменит SplitChunks не трогая цикл/disposition. chunkerVersion бампнут v1-wholefilev2-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.ExitOnErroros.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, перевода нет». Провалидировал трассировкой capability→wire (не грепом):

Состояние детекта (после Вехи 2):

  • Эхо (cjk_artifact) ДЕТЕКТИТСЯ: classify (disposition.go) флагует при cjkShare(out) > 0.15 (порог из refusal_bench). Полигоновское «детекта нет» устарело — добавлено в Вехе 2 (после их грепа). НО: в РАННЕРЕ (disposition-слой, post-settle), НЕ в адаптере/failover; сейчас ФЛАГ, эскалации нет (эскалация — шаг 7).
  • Пусто ДЕТЕКТИТСЯ: classifyempty (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. Не блокирует шаг 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-flashReasoningNone; 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<коридор-lowexcision_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-детерминизм, healthy→pass, snapshot-флип→--resnapshot, no-thresholds→fail-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/v1api.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_filterFlagReason.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-заглушек → префлайт ключей эскалации отвязан от gatesEnabledbudget_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 — отдельные задачи).

Полигон

(секция параллельной сессии — записи добавлять сюда)

Сообщение от основной сессии (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. Два расхождения с 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. 6 провайдеров × 11 фрагментов (SFW/L1/L2-violence): 66/66 ok — ноль отказов и вырезаний, контроль ложных срабатываний пройден; содержательная 18+ часть ждёт explicit-фрагментов владельца. Пороги len_ratio для coverage-гейта готовы (п.2 вводных): zh→ru <2.2, ja→ru <1.4, en→ru <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. По п.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: ollama 10 → llama.cpp --cpu-moe 11.2 → --n-cpu-moe 33 13.5 (VRAM 2.9→7.8GB, prefill 105→208). Узкое место — пропускная способность 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. Три вывода: (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, раздел «Влияние thinking». Итог: (а) прежняя «пустота» — артефакт тесного контекста (рассуждения не влезали с ответом), не зависание; (б) с ctx 16k think завершается и реально чинит реалии (羅生門: «Радзёмон»→«Рашо-мон»; 朱雀 с китайского чтения на японское) — гипотеза частично подтвердилась; (в) но локально нежизнеспособен: 8,6 мин и ~11k токенов рассуждений на 1400 знаков (вебновелла ≈ 200 ч). Новый пункт бэклога → оркестратору/бэкенду: проверить think-ON vs OFF по КАЧЕСТВУ на быстром облачном черновике/редакторе (DeepSeek/GLM) — потенциальный дешёвый рычаг качества, раз reasoning вытаскивает реалии.

  • Справочник провайдерских граблей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. Метод: 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.

⚠️ КОРРЕКЦИЯ ВВОДНЫХ ОТ ВЛАДЕЛЬЦА (04.07) → ОРКЕСТРАТОРУ, фундаментально: владелец НЕ в РФ; бэкенд на EU-сервере, все вызовы моделей идут оттуда; модель — обычный SaaS с прямыми ключами (владелец платит за токены, клиент платит за сервис). BYOK НЕ делается — ни сейчас, ни в планах (стопнуть в доках). Следствие: весь «ru-контур / BYOK / агрегаторы» неверенР5 «два контура чей ключ» схлопывается в один (прямые ключи), почти весь Р8 (152-ФЗ/259-ФЗ/ЮKassa/ИП) неприменим. Остаётся валидным ru как язык перевода (рынок ru-читателей), меняется только доставка. Правки Р5/Р8/Р9 — на оркестраторе (полигон архдоки не трогает). Полигон: проверку ru-агрегаторов из очереди снял.

Следующие шаги полигона

  • Эксперимент 04 (редактор) — оценён (grok-4.3 дефолт, gemini-3.1-pro премиум; GLM/Kimi не дефолт); правка Р4 на оркестраторе.
  • Прогон refusal-бенчмарка (SFW/L1/L2-violence часть) — 66/66 ok, пороги в 02.
  • Эталон DeepSeek + llama.cpp 30b-a3b (13.5 tok/s) — в 03.
  • [~] explicit-часть refusal-бенчмарка — владелец даёт фрагмент реальной вебновеллы («Мастер Гу», жёсткая сцена) → полигон заведёт в корпус и прогонит через провайдеров (кто откажет/вырежет/переведёт). Проверка ставки «Grok = NSFW-канал».
  • Проверка ru-агрегаторовСНЯТА (BYOK отменён владельцем, см. коррекцию выше).
  • [—] Банк памяти (задача 5 + шире) — по решению владельца выносится в отдельную сессию «Валидация банка памяти» (главная точка отказа пайплайна; не бросаться в код без разбора опасных сценариев). Полигон подготовил черновик промта → docs/MEMORY_RESEARCH_SESSION_PROMPT.md; оркестратору вычитать/финализировать, затем владелец запускает. Замер эмбеддингов (bge-m3 vs Qwen3-Embedding vs LaBSE) — часть мандата той сессии.
  • Довалидация токен-калибровки на 35 главах реальных вебновелл (файлы владельца).
  • Задача 4 (пилот выбора ядра, Фаза 2.5): протокол BWS + панель LLM-судей.
  • Эксперимент 05 — memory-betСНЯТ как низкосигнальный (решение владельца). Прогон был, но его ось C0-vs-C1 («бредит ли модель без глоссария») предрешена, а C3/C2 лишь пере-подтвердили уже процитированную литературу (2510.00829) — тест не мог изменить ни одного решения. Артефакты (doc/скрипт/данные) удалены. Единственный actionable-вывод (post-check + disposition обязательны) уже зафиксирован в реестре architecture/06 (A2/E1) независимо от этого прогона. Урок для eval: тест ставить только если его исход мог бы перевернуть решение И не установлен литературой. Ценность вместо этого — валидация самого МЕХАНИЗМА (см. ниже).
  • Референс горячего пути банка памяти + self-testseval/memory_hotpath.py (11/11 PASS). Исполняемая спека механизма (не продукт): нормализация trad→simp/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):

  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 — вердикт (что менять, обоснование, источники).
  • 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/ja→ru стеке не проведено, 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_chsafety-гейт с жёстким 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, 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 банка). Запускает владелец отдельной сессией.