Split PROGRESS journal: move 330KB of closed 04-10.07 chronology to archive with verbatim headings, keep live sections and anchors, repoint incoming references
This commit is contained in:
parent
a83313d0c3
commit
9e3762eaa8
7 changed files with 986 additions and 950 deletions
953
docs/PROGRESS.md
953
docs/PROGRESS.md
|
|
@ -98,685 +98,9 @@
|
|||
|
||||
**12.07: research/16 «Ридер-IDE» отревьюирован и залендён (458b0ea), ратификация D29.** 4 оси (источники ×2 по первоисточникам, независимая реплика $0-пробы, red-team контракта против кода/D15.2-спеки): **ACCEPT_WITH_FIXES**. Ядро принято: чанк = несущий якорь; precision-гейт YELLOW перед показом цветов (<10% ложных/флаг); детект-флаггер, не форс-структура; числовой confidence — никогда без QE. Поправки ревью: числа пробы — верх метрик-диапазона 44–58% на stale-базе (DB-истина 57.4%/70.4%, редактор 90.7%, не 93%); «полностью из read-model» — оверклейм (src/dst_range, source_file_hash, спаны = net-new → нужна настоящая `tmctl export`-команда с ассемблером); passport-3-тир = явный амендмент вердикт-правила D12/exp07 (при gate-on glossary_miss уже катится в fail); override-ключ = хеш СЫРОГО src-текста (не content_hash=rendered msgs — ловушка), override — новое provenance-состояние, не «verdict-нейтрален». Плюс находка реплики: 8/54 финалов несут markdown-`###` → нормализация выхода в экспорт-контракт. Абсорбция: D29.1(а–д) в пакет D15.2; полигону 4 задачи (precision — только post-hoc, пре-регистрацию exp12 не трогать); Ф3-хвост — в F3-brief.
|
||||
|
||||
## 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 тома ранобэ ~$2–4 при марже 70–96%; главные рычаги — 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` — фазы 0–3 с критериями приёмки.
|
||||
- `architecture/components.puml` + `pipeline.puml` (+ отрендеренные .svg) — провалидированы PlantUML.
|
||||
- `PARALLEL_SESSION_PROMPT.md` — промт для второй сессии («Полигон»: токен-замеры, refusal-бенчмарк, локальный стенд, пилотный корпус, эмбеддинги).
|
||||
- Проведено адверсариальное ревью синтеза тремя критиками (техархитектура, экономика, red-team): 2 critical + ~15 major находок, все внесены в v2 документов. Главные исправления:
|
||||
- экономика разделена на контуры «чей ключ» (прямые ключи / ru-агрегаторы ×2–6 на флагманы / 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 честно сдвинут до 10–11 недель;
|
||||
- baseline метрики качества заменён с «сырой DeepSeek» на «DeepSeek+глоссарий» (уровень VseGPT), порог — статистический;
|
||||
- в план добавлены режим онгоинга и series-bible-lite (сегмент «ИИ-фабрик» и проверка рода/ты-вы).
|
||||
|
||||
### Следующие шаги
|
||||
- [~] Фаза 0 (каркас) ЗАВЕРШЕНА; машинерия Фазы 1 в основном построена — сессия «Бэкенд» (промт: `archive/prompts/BACKEND_SESSION_PROMPT.md`; шаг 0 — перевалидация решений, финал фаз — агентное селфревью). Осталось: полный стек-wiring, автопопуляция глоссария, реальный ja→ru прогон. Оркестратор делает внешнее ревью её кода.
|
||||
- [x] Параллельная сессия «Полигон» запущена (эксперименты 01–03 идут).
|
||||
- [ ] Сессия «Редакция» (промпты ролей) — после фиксации формата конфига в Фазе 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-09 — Стратегическое ревью + консолидация доков (оркестратор)
|
||||
|
||||
- **Стратегическое ревью выполнено** → [`architecture/07-strategic-review.md`](architecture/07-strategic-review.md) (коммит b1d54b6). Метод: 14 сборщиков (8 репо-аудиторов + 6 SOTA-веб) → 9 адверсариальных верификаторов (8 CONFIRMED / 1 PARTIAL; 6 находок воспроизведены исполнением временных Go-тестов). Вердикт: **архитектура end-to-end цела**, наука-2026 подтверждает C1-схему/чанки+гейты/терминологию/DeepSeek-draft; детерминированному пути памяти аналогов не найдено. Топ-находки: D1-моноредактор получил внешне измеренный налог верности (2605.13368, вкл. en→ru); `--resnapshot` = переоплата книги (блокер онгоинга); 4 дыры границ доверия памяти (одна — ложно отсеяна 44-агенткой 0/3); слепота exp04 структурно сломана (ключ в артефакте при оценке); memory_eval контаминирован эхом глоссария; 18+ — ноль замеров (critical); DeepSeek выбыл из explicit-канала B по ToS 27.03.2026.
|
||||
- **Роль оркестратора передана этой сессии (решение владельца 09.07).** Владелец подтвердил курс: Rust-переписывание — НЕТ до пост-пилота (Р1/Go остаётся); архив + онбординг-доки — одобрены.
|
||||
- **Ратифицированы D13–D17** ([05-decisions-log](architecture/05-decisions-log.md)): D13 поправки пилота (арм моно-vs-билингв, гетерогенные кандидаты C2, панель 2–3 семейства × 11+ повторов, починка харнесса ДО прогона); D14 канал B (минус DeepSeek-explicit, плюс проба Mistral, xAI-опора = AUP); D15 resume/онгоинг (комментарии-фиксы + status/redrive сейчас, content-addressed reuse — гейт онгоинга); D16 фиксы границ памяти; D17 D1 понижен до «дефолт Ф1, оспорен — решает пилот».
|
||||
- **Консолидация доков:** `02-mvp-plan` → v3 (мёртвые пороги сняты, интерим-18+ переписан, фазы синхронизированы); обе `*.puml` → v3 (минус Opus/BYOK/«≤2×», плюс ре-гейт эскалации, три класса отказов D12, человек в петле, фазовые пометки); superseded-баннеры на `research/01/02/03/04/09`; провенанс-шапки на два внешних `12-*`-дока; закрытые промты → `docs/archive/prompts/`; онбординг: корневой `CLAUDE.md` + `backend/README.md` + `eval/README.md` + обновлённый `docs/README.md`.
|
||||
- **Хендофф-промты выданы (09.07):** [`BACKEND_SESSION_PROMPT_REVIEW_FIXES.md`](BACKEND_SESSION_PROMPT_REVIEW_FIXES.md) — гигиена (комментарии resume, prompt_version-бамп) → фиксы памяти D16 → `tmctl status`/`redrive` → спека content-addressed resume (D15.2) → reasoning-буфер additive (D13.6) → перепроверка отсевов 44-агентки; [`POLYGON_SESSION_PROMPT_PILOT_HARNESS.md`](POLYGON_SESSION_PROMPT_PILOT_HARNESS.md) — memory_eval (эхо-контроль, полные выходы, fidelity, M0–M3, синк с Go) → гигиена оценочных артефактов → протокол пилота v2 (D13) → проба Mistral (⚠ нужен `MISTRAL_API_KEY` от владельца) → kana-precision → подготовка вебновелл-среза. ⚠ Порядок запуска: бэкенд-сессию первой или одновременно — полигон синкает зеркало памяти с кодом ПОСЛЕ D16-фиксов (в промте оговорено).
|
||||
|
||||
### 2026-07-09 (вечер) — Внешнее ревью и приёмка обоих пакетов (оркестратор)
|
||||
|
||||
- **Оба пакета приняты и залендены** (backend 153277e, eval 9afea37) после внешнего ревью (7 ревьюеров, всё исполнением: CLI-прогоны на моках $0, мутационные реверты в scratchpad-копии, пересчёт данных из raw). Вердикты: backend-d16 / backend-ops / spec-d15 / eval-harness / eval-protocol — ACCEPT_WITH_FIXES; backend-misc / координация — ACCEPT. Самоотчёты обеих сессий соответствуют диффам; заявленные цифры полигона воспроизведены точно (M0 0.567/94.6 · M1 1.0/93.4 · M2 1.0/93.4 · M3 0.467/49.0, echo 0/5; kana-таблица байт-в-байт; вебновелл-эхо 4/16 подтверждено по сырым выходам).
|
||||
- **Ратификации** → полный текст в [`05-decisions-log.md`](architecture/05-decisions-log.md) §«Ратификации 09.07»: (1) kana/Han-исключение из source-границы (D16.3) — ратифицировано, kana-омографы → B6, MIN=3 — дефолт; (2) **спека D15.2: направление да, реализация заблокирована** — 3 дизайн-дыры (fast-path-гард слабее текущего; расщепление memory_version обязательно; замена consent-гейта); (3) Mistral: refusal принят, fidelity-числа НЕ приняты (нет сырых артефактов — переснять с персистом); (4) Pearmut-отказ ратифицирован.
|
||||
- **Fix-листы след. пакетов** (в D-логе §Ратификации, пп.5–6): бэкенду — homophone first-wins (major), GB18030-ingest, мутационное закрепление redrive-инварианта, snapshot-чек до ResetChunkStages + minors; полигону — дозеркалить suppressUnboundedPhonetic и апостроф-фолд (критично для en→ru руки), эхо-детектор хвоста, Mistral-переснятие + minors.
|
||||
- Гигиена: `*.key.json` в .gitignore; **правило git-координации мультисессий** внесено в CLAUDE.md (признание инцидента: перезапись истории оркестратором 09.07 при грязном дереве полигона стёрла его незакоммиченные правки — восстановлены сессией).
|
||||
- **Ждём от владельца (без изменений):** explicit-18+ фрагменты (последний critical-блокер D14.4), приёмочная ja→ru книга (epub) для прогона D9, провенанс двух внешних 12-*-доков; решение по юр-пакету (EU-хостинг/провайдер-матрица данных/compliance-паспорт — обсуждено 09.07).
|
||||
|
||||
### 2026-07-09 (поздний вечер) — D18 + промты пакетов №2 (оркестратор)
|
||||
|
||||
- **D18 ратифицирован (решение владельца):** приёмка Фазы 1 — на **蛊真人 zh→ru** (полная книга ~2.5k глав от владельца лежит на стенде: `/home/ubuntu/books/gu-zhenren/guzhenren-gb18030.txt`, GB18030+CRLF — проверено декодом; текст и производные ВНЕ git); ja→ru — второй прогон при появлении ja-epub (форсирующая функция D9 по ruby уже выполнена кодом). Полный текст — D-лог D18.
|
||||
- **18+ блокер снят владельцем:** explicit-фрагменты берутся из 蛊真人 (dark/violence; покрытие l2-erotica полигон оценит честно — возможно понадобится второй источник).
|
||||
- **Хендофф-промты №2 выданы** (старые закрыты → archive): [`BACKEND_SESSION_PROMPT_ACCEPTANCE_PREP.md`](BACKEND_SESSION_PROMPT_ACCEPTANCE_PREP.md) — fix-лист ревью (homophone first-wins и др.) → GB18030-ingest → дешёвые гейты Ф1 → спека D15.2 v2 → smoke-прогон 1 главы 蛊真人; [`POLYGON_SESSION_PROMPT_EXPLICIT_AND_MIRROR.md`](POLYGON_SESSION_PROMPT_EXPLICIT_AND_MIRROR.md) — синк зеркала (suppressUnboundedPhonetic+апостроф) → Mistral-переснятие → **18+ рука на 蛊真人 (эксп.10)** → сид-глоссарий приёмки → терсный precision. Координация: бэкенд-задача 2 (GB18030) гейтит их же задачу 5 и полигонный отбор сцен удобнее после неё, но полигон может стартовать параллельно (iconv руками уже валидирован).
|
||||
- Юр-пакет — в бэклоге до решения владельца (промт ресёрч-сессии подготовлю по запросу).
|
||||
- **Передача роли оркестратора (09.07 ночь, решение владельца — контекст сессии заполнился):** выдан [`ORCHESTRATOR_SESSION_PROMPT.md`](ORCHESTRATOR_SESSION_PROMPT.md) — преемник наследует зону docs/, методологию внешнего ревью (адверсариальные воркфлоу исполнением), право ратификации D-блоками и очередь: ревью research/15 по отчёту → приёмка полигона-erotica → промт бэкенд-пакета №3 (fix-лист D20.4 + D15.2 v3 + D3-цепочка) → промт приёмочной сессии Ф1. Параллельно выдан [`POLYGON_SESSION_PROMPT_EROTICA.md`](POLYGON_SESSION_PROMPT_EROTICA.md) (ja-книга владельца + 金瓶梅 + Fifty Shades → l2-erotica по трём парам, конвейер exp10, fix-лист D19.5, финализация сида gender=hidden) — закрывает D14.4. Промты пакетов №2 → архив.
|
||||
- **Бэкенд-пакет №2 принят и залендён (b51ac4c) после внешнего ревью** (5 ревьюеров исполнением/мутациями; smoke-деньги сверены по БД до микроцента; заглушка D19.6 подтверждённо убрана и мутационно защищена). **Ратифицирован D20**: спека D15.2 — направление принято, реализация после двух v3-правок (role в guard_hash; правило editor-каскада в dry-run-проекции); ответы §13 (пер-стадийная гранулярность wire-снапшота; `--accept-rebill[=usd]` c порогом min($0.50, 5%); Adult нейтрален + конфиг-линт); **приёмка Ф1 допустима на glm-5-редакторе; пилот требует боевой grok-4.3 → чистый xAI-ключ = блокер пилота, не приёмки**; fix-лист №3 (README v7, cheap-gates v2 против 3 FP, NUL-гард на не-UTF8 путях декода, minors). До полной приёмки на 蛊真人: финализация сида (gender=hidden — одно поле, полигон), заводка D3-цепочки, приёмочная сессия. ⚠ В дереве черновик `research/15-voice-and-state.md` (сессия «Голос и состояние» в полёте) — не трогать до её отчёта.
|
||||
- **Полигон-пакет №2 принят и залендён (3d183bc) после внешнего ревью** (4 ревьюера исполнением: mirror ACCEPT; explicit/seed/coord ACCEPT_WITH_FIXES — все фактические микро-дефекты доков исправлены оркестратором при лендинге). **Ратифицирован D19**: канал B v2 (Mistral-переводчик / grok-4.3 reasoning-ON эскалация / abliterated-скрининг / судьи Grok+Gemini), эхо-класс «reasoning-off + плотный CJK» обобщён, сид-развязки (перевод имён гу; «Гуюэ» слитно; 白凝冰 → gender=hidden), гигиена xAI пост-фактум + выделенный NSFW-ключ до пилота. Остаток D14.4: **только erotica-источник от владельца**. ⚠ Срочный пинг бэкенду в D19 п.6 (заглушка contested() в их незакоммиченном memseed.go).
|
||||
- **Промт ресёрч-сессии «Голос и состояние» выдан** (запрос владельца 09.07): [`VOICE_STATE_RESEARCH_SESSION_PROMPT.md`](VOICE_STATE_RESEARCH_SESSION_PROMPT.md) → `research/15-voice-and-state.md`. Мандат: голоса персонажей (voice exemplars vs дескрипторы — проверить клейм antipattern-дока; RP/game-loc прайор-арт; дешёвый детектор отклонения), scene/epistemic-state инъекция + скоуп Annotator Ф2, валидированный промптинг литперевода (формат/позиция инъекций, анти-галлюцинационные приёмы, «двухпроходность в одном вызове»), параметры запроса (temp-свип как ТЗ полигону), прайор-арт-проверка наших «уникальных» механизмов (спойлер-окна и др.), креатив с обязательной привязкой к слотам архитектуры. Пробы ≤$3 на SFW-чанках 蛊真人. Выход приземляется к Фазе 2 (Annotator, voice-профили) и в армы пилота. Параллелится с пакетами №2, ничего не блокирует.
|
||||
|
||||
### 2026-07-09 (ночь) — Приёмка research/15 «Голос и состояние» + D21 (оркестратор-преемник)
|
||||
|
||||
- **Роль принята** по `ORCHESTRATOR_SESSION_PROMPT.md`; онбординг по порядку промта; артефакты проб ресёрч-сессии продублированы из волатильного /tmp в `/home/ubuntu/books/gu-zhenren/research15-probes/` (вне git).
|
||||
- **Внешнее ревью research/15 выполнено** (9 агентов: 5 спот-чеков первоисточников — кандидаты из самоотчёта сессии, пересчёт проб из сырья, консистентность, red-team ратификации, аудит доков). Вердикт **ACCEPT_WITH_FIXES → залендён (5953b37)**: DelTA — CONFIRMED точно; RoleLLM/Voita/similarity/WMT25 — CONFIRMED_WITH_NUANCE (нюансы вписаны пометками *(ревью)*); P4/P1/P3/бюджет пересчитаны поштучно — сходятся; микро-дефекты счёта исправлены оркестратором (0/26→0/29; «~35%»→«30–67% по армам»; deepseek-эха rt 111/182/149; пятый судья gemini-2.5-flash; строгий маркер-пересчёт 0/4→2/4→3/4→4/4 — порядок армов устойчив).
|
||||
- **Ратифицирован D21** ([05-decisions-log](architecture/05-decisions-log.md)): voice-профиль (Ф2, с оговорками: заморозка per-job до D15.2, приоритет/кап бюджета инъекции, brightness — гипотеза-под-пилот, editor-слот не исключён, курация сида владельцем + кросс-семейный судья); address_pair = материализация журнала D7 (флаггер безусловно, инъекция — после пробы на трудных парах); reveal-окна (переобоснованы без 12-common); армы пилота с тирингом (минус двухпроходность/min_p); скоуп Annotator Ф2 с честным ресурсом голда; **анти-эхо wiring гейтится fidelity-хвостом P4 (35 пар) и только для deepseek-драфта**; клеймы уникальности сужены (скрининг ≠ FTO); exp08 v3 заказан.
|
||||
- **Аудит доков «что упустили»**: найдено и исправлено — CURRENT-STATE/README/CLAUDE.md отставали на два цикла (D18–D20, канал B v2, 7 ключей); quirks-строка «editor/translator ВСЕГДА reasoning:none» противоречила D19.1 (сужена до редактора); поручение D19.2 «обобщающая строка эхо-класса в quirks» не выполнено — включено в D21.9, чтобы не потерялось; backend/eval README-хвосты обновлены.
|
||||
- **Live-фактчек Gemini (вопрос владельца, 09.07):** /models-листинг живьём — 2.5-flash / 3.5-flash / 3.1-flash-lite все числятся; офиц. deprecations-страница — **вся 2.5-серия shutdown 16.10.2026** (замены 3.1-pro-preview / 3.5-flash / 3.1-flash-lite) → миграция судьи memory_eval оправдана вдвойне (флейки + EOL); интермиттентный 404 вендором НЕ документирован (наблюдение проб = аномалия, слаг в списке); `PROHIBITED_CONTENT` — неконфигурируемый фильтр-класс (safety_settings не влияют, в отличие от SAFETY). Вписано в quirks-календарь и erotica-промт.
|
||||
- **Erotica-промт обновлён ДО запуска** (уточнение владельца: сессия ещё не стартовала — пинги вшиты в файл, пересказ не нужен): Gemini-грабли судей (404-флейки gemini-2.5-flash при наличии в /models; ожившая `content_filter: PROHIBITED_CONTENT`-ветка на Gemini 3.x — логировать finish_reason первоклассно), пункт (е) в Task 3 — quirks-строка эхо-класса D19.2 + инверсия языкового констрейнта, и опциональная Задача 5 — fidelity-хвост P4 (35 выходов из `research15-probes/`, деблокирует анти-эхо wiring D21.6; приёмку сессии не гейтит).
|
||||
|
||||
### 2026-07-10 — Правило вендор-сверки аномалий (решение владельца, оркестратор)
|
||||
|
||||
Разбор Gemini-кейса: интерпретация 404-флейков ушла в промт без вендор-сверки, потому что урок «проверяй пробой» был записан только в направлении «клейм → проба», а сигнал ревью-аудитора «404-записи неверифицируемы» оркестратор не эскалировал. **Зафиксировано правило двух направлений** (шапка `00-provider-quirks.md` + гардрейл CLAUDE.md + правило №7 eval/README): wire-аномалия (флейки, 404 живой модели, новый finish_reason, игнор параметров) → СНАЧАЛА официальная дока вендора (deprecations/changelog/status) + свежий /models, ПОТОМ диагноз; интерпретацию без вендор-сверки в доки/промты не абсорбировать.
|
||||
|
||||
### 2026-07-10 — Видение фронта Ф3 + промт ресёрча «Ридер-IDE» (оркестратор)
|
||||
|
||||
- **Владелец детализировал план фронта** (VS Code-паттерн): дерево глав · две панели оригинал|перевод · панель команд/чат-редактирования · цветная статус-полоса с ползунком (зелёный/жёлтый/красный из детерминированных вердиктов). Открытые вопросы: якорение соответствия (не «страница в страницу»), UX редакторов, прайор-арт конкурентов.
|
||||
- **Оценка влияния на бэкенд (оркестратор):** read-model уже есть (chunk_status/паспорта/вердикты — D12 строил `--json` «для CI/IDE»); новая работа мала и read-only: персист/экспорт якорей чанков, `annotations.json`, сборка перевода с политикой красных чанков, возможно дешёвый флаггер абзацной парности. Контрактно-опасен один кусок — **human_override** (пост-правка человека против redrive/resume/TM — пересечение со snapshot-дисциплиной, думать вместе с D15.2). Веб-сервер/SSE НЕ строим (Ф3, D12-caution в силе). Кандидат-скоуп бэкенд-пакета №4 — после ресёрча.
|
||||
- **Выдан промт** [`READER_IDE_RESEARCH_SESSION_PROMPT.md`](READER_IDE_RESEARCH_SESSION_PROMPT.md) → `research/16-reader-ide-alignment.md`: прайор-арт HITL-редактуры (CAT/Mantra/фан-стек/PE-исследования), якорение (гипотеза «чанк/абзац, страницы виртуальны»), визуализация доверия, контракт бэкенд→фронт; $0-проба парности абзацев на сохранённых выходах. Живые LLM-вызовы: $0.
|
||||
|
||||
### 2026-07-10 — Приёмка пакетов «бэкенд №3» и «полигон-erotica» + D22 (оркестратор)
|
||||
|
||||
- **Внешнее ревью обоих пакетов** (8 ревьюеров, всё исполнением: go test/race + 11 мутаций в scratchpad-копии; exp11 пересчитан из сырья поштучно независимой репликой классификатора — 15/15 ячеек и все судейские числа сошлись; Fisher-статистика клеймов; цены по вендор-страницам). **Оба ACCEPT_WITH_FIXES → залендены (e1fcee4, 3551997), ратифицирован D22.**
|
||||
- **Топ-находки ревью:** (1) спека v3 на оси SourceLang/TargetLang была СЛАБЕЕ текущей защиты (исполненный stale-hit) → два обязательных v3.1-амендмента до реализации; (2) дублёра-судью 18+ ратифицировать нельзя (gpt-5-mini не мерен; D13.3-коллизия: grok-эскалированные 18+ чанки без померенного судьи) → проба-гейт; (3) register-клейм сужен до «архаика ломает МИТИГАЦИЮ reasoning-ON» (p=0.008 vs совр. zh; «регистр» = гипотеза до контрольных ячеек); (4) кодовая ветка content-filter полигона мертва на фактическом составном wire-формате (счёт отчёта верен через ручной finish_reason); (5) ja/en-fidelity сняты под zh-рамкой судейского промпта — индикатив; (6) полигон случайно стёр заголовок чужой записи в журнале — восстановлен; правило transient-прогонов в чужой зоне кодифицировано (D22.10).
|
||||
- **D3-текст исправлен** (`gemini-3.1-pro-preview`; голый слаг 404 — квирк 04.07, синк живых доков perl-grep'ом); цена Mistral $0.5/$1.5 закрыта тройной сходимостью; квирк-строки (register-оговорка, additive_total) дописаны.
|
||||
- **Промты выданы (по заданию владельца):** [`GPT_EXTERNAL_ASCENT_PROMPT.md`](GPT_EXTERNAL_ASCENT_PROMPT.md) (внешняя критика GPT-5.6, анти-якорный трёхфазный протокол) и [`BACKEND_SESSION_PROMPT_REFACTOR.md`](BACKEND_SESSION_PROMPT_REFACTOR.md) (пакет №4: код-хелс + golden-гард детерминизма). Закрытые промты №3/erotica — в архив.
|
||||
- **Приёмка Ф1 разблокирована полностью** (D22.11): следующий деливерабл оркестратора — промт приёмочной сессии.
|
||||
|
||||
### 2026-07-10 (вечер) — Приёмка рефакторинг-пакета №4 + D23 (оркестратор)
|
||||
|
||||
- **Внешнее ревью** (5 ревьюеров, всё исполнением): эквивалентность «форма, не поведение» доказана трижды независимо — новый golden на ЧИСТОМ HEAD-коде PASS байт-в-байт; чувствительность golden 5/5 мутаций; AST-дифф 36 деклараций (0 потеряно, 7 изменены только заявленно); CLI байт-идентичен исполнением двух бинарей; 9/9 мутаций инвариантов убиты; миграции/промпты/конфиги sha256-нетронуты. Вердикты ACCEPT ×2 + ACCEPT_WITH_FIXES ×3 → **залендён (296419c), ратифицирован D23** (golden-гард = инвариант №8; OpenReadOnly санкционирован с трейд-оффом reserved-хвоста; fix-лист мелочи — с реализационным пакетом D15.2).
|
||||
- Микро-фиксы оркестратора: diffstat +3317, фикстура 4гл/11 тел, оговорка про тест-непокрытые лог-фиксы; line-refs старого runner.go починены в 06/07/research-13 (историю не переписывал); backend/README техдолг-строка синкнута с D22.
|
||||
- **Промт приёмки Ф1 выдан** (`ACCEPTANCE_SESSION_PROMPT.md`); GPT-восхождение деблокировано (условие владельца «после рефакторинга» выполнено). Оба запуска + ридер-IDE ресёрч — параллельны и независимы.
|
||||
|
||||
## Бэкенд
|
||||
|
||||
### 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 30–44%); в транспорте донора скрытый захардкоженный 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).
|
||||
|
||||
**РЕШЕНО** (04.07) → ответ оркестратора ниже + ратифицировано в [05-decisions-log](architecture/05-decisions-log.md) (D1–D7); детали в 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 в Фазу 1–2; в Фазе 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-стриминг в Фазу 1–2 (без SSE-фронта), зафиксировано в плане; в Фазе 0 — длинные per-роль таймауты.
|
||||
> 5. **Р5 обновлён** сноской на токен-калибровку (×1.4–1.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`
|
||||
гоняет чанк 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](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_ttl↔cache_write под один TTL (5m);
|
||||
гонка `Runner.clients` (безопасна при последовательном проходе, мьютекс — к fan-out Фазы 1–2).
|
||||
|
||||
**Ключи: бэкенд заводится на ДВУХ ключах** (`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 отметил
|
||||
«уровень L0–L1 можно добавить отдельным конфигом для проверки стерильного канала». Можно ли прогнать
|
||||
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-недоучёта уточнена — до `MaxAttempts−1`, не «≤1»; честный фикс —
|
||||
idempotency-ключ, отложено). Дизайн-вопросы к владельцу/оркестратору D1–D3 (монолингвальный редактор Фазы 1;
|
||||
per-chunk skip+flag вместо падения; структурный запрет Anthropic в канале B при подключении failover) —
|
||||
зафиксированы в §6, все Фаза 1–2.
|
||||
|
||||
Следующее: Фаза 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 латентность штатная (5–8 с,
|
||||
без ×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 знаков (`(453−384)·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 (Ф1–2), инъекция глоссария (`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/archive/prompts/MEMORY_RESEARCH_SESSION_PROMPT.md`, финализирован); её выход — `architecture/06-memory-risk-registry.md` — вход, по которому ты фиксируешь схему store/глоссария. Шаги 1–3 (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 D8–D11](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.4–1.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 доп. вызов, не MaxAttempts−1) + консервативный 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 под шаги 6–7). Единый `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, перевода нет». Провалидировал **трассировкой** capability→wire (не грепом):
|
||||
|
||||
**Состояние детекта (после Вехи 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 эхать нечего.)
|
||||
|
||||
**Архитектурные ответы (Q1–Q3):**
|
||||
- **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](archive/prompts/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.4–1.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/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+001C–001F → `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).
|
||||
|
||||
### 2026-07-05 — Шаг 3a: настоящий чанкер + импорт txt/epub + ruby-захват
|
||||
|
||||
Снят плейсхолдер-чанкер: книга (D9 ja→ru ранобэ epub) гоняется end-to-end на настоящих границах. Всё зелёное `go build/vet/test -race`, `tmctl report` $0, живые LLM не звались (моки + $0-report). Три части + селфревью с фиксами.
|
||||
|
||||
**A. Настоящий сорс-чанкер (`chunker.go`).** `SplitChunks(source string)`→`SplitChunks(chapters []string)` (ingest уже режет главы). Паковка **по границам предложений/абзацев** в **коридор ~1–2k токенов** (`targetChunkTokens=1500`, **const покрыт `chunkerVersion`**, не конфиг — Р2=код; если станет конфигом — обязателен snapshot-fold как `coverageSnap`, §7d). Отдельный сорс-сплиттер `splitSourceSentences` (zh/ja/en): CJK zero-width `。!?`, **quote-depth** (терминатор внутри `「…!」と…。` — НЕ конец предложения, диалоговый кейс §3.7/D12-Q1), эллипсис `…`, абсорбция закрывающих скобок, guard аббревиатур/инициалов, **lossless-тайлинг** (конкатенация сегментов = исходный абзац, текст не теряется/не сдвигается). **Никогда не режет предложение**; абзац>цели → дробится по предложениям, предложение>цели → свой чанк. **ОТДЕЛЬН от coverage-`splitSentences`** (тот Python-locked по РУССКОМУ ВЫХОДУ; этот — по ИСХОДНИКУ, `chunkerVersion`-versioned). `chunkerVersion` бампнут `v2-ff-para-pack`→**`v3-sentence-pack`** (в snapshot → перечанкование = громкий `--resnapshot`).
|
||||
|
||||
**B. Импорт txt/epub (`ingest.go`, новый).** `Ingest(path)→*Document{Chapters []string, Ruby []RubyReading}`, диспетчер по расширению. **txt:** главы по `\f` (обратная совместимость example), `NormalizeSource` каждой. **epub — чисто stdlib** (CGO-free, без новых зависимостей): `archive/zip`→`container.xml`→OPF→**spine-порядок**→`encoding/xml` (`Strict=false`, `HTMLEntity`, `HTMLAutoClose`)→стрип тегов, скип `head/script/style`, block-теги→абзацные разрывы. Битый/пустой/чужой epub — **fail-loud, не паника** (нет container/opf/spine, dangling idref, не-zip). epub v1 = текст по spine, инлайн-разметка не сохраняется (осознанно, 02-mvp:25). Раннер: `os.ReadFile+NormalizeSource+SplitChunks` → `Ingest→SplitChunks(doc.Chapters)→persistRuby` (минимальный след, шов цикла цел; `ch.Text` в 3 местах не тронут).
|
||||
|
||||
**C. Ruby-захват + персист (`store/ruby.go`, миграция v4).** `<ruby>base<rt>reading</rt></ruby>` → **base в тело, reading захвачен, `<rp>` скобки-фолбэк дропнуты**, mono-ruby склеен. Персист в **v4 `ruby_readings(book_id, base, reading, first_chapter, occurrences)`** (PK `(book_id,base,reading)` — вариантные чтения = разные строки). **Идемпотентный upsert:** `persistRuby` агрегирует по всей книге раз на инжест → оба поля **REPLACE** (ре-инжест того же источника = те же строки, правка источника = сходится к правде). **НЕ инъектится в промпт** (§7d, память v2 + детерминизм-load-bearing) → не в snapshot/`request_hash`. Память v2 (шаг 4) потребит → глоссарий-лок имён (D9).
|
||||
|
||||
**Селфревью (адверсариальный Workflow: 5 дименсий → находки → независимая CONFIRMED/REFUTED-верификация с конкретным сценарием инпут→неверный-выход).** Сам нашёл до ревью 1 баг (dense-numbering, ниже). Ревью: 9 находок, 4 подтверждены (≥1 верификатором), **все 4 исправлены + регресс-тесты мутационно-проверены** (реверт → падает именно его тест):
|
||||
1. *[dense-numbering, до ревью]* ruby.Chapter брал spine-read-index, а `SplitChunks` нумерует главы **плотно** (пустые cover/nav скипаются) → `first_chapter` расходился с осью глав раннера (сдвиг `since_ch` памяти v2). Фикс: ingest нумерует тем же плотным правилом.
|
||||
2. *[segmentation]* паковка **суммировала per-unit `EstimateTokens`** (флор 16 на каждый абзац/предложение) → глава из коротких реплик дробилась в суб-500-симв. чанки, которые coverage-гейт молча скипает. Фикс: аддитивный подсчёт классов символов, флор-16 **один раз на весь чанк** (= `EstimateTokens` от склейки).
|
||||
3. *[epub]* `isXHTML` фолбэк на расширение только при ПУСТОМ media-type → глава с `application/xml`/`text/xml`/`…; charset=utf-8` молча терялась (реальные epub так мислейблят). Фикс: стрип параметров + фолбэк на расширение при ЛЮБОМ нераспознанном типе.
|
||||
4. *[epub]* форматирующий whitespace МЕЖДУ base-сегментами ruby (pretty-printed jukugo `<rb>`) тёк в base (мис-ключ глоссария) и в `ch.Text`. Фикс: whitespace-only CharData внутри ruby-base дропается.
|
||||
5. *[ruby-persist]* `first_chapter` был MIN-merge, `occurrences` — REPLACE (асимметрия): после правки источника, сдвигающей первое появление позже, `first_chapter` застревал на устаревшей ранней главе. Фикс: оба REPLACE (агрегат `persistRuby` — авторитетный full-book).
|
||||
|
||||
**Отклонено (обоснованно, оба верификатора REFUTED):** голый `<` в прозе валит весь epub — это **корректный fail-loud** на невалидном xhtml (альтернатива = тихая потеря главы, против инварианта); zip-bomb LimitReader — вне threat-model MVP (оператор-файл), в докстринг как future-hardening. Dense-numbering-находка ревью REFUTED — потому что уже был исправлен (верификаторы читали пофикшенный код).
|
||||
|
||||
**Границы/техдолг (не блокеры):** чанк <500 симв. молча выключает excision-гейт — **документированная граница §7b** (после фикса #2 случается только на реально-крошечной главе/хвосте); overlap-инъекция и ruby→глоссарий-лок отложены (§3, ждут msgs-поверхности памяти v2 — строим один раз); epub v1 не сохраняет инлайн-разметку; zip-bomb hardening — future. Форму `ruby_readings` согласовать с памятью v2 при шаге 4 (контракт: base→dst через reading, first_chapter→since_ch, occurrences=confidence). Тесты: чанкер (сегментация/паковка/детерминизм/аббревиатуры/quote-depth), ingest (txt/epub/spine-порядок/entity/ruby/битый-epub/dense-numbering/media-types), ruby-persist (идемпотентность+сходимость), e2e мульти-глава epub→чанки→мок-перевод→resume $0.
|
||||
|
||||
> **Внешнее ревью оркестратора Шага 3a (05.07): ПРИНЯТО, 0 живых блокеров, 7 подтверждённых находок (1 отсеяна).** Независимый воркфлоу — **агенты гоняли реальный код** (пробы в пакете), не утверждали. Money/детерминизм я подтвердил чтением сам. Тема: **тихая потеря главы/контента** — ровно тот класс, ради которого продукт есть. Ранг по важности:
|
||||
> 1. **[major] Тихая потеря главы на dangling spine idref** (ingest.go:168-201). idref-опечатка, орфанящая главу, молча скипается через `continue`; ошибки нет, пока читается хоть одна другая глава (`read>0`). **Противоречит СОБСТВЕННОМУ контракту** (PROGRESS:400 перечисляет dangling idref среди fail-loud; :402 инвариант «тихая потеря главы, против инварианта»). Прогон: manifest=[c1,c2,c3], spine=[c1,ghost,c3] → главы=[c1,c3], c2 потеряна, **и `since_ch` всего хвоста книги сдвинут** (ruby c3 штампуется chapter=2). Асимметрия: пропавший zip-файл фатален, пропавший manifest-id молчит. Фикс: собрать неразрешённые idref → loud-ошибка (как для zip-entry). **Топ-приоритет.**
|
||||
> 2. **[major] Тихая потеря главы на `application/xml`+`.xml`** (ingest.go:212-226). Тот же класс: контент-док, мислейбленный `application/xml`/`text/xml` С расширением `.xml`, промахивается мимо и type-switch, и extension-фолбэка (знает только .xhtml/.html/.htm) → молча скип + dense-renumber сдвигает `since_ch`. (Селфревью-фикс #3 закрыл ПУСТОЙ media-type, но не generic+`.xml`.) Фикс: при generic XML MIME распознавать `.xml` как контент. **Чинить вместе с #1.** → Системный фикс обоих: **spine-reconciliation** — сверять число контент-spine-items с реально прочитанными главами, расхождение = fail-loud.
|
||||
> 3. **[major] Size-зависимая порча invalid-UTF-8 → U+FFFD** (chunker.go:220). Oversize-путь round-trip `[]rune(paragraph)` заменяет невалидный байт на U+FFFD, а нормальный путь (короткий абзац, `strings.Join`) сохраняет сырые байты. Тот же source-байт цел в коротком абзаце, испорчен в длинном — нарушение losslessness + size-зависимая несогласованность; течёт в `{{text}}` и `request_hash`. Триггер: mostly-UTF-8 файл со стрей/обрезанными байтами (txt без charset-guard). Прогон: `abc\xe9def` короткий → байты целы, oversize → `abc\xef\xbf\xbddef`. Фикс: нормализовать invalid-UTF-8 ОДИН раз в `NormalizeSource` (fail-loud или документированная замена, покрыто `chunkerVersion`).
|
||||
> **Minor:**
|
||||
> 4. **[minor] ASCII/эллипсис-граница игнорирует quote-depth** (chunker.go:263-273). Depth-подсистема читается только в CJK-ветке; ASCII-ветка (`.!?…`) депт не проверяет → терминатор внутри трекнутой кавычки over-splits (запретное направление). Прогон: `「Stop. Now.」` → 2 сегмента (CJK-твин → 1). Проявляется в oversize-абзаце (режет диалог через границу чанка). Фикс: гейтить ASCII-границу на `depthHere==0` тоже (straight-quote англ. кейс не регрессит — проверено).
|
||||
> 5. **[minor] `<br>` внутри `<ruby>`** (ingest.go:326-327) не гардится `rubyDepth==0` (в отличие от block-тегов) → `\n` между base-глифами, обходит whitespace-collapse фикс #4; base и body расходятся. Whitespace-only, детерминизм цел. Фикс: гард `rubyDepth==0`.
|
||||
> 6. **[minor] ruby phantom-строки** (ruby.go, нет delete). Пара, УБРАННАЯ правкой источника, навсегда остаётся фантомом (upsert-only, нет delete-by-book). Латентно (память v2 не приземлена, capture-only, ноль текущего impact), но памяти v2 навесит name-lock на имя, которого в книге нет. **Фикс совмещается с шагом 4:** `DELETE FROM ruby_readings WHERE book_id=?` перед bulk-upsert (полная замена агрегата — тогда «сходится к правде» верно и для удалений). Связано с ruby-контрактом в `architecture/06`.
|
||||
> 7. **[minor] нет fuzz/property-теста tiling** (chunker_test.go). Единственный losslessness-тест — 6 ручных valid-UTF-8 инпутов; `Join(split(x))==x` над рандомом (вкл. invalid-UTF-8, вложенные/несбалансир. кавычки) поймал бы #3. Фикс: Go fuzz / testing/quick property + chunk-level losslessness (Σ не-пробел чанков == Σ не-пробел источника).
|
||||
> **Отсеяна: 1** (oversize-хвост <500 симв. — механизм подтверждён, но это документированная граница §7b, не баг; верификатор REFUTED).
|
||||
>
|
||||
> **Приоритет фикса:** #1+#2 (тихая потеря главы, системно через spine-reconciliation) → #3 (losslessness UTF-8) → #7 (fuzz-тест, поймал бы #3) → #4 (quote-depth ASCII) → #5/#6 (мелочь, #6 — с шагом 4). Ничего не горит на боевом (все триггеры — битый/мислейбленный epub или invalid-UTF-8), но #1/#2 — именно тот тихий-потери класс, где мы обязаны быть fail-loud.
|
||||
|
||||
### 2026-07-05 — Шаг 3a: закрытие 7 находок внешнего ревью (все, в приоритете оркестратора)
|
||||
|
||||
Все 7 закрыты в этой же сессии (автор с контекстом — дешевле, чем перезагружать свежую), каждый фикс **мутационно-проверен** (сломай — падает именно его тест) + три fuzz-таргета прогнаны ~200k+ рандом-инпутов live. Всё зелёное `go build/vet/test -race`, `tmctl report` $0. `chunkerVersion` бампнут `v3-sentence-pack`→**`v4-utf8-quotedepth`** (правки нормализации/сегментации/инжеста = осознанная инвалидация, `--resnapshot`).
|
||||
|
||||
**Major (тихая потеря главы/контента):**
|
||||
- **#1+#2 — spine-reconciliation (`ingest.go`).** Dangling spine idref (опечатка, орфанящая главу) больше НЕ скипается тихо: собираются все неразрешённые idref → **fail-loud** (как пропавший zip-entry) — иначе терялась глава И сдвигался `since_ch` всего хвоста. `isXHTML` расширен: generic-XML MIME (`application/xml`/`text/xml`) + расширение `.xml` распознаются как контент (мислейбленная `.xml`-глава больше не исчезает). Не-контент-ассеты в spine (image/css) по-прежнему легитимно скипаются.
|
||||
- **#3 — invalid-UTF-8 в `NormalizeSource` (`render.go`).** `strings.ToValidUTF8(…, U+FFFD)` ОДИН раз в нормализации → чанкер больше не расходится с собой ([]rune-путь по предложениям vs строковый по абзацам молча по-разному трактовали стрей-байт — size-зависимая порча в `{{text}}`/`request_hash`). `FuzzNormalizeSourceValidUTF8` гарантирует валидный UTF-8 на выходе.
|
||||
|
||||
**Minor:**
|
||||
- **#4 — quote-depth в ASCII-ветке (`chunker.go`).** ASCII/эллипсис-граница теперь тоже гейтится `depthHere==0` → `「Stop. Now.」` не over-splitится (straight-quote англ. не регрессит — untracked, depth 0).
|
||||
- **#5 — `<br>` внутри `<ruby>` (`ingest.go`)** гардится `rubyDepth==0` → `\n` больше не течёт между base-глифами.
|
||||
- **#6 — ruby phantom-строки (`ruby.go`/`persistRuby`).** `UpsertRubyReading`→**`ReplaceRubyReadings`** (DELETE-by-book + INSERT в одной tx): полная замена агрегата → пара, убранная правкой источника, исчезает, а не остаётся фантомом; `persistRuby` зовётся безусловно (пустой набор чистит книгу). «Сходится к правде» теперь верно и для удалений — контракт под память v2.
|
||||
- **#7 — fuzz/property tiling (`chunker_test.go`).** `FuzzSplitSourceSentencesTiles` (rune-lossless всегда, байт-точно на валидном UTF-8), `FuzzNormalizeSourceValidUTF8`, `FuzzSplitChunksPreservesContent` (Σ не-пробел чанков == Σ не-пробел источника) — поймали бы #3.
|
||||
|
||||
Отсеянная находка (oversize-хвост <500) осталась документированной границей §7b. Дальше — банк памяти v2 (шаг 4): реестр рисков `architecture/06` + ruby-контракт готовы (F1-materialization + горячий путь + post-check). Онбординг-промт след. сессии — `docs/BACKEND_SESSION_PROMPT_MEMORY.md`.
|
||||
|
||||
### 2026-07-05 — Шаг 4: банк памяти v2 (глоссарий + горячий путь + инъекция + F1 + post-check)
|
||||
|
||||
**Главный блокер качества (консистентность имён/терминов) реализован — веха A–E на seeded-глоссарии** (граница вехи подтверждена оркестратором §8: механизм на ручном+ruby-сиде; автопопуляция/адъюдикация/резюме/series-bible — отдельные вехи). Всё зелёное `go build/vet/test ./... -race` (125 тестов в pipeline), `tmctl report` $0. Ратифицированный порядок реестра `architecture/06` §Гейты соблюдён.
|
||||
|
||||
**A4 нормализация (`memnorm.go` + `data/trad2simp.txt`):** NFKC + trad→simp (вендорённая таблица, **версия = хеш содержимого таблицы** → дополнение = громкий `--resnapshot`, не тихая мини-карта) + катакана→хирагана + lower для источника; NFC + lower + ё→е + **схлопывание whitespace + унификация тире** для ru-цели. Симметрично ключ↔текст. Полный OpenCC оффлайн недоступен (нет данных на стенде) → курированный высокочастотный набор, все referenced/live-bug кейсы (爺→爷 и др.) покрыты и заассерчены; **завершение полного OpenCC — единственный отслеживаемый data-drop перед zh-приёмкой** (приёмочная книга D9 — ja→ru, где trad→simp не несущий).
|
||||
|
||||
**A схема (миграция v5):** `glossary` (D7 + `sense`/ось редакционного времени `glossary_revisions`/`UNIQUE(src,sense,window)`/`min_key_len`-запрет одиночных ключей/`allow_short`) + `glossary_aliases` (alias-граф) + `glossary_revisions` (B1 append-only) + `retrieval_state` (гейт #4). Idempotent full-replace (как ruby). `store/glossary.go`.
|
||||
|
||||
**B горячий путь (`memory.go`):** frozen `MemoryBank` из store-строк; **Aho-Corasick** по нормализованным ключам; запрет одиночных ключей (A3); longest-match containment; спойлер-hard-reject (C1, `since_ch/until_ch`, 0=безграничен); sticky scene-inertia (A5); токен-бюджет с логируемым вытеснением (F2); трёхсторонний disposition (A2 confirmed/ambiguous/reject). Детерминизм: 0 map-order в выводе, T1–T10 портированы (**не accept-регэкспы**), ловушки `retrieval_bench` 0/N, 200× determinism. **НЕ FTS5/вектор/эмбеддинги** (Р3).
|
||||
|
||||
**C инъекция (`render.go`):** `MessagesWithInjection` — код-собранный `system`-месседж глоссария МЕЖДУ стабильным префиксом (кэш-граница) и user-чанком (вариант «а» оркестратора, шаблон не трогаем); НЕ в `ch.Text` (coverage/`{{text}}` чисты); свёрнут в `request_hash`/`content_hash`.
|
||||
|
||||
**D закрыт F1 (`runner.go`):** `memoryVersion()` = content-hash замороженных **approved**-строк + версии норм/матч-алгоритмов (D8, не version-counter). Смена approved → громкий `--resnapshot` (e2e доказал `1e7b…`→`552c…`). id не хешируется; auto/draft вне хеша (их инъекция ловится `content_hash`).
|
||||
|
||||
**E post-check (`mempostcheck.go`) + E1-замер:** decl-осознанный (**наивный регэксп = 18–36% ложных, research/14**), whole-word матч по записанным `decl`-формам, sticky исключён, слепой post-replace запрещён (E2). **Флаггер по умолчанию** (миссы → `retrieval_state`, видны в `tmctl report`), **жёсткий гейт opt-in** (`gates.glossary.postcheck_gate`, как coverage — флип после валидации владельцем). **E1 измерен как Go-тест на реальном склонённом русском (канон Рогова): full-decl 0% ложных, base-only 67%** — эмпирическое подтверждение, что stored-decl надёжен ТОЛЬКО при полноте (ответ на развилку stored-decl-в-Go vs pymorphy-сайдкар Ф2: держим флаггером, сайдкар — валидированный фолбэк если реальные книги зашумят).
|
||||
|
||||
**Ruby→глоссарий (`memseed.go`):** классификатор `name_candidate`/`gloss_candidate`/`ambiguous` — **никогда не авто-лочит** (блайнд-лок = mistranslation; 強敵→とも неотличим от имени оффлайн → кандидат человеку). Ruby → auto-кандидаты (src=base, reading=мост к Поливанову B6, без dst), дедуп по base, скип manual-src.
|
||||
|
||||
**Интеграция + config:** `TranslateBook`: ingest→persistRuby→seedGlossary(replace+materialize)→snapshot→loop с sticky-окном (ресет на границе главы, пересобирается детерминированно на resume). `book.yaml: glossary_seed`. `tmctl report` — секция ПАМЯТЬ (агрегаты + пост-check миссы). Пост-check валидирует **финальный (редакторский) вывод** — то, что экспортируется, не только черновик.
|
||||
|
||||
**Агентское адверсариальное селфревью (§6, многоагентный Workflow):** 7 дименсий → 10 находок → независимая refute-by-default верификация с прогоном реального кода → **8 CONFIRMED (все воспроизведены), 2 REFUTED** (документированные размены: min-key-2 гомографы; редакторский drift — закрыт пост-check'ом финала). Все 8 исправлены + регресс-тесты **мутационно-проверены** (реверт → падает именно его тест): #1 empty-dst не матчится; #2/#8 whitespace-wrap/тире в post-check; #3 whole-word матч (дропнутый «Ван» не маскируется «караван»); #4 gate-mode `memoryVersion` сворачивает draft-decl (иначе resume молча флипал чанк); #5 дубль-alias в сиде дедупится (не крашит книгу); #6 спойлер-фильтр перед longest-match (спойлер-блокнутый длинный ключ не глотает валидное короткое имя); #7 floor-free токен-бюджет.
|
||||
|
||||
**Заложено/отложено (реестр §5, поля/место есть, реализация — Ф2/веха+):** Палладий/Поливанов B6 (reading как мост заложен), гейт фактичности резюме D1, эмбеддинг-слой A7/D2, морфо-гейт глагольного рода C3 (pymorphy-сайдкар), бэкап файла F4, автопопуляция/адъюдикация G1/F5, series-bible ты/вы-журнал, инъекция глоссария в редактор (dst-констрейнты) — fast-follow на той же поверхности. Ставка (селективная инъекция vs длинный контекст) гейтится in-house eval'ом пилота Ф2.5 (параллельно, не блокер). Правки только в коде `backend/` + этот журнал; `architecture/06`/`research/*` не трогались.
|
||||
|
||||
> **Внешнее ревью оркестратора банка памяти v2 (05.07): ПРИНЯТО, 0 живых блокеров на дефолтном конфиге, 6 подтверждённых (5 различных, 3 major; gate-находка независимо продублирована 2 линзами), 0 отсеяно — ВСЕ прогоном реального кода.** **Ядро держится:** F1 (материализация/resume/детерминизм — тихий расходящийся ре-пэй), нормализация A4 (симметрия ключ↔текст), спойлер C1, инъекц-поверхность (сам проверил) — **чисты, находок нет.** Все гэпы в одной зоне — **короткие/коллизионные ключи + гейт инвертирует свою же safety** — ровно те «hard traps», что `research/13` §«Честные слабые места» **предсказал непроверенными** (материализовались в коде, пойманы до продакшена).
|
||||
> **Major (закрыть до флипа гейта / до ja-kana в проде):**
|
||||
> 1. **[major, ONE-LINER, делать первым] PostcheckGate флагает по ОБЩЕМУ числу miss без фильтра disposition** (runner.go:744; продублировано 2 линзами). AMBIGUOUS-only miss (кандидат, который модель ВПРАВЕ отклонить) роняет чанк → `FinalText=""` → **выбрасывает корректный перевод**. Инвертирует A2/E1: модель, ПОСЛЕДОВАВШАЯ неверной инъекции, проходит; модель, ПРАВИЛЬНО отклонившая — наказана. Контракт (E1/B4/gate-list/config, 4 источника) скоупит гейт на approved. Фикс: считать в гейт только `Disp==confirmed` miss; ambiguous — только в retrieval-state (наблюдаемость). Опт-ин (дефолт=флаггер) → на дефолте не горит, но чинить ДО флипа.
|
||||
> 2. **[major] Source-side матч без word/script-границы + `dispositionFor` только по статусу** (memory.go:361, ac.matches). A2-ветка «коллизия поверхности → AMBIGUOUS» НЕ реализована; source-сторона без границы (асимметрия с target `containsWholeWord`, фикс селфревью #3). 2-символьный коллизионный ключ фичит **CONFIRMED внутри обычного слова** (リン→Рин в リンゴ/яблоко, AI→ИИ в RAID, 天下 в 天下无双). Post-check ИНВЕРТИРУЕТ: ложный confirmed-miss на КОРРЕКТНОМ выходе, и **не ловит FOLLOWED-отравление** (presence-only ловит только ДРОПнутый термин). Фикс: A2-даунгрейд коллизионных коротких ключей в AMBIGUOUS (не CONFIRMED); source-граница где есть смена скрипта/не-буква.
|
||||
> 3. **[major] `min_key_len` per-язык НЕ разведён** (memory.go:42 `defaultMinKeyLen=2` хардкод). Реестр A3 называет `glossary.min_key_len` per-язык как механизм — не разведён. Precision-1.0/MIN=2 мерена на zh-Han-ловушках, **не переносится на ja-kana** (#2 язык, 46-символьная слоговая → 2-kana ключи = частые подстроки). **NB: селфревью REFUTED это как «документированный размен» — но замер был zh-Han-scoped; для kana это реальный гэп.** Фикс: развести per-язык (в `memoryMatchVersion`+snapshot), kana ≥3, или 2-kana за `allow_short`.
|
||||
> **Minor (гарды от авторской описки, закрыть тихие дыры):**
|
||||
> 4. **[minor] 1 src → 2 dst с ПЕРЕСЕКАЮЩИМИСЯ спойлер-окнами** → две противоречивые авторитетные строки, **молча** (асимметрия: зеркальный B2 2src→1dst логируется громко). Фикс: overlap-проверка same (src,sense) → WARN/fail-loud.
|
||||
> 5. **[minor] approved-термин с пустым dst — молча инертен** (memseed.go:62; нет empty-dst-гарда на approved). Не матчится, не инъектится, 0 предупреждений → тихая потеря recall на всю книгу (ruby-auto с пустым dst легитимен, но там status=auto). Фикс: reject `status∈{approved,draft}` с пустым dst в loadGlossarySeed.
|
||||
> **Протокол включения гейта (важно):** твой E1-замер меряет false-flag **approved**-терминов на русской морфологии — но находки 1/2/3 вскрывают **другие оси** false-flag (ambiguous-decline, коллизионные короткие ключи), которые E1-протокол НЕ покрывает. Значит либо чинить 3 major ДО флипа (что убирает эти оси), либо расширить протокол валидации на них. Рекомендую первое.
|
||||
> **Приоритет:** #1 (one-liner, немедленно) → #2+#3 (коллизия/kana, до ja-kana или флипа гейта) → #4/#5 (дешёвые гарды). Ничего не блокирует дефолтный конфиг; всё блокирует флип гейта и прод ja-kana.
|
||||
|
||||
> **Внешнее ревью eval банка памяти v2 (05.07): ПРИНЯТО, 0 блокеров, 0 баг-находок.** Прогнал независимо на `aa00339` (сборка/тесты `-race` зелёные, E1 воспроизведён full-decl 0%/base-only 67%, трад-таблица 508 маппингов 爺→爷 на месте, изоляция инъекции/sticky-resume/F1/схема — проверил сам). 4 low/scope-заметки: (a) перекрывающиеся НЕвложенные ключи оба срабатывают (precision-сторона, обе поверхности реально есть); (b) редактор глоссарий не получает — защита только post-check финала (fast-follow: dst-констрейнт-инъекция в редактор — приоритет след. вехи); (c) gate-режим выкидывает весь чанк (opt-in, агрессивно — задокументировать до флипа); (d) 2-й system-месседж не на живом проводе (только моки — live-conformance кейс follow-up).
|
||||
|
||||
### 2026-07-05 — Шаг 4: закрытие внешних ревью (6 находок оркестратора + 4 low eval)
|
||||
|
||||
Все находки закрыты в этой же сессии, каждый фикс **мутационно-проверен** (реверт → падает именно его тест) + полный набор зелёный `go build/vet/test ./... -race`, `tmctl report` $0. Ядро (F1/нормализация/спойлер/поверхность) оба ревью подтвердили чистым — трогал только зону находок. `memoryMatchVersion` бампнут **v1→v2** (смена семантики матча/disposition = осознанная инвалидация → громкий `--resnapshot`).
|
||||
|
||||
**Major:**
|
||||
- **#1 — gate по CONFIRMED-only.** `PostcheckGate` и `n_postcheck_miss` считают только `Disp==confirmed` (`countConfirmedMisses`); AMBIGUOUS-miss (кандидат, который модель вправе отклонить) больше не роняет корректный перевод — только в `postcheck_detail` (A2-наблюдаемость). Инверсия контракта устранена.
|
||||
- **#2 — A2 коллизия→AMBIGUOUS.** `dispositionFor(entry, via)`: короткий чисто-фонетический ключ (kana/latin без Han-якоря, ≤3 знака) даунгрейдится в AMBIGUOUS даже у approved (мог сработать внутри чужого слова). `allow_short` — явный оверрайд автора. Sticky-кэрри сохраняет status-based (нет firing-ключа).
|
||||
- **#3 — min_key_len per-язык.** `minKeyLenFor`: Han-якорь → 2 (эмпирика zh-Han precision-1.0); чисто-фонетический → 3 (リン в リンゴ, ai в raid больше не фичат). **Kana=3 — консервативный дефолт до ja-kana precision-замера (расширение E1-протокола)** — свежие глаза показали, что zh-Han-замер MIN=2 на kana не переносится.
|
||||
- **Протокол флипа гейта:** оси false-flag из #1/#2/#3 (ambiguous-decline, коллизионные короткие ключи) E1-замер не покрывал → закрыты в коде, поэтому расширять протокол не нужно; флип гейта разблокирован после этих фиксов + owner-валидации precision.
|
||||
|
||||
**Minor:**
|
||||
- **#4 — overlap спойлер-окон fail-loud.** `loadGlossarySeed`: same (src,sense) с пересекающимися окнами и РАЗНЫМ dst → громкая ошибка (`windowsOverlap`; молчаливая противоречивая инъекция устранена).
|
||||
- **#5 — approved/draft пустой dst fail-loud.** Только `status=auto` (сырой кандидат, ruby-reading без dst) может быть пустым; approved/draft с пустым dst — ошибка (тихая потеря recall).
|
||||
|
||||
**eval low:** #a — тест `TestOverlappingNonNestedKeysBothFire` фиксирует принятое поведение (обе срабатывают); #b/#c/#d — задокументированы (редактор-инъекция = приоритет след. вехи; gate-агрессивность — `FlagGlossaryMiss` не-retryable/не-escalatable, флагает для человека; live-wire кейс — follow-up на `live_conformance`-харнесс). Регресс-тесты: per-lang-min+collision-disposition, gate-ignores-ambiguous (e2e), overlap-windows/empty-dst fail-loud, overlapping-non-nested. Оба вердикта: **ПРИНЯТО**; дефолтный конфиг чист, флип гейта и прод ja-kana разблокированы.
|
||||
|
||||
### 2026-07-05 — Шаг 4: глубокое адверсариальное ревью полной поверхности (44 агента)
|
||||
|
||||
По запросу владельца — многоагентный воркфлоу поверх `cc57c7b`: 8 finder-дименсий (нормализация / матчер+disposition / F1 / post-check / seed+ruby / store / инъекция+resume / мутационная-стойкость тестов), каждая не-минорная находка → 3 адверсариальных верификатора refute-by-default, подтверждение большинством ≥2/3. **24 кандидата → 2 подтверждённых major, 10 отсеяно (все 0/3–1/3), 12 миноров.** Отсев здоровый: напр. «sticky протаскивает collision-prone AMBIGUOUS в CONFIRMED» зарублен 0/3 верно — sticky не матчит исходник заново, а несёт установленный в сцене термин, collision-риск (срабатывание внутри длинного слова) к нему неприменим. Оба major — класс «тихо пусто», ровно та зона, ради которой банк существует; оба закрыты, каждый фикс **мутационно-проверен** (реверт → падает именно его тест), полный `-race` зелёный.
|
||||
|
||||
- **major #1 — default-ignorables в A4-нормализаторах (`memnorm.go`).** Zero-width (U+200B/200C/200D/2060/FEFF) и вариационные селекторы (U+FE0F, IVS) переживали NFKC/NFC → ключ `渡邊` молча не матчил `渡<ZWSP>邊` (частый артефакт EPUB/скрейпа CJK — «тихо пусто» переоткрыт), симметрично на target `<WJ>` внутри слова давал ложный post-check-miss. Фикс: `isIgnorableForMatch` (unicode.Cf + VS-диапазоны) дропает их в ОБОИХ нормализаторах; soft-hyphen U+00AD сохранён как fold→'-' (self-review #8 — порядок проверок гарантирует). `memoryNormAlgoVersion` бампнут **v1→v2** → громкий `--resnapshot`.
|
||||
- **major #2 — окружающие пробелы на keying-поверхностях (`memseed.go`).** `loadGlossarySeed` проверял пустоту через TrimSpace, но хранил СЫРОЕ значение: `src: " 強敵"` (approved, непустой dst) проходил валидацию, ключился как `" 強敵"` и НИКОГДА не матчил `強敵` — молча-инертный approved-термин на всю книгу; плюс trailing-space на `sense` маскировал same-sense-противоречие мимо обоих гардов (#4/#5). Фикс: тримминг `src`/`sense`/`dst`/`alias` до построения ключей и хранения (прощающий фикс, как alias-дедуп).
|
||||
|
||||
Отсев и 12 миноров оставлены как задокументированные размены/fast-follow (per-lang boundary-тесты post-check, sticky-decay coverage, apostrophe-fold — не гарят на дефолте). Вердикт сессии: **ПРИНЯТО**, шаг 4 закрыт.
|
||||
|
||||
### 2026-07-05 — D1: инъекция глоссария в редактор (монолингвальный редактор)
|
||||
|
||||
Первый fast-follow на поверхности памяти (eval-приоритет). Редактор теперь получает одобренный глоссарий как **target-констрейнты** и переведён в **монолингвальный** режим (decisions-log D1).
|
||||
- **`renderEditorConstraintBlock` (memory.go):** dst-only блок (без `src → dst` — редактор не видит исходник), **CONFIRMED-only** (AMBIGUOUS — кандидат, который переводчик вправе отклонить; форсить редактора переписывать черновик под непроверенное = порча корректного перевода, зеркалит gate-CONFIRMED-only #1), дедуп по dst, подмножество уже забюджеченного `memSel.injected` (свой токен-бюджет не нужен). Пустой → редактор без инъекции.
|
||||
- **runner.go:** `roleEditor`-ветка в стадийном цикле; `editorInjection` из того же `memSel` (детерминизм, resume-стабилен, входит в editor `request_hash` через msgs — не в snapshotID, memoryVersion уже там).
|
||||
- **`prompts/editor.md`:** убран `{{text}}` (D1: билингвальный редактор якорится к исходнику → кальки, главная translationese-болезнь; монолингвальный ещё и дешевле — исходник не сидит на входе каждого edit-вызова); мандат строки 7 согласован с инъекцией («приводи к каноническим формам глоссария», а не «не трогай»).
|
||||
|
||||
Тесты **мутационно-проверены** (реверт → падает именно его тест): `TestRenderEditorConstraintBlock` (CONFIRMED-only / dst-only / дедуп), обновлён `TestRunnerMemoryInjectionAndPostcheck` (editor получает dst-констрейнт-блок «КАНОНИЧЕСКИЕ ПЕРЕВОДЫ», не «src→dst ГЛОССАРИЙ»), `TestEditorPromptIsMonolingual` (guard: реальный editor.md без `{{text}}`). Полный `-race` зелёный, `tmctl report` $0.
|
||||
|
||||
**Заметка владельцу/оркестратору:** редактор стал **источник-слепым** (D1) — правит стиль/консистентность имён, но не ловит мистранслейты (это судья/эскалация, Фаза 2). Осознанный размен по контракту D1.
|
||||
|
||||
### 2026-07-05 — Консолидация конфига (drift из doc-аудита оркестратора)
|
||||
|
||||
6 конфиг-расхождений моей зоны (промт `BACKEND_SESSION_PROMPT_CONSOLIDATION`); центральный grok-разворот верифицирован веб-чеком xAI-доки + пробой eval, всё — адверсариальным селфревью (5 измерений, **0 находок**).
|
||||
- **grok-4.3 reasoning OFF даётся ЯВНО** (задачи 1-2, money-path). `models.yaml`: `control:none`→`control:effort/off_effort:none`. Дефолт grok = `low` (омиссия заставляет думать, additive-биллинг ~444 ток./правку) → `ReasoningNone` (off-by-omission) молча оставлял бы low; теперь при `reasoning:"off"` уходит плоский `reasoning_effort:"none"` (проба eval → 0 ток.). Комментарий `ReasoningNone` в `capability.go` разведён (DeepSeek ≠ grok — логика не тронута). **DeepSeek остаётся `ReasoningNone`** (omission намеренный: отключение thinking взводит эхо-мину; гвард `echoMineViolation` цел, xAI не echo-prone).
|
||||
- **Редактор glm-5 → grok-4.3** (задача 3, D1/D3; glm-5 был плейсхолдером) в edit-стадии C1/C2; select-стадия C2 (judge/glm-5, Gemini-слот Ф2) не тронута. Прод — только чистый xAI-ключ без data-sharing.
|
||||
- **Anthropic price-litter убран** из шапки `models.yaml` (з.4); **escalation-заглушки `[kimi-k2.6]` помечены интеримом** с названной D3-цепочкой (з.5 — заводка провайдеров gemini/openai + v4-pro/glm-5.1/gemini-3.1-pro отдельным шагом, гейтится ценами/ключами/cost-model); **бэкендовый `[НУЖНО РЕШЕНИЕ]`-маркер → РЕШЕНО** (з.6; оркестраторский блок не тронут).
|
||||
|
||||
Тесты: `capability_test` кейс assert'ит **присутствие** `reasoning_effort:"none"` (закрыл eval-указанную дыру — ложный «off шлёт nothing» тут падает); `TestBoevoyConfigGrokEditorExplicitNone` (config end-to-end: grok→explicit-none, не echo-flagged, edit=grok, c2-select=glm-5). Полный `-race` зелёный, `tmctl report` $0. Eval подтвердил: прогоны переигрывать не надо, баг был латентным (grok не был в стадии) — пойман до флипа.
|
||||
|
||||
### 2026-07-09 — Пакет фиксов стратегического ревью (D15/D16, промт `BACKEND_SESSION_PROMPT_REVIEW_FIXES`) ЗАВЕРШЁН
|
||||
|
||||
6 задач + 3 самопойманных дефекта + 7 находок финального адверсариального селфревью — всё исправлено, каждый фикс **мутационно-проверен**, `go build/vet/test ./... -race` зелёный, `tmctl report` $0.
|
||||
|
||||
- **Задача 1 (гигиена).** Лгущие resume-комментарии (`runner.go` coverageSnap, `coverage.go` coverageGateVersion) переписаны честно: `--resnapshot` переоплачивает ВСЮ книгу (snapshotID в RequestHash), никакого «free re-classify» — только внутри неизменного снапшота. Edit `prompt_version` `v0-draft`→`v1-monolingual` в обоих `pipeline-c*.yaml` (D1-уточнение №3: один лейбл на два SHA закрыт). `capability.go:3` ссылка 03→05.
|
||||
- **Задача 2 (D16 память).** 2a полисемия fail-loud (same-src/разные sense/dst/пересекающиеся окна, scoped к matchable src — `道` инертен, не регресс); 2b sticky **наследует** disposition (`activeIDs` → `map[string]injectionDisposition`, `Select`/`unionSticky`/`stickyWin` обновлены) — collision-prone AMBIGUOUS больше не апгрейдится в CONFIRMED мимо post-check/editor; 2c source word-boundary для **латиница/кириллица** (`suppressUnboundedPhonetic`); 2d ruby-reading→alias ручного термина (`attachRubyAliasesToManual`) + чек-лист ja-книги в `backend/README.md`. `memoryMatchVersion` v2→v3, `memoryNormAlgoVersion` v2→v3.
|
||||
- **⚠ [→ оркестратору] 2c: kana/Han НЕ boundary-checked (осознанное расхождение с буквой промта «латиница, кана»).** Обоснование: у каны нет сегментации (как у Han) — letter-boundary ломает частый кейс «имя+частица» (すずきは) и противоречит контракту «длинный кана-ключ = CONFIRMED». ≥4-кана-компаунд-precision отложен на kana-precision-замер полигона + токенизатор B6 (согласуется с D16 «minKeyLenPhonetic=3 — консервативный дефолт до замера»). Прошу ратифицировать это сужение.
|
||||
- **Задача 3 (`tmctl status`+`redrive`, D15.3).** `status.go`: read-only проекция (0 LLM, 0 replay) — book-manifest N/M (честный знаменатель через ре-чанкинг $0), unit-счёт done/in_progress/flagged/pending, паспорта глав (total/ok/flagged/skipped-stages, worst_flag, вердикт pass|attention|fail по exp07, $), деньги committed/reserved/ceiling%/projected, ETA от throughput (вторично), `--json` со стабильными enum. Колонка `escalated`/`escalation_model` в `chunk_status` (миграция v6) — телеметрия эскалации на flagged-resume (отложенная находка №6 Вехи 2.5). `redrive`: точечная переатака флагнутых (`--chapter/--chunk/--reason/--dry-run`), сброс терминального флага (`ResetChunkStages` удаляет chunk_status+чекпоинты сброшенных стадий, DispOK не тронут), свежий retry/escalation-бюджет, ре-ран durable-цикла. Продемонстрировано на example-книге ($0). **Деньги-семантика (задокументирована):** redrive НЕ возвращает committed (реально потраченное остаётся) → после redrive `committed ≥ SUM(checkpoints)`, безопасное направление; инвариант №1 в `README.md` дополнен исключением.
|
||||
- **Задача 4 (спека D15.2, документ).** `backend/docs/D15.2-content-addressed-resume-spec.md` (в моей зоне). Суть: `snapshotID` в ключе вызова смешивает wire- и вердикт-входы; расщепить (`wireSnapshotID`/`verdictSnapshotID`), ключ чекпоинта держать на wire-идентичности (по факту `msgsContentHash` + не-msgs wire-параметры), вердикт-версии убрать из ключа и re-classify-ить на resume бесплатно. Снимает онгоинг-мину D15 (append-термин re-bill-ит только реально затронутые чанки). **[→ оркестратору] на утверждение; при ок — свернуть в `03-implementation-notes.md`.**
|
||||
- **Задача 5 (reasoning-буфер, D13.6).** `EstimateUSD(+reasoningBudgetTokens)` резервирует reasoning как output для additive-провайдеров (xAI); fail-fast в `LoadPipeline`: reasoning-стадия на additive-провайдере без `reasoning_max_tokens` (+ escalate_to). Снимает D6.2-блок think-ON grok.
|
||||
- **Задача 6 (перепроверка отсевов).** Артефакты 44-агентки эфемерны (PROGRESS называет лишь sticky-отсев — уже закрыт 2b). Адверсариальные пробы с исполнением по границам доверия → **2 подтверждённых + пофикшено:** (F) shared-alias livelock (общий firing-key между разными approved-терминами → `approvedSharedKeyCollisions` fail-loud) и (A) apostrophe-fold тихо-пусто (типографский апостроф → ASCII в обоих нормализаторах). Пробы удалены, `git status backend/` чист.
|
||||
|
||||
**Самопойманный при селфревью (сверх задач):** 2d+Задача6 могли hard-блокировать легитимную ja-книгу с омофонами (鈴木/鈴樹 → оба すずき) — `attachRubyAliasesToManual` теперь graceful skip+log коллизии (best-effort, не hard-block), ручные коллизии сида по-прежнему fail-loud.
|
||||
|
||||
**Финальное адверсариальное селфревью — воркфлоу 5 дименсий × верификация (15 агентов, refute-by-default): 7 CONFIRMED / 3 refuted, все 7 исправлены:**
|
||||
1. [major] Полисемия same-src через общий matchable ALIAS проскакивала оба гарда D16.1 (sub-floor src `道` + общий алиас `大道`) → снял same-src-skip в `approvedSharedKeyCollisions` (ловит через общий alias-ключ; в обычном eligible-src кейсе `loadGlossarySeed` короткозамыкает — двойного репорта нет).
|
||||
2. [major] `glossary_miss` (post-check-гейт, флаг на уровне ЧАНКА после стадий) был невидим `status`/`redrive` (все stage-строки DispOK) → status показывал done/pass против exit-2 translate. Фикс: при gate ON чанк с post-check-промахом промотится в flagged/glossary_miss (не re-drivable — правка глоссария = --resnapshot).
|
||||
3. [major] additive-гейт ложно-негативил на `reasoning:""` (омиссия у grok = дефолт low = думает additive) → гейт и буфер теперь на `!= "off"` (не только low|med|high).
|
||||
4. [minor] `status` ловил только intra-store multi-snapshot, не store-vs-current-config → добавлен ConfigDrift (read-only расчёт текущего снапшота, сравнение).
|
||||
5. [minor] инвариант №1 README (`committed==SUM(checkpoints)`) — дополнен redrive-исключением.
|
||||
6. [minor] `unionSticky` newest-wins не тестировался → тест на конфликтующие disposition.
|
||||
7. [nit] `ProjectedBookUSD` пере-считывал при in-progress-спенде → база проекции = processedCost (только done+flagged).
|
||||
|
||||
**Техдолг / вопросы оркестратору:**
|
||||
- Спека D15.2 и сужение 2c (kana-boundary) — на ратификацию (см. выше).
|
||||
- **⚠ Рабочее дерево несёт незакоммиченные правки ПАРАЛЛЕЛЬНОЙ полигон-сессии** (`eval/`, `docs/experiments/`) — не мои, не трогал; коммитить пакет надо аккуратно (только `backend/` + `backend/docs/` + эта запись).
|
||||
- Известная граница `status`/`redrive`: glossary_miss re-деривится из неизменного глоссария → не re-drivable (фикс = правка глоссария = --resnapshot); status теперь честно это показывает.
|
||||
- F3 at-most-once — следующий D12-хвост (status/redrive закрыты).
|
||||
|
||||
### 2026-07-09 (пакет-2) — Приёмка-prep Ф1 на 蛊真人 (fix-лист ревью + GB18030 + дешёвые гейты + D15.2 v2 + smoke) ЗАВЕРШЕНА
|
||||
|
||||
Мандат `BACKEND_SESSION_PROMPT_ACCEPTANCE_PREP.md` (5 задач) выполнен. Порядок 1 → 2 → (3∥4) → 5. `go build/vet/test ./... -race` зелёные; фиксы mutation-verified; `tmctl report` $0. Смоук-книга/производные/сид — ВНЕ git (Р8; в журнал только метрики).
|
||||
|
||||
- **Задача 1 — fix-лист внешнего ревью.** (1a, **major, mutation-verified**) homophone first-wins в `attachRubyAliasesToManual`: контестед-ключ решается ДО аттача для ВСЕХ владельцев симметрично (было attach-then-block → алфавитно-первая база получала kana-alias CONFIRMED = A2 неверная авторитетная инъекция при ≥4 каны). Плюс window+dst-eligibility awareness (минор 1d — меньше ложных скипов). Ревертом ловится тест `TestRubyHomophoneNoWrongConfirmedInjection` (たかはし 4-каны материализуется → NEITHER инъектится). (1b) redrive-инвариант «DispOK НЕ сбрасывается» **закреплён мутационно** (draft=ok/edit=flagged → сброс ТОЛЬКО edit, draft резюмится за $0; мутант `filter→true` даёт Stages=[draft,edit] → тест валит) + тест НЕсовпадающего `--reason`. (1c) snapshot-чек ДО `ResetChunkStages` (**mutation-verified**: без гарда drift-редрайв удаляет флаг-строку → status pending/pass). (1d) minors: `--json` тоже exit 2 при флагах; hint для glossary_miss отдельный (redrive для него no-op → правка сида + --resnapshot); README миграции v1–v6; ETA — явная пометка D12-отступления (mean, не EWMA); overclaim-коммент `bookChunks` сужен (правка исходника без смены границ невидима status'у).
|
||||
- **Задача 2 — GB18030/кодировки в ingest.** `decodeSourceBytes`: лестница BOM(UTF-8/UTF-16) → валидный UTF-8 → **GB18030-проба (только zh-источник)** → fail-loud. Гарды: U+FFFD, NUL (UTF-16-без-BOM), Han-density+plausibleCJK (анти-мохибаке). `book.yaml encoding: auto|utf8|gb18030` + `source_lang`-скоуп пробы. Chapter-split добавлен для txt: **«第N章/节/回» авто-детект дом. юнита + separator-guard** (回 — мера, «第一回见面» НЕ дробит; сепаратор после юнита обязателен), preamble→гл.1. Новая внешняя зависимость: `golang.org/x/text/encoding/{simplifiedchinese,unicode}` (+ `japanese` в тестах) — первая за пределами go.sum-минимума (x/text уже был для NFC).
|
||||
- **Задача 3 — 4 дешёвых детерминированных гейта (наблюдаемость, НЕ гейты, на финальном тексте).** Линтер тире-диалогов (Розенталь §47–52: прямые кавычки/дефис/en-dash вместо «—», смешение стилей), ёфикатор (Пётр/Петр + brief-политика all-ё/all-е, ~30 омографов-исключений), блок-лист транслит-междометий (ара-ара/маа/нани/…; per-project allowlist), число-гейт 万/億 (CJK-парсер значений + диапазоны-множители на выходе; digit-coefficient-guard исключает идиомы 万一/千万/万物). `cheapGateVersion` свёрнут в snapshot (правка правил = --resnapshot, как classifierVersion); миграция store **v7** (`retrieval_state.n_style_flags`+`style_detail`); счётчики в `tmctl status`/`report`/паспорте главы + `StatusReport.StyleFlags`/`GlossaryMissFlagged`.
|
||||
- **Задача 4 — спека D15.2 v2** (`backend/docs/D15.2-content-addressed-resume-spec.md`, дизайн, реализация ОСТАЁТСЯ заблокированной до ратификации v2). Закрыты 3 дыры ревью: (a) fast-path-гард — отдельная колонка `guard_hash` (весь wire stage-план, суперсет текущего); (b) расщепление `memory_version` ОБЯЗАТЕЛЬНО — inject-часть в `content_hash` (из ключа вон), post-check+gate+decl → `verdictSnapshotID` (пересчёт на resume бесплатно); (c) замена loud-гейта согласия pre-flight dry-run «N чанков, ~$X» + порог `--accept-rebill`. Плюс: полный полевой маппинг снапшота (wire/verdict/dropped), судьба `chunk_status.snapshot_id`/status-ридеров, sequencing миграции (ДО первой онгоинг-книги; миграция v8), blast-radius append-а (sticky depth2 + F2 eviction + каскад на редактор). 3 открытых вопроса оркестратору в §13. **На утверждение.**
|
||||
- **Задача 5 — D18 smoke на 蛊真人.** (а) **ingest+chunker на реальном GB18030-файле (15.5 МБ):** 2283 главы (第N节-детект), **5088 чанков** (медиана 1445 ток., целевой 1500), ~6.52M токенов (медиана главы 2832), 0 ruby (zh), U+FFFD=0. (б) escalate_to заведён (интерим glm-5 фолбэком черновика). (в) **живой smoke 1 главы (draft=deepseek-v4-flash → edit=glm-5, escalate=glm-5; БЕЗ xAI — гигиена ключа D8 не подтверждена для книжного контента; потолок $0.10):** деньги сходятся **до цента** — Σ(request_log billed) == committed == **$0.031634**, reserved=$0; **живое эхо+эскалация** (chunk3 deepseek→cjk_artifact→glm-5 ok); **redrive на реальном флаге** (esc-off вариант дал cjk_artifact-флаг → redrive сбросил+перезапустил, DispOK за $0, 2-й проход: empty→удвоение бюджета→ok → флаг снят, 6/6 done); cheap gates фаернули на реальном выводе (万/億-разряды, дефис-диалоги). Полигонный сид (49 терминов, 35 approved/14 draft) грузится **чисто** через мой `loadGlossarySeed`+`approvedSharedKeyCollisions`+`materializeMemory` (схема совпадает). Суммарный живой спенд сессии ≈ $0.065.
|
||||
- **Финал — агентское адверсариальное селфревью** (6 дименсий × find→refute-by-default verify, 21 агент, ~835k ток.): **15 находок, 14 подтверждено, все закрыты** с регресс-тестами. Крит: Shift-JIS/EUC-JP молча принимался как GB18030-мохибаке (плаузибилити не отличает CJK-shaped мусор) → GB18030-проба скоупнута на zh (**mutation-verified**). Мажоры: seed-FILE drift не ловился redrive-гардом (read-only проекция) → гард **re-seed'ит** как TranslateBook, ловит ДО сброса (**mutation-verified**); UTF-16-без-BOM ASCII (interleaved NUL) → NUL-гард; chapter false-split на 回 → separator-guard; cheapgate ложные позитивы («уму»/«ара» убраны из блок-листа, 万-идиомы digit-guard, ё-омографы расширены, em-dash scene-break не считается диалогом); plausibleCJK получил прямой тест (была 0-покрытость). Миноры: StyleAllowlist сортируется до BriefHash, redrive-abort-сообщение переформулировано.
|
||||
|
||||
**Блокеры полной приёмки (владельцу/оркестратору):**
|
||||
1. **Сид готов, но политические развязки D10 открыты** (полигон §вопросы п.3): имена гу перевод-vs-транслит, 古月=Гуюэ vs Гу Юэ, пол 白凝冰 (draft/female — 他 в первых главах, gender=hidden трап). Гейтят финализацию сида.
|
||||
2. **Пороги гейтов:** coverage len_ratio zh-ru [2.2,4.2] (полигон подтвердил на срезе); postcheck-гейт держать OFF до замера precision на реальной инфлекции (E1); дешёвые стиль-гейты — наблюдаемость, порогов не имеют.
|
||||
3. **Канал 18+/violence:** полигон — grok thinking-off эхает 40% как ПЕРЕВОДЧИК (класс deepseek-эхо) → канал B: Mistral-переводчик + echo-гейт, ИЛИ grok reasoning-ON + reasoning-буфер (D6.2). xAI clean-key для боевого прогона (гигиена D8) — не подтверждён; smoke сознательно обошёл xAI.
|
||||
4. **D3-цепочка эскалации не заведена** (deepseek-v4-pro/glm-5.1/gemini — цены/ключи) — интерим glm-5; заводка — отдельный шаг.
|
||||
5. Полный прогон целой книги — **отдельная сессия** по готовности сида (п.1) + порогов (п.2) + канала (п.3).
|
||||
|
||||
**Вопросы оркестратору:** (1) **D15.2 v2 на ратификацию** (3 развязки в §13: пер-стадийная гранулярность wire-снапшота vs book-global; дефолт порога `rebill_consent_usd` + имя флага; слой для `Adult`). (2) Редактор smoke — glm-5 вместо ратифицированного grok-4.3 из-за xAI-гигиены: для боевой приёмки нужен ЧИСТЫЙ xAI-ключ ИЛИ решение держать glm/Mistral редактором. (3) ja-путь: Shift-JIS сознательно НЕ авто-детектится (fail-loud) — ja-книги должны быть UTF-8/epub (ja-приёмка отложена D18 — ок).
|
||||
|
||||
### 2026-07-10 (пакет-3) — D15.2 v3 + fix-лист D20.4 + заводка цепочки D3/канала B ЗАВЕРШЕНА
|
||||
|
||||
Все 4 задачи промта пакета №3 выполнены; `go build ./... && go vet ./... && go test ./... -race` зелёные; **ничего не коммичено** (внешнее ревью и лендинг — оркестратор). Зона правок — строго `backend/` (20 файлов, +860/−143 — счёт испр. оркестратором по diff; самоотчёт «19, +770/−132» был до финальных селфревью-тестов); чужие правки (eval/, docs/) не тронуты.
|
||||
|
||||
**Задача 1 — спека D15.2 → v3** (`backend/docs/D15.2-…`, дизайн; реализация ЗАБЛОКИРОВАНА до ратификации). Три правки D20.1: (а) `guard_hash` теперь несёт `role`+`stageName` (префикс `tm-guard-v2`) с КОНТРПРИМЕРОМ в §5 (флип роли editor↔translator на wire-нейтральном чанке → без role fast-path отдаёт stale-`ok`, хотя coverage-гейт сменил бы вердикт; показано, что без role формула НЕ суперсет); (б) §7 п.1-бис — аналитическое правило editor-каскада (любая стадия ниже re-bill-юнита чанка = re-bill; иначе консент занижен ~2× на смене temp/reasoning/model translator'а); (в) §4 доукомплектован (`style_check_version`, YoPolicy/StyleAllowlist → verdictSnapshotID; target-часть memoryNormVersion → postcheck; судьба `jobs.snapshot_id`; coverage-фолд только при enabled). Ответы D20.2 вписаны (Q1 пер-стадийность; Q2 `--accept-rebill[=usd]`+порог+fallback-флор, каскад ПЕРВЫМ; Q3 Adult нейтрален → adult-линт).
|
||||
|
||||
**Задача 2 — fix-лист D20.4** (каждый содержательный фикс mutation-verified — реверт валит именно его тест): README v7; cheap-gates **v2** (`cheapGateVersion` bump — громкий resnapshot; 3 FP закрыты: chevron-цитата в начале строки, 万-в-имени+постороннее число, перефраз+год; note про дефисные редупликации; честная recall-нота про `三万→300`); NUL-гард на GB18030/UTF-16 путях (был только UTF-8); `redrive --resnapshot` ПОДДЕРЖАН (main.go прокидывал флаг в `r.Resnapshot`); style-колонка в human-`status`; `report`/`status` через `NewReadOnlyRunner` без API-key-preflight.
|
||||
|
||||
**Задача 3 — цепочка D3 / канал B** (`models.yaml`+`pipeline-c1.yaml`; каждый слаг live-фактчекнут 2026-07-10 — `/models` И пробный вызов). Провайдеры gemini/openai/mistral + модели deepseek-v4-pro/glm-5.1/gemini-3.1-pro-preview/mistral-large-2512/gpt-5-mini с ценами (офиц., с URL) и capability; цепочки `default:[v4-pro,glm-5.1,gemini-3.1-pro-preview]` `adult:[grok-4.3]`; draft `escalate_to: deepseek-v4-pro`; permissive на xai/mistral/local (deepseek НЕ permissive — ToS D14.1); **adult-линт `CheckAdultChannel`** реализован (D20.2-Q3); xAI reasoning-буфер проверен runner-тестом (ceiling-trip). boevoy-config тесты (echo_mine) целы.
|
||||
|
||||
**⚠ Две существенные ЖИВЫЕ находки (правило двух направлений — вендор-сверка сделана):**
|
||||
1. **`gemini-3.1-pro` → HTTP 404 NOT_FOUND; callable слаг ТОЛЬКО `gemini-3.1-pro-preview`** (совпадает с quirks и преамбулой D8–D11 04.07 — 05-decisions-log:46, не D21; провенанс испр. оркестратором). В конфиг пошёл `-preview`. → **ПИНГ:** поправить D3-текст «gemini-3.1-pro» → `-preview` *(исполнено оркестратором при D22)*.
|
||||
2. **Gemini thinking-токены НЕ в `completion_tokens`** — проба: `completion=2, prompt=22, total=847` → 823 thinking ТОЛЬКО в `total_tokens`, поля `reasoning_tokens` НЕТ (у xAI есть). Офиц. прайс: «output includes thinking». Текущий адаптер биллил бы Gemini почти по нулю = слепота потолка. Фикс: провайдер `reasoning: additive_total` — settle деривит `thinking=total−prompt−completion`, биллит по output (тест+мутация). Резерв не слепнет (thinking ⊆ max_tokens ≥8000). Полный reasoning-буфер mandatory-thinking на РЕЗЕРВ-стороне — Ф2 (апекс-wiring; settle уже корректен).
|
||||
|
||||
**Задача 4 — D21.10:** (а) design-note резерва схемы банка v2 (voice_profile / address_pair = материализация ты/вы-журнала D7, один источник истины / reveal_ch + pre-post-алиасы) — комментарий в `store/migrate.go`, НЕ миграция/код; (б) wire-probe: **temperature молча игнорируется в thinking-канале DeepSeek** (temp=0.0 ×3 → 3 разных вывода) → draft `temperature:0.3` = no-op на deepseek-thinking (вендор-док подтверждён); temp остаётся в снапшоте (детерминизм), но wire-инертен — бэклог полигону (D21.9 wire-аудит); (в) промпты ролей НЕ тронуты (анти-эхо гейтится fidelity-хвостом P4).
|
||||
|
||||
**Финал — агентское адверсариальное селфревью** (workflow: 6 дименсий → верификация каждой находки, 22 агента; 16 находок → 3 CONFIRMED, 13 refuted). Все 3 закрыты; (2) и (3) mutation-verified, (1) — правка ТЕКСТА спеки, сверена с кодом *(уточнено оркестратором: сам инвариант «role в RequestHash» тест-незащищён — axis-тест в fix-лист D22)*: (1) **major** — §5 спеки клеймила «re-classify бесплатно», но `role` в `RequestHash` → флип роли = честный re-bill (промах чекпоинта), НЕ $0; текст исправлен (безопасность stale-`ok` serve сохранена, стоимость честна); (2) **minor** — `redrive --resnapshot` пропускал pre-reset `seedGlossary` → регресс защиты 1c (seed-коллизия падала бы ПОСЛЕ reset, стерев флаг-телеметрию); `seedGlossary` вынесен из-под `if !r.Resnapshot` (+ тест); (3) **minor** — NUL-гард на UTF-16 BOM-пути был без mutation-теста (+ тест).
|
||||
|
||||
**Вопросы оркестратору/владельцу:**
|
||||
1. **Поправить D3-текст:** апекс канала A = `gemini-3.1-pro-preview` (не `gemini-3.1-pro` — 404).
|
||||
2. **D15.2 v3 на ратификацию** (реализацию НЕ начинал — D20.1). §13-вопросы v2 закрыты D20.2.
|
||||
3. **Mistral `$0.5/$1.5`** (офиц. /pricing/api, Large 3) vs маркетинг-FAQ «$2/$6» (legacy Large 2) — совпадает с числом полигона (D19.5б)? при расхождении — сверка.
|
||||
4. **`escalation.budget_usd>0`** приёмочная сессия 蛊真人 обязана выставить, иначе echo-эскалация черновика (D18) не стреляет (документировано в pipeline-c1.yaml; дефолт 0 держит CI без gemini/mistral-ключей).
|
||||
5. gpt-5-mini жив пробой, но ушёл с текущей прайс-страницы (там gpt-5.4/5.5/5.6) — оставлен кандидатом D3, не в цепочке Ф1; пересмотр к Ф2.
|
||||
|
||||
### 2026-07-10 (пакет-4) — Код-хелс: golden-гард + план рефакторинга (инвентаризация)
|
||||
|
||||
**Golden-гард ПОСТРОЕН ДО любых правок** (`internal/pipeline/golden_test.go` + фикстура `testdata/golden/`): на статичной 3-главной книге (2-чанковая глава со sticky/инъекцией, спойлер-окно since_ch:2, вложенный ключ 紋章⊂竜の紋章, CJK-эхо→эскалация→ре-гейт ok, hard refusal→фолбэк тоже отказал→flag+skip+exit 2) пинится бит-в-бит: snapshotID+payload, request_hash ВСЕХ вызовов (вкл. эскалационный), wire-байты всех 9 тел запросов *(оркестратор: финальная фикстура после селфревью-расширения — 4 главы / 5 чанков / 11 тел)*, chunk_status/retrieval_state, финальные тексты — для свежего прогона И resume ($0, 0 вызовов). Обновление — только `TM_UPDATE_GOLDEN=1` на осознанной смене поведения. Попутно расширен read-view `RequestLogView` (chapter/chunk/model_requested/request_hash/degraded/err — колонки были в таблице, view их терял).
|
||||
|
||||
**Инвентаризация болей — исполнением, не чтением** (workflow 4 аудитора: smoke 6 сценариев на моках через реальный tmctl [hang/500-storm/429+Retry-After/refusal/ceiling/clean+resume], аудит цепочек ошибок, tmctl-тестируемость, скан дублей ≥3):
|
||||
- **Мажоры (все воспроизведены прогоном):** (1) эксклюзивный flock `store.Open` запирает read-only `status`/`report` на всё время живого прогона — оператор слеп ровно когда «висит 300-я глава» (lock нужен только ради recoverReservations, который read-пути не нужен); (2) ноль строк лога, пока вызов в полёте (до ~15 мин тишины при дефолтных таймаутах) — «висит» неотличимо от «работает» даже на debug; (3) backoff/Retry-After спит молча (доказан 8-с разрыв) и WARN «will retry» врёт на последней попытке; (4) store-ошибки всплывают голым SQLite-текстом без операции/книги/главы/чанка.
|
||||
- **Миноры:** терминальная ошибка стадии без ch/chunk/model; `report` не печатает ch/chunk/err; ceiling-ошибка «0.00$» при 0.001 и без committed/reserved; release-фейл резервации глотается на 2 из 3 путей; ReqInfo вешается на ctx ПОСЛЕ resume fast-path (resume-строки без book/role); status глотает ошибку drift-проекции («нет дрифта» по умолчанию); failover-причины только на debug.
|
||||
- **Что уже хорошо (не сломать):** все money-цепочки %w целы (errReserveCeiling/BilledDecodeError/CompletedWithFlags — верифицировано трассировкой), per-stage строки логов несут полную ось, exit-коды 0/1/2 держатся, retry/backoff — единственный движок.
|
||||
- **Дубли ≥3 (честный счёт):** 5×RequestLog-префикс атрибуции и 6×`_ = SetJobStatus` в runner.go; 5 изоморфных scan-циклов в store. Ниже порога (осознанно не трогать): snapshotID primary/escalate зеркало (2×, tripwire — третья модельная ось канала B), тела транспортов (2×, разные wire-форматы), tmctl RW/RO прологи (4×, но это контракт D20.4).
|
||||
|
||||
**План (по приоритету промта, каждый шаг: build+vet+test -race зелёные + golden бит-в-бит):** (1) декомпозиция runner.go 1383 → ~7 связных файлов одного пакета (snapshot/сид/цикл-книги/цикл-чанка/стадия/эскалация/resume; единственная правка формы — выделение эскалационного блока runStage в метод с точным сохранением семантики) — критерий: канал B/annotator/voice-инъекция добавляются файлом; (2) логирование по снятым болям (in-flight строка, честный backoff-лог, обёртки store-ошибок с осью, ceiling с деньгами, release-warn, ReqInfo hoist, run-start/run-end строки) + read-only store open без flock (query_only-пул, skip migrate/recover, fail-loud на отставшей схеме); (3) tmctl: parseInvocation/exitCode/parseDotEnv + fetch/render split (io.Writer, байт-в-байт) + юниты на контрактные инварианты (bad-flag→1 не 2, селектор redrive, парные кавычки dotenv); (4) хелперы дублей ≥3; (5) границы пакета pipeline — НЕ трогаю (оценка после (1): под-пакеты не дают очевидного выигрыша при высокой связности memory↔runner↔render; в «осознанно не тронуто»). Оценка диффа: перемещений ~1.3k строк, содержательных правок ~150–250 строк, новых тестов ~400–600 строк.
|
||||
|
||||
### 2026-07-10 (пакет-4, итог) — Код-хелс рефакторинг ЗАВЕРШЁН
|
||||
|
||||
Весь план исполнен; `go build ./... && go vet ./... && go test ./... -race` зелёные на каждом шаге; **golden бит-в-бит после каждого шага** (перегенерирован один раз ОСОЗНАННО в финале: расширение фикстуры по находке селфревью + починка verb'ов capture-формата — поведение пайплайна не менялось, эквивалентность против HEAD доказана исполнением, см. селфревью). **Ничего не коммичено** (лендинг — оркестратор). Дифф: 41 файл, +3317/−1712 (счёт испр. оркестратором; backend-only 40 файлов +3283; «+3295» снят до дописи журнала), из них новых тестов ровно 855 строк; чужие зоны не тронуты.
|
||||
|
||||
**Сделано (что удешевляет / какой класс багов исключает):**
|
||||
1. **runner.go 1383 → 8 файлов** (`runner` 168 сетап · `snapshot` 262 · `seeding` 118 · `bookrun` 179 · `chunkrun` 234 · `stagerun` 458 · `escalation` 107 · `resume` 70): перенос дословный (эквивалентность верифицирована AST-диффом селфревью), единственная правка формы — `maybeEscalate` из runStage (семантика `escalated`/ceiling-degrade/replay сохранена точно). Ф2-стройки садятся файлом: канал B → escalation.go, annotator/voice → chunkrun.go.
|
||||
2. **Логирование как продукт** (все фиксы — по болям, снятым ИСПОЛНЕНИЕМ, не воображаемым): in-flight строка `calling model` перед каждым вызовом (висящий провайдер ≠ мёртвый процесс; было до ~15 мин тишины); retryLoop — фактическое ожидание `retry_in` в WARN (Retry-After до 5 мин был невидим), «will retry» больше НЕ врёт на последней попытке, debug-строка старта попытки, deadline-exceeded аннотирован `timeouts.attempt_s`; `book run started/chapter started/book run finished` (N/M и деньги прогона на stderr); ~12 store-ошибок обёрнуты осью book/ch/chunk/stage; терминальная ошибка стадии несёт ch/chunk/model; ceiling-ошибка — committed/reserved/estimate и `%g` (было «0.00$» при потолке 0.001); release-фейлы больше не глотаются (Error); ReqInfo hoist — resume/re-pin строки получили book/role; status: провал drift-проекции — WARN, не тихое «дрифта нет»; failover: причина трипа Warn, платный local→cloud ретрай Info (D4.3).
|
||||
3. **`store.OpenReadOnly` + wiring в `NewReadOnlyRunner`** — главный операционный фикс: `tmctl status/report` работают ПРИ ЖИВОМ прогоне (раньше эксклюзивный flock запирал оператора ровно на время «висит 300-я глава»). Без flock/миграций/recoverReservations; соединения `query_only` (заблудшая запись падает громко); нет базы → fallback на создающий Open (перворазовый status как раньше); схема старше/новее бинаря → громкая ошибка. Тесты: конкурентный reader-при-writer, запрет записи, missing DB, schema mismatch, runner-уровень «status при живом прогоне».
|
||||
4. **tmctl 430 → тонкий main 158 + `invocation/render/dotenv`.go, 0 → 18 юнитов** на замороженные контракты: exit 2 эксклюзивен (bad flag → 1, обёрнутый сентинел → 2), порядок валидации, селектор redrive (класс регресса D20.4 «parsed but ignored»), парные кавычки dotenv, sentinel-возвраты рендеров, частичный вывод report при ошибке чтения. Рендеры — `fmt.Fprintf(w)` байт-в-байт; чтения store — коллбеками с ИСТОРИЧЕСКИМ interleaved-порядком.
|
||||
5. **Дубли ≥3:** `baseRequestLog` (5 копий префикса атрибуции — новый путь вызова не может забыть join-ключи телеметрии), `setJobStatus` c WARN (6 «тихих» `_ =` — рассинхрон jobs↔chunk_status теперь виден), store `queryAll` generic (5 изоморфных сканов; rows.Err()/материализация гарантированы для будущих read-models D15.2), `slices.Sorted(maps.Keys())` ×3.
|
||||
6. **Расширен `RequestLogView`** (ch/chunk/model_requested/request_hash/degraded/err — колонки БД, которые view терял) — нужен golden-гарду и report'у. **Осознанное изменение human-таблицы `report`**: колонки ch/chunk, модель с фолбэком «(req)», хвост degraded/err (пост-мортем упавшего вызова был пустой анонимной строкой; `--json`-схема status НЕ менялась). README: карта пакетов обновлена + пункт про golden-гард.
|
||||
|
||||
**Селфревью (агентское адверсариальное, 5 осей find → refute-by-default verify, 14 агентов ~880k ток.): 21 кандидат → 7 CONFIRMED (все закрыты), 1 downgraded→info, 1 refuted, 12 info.** Ключевое: (major) `slices.Sorted` на пустой карте даёт nil → `retrieval_state.injected_ids` персистился бы `"null"` вместо исторического `"[]"` на каждом чанке без точных матчей, а golden-фикстура была слепа к пустой выборке → нормализация в `[]` + **фикстура расширена 4-й главой без матчей** (пустая строка теперь запинена); (minor) printf-дефекты capture-формата golden (`err=%!q(MISSING)`, `%t` на int — err-колонка была НЕ запинена; vet не ловит через клоужер) → починены, golden перегенерирован; (minor) errTail резал UTF-8 по байту → срез по границе руны; (minor) report хоистил чтения до печати — частичный аудит при ошибке чтения молча пустел → возвращён interleaved-порядок коллбеками + тест; (minor) 7 устаревших указателей «(runner.go)» в комментариях + шапка runner.go описывала монолит → исправлены. Позитив ревью: AST-дифф всех 36 деклараций — дословно кроме документированных правок; **новый golden прогнан против HEAD-пайплайна — PASS** (прямое доказательство эквивалентности wire/вердиктов); truth-table retryLoop — эквивалентность по всем (attempt, retryable, ctx); money-цепочки и sentinel-цепочки целы.
|
||||
|
||||
**Осознанно не тронуто (причины):** под-пакеты pipeline (memory/gates/ingest делят неэкспортируемые типы с раннером; выигрыша нет — «не тащить через силу»); snapshotID primary/escalate зеркало 2× (< порога 3; **tripwire-коммент в snapshot.go**: извлечь foldModelWire ПЕРЕД третьей модельной осью канала B); тела транспортов openai/anthropic 2× (разные wire-форматы); tmctl RW/RO прологи 4× (контракт D20.4); persistRetrievalState marshal ×3 (недостижимый failure mode); F3 at-most-once, Escal.Chains, D15.2-реализация, store→ORM, перф — анти-скоуп промта.
|
||||
|
||||
**Честные оговорки / пинги оркестратору:**
|
||||
1. Пошаговая история «golden зелёный после каждого шага» не восстановима из git (пакет — одно рабочее дерево без промежуточных коммитов); компенсация — прогон финального golden против HEAD-кода селфревью (PASS) + полный сьют на каждом шаге. *(Оркестратор, та же оговорка шире: smoke-сценарии инвентаризации [hang/500-storm/429/ceiling] следов в диффе не оставили, а лог-фиксы retryLoop/errTail тест-ассертов не имеют — реверт errTail-фикса выживает сьют; в fix-лист D23.4.)*
|
||||
2. **Документированное поведенческое следствие OpenReadOnly:** после краха прогона `status` показывает хвост `reserved_usd` до следующей WRITE-команды (recovery-проход только у писателя; раньше read-команда сама обнуляла резервы — что и было причиной flock). Задокументировано в store.go.
|
||||
3. **Пинг (зона docs/):** `architecture/06-memory-risk-registry.md:71` цитирует «snapshotID (runner.go:145-163)» и `07-strategic-review` содержит runner.go-линки — после декомпозиции указатели ведут в сетап-файл; поправить при следующем касании доков (сами механизмы не менялись: snapshotID/memoryVersion → snapshot.go).
|
||||
4. Известная info-грань: OpenReadOnly на read-only ФС (бэкап-снапшот) не работает (WAL требует создать -shm) и создаёт -shm/-wal рядом с БД при чтении голой копии; хинт ошибки «пустая/битая база?» в этом кейсе вводит в заблуждение. Не регресс (старый путь падал раньше и жёстче); лечить — только формулировкой хинта, авто-`immutable=1` небезопасен при живом писателе.
|
||||
*(Закрытая хроника пакетов №0–№4 (04–10.07) перенесена в [archive/PROGRESS-2026-07-04-10.md](archive/PROGRESS-2026-07-04-10.md) — ревизия D31.)*
|
||||
|
||||
### 2026-07-11 (пакет-5) — Фиксы приёмки этапа A (D24.3/24.4) + тесты-оговорки + D23.4-хвосты ЗАВЕРШЕНО
|
||||
|
||||
|
|
@ -808,6 +132,8 @@ keep-alive (Ф1–2), инъекция глоссария (`selective`), пор
|
|||
## Полигон
|
||||
(секция параллельной сессии — записи добавлять сюда)
|
||||
|
||||
*(Закрытая хроника сессий 1–3, 18+ пакетов и exp10/11 (04–10.07) — в [archive/PROGRESS-2026-07-04-10.md](archive/PROGRESS-2026-07-04-10.md), D31.)*
|
||||
|
||||
### 2026-07-11 — exp12 «диагностика качества 25 глав» (D26, приоритет №1) — армы+судьи+root-cause СДЕЛАНЫ, чтение владельца ждём
|
||||
|
||||
Мандат `POLYGON_QUALITY_DIAG_SESSION_PROMPT.md` + аддендум оркестратора (D27: единый xAI-ключ, grok-армы без ограничений; backend/ — живая сессия №5, ничего там не гонял/не читал WIP; пакеты чтения → `diag/reading/`). **Ничего не закоммичено.** Отчёт: `docs/experiments/12-quality-diagnosis.md`. Артефакты/тексты — `/home/ubuntu/books/gu-zhenren/diag/` (ВНЕ git). Скрипты `eval/exp12_*.py`. **Потрачено ≈$2.22 из капа $5** (армы $0.78 / судьи $1.31 / демо $0.13; 0 ошибок).
|
||||
|
|
@ -829,278 +155,17 @@ keep-alive (Ф1–2), инъекция глоссария (`selective`), пор
|
|||
|
||||
**Ждём:** (1) **Пере-курация глоссария** — утверждение владельцем терминов (§4.2 + флагман-таблицы: врата→апертура, 真元, 本命蛊→жизненный гу, 长生→бессмертие, 族长/家老; спорное — Первопредок/Жэнь Цзу, культивация/совершенствование — за владельцем) → засид GAP + переголос lock → resnapshot. (2) **Оркестратору:** ратификация флипа D1 (моно→билингв) + бриф вёрстки + **новые задачи**: output-санитайзер (класс «мгновенной нечитаемости»), сноски-на-аллюзии, и — по сигналу флагманов «издательский уровень требует ядра» — поднять приоритет выбора базового переводчика/пилота Ф2.5; фиксация owner-proposal «автолукап терминов = Ф3». Дефолт сам не трогаю. (3) Полигон №4 (сид мн.ч.) — второй приоритет, не начат.
|
||||
|
||||
### 2026-07-10 — Сессия «erotica-срез 18+ + fix-лист + финализация сида» (закрытие D14.4) ЗАВЕРШЕНА
|
||||
|
||||
Мандат `POLYGON_SESSION_PROMPT_EROTICA.md`. Всё с провенансом (model id, UTC, usage, ПОЛНЫЕ сырые выходы; results не перезаписаны). Книги/корпуса — ВНЕ git (Р8). **18+ мандат владельца исполнен; жёсткая линия level-3 (минори) удержана.**
|
||||
|
||||
- **Task 4 — сид 蛊真人 финализирован (D19.3).** `白凝冰` → `gender: hidden` + `status: approved` + `until_ch: 0` (note: выставить главу раскрытия; механизм D5.1). Валидация **$0 бэкенд-путём** (transient `go test` на боевом loader `loadGlossarySeed` + `approvedSharedKeyCollisions` → **49 записей чисто, hidden/approved, 0 коллизий**; временный тест удалён, backend/ дерево чистое). Снят блокер №1 полной приёмки.
|
||||
- **Task 3 — fix-лист D19.5/D20 закрыт (a–f).** (a) `mistral_fidelity.py` — агрегация MEAN при n=2 (было `sorted[n//2]`=max; поле `fidelity_mean`), +404-retry для gemini-флейков. (b) **Цена Mistral сверена офиц.:** `mistral-large-2512` (Large 3) = **$0.50/$1.50** (OpenRouter-зеркало + аггрегаторы; 75% срез от Large 2); $2/$6 = LEGACY Large 2 (2411, ретайр 31.05.2026), офиц. FAQ mistral.ai показывает УСТАРЕВШИЙ generic-пример — 4× расхождение генерационное, не ошибка. (c) provenance-нота в `ahq_final.json` meta (pre-Task-1 mirror; для zh no-op). (d) эхо-детектор line-start FP на прозе с «Глоссарий» — задокументирован (консервативный, видимый флаг). (e) `glossary_line_tokens` синк с Go: 々U+3005/〇U+3007→CJK, halfwidth-кана FF66–FF9D→CJK, ゛゜U+309B/C→other (каждый code-point сверен scratch-`unicode.In`; Py↔Go parity=5/5). (f) **строка эхо-класса в `00-provider-quirks.md`** (поручение D19.2, не выполнялось): «reasoning-off + плотный CJK = зона эха — свойство КЛАССА, не квирк вендора» + P4-инверсия языкового констрейнта. Плюс миграция судьи `providers.json gemini`: 2.5-flash (EOL 16.10.2026 + 404-флейк, +баг двойного `extra_body`) → **gemini-3.1-flash-lite** (live-смоук 07-10: finish=stop; 3.5-flash даёт 503 — не берём). Логирование `finish_reason` сделано первоклассным в `refusal_bench.call_provider` (+распознавание Gemini `PROHIBITED_CONTENT`/`SAFETY` как content-filter — ожившая ветка D2.4).
|
||||
- **Task 1+2 — эротика-рука прогнана на ВСЕХ ТРЁХ парах / трёх регистрах** (полный отчёт → **[experiments/11-erotica-benchmark.md](experiments/11-erotica-benchmark.md)**). **zh: 金瓶梅** (PD, ctext упр-слой) — 6 adult-only (классика); аудит исключил 3 главы (回27/51/52) за 春梅/书童. **ja: 異世界魔術師** (novel18, 洗脳-гарем) — **первично отклонил всю книгу (слишком консервативно), по решению владельца пересобрал ADULT-ONLY per-fragment**: 6 фрагментов (совр. вебновелла), L3-сцены (第8話 幼い顔, 第35話 幼女-аукцион, 第32話) ИСКЛЮЧЕНЫ, участники возрастно-верифицированы. **en: «Fifty Shades» кн.1** (владелец положил epub→txt) — 6 фрагментов Ana(21)×Christian(27), контракт-глава ch11 + Elena-бэкстори про 15-летнего ИСКЛЮЧЕНЫ. 0 hard-minor-маркеров ни в одном фрагменте (18 всего). Армы (=violence exp10): Mistral, grok reason-ON/OFF, DeepSeek(контроль), local abliterated 8b; судьи Grok+Gemini на Mistral-переводах.
|
||||
|
||||
**Три главных вывода (18/18 фрагментов):**
|
||||
1. **Mistral держит эротику чисто на ВСЕХ трёх (6/6 zh + 6/6 ja + 6/6 en)** — дефолт-переводчик канала B (D19) валиден на классике, совр. вебновелле И совр. романе. DeepSeek тоже 6/6×3 (переводит explicit несмотря на ToS; исключён юридически D14.1).
|
||||
2. **0 content_refusal у ВСЕХ переводчиков, все три (0/18).** Единственный сбой — **эхо, не цензура**, гонится **РЕГИСТРОМ ВХОДА**: плотный классический Хань → grok reason-ON эхает **4/6** (`reasoning_tokens`=349–847, ON подтверждён!); совр. японская → grok-ON **1/6**; **английский → 0/6 даже reasoning-OFF**. → **уточнение к D19.1**: reasoning-ON снимает эхо на совр./не-CJK, НЕ на плотном классическом Хане. *(пинг оркестратору: register-оговорка.)*
|
||||
3. **Судья 18+: Grok надёжен (0 отказов на всех 3 + насилии), Gemini отказывает по ГРАДИЕНТУ графичности** — насилие 0/10 → en 1/6 → zh-классика 2/6 → **ja 5/6** `PROHIBITED_CONTENT` (неконфигурируемо, все подтверждены `finish_reason`). → 18+-судья эротики = **Grok**; Gemini-дублёр непригоден (native API не спасёт). Дублёр — не-Google (gpt-5-mini) на пилоте *(оркестратор: дублёр НЕ ратифицирован — на эротике не мерен, гейтится пробой на лежащем материале; плюс D13.3-коллизия — для grok-эскалированных 18+ чанков померенного судьи нет вовсе; D22)*. **Сужает** exp10-вывод «Gemini-судья 18+ ок» — держится только на насилии.
|
||||
|
||||
**⛳ Вопросы/пинги владельцу и оркестратору:**
|
||||
1. **Пинг бэкенду/оркестратору (архитектура):** имеет смысл предусмотреть опциональный пре-перевод гейт, способный остановить или отвести чанк ДО эскалации. Сейчас такого нет — ingest и пост-гейты (D12: echo/excision/coverage) ловят только сбой перевода, а эскалация канала B обходит отказ провайдера вплоть до пермиссивной local-модели. Механизм — backend, включение по конфигу; детали — решение оркестратора.
|
||||
2. **D19.1 register-оговорка** (см. вывод 2) и **exp10-сужение** (вывод 3) — оркестратору на ратификацию/синк D-лога.
|
||||
3. Task 5 (fidelity-хвост P4, опциональный) НЕ выполнен — бюджет сессии ушёл на 3-парную эротику + ja-пересбор + en; материал (71 echo-проба) на месте, готов к прогону следующей сессией. (en-пара закрыта — владелец положил Fifty Shades.)
|
||||
|
||||
> **[Правки ревью — оркестратор, 10.07, D22]** (1) «results не перезаписаны» неточно: два 429-рекорда mistral/en-05,06 вычищены из jsonl перед перегоном (сам перегон раскрыт честно, но append-only провенанс нарушен — правило в D22); (2) «цена сверена офиц.» — источники сессии: зеркало провайдера + агрегаторы; ревью добрало вендор-страницу /pricing/api — $0.5/$1.5 подтверждены, вопрос закрыт; (3) «+распознавание PROHIBITED_CONTENT» — распознавание в отчёте РУЧНОЕ по finish_reason; кодовая ветка `refusal_bench.py:198` НЕ матчит фактический составной wire-формат `'content_filter: PROHIBITED_CONTENT'` (все 8 отказов легли в behaviour='empty' — major, fix-лист D22); (4) ja/en-fidelity судились промптом с жёсткой zh-рамкой («исходный фрагмент — китайский») — числа индикативны, при переиспользовании переснять; grok-судья шёл `reasoning_effort:none` (в отчёте не декларировано); (5) token-bucket синк внёс НОВОЕ расхождение с Go: U+FF70 (halfwidth ー) в Python — кана, в Go — нет (консервативное направление, fix-лист).
|
||||
|
||||
### 2026-07-09 (пакет-2) — Сессия «18+ рука + синк зеркала + сид-глоссарий» (D14.4/D18) ЗАВЕРШЕНА *(заголовок восстановлен оркестратором — стёрт при вставке записи 10.07)*
|
||||
|
||||
Мандат `POLYGON_SESSION_PROMPT_EXPLICIT_AND_MIRROR.md` (5 задач) выполнен. Порядок 1 → (2∥3) → 4 → 5. Всё с провенансом (model id, UTC, usage, полные сырые выходы; results не перезаписаны). Книга/сид/корпус — ВНЕ git (Р8).
|
||||
|
||||
- **Task 1 — зеркало ↔ Go синхронно (fix-лист ревью, гейтит пилот).** Дозеркалено в `memory_eval.py`/`declmetric.py`: (1a) `suppressUnboundedPhonetic` D16.3 — source word-boundary для Latin/Cyrillic (rose⊄roseanne, кросс-скрипт=валидная граница, кана/Han НЕ проверяются) + self-test мирроры Go-тестов `TestSourcePhoneticWordBoundary`/`TestKanaNotSourceBoundaryChecked`; (1b) апостроф-фолд `‘’ʼ'→'` с ОБЕИХ сторон (норм-src + `declmetric.normalize_target`) + parity-asserts (критично для en→ru руки: д'Артаньян/O'Brien); (1c) эхо-детектор ловит хвостовой/встроенный глоссарий-эхо (не только лидирующую преамбулу); (1d) байт-синк заголовка инъекции с Go, ts(UTC) в refusal-записи, trad2simp dedup-guard (508→500, 8 консистентных дублей — fail-loud на несогласованный + md5-parity self-test с Go-embed), карантин-маркер в `memory_eval_indicative.json`, exp09 §6-bis «precision trap-set-относительная» пометка, докстринг-cleanup. **Адверсариальное parity-ревью (differential-тест: Go x/text vs Python по 1.1M code points + 20328 строк, оба Unicode 15.0):** NFKC/NFC/apos/dash — байт-в-байт; 3 находки пофикшены (İ→'i' — единственный `.lower()`≠Go рун; эхо-детектор ужат чтобы не резать легит-прозу с «глоссарий» в середине; `glossaryLineTokens` ー・ исключены из cjk-корзины по Go), 2 латентных (kana/hangul range-аппрокс, C0-space) задокументированы как нереачабельные для zh-книги. `--self-test`/declmetric parity/kana_precision — зелёные; Go-эталон-тесты зелёные.
|
||||
- **Task 2 — Mistral fidelity ПЕРЕСНЯТ с полным персистом (D14.2 §3).** `eval/mistral_fidelity.py`: 5 PD-фрагментов (2 zh+2 ja+1 en), 2 кросс-семейных судьи (gemini-2.5-flash+gpt-5-mini, D13.3), медиана. **zh 93.0 / ja 95.0 / en 93.0 → OVERALL ≈93.8** (n=5; *исправлено оркестратором: «95.4» был артефактом агрегации — sorted[n//2] при 2 судьях = max, см. exp02*), все `ok`, эхо нет. Сырьё+судейские JSON+usage — `data/mistral_fidelity/raw_20260709T165023Z/`; exp02 §Mistral обновлён. **D14.2-fidelity готов к финализации.**
|
||||
- **Task 3 — 18+ рука закрыта на violence/dark (последний critical, exp10).** Корпус: 10 zh violence/gore фрагментов 蛊真人 (проаудированы отд. агентом: связность+жестокость+**скрин уровня-3=чисто**; аудит поймал баг экстракции global-节-индекс vs номер главы). **3b refusal/excision (0 отказов у ВСЕХ):** grok-4.3 reasoning-OFF **эхает 40%** (4/10, тот же класс, что deepseek-эхо) → контроль reasoning-ON = **10/10 чисто** (причина — reasoning-off); Mistral **10/10 чисто**; DeepSeek(контроль) 9 ok/1 эхо (переводит насилие без отказа, D14.1); abliterated-8b 8 ok/2 excision (n=10; *исправлено оркестратором по jsonl*), 30b чисто но слишком медленно на 8GB. **3c судьи:** Grok-4.3 **10/10 judged, 0 отказов** (fidelity 62–92); **Gemini-3.1-pro НЕ отказывается судить explicit** под издательской рамкой (10/10, 0 отказов) → **замена судьи 18+ НЕ нужна** (открытый вопрос D14.4 закрыт). Провенанс: `data/refusal_results_explicit/`, `data/explicit_judges/raw_*`. Полный отчёт → **[experiments/10-explicit-benchmark.md](experiments/10-explicit-benchmark.md)**.
|
||||
- **Task 4 — сид-глоссарий 蛊真人 передан (D18/D10).** 49 терминов (35 approved/14 draft) по 节1–25, схема = `memseed.go seedTerm` (согласована), dst по Палладию, decl заполнены, spoiler-окна (血颅蛊 since_ch193 и др.). Валидирован (парс + Go-guard проверки чисто). Файл `/home/ubuntu/books/gu-zhenren/guzhenren-seed.yaml` (ВНЕ git). **Бэкенду:** сид готов для задачи-5 приёмки; схема совпадает.
|
||||
- **Task 5 — терсный precision закрыт (вебновелл-режим exp07).** `eval/dialogue_precision.py`: детектор ловит встроенную атрибуцию (`方源道:“…”`), сегментация по строкам. 24 терсных чанка 蛊真人 (density 1.0) + 10 контроль; grok-перевод + gemini completeness-судья. **Ложных excision_suspect = 0/24 (0%)** (min len_ratio 2.69≫2.2, min sent_cov 0.75). Recall-оговорка: судья пометил 8/24 с мелкими пропусками, гейт не флагнул → precision-safe, recall-слаб для мелких (нижняя граница, Ф2). exp07 обновлён.
|
||||
|
||||
**⛳ Вопросы владельцу/оркестратору:**
|
||||
1. **🔴 Канал B: grok-4.3 «thinking-OFF» эхает 40% как переводчик** (D3/D6.2 конфликт). Развязка — за оркестратором/бэкендом: (а) канал B на grok reasoning-ON + reasoning-буфер `EstimateUSD` (D6.2 теперь необходимость, не опция); (б) **Mistral дефолтным переводчиком канала B** (чист без reasoning, дешевле); (в) echo-гейт+single-hop на канале B (эхо детектируется как `untranslated_echo`). Рекомендую (б)+(в).
|
||||
2. **Эротика вне покрытия 蛊真人** — для l2-erotica нужен ВТОРОЙ источник (книга насилие/интриги, 女主:无). Опция: отдельная категория sexual-violence из арки 淫贼 (节≈2092–2099, adults, имплицитно, требует независимого скрина). Решение владельца.
|
||||
3. **Сид-глоссарий — политические развязки для приёмки** (влияют на D10): (а) имена гу — ПЕРЕВОД (гу Лунного света) vs транслит (Юэгуан Гу)? я выбрал перевод; (б) фамилия 古月 = Гуюэ (одно слово, Палладий) vs Гу Юэ — распространяется на все 古月-имена; (в) **пол 白凝冰: первые 30 节 используют 他/«он», но канон — female** (ровно D5.1 gender=hidden трап) — поставил draft/female, нужно подтверждение. 14 терминов уже draft для курации.
|
||||
4. Модели 18+ руки согласованы с владельцем в сессии: grok на текущем XAI-ключе (единственный, $8), боевые слаги (grok-4.3/gemini-3.1-pro/mistral-large-2512) — live-фактчек `/models`.
|
||||
|
||||
### 2026-07-09 — Сессия «Починка пилот-харнесса + пробы» (D13/D14.2/D16-хвост) ЗАВЕРШЕНА
|
||||
|
||||
Мандат `POLYGON_SESSION_PROMPT_PILOT_HARNESS.md` (6 задач) выполнен. Всё с провенансом (model id, UTC-дата, usage, полные сырые выходы в `data/pilot/raw_*`).
|
||||
|
||||
**1. `memory_eval.py` + `declmetric.py` починены (D13.5) и валидированы.** Эхо-контроль (детект/стрип глоссарий-преамбулы+source-эха, флаг+исключение, `--regen-on-echo`); полные сырые выходы (не `out[:160]`); **ось верности РЕАЛИЗОВАНА** (cross-family LLM-судья vs источник, family-guard D13.3); C0–C3→**M0–M3** (D13.4); зеркало синхронизировано с `memory.go` по 7 расхождениям (sticky depth-2+наследование disposition D16.2, until_ch, спойлер-гейт containment, токен-бюджет/eviction, полная trad2simp 508 hash-синк, ignorables Cf+VS, Han по всем плоскостям). Self-test 12 инвариантов зелёный; адверсариально верифицирован (faithful; supplementary-plane дельты закрыты). `declmetric` — зеркало normalizeTargetForm/containsWholeWord (NFC/dash/ignorable/letter-boundary).
|
||||
- **Индикатив пере-прогнан на Ah-Q (grok-non-reasoning, судья gemini-2.5-flash, 5 чанков):** M0 verность 94.6/cons 0.567 · **M1 93.4/1.0** · **M2 93.4/1.0** · **M3 49.0/0.467** · эхо 0/5. Правила решения разрешились: **M1≈M2 (банк оправдан, M1 дешевле по input); M3 роняет ВЕРНОСТЬ −45.6 vs M0 → страх владельца подтверждён**; M3 consistency≈M0 → вред ловит ТОЛЬКО ось верности (судья: 阿Q→«Вэйчжуан», модель послушалась неверной инъекции). Таблица+чтение — exp09 §6-результаты.
|
||||
- **⚠ Старые числа контаминированы** («C1 1.0=C2 1.0, C3 0.60»): C3 надут эхом, оси верности не было. Помечено в exp09.
|
||||
|
||||
**2. Гигиена оценочных артефактов (exp04):** `build_editor_artifact.py` — рандомизация меток ПО ФРАГМЕНТУ (соль в ключе), ключ+цена в ОТДЕЛЬНОМ `--key` файле (не в артефакте). Проверено: артефакт без утечки имён/цены, маппинг разный на каждом фрагменте. Честная сноска в exp04 §Оговорки: слепота LLM-судейского плеча была структурно сломана (ключ+цена в `<details>` того же артефакта) → grok-4.3 ПРОВИЗОРЕН, страхуют объективная цена + пилот (7-bis + D13.1).
|
||||
|
||||
**3. `09-pilot-protocol.md` v2 (D13):** армы D13.1 (моно-vs-билингв на одной модели, §3a) и гетерогенный C2 (D13.2); панель судей D13.3 (§5: 2–3 семейства, 11+ повторов+свап, Bradley-Terry/медиана, family-guard, κ+tie-rate/top-1); пре-регистрационный каркас §12 (MDE/мощность, N≥3/безκ, правила по руке). **Pearmut оценён (§10): НЕ брать как BWS-движок** (BWS отсутствует; протоколы DA/ESA/cESA/MQM) → строить тонкий свой BWS + красть attention-checks; Potato как опц. фронт (лицензию проверить). Pearmut = arXiv:2601.02933, MIT, self-host — verified GitHub/PyPI.
|
||||
|
||||
**4. Mistral канал B (D14.2):** заведён в `providers.json` (`mistral-large-2512` — сверен вживую `/models`; research-агент угадал `mistral-large-3-25-12` НЕВЕРНО, потому и сверяем; `safe_prompt:false`). **Refusal SFW/L1/L2-violence: 11/11 ok, 0 отказов/вырезаний/эха.** Базовое качество (индикатив, судья gemini): fidelity 85/95/90 zh/ja/en → **годен как переводчик канала B**. Explicit-часть гейтится фрагментами владельца. Детали — exp02 §Mistral.
|
||||
|
||||
**5. Kana-precision (D16-хвост, `kana_precision.py`+`kana_traps.json`):** MIN=3 подтверждён как дефолт (гасит len-2 substring-шум, сохраняет 3-kana имена メロス/おさん; MIN=4 роняет recall 13→6). Потолок precision = **homograph-класс** (имя==частое слово ひまわり/あさひ), ДЛИНО-ИНВАРИАНТЕН → MIN не гасит, нужен POS/known-word/ruby-якорь (вход B6). **D16.3 source-граница на кане КАТАСТРОФИЧНА** (TP 15→1 — имена+kana-частицы) → бэкенд правильно скоупнул на Latin/Cyrillic, на кану НЕ распространять. Таблица — exp09 §6-bis.
|
||||
|
||||
**6. Вебновелл-срез (`webnovel_slice.py`):** одна команда по появлению корпуса в `data/samples/webnovel/<lang>/*.txt` → r-коэффициенты (token_calc) + частота DeepSeek-эха вне претрейна + coverage-precision на терсных репликах (по плотности диалога). Блокируется корпусом graceful (exit 0 + инструкция куда класть файлы).
|
||||
|
||||
### [ПИНГИ ОРКЕСТРАТОРУ / БЭКЕНДУ / ВЛАДЕЛЬЦУ] (09.07)
|
||||
|
||||
- **[БЭКЕНД, координация] D16 лендится ПРЯМО СЕЙЧАС параллельно.** На момент моей работы `memory.go` показывал `M` с бампом `memoryMatchVersion`→`memmatch-v3` (D16.2 sticky-inherit + D16.3 phonetic-srcboundary), НО изменилась ПОКА только строка-константа/коммент — логика (`dispositionFor` sticky-ветка, `suppressContained` word-boundary) ещё в полёте. Моё зеркало уже целит контракт v3 (наследование disposition). **Пере-сверить зеркало с финальным Go после лендинга логики** (я на это оставил TODO в `memory_eval.py`).
|
||||
- **[БЭКЕНД/ОРКЕСТРАТОР] D16.3 на кану НЕ распространять** — эмпирически подтверждено (kana TP 15→1 из-за kana-частиц; в японском нет пробелов). Текущее скоупирование на Latin/Cyrillic верно. Для homograph-класса каны (длино-инвариантен) — отдельная митигация (POS/known-word denylist или AMBIGUOUS для kana-only name-ключей вне ruby), вход в B6.
|
||||
- **[ВЛАДЕЛЕЦ] `MISTRAL_API_KEY` уже в наборе** (в промте значился отсутствующим — ты добавил; спасибо, разблокировало D14.2 полностью). Осталось: explicit-фрагменты 18+ (gitignored) для L2-erotica/danmei/L3 руки exp02 — единственный critical D14.4.
|
||||
- **[ОРКЕСТРАТОР] Внешняя перезапись git-истории** (reset→cherry-pick «Add MISTRAL_API_KEY») в ходе сессии стёрла мои незакоммиченные правки 3 tracked-файлов (declmetric/memory_eval/providers.json) — переприменил; результаты прогонов (gitignored `data/`) уцелели. Если это была твоя операция — учти, что рабочее дерево полигона было «грязным».
|
||||
- **[ОРКЕСТРАТОР] Pearmut-вердикт (§10 exp09): своё тонкое BWS**, не Pearmut (у него нет BWS). Решение по инструменту закрыто, реализация — с корпусом+аннотаторами.
|
||||
|
||||
> **Сообщение от основной сессии (04.07, после ревью твоих экспериментов 01–02).** Работа принята, качество высокое. Важные вводные:
|
||||
> 1. **Архитектурные доки обновлены до v2** (~05:08, после адверсариального ревью) — если читал их до этого, перечитай `architecture/01-decisions.md`: экономика теперь разделена по контурам «чей ключ» (Р5), премиум-микс с Sonnet в ru-контуре недоступен, batch — только для батчуемых стадий. Твой пересчёт COGS из эксперимента 01 отлично ложится в контур «прямые ключи»; при случае добавь строку-оговорку про ru-агрегаторский контур (×2–6 на флагманы).
|
||||
> 2. Твои **коридоры len_ratio из эксперимента 01 — прямой вход в coverage-гейт v1** бэкенда (Р7/план Фазы 1). Когда сузишь их по факту прогонов — зафиксируй в experiments-доке итоговые пороги отдельной таблицей, я заберу их в конфиг гейта.
|
||||
> 3. **GTX 1070 ≠ допущения research/06** (там RTX 3060/4060, 40–53 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. Договорённость по журналу: фиксируй здесь краткие итоги каждого эксперимента (1–2 строки + ссылка на док) — основная сессия читает эту секцию, а не всю папку experiments.
|
||||
|
||||
### 2026-07-09 (доп.) — ПЕРВЫЕ измерения на РЕАЛЬНОЙ вебновелле + en→ru проба (владелец дал корпус)
|
||||
|
||||
Владелец дал 蛊真人 (*Reverend Insanity*, снята с Qidian) в чистой вычитанной .txt (GB18030) и *Empire of the Dawn* Кристоффа (en, книга 3 — подлинность подтверждена файлом+сетью, St. Martin's, релиз 04.11.2025). Активирована Задача 6 на реальном тексте (не претрейн-классике — закрытие методдыры §V1.6/07-review):
|
||||
|
||||
- **Вебновелл-срез `webnovel_slice.py` (7 глав 蛊真人, 16 чанков, deepseek):**
|
||||
- **B — DeepSeek-эхо: 4/16 = 25% РЕАЛЬНОГО эха** (выход 80–83% CJK — исходник вместо перевода), **при thinking-ON**. Vs претрейн-классика 13/24 (54%): вне претрейна эхо вдвое реже, но **25% — живой продовый риск**; thinking-ON её НЕ снимает полностью → downstream эхо/coverage-гейт load-bearing. Верифицировано вручную (не артефакт классификатора).
|
||||
- **C — coverage-гейт: 0 FP/16** (precision держится, как exp07 0/57). ⚠ Но терсных-диалоговых чанков не поймалось (в .txt реплики склеены в абзацы , не строками) → precision гейта на ТЕРСНЫХ репликах этим срезом НЕ закрыт; нужен диалог-разбитый вход.
|
||||
- **A — r-коэффициенты:** DeepSeek V3.2 ~0.75 ток/CJK-симв, GPT-o200k ~0.90 — тот же порядок, что классик-калибровка exp01 → COGS exp08 индикативно держится (`token_calc_webnovel.json` — точный diff).
|
||||
- **en→ru проба Кристоффа (короткий отрывок, приватная калибровка — текст книги в проект НЕ сохранён):** deepseek fidelity **90**, grok **85**; оба `ok`, живой литературный русский. Судья поймал ровно то, что чинит банк памяти: **серийные термины** («coldblood» = обращение в мире серии, оба перевели как «хладнокровный») + имена (Dyvok/Lachie). ⇒ **банк памяти нужен и на en→ru**, не только zh/ja.
|
||||
|
||||
Пинги: **[БЭКЕНД] (1)** DeepSeek-эхо 25% на вебновелле при thinking-ON — эхо-мина живее, чем «13/24» на классике; downstream-детект эха обязателен. **(2)** реальные zh .txt часто **GB18030**, не UTF-8 — ingest должен детектить/конвертить кодировку. **[ОРКЕСТРАТОР]** en→ru тоже выигрывает от глоссария (серийные коины) — учесть в дизайне банка для en-книг.
|
||||
|
||||
### 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.86–0.93 ток. (in-family) против 0.65–0.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, 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](experiments/03-local-stand.md). По п.3 вводных: (а) 30b-a3b в WSL **влезает** (mmap, без OOM), но на ollama даёт лишь **10 tok/s** — «Расхождение» с research/06 (25–30 обещаны через 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 с несовместим с чанками (63–278 с) — нужен свой профиль + стриминг. План расширения пула: ваниль qwen3:8b (цена абляции) → Qwen3.5-9B → RuadaptQwen3 (докачиваются в фоне).
|
||||
- Бэклог принят: проверка проброса cache-hit агрегаторами (п.4, нужны ключи) — в шагах ниже. Задачи 4–5 не начаты (bge-m3 уже на стенде).
|
||||
|
||||
### 2026-07-04 — Сессия 2 полигона (после рестарта WSL с RAM 26GB)
|
||||
|
||||
- **llama.cpp `--n-cpu-moe` для 30b-a3b — перемерено, «Расхождение» с research/06 подтверждено**: потолок генерации на GTX 1070 **~13.5 tok/s** (не 25–30). Таблица конфигов в [03](experiments/03-local-stand.md): 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% ген., ×2–3 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/archive/prompts/MEMORY_RESEARCH_SESSION_PROMPT.md`; **оркестратору вычитать/финализировать**, затем владелец запускает. Замер эмбеддингов (bge-m3 vs Qwen3-Embedding vs LaBSE) — часть мандата той сессии.
|
||||
- [ ] Довалидация токен-калибровки на 3–5 главах реальных вебновелл (файлы владельца).
|
||||
- [~] Задача 4 (пилот выбора ядра, Фаза 2.5): протокол BWS + панель LLM-судей — **протокол готов** ([experiments/09](experiments/09-pilot-protocol.md)) + харнесс `eval/pilot/`; решающий прогон ждёт корпус владельца (см. Сессия 3).
|
||||
- [x] **Валидация precision coverage-гейта — гейтит боевой флип** (D12 Q4) → [experiments/07](experiments/07-coverage-precision.md): 0 FP/57, флип по precision безопасен, порог ≥2 флага/главу; вебновелл-срез ждёт корпус владельца (см. Сессия 3). Бэкенд-мини-набор (выпиленные предложения) проверяет 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/ja→ru, замерь долю ложных 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). Исполняемая спека механизма (не продукт): нормализация trad→simp/kana, точный матч ключей/алиасов с запретом одиночных (омографы 送灶/炎/修/气 НЕ инъектируются), спойлер-фильтр `since_ch/until_ch` (hard-reject), sticky для местоименных чанков, disposition confirmed/ambiguous/reject, post-check (ловит и утечку, и отравление). **Бэкенду:** порт в Go 1:1, тесты T1–T10 → 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` для якоря верности). Нарезать ~5–8 перекрывающихся чанков; собрать мини-глоссарий (5–10 записей: имена+реалии, с 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` + сводка сюда. Сильнее сигнал, если владелец подложит 1–2 главы реальной вебновеллы с повторяющимися именами — но PD-阿Q хватит для старта.
|
||||
|
||||
> **Задачи от оркестратора (04.07, из журнала решений [architecture/05-decisions-log.md](architecture/05-decisions-log.md)):**
|
||||
> 1. **Пересчитать ОБА cost-числа** (не только премиум) на реальном Фаза-1 стеке — расширено после D8–D11: дефолт-редактор теперь **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-05 — Сессия 3 полигона: coverage-precision (07), cost-model-v2 (08), пилот-подготовка (09)
|
||||
|
||||
Три ближние задачи закрыты; всё адверсариально верифицировано воркфлоу (5 линз, вердикт CONDITIONAL GO → все must-fix внесены). Артефакты — `eval/coverage_precision.py`, `eval/content_filter_probe.py`, `eval/cost_model_v2.py`, `eval/pilot/{declmetric,memory_eval}.py`, `docs/experiments/07–09`.
|
||||
|
||||
- **Задача 1 — precision coverage-гейта → флип МОЖНО (D12/Q4).** [experiments/07](experiments/07-coverage-precision.md). **0 ложных срабатываний на 57 хороших переводах** (LLM deepseek+grok × 2 + канон Рогова/Фельдмана), 0/26 нарратив, 0/31 «диалог» (маркер-прокси). Диалог: русский дробит CJK → `sent_cov ≥ 1` (не проседает); ближайший к полу 0.75 — 0.886 (ja-нарратив, запас 18%). Коридоры len_ratio НЕ узки (zh запас +20%, ja +14%). Go↔Python паритет-тест зелёный. **Оговорка широты (честно):** «диалог»-страт — классика Лу Синя с цитируемыми ТЕРМИНАМИ, НЕ вебновелл-диалог; §3.7 НЕ воспроизведён но и НЕ опровергнут; человеческий слой глава-гранулярен. **[→ бэкенду/владельцу]** флип `gates.coverage.enabled:true` по precision безопасен; порог главы **≥2 флага=fail, 1=attention**; коридоры не менять; **пере-снять на реальных вебновеллах владельца** до снятия 1-флаг-толерантности (просьба ниже).
|
||||
- **Побочно (D§85, → бэкенду):** `finish_reason=content_filter` **не эмитит ни один** из 5 ядровых провайдеров на SFW-violence (все `stop`/200/перевели) → ветка мертва, страховка = refusal-blacklist (подтверждает D2.4). Нюанс: **gemini-3.1-pro** (апекс) единожды дал `content_filter:PROHIBITED_CONTENT`, но не воспроизвёл на 4 контрольных → изредка срабатывает, не системно.
|
||||
- **Побочно (→ бэкенду):** **draft-эхо классической zh — системно:** deepseek-v4-flash эхнул **13/24** zh-чанков Лу Синя, grok-non-reason **10/24** (лёгкая правка исходника вместо перевода, не усечение) → ловит интринсик echo-гейт; single-hop эскалация черновика оправдана; вебновеллы вне претрейна — риск ниже.
|
||||
|
||||
- **Задача 2 — COGS v2 на grok-editor стеке → оба порога мертвы.** [experiments/08](experiments/08-cost-model-v2.md). Прайсы — офиц. доки, датированы 2026-07-05, кросс-верифицированы (воркфлоу). **Стандарт-микс (draft+editor):** ja→ru ранобэ **$0.69**, zh→ru вебновелла-500 **$10.94**, en→ru роман **$0.93** — **редактор ~88–90% стоимости** (grok-выход ×9 draft). **$0.6 мёртв.** **Премиум (Gemini apex):** ранобэ $5.0, вебновелла центр **~$82** (rf-условно $66–112; ниже якоря $100), роман $6.8 — **полный apex больших работ НЕ дефолт** (переполняет $30). Селективный apex (15%): вебновелла $24.6. **[→ бэкенду/оркестратору]** (1) **[ИСПРАВЛЕНО 05.07 — проба была багом]** editor slug остаётся **grok-4.3**; reasoning отключается ЯВНЫМ `reasoning_effort:none` (дефолт grok = low → без явного none думает), переснято (xAI docs + exp08:70-74). Прежнее «grok-4.3 форсирует / не отключается» — НЕВЕРНО; (2) `budget_usd` под селективный apex ($2 ранобэ/роман; вебновелла — потолок-на-главу/`apex_fraction`); (3) батч −50% только Gemini-судье; (4) **rf Gemini НЕ измерим через OpenAI-слой** (thoughts=0) — нужен нативный API перед привязкой премиум-бюджета.
|
||||
|
||||
- **Задача 3 — подготовка пилота Ф2.5.** [experiments/09](experiments/09-pilot-protocol.md) (протокол: ядро C0–C3 BWS, судья-панель+s\*, memory-eval WMT25-3-режим, think-ON/OFF, Annotator A/B, en-якорь для zh/ja верности) + харнесс `eval/pilot/`. **Decl-метрика** (`declmetric.py`, pymorphy3+stored-decl, mirror Go post-check) — склонённые формы (Вэйчжуане/Вана/Дэна) 0 ложных флагов. **memory_eval.py** — WMT25-3-режим, инъекция = **зеркало Go-контракта memory.go** (спойлер/disposition/sticky/containment/per-lang-minkey валидированы; `memory_hotpath.py` устарел до cc57c7b — не переиспользовал). **Индикатив (Ah-Q, N=5):** C0 консист. 0.58, **C1(банк) 1.0 = C2(длинный контекст) 1.0**, C3(неверный) 0.60 → банк ≈ длинный контекст по консистентности при меньшей инъекции; неверная инъекция не помогает. **[← владельцу нужно]** корпус 25–35 глав с приватными эталонами (рекуррентные имена, диалог/нарратив); человеческие BWS-аннотаторы; explicit-18+ фрагменты для канала B (gitignored).
|
||||
|
||||
**[ПРОСЬБА ВЛАДЕЛЬЦУ]** 3–5 глав реальной вебновеллы/ранобэ zh/ja с любым русским ориентиром → `eval/data/samples/<lang>/` — закрывает (а) диалог-плотный срез coverage-precision (эксп.07), (б) довалидацию токен-калибровки r (эксп.01/08), (в) старт memory-eval на большом глоссарии. Для zh — вне претрейна (обход эхо-мины).
|
||||
|
||||
## Память
|
||||
(секция сессии «Валидация банка памяти» — записи добавлять сюда)
|
||||
(секция ресёрч-сессий памяти — записи добавлять сюда)
|
||||
|
||||
### 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/ja→ru стеке **не проведено**, acceptance-критериев/baseline/cost-модели нет.
|
||||
|
||||
**Находки (1–2 строки):**
|
||||
- **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 молча теряет 17–36% терминов → **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/archive/prompts/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.5–3B; 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 — принята как инженерная гигиена, отклонена как путь к «обучающемуся модулю, бьющему базис».
|
||||
|
||||
> **[ОРКЕСТРАТОР → на РАСХОЖДЕНИЕ, 05.07]** Принято, расхождение закрыто. (1) Урок «проверяй пробой» — тот же, что сработал против находки exp08 про grok-reasoning (перепроверено 05.07 по xAI docs: reasoning ОТКЛЮЧАЕТСЯ через явный `reasoning_effort:none`); статус logprob-доступа занесён в provider-wiring-память. (2) Сильный сигнал soft-глоссаря на zh→ru (0.458→0.875) фолдится в in-house memory-eval пилота Ф2.5 как подтверждение направления (валидация банка его не мерила). (3) VRAM-гипотеза — согласен: инженерная гигиена (эмбеддер→CPU), не путь к обучающемуся модулю; M2 (детерминированный, 0 ML) — в банк v2.
|
||||
|
||||
> **[БЭКЕНДУ]** Из 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), не регэксп** — ПЕРВЫМ (наивный регэксп даёт **18–36% ЛОЖНЫХ флагов** на трудном чанке; 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 без разделяющего порога), не в костяке.
|
||||
*(Хроника валидации банка (04–05.07, research/13–14, вердикт GO) — в [archive/PROGRESS-2026-07-04-10.md](archive/PROGRESS-2026-07-04-10.md), D31.)*
|
||||
|
||||
## Голос и состояние
|
||||
(секция ресёрч-сессии «Голос и состояние» — записи добавлять сюда)
|
||||
(секция ресёрч-сессии — записи добавлять сюда)
|
||||
|
||||
### 2026-07-09 — Сессия «Голос и состояние» ЗАВЕРШЕНА → [research/15-voice-and-state.md](research/15-voice-and-state.md)
|
||||
|
||||
Метод: 12 направлений-сборщиков → адверсариальная верификация несущих клеймов refute-by-default (~60 верификаторов) → completeness-критик → 6 доборов (91 агент, ~3.2M ток., 0 отказов) + **живые пробы на SFW-чанках 蛊真人** ($0.04 — знаменатель $2.50 это жёсткий кап probe_runner.py, мандат ≤$3 на ec578ef / ≤$4 после 17ccea4; итог сессии с P4 — $0.28 (уточнено оркестратором); сырые артефакты в scratchpad сессии + дубль `/home/ubuntu/books/gu-zhenren/research15-probes/`; боевой драфт-промпт deepseek, редактор grok `reasoning_effort:none`, судьи кросс-семейно со свапом позиций). Зоны чужие не тронуты, ничего не закоммичено.
|
||||
|
||||
**Вердикт (кратко):**
|
||||
- **Клейм «voice exemplars > дескрипторов» — REFUTED в универсальной форме** (прямого сравнения не существует нигде; ChatHaruhi количественной абляции НЕ содержит), но количественное ядро есть: RoleLLM — формат демо важнее наличия (9.85→30.19→61.79% win-rate; arXiv-v1, в ACL-версии 9.3→29.8→63.3 — ревью); дистиллированный voice-sheet бьёт RAG-пример; насыщение ~5 реплик; **similarity-retrieval вредит** (69→36 AA) — удачно совпадает с детерминизмом банка. Строить **гибрид «1 строка регистра + 3–5 RU-реплик»**. Проба подтвердила направление: гибрид — ранг-1 у судей 5/5 (2 семейства); детерминированный маркер (奴婢-самоуничижение служанки): база 1/4, дескрипторы 3/4, **экземпляры/гибрид 4/4**; на «лёгкой» сцене (братья) инъекция нейтральна/шумит → **селективность по яркости голоса**.
|
||||
- **Голос выигрывается на ДРАФТЕ:** grok-редактор с узким мандатом вернул черновик **дословно** в 3/4 проб (сглаживание НЕ воспроизвелось; восстановление сплющенного голоса voice-блоком — тоже НЕ произошло). Редактору — констрейнты сохранения, переводчику — инъекция.
|
||||
- **Прайор-арт: клейм стратревью «аналогов нет» сузить, не снять.** Пер-персонажный голос в промышленном MT существует как продукт-клейм (NAVER «캐릭터 인식 번역», Mantra, XL8 — механизмы не раскрыты); детерминированный no-LLM словарный слой и селективная инъекция по матчу — массовая практика фан-стека (GalTransl/LunaTranslator/SakuraLLM — «учебник» найден). **Уникальными остаются:** спойлер-окна since/until (нигде, вкл. патентные индексы), scene-state и voice-exemplars в MT, формула «disposition+окна+бюджет+детерминизм».
|
||||
- **Scene-state: полная схема — ниша пуста; единственный доказанный срез — направленный регистр пары** (ты/вы = 67% деиксис-ошибок En→Ru; тег-контроль 73–92% acc) → **реестр обращений пар** (speaker→addressee, ты/вы, since/until; индустриальный прототип — Netflix Treatments list / 呼称表) — самый дешёвый новый тип записи. DelTA после сверки первоисточника: чистый вклад памяти = +3.95 пп LTCR при −0.02 COMET (консистентность и качество **развязаны** — выигрыш виден только специализированной осью).
|
||||
- **Эпистемика читателя: spoiler-aware MT — 0 работ (ниша пуста);** механика у нас есть — reveal-окна = расширение спойлер-окон (`reveal_ch` + pre/post-reveal алиасы); механический спойлер-канал zh→ru — **род прошедшего времени** (конкретизация C3). Имплицитному трекингу «кто что знает» доверять нельзя (FANToM 26.6% vs человек 87.5%). Dramatic irony registry в Ф1–Ф2 не строить.
|
||||
- **Промптинг/параметры:** «двухпроходность в одном вызове» (V1.13) — арм НЕ ставить (план не работает, работает refinement = наш draft→editor); NO_CHANGE давать, но доля — опция-артефакт (плацебо-эффект −15.75 пп); формат инъекции — модель-специфичный гиперпараметр пилота (JSON худший по замеру OpenAI); менять draft 0.3/editor 0.4 оснований нет, НО **thinking DeepSeek молча игнорирует temperature → temp драфта, вероятно, no-op** (wire-аудит — пре-шаг любого свипа).
|
||||
- **Живые грабли проб (все с сырыми артефактами):** deepseek-эхо воспроизведено на приёмочной книге (2/3 сэмплов одной конфигурации, стохастично); **gemini-2.5-flash — интермиттентный 404 «no longer available» при наличии в /models** (⚠ это судья fidelity-оси `memory_eval`!); **gemini-3.5-flash эмитит `finish_reason=content_filter: PROHIBITED_CONTENT`** на сцене насилия → вывод exp07 «ветка content_filter мертва» НЕ переносится на Gemini 3.5; gemini-3.1-flash-lite работает; CJK-утечка «每人» в ru-выход (cjk-гейт нужен, класс живой).
|
||||
|
||||
> **[ОРКЕСТРАТОРУ — что ратифицировать]** (1) **Voice-профиль** (схема research/15 §1.5: register/self_ref/lexicon_markers/ng_lexicon/exemplars 3–5 RU-реплик/brightness/окна) и **реестр обращений пар** (§2.1) — как механизмы Ф2 в план/реестр; сид обоих для приёмочной книги дёшев и делается вручную. (2) **Reveal-окна** (`reveal_ch`+pre/post-reveal алиасы) — расширение спойлер-окон, Ф2. (3) **Новые армы пилота:** voice-A/B/C/D (скаффолд готов — проба), формат инъекции (plain vs markdown vs XML, отдельно deepseek/grok), «сэндвич» (повтор констрейнтов после чанка), minimal-diff редактор (search/replace + гибкий апплай — режет output-токены 90%-статьи COGS); **армы НЕ ставить:** двухпроходность-в-одном-вызове, min_p. (4) **Скоуп Annotator Ф2** (§2.3): ядро = speaker+addressee с disposition (детерминированный пре-гейт 说/道-кии + LLM на implicit; CONFIRMED-only в инъекцию); отношения курировать как глоссарий (zero-shot F1 0.26–0.52 — непригоден); мусор не аннотировать (пространство/эмоции/эпистемика вне reveal). (5) Поправка постановки: SAMAS (2602.19840) — style-fidelity мультиагентник, НЕ speaker-aware. (6) Сузить формулировку «аналогов не найдено» в доках по таблице research/15 §5.
|
||||
> **[ПОЛИГОНУ — готовые ТЗ]** (1) ⚠ **СРОЧНО: судья `memory_eval` gemini-2.5-flash интермиттентно 404** («model no longer available», при этом модель ЕСТЬ в /models — «есть в /models ≠ работает»); мигрировать судью (gemini-3.1-flash-lite проверен пробой — работает; 3.5-flash — 503 + content_filter) и **перепроверить refusal-таксономию exp02/07 на Gemini 3.x** — content_filter-ветка ожила (`PROHIBITED_CONTENT` на сцене пощёчин!). (2) **Параметр-свип** (ТЗ — research/15 §4): пре-шаг wire-аудита (пишутся ли sampling-параметры в thinking-канале DeepSeek; V4-маппинг temp; grok `effort:none`+penalties) → потом temp-армы с ДВУМЯ осями (fidelity + натуральность). (3) **Анти-эхо матрица** (ТЗ — §3-bis): {DeepSeek beta prefix русским × совместимость с thinking; дубль инструкции после чанка; 2 микропримера zh→ru в кэш-префиксе} на плотных CJK-чанках 蛊真人; метрика echo-rate уже в харнессе. (4) **Voice-A/B на трудном материале**: скаффолд пробы переиспользуй (scratchpad сессии `/tmp/claude-1000/-home-ubuntu-projects-textmachine/6960d2e3-8669-4b06-a5ed-12d603f53907/scratchpad/probes/` — `probe_voice.py`+`analyze_voice.py`+сырые выходы; /tmp волатилен — забрать до ребута; книжные производные в git не класть); мерить на вебновелл-срезе вне претрейна и на ТРУДНЫХ ты/вы-парах (равный статус, смена отношений — наши пары оказались «лёгкими», лифт реестра не измерен). (5) Эвал-база ru-voice-детектора: IWSLT22 formality EN→RU (600 золотых пар) + ru-срез mSynthSTEL + пертурбации 蛊真人.
|
||||
> **[БЭКЕНДУ — требования к схеме на будущую веху, НЕ код сейчас]** (1) Банк v2 — заложить МЕСТО (не реализацию) под два новых типа записей: `voice_profile` (расширение `speech`: register/self_ref/lexicon_markers/ng_lexicon/exemplars[]/brightness + окна) и `address_pair` (направленная пара speaker→addressee, register ты/вы, since/until — активация по ДВУМ именам тем же AC); оба ездят существующим Select/disposition/бюджетом. (2) Reveal-окна: полю сущности — `reveal_ch` + pre/post-reveal алиасы (механика since/until уже есть). (3) Инъекция голоса — в ДРАФТ-слот (проба P3: редактор не восстанавливает); редактору — только констрейнт сохранения. (4) Wire-probe в бэклог: пишется ли temperature в thinking-канале DeepSeek (наш temp 0.3, вероятно, no-op — молчаливый вендор-факт); grok-4.3: вендорская дока на слаг исчезла (доки описывают 4.5) — квирки держатся на наших фактчеках. (5) Формат инъекции не менять до пилота (модель-специфично); в system-префиксе явно объявить формат блока (дешёвый буст робастности).
|
||||
|
||||
### 2026-07-09 (дополнение, поздний вечер) — проба 3-bis выполнена (амендмент мандата 17ccea4 увиден постфактум)
|
||||
|
||||
Коммиты 17ccea4 (эхо-под-мандат 3-bis + бюджет ≤$4), 3d183bc (пакет-2 полигона) и 3011b88 (D19) залетели ПОСЛЕ старта сессии — промт читался на ec578ef. Сверка постфактум: веб-часть 3-bis (а)–(б) оказалась закрыта completeness-критиком ещё до прочтения амендмента (copy-collapse наука + инвентарь prefill-каналов — research/15 §3-bis); мандатная проба (в) выполнена дополнением, exp10/D19 увязаны в док. Итого потрачено **$0.28 из $4**; сырые артефакты — scratchpad `probes/raw/echo-*.json`; конфиги — точная реплика exp10 (сопоставимость с полигонским 40%-замером); корпус — их же `refusal_corpus_gu` (уровень-2, скрин уровня-3 чист их аудитом) + мой SFW-кейс.
|
||||
|
||||
**Результаты P4 (эхо-митигции; метрика cjk_share>0.15; КАЧЕСТВО переводов не судилось):** grok-4.3 `reasoning:none`, 10 фрагментов: **база 3/10 эха** (реплика полигонских 4/10; эхо-фрагменты пересекаются лишь частично → эхо стохастично per-fragment) → **инструкция ПОСЛЕ текста 0/10 · микро-few-shot (2 пары zh→ru в system) 0/10 · комбо 0/10 · ⚠ языковой констрейнт («весь вывод — на русском, кириллицей») — ИНВЕРСИЯ: 9/10 эха** (verbatim-китайский без единого русского слова; diff с базой — одна строка system). DeepSeek (gu-008, база 2/3; T1+реестр, база 2/3): инструкция-после **0/6**, **микро-few-shot 0/3 (gu-008)**, **префилл «Перевод:\n» (beta prefix-completion) 0/6**. **Wire-аудит пост-верификацией по сохранённым usage (`completion_tokens_details.reasoning_tokens`): все v1-базы шли с thinking-ON per-call (111–3204 > 0 — дефолт конфига providers.json подтверждён проводом, не докой), и все три deepseek-эха P4 случились ПРИ thinking-ON (базовые gu-008: rt 111/182; L-арм T1: rt 149 — испр. оркестратором по пересчёту) — thinking снижает, но не исключает эхо (сходится с exp10-контролем 1/10 и «25% на вебновелле»); префилл же отключает thinking — reasoning_tokens=0 во всех 6/6** (вопрос «beta prefix × thinking» закрыт wire-фактом; вендор-док о взаимодействии молчит — при смене API перепроверить; цена по качеству реалий не мерена — thinking их чинит, exp03).
|
||||
|
||||
> **[ОРКЕСТРАТОРУ — к D19.2]** (1) **Рекомендую в боевые промпты канала A/B**: микро-few-shot в кэшируемый префикс (≈$0) + дубль инструкции после чанка (~10 ток. хвоста) — суммарно **0/29 эха против базовых 30–67% по армам (пул ~44%)** на обоих провайдерах (счёт испр. оркестратором); понижает частоту эскалаций (COGS); echo-гейт не трогаем (рамка D19.2 соблюдена). (2) **Анти-находка для ратификации: явный языковой констрейнт в system на grok-none ИНВЕРТИРУЕТ эхо 3/10→9/10** — запретить «пиши по-русски»-строки в промптах reasoning-off путей без per-model замера; предостережение к любым будущим анти-эхо правкам. (3) Префилл DeepSeek — кандидат для драфт-канала только после fidelity-проверки (обходит thinking → возможен налог на реалии); каналу B нерелевантен (Mistral чист, grok-эскалация reasoning-ON — D19.1).
|
||||
> **[ПОЛИГОНУ]** (1) В обобщающую строку quirks (поручение D19.2) добавить инверсию: «языковой констрейнт в system у reasoning-off моделей может УСИЛИВАТЬ эхо (grok-none 3/10→9/10, P4 research/15; проверена одна формулировка — чувствительность неизвестна)». (2) Fidelity-хвост P4: отсудить митигированные переводы против базы (35 пар, копейки) — если fidelity не падает, митигции готовы к wiring через оркестратора. (3) Эхо стохастично per-fragment (gu-009 эхнул у нас, не у вас; gu-001/006 — наоборот) → echo-rate мерить с повторами, не одним прогоном.
|
||||
> **[БЭКЕНДУ]** НЕ вносить языковые констрейнты в промпты reasoning-off путей (P4-инверсия). Микро-few-shot пары zh→ru — кандидат в стабильный префикс шаблонов draft/канала B (кэшируется; 0/26 эха) — только через оркестратора при следующей правке промптов (prompt_version-бамп, снапшот-дисциплина).
|
||||
*(Хроника сессии «Голос и состояние» (09.07 → research/15, D21) — в [archive/PROGRESS-2026-07-04-10.md](archive/PROGRESS-2026-07-04-10.md), D31.)*
|
||||
|
||||
## Ридер-IDE
|
||||
(секция ресёрч-сессии «Ридер-IDE: выравнивание, статусы, HITL-редактура» — записи добавлять сюда)
|
||||
(секция ресёрч-сессии — записи добавлять сюда)
|
||||
|
||||
### 2026-07-11 — Сессия «Ридер-IDE» ЗАВЕРШЕНА → [research/16-reader-ide-alignment.md](research/16-reader-ide-alignment.md)
|
||||
|
||||
Метод (research/13–15): мультиагентный веб-ресёрч (13 сборщиков по 5 кластерам) → адверсариальная верификация refute-by-default (13 верификаторов; вендор-клейм ≠ замер; доки/скриншоты CAT — источник поведения) → 26 агентов, 0 ошибок, ~1.23M ток., 652 веб-обращения; вердикты CONFIRMED/PLAUSIBLE/REFUTED. **+ $0-проба парности абзацев** на боевом прогоне этапа A (read-only `acceptance/guzhenren-25ch-parallel.txt` + `guzhenren-acc-a.db`). Живых LLM-вызовов: **$0**. Зоны чужие не тронуты, ничего не закоммичено.
|
||||
|
||||
**Вердикт (кратко):**
|
||||
- **$0-проба парности абзацев (этап A, deepseek→glm-5, 25 гл):** src↔финал **58% точно / 72% в ±1**, агрегат абзацев 0.987; **расхождение рождается на ДРАФТЕ (редактор сохранил число абзацев в 93% чанков), и это ЛЕГИТИМНОЕ слияние/дробление, не тихое вырезание** (границы двух худших чанков целы, объём нормален); объём ru/zh ≈3.0× (в символах; «1.9×» промта — токены). Внешне валидировано: CJK-литература 60.2% 1:1 на предложениях (Bertalign/MAC), структурный текст 85% абзацев (JRC) — наши 58% = норма жанра.
|
||||
- **Гипотеза оркестратора «страница=артефакт, якорить узлы» — CONFIRMED** (все инструменты якорят узел/сегмент, никогда страницу; атом = «бед» Gale-Church = наш чанк). Но расщепляется: потребительские ридеры парят 1:1 по узлу; N:M split-diff + «флаг не-1:1 первыми» — из выравнивателей/InterText. **Синк — КО-ЛОКАЦИЕЙ спаренных якорей (интерлив/общий грид), НЕ свободным скролл-синком двух панелей** (дрейфует на N:M).
|
||||
- **Самое консеквентное — калибровка YELLOW, не якорь.** QE4PE (TACL 2025, 42 профредактора): подсветка ошибок НЕ ускоряет PE и мешает при неточности; **точность флага важнее покрытия.** Google Tricorder (<10% ложных/чекер), alert-fatigue (49–96% игнора) → преимущественно-жёлтая полоса бросается целиком. Замер precision каждого флага — ГЕЙТ перед показом цветов.
|
||||
- **Контракт под фронт целиком выводится из read-model** (`status.go`): цвета = проекция disposition/passport/retrieval_state ($0). Net-new: `annotations.json`-схема, политика красных (editor-facing плейсхолдер / reader-facing fail-closed — D25.1), **human_override** (в D15.2 НЕ спроектирован; аналог CAT lock + PerfectMatch/X-Translate content-keyed carry-over), chat-edit фрагмента.
|
||||
- **Форсировать структуру промптом — НЕТ** (инструкция ненадёжна: gpt-4o-mini сливает вопреки «do not merge»; жёсткость деградирует качество — Karpinska); индустрия конвергировала на **detect-and-recover ФЛАГГЕР** (GalTransl 8 категорий + retranslKey redrive ≈ наш per-flag redrive). Bertalign (MAC F1 0.909, $0 на GTX 1070) — для GOLD-пар канона в eval, НЕ в прод.
|
||||
|
||||
> **[ОРКЕСТРАТОРУ — что ратифицировать]** (1) **Иерархия якорей** глава→чанк(нативный,точный)→абзац(best-effort ~58%)→предложение; **чанк = несущий якорь** (src_range↔dst_range), абзац — мягкий оверлей; синк ко-локацией, не скролл-синком. (2) **Контракт `annotations.json`** (§4.1: per-chunk state/color/reasons/src_range/dst_range/paragraph_anchors + version-хеши snapshot/chunker/source) как экспорт-артефакт пакета №4. (3) **Политика красных:** editor-facing — помеченный плейсхолдер (текущее, честно); **reader-facing fail-closed на красных = якорь release-state D25.1** (structurally_complete требует 0 красных) — ратифицировать при постройке reader-экспорта. (4) **human_override — скоуп в контракт (не полный дизайн):** 2 слоя — provenance LOCK safe-by-default (иммутабелен на redrive/resume) + content/context-keyed carry-over через --resnapshot с ТРЕТЬИМ состоянием «override needs re-review» (YELLOW-конфликт при смене src/контекста, никогда тихо-хранить/тихо-клоббить); НЕ авто-кормить override в TM; полный дизайн — с реализацией D15.2 v3.1 (wire/verdict-split = та же машинерия — синергия D26.4). (5) **Конвенция цвета:** добавить GREY=pending (CAT-конвенция: непереведённое=серое, красное=жёсткий провал); passport-rollup расширить до 3-тир (done+escalated/glossary_miss/style → YELLOW; сегодня «attention» триггерит только на RED). (6) Reader-embedded книго-полоса из детерминированных вердиктов + ru + серия — при скрининге аналогов не найдено (новый синтез; сузить как в research/15, не «аналогов нет»).
|
||||
|
||||
> **[БЭКЕНДУ — требования к экспорту, НЕ код сейчас]** (1) Экспорт `annotations.json` — проекция `chunk_status`+`retrieval_state`+`request_log` ($0, как `status --json`; `tmctl` сегодня не имеет export-команды — параллельный экспорт этапа A был ad-hoc). Поля §4.1; `src_range/dst_range` в нормализованный источник/собранный перевод — чанкер lossless даёт точно. (2) **Цвет-мап детерминирован из УЖЕ существующих полей** (§3.1): RED=flagged-без-dst; YELLOW=done+escalated ∨ glossary_miss ∨ postcheck_misses>0 ∨ style_flags>0; GREEN=чисто; GREY=pending. `flagReasonSeverity()` уже даёт приоритет. (3) **Диалог-аварный флаггер парности абзацев** — класс style-флага (наблюдаемость/YELLOW, НЕ hard-fail: 1:N на диалоге — норма Розенталь §52; описательное слияние — слабее вес); пере-инжектить правки через span-map, не LLM-apply. (4) **passport несёт arity-распределение абзацев** (1:1/1:N/N:1 vs полоса ~60% CJK…85% структурный) — чтобы 58% читалось как норма. (5) **human_override — provenance-слой вне RequestHash** (как post-check: live-recomputed, verdict-нейтрален), ключ по content_hash чанка; проектировать вместе с D15.2 v3.1. Реализация — не сейчас; армит фронт Ф3.
|
||||
|
||||
> **[ПОЛИГОНУ — ТЗ]** (1) **Диалог-аварная пере-нарезка $0-пробы парности** (фальсифицируемо, §5-🧪): классифицировать 53 чанка этапа A на диалог/описание, проверить — концентрируется ли расхождение в (i) легитимно-развернувшихся диалогах и (ii) слияниях; если равномерно — норма-гипотеза неверна. Скрипт-затравка: `scratchpad/parity_probe.py` (переиспользуем; /tmp волатилен — забрать). (2) **Замер precision флаггеров** для калибровки YELLOW (гейт §3.2): per-flag-reason точность против blind-чтения владельца/редактора на срезе; демоут флага <10% истинных в «слабые сигналы». Совместить с exp12 (диагностика уже читает те же главы). (3) **Bertalign zh→ru spot-check** до доверия (нет измеренных zh→ru; всё внешнее — zh→en): ручная сверка на held-out срезе перед использованием для GOLD-пар пилота. Свежие прогоны НЕ требуются — проба сделана на сохранённых выходах этапа A.
|
||||
*(Хроника сессии «Ридер-IDE» (11.07 → research/16, D29) — в [archive/PROGRESS-2026-07-04-10.md](archive/PROGRESS-2026-07-04-10.md), D31.)*
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ v2 (04.07) — после адверсариального ревью синте
|
|||
|
||||
## Фаза 1 — Перевод целой книги (текущая; машинерия в основном построена)
|
||||
|
||||
**Построено** (журнал: PROGRESS, вехи 1–2.5, шаги 3a–4): capability-слой (D3.1) + эхо-мина-гейт DeepSeek; runner-цикл по главам/чанкам + disposition skip/flag/continue (D2, 12 flag_reasons); coverage-гейт (порт Python-оракула, opt-in, precision 0/57 — exp07); single-hop эскалация с ре-гейтом и бюджетом (D12); чанкер v4 + импорт txt/epub + ruby-захват (D9); **банк памяти v2** (нормализация, Aho-Corasick, спойлер-окна, трёхсторонний disposition, decl-aware post-check-флаггер, ruby-сид); монолингвальный редактор с dst-констрейнтами глоссария (D1); snapshotID покрывает память/context-assembly/capability (F1/D5.2/D8).
|
||||
**Построено** (журнал: вехи 1–2.5, шаги 3a–4 — с ревизии D31 в `../archive/PROGRESS-2026-07-04-10.md`): capability-слой (D3.1) + эхо-мина-гейт DeepSeek; runner-цикл по главам/чанкам + disposition skip/flag/continue (D2, 12 flag_reasons); coverage-гейт (порт Python-оракула, opt-in, precision 0/57 — exp07); single-hop эскалация с ре-гейтом и бюджетом (D12); чанкер v4 + импорт txt/epub + ruby-захват (D9); **банк памяти v2** (нормализация, Aho-Corasick, спойлер-окна, трёхсторонний disposition, decl-aware post-check-флаггер, ruby-сид); монолингвальный редактор с dst-констрейнтами глоссария (D1); snapshotID покрывает память/context-assembly/capability (F1/D5.2/D8).
|
||||
|
||||
**Осталось до приёмки Фазы 1:**
|
||||
- Фиксы границ доверия памяти (D16: полисемия, sticky-disposition, source-граница фонетики, ruby-alias) + лгущие комментарии resume + бамп edit `prompt_version` (D15.3).
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
Метод: собственное чтение донорского кода vojo + воркфлоу из 4 критиков (линзы: консистентность доков,
|
||||
исполнимость в Go, сверка с донором построчно, онлайн-фактчек цен/API; ~940k токенов, находки ниже отобраны и объединены).
|
||||
Формат: **подтверждаю** / **правки реализации** (фиксируются здесь, архитектурные доки не трогаю) /
|
||||
**[НУЖНО РЕШЕНИЕ]** (продублировано в PROGRESS).
|
||||
**[НУЖНО РЕШЕНИЕ]** (продублировано в PROGRESS; с ревизии D31 — в `../archive/PROGRESS-2026-07-04-10.md`; все пункты развязаны D-логом).
|
||||
|
||||
## 1. Общий вердикт
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Журнал решений оркестратора — развязки перед Фазой 1 (2026-07-04) + пост-ревью D13–D17, ратификации пакетов и D18–D21 (2026-07-09)
|
||||
|
||||
Ответ на вопросы бэкенд-сессии (PROGRESS §«Вопросы от бэкенда», §«[НУЖНО РЕШЕНИЕ] перед Фазой 1») и полигона (think-режим). Каждое решение прошло адверсариальную панель из 3 критиков (research / экономика / исполнимость в коде Фазы 0); ни одно не отклонено, все уточнены. Это **контракт Фазы 1** — бэкенд исполняет отсюда; при конфликте с буквой 01-decisions/02-mvp-plan — источник истины здесь (потом сольём в основные доки).
|
||||
Ответ на вопросы бэкенд-сессии (PROGRESS §«Вопросы от бэкенда», §«[НУЖНО РЕШЕНИЕ] перед Фазой 1» — с ревизии D31 в `archive/PROGRESS-2026-07-04-10.md`) и полигона (think-режим). Каждое решение прошло адверсариальную панель из 3 критиков (research / экономика / исполнимость в коде Фазы 0); ни одно не отклонено, все уточнены. Это **контракт Фазы 1** — бэкенд исполняет отсюда; при конфликте с буквой 01-decisions/02-mvp-plan — источник истины здесь (потом сольём в основные доки).
|
||||
|
||||
Статусы: ✅ принято · ✅+ принято с уточнением панели.
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ grok-4.3 теперь дефолт-редактор → **каждый чанк
|
|||
|
||||
**Решение:** `reasoning_effort` per-роль, дефолт **off/minimal** для draft/edit — но **по операционным причинам** (эмпирика полигона: GLM ×3 таймауты, Gemini жрёт max_tokens, gpt-5-mini выжигает бюджет — `00-provider-quirks`), НЕ потому что «reasoning вредит переводу».
|
||||
|
||||
**Переписанное обоснование (панель отозвала мою посылку):** прежняя «think ломает роль переводчика — пустой вывод» — **отозванная находка**: PROGRESS:230 исправляет её («пустота — артефакт тесного контекста, не зависание; с ctx 16k think завершается и реально чинит реалии: 羅生門→Радзёмон, чтение 朱雀»). DRT (research/03, arXiv:2412.17498) независимо показывает: long-CoT над метафорами/сравнениями **поднимает литперевод** — это роль ПЕРЕВОДЧИКА. Владелец был прав в гипотезе.
|
||||
**Переписанное обоснование (панель отозвала мою посылку):** прежняя «think ломает роль переводчика — пустой вывод» — **отозванная находка**: запись «Сессия 2 полигона» (04.07, ныне `archive/PROGRESS-2026-07-04-10.md`) исправляет её («пустота — артефакт тесного контекста, не зависание; с ctx 16k think завершается и реально чинит реалии: 羅生門→Радзёмон, чтение 朱雀»). DRT (research/03, arXiv:2412.17498) независимо показывает: long-CoT над метафорами/сравнениями **поднимает литперевод** — это роль ПЕРЕВОДЧИКА. Владелец был прав в гипотезе.
|
||||
|
||||
**Уточнения (обязательны):**
|
||||
1. **Пилот Ф2.5 think-ON vs OFF по качеству включает draft/translator и editor** (не только Terminologist+эскалацию, как я ошибочно сузил) — именно туда указывают и полигон, и DRT. Дефолт-off остаётся до результатов пилота.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Реестр рисков банка памяти (v1, 2026-07-04)
|
||||
|
||||
Выход сессии **«Валидация банка памяти»** (промт `docs/archive/prompts/MEMORY_RESEARCH_SESSION_PROMPT.md`). Это **вход для бэкенд-сессии перед фиксацией схемы store/глоссария Фазы 1** (шаг 4 «миграция памяти v2» держится до этого реестра — PROGRESS §Память, D7).
|
||||
Выход сессии **«Валидация банка памяти»** (промт `docs/archive/prompts/MEMORY_RESEARCH_SESSION_PROMPT.md`). Это **вход для бэкенд-сессии перед фиксацией схемы store/глоссария Фазы 1** (шаг 4 «миграция памяти v2» держится до этого реестра — §Память (с D31 в `../archive/PROGRESS-2026-07-04-10.md`), D7).
|
||||
|
||||
Метод: многоагентный ресёрч по 7 направлениям + независимая адверсариальная верификация каждой находки по первоисточникам + локальный эмпирический бенчмарк retrieval на реальном PD-корпусе (`eval/retrieval_bench.py`, `eval/data/retrieval_bench/`) + чтение реального кода `backend/`. Полный разбор с источниками и датами — `docs/research/13-memory-bank-validation.md`. Продуктовый код здесь не пишется — реестр описывает требования к нему.
|
||||
|
||||
|
|
|
|||
971
docs/archive/PROGRESS-2026-07-04-10.md
Normal file
971
docs/archive/PROGRESS-2026-07-04-10.md
Normal file
|
|
@ -0,0 +1,971 @@
|
|||
# Архив журнала прогресса — закрытая хроника 2026-07-04…10 (вынесено ревизией D31, 12.07)
|
||||
|
||||
> **⚠ Точка-во-времени.** Это закрытые записи журнала `../PROGRESS.md` (день-0, стратревью 09.07, оркестраторские записи 09–10.07, пакеты бэкенда №0–4, сессии полигона 1–3 + 18+, память, голос, ридер-IDE). Ранние записи содержат устаревшие цифры/решения (COGS $2–4, BYOK, Anthropic-Sonnet, монолингвальный редактор, «чистый xAI-ключ»), переопределённые контрактом — **источник истины: `../architecture/05-decisions-log.md` (D1–D30+)**. Заголовки секций сохранены дословно (на них ссылаются комментарии кода и живые доки).
|
||||
|
||||
## Оркестраторская хроника 04–10.07
|
||||
|
||||
## 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 тома ранобэ ~$2–4 при марже 70–96%; главные рычаги — 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` — фазы 0–3 с критериями приёмки.
|
||||
- `architecture/components.puml` + `pipeline.puml` (+ отрендеренные .svg) — провалидированы PlantUML.
|
||||
- `PARALLEL_SESSION_PROMPT.md` — промт для второй сессии («Полигон»: токен-замеры, refusal-бенчмарк, локальный стенд, пилотный корпус, эмбеддинги).
|
||||
- Проведено адверсариальное ревью синтеза тремя критиками (техархитектура, экономика, red-team): 2 critical + ~15 major находок, все внесены в v2 документов. Главные исправления:
|
||||
- экономика разделена на контуры «чей ключ» (прямые ключи / ru-агрегаторы ×2–6 на флагманы / 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 честно сдвинут до 10–11 недель;
|
||||
- baseline метрики качества заменён с «сырой DeepSeek» на «DeepSeek+глоссарий» (уровень VseGPT), порог — статистический;
|
||||
- в план добавлены режим онгоинга и series-bible-lite (сегмент «ИИ-фабрик» и проверка рода/ты-вы).
|
||||
|
||||
### Следующие шаги
|
||||
- [~] Фаза 0 (каркас) ЗАВЕРШЕНА; машинерия Фазы 1 в основном построена — сессия «Бэкенд» (промт: `archive/prompts/BACKEND_SESSION_PROMPT.md`; шаг 0 — перевалидация решений, финал фаз — агентное селфревью). Осталось: полный стек-wiring, автопопуляция глоссария, реальный ja→ru прогон. Оркестратор делает внешнее ревью её кода.
|
||||
- [x] Параллельная сессия «Полигон» запущена (эксперименты 01–03 идут).
|
||||
- [ ] Сессия «Редакция» (промпты ролей) — после фиксации формата конфига в Фазе 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-09 — Стратегическое ревью + консолидация доков (оркестратор)
|
||||
|
||||
- **Стратегическое ревью выполнено** → [`architecture/07-strategic-review.md`](architecture/07-strategic-review.md) (коммит b1d54b6). Метод: 14 сборщиков (8 репо-аудиторов + 6 SOTA-веб) → 9 адверсариальных верификаторов (8 CONFIRMED / 1 PARTIAL; 6 находок воспроизведены исполнением временных Go-тестов). Вердикт: **архитектура end-to-end цела**, наука-2026 подтверждает C1-схему/чанки+гейты/терминологию/DeepSeek-draft; детерминированному пути памяти аналогов не найдено. Топ-находки: D1-моноредактор получил внешне измеренный налог верности (2605.13368, вкл. en→ru); `--resnapshot` = переоплата книги (блокер онгоинга); 4 дыры границ доверия памяти (одна — ложно отсеяна 44-агенткой 0/3); слепота exp04 структурно сломана (ключ в артефакте при оценке); memory_eval контаминирован эхом глоссария; 18+ — ноль замеров (critical); DeepSeek выбыл из explicit-канала B по ToS 27.03.2026.
|
||||
- **Роль оркестратора передана этой сессии (решение владельца 09.07).** Владелец подтвердил курс: Rust-переписывание — НЕТ до пост-пилота (Р1/Go остаётся); архив + онбординг-доки — одобрены.
|
||||
- **Ратифицированы D13–D17** ([05-decisions-log](architecture/05-decisions-log.md)): D13 поправки пилота (арм моно-vs-билингв, гетерогенные кандидаты C2, панель 2–3 семейства × 11+ повторов, починка харнесса ДО прогона); D14 канал B (минус DeepSeek-explicit, плюс проба Mistral, xAI-опора = AUP); D15 resume/онгоинг (комментарии-фиксы + status/redrive сейчас, content-addressed reuse — гейт онгоинга); D16 фиксы границ памяти; D17 D1 понижен до «дефолт Ф1, оспорен — решает пилот».
|
||||
- **Консолидация доков:** `02-mvp-plan` → v3 (мёртвые пороги сняты, интерим-18+ переписан, фазы синхронизированы); обе `*.puml` → v3 (минус Opus/BYOK/«≤2×», плюс ре-гейт эскалации, три класса отказов D12, человек в петле, фазовые пометки); superseded-баннеры на `research/01/02/03/04/09`; провенанс-шапки на два внешних `12-*`-дока; закрытые промты → `docs/archive/prompts/`; онбординг: корневой `CLAUDE.md` + `backend/README.md` + `eval/README.md` + обновлённый `docs/README.md`.
|
||||
- **Хендофф-промты выданы (09.07):** [`BACKEND_SESSION_PROMPT_REVIEW_FIXES.md`](BACKEND_SESSION_PROMPT_REVIEW_FIXES.md) — гигиена (комментарии resume, prompt_version-бамп) → фиксы памяти D16 → `tmctl status`/`redrive` → спека content-addressed resume (D15.2) → reasoning-буфер additive (D13.6) → перепроверка отсевов 44-агентки; [`POLYGON_SESSION_PROMPT_PILOT_HARNESS.md`](POLYGON_SESSION_PROMPT_PILOT_HARNESS.md) — memory_eval (эхо-контроль, полные выходы, fidelity, M0–M3, синк с Go) → гигиена оценочных артефактов → протокол пилота v2 (D13) → проба Mistral (⚠ нужен `MISTRAL_API_KEY` от владельца) → kana-precision → подготовка вебновелл-среза. ⚠ Порядок запуска: бэкенд-сессию первой или одновременно — полигон синкает зеркало памяти с кодом ПОСЛЕ D16-фиксов (в промте оговорено).
|
||||
|
||||
### 2026-07-09 (вечер) — Внешнее ревью и приёмка обоих пакетов (оркестратор)
|
||||
|
||||
- **Оба пакета приняты и залендены** (backend 153277e, eval 9afea37) после внешнего ревью (7 ревьюеров, всё исполнением: CLI-прогоны на моках $0, мутационные реверты в scratchpad-копии, пересчёт данных из raw). Вердикты: backend-d16 / backend-ops / spec-d15 / eval-harness / eval-protocol — ACCEPT_WITH_FIXES; backend-misc / координация — ACCEPT. Самоотчёты обеих сессий соответствуют диффам; заявленные цифры полигона воспроизведены точно (M0 0.567/94.6 · M1 1.0/93.4 · M2 1.0/93.4 · M3 0.467/49.0, echo 0/5; kana-таблица байт-в-байт; вебновелл-эхо 4/16 подтверждено по сырым выходам).
|
||||
- **Ратификации** → полный текст в [`05-decisions-log.md`](architecture/05-decisions-log.md) §«Ратификации 09.07»: (1) kana/Han-исключение из source-границы (D16.3) — ратифицировано, kana-омографы → B6, MIN=3 — дефолт; (2) **спека D15.2: направление да, реализация заблокирована** — 3 дизайн-дыры (fast-path-гард слабее текущего; расщепление memory_version обязательно; замена consent-гейта); (3) Mistral: refusal принят, fidelity-числа НЕ приняты (нет сырых артефактов — переснять с персистом); (4) Pearmut-отказ ратифицирован.
|
||||
- **Fix-листы след. пакетов** (в D-логе §Ратификации, пп.5–6): бэкенду — homophone first-wins (major), GB18030-ingest, мутационное закрепление redrive-инварианта, snapshot-чек до ResetChunkStages + minors; полигону — дозеркалить suppressUnboundedPhonetic и апостроф-фолд (критично для en→ru руки), эхо-детектор хвоста, Mistral-переснятие + minors.
|
||||
- Гигиена: `*.key.json` в .gitignore; **правило git-координации мультисессий** внесено в CLAUDE.md (признание инцидента: перезапись истории оркестратором 09.07 при грязном дереве полигона стёрла его незакоммиченные правки — восстановлены сессией).
|
||||
- **Ждём от владельца (без изменений):** explicit-18+ фрагменты (последний critical-блокер D14.4), приёмочная ja→ru книга (epub) для прогона D9, провенанс двух внешних 12-*-доков; решение по юр-пакету (EU-хостинг/провайдер-матрица данных/compliance-паспорт — обсуждено 09.07).
|
||||
|
||||
### 2026-07-09 (поздний вечер) — D18 + промты пакетов №2 (оркестратор)
|
||||
|
||||
- **D18 ратифицирован (решение владельца):** приёмка Фазы 1 — на **蛊真人 zh→ru** (полная книга ~2.5k глав от владельца лежит на стенде: `/home/ubuntu/books/gu-zhenren/guzhenren-gb18030.txt`, GB18030+CRLF — проверено декодом; текст и производные ВНЕ git); ja→ru — второй прогон при появлении ja-epub (форсирующая функция D9 по ruby уже выполнена кодом). Полный текст — D-лог D18.
|
||||
- **18+ блокер снят владельцем:** explicit-фрагменты берутся из 蛊真人 (dark/violence; покрытие l2-erotica полигон оценит честно — возможно понадобится второй источник).
|
||||
- **Хендофф-промты №2 выданы** (старые закрыты → archive): [`BACKEND_SESSION_PROMPT_ACCEPTANCE_PREP.md`](BACKEND_SESSION_PROMPT_ACCEPTANCE_PREP.md) — fix-лист ревью (homophone first-wins и др.) → GB18030-ingest → дешёвые гейты Ф1 → спека D15.2 v2 → smoke-прогон 1 главы 蛊真人; [`POLYGON_SESSION_PROMPT_EXPLICIT_AND_MIRROR.md`](POLYGON_SESSION_PROMPT_EXPLICIT_AND_MIRROR.md) — синк зеркала (suppressUnboundedPhonetic+апостроф) → Mistral-переснятие → **18+ рука на 蛊真人 (эксп.10)** → сид-глоссарий приёмки → терсный precision. Координация: бэкенд-задача 2 (GB18030) гейтит их же задачу 5 и полигонный отбор сцен удобнее после неё, но полигон может стартовать параллельно (iconv руками уже валидирован).
|
||||
- Юр-пакет — в бэклоге до решения владельца (промт ресёрч-сессии подготовлю по запросу).
|
||||
- **Передача роли оркестратора (09.07 ночь, решение владельца — контекст сессии заполнился):** выдан [`ORCHESTRATOR_SESSION_PROMPT.md`](ORCHESTRATOR_SESSION_PROMPT.md) — преемник наследует зону docs/, методологию внешнего ревью (адверсариальные воркфлоу исполнением), право ратификации D-блоками и очередь: ревью research/15 по отчёту → приёмка полигона-erotica → промт бэкенд-пакета №3 (fix-лист D20.4 + D15.2 v3 + D3-цепочка) → промт приёмочной сессии Ф1. Параллельно выдан [`POLYGON_SESSION_PROMPT_EROTICA.md`](POLYGON_SESSION_PROMPT_EROTICA.md) (ja-книга владельца + 金瓶梅 + Fifty Shades → l2-erotica по трём парам, конвейер exp10, fix-лист D19.5, финализация сида gender=hidden) — закрывает D14.4. Промты пакетов №2 → архив.
|
||||
- **Бэкенд-пакет №2 принят и залендён (b51ac4c) после внешнего ревью** (5 ревьюеров исполнением/мутациями; smoke-деньги сверены по БД до микроцента; заглушка D19.6 подтверждённо убрана и мутационно защищена). **Ратифицирован D20**: спека D15.2 — направление принято, реализация после двух v3-правок (role в guard_hash; правило editor-каскада в dry-run-проекции); ответы §13 (пер-стадийная гранулярность wire-снапшота; `--accept-rebill[=usd]` c порогом min($0.50, 5%); Adult нейтрален + конфиг-линт); **приёмка Ф1 допустима на glm-5-редакторе; пилот требует боевой grok-4.3 → чистый xAI-ключ = блокер пилота, не приёмки**; fix-лист №3 (README v7, cheap-gates v2 против 3 FP, NUL-гард на не-UTF8 путях декода, minors). До полной приёмки на 蛊真人: финализация сида (gender=hidden — одно поле, полигон), заводка D3-цепочки, приёмочная сессия. ⚠ В дереве черновик `research/15-voice-and-state.md` (сессия «Голос и состояние» в полёте) — не трогать до её отчёта.
|
||||
- **Полигон-пакет №2 принят и залендён (3d183bc) после внешнего ревью** (4 ревьюера исполнением: mirror ACCEPT; explicit/seed/coord ACCEPT_WITH_FIXES — все фактические микро-дефекты доков исправлены оркестратором при лендинге). **Ратифицирован D19**: канал B v2 (Mistral-переводчик / grok-4.3 reasoning-ON эскалация / abliterated-скрининг / судьи Grok+Gemini), эхо-класс «reasoning-off + плотный CJK» обобщён, сид-развязки (перевод имён гу; «Гуюэ» слитно; 白凝冰 → gender=hidden), гигиена xAI пост-фактум + выделенный NSFW-ключ до пилота. Остаток D14.4: **только erotica-источник от владельца**. ⚠ Срочный пинг бэкенду в D19 п.6 (заглушка contested() в их незакоммиченном memseed.go).
|
||||
- **Промт ресёрч-сессии «Голос и состояние» выдан** (запрос владельца 09.07): [`VOICE_STATE_RESEARCH_SESSION_PROMPT.md`](VOICE_STATE_RESEARCH_SESSION_PROMPT.md) → `research/15-voice-and-state.md`. Мандат: голоса персонажей (voice exemplars vs дескрипторы — проверить клейм antipattern-дока; RP/game-loc прайор-арт; дешёвый детектор отклонения), scene/epistemic-state инъекция + скоуп Annotator Ф2, валидированный промптинг литперевода (формат/позиция инъекций, анти-галлюцинационные приёмы, «двухпроходность в одном вызове»), параметры запроса (temp-свип как ТЗ полигону), прайор-арт-проверка наших «уникальных» механизмов (спойлер-окна и др.), креатив с обязательной привязкой к слотам архитектуры. Пробы ≤$3 на SFW-чанках 蛊真人. Выход приземляется к Фазе 2 (Annotator, voice-профили) и в армы пилота. Параллелится с пакетами №2, ничего не блокирует.
|
||||
|
||||
### 2026-07-09 (ночь) — Приёмка research/15 «Голос и состояние» + D21 (оркестратор-преемник)
|
||||
|
||||
- **Роль принята** по `ORCHESTRATOR_SESSION_PROMPT.md`; онбординг по порядку промта; артефакты проб ресёрч-сессии продублированы из волатильного /tmp в `/home/ubuntu/books/gu-zhenren/research15-probes/` (вне git).
|
||||
- **Внешнее ревью research/15 выполнено** (9 агентов: 5 спот-чеков первоисточников — кандидаты из самоотчёта сессии, пересчёт проб из сырья, консистентность, red-team ратификации, аудит доков). Вердикт **ACCEPT_WITH_FIXES → залендён (5953b37)**: DelTA — CONFIRMED точно; RoleLLM/Voita/similarity/WMT25 — CONFIRMED_WITH_NUANCE (нюансы вписаны пометками *(ревью)*); P4/P1/P3/бюджет пересчитаны поштучно — сходятся; микро-дефекты счёта исправлены оркестратором (0/26→0/29; «~35%»→«30–67% по армам»; deepseek-эха rt 111/182/149; пятый судья gemini-2.5-flash; строгий маркер-пересчёт 0/4→2/4→3/4→4/4 — порядок армов устойчив).
|
||||
- **Ратифицирован D21** ([05-decisions-log](architecture/05-decisions-log.md)): voice-профиль (Ф2, с оговорками: заморозка per-job до D15.2, приоритет/кап бюджета инъекции, brightness — гипотеза-под-пилот, editor-слот не исключён, курация сида владельцем + кросс-семейный судья); address_pair = материализация журнала D7 (флаггер безусловно, инъекция — после пробы на трудных парах); reveal-окна (переобоснованы без 12-common); армы пилота с тирингом (минус двухпроходность/min_p); скоуп Annotator Ф2 с честным ресурсом голда; **анти-эхо wiring гейтится fidelity-хвостом P4 (35 пар) и только для deepseek-драфта**; клеймы уникальности сужены (скрининг ≠ FTO); exp08 v3 заказан.
|
||||
- **Аудит доков «что упустили»**: найдено и исправлено — CURRENT-STATE/README/CLAUDE.md отставали на два цикла (D18–D20, канал B v2, 7 ключей); quirks-строка «editor/translator ВСЕГДА reasoning:none» противоречила D19.1 (сужена до редактора); поручение D19.2 «обобщающая строка эхо-класса в quirks» не выполнено — включено в D21.9, чтобы не потерялось; backend/eval README-хвосты обновлены.
|
||||
- **Live-фактчек Gemini (вопрос владельца, 09.07):** /models-листинг живьём — 2.5-flash / 3.5-flash / 3.1-flash-lite все числятся; офиц. deprecations-страница — **вся 2.5-серия shutdown 16.10.2026** (замены 3.1-pro-preview / 3.5-flash / 3.1-flash-lite) → миграция судьи memory_eval оправдана вдвойне (флейки + EOL); интермиттентный 404 вендором НЕ документирован (наблюдение проб = аномалия, слаг в списке); `PROHIBITED_CONTENT` — неконфигурируемый фильтр-класс (safety_settings не влияют, в отличие от SAFETY). Вписано в quirks-календарь и erotica-промт.
|
||||
- **Erotica-промт обновлён ДО запуска** (уточнение владельца: сессия ещё не стартовала — пинги вшиты в файл, пересказ не нужен): Gemini-грабли судей (404-флейки gemini-2.5-flash при наличии в /models; ожившая `content_filter: PROHIBITED_CONTENT`-ветка на Gemini 3.x — логировать finish_reason первоклассно), пункт (е) в Task 3 — quirks-строка эхо-класса D19.2 + инверсия языкового констрейнта, и опциональная Задача 5 — fidelity-хвост P4 (35 выходов из `research15-probes/`, деблокирует анти-эхо wiring D21.6; приёмку сессии не гейтит).
|
||||
|
||||
### 2026-07-10 — Правило вендор-сверки аномалий (решение владельца, оркестратор)
|
||||
|
||||
Разбор Gemini-кейса: интерпретация 404-флейков ушла в промт без вендор-сверки, потому что урок «проверяй пробой» был записан только в направлении «клейм → проба», а сигнал ревью-аудитора «404-записи неверифицируемы» оркестратор не эскалировал. **Зафиксировано правило двух направлений** (шапка `00-provider-quirks.md` + гардрейл CLAUDE.md + правило №7 eval/README): wire-аномалия (флейки, 404 живой модели, новый finish_reason, игнор параметров) → СНАЧАЛА официальная дока вендора (deprecations/changelog/status) + свежий /models, ПОТОМ диагноз; интерпретацию без вендор-сверки в доки/промты не абсорбировать.
|
||||
|
||||
### 2026-07-10 — Видение фронта Ф3 + промт ресёрча «Ридер-IDE» (оркестратор)
|
||||
|
||||
- **Владелец детализировал план фронта** (VS Code-паттерн): дерево глав · две панели оригинал|перевод · панель команд/чат-редактирования · цветная статус-полоса с ползунком (зелёный/жёлтый/красный из детерминированных вердиктов). Открытые вопросы: якорение соответствия (не «страница в страницу»), UX редакторов, прайор-арт конкурентов.
|
||||
- **Оценка влияния на бэкенд (оркестратор):** read-model уже есть (chunk_status/паспорта/вердикты — D12 строил `--json` «для CI/IDE»); новая работа мала и read-only: персист/экспорт якорей чанков, `annotations.json`, сборка перевода с политикой красных чанков, возможно дешёвый флаггер абзацной парности. Контрактно-опасен один кусок — **human_override** (пост-правка человека против redrive/resume/TM — пересечение со snapshot-дисциплиной, думать вместе с D15.2). Веб-сервер/SSE НЕ строим (Ф3, D12-caution в силе). Кандидат-скоуп бэкенд-пакета №4 — после ресёрча.
|
||||
- **Выдан промт** [`READER_IDE_RESEARCH_SESSION_PROMPT.md`](READER_IDE_RESEARCH_SESSION_PROMPT.md) → `research/16-reader-ide-alignment.md`: прайор-арт HITL-редактуры (CAT/Mantra/фан-стек/PE-исследования), якорение (гипотеза «чанк/абзац, страницы виртуальны»), визуализация доверия, контракт бэкенд→фронт; $0-проба парности абзацев на сохранённых выходах. Живые LLM-вызовы: $0.
|
||||
|
||||
### 2026-07-10 — Приёмка пакетов «бэкенд №3» и «полигон-erotica» + D22 (оркестратор)
|
||||
|
||||
- **Внешнее ревью обоих пакетов** (8 ревьюеров, всё исполнением: go test/race + 11 мутаций в scratchpad-копии; exp11 пересчитан из сырья поштучно независимой репликой классификатора — 15/15 ячеек и все судейские числа сошлись; Fisher-статистика клеймов; цены по вендор-страницам). **Оба ACCEPT_WITH_FIXES → залендены (e1fcee4, 3551997), ратифицирован D22.**
|
||||
- **Топ-находки ревью:** (1) спека v3 на оси SourceLang/TargetLang была СЛАБЕЕ текущей защиты (исполненный stale-hit) → два обязательных v3.1-амендмента до реализации; (2) дублёра-судью 18+ ратифицировать нельзя (gpt-5-mini не мерен; D13.3-коллизия: grok-эскалированные 18+ чанки без померенного судьи) → проба-гейт; (3) register-клейм сужен до «архаика ломает МИТИГАЦИЮ reasoning-ON» (p=0.008 vs совр. zh; «регистр» = гипотеза до контрольных ячеек); (4) кодовая ветка content-filter полигона мертва на фактическом составном wire-формате (счёт отчёта верен через ручной finish_reason); (5) ja/en-fidelity сняты под zh-рамкой судейского промпта — индикатив; (6) полигон случайно стёр заголовок чужой записи в журнале — восстановлен; правило transient-прогонов в чужой зоне кодифицировано (D22.10).
|
||||
- **D3-текст исправлен** (`gemini-3.1-pro-preview`; голый слаг 404 — квирк 04.07, синк живых доков perl-grep'ом); цена Mistral $0.5/$1.5 закрыта тройной сходимостью; квирк-строки (register-оговорка, additive_total) дописаны.
|
||||
- **Промты выданы (по заданию владельца):** [`GPT_EXTERNAL_ASCENT_PROMPT.md`](GPT_EXTERNAL_ASCENT_PROMPT.md) (внешняя критика GPT-5.6, анти-якорный трёхфазный протокол) и [`BACKEND_SESSION_PROMPT_REFACTOR.md`](BACKEND_SESSION_PROMPT_REFACTOR.md) (пакет №4: код-хелс + golden-гард детерминизма). Закрытые промты №3/erotica — в архив.
|
||||
- **Приёмка Ф1 разблокирована полностью** (D22.11): следующий деливерабл оркестратора — промт приёмочной сессии.
|
||||
|
||||
### 2026-07-10 (вечер) — Приёмка рефакторинг-пакета №4 + D23 (оркестратор)
|
||||
|
||||
- **Внешнее ревью** (5 ревьюеров, всё исполнением): эквивалентность «форма, не поведение» доказана трижды независимо — новый golden на ЧИСТОМ HEAD-коде PASS байт-в-байт; чувствительность golden 5/5 мутаций; AST-дифф 36 деклараций (0 потеряно, 7 изменены только заявленно); CLI байт-идентичен исполнением двух бинарей; 9/9 мутаций инвариантов убиты; миграции/промпты/конфиги sha256-нетронуты. Вердикты ACCEPT ×2 + ACCEPT_WITH_FIXES ×3 → **залендён (296419c), ратифицирован D23** (golden-гард = инвариант №8; OpenReadOnly санкционирован с трейд-оффом reserved-хвоста; fix-лист мелочи — с реализационным пакетом D15.2).
|
||||
- Микро-фиксы оркестратора: diffstat +3317, фикстура 4гл/11 тел, оговорка про тест-непокрытые лог-фиксы; line-refs старого runner.go починены в 06/07/research-13 (историю не переписывал); backend/README техдолг-строка синкнута с D22.
|
||||
- **Промт приёмки Ф1 выдан** (`ACCEPTANCE_SESSION_PROMPT.md`); GPT-восхождение деблокировано (условие владельца «после рефакторинга» выполнено). Оба запуска + ридер-IDE ресёрч — параллельны и независимы.
|
||||
|
||||
|
||||
## Бэкенд (закрытая хроника: сессии 1–5, вехи 1–2.5, шаги 3a–4, пакеты №1–4)
|
||||
|
||||
### 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 30–44%); в транспорте донора скрытый захардкоженный 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).
|
||||
|
||||
**РЕШЕНО** (04.07) → ответ оркестратора ниже + ратифицировано в [05-decisions-log](architecture/05-decisions-log.md) (D1–D7); детали в 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 в Фазу 1–2; в Фазе 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-стриминг в Фазу 1–2 (без SSE-фронта), зафиксировано в плане; в Фазе 0 — длинные per-роль таймауты.
|
||||
> 5. **Р5 обновлён** сноской на токен-калибровку (×1.4–1.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`
|
||||
гоняет чанк 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](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_ttl↔cache_write под один TTL (5m);
|
||||
гонка `Runner.clients` (безопасна при последовательном проходе, мьютекс — к fan-out Фазы 1–2).
|
||||
|
||||
**Ключи: бэкенд заводится на ДВУХ ключах** (`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 отметил
|
||||
«уровень L0–L1 можно добавить отдельным конфигом для проверки стерильного канала». Можно ли прогнать
|
||||
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-недоучёта уточнена — до `MaxAttempts−1`, не «≤1»; честный фикс —
|
||||
idempotency-ключ, отложено). Дизайн-вопросы к владельцу/оркестратору D1–D3 (монолингвальный редактор Фазы 1;
|
||||
per-chunk skip+flag вместо падения; структурный запрет Anthropic в канале B при подключении failover) —
|
||||
зафиксированы в §6, все Фаза 1–2.
|
||||
|
||||
Следующее: Фаза 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 латентность штатная (5–8 с,
|
||||
без ×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 знаков (`(453−384)·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 (Ф1–2), инъекция глоссария (`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/archive/prompts/MEMORY_RESEARCH_SESSION_PROMPT.md`, финализирован); её выход — `architecture/06-memory-risk-registry.md` — вход, по которому ты фиксируешь схему store/глоссария. Шаги 1–3 (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 D8–D11](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.4–1.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 доп. вызов, не MaxAttempts−1) + консервативный 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 под шаги 6–7). Единый `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, перевода нет». Провалидировал **трассировкой** capability→wire (не грепом):
|
||||
|
||||
**Состояние детекта (после Вехи 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 эхать нечего.)
|
||||
|
||||
**Архитектурные ответы (Q1–Q3):**
|
||||
- **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](archive/prompts/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.4–1.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/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+001C–001F → `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).
|
||||
|
||||
### 2026-07-05 — Шаг 3a: настоящий чанкер + импорт txt/epub + ruby-захват
|
||||
|
||||
Снят плейсхолдер-чанкер: книга (D9 ja→ru ранобэ epub) гоняется end-to-end на настоящих границах. Всё зелёное `go build/vet/test -race`, `tmctl report` $0, живые LLM не звались (моки + $0-report). Три части + селфревью с фиксами.
|
||||
|
||||
**A. Настоящий сорс-чанкер (`chunker.go`).** `SplitChunks(source string)`→`SplitChunks(chapters []string)` (ingest уже режет главы). Паковка **по границам предложений/абзацев** в **коридор ~1–2k токенов** (`targetChunkTokens=1500`, **const покрыт `chunkerVersion`**, не конфиг — Р2=код; если станет конфигом — обязателен snapshot-fold как `coverageSnap`, §7d). Отдельный сорс-сплиттер `splitSourceSentences` (zh/ja/en): CJK zero-width `。!?`, **quote-depth** (терминатор внутри `「…!」と…。` — НЕ конец предложения, диалоговый кейс §3.7/D12-Q1), эллипсис `…`, абсорбция закрывающих скобок, guard аббревиатур/инициалов, **lossless-тайлинг** (конкатенация сегментов = исходный абзац, текст не теряется/не сдвигается). **Никогда не режет предложение**; абзац>цели → дробится по предложениям, предложение>цели → свой чанк. **ОТДЕЛЬН от coverage-`splitSentences`** (тот Python-locked по РУССКОМУ ВЫХОДУ; этот — по ИСХОДНИКУ, `chunkerVersion`-versioned). `chunkerVersion` бампнут `v2-ff-para-pack`→**`v3-sentence-pack`** (в snapshot → перечанкование = громкий `--resnapshot`).
|
||||
|
||||
**B. Импорт txt/epub (`ingest.go`, новый).** `Ingest(path)→*Document{Chapters []string, Ruby []RubyReading}`, диспетчер по расширению. **txt:** главы по `\f` (обратная совместимость example), `NormalizeSource` каждой. **epub — чисто stdlib** (CGO-free, без новых зависимостей): `archive/zip`→`container.xml`→OPF→**spine-порядок**→`encoding/xml` (`Strict=false`, `HTMLEntity`, `HTMLAutoClose`)→стрип тегов, скип `head/script/style`, block-теги→абзацные разрывы. Битый/пустой/чужой epub — **fail-loud, не паника** (нет container/opf/spine, dangling idref, не-zip). epub v1 = текст по spine, инлайн-разметка не сохраняется (осознанно, 02-mvp:25). Раннер: `os.ReadFile+NormalizeSource+SplitChunks` → `Ingest→SplitChunks(doc.Chapters)→persistRuby` (минимальный след, шов цикла цел; `ch.Text` в 3 местах не тронут).
|
||||
|
||||
**C. Ruby-захват + персист (`store/ruby.go`, миграция v4).** `<ruby>base<rt>reading</rt></ruby>` → **base в тело, reading захвачен, `<rp>` скобки-фолбэк дропнуты**, mono-ruby склеен. Персист в **v4 `ruby_readings(book_id, base, reading, first_chapter, occurrences)`** (PK `(book_id,base,reading)` — вариантные чтения = разные строки). **Идемпотентный upsert:** `persistRuby` агрегирует по всей книге раз на инжест → оба поля **REPLACE** (ре-инжест того же источника = те же строки, правка источника = сходится к правде). **НЕ инъектится в промпт** (§7d, память v2 + детерминизм-load-bearing) → не в snapshot/`request_hash`. Память v2 (шаг 4) потребит → глоссарий-лок имён (D9).
|
||||
|
||||
**Селфревью (адверсариальный Workflow: 5 дименсий → находки → независимая CONFIRMED/REFUTED-верификация с конкретным сценарием инпут→неверный-выход).** Сам нашёл до ревью 1 баг (dense-numbering, ниже). Ревью: 9 находок, 4 подтверждены (≥1 верификатором), **все 4 исправлены + регресс-тесты мутационно-проверены** (реверт → падает именно его тест):
|
||||
1. *[dense-numbering, до ревью]* ruby.Chapter брал spine-read-index, а `SplitChunks` нумерует главы **плотно** (пустые cover/nav скипаются) → `first_chapter` расходился с осью глав раннера (сдвиг `since_ch` памяти v2). Фикс: ingest нумерует тем же плотным правилом.
|
||||
2. *[segmentation]* паковка **суммировала per-unit `EstimateTokens`** (флор 16 на каждый абзац/предложение) → глава из коротких реплик дробилась в суб-500-симв. чанки, которые coverage-гейт молча скипает. Фикс: аддитивный подсчёт классов символов, флор-16 **один раз на весь чанк** (= `EstimateTokens` от склейки).
|
||||
3. *[epub]* `isXHTML` фолбэк на расширение только при ПУСТОМ media-type → глава с `application/xml`/`text/xml`/`…; charset=utf-8` молча терялась (реальные epub так мислейблят). Фикс: стрип параметров + фолбэк на расширение при ЛЮБОМ нераспознанном типе.
|
||||
4. *[epub]* форматирующий whitespace МЕЖДУ base-сегментами ruby (pretty-printed jukugo `<rb>`) тёк в base (мис-ключ глоссария) и в `ch.Text`. Фикс: whitespace-only CharData внутри ruby-base дропается.
|
||||
5. *[ruby-persist]* `first_chapter` был MIN-merge, `occurrences` — REPLACE (асимметрия): после правки источника, сдвигающей первое появление позже, `first_chapter` застревал на устаревшей ранней главе. Фикс: оба REPLACE (агрегат `persistRuby` — авторитетный full-book).
|
||||
|
||||
**Отклонено (обоснованно, оба верификатора REFUTED):** голый `<` в прозе валит весь epub — это **корректный fail-loud** на невалидном xhtml (альтернатива = тихая потеря главы, против инварианта); zip-bomb LimitReader — вне threat-model MVP (оператор-файл), в докстринг как future-hardening. Dense-numbering-находка ревью REFUTED — потому что уже был исправлен (верификаторы читали пофикшенный код).
|
||||
|
||||
**Границы/техдолг (не блокеры):** чанк <500 симв. молча выключает excision-гейт — **документированная граница §7b** (после фикса #2 случается только на реально-крошечной главе/хвосте); overlap-инъекция и ruby→глоссарий-лок отложены (§3, ждут msgs-поверхности памяти v2 — строим один раз); epub v1 не сохраняет инлайн-разметку; zip-bomb hardening — future. Форму `ruby_readings` согласовать с памятью v2 при шаге 4 (контракт: base→dst через reading, first_chapter→since_ch, occurrences=confidence). Тесты: чанкер (сегментация/паковка/детерминизм/аббревиатуры/quote-depth), ingest (txt/epub/spine-порядок/entity/ruby/битый-epub/dense-numbering/media-types), ruby-persist (идемпотентность+сходимость), e2e мульти-глава epub→чанки→мок-перевод→resume $0.
|
||||
|
||||
> **Внешнее ревью оркестратора Шага 3a (05.07): ПРИНЯТО, 0 живых блокеров, 7 подтверждённых находок (1 отсеяна).** Независимый воркфлоу — **агенты гоняли реальный код** (пробы в пакете), не утверждали. Money/детерминизм я подтвердил чтением сам. Тема: **тихая потеря главы/контента** — ровно тот класс, ради которого продукт есть. Ранг по важности:
|
||||
> 1. **[major] Тихая потеря главы на dangling spine idref** (ingest.go:168-201). idref-опечатка, орфанящая главу, молча скипается через `continue`; ошибки нет, пока читается хоть одна другая глава (`read>0`). **Противоречит СОБСТВЕННОМУ контракту** (PROGRESS:400 перечисляет dangling idref среди fail-loud; :402 инвариант «тихая потеря главы, против инварианта»). Прогон: manifest=[c1,c2,c3], spine=[c1,ghost,c3] → главы=[c1,c3], c2 потеряна, **и `since_ch` всего хвоста книги сдвинут** (ruby c3 штампуется chapter=2). Асимметрия: пропавший zip-файл фатален, пропавший manifest-id молчит. Фикс: собрать неразрешённые idref → loud-ошибка (как для zip-entry). **Топ-приоритет.**
|
||||
> 2. **[major] Тихая потеря главы на `application/xml`+`.xml`** (ingest.go:212-226). Тот же класс: контент-док, мислейбленный `application/xml`/`text/xml` С расширением `.xml`, промахивается мимо и type-switch, и extension-фолбэка (знает только .xhtml/.html/.htm) → молча скип + dense-renumber сдвигает `since_ch`. (Селфревью-фикс #3 закрыл ПУСТОЙ media-type, но не generic+`.xml`.) Фикс: при generic XML MIME распознавать `.xml` как контент. **Чинить вместе с #1.** → Системный фикс обоих: **spine-reconciliation** — сверять число контент-spine-items с реально прочитанными главами, расхождение = fail-loud.
|
||||
> 3. **[major] Size-зависимая порча invalid-UTF-8 → U+FFFD** (chunker.go:220). Oversize-путь round-trip `[]rune(paragraph)` заменяет невалидный байт на U+FFFD, а нормальный путь (короткий абзац, `strings.Join`) сохраняет сырые байты. Тот же source-байт цел в коротком абзаце, испорчен в длинном — нарушение losslessness + size-зависимая несогласованность; течёт в `{{text}}` и `request_hash`. Триггер: mostly-UTF-8 файл со стрей/обрезанными байтами (txt без charset-guard). Прогон: `abc\xe9def` короткий → байты целы, oversize → `abc\xef\xbf\xbddef`. Фикс: нормализовать invalid-UTF-8 ОДИН раз в `NormalizeSource` (fail-loud или документированная замена, покрыто `chunkerVersion`).
|
||||
> **Minor:**
|
||||
> 4. **[minor] ASCII/эллипсис-граница игнорирует quote-depth** (chunker.go:263-273). Depth-подсистема читается только в CJK-ветке; ASCII-ветка (`.!?…`) депт не проверяет → терминатор внутри трекнутой кавычки over-splits (запретное направление). Прогон: `「Stop. Now.」` → 2 сегмента (CJK-твин → 1). Проявляется в oversize-абзаце (режет диалог через границу чанка). Фикс: гейтить ASCII-границу на `depthHere==0` тоже (straight-quote англ. кейс не регрессит — проверено).
|
||||
> 5. **[minor] `<br>` внутри `<ruby>`** (ingest.go:326-327) не гардится `rubyDepth==0` (в отличие от block-тегов) → `\n` между base-глифами, обходит whitespace-collapse фикс #4; base и body расходятся. Whitespace-only, детерминизм цел. Фикс: гард `rubyDepth==0`.
|
||||
> 6. **[minor] ruby phantom-строки** (ruby.go, нет delete). Пара, УБРАННАЯ правкой источника, навсегда остаётся фантомом (upsert-only, нет delete-by-book). Латентно (память v2 не приземлена, capture-only, ноль текущего impact), но памяти v2 навесит name-lock на имя, которого в книге нет. **Фикс совмещается с шагом 4:** `DELETE FROM ruby_readings WHERE book_id=?` перед bulk-upsert (полная замена агрегата — тогда «сходится к правде» верно и для удалений). Связано с ruby-контрактом в `architecture/06`.
|
||||
> 7. **[minor] нет fuzz/property-теста tiling** (chunker_test.go). Единственный losslessness-тест — 6 ручных valid-UTF-8 инпутов; `Join(split(x))==x` над рандомом (вкл. invalid-UTF-8, вложенные/несбалансир. кавычки) поймал бы #3. Фикс: Go fuzz / testing/quick property + chunk-level losslessness (Σ не-пробел чанков == Σ не-пробел источника).
|
||||
> **Отсеяна: 1** (oversize-хвост <500 симв. — механизм подтверждён, но это документированная граница §7b, не баг; верификатор REFUTED).
|
||||
>
|
||||
> **Приоритет фикса:** #1+#2 (тихая потеря главы, системно через spine-reconciliation) → #3 (losslessness UTF-8) → #7 (fuzz-тест, поймал бы #3) → #4 (quote-depth ASCII) → #5/#6 (мелочь, #6 — с шагом 4). Ничего не горит на боевом (все триггеры — битый/мислейбленный epub или invalid-UTF-8), но #1/#2 — именно тот тихий-потери класс, где мы обязаны быть fail-loud.
|
||||
|
||||
### 2026-07-05 — Шаг 3a: закрытие 7 находок внешнего ревью (все, в приоритете оркестратора)
|
||||
|
||||
Все 7 закрыты в этой же сессии (автор с контекстом — дешевле, чем перезагружать свежую), каждый фикс **мутационно-проверен** (сломай — падает именно его тест) + три fuzz-таргета прогнаны ~200k+ рандом-инпутов live. Всё зелёное `go build/vet/test -race`, `tmctl report` $0. `chunkerVersion` бампнут `v3-sentence-pack`→**`v4-utf8-quotedepth`** (правки нормализации/сегментации/инжеста = осознанная инвалидация, `--resnapshot`).
|
||||
|
||||
**Major (тихая потеря главы/контента):**
|
||||
- **#1+#2 — spine-reconciliation (`ingest.go`).** Dangling spine idref (опечатка, орфанящая главу) больше НЕ скипается тихо: собираются все неразрешённые idref → **fail-loud** (как пропавший zip-entry) — иначе терялась глава И сдвигался `since_ch` всего хвоста. `isXHTML` расширен: generic-XML MIME (`application/xml`/`text/xml`) + расширение `.xml` распознаются как контент (мислейбленная `.xml`-глава больше не исчезает). Не-контент-ассеты в spine (image/css) по-прежнему легитимно скипаются.
|
||||
- **#3 — invalid-UTF-8 в `NormalizeSource` (`render.go`).** `strings.ToValidUTF8(…, U+FFFD)` ОДИН раз в нормализации → чанкер больше не расходится с собой ([]rune-путь по предложениям vs строковый по абзацам молча по-разному трактовали стрей-байт — size-зависимая порча в `{{text}}`/`request_hash`). `FuzzNormalizeSourceValidUTF8` гарантирует валидный UTF-8 на выходе.
|
||||
|
||||
**Minor:**
|
||||
- **#4 — quote-depth в ASCII-ветке (`chunker.go`).** ASCII/эллипсис-граница теперь тоже гейтится `depthHere==0` → `「Stop. Now.」` не over-splitится (straight-quote англ. не регрессит — untracked, depth 0).
|
||||
- **#5 — `<br>` внутри `<ruby>` (`ingest.go`)** гардится `rubyDepth==0` → `\n` больше не течёт между base-глифами.
|
||||
- **#6 — ruby phantom-строки (`ruby.go`/`persistRuby`).** `UpsertRubyReading`→**`ReplaceRubyReadings`** (DELETE-by-book + INSERT в одной tx): полная замена агрегата → пара, убранная правкой источника, исчезает, а не остаётся фантомом; `persistRuby` зовётся безусловно (пустой набор чистит книгу). «Сходится к правде» теперь верно и для удалений — контракт под память v2.
|
||||
- **#7 — fuzz/property tiling (`chunker_test.go`).** `FuzzSplitSourceSentencesTiles` (rune-lossless всегда, байт-точно на валидном UTF-8), `FuzzNormalizeSourceValidUTF8`, `FuzzSplitChunksPreservesContent` (Σ не-пробел чанков == Σ не-пробел источника) — поймали бы #3.
|
||||
|
||||
Отсеянная находка (oversize-хвост <500) осталась документированной границей §7b. Дальше — банк памяти v2 (шаг 4): реестр рисков `architecture/06` + ruby-контракт готовы (F1-materialization + горячий путь + post-check). Онбординг-промт след. сессии — `docs/BACKEND_SESSION_PROMPT_MEMORY.md`.
|
||||
|
||||
### 2026-07-05 — Шаг 4: банк памяти v2 (глоссарий + горячий путь + инъекция + F1 + post-check)
|
||||
|
||||
**Главный блокер качества (консистентность имён/терминов) реализован — веха A–E на seeded-глоссарии** (граница вехи подтверждена оркестратором §8: механизм на ручном+ruby-сиде; автопопуляция/адъюдикация/резюме/series-bible — отдельные вехи). Всё зелёное `go build/vet/test ./... -race` (125 тестов в pipeline), `tmctl report` $0. Ратифицированный порядок реестра `architecture/06` §Гейты соблюдён.
|
||||
|
||||
**A4 нормализация (`memnorm.go` + `data/trad2simp.txt`):** NFKC + trad→simp (вендорённая таблица, **версия = хеш содержимого таблицы** → дополнение = громкий `--resnapshot`, не тихая мини-карта) + катакана→хирагана + lower для источника; NFC + lower + ё→е + **схлопывание whitespace + унификация тире** для ru-цели. Симметрично ключ↔текст. Полный OpenCC оффлайн недоступен (нет данных на стенде) → курированный высокочастотный набор, все referenced/live-bug кейсы (爺→爷 и др.) покрыты и заассерчены; **завершение полного OpenCC — единственный отслеживаемый data-drop перед zh-приёмкой** (приёмочная книга D9 — ja→ru, где trad→simp не несущий).
|
||||
|
||||
**A схема (миграция v5):** `glossary` (D7 + `sense`/ось редакционного времени `glossary_revisions`/`UNIQUE(src,sense,window)`/`min_key_len`-запрет одиночных ключей/`allow_short`) + `glossary_aliases` (alias-граф) + `glossary_revisions` (B1 append-only) + `retrieval_state` (гейт #4). Idempotent full-replace (как ruby). `store/glossary.go`.
|
||||
|
||||
**B горячий путь (`memory.go`):** frozen `MemoryBank` из store-строк; **Aho-Corasick** по нормализованным ключам; запрет одиночных ключей (A3); longest-match containment; спойлер-hard-reject (C1, `since_ch/until_ch`, 0=безграничен); sticky scene-inertia (A5); токен-бюджет с логируемым вытеснением (F2); трёхсторонний disposition (A2 confirmed/ambiguous/reject). Детерминизм: 0 map-order в выводе, T1–T10 портированы (**не accept-регэкспы**), ловушки `retrieval_bench` 0/N, 200× determinism. **НЕ FTS5/вектор/эмбеддинги** (Р3).
|
||||
|
||||
**C инъекция (`render.go`):** `MessagesWithInjection` — код-собранный `system`-месседж глоссария МЕЖДУ стабильным префиксом (кэш-граница) и user-чанком (вариант «а» оркестратора, шаблон не трогаем); НЕ в `ch.Text` (coverage/`{{text}}` чисты); свёрнут в `request_hash`/`content_hash`.
|
||||
|
||||
**D закрыт F1 (`runner.go`):** `memoryVersion()` = content-hash замороженных **approved**-строк + версии норм/матч-алгоритмов (D8, не version-counter). Смена approved → громкий `--resnapshot` (e2e доказал `1e7b…`→`552c…`). id не хешируется; auto/draft вне хеша (их инъекция ловится `content_hash`).
|
||||
|
||||
**E post-check (`mempostcheck.go`) + E1-замер:** decl-осознанный (**наивный регэксп = 18–36% ложных, research/14**), whole-word матч по записанным `decl`-формам, sticky исключён, слепой post-replace запрещён (E2). **Флаггер по умолчанию** (миссы → `retrieval_state`, видны в `tmctl report`), **жёсткий гейт opt-in** (`gates.glossary.postcheck_gate`, как coverage — флип после валидации владельцем). **E1 измерен как Go-тест на реальном склонённом русском (канон Рогова): full-decl 0% ложных, base-only 67%** — эмпирическое подтверждение, что stored-decl надёжен ТОЛЬКО при полноте (ответ на развилку stored-decl-в-Go vs pymorphy-сайдкар Ф2: держим флаггером, сайдкар — валидированный фолбэк если реальные книги зашумят).
|
||||
|
||||
**Ruby→глоссарий (`memseed.go`):** классификатор `name_candidate`/`gloss_candidate`/`ambiguous` — **никогда не авто-лочит** (блайнд-лок = mistranslation; 強敵→とも неотличим от имени оффлайн → кандидат человеку). Ruby → auto-кандидаты (src=base, reading=мост к Поливанову B6, без dst), дедуп по base, скип manual-src.
|
||||
|
||||
**Интеграция + config:** `TranslateBook`: ingest→persistRuby→seedGlossary(replace+materialize)→snapshot→loop с sticky-окном (ресет на границе главы, пересобирается детерминированно на resume). `book.yaml: glossary_seed`. `tmctl report` — секция ПАМЯТЬ (агрегаты + пост-check миссы). Пост-check валидирует **финальный (редакторский) вывод** — то, что экспортируется, не только черновик.
|
||||
|
||||
**Агентское адверсариальное селфревью (§6, многоагентный Workflow):** 7 дименсий → 10 находок → независимая refute-by-default верификация с прогоном реального кода → **8 CONFIRMED (все воспроизведены), 2 REFUTED** (документированные размены: min-key-2 гомографы; редакторский drift — закрыт пост-check'ом финала). Все 8 исправлены + регресс-тесты **мутационно-проверены** (реверт → падает именно его тест): #1 empty-dst не матчится; #2/#8 whitespace-wrap/тире в post-check; #3 whole-word матч (дропнутый «Ван» не маскируется «караван»); #4 gate-mode `memoryVersion` сворачивает draft-decl (иначе resume молча флипал чанк); #5 дубль-alias в сиде дедупится (не крашит книгу); #6 спойлер-фильтр перед longest-match (спойлер-блокнутый длинный ключ не глотает валидное короткое имя); #7 floor-free токен-бюджет.
|
||||
|
||||
**Заложено/отложено (реестр §5, поля/место есть, реализация — Ф2/веха+):** Палладий/Поливанов B6 (reading как мост заложен), гейт фактичности резюме D1, эмбеддинг-слой A7/D2, морфо-гейт глагольного рода C3 (pymorphy-сайдкар), бэкап файла F4, автопопуляция/адъюдикация G1/F5, series-bible ты/вы-журнал, инъекция глоссария в редактор (dst-констрейнты) — fast-follow на той же поверхности. Ставка (селективная инъекция vs длинный контекст) гейтится in-house eval'ом пилота Ф2.5 (параллельно, не блокер). Правки только в коде `backend/` + этот журнал; `architecture/06`/`research/*` не трогались.
|
||||
|
||||
> **Внешнее ревью оркестратора банка памяти v2 (05.07): ПРИНЯТО, 0 живых блокеров на дефолтном конфиге, 6 подтверждённых (5 различных, 3 major; gate-находка независимо продублирована 2 линзами), 0 отсеяно — ВСЕ прогоном реального кода.** **Ядро держится:** F1 (материализация/resume/детерминизм — тихий расходящийся ре-пэй), нормализация A4 (симметрия ключ↔текст), спойлер C1, инъекц-поверхность (сам проверил) — **чисты, находок нет.** Все гэпы в одной зоне — **короткие/коллизионные ключи + гейт инвертирует свою же safety** — ровно те «hard traps», что `research/13` §«Честные слабые места» **предсказал непроверенными** (материализовались в коде, пойманы до продакшена).
|
||||
> **Major (закрыть до флипа гейта / до ja-kana в проде):**
|
||||
> 1. **[major, ONE-LINER, делать первым] PostcheckGate флагает по ОБЩЕМУ числу miss без фильтра disposition** (runner.go:744; продублировано 2 линзами). AMBIGUOUS-only miss (кандидат, который модель ВПРАВЕ отклонить) роняет чанк → `FinalText=""` → **выбрасывает корректный перевод**. Инвертирует A2/E1: модель, ПОСЛЕДОВАВШАЯ неверной инъекции, проходит; модель, ПРАВИЛЬНО отклонившая — наказана. Контракт (E1/B4/gate-list/config, 4 источника) скоупит гейт на approved. Фикс: считать в гейт только `Disp==confirmed` miss; ambiguous — только в retrieval-state (наблюдаемость). Опт-ин (дефолт=флаггер) → на дефолте не горит, но чинить ДО флипа.
|
||||
> 2. **[major] Source-side матч без word/script-границы + `dispositionFor` только по статусу** (memory.go:361, ac.matches). A2-ветка «коллизия поверхности → AMBIGUOUS» НЕ реализована; source-сторона без границы (асимметрия с target `containsWholeWord`, фикс селфревью #3). 2-символьный коллизионный ключ фичит **CONFIRMED внутри обычного слова** (リン→Рин в リンゴ/яблоко, AI→ИИ в RAID, 天下 в 天下无双). Post-check ИНВЕРТИРУЕТ: ложный confirmed-miss на КОРРЕКТНОМ выходе, и **не ловит FOLLOWED-отравление** (presence-only ловит только ДРОПнутый термин). Фикс: A2-даунгрейд коллизионных коротких ключей в AMBIGUOUS (не CONFIRMED); source-граница где есть смена скрипта/не-буква.
|
||||
> 3. **[major] `min_key_len` per-язык НЕ разведён** (memory.go:42 `defaultMinKeyLen=2` хардкод). Реестр A3 называет `glossary.min_key_len` per-язык как механизм — не разведён. Precision-1.0/MIN=2 мерена на zh-Han-ловушках, **не переносится на ja-kana** (#2 язык, 46-символьная слоговая → 2-kana ключи = частые подстроки). **NB: селфревью REFUTED это как «документированный размен» — но замер был zh-Han-scoped; для kana это реальный гэп.** Фикс: развести per-язык (в `memoryMatchVersion`+snapshot), kana ≥3, или 2-kana за `allow_short`.
|
||||
> **Minor (гарды от авторской описки, закрыть тихие дыры):**
|
||||
> 4. **[minor] 1 src → 2 dst с ПЕРЕСЕКАЮЩИМИСЯ спойлер-окнами** → две противоречивые авторитетные строки, **молча** (асимметрия: зеркальный B2 2src→1dst логируется громко). Фикс: overlap-проверка same (src,sense) → WARN/fail-loud.
|
||||
> 5. **[minor] approved-термин с пустым dst — молча инертен** (memseed.go:62; нет empty-dst-гарда на approved). Не матчится, не инъектится, 0 предупреждений → тихая потеря recall на всю книгу (ruby-auto с пустым dst легитимен, но там status=auto). Фикс: reject `status∈{approved,draft}` с пустым dst в loadGlossarySeed.
|
||||
> **Протокол включения гейта (важно):** твой E1-замер меряет false-flag **approved**-терминов на русской морфологии — но находки 1/2/3 вскрывают **другие оси** false-flag (ambiguous-decline, коллизионные короткие ключи), которые E1-протокол НЕ покрывает. Значит либо чинить 3 major ДО флипа (что убирает эти оси), либо расширить протокол валидации на них. Рекомендую первое.
|
||||
> **Приоритет:** #1 (one-liner, немедленно) → #2+#3 (коллизия/kana, до ja-kana или флипа гейта) → #4/#5 (дешёвые гарды). Ничего не блокирует дефолтный конфиг; всё блокирует флип гейта и прод ja-kana.
|
||||
|
||||
> **Внешнее ревью eval банка памяти v2 (05.07): ПРИНЯТО, 0 блокеров, 0 баг-находок.** Прогнал независимо на `aa00339` (сборка/тесты `-race` зелёные, E1 воспроизведён full-decl 0%/base-only 67%, трад-таблица 508 маппингов 爺→爷 на месте, изоляция инъекции/sticky-resume/F1/схема — проверил сам). 4 low/scope-заметки: (a) перекрывающиеся НЕвложенные ключи оба срабатывают (precision-сторона, обе поверхности реально есть); (b) редактор глоссарий не получает — защита только post-check финала (fast-follow: dst-констрейнт-инъекция в редактор — приоритет след. вехи); (c) gate-режим выкидывает весь чанк (opt-in, агрессивно — задокументировать до флипа); (d) 2-й system-месседж не на живом проводе (только моки — live-conformance кейс follow-up).
|
||||
|
||||
### 2026-07-05 — Шаг 4: закрытие внешних ревью (6 находок оркестратора + 4 low eval)
|
||||
|
||||
Все находки закрыты в этой же сессии, каждый фикс **мутационно-проверен** (реверт → падает именно его тест) + полный набор зелёный `go build/vet/test ./... -race`, `tmctl report` $0. Ядро (F1/нормализация/спойлер/поверхность) оба ревью подтвердили чистым — трогал только зону находок. `memoryMatchVersion` бампнут **v1→v2** (смена семантики матча/disposition = осознанная инвалидация → громкий `--resnapshot`).
|
||||
|
||||
**Major:**
|
||||
- **#1 — gate по CONFIRMED-only.** `PostcheckGate` и `n_postcheck_miss` считают только `Disp==confirmed` (`countConfirmedMisses`); AMBIGUOUS-miss (кандидат, который модель вправе отклонить) больше не роняет корректный перевод — только в `postcheck_detail` (A2-наблюдаемость). Инверсия контракта устранена.
|
||||
- **#2 — A2 коллизия→AMBIGUOUS.** `dispositionFor(entry, via)`: короткий чисто-фонетический ключ (kana/latin без Han-якоря, ≤3 знака) даунгрейдится в AMBIGUOUS даже у approved (мог сработать внутри чужого слова). `allow_short` — явный оверрайд автора. Sticky-кэрри сохраняет status-based (нет firing-ключа).
|
||||
- **#3 — min_key_len per-язык.** `minKeyLenFor`: Han-якорь → 2 (эмпирика zh-Han precision-1.0); чисто-фонетический → 3 (リン в リンゴ, ai в raid больше не фичат). **Kana=3 — консервативный дефолт до ja-kana precision-замера (расширение E1-протокола)** — свежие глаза показали, что zh-Han-замер MIN=2 на kana не переносится.
|
||||
- **Протокол флипа гейта:** оси false-flag из #1/#2/#3 (ambiguous-decline, коллизионные короткие ключи) E1-замер не покрывал → закрыты в коде, поэтому расширять протокол не нужно; флип гейта разблокирован после этих фиксов + owner-валидации precision.
|
||||
|
||||
**Minor:**
|
||||
- **#4 — overlap спойлер-окон fail-loud.** `loadGlossarySeed`: same (src,sense) с пересекающимися окнами и РАЗНЫМ dst → громкая ошибка (`windowsOverlap`; молчаливая противоречивая инъекция устранена).
|
||||
- **#5 — approved/draft пустой dst fail-loud.** Только `status=auto` (сырой кандидат, ruby-reading без dst) может быть пустым; approved/draft с пустым dst — ошибка (тихая потеря recall).
|
||||
|
||||
**eval low:** #a — тест `TestOverlappingNonNestedKeysBothFire` фиксирует принятое поведение (обе срабатывают); #b/#c/#d — задокументированы (редактор-инъекция = приоритет след. вехи; gate-агрессивность — `FlagGlossaryMiss` не-retryable/не-escalatable, флагает для человека; live-wire кейс — follow-up на `live_conformance`-харнесс). Регресс-тесты: per-lang-min+collision-disposition, gate-ignores-ambiguous (e2e), overlap-windows/empty-dst fail-loud, overlapping-non-nested. Оба вердикта: **ПРИНЯТО**; дефолтный конфиг чист, флип гейта и прод ja-kana разблокированы.
|
||||
|
||||
### 2026-07-05 — Шаг 4: глубокое адверсариальное ревью полной поверхности (44 агента)
|
||||
|
||||
По запросу владельца — многоагентный воркфлоу поверх `cc57c7b`: 8 finder-дименсий (нормализация / матчер+disposition / F1 / post-check / seed+ruby / store / инъекция+resume / мутационная-стойкость тестов), каждая не-минорная находка → 3 адверсариальных верификатора refute-by-default, подтверждение большинством ≥2/3. **24 кандидата → 2 подтверждённых major, 10 отсеяно (все 0/3–1/3), 12 миноров.** Отсев здоровый: напр. «sticky протаскивает collision-prone AMBIGUOUS в CONFIRMED» зарублен 0/3 верно — sticky не матчит исходник заново, а несёт установленный в сцене термин, collision-риск (срабатывание внутри длинного слова) к нему неприменим. Оба major — класс «тихо пусто», ровно та зона, ради которой банк существует; оба закрыты, каждый фикс **мутационно-проверен** (реверт → падает именно его тест), полный `-race` зелёный.
|
||||
|
||||
- **major #1 — default-ignorables в A4-нормализаторах (`memnorm.go`).** Zero-width (U+200B/200C/200D/2060/FEFF) и вариационные селекторы (U+FE0F, IVS) переживали NFKC/NFC → ключ `渡邊` молча не матчил `渡<ZWSP>邊` (частый артефакт EPUB/скрейпа CJK — «тихо пусто» переоткрыт), симметрично на target `<WJ>` внутри слова давал ложный post-check-miss. Фикс: `isIgnorableForMatch` (unicode.Cf + VS-диапазоны) дропает их в ОБОИХ нормализаторах; soft-hyphen U+00AD сохранён как fold→'-' (self-review #8 — порядок проверок гарантирует). `memoryNormAlgoVersion` бампнут **v1→v2** → громкий `--resnapshot`.
|
||||
- **major #2 — окружающие пробелы на keying-поверхностях (`memseed.go`).** `loadGlossarySeed` проверял пустоту через TrimSpace, но хранил СЫРОЕ значение: `src: " 強敵"` (approved, непустой dst) проходил валидацию, ключился как `" 強敵"` и НИКОГДА не матчил `強敵` — молча-инертный approved-термин на всю книгу; плюс trailing-space на `sense` маскировал same-sense-противоречие мимо обоих гардов (#4/#5). Фикс: тримминг `src`/`sense`/`dst`/`alias` до построения ключей и хранения (прощающий фикс, как alias-дедуп).
|
||||
|
||||
Отсев и 12 миноров оставлены как задокументированные размены/fast-follow (per-lang boundary-тесты post-check, sticky-decay coverage, apostrophe-fold — не гарят на дефолте). Вердикт сессии: **ПРИНЯТО**, шаг 4 закрыт.
|
||||
|
||||
### 2026-07-05 — D1: инъекция глоссария в редактор (монолингвальный редактор)
|
||||
|
||||
Первый fast-follow на поверхности памяти (eval-приоритет). Редактор теперь получает одобренный глоссарий как **target-констрейнты** и переведён в **монолингвальный** режим (decisions-log D1).
|
||||
- **`renderEditorConstraintBlock` (memory.go):** dst-only блок (без `src → dst` — редактор не видит исходник), **CONFIRMED-only** (AMBIGUOUS — кандидат, который переводчик вправе отклонить; форсить редактора переписывать черновик под непроверенное = порча корректного перевода, зеркалит gate-CONFIRMED-only #1), дедуп по dst, подмножество уже забюджеченного `memSel.injected` (свой токен-бюджет не нужен). Пустой → редактор без инъекции.
|
||||
- **runner.go:** `roleEditor`-ветка в стадийном цикле; `editorInjection` из того же `memSel` (детерминизм, resume-стабилен, входит в editor `request_hash` через msgs — не в snapshotID, memoryVersion уже там).
|
||||
- **`prompts/editor.md`:** убран `{{text}}` (D1: билингвальный редактор якорится к исходнику → кальки, главная translationese-болезнь; монолингвальный ещё и дешевле — исходник не сидит на входе каждого edit-вызова); мандат строки 7 согласован с инъекцией («приводи к каноническим формам глоссария», а не «не трогай»).
|
||||
|
||||
Тесты **мутационно-проверены** (реверт → падает именно его тест): `TestRenderEditorConstraintBlock` (CONFIRMED-only / dst-only / дедуп), обновлён `TestRunnerMemoryInjectionAndPostcheck` (editor получает dst-констрейнт-блок «КАНОНИЧЕСКИЕ ПЕРЕВОДЫ», не «src→dst ГЛОССАРИЙ»), `TestEditorPromptIsMonolingual` (guard: реальный editor.md без `{{text}}`). Полный `-race` зелёный, `tmctl report` $0.
|
||||
|
||||
**Заметка владельцу/оркестратору:** редактор стал **источник-слепым** (D1) — правит стиль/консистентность имён, но не ловит мистранслейты (это судья/эскалация, Фаза 2). Осознанный размен по контракту D1.
|
||||
|
||||
### 2026-07-05 — Консолидация конфига (drift из doc-аудита оркестратора)
|
||||
|
||||
6 конфиг-расхождений моей зоны (промт `BACKEND_SESSION_PROMPT_CONSOLIDATION`); центральный grok-разворот верифицирован веб-чеком xAI-доки + пробой eval, всё — адверсариальным селфревью (5 измерений, **0 находок**).
|
||||
- **grok-4.3 reasoning OFF даётся ЯВНО** (задачи 1-2, money-path). `models.yaml`: `control:none`→`control:effort/off_effort:none`. Дефолт grok = `low` (омиссия заставляет думать, additive-биллинг ~444 ток./правку) → `ReasoningNone` (off-by-omission) молча оставлял бы low; теперь при `reasoning:"off"` уходит плоский `reasoning_effort:"none"` (проба eval → 0 ток.). Комментарий `ReasoningNone` в `capability.go` разведён (DeepSeek ≠ grok — логика не тронута). **DeepSeek остаётся `ReasoningNone`** (omission намеренный: отключение thinking взводит эхо-мину; гвард `echoMineViolation` цел, xAI не echo-prone).
|
||||
- **Редактор glm-5 → grok-4.3** (задача 3, D1/D3; glm-5 был плейсхолдером) в edit-стадии C1/C2; select-стадия C2 (judge/glm-5, Gemini-слот Ф2) не тронута. Прод — только чистый xAI-ключ без data-sharing.
|
||||
- **Anthropic price-litter убран** из шапки `models.yaml` (з.4); **escalation-заглушки `[kimi-k2.6]` помечены интеримом** с названной D3-цепочкой (з.5 — заводка провайдеров gemini/openai + v4-pro/glm-5.1/gemini-3.1-pro отдельным шагом, гейтится ценами/ключами/cost-model); **бэкендовый `[НУЖНО РЕШЕНИЕ]`-маркер → РЕШЕНО** (з.6; оркестраторский блок не тронут).
|
||||
|
||||
Тесты: `capability_test` кейс assert'ит **присутствие** `reasoning_effort:"none"` (закрыл eval-указанную дыру — ложный «off шлёт nothing» тут падает); `TestBoevoyConfigGrokEditorExplicitNone` (config end-to-end: grok→explicit-none, не echo-flagged, edit=grok, c2-select=glm-5). Полный `-race` зелёный, `tmctl report` $0. Eval подтвердил: прогоны переигрывать не надо, баг был латентным (grok не был в стадии) — пойман до флипа.
|
||||
|
||||
### 2026-07-09 — Пакет фиксов стратегического ревью (D15/D16, промт `BACKEND_SESSION_PROMPT_REVIEW_FIXES`) ЗАВЕРШЁН
|
||||
|
||||
6 задач + 3 самопойманных дефекта + 7 находок финального адверсариального селфревью — всё исправлено, каждый фикс **мутационно-проверен**, `go build/vet/test ./... -race` зелёный, `tmctl report` $0.
|
||||
|
||||
- **Задача 1 (гигиена).** Лгущие resume-комментарии (`runner.go` coverageSnap, `coverage.go` coverageGateVersion) переписаны честно: `--resnapshot` переоплачивает ВСЮ книгу (snapshotID в RequestHash), никакого «free re-classify» — только внутри неизменного снапшота. Edit `prompt_version` `v0-draft`→`v1-monolingual` в обоих `pipeline-c*.yaml` (D1-уточнение №3: один лейбл на два SHA закрыт). `capability.go:3` ссылка 03→05.
|
||||
- **Задача 2 (D16 память).** 2a полисемия fail-loud (same-src/разные sense/dst/пересекающиеся окна, scoped к matchable src — `道` инертен, не регресс); 2b sticky **наследует** disposition (`activeIDs` → `map[string]injectionDisposition`, `Select`/`unionSticky`/`stickyWin` обновлены) — collision-prone AMBIGUOUS больше не апгрейдится в CONFIRMED мимо post-check/editor; 2c source word-boundary для **латиница/кириллица** (`suppressUnboundedPhonetic`); 2d ruby-reading→alias ручного термина (`attachRubyAliasesToManual`) + чек-лист ja-книги в `backend/README.md`. `memoryMatchVersion` v2→v3, `memoryNormAlgoVersion` v2→v3.
|
||||
- **⚠ [→ оркестратору] 2c: kana/Han НЕ boundary-checked (осознанное расхождение с буквой промта «латиница, кана»).** Обоснование: у каны нет сегментации (как у Han) — letter-boundary ломает частый кейс «имя+частица» (すずきは) и противоречит контракту «длинный кана-ключ = CONFIRMED». ≥4-кана-компаунд-precision отложен на kana-precision-замер полигона + токенизатор B6 (согласуется с D16 «minKeyLenPhonetic=3 — консервативный дефолт до замера»). Прошу ратифицировать это сужение.
|
||||
- **Задача 3 (`tmctl status`+`redrive`, D15.3).** `status.go`: read-only проекция (0 LLM, 0 replay) — book-manifest N/M (честный знаменатель через ре-чанкинг $0), unit-счёт done/in_progress/flagged/pending, паспорта глав (total/ok/flagged/skipped-stages, worst_flag, вердикт pass|attention|fail по exp07, $), деньги committed/reserved/ceiling%/projected, ETA от throughput (вторично), `--json` со стабильными enum. Колонка `escalated`/`escalation_model` в `chunk_status` (миграция v6) — телеметрия эскалации на flagged-resume (отложенная находка №6 Вехи 2.5). `redrive`: точечная переатака флагнутых (`--chapter/--chunk/--reason/--dry-run`), сброс терминального флага (`ResetChunkStages` удаляет chunk_status+чекпоинты сброшенных стадий, DispOK не тронут), свежий retry/escalation-бюджет, ре-ран durable-цикла. Продемонстрировано на example-книге ($0). **Деньги-семантика (задокументирована):** redrive НЕ возвращает committed (реально потраченное остаётся) → после redrive `committed ≥ SUM(checkpoints)`, безопасное направление; инвариант №1 в `README.md` дополнен исключением.
|
||||
- **Задача 4 (спека D15.2, документ).** `backend/docs/D15.2-content-addressed-resume-spec.md` (в моей зоне). Суть: `snapshotID` в ключе вызова смешивает wire- и вердикт-входы; расщепить (`wireSnapshotID`/`verdictSnapshotID`), ключ чекпоинта держать на wire-идентичности (по факту `msgsContentHash` + не-msgs wire-параметры), вердикт-версии убрать из ключа и re-classify-ить на resume бесплатно. Снимает онгоинг-мину D15 (append-термин re-bill-ит только реально затронутые чанки). **[→ оркестратору] на утверждение; при ок — свернуть в `03-implementation-notes.md`.**
|
||||
- **Задача 5 (reasoning-буфер, D13.6).** `EstimateUSD(+reasoningBudgetTokens)` резервирует reasoning как output для additive-провайдеров (xAI); fail-fast в `LoadPipeline`: reasoning-стадия на additive-провайдере без `reasoning_max_tokens` (+ escalate_to). Снимает D6.2-блок think-ON grok.
|
||||
- **Задача 6 (перепроверка отсевов).** Артефакты 44-агентки эфемерны (PROGRESS называет лишь sticky-отсев — уже закрыт 2b). Адверсариальные пробы с исполнением по границам доверия → **2 подтверждённых + пофикшено:** (F) shared-alias livelock (общий firing-key между разными approved-терминами → `approvedSharedKeyCollisions` fail-loud) и (A) apostrophe-fold тихо-пусто (типографский апостроф → ASCII в обоих нормализаторах). Пробы удалены, `git status backend/` чист.
|
||||
|
||||
**Самопойманный при селфревью (сверх задач):** 2d+Задача6 могли hard-блокировать легитимную ja-книгу с омофонами (鈴木/鈴樹 → оба すずき) — `attachRubyAliasesToManual` теперь graceful skip+log коллизии (best-effort, не hard-block), ручные коллизии сида по-прежнему fail-loud.
|
||||
|
||||
**Финальное адверсариальное селфревью — воркфлоу 5 дименсий × верификация (15 агентов, refute-by-default): 7 CONFIRMED / 3 refuted, все 7 исправлены:**
|
||||
1. [major] Полисемия same-src через общий matchable ALIAS проскакивала оба гарда D16.1 (sub-floor src `道` + общий алиас `大道`) → снял same-src-skip в `approvedSharedKeyCollisions` (ловит через общий alias-ключ; в обычном eligible-src кейсе `loadGlossarySeed` короткозамыкает — двойного репорта нет).
|
||||
2. [major] `glossary_miss` (post-check-гейт, флаг на уровне ЧАНКА после стадий) был невидим `status`/`redrive` (все stage-строки DispOK) → status показывал done/pass против exit-2 translate. Фикс: при gate ON чанк с post-check-промахом промотится в flagged/glossary_miss (не re-drivable — правка глоссария = --resnapshot).
|
||||
3. [major] additive-гейт ложно-негативил на `reasoning:""` (омиссия у grok = дефолт low = думает additive) → гейт и буфер теперь на `!= "off"` (не только low|med|high).
|
||||
4. [minor] `status` ловил только intra-store multi-snapshot, не store-vs-current-config → добавлен ConfigDrift (read-only расчёт текущего снапшота, сравнение).
|
||||
5. [minor] инвариант №1 README (`committed==SUM(checkpoints)`) — дополнен redrive-исключением.
|
||||
6. [minor] `unionSticky` newest-wins не тестировался → тест на конфликтующие disposition.
|
||||
7. [nit] `ProjectedBookUSD` пере-считывал при in-progress-спенде → база проекции = processedCost (только done+flagged).
|
||||
|
||||
**Техдолг / вопросы оркестратору:**
|
||||
- Спека D15.2 и сужение 2c (kana-boundary) — на ратификацию (см. выше).
|
||||
- **⚠ Рабочее дерево несёт незакоммиченные правки ПАРАЛЛЕЛЬНОЙ полигон-сессии** (`eval/`, `docs/experiments/`) — не мои, не трогал; коммитить пакет надо аккуратно (только `backend/` + `backend/docs/` + эта запись).
|
||||
- Известная граница `status`/`redrive`: glossary_miss re-деривится из неизменного глоссария → не re-drivable (фикс = правка глоссария = --resnapshot); status теперь честно это показывает.
|
||||
- F3 at-most-once — следующий D12-хвост (status/redrive закрыты).
|
||||
|
||||
### 2026-07-09 (пакет-2) — Приёмка-prep Ф1 на 蛊真人 (fix-лист ревью + GB18030 + дешёвые гейты + D15.2 v2 + smoke) ЗАВЕРШЕНА
|
||||
|
||||
Мандат `BACKEND_SESSION_PROMPT_ACCEPTANCE_PREP.md` (5 задач) выполнен. Порядок 1 → 2 → (3∥4) → 5. `go build/vet/test ./... -race` зелёные; фиксы mutation-verified; `tmctl report` $0. Смоук-книга/производные/сид — ВНЕ git (Р8; в журнал только метрики).
|
||||
|
||||
- **Задача 1 — fix-лист внешнего ревью.** (1a, **major, mutation-verified**) homophone first-wins в `attachRubyAliasesToManual`: контестед-ключ решается ДО аттача для ВСЕХ владельцев симметрично (было attach-then-block → алфавитно-первая база получала kana-alias CONFIRMED = A2 неверная авторитетная инъекция при ≥4 каны). Плюс window+dst-eligibility awareness (минор 1d — меньше ложных скипов). Ревертом ловится тест `TestRubyHomophoneNoWrongConfirmedInjection` (たかはし 4-каны материализуется → NEITHER инъектится). (1b) redrive-инвариант «DispOK НЕ сбрасывается» **закреплён мутационно** (draft=ok/edit=flagged → сброс ТОЛЬКО edit, draft резюмится за $0; мутант `filter→true` даёт Stages=[draft,edit] → тест валит) + тест НЕсовпадающего `--reason`. (1c) snapshot-чек ДО `ResetChunkStages` (**mutation-verified**: без гарда drift-редрайв удаляет флаг-строку → status pending/pass). (1d) minors: `--json` тоже exit 2 при флагах; hint для glossary_miss отдельный (redrive для него no-op → правка сида + --resnapshot); README миграции v1–v6; ETA — явная пометка D12-отступления (mean, не EWMA); overclaim-коммент `bookChunks` сужен (правка исходника без смены границ невидима status'у).
|
||||
- **Задача 2 — GB18030/кодировки в ingest.** `decodeSourceBytes`: лестница BOM(UTF-8/UTF-16) → валидный UTF-8 → **GB18030-проба (только zh-источник)** → fail-loud. Гарды: U+FFFD, NUL (UTF-16-без-BOM), Han-density+plausibleCJK (анти-мохибаке). `book.yaml encoding: auto|utf8|gb18030` + `source_lang`-скоуп пробы. Chapter-split добавлен для txt: **«第N章/节/回» авто-детект дом. юнита + separator-guard** (回 — мера, «第一回见面» НЕ дробит; сепаратор после юнита обязателен), preamble→гл.1. Новая внешняя зависимость: `golang.org/x/text/encoding/{simplifiedchinese,unicode}` (+ `japanese` в тестах) — первая за пределами go.sum-минимума (x/text уже был для NFC).
|
||||
- **Задача 3 — 4 дешёвых детерминированных гейта (наблюдаемость, НЕ гейты, на финальном тексте).** Линтер тире-диалогов (Розенталь §47–52: прямые кавычки/дефис/en-dash вместо «—», смешение стилей), ёфикатор (Пётр/Петр + brief-политика all-ё/all-е, ~30 омографов-исключений), блок-лист транслит-междометий (ара-ара/маа/нани/…; per-project allowlist), число-гейт 万/億 (CJK-парсер значений + диапазоны-множители на выходе; digit-coefficient-guard исключает идиомы 万一/千万/万物). `cheapGateVersion` свёрнут в snapshot (правка правил = --resnapshot, как classifierVersion); миграция store **v7** (`retrieval_state.n_style_flags`+`style_detail`); счётчики в `tmctl status`/`report`/паспорте главы + `StatusReport.StyleFlags`/`GlossaryMissFlagged`.
|
||||
- **Задача 4 — спека D15.2 v2** (`backend/docs/D15.2-content-addressed-resume-spec.md`, дизайн, реализация ОСТАЁТСЯ заблокированной до ратификации v2). Закрыты 3 дыры ревью: (a) fast-path-гард — отдельная колонка `guard_hash` (весь wire stage-план, суперсет текущего); (b) расщепление `memory_version` ОБЯЗАТЕЛЬНО — inject-часть в `content_hash` (из ключа вон), post-check+gate+decl → `verdictSnapshotID` (пересчёт на resume бесплатно); (c) замена loud-гейта согласия pre-flight dry-run «N чанков, ~$X» + порог `--accept-rebill`. Плюс: полный полевой маппинг снапшота (wire/verdict/dropped), судьба `chunk_status.snapshot_id`/status-ридеров, sequencing миграции (ДО первой онгоинг-книги; миграция v8), blast-radius append-а (sticky depth2 + F2 eviction + каскад на редактор). 3 открытых вопроса оркестратору в §13. **На утверждение.**
|
||||
- **Задача 5 — D18 smoke на 蛊真人.** (а) **ingest+chunker на реальном GB18030-файле (15.5 МБ):** 2283 главы (第N节-детект), **5088 чанков** (медиана 1445 ток., целевой 1500), ~6.52M токенов (медиана главы 2832), 0 ruby (zh), U+FFFD=0. (б) escalate_to заведён (интерим glm-5 фолбэком черновика). (в) **живой smoke 1 главы (draft=deepseek-v4-flash → edit=glm-5, escalate=glm-5; БЕЗ xAI — гигиена ключа D8 не подтверждена для книжного контента; потолок $0.10):** деньги сходятся **до цента** — Σ(request_log billed) == committed == **$0.031634**, reserved=$0; **живое эхо+эскалация** (chunk3 deepseek→cjk_artifact→glm-5 ok); **redrive на реальном флаге** (esc-off вариант дал cjk_artifact-флаг → redrive сбросил+перезапустил, DispOK за $0, 2-й проход: empty→удвоение бюджета→ok → флаг снят, 6/6 done); cheap gates фаернули на реальном выводе (万/億-разряды, дефис-диалоги). Полигонный сид (49 терминов, 35 approved/14 draft) грузится **чисто** через мой `loadGlossarySeed`+`approvedSharedKeyCollisions`+`materializeMemory` (схема совпадает). Суммарный живой спенд сессии ≈ $0.065.
|
||||
- **Финал — агентское адверсариальное селфревью** (6 дименсий × find→refute-by-default verify, 21 агент, ~835k ток.): **15 находок, 14 подтверждено, все закрыты** с регресс-тестами. Крит: Shift-JIS/EUC-JP молча принимался как GB18030-мохибаке (плаузибилити не отличает CJK-shaped мусор) → GB18030-проба скоупнута на zh (**mutation-verified**). Мажоры: seed-FILE drift не ловился redrive-гардом (read-only проекция) → гард **re-seed'ит** как TranslateBook, ловит ДО сброса (**mutation-verified**); UTF-16-без-BOM ASCII (interleaved NUL) → NUL-гард; chapter false-split на 回 → separator-guard; cheapgate ложные позитивы («уму»/«ара» убраны из блок-листа, 万-идиомы digit-guard, ё-омографы расширены, em-dash scene-break не считается диалогом); plausibleCJK получил прямой тест (была 0-покрытость). Миноры: StyleAllowlist сортируется до BriefHash, redrive-abort-сообщение переформулировано.
|
||||
|
||||
**Блокеры полной приёмки (владельцу/оркестратору):**
|
||||
1. **Сид готов, но политические развязки D10 открыты** (полигон §вопросы п.3): имена гу перевод-vs-транслит, 古月=Гуюэ vs Гу Юэ, пол 白凝冰 (draft/female — 他 в первых главах, gender=hidden трап). Гейтят финализацию сида.
|
||||
2. **Пороги гейтов:** coverage len_ratio zh-ru [2.2,4.2] (полигон подтвердил на срезе); postcheck-гейт держать OFF до замера precision на реальной инфлекции (E1); дешёвые стиль-гейты — наблюдаемость, порогов не имеют.
|
||||
3. **Канал 18+/violence:** полигон — grok thinking-off эхает 40% как ПЕРЕВОДЧИК (класс deepseek-эхо) → канал B: Mistral-переводчик + echo-гейт, ИЛИ grok reasoning-ON + reasoning-буфер (D6.2). xAI clean-key для боевого прогона (гигиена D8) — не подтверждён; smoke сознательно обошёл xAI.
|
||||
4. **D3-цепочка эскалации не заведена** (deepseek-v4-pro/glm-5.1/gemini — цены/ключи) — интерим glm-5; заводка — отдельный шаг.
|
||||
5. Полный прогон целой книги — **отдельная сессия** по готовности сида (п.1) + порогов (п.2) + канала (п.3).
|
||||
|
||||
**Вопросы оркестратору:** (1) **D15.2 v2 на ратификацию** (3 развязки в §13: пер-стадийная гранулярность wire-снапшота vs book-global; дефолт порога `rebill_consent_usd` + имя флага; слой для `Adult`). (2) Редактор smoke — glm-5 вместо ратифицированного grok-4.3 из-за xAI-гигиены: для боевой приёмки нужен ЧИСТЫЙ xAI-ключ ИЛИ решение держать glm/Mistral редактором. (3) ja-путь: Shift-JIS сознательно НЕ авто-детектится (fail-loud) — ja-книги должны быть UTF-8/epub (ja-приёмка отложена D18 — ок).
|
||||
|
||||
### 2026-07-10 (пакет-3) — D15.2 v3 + fix-лист D20.4 + заводка цепочки D3/канала B ЗАВЕРШЕНА
|
||||
|
||||
Все 4 задачи промта пакета №3 выполнены; `go build ./... && go vet ./... && go test ./... -race` зелёные; **ничего не коммичено** (внешнее ревью и лендинг — оркестратор). Зона правок — строго `backend/` (20 файлов, +860/−143 — счёт испр. оркестратором по diff; самоотчёт «19, +770/−132» был до финальных селфревью-тестов); чужие правки (eval/, docs/) не тронуты.
|
||||
|
||||
**Задача 1 — спека D15.2 → v3** (`backend/docs/D15.2-…`, дизайн; реализация ЗАБЛОКИРОВАНА до ратификации). Три правки D20.1: (а) `guard_hash` теперь несёт `role`+`stageName` (префикс `tm-guard-v2`) с КОНТРПРИМЕРОМ в §5 (флип роли editor↔translator на wire-нейтральном чанке → без role fast-path отдаёт stale-`ok`, хотя coverage-гейт сменил бы вердикт; показано, что без role формула НЕ суперсет); (б) §7 п.1-бис — аналитическое правило editor-каскада (любая стадия ниже re-bill-юнита чанка = re-bill; иначе консент занижен ~2× на смене temp/reasoning/model translator'а); (в) §4 доукомплектован (`style_check_version`, YoPolicy/StyleAllowlist → verdictSnapshotID; target-часть memoryNormVersion → postcheck; судьба `jobs.snapshot_id`; coverage-фолд только при enabled). Ответы D20.2 вписаны (Q1 пер-стадийность; Q2 `--accept-rebill[=usd]`+порог+fallback-флор, каскад ПЕРВЫМ; Q3 Adult нейтрален → adult-линт).
|
||||
|
||||
**Задача 2 — fix-лист D20.4** (каждый содержательный фикс mutation-verified — реверт валит именно его тест): README v7; cheap-gates **v2** (`cheapGateVersion` bump — громкий resnapshot; 3 FP закрыты: chevron-цитата в начале строки, 万-в-имени+постороннее число, перефраз+год; note про дефисные редупликации; честная recall-нота про `三万→300`); NUL-гард на GB18030/UTF-16 путях (был только UTF-8); `redrive --resnapshot` ПОДДЕРЖАН (main.go прокидывал флаг в `r.Resnapshot`); style-колонка в human-`status`; `report`/`status` через `NewReadOnlyRunner` без API-key-preflight.
|
||||
|
||||
**Задача 3 — цепочка D3 / канал B** (`models.yaml`+`pipeline-c1.yaml`; каждый слаг live-фактчекнут 2026-07-10 — `/models` И пробный вызов). Провайдеры gemini/openai/mistral + модели deepseek-v4-pro/glm-5.1/gemini-3.1-pro-preview/mistral-large-2512/gpt-5-mini с ценами (офиц., с URL) и capability; цепочки `default:[v4-pro,glm-5.1,gemini-3.1-pro-preview]` `adult:[grok-4.3]`; draft `escalate_to: deepseek-v4-pro`; permissive на xai/mistral/local (deepseek НЕ permissive — ToS D14.1); **adult-линт `CheckAdultChannel`** реализован (D20.2-Q3); xAI reasoning-буфер проверен runner-тестом (ceiling-trip). boevoy-config тесты (echo_mine) целы.
|
||||
|
||||
**⚠ Две существенные ЖИВЫЕ находки (правило двух направлений — вендор-сверка сделана):**
|
||||
1. **`gemini-3.1-pro` → HTTP 404 NOT_FOUND; callable слаг ТОЛЬКО `gemini-3.1-pro-preview`** (совпадает с quirks и преамбулой D8–D11 04.07 — 05-decisions-log:46, не D21; провенанс испр. оркестратором). В конфиг пошёл `-preview`. → **ПИНГ:** поправить D3-текст «gemini-3.1-pro» → `-preview` *(исполнено оркестратором при D22)*.
|
||||
2. **Gemini thinking-токены НЕ в `completion_tokens`** — проба: `completion=2, prompt=22, total=847` → 823 thinking ТОЛЬКО в `total_tokens`, поля `reasoning_tokens` НЕТ (у xAI есть). Офиц. прайс: «output includes thinking». Текущий адаптер биллил бы Gemini почти по нулю = слепота потолка. Фикс: провайдер `reasoning: additive_total` — settle деривит `thinking=total−prompt−completion`, биллит по output (тест+мутация). Резерв не слепнет (thinking ⊆ max_tokens ≥8000). Полный reasoning-буфер mandatory-thinking на РЕЗЕРВ-стороне — Ф2 (апекс-wiring; settle уже корректен).
|
||||
|
||||
**Задача 4 — D21.10:** (а) design-note резерва схемы банка v2 (voice_profile / address_pair = материализация ты/вы-журнала D7, один источник истины / reveal_ch + pre-post-алиасы) — комментарий в `store/migrate.go`, НЕ миграция/код; (б) wire-probe: **temperature молча игнорируется в thinking-канале DeepSeek** (temp=0.0 ×3 → 3 разных вывода) → draft `temperature:0.3` = no-op на deepseek-thinking (вендор-док подтверждён); temp остаётся в снапшоте (детерминизм), но wire-инертен — бэклог полигону (D21.9 wire-аудит); (в) промпты ролей НЕ тронуты (анти-эхо гейтится fidelity-хвостом P4).
|
||||
|
||||
**Финал — агентское адверсариальное селфревью** (workflow: 6 дименсий → верификация каждой находки, 22 агента; 16 находок → 3 CONFIRMED, 13 refuted). Все 3 закрыты; (2) и (3) mutation-verified, (1) — правка ТЕКСТА спеки, сверена с кодом *(уточнено оркестратором: сам инвариант «role в RequestHash» тест-незащищён — axis-тест в fix-лист D22)*: (1) **major** — §5 спеки клеймила «re-classify бесплатно», но `role` в `RequestHash` → флип роли = честный re-bill (промах чекпоинта), НЕ $0; текст исправлен (безопасность stale-`ok` serve сохранена, стоимость честна); (2) **minor** — `redrive --resnapshot` пропускал pre-reset `seedGlossary` → регресс защиты 1c (seed-коллизия падала бы ПОСЛЕ reset, стерев флаг-телеметрию); `seedGlossary` вынесен из-под `if !r.Resnapshot` (+ тест); (3) **minor** — NUL-гард на UTF-16 BOM-пути был без mutation-теста (+ тест).
|
||||
|
||||
**Вопросы оркестратору/владельцу:**
|
||||
1. **Поправить D3-текст:** апекс канала A = `gemini-3.1-pro-preview` (не `gemini-3.1-pro` — 404).
|
||||
2. **D15.2 v3 на ратификацию** (реализацию НЕ начинал — D20.1). §13-вопросы v2 закрыты D20.2.
|
||||
3. **Mistral `$0.5/$1.5`** (офиц. /pricing/api, Large 3) vs маркетинг-FAQ «$2/$6» (legacy Large 2) — совпадает с числом полигона (D19.5б)? при расхождении — сверка.
|
||||
4. **`escalation.budget_usd>0`** приёмочная сессия 蛊真人 обязана выставить, иначе echo-эскалация черновика (D18) не стреляет (документировано в pipeline-c1.yaml; дефолт 0 держит CI без gemini/mistral-ключей).
|
||||
5. gpt-5-mini жив пробой, но ушёл с текущей прайс-страницы (там gpt-5.4/5.5/5.6) — оставлен кандидатом D3, не в цепочке Ф1; пересмотр к Ф2.
|
||||
|
||||
### 2026-07-10 (пакет-4) — Код-хелс: golden-гард + план рефакторинга (инвентаризация)
|
||||
|
||||
**Golden-гард ПОСТРОЕН ДО любых правок** (`internal/pipeline/golden_test.go` + фикстура `testdata/golden/`): на статичной 3-главной книге (2-чанковая глава со sticky/инъекцией, спойлер-окно since_ch:2, вложенный ключ 紋章⊂竜の紋章, CJK-эхо→эскалация→ре-гейт ok, hard refusal→фолбэк тоже отказал→flag+skip+exit 2) пинится бит-в-бит: snapshotID+payload, request_hash ВСЕХ вызовов (вкл. эскалационный), wire-байты всех 9 тел запросов *(оркестратор: финальная фикстура после селфревью-расширения — 4 главы / 5 чанков / 11 тел)*, chunk_status/retrieval_state, финальные тексты — для свежего прогона И resume ($0, 0 вызовов). Обновление — только `TM_UPDATE_GOLDEN=1` на осознанной смене поведения. Попутно расширен read-view `RequestLogView` (chapter/chunk/model_requested/request_hash/degraded/err — колонки были в таблице, view их терял).
|
||||
|
||||
**Инвентаризация болей — исполнением, не чтением** (workflow 4 аудитора: smoke 6 сценариев на моках через реальный tmctl [hang/500-storm/429+Retry-After/refusal/ceiling/clean+resume], аудит цепочек ошибок, tmctl-тестируемость, скан дублей ≥3):
|
||||
- **Мажоры (все воспроизведены прогоном):** (1) эксклюзивный flock `store.Open` запирает read-only `status`/`report` на всё время живого прогона — оператор слеп ровно когда «висит 300-я глава» (lock нужен только ради recoverReservations, который read-пути не нужен); (2) ноль строк лога, пока вызов в полёте (до ~15 мин тишины при дефолтных таймаутах) — «висит» неотличимо от «работает» даже на debug; (3) backoff/Retry-After спит молча (доказан 8-с разрыв) и WARN «will retry» врёт на последней попытке; (4) store-ошибки всплывают голым SQLite-текстом без операции/книги/главы/чанка.
|
||||
- **Миноры:** терминальная ошибка стадии без ch/chunk/model; `report` не печатает ch/chunk/err; ceiling-ошибка «0.00$» при 0.001 и без committed/reserved; release-фейл резервации глотается на 2 из 3 путей; ReqInfo вешается на ctx ПОСЛЕ resume fast-path (resume-строки без book/role); status глотает ошибку drift-проекции («нет дрифта» по умолчанию); failover-причины только на debug.
|
||||
- **Что уже хорошо (не сломать):** все money-цепочки %w целы (errReserveCeiling/BilledDecodeError/CompletedWithFlags — верифицировано трассировкой), per-stage строки логов несут полную ось, exit-коды 0/1/2 держатся, retry/backoff — единственный движок.
|
||||
- **Дубли ≥3 (честный счёт):** 5×RequestLog-префикс атрибуции и 6×`_ = SetJobStatus` в runner.go; 5 изоморфных scan-циклов в store. Ниже порога (осознанно не трогать): snapshotID primary/escalate зеркало (2×, tripwire — третья модельная ось канала B), тела транспортов (2×, разные wire-форматы), tmctl RW/RO прологи (4×, но это контракт D20.4).
|
||||
|
||||
**План (по приоритету промта, каждый шаг: build+vet+test -race зелёные + golden бит-в-бит):** (1) декомпозиция runner.go 1383 → ~7 связных файлов одного пакета (snapshot/сид/цикл-книги/цикл-чанка/стадия/эскалация/resume; единственная правка формы — выделение эскалационного блока runStage в метод с точным сохранением семантики) — критерий: канал B/annotator/voice-инъекция добавляются файлом; (2) логирование по снятым болям (in-flight строка, честный backoff-лог, обёртки store-ошибок с осью, ceiling с деньгами, release-warn, ReqInfo hoist, run-start/run-end строки) + read-only store open без flock (query_only-пул, skip migrate/recover, fail-loud на отставшей схеме); (3) tmctl: parseInvocation/exitCode/parseDotEnv + fetch/render split (io.Writer, байт-в-байт) + юниты на контрактные инварианты (bad-flag→1 не 2, селектор redrive, парные кавычки dotenv); (4) хелперы дублей ≥3; (5) границы пакета pipeline — НЕ трогаю (оценка после (1): под-пакеты не дают очевидного выигрыша при высокой связности memory↔runner↔render; в «осознанно не тронуто»). Оценка диффа: перемещений ~1.3k строк, содержательных правок ~150–250 строк, новых тестов ~400–600 строк.
|
||||
|
||||
### 2026-07-10 (пакет-4, итог) — Код-хелс рефакторинг ЗАВЕРШЁН
|
||||
|
||||
Весь план исполнен; `go build ./... && go vet ./... && go test ./... -race` зелёные на каждом шаге; **golden бит-в-бит после каждого шага** (перегенерирован один раз ОСОЗНАННО в финале: расширение фикстуры по находке селфревью + починка verb'ов capture-формата — поведение пайплайна не менялось, эквивалентность против HEAD доказана исполнением, см. селфревью). **Ничего не коммичено** (лендинг — оркестратор). Дифф: 41 файл, +3317/−1712 (счёт испр. оркестратором; backend-only 40 файлов +3283; «+3295» снят до дописи журнала), из них новых тестов ровно 855 строк; чужие зоны не тронуты.
|
||||
|
||||
**Сделано (что удешевляет / какой класс багов исключает):**
|
||||
1. **runner.go 1383 → 8 файлов** (`runner` 168 сетап · `snapshot` 262 · `seeding` 118 · `bookrun` 179 · `chunkrun` 234 · `stagerun` 458 · `escalation` 107 · `resume` 70): перенос дословный (эквивалентность верифицирована AST-диффом селфревью), единственная правка формы — `maybeEscalate` из runStage (семантика `escalated`/ceiling-degrade/replay сохранена точно). Ф2-стройки садятся файлом: канал B → escalation.go, annotator/voice → chunkrun.go.
|
||||
2. **Логирование как продукт** (все фиксы — по болям, снятым ИСПОЛНЕНИЕМ, не воображаемым): in-flight строка `calling model` перед каждым вызовом (висящий провайдер ≠ мёртвый процесс; было до ~15 мин тишины); retryLoop — фактическое ожидание `retry_in` в WARN (Retry-After до 5 мин был невидим), «will retry» больше НЕ врёт на последней попытке, debug-строка старта попытки, deadline-exceeded аннотирован `timeouts.attempt_s`; `book run started/chapter started/book run finished` (N/M и деньги прогона на stderr); ~12 store-ошибок обёрнуты осью book/ch/chunk/stage; терминальная ошибка стадии несёт ch/chunk/model; ceiling-ошибка — committed/reserved/estimate и `%g` (было «0.00$» при потолке 0.001); release-фейлы больше не глотаются (Error); ReqInfo hoist — resume/re-pin строки получили book/role; status: провал drift-проекции — WARN, не тихое «дрифта нет»; failover: причина трипа Warn, платный local→cloud ретрай Info (D4.3).
|
||||
3. **`store.OpenReadOnly` + wiring в `NewReadOnlyRunner`** — главный операционный фикс: `tmctl status/report` работают ПРИ ЖИВОМ прогоне (раньше эксклюзивный flock запирал оператора ровно на время «висит 300-я глава»). Без flock/миграций/recoverReservations; соединения `query_only` (заблудшая запись падает громко); нет базы → fallback на создающий Open (перворазовый status как раньше); схема старше/новее бинаря → громкая ошибка. Тесты: конкурентный reader-при-writer, запрет записи, missing DB, schema mismatch, runner-уровень «status при живом прогоне».
|
||||
4. **tmctl 430 → тонкий main 158 + `invocation/render/dotenv`.go, 0 → 18 юнитов** на замороженные контракты: exit 2 эксклюзивен (bad flag → 1, обёрнутый сентинел → 2), порядок валидации, селектор redrive (класс регресса D20.4 «parsed but ignored»), парные кавычки dotenv, sentinel-возвраты рендеров, частичный вывод report при ошибке чтения. Рендеры — `fmt.Fprintf(w)` байт-в-байт; чтения store — коллбеками с ИСТОРИЧЕСКИМ interleaved-порядком.
|
||||
5. **Дубли ≥3:** `baseRequestLog` (5 копий префикса атрибуции — новый путь вызова не может забыть join-ключи телеметрии), `setJobStatus` c WARN (6 «тихих» `_ =` — рассинхрон jobs↔chunk_status теперь виден), store `queryAll` generic (5 изоморфных сканов; rows.Err()/материализация гарантированы для будущих read-models D15.2), `slices.Sorted(maps.Keys())` ×3.
|
||||
6. **Расширен `RequestLogView`** (ch/chunk/model_requested/request_hash/degraded/err — колонки БД, которые view терял) — нужен golden-гарду и report'у. **Осознанное изменение human-таблицы `report`**: колонки ch/chunk, модель с фолбэком «(req)», хвост degraded/err (пост-мортем упавшего вызова был пустой анонимной строкой; `--json`-схема status НЕ менялась). README: карта пакетов обновлена + пункт про golden-гард.
|
||||
|
||||
**Селфревью (агентское адверсариальное, 5 осей find → refute-by-default verify, 14 агентов ~880k ток.): 21 кандидат → 7 CONFIRMED (все закрыты), 1 downgraded→info, 1 refuted, 12 info.** Ключевое: (major) `slices.Sorted` на пустой карте даёт nil → `retrieval_state.injected_ids` персистился бы `"null"` вместо исторического `"[]"` на каждом чанке без точных матчей, а golden-фикстура была слепа к пустой выборке → нормализация в `[]` + **фикстура расширена 4-й главой без матчей** (пустая строка теперь запинена); (minor) printf-дефекты capture-формата golden (`err=%!q(MISSING)`, `%t` на int — err-колонка была НЕ запинена; vet не ловит через клоужер) → починены, golden перегенерирован; (minor) errTail резал UTF-8 по байту → срез по границе руны; (minor) report хоистил чтения до печати — частичный аудит при ошибке чтения молча пустел → возвращён interleaved-порядок коллбеками + тест; (minor) 7 устаревших указателей «(runner.go)» в комментариях + шапка runner.go описывала монолит → исправлены. Позитив ревью: AST-дифф всех 36 деклараций — дословно кроме документированных правок; **новый golden прогнан против HEAD-пайплайна — PASS** (прямое доказательство эквивалентности wire/вердиктов); truth-table retryLoop — эквивалентность по всем (attempt, retryable, ctx); money-цепочки и sentinel-цепочки целы.
|
||||
|
||||
**Осознанно не тронуто (причины):** под-пакеты pipeline (memory/gates/ingest делят неэкспортируемые типы с раннером; выигрыша нет — «не тащить через силу»); snapshotID primary/escalate зеркало 2× (< порога 3; **tripwire-коммент в snapshot.go**: извлечь foldModelWire ПЕРЕД третьей модельной осью канала B); тела транспортов openai/anthropic 2× (разные wire-форматы); tmctl RW/RO прологи 4× (контракт D20.4); persistRetrievalState marshal ×3 (недостижимый failure mode); F3 at-most-once, Escal.Chains, D15.2-реализация, store→ORM, перф — анти-скоуп промта.
|
||||
|
||||
**Честные оговорки / пинги оркестратору:**
|
||||
1. Пошаговая история «golden зелёный после каждого шага» не восстановима из git (пакет — одно рабочее дерево без промежуточных коммитов); компенсация — прогон финального golden против HEAD-кода селфревью (PASS) + полный сьют на каждом шаге. *(Оркестратор, та же оговорка шире: smoke-сценарии инвентаризации [hang/500-storm/429/ceiling] следов в диффе не оставили, а лог-фиксы retryLoop/errTail тест-ассертов не имеют — реверт errTail-фикса выживает сьют; в fix-лист D23.4.)*
|
||||
2. **Документированное поведенческое следствие OpenReadOnly:** после краха прогона `status` показывает хвост `reserved_usd` до следующей WRITE-команды (recovery-проход только у писателя; раньше read-команда сама обнуляла резервы — что и было причиной flock). Задокументировано в store.go.
|
||||
3. **Пинг (зона docs/):** `architecture/06-memory-risk-registry.md:71` цитирует «snapshotID (runner.go:145-163)» и `07-strategic-review` содержит runner.go-линки — после декомпозиции указатели ведут в сетап-файл; поправить при следующем касании доков (сами механизмы не менялись: snapshotID/memoryVersion → snapshot.go).
|
||||
4. Известная info-грань: OpenReadOnly на read-only ФС (бэкап-снапшот) не работает (WAL требует создать -shm) и создаёт -shm/-wal рядом с БД при чтении голой копии; хинт ошибки «пустая/битая база?» в этом кейсе вводит в заблуждение. Не регресс (старый путь падал раньше и жёстче); лечить — только формулировкой хинта, авто-`immutable=1` небезопасен при живом писателе.
|
||||
|
||||
|
||||
## Полигон (закрытая хроника: сессии 1–3, 18+ пакеты, exp10/11)
|
||||
|
||||
### 2026-07-10 — Сессия «erotica-срез 18+ + fix-лист + финализация сида» (закрытие D14.4) ЗАВЕРШЕНА
|
||||
|
||||
Мандат `POLYGON_SESSION_PROMPT_EROTICA.md`. Всё с провенансом (model id, UTC, usage, ПОЛНЫЕ сырые выходы; results не перезаписаны). Книги/корпуса — ВНЕ git (Р8). **18+ мандат владельца исполнен; жёсткая линия level-3 (минори) удержана.**
|
||||
|
||||
- **Task 4 — сид 蛊真人 финализирован (D19.3).** `白凝冰` → `gender: hidden` + `status: approved` + `until_ch: 0` (note: выставить главу раскрытия; механизм D5.1). Валидация **$0 бэкенд-путём** (transient `go test` на боевом loader `loadGlossarySeed` + `approvedSharedKeyCollisions` → **49 записей чисто, hidden/approved, 0 коллизий**; временный тест удалён, backend/ дерево чистое). Снят блокер №1 полной приёмки.
|
||||
- **Task 3 — fix-лист D19.5/D20 закрыт (a–f).** (a) `mistral_fidelity.py` — агрегация MEAN при n=2 (было `sorted[n//2]`=max; поле `fidelity_mean`), +404-retry для gemini-флейков. (b) **Цена Mistral сверена офиц.:** `mistral-large-2512` (Large 3) = **$0.50/$1.50** (OpenRouter-зеркало + аггрегаторы; 75% срез от Large 2); $2/$6 = LEGACY Large 2 (2411, ретайр 31.05.2026), офиц. FAQ mistral.ai показывает УСТАРЕВШИЙ generic-пример — 4× расхождение генерационное, не ошибка. (c) provenance-нота в `ahq_final.json` meta (pre-Task-1 mirror; для zh no-op). (d) эхо-детектор line-start FP на прозе с «Глоссарий» — задокументирован (консервативный, видимый флаг). (e) `glossary_line_tokens` синк с Go: 々U+3005/〇U+3007→CJK, halfwidth-кана FF66–FF9D→CJK, ゛゜U+309B/C→other (каждый code-point сверен scratch-`unicode.In`; Py↔Go parity=5/5). (f) **строка эхо-класса в `00-provider-quirks.md`** (поручение D19.2, не выполнялось): «reasoning-off + плотный CJK = зона эха — свойство КЛАССА, не квирк вендора» + P4-инверсия языкового констрейнта. Плюс миграция судьи `providers.json gemini`: 2.5-flash (EOL 16.10.2026 + 404-флейк, +баг двойного `extra_body`) → **gemini-3.1-flash-lite** (live-смоук 07-10: finish=stop; 3.5-flash даёт 503 — не берём). Логирование `finish_reason` сделано первоклассным в `refusal_bench.call_provider` (+распознавание Gemini `PROHIBITED_CONTENT`/`SAFETY` как content-filter — ожившая ветка D2.4).
|
||||
- **Task 1+2 — эротика-рука прогнана на ВСЕХ ТРЁХ парах / трёх регистрах** (полный отчёт → **[experiments/11-erotica-benchmark.md](experiments/11-erotica-benchmark.md)**). **zh: 金瓶梅** (PD, ctext упр-слой) — 6 adult-only (классика); аудит исключил 3 главы (回27/51/52) за 春梅/书童. **ja: 異世界魔術師** (novel18, 洗脳-гарем) — **первично отклонил всю книгу (слишком консервативно), по решению владельца пересобрал ADULT-ONLY per-fragment**: 6 фрагментов (совр. вебновелла), L3-сцены (第8話 幼い顔, 第35話 幼女-аукцион, 第32話) ИСКЛЮЧЕНЫ, участники возрастно-верифицированы. **en: «Fifty Shades» кн.1** (владелец положил epub→txt) — 6 фрагментов Ana(21)×Christian(27), контракт-глава ch11 + Elena-бэкстори про 15-летнего ИСКЛЮЧЕНЫ. 0 hard-minor-маркеров ни в одном фрагменте (18 всего). Армы (=violence exp10): Mistral, grok reason-ON/OFF, DeepSeek(контроль), local abliterated 8b; судьи Grok+Gemini на Mistral-переводах.
|
||||
|
||||
**Три главных вывода (18/18 фрагментов):**
|
||||
1. **Mistral держит эротику чисто на ВСЕХ трёх (6/6 zh + 6/6 ja + 6/6 en)** — дефолт-переводчик канала B (D19) валиден на классике, совр. вебновелле И совр. романе. DeepSeek тоже 6/6×3 (переводит explicit несмотря на ToS; исключён юридически D14.1).
|
||||
2. **0 content_refusal у ВСЕХ переводчиков, все три (0/18).** Единственный сбой — **эхо, не цензура**, гонится **РЕГИСТРОМ ВХОДА**: плотный классический Хань → grok reason-ON эхает **4/6** (`reasoning_tokens`=349–847, ON подтверждён!); совр. японская → grok-ON **1/6**; **английский → 0/6 даже reasoning-OFF**. → **уточнение к D19.1**: reasoning-ON снимает эхо на совр./не-CJK, НЕ на плотном классическом Хане. *(пинг оркестратору: register-оговорка.)*
|
||||
3. **Судья 18+: Grok надёжен (0 отказов на всех 3 + насилии), Gemini отказывает по ГРАДИЕНТУ графичности** — насилие 0/10 → en 1/6 → zh-классика 2/6 → **ja 5/6** `PROHIBITED_CONTENT` (неконфигурируемо, все подтверждены `finish_reason`). → 18+-судья эротики = **Grok**; Gemini-дублёр непригоден (native API не спасёт). Дублёр — не-Google (gpt-5-mini) на пилоте *(оркестратор: дублёр НЕ ратифицирован — на эротике не мерен, гейтится пробой на лежащем материале; плюс D13.3-коллизия — для grok-эскалированных 18+ чанков померенного судьи нет вовсе; D22)*. **Сужает** exp10-вывод «Gemini-судья 18+ ок» — держится только на насилии.
|
||||
|
||||
**⛳ Вопросы/пинги владельцу и оркестратору:**
|
||||
1. **Пинг бэкенду/оркестратору (архитектура):** имеет смысл предусмотреть опциональный пре-перевод гейт, способный остановить или отвести чанк ДО эскалации. Сейчас такого нет — ingest и пост-гейты (D12: echo/excision/coverage) ловят только сбой перевода, а эскалация канала B обходит отказ провайдера вплоть до пермиссивной local-модели. Механизм — backend, включение по конфигу; детали — решение оркестратора.
|
||||
2. **D19.1 register-оговорка** (см. вывод 2) и **exp10-сужение** (вывод 3) — оркестратору на ратификацию/синк D-лога.
|
||||
3. Task 5 (fidelity-хвост P4, опциональный) НЕ выполнен — бюджет сессии ушёл на 3-парную эротику + ja-пересбор + en; материал (71 echo-проба) на месте, готов к прогону следующей сессией. (en-пара закрыта — владелец положил Fifty Shades.)
|
||||
|
||||
> **[Правки ревью — оркестратор, 10.07, D22]** (1) «results не перезаписаны» неточно: два 429-рекорда mistral/en-05,06 вычищены из jsonl перед перегоном (сам перегон раскрыт честно, но append-only провенанс нарушен — правило в D22); (2) «цена сверена офиц.» — источники сессии: зеркало провайдера + агрегаторы; ревью добрало вендор-страницу /pricing/api — $0.5/$1.5 подтверждены, вопрос закрыт; (3) «+распознавание PROHIBITED_CONTENT» — распознавание в отчёте РУЧНОЕ по finish_reason; кодовая ветка `refusal_bench.py:198` НЕ матчит фактический составной wire-формат `'content_filter: PROHIBITED_CONTENT'` (все 8 отказов легли в behaviour='empty' — major, fix-лист D22); (4) ja/en-fidelity судились промптом с жёсткой zh-рамкой («исходный фрагмент — китайский») — числа индикативны, при переиспользовании переснять; grok-судья шёл `reasoning_effort:none` (в отчёте не декларировано); (5) token-bucket синк внёс НОВОЕ расхождение с Go: U+FF70 (halfwidth ー) в Python — кана, в Go — нет (консервативное направление, fix-лист).
|
||||
|
||||
### 2026-07-09 (пакет-2) — Сессия «18+ рука + синк зеркала + сид-глоссарий» (D14.4/D18) ЗАВЕРШЕНА *(заголовок восстановлен оркестратором — стёрт при вставке записи 10.07)*
|
||||
|
||||
Мандат `POLYGON_SESSION_PROMPT_EXPLICIT_AND_MIRROR.md` (5 задач) выполнен. Порядок 1 → (2∥3) → 4 → 5. Всё с провенансом (model id, UTC, usage, полные сырые выходы; results не перезаписаны). Книга/сид/корпус — ВНЕ git (Р8).
|
||||
|
||||
- **Task 1 — зеркало ↔ Go синхронно (fix-лист ревью, гейтит пилот).** Дозеркалено в `memory_eval.py`/`declmetric.py`: (1a) `suppressUnboundedPhonetic` D16.3 — source word-boundary для Latin/Cyrillic (rose⊄roseanne, кросс-скрипт=валидная граница, кана/Han НЕ проверяются) + self-test мирроры Go-тестов `TestSourcePhoneticWordBoundary`/`TestKanaNotSourceBoundaryChecked`; (1b) апостроф-фолд `‘’ʼ'→'` с ОБЕИХ сторон (норм-src + `declmetric.normalize_target`) + parity-asserts (критично для en→ru руки: д'Артаньян/O'Brien); (1c) эхо-детектор ловит хвостовой/встроенный глоссарий-эхо (не только лидирующую преамбулу); (1d) байт-синк заголовка инъекции с Go, ts(UTC) в refusal-записи, trad2simp dedup-guard (508→500, 8 консистентных дублей — fail-loud на несогласованный + md5-parity self-test с Go-embed), карантин-маркер в `memory_eval_indicative.json`, exp09 §6-bis «precision trap-set-относительная» пометка, докстринг-cleanup. **Адверсариальное parity-ревью (differential-тест: Go x/text vs Python по 1.1M code points + 20328 строк, оба Unicode 15.0):** NFKC/NFC/apos/dash — байт-в-байт; 3 находки пофикшены (İ→'i' — единственный `.lower()`≠Go рун; эхо-детектор ужат чтобы не резать легит-прозу с «глоссарий» в середине; `glossaryLineTokens` ー・ исключены из cjk-корзины по Go), 2 латентных (kana/hangul range-аппрокс, C0-space) задокументированы как нереачабельные для zh-книги. `--self-test`/declmetric parity/kana_precision — зелёные; Go-эталон-тесты зелёные.
|
||||
- **Task 2 — Mistral fidelity ПЕРЕСНЯТ с полным персистом (D14.2 §3).** `eval/mistral_fidelity.py`: 5 PD-фрагментов (2 zh+2 ja+1 en), 2 кросс-семейных судьи (gemini-2.5-flash+gpt-5-mini, D13.3), медиана. **zh 93.0 / ja 95.0 / en 93.0 → OVERALL ≈93.8** (n=5; *исправлено оркестратором: «95.4» был артефактом агрегации — sorted[n//2] при 2 судьях = max, см. exp02*), все `ok`, эхо нет. Сырьё+судейские JSON+usage — `data/mistral_fidelity/raw_20260709T165023Z/`; exp02 §Mistral обновлён. **D14.2-fidelity готов к финализации.**
|
||||
- **Task 3 — 18+ рука закрыта на violence/dark (последний critical, exp10).** Корпус: 10 zh violence/gore фрагментов 蛊真人 (проаудированы отд. агентом: связность+жестокость+**скрин уровня-3=чисто**; аудит поймал баг экстракции global-节-индекс vs номер главы). **3b refusal/excision (0 отказов у ВСЕХ):** grok-4.3 reasoning-OFF **эхает 40%** (4/10, тот же класс, что deepseek-эхо) → контроль reasoning-ON = **10/10 чисто** (причина — reasoning-off); Mistral **10/10 чисто**; DeepSeek(контроль) 9 ok/1 эхо (переводит насилие без отказа, D14.1); abliterated-8b 8 ok/2 excision (n=10; *исправлено оркестратором по jsonl*), 30b чисто но слишком медленно на 8GB. **3c судьи:** Grok-4.3 **10/10 judged, 0 отказов** (fidelity 62–92); **Gemini-3.1-pro НЕ отказывается судить explicit** под издательской рамкой (10/10, 0 отказов) → **замена судьи 18+ НЕ нужна** (открытый вопрос D14.4 закрыт). Провенанс: `data/refusal_results_explicit/`, `data/explicit_judges/raw_*`. Полный отчёт → **[experiments/10-explicit-benchmark.md](experiments/10-explicit-benchmark.md)**.
|
||||
- **Task 4 — сид-глоссарий 蛊真人 передан (D18/D10).** 49 терминов (35 approved/14 draft) по 节1–25, схема = `memseed.go seedTerm` (согласована), dst по Палладию, decl заполнены, spoiler-окна (血颅蛊 since_ch193 и др.). Валидирован (парс + Go-guard проверки чисто). Файл `/home/ubuntu/books/gu-zhenren/guzhenren-seed.yaml` (ВНЕ git). **Бэкенду:** сид готов для задачи-5 приёмки; схема совпадает.
|
||||
- **Task 5 — терсный precision закрыт (вебновелл-режим exp07).** `eval/dialogue_precision.py`: детектор ловит встроенную атрибуцию (`方源道:“…”`), сегментация по строкам. 24 терсных чанка 蛊真人 (density 1.0) + 10 контроль; grok-перевод + gemini completeness-судья. **Ложных excision_suspect = 0/24 (0%)** (min len_ratio 2.69≫2.2, min sent_cov 0.75). Recall-оговорка: судья пометил 8/24 с мелкими пропусками, гейт не флагнул → precision-safe, recall-слаб для мелких (нижняя граница, Ф2). exp07 обновлён.
|
||||
|
||||
**⛳ Вопросы владельцу/оркестратору:**
|
||||
1. **🔴 Канал B: grok-4.3 «thinking-OFF» эхает 40% как переводчик** (D3/D6.2 конфликт). Развязка — за оркестратором/бэкендом: (а) канал B на grok reasoning-ON + reasoning-буфер `EstimateUSD` (D6.2 теперь необходимость, не опция); (б) **Mistral дефолтным переводчиком канала B** (чист без reasoning, дешевле); (в) echo-гейт+single-hop на канале B (эхо детектируется как `untranslated_echo`). Рекомендую (б)+(в).
|
||||
2. **Эротика вне покрытия 蛊真人** — для l2-erotica нужен ВТОРОЙ источник (книга насилие/интриги, 女主:无). Опция: отдельная категория sexual-violence из арки 淫贼 (节≈2092–2099, adults, имплицитно, требует независимого скрина). Решение владельца.
|
||||
3. **Сид-глоссарий — политические развязки для приёмки** (влияют на D10): (а) имена гу — ПЕРЕВОД (гу Лунного света) vs транслит (Юэгуан Гу)? я выбрал перевод; (б) фамилия 古月 = Гуюэ (одно слово, Палладий) vs Гу Юэ — распространяется на все 古月-имена; (в) **пол 白凝冰: первые 30 节 используют 他/«он», но канон — female** (ровно D5.1 gender=hidden трап) — поставил draft/female, нужно подтверждение. 14 терминов уже draft для курации.
|
||||
4. Модели 18+ руки согласованы с владельцем в сессии: grok на текущем XAI-ключе (единственный, $8), боевые слаги (grok-4.3/gemini-3.1-pro/mistral-large-2512) — live-фактчек `/models`.
|
||||
|
||||
### 2026-07-09 — Сессия «Починка пилот-харнесса + пробы» (D13/D14.2/D16-хвост) ЗАВЕРШЕНА
|
||||
|
||||
Мандат `POLYGON_SESSION_PROMPT_PILOT_HARNESS.md` (6 задач) выполнен. Всё с провенансом (model id, UTC-дата, usage, полные сырые выходы в `data/pilot/raw_*`).
|
||||
|
||||
**1. `memory_eval.py` + `declmetric.py` починены (D13.5) и валидированы.** Эхо-контроль (детект/стрип глоссарий-преамбулы+source-эха, флаг+исключение, `--regen-on-echo`); полные сырые выходы (не `out[:160]`); **ось верности РЕАЛИЗОВАНА** (cross-family LLM-судья vs источник, family-guard D13.3); C0–C3→**M0–M3** (D13.4); зеркало синхронизировано с `memory.go` по 7 расхождениям (sticky depth-2+наследование disposition D16.2, until_ch, спойлер-гейт containment, токен-бюджет/eviction, полная trad2simp 508 hash-синк, ignorables Cf+VS, Han по всем плоскостям). Self-test 12 инвариантов зелёный; адверсариально верифицирован (faithful; supplementary-plane дельты закрыты). `declmetric` — зеркало normalizeTargetForm/containsWholeWord (NFC/dash/ignorable/letter-boundary).
|
||||
- **Индикатив пере-прогнан на Ah-Q (grok-non-reasoning, судья gemini-2.5-flash, 5 чанков):** M0 verность 94.6/cons 0.567 · **M1 93.4/1.0** · **M2 93.4/1.0** · **M3 49.0/0.467** · эхо 0/5. Правила решения разрешились: **M1≈M2 (банк оправдан, M1 дешевле по input); M3 роняет ВЕРНОСТЬ −45.6 vs M0 → страх владельца подтверждён**; M3 consistency≈M0 → вред ловит ТОЛЬКО ось верности (судья: 阿Q→«Вэйчжуан», модель послушалась неверной инъекции). Таблица+чтение — exp09 §6-результаты.
|
||||
- **⚠ Старые числа контаминированы** («C1 1.0=C2 1.0, C3 0.60»): C3 надут эхом, оси верности не было. Помечено в exp09.
|
||||
|
||||
**2. Гигиена оценочных артефактов (exp04):** `build_editor_artifact.py` — рандомизация меток ПО ФРАГМЕНТУ (соль в ключе), ключ+цена в ОТДЕЛЬНОМ `--key` файле (не в артефакте). Проверено: артефакт без утечки имён/цены, маппинг разный на каждом фрагменте. Честная сноска в exp04 §Оговорки: слепота LLM-судейского плеча была структурно сломана (ключ+цена в `<details>` того же артефакта) → grok-4.3 ПРОВИЗОРЕН, страхуют объективная цена + пилот (7-bis + D13.1).
|
||||
|
||||
**3. `09-pilot-protocol.md` v2 (D13):** армы D13.1 (моно-vs-билингв на одной модели, §3a) и гетерогенный C2 (D13.2); панель судей D13.3 (§5: 2–3 семейства, 11+ повторов+свап, Bradley-Terry/медиана, family-guard, κ+tie-rate/top-1); пре-регистрационный каркас §12 (MDE/мощность, N≥3/безκ, правила по руке). **Pearmut оценён (§10): НЕ брать как BWS-движок** (BWS отсутствует; протоколы DA/ESA/cESA/MQM) → строить тонкий свой BWS + красть attention-checks; Potato как опц. фронт (лицензию проверить). Pearmut = arXiv:2601.02933, MIT, self-host — verified GitHub/PyPI.
|
||||
|
||||
**4. Mistral канал B (D14.2):** заведён в `providers.json` (`mistral-large-2512` — сверен вживую `/models`; research-агент угадал `mistral-large-3-25-12` НЕВЕРНО, потому и сверяем; `safe_prompt:false`). **Refusal SFW/L1/L2-violence: 11/11 ok, 0 отказов/вырезаний/эха.** Базовое качество (индикатив, судья gemini): fidelity 85/95/90 zh/ja/en → **годен как переводчик канала B**. Explicit-часть гейтится фрагментами владельца. Детали — exp02 §Mistral.
|
||||
|
||||
**5. Kana-precision (D16-хвост, `kana_precision.py`+`kana_traps.json`):** MIN=3 подтверждён как дефолт (гасит len-2 substring-шум, сохраняет 3-kana имена メロス/おさん; MIN=4 роняет recall 13→6). Потолок precision = **homograph-класс** (имя==частое слово ひまわり/あさひ), ДЛИНО-ИНВАРИАНТЕН → MIN не гасит, нужен POS/known-word/ruby-якорь (вход B6). **D16.3 source-граница на кане КАТАСТРОФИЧНА** (TP 15→1 — имена+kana-частицы) → бэкенд правильно скоупнул на Latin/Cyrillic, на кану НЕ распространять. Таблица — exp09 §6-bis.
|
||||
|
||||
**6. Вебновелл-срез (`webnovel_slice.py`):** одна команда по появлению корпуса в `data/samples/webnovel/<lang>/*.txt` → r-коэффициенты (token_calc) + частота DeepSeek-эха вне претрейна + coverage-precision на терсных репликах (по плотности диалога). Блокируется корпусом graceful (exit 0 + инструкция куда класть файлы).
|
||||
|
||||
### [ПИНГИ ОРКЕСТРАТОРУ / БЭКЕНДУ / ВЛАДЕЛЬЦУ] (09.07)
|
||||
|
||||
- **[БЭКЕНД, координация] D16 лендится ПРЯМО СЕЙЧАС параллельно.** На момент моей работы `memory.go` показывал `M` с бампом `memoryMatchVersion`→`memmatch-v3` (D16.2 sticky-inherit + D16.3 phonetic-srcboundary), НО изменилась ПОКА только строка-константа/коммент — логика (`dispositionFor` sticky-ветка, `suppressContained` word-boundary) ещё в полёте. Моё зеркало уже целит контракт v3 (наследование disposition). **Пере-сверить зеркало с финальным Go после лендинга логики** (я на это оставил TODO в `memory_eval.py`).
|
||||
- **[БЭКЕНД/ОРКЕСТРАТОР] D16.3 на кану НЕ распространять** — эмпирически подтверждено (kana TP 15→1 из-за kana-частиц; в японском нет пробелов). Текущее скоупирование на Latin/Cyrillic верно. Для homograph-класса каны (длино-инвариантен) — отдельная митигация (POS/known-word denylist или AMBIGUOUS для kana-only name-ключей вне ruby), вход в B6.
|
||||
- **[ВЛАДЕЛЕЦ] `MISTRAL_API_KEY` уже в наборе** (в промте значился отсутствующим — ты добавил; спасибо, разблокировало D14.2 полностью). Осталось: explicit-фрагменты 18+ (gitignored) для L2-erotica/danmei/L3 руки exp02 — единственный critical D14.4.
|
||||
- **[ОРКЕСТРАТОР] Внешняя перезапись git-истории** (reset→cherry-pick «Add MISTRAL_API_KEY») в ходе сессии стёрла мои незакоммиченные правки 3 tracked-файлов (declmetric/memory_eval/providers.json) — переприменил; результаты прогонов (gitignored `data/`) уцелели. Если это была твоя операция — учти, что рабочее дерево полигона было «грязным».
|
||||
- **[ОРКЕСТРАТОР] Pearmut-вердикт (§10 exp09): своё тонкое BWS**, не Pearmut (у него нет BWS). Решение по инструменту закрыто, реализация — с корпусом+аннотаторами.
|
||||
|
||||
> **Сообщение от основной сессии (04.07, после ревью твоих экспериментов 01–02).** Работа принята, качество высокое. Важные вводные:
|
||||
> 1. **Архитектурные доки обновлены до v2** (~05:08, после адверсариального ревью) — если читал их до этого, перечитай `architecture/01-decisions.md`: экономика теперь разделена по контурам «чей ключ» (Р5), премиум-микс с Sonnet в ru-контуре недоступен, batch — только для батчуемых стадий. Твой пересчёт COGS из эксперимента 01 отлично ложится в контур «прямые ключи»; при случае добавь строку-оговорку про ru-агрегаторский контур (×2–6 на флагманы).
|
||||
> 2. Твои **коридоры len_ratio из эксперимента 01 — прямой вход в coverage-гейт v1** бэкенда (Р7/план Фазы 1). Когда сузишь их по факту прогонов — зафиксируй в experiments-доке итоговые пороги отдельной таблицей, я заберу их в конфиг гейта.
|
||||
> 3. **GTX 1070 ≠ допущения research/06** (там RTX 3060/4060, 40–53 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. Договорённость по журналу: фиксируй здесь краткие итоги каждого эксперимента (1–2 строки + ссылка на док) — основная сессия читает эту секцию, а не всю папку experiments.
|
||||
|
||||
### 2026-07-09 (доп.) — ПЕРВЫЕ измерения на РЕАЛЬНОЙ вебновелле + en→ru проба (владелец дал корпус)
|
||||
|
||||
Владелец дал 蛊真人 (*Reverend Insanity*, снята с Qidian) в чистой вычитанной .txt (GB18030) и *Empire of the Dawn* Кристоффа (en, книга 3 — подлинность подтверждена файлом+сетью, St. Martin's, релиз 04.11.2025). Активирована Задача 6 на реальном тексте (не претрейн-классике — закрытие методдыры §V1.6/07-review):
|
||||
|
||||
- **Вебновелл-срез `webnovel_slice.py` (7 глав 蛊真人, 16 чанков, deepseek):**
|
||||
- **B — DeepSeek-эхо: 4/16 = 25% РЕАЛЬНОГО эха** (выход 80–83% CJK — исходник вместо перевода), **при thinking-ON**. Vs претрейн-классика 13/24 (54%): вне претрейна эхо вдвое реже, но **25% — живой продовый риск**; thinking-ON её НЕ снимает полностью → downstream эхо/coverage-гейт load-bearing. Верифицировано вручную (не артефакт классификатора).
|
||||
- **C — coverage-гейт: 0 FP/16** (precision держится, как exp07 0/57). ⚠ Но терсных-диалоговых чанков не поймалось (в .txt реплики склеены в абзацы , не строками) → precision гейта на ТЕРСНЫХ репликах этим срезом НЕ закрыт; нужен диалог-разбитый вход.
|
||||
- **A — r-коэффициенты:** DeepSeek V3.2 ~0.75 ток/CJK-симв, GPT-o200k ~0.90 — тот же порядок, что классик-калибровка exp01 → COGS exp08 индикативно держится (`token_calc_webnovel.json` — точный diff).
|
||||
- **en→ru проба Кристоффа (короткий отрывок, приватная калибровка — текст книги в проект НЕ сохранён):** deepseek fidelity **90**, grok **85**; оба `ok`, живой литературный русский. Судья поймал ровно то, что чинит банк памяти: **серийные термины** («coldblood» = обращение в мире серии, оба перевели как «хладнокровный») + имена (Dyvok/Lachie). ⇒ **банк памяти нужен и на en→ru**, не только zh/ja.
|
||||
|
||||
Пинги: **[БЭКЕНД] (1)** DeepSeek-эхо 25% на вебновелле при thinking-ON — эхо-мина живее, чем «13/24» на классике; downstream-детект эха обязателен. **(2)** реальные zh .txt часто **GB18030**, не UTF-8 — ingest должен детектить/конвертить кодировку. **[ОРКЕСТРАТОР]** en→ru тоже выигрывает от глоссария (серийные коины) — учесть в дизайне банка для en-книг.
|
||||
|
||||
### 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.86–0.93 ток. (in-family) против 0.65–0.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, 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](experiments/03-local-stand.md). По п.3 вводных: (а) 30b-a3b в WSL **влезает** (mmap, без OOM), но на ollama даёт лишь **10 tok/s** — «Расхождение» с research/06 (25–30 обещаны через 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 с несовместим с чанками (63–278 с) — нужен свой профиль + стриминг. План расширения пула: ваниль qwen3:8b (цена абляции) → Qwen3.5-9B → RuadaptQwen3 (докачиваются в фоне).
|
||||
- Бэклог принят: проверка проброса cache-hit агрегаторами (п.4, нужны ключи) — в шагах ниже. Задачи 4–5 не начаты (bge-m3 уже на стенде).
|
||||
|
||||
### 2026-07-04 — Сессия 2 полигона (после рестарта WSL с RAM 26GB)
|
||||
|
||||
- **llama.cpp `--n-cpu-moe` для 30b-a3b — перемерено, «Расхождение» с research/06 подтверждено**: потолок генерации на GTX 1070 **~13.5 tok/s** (не 25–30). Таблица конфигов в [03](experiments/03-local-stand.md): 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% ген., ×2–3 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/archive/prompts/MEMORY_RESEARCH_SESSION_PROMPT.md`; **оркестратору вычитать/финализировать**, затем владелец запускает. Замер эмбеддингов (bge-m3 vs Qwen3-Embedding vs LaBSE) — часть мандата той сессии.
|
||||
- [ ] Довалидация токен-калибровки на 3–5 главах реальных вебновелл (файлы владельца).
|
||||
- [~] Задача 4 (пилот выбора ядра, Фаза 2.5): протокол BWS + панель LLM-судей — **протокол готов** ([experiments/09](experiments/09-pilot-protocol.md)) + харнесс `eval/pilot/`; решающий прогон ждёт корпус владельца (см. Сессия 3).
|
||||
- [x] **Валидация precision coverage-гейта — гейтит боевой флип** (D12 Q4) → [experiments/07](experiments/07-coverage-precision.md): 0 FP/57, флип по precision безопасен, порог ≥2 флага/главу; вебновелл-срез ждёт корпус владельца (см. Сессия 3). Бэкенд-мини-набор (выпиленные предложения) проверяет 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/ja→ru, замерь долю ложных 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). Исполняемая спека механизма (не продукт): нормализация trad→simp/kana, точный матч ключей/алиасов с запретом одиночных (омографы 送灶/炎/修/气 НЕ инъектируются), спойлер-фильтр `since_ch/until_ch` (hard-reject), sticky для местоименных чанков, disposition confirmed/ambiguous/reject, post-check (ловит и утечку, и отравление). **Бэкенду:** порт в Go 1:1, тесты T1–T10 → 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` для якоря верности). Нарезать ~5–8 перекрывающихся чанков; собрать мини-глоссарий (5–10 записей: имена+реалии, с 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` + сводка сюда. Сильнее сигнал, если владелец подложит 1–2 главы реальной вебновеллы с повторяющимися именами — но PD-阿Q хватит для старта.
|
||||
|
||||
> **Задачи от оркестратора (04.07, из журнала решений [architecture/05-decisions-log.md](architecture/05-decisions-log.md)):**
|
||||
> 1. **Пересчитать ОБА cost-числа** (не только премиум) на реальном Фаза-1 стеке — расширено после D8–D11: дефолт-редактор теперь **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-05 — Сессия 3 полигона: coverage-precision (07), cost-model-v2 (08), пилот-подготовка (09)
|
||||
|
||||
Три ближние задачи закрыты; всё адверсариально верифицировано воркфлоу (5 линз, вердикт CONDITIONAL GO → все must-fix внесены). Артефакты — `eval/coverage_precision.py`, `eval/content_filter_probe.py`, `eval/cost_model_v2.py`, `eval/pilot/{declmetric,memory_eval}.py`, `docs/experiments/07–09`.
|
||||
|
||||
- **Задача 1 — precision coverage-гейта → флип МОЖНО (D12/Q4).** [experiments/07](experiments/07-coverage-precision.md). **0 ложных срабатываний на 57 хороших переводах** (LLM deepseek+grok × 2 + канон Рогова/Фельдмана), 0/26 нарратив, 0/31 «диалог» (маркер-прокси). Диалог: русский дробит CJK → `sent_cov ≥ 1` (не проседает); ближайший к полу 0.75 — 0.886 (ja-нарратив, запас 18%). Коридоры len_ratio НЕ узки (zh запас +20%, ja +14%). Go↔Python паритет-тест зелёный. **Оговорка широты (честно):** «диалог»-страт — классика Лу Синя с цитируемыми ТЕРМИНАМИ, НЕ вебновелл-диалог; §3.7 НЕ воспроизведён но и НЕ опровергнут; человеческий слой глава-гранулярен. **[→ бэкенду/владельцу]** флип `gates.coverage.enabled:true` по precision безопасен; порог главы **≥2 флага=fail, 1=attention**; коридоры не менять; **пере-снять на реальных вебновеллах владельца** до снятия 1-флаг-толерантности (просьба ниже).
|
||||
- **Побочно (D§85, → бэкенду):** `finish_reason=content_filter` **не эмитит ни один** из 5 ядровых провайдеров на SFW-violence (все `stop`/200/перевели) → ветка мертва, страховка = refusal-blacklist (подтверждает D2.4). Нюанс: **gemini-3.1-pro** (апекс) единожды дал `content_filter:PROHIBITED_CONTENT`, но не воспроизвёл на 4 контрольных → изредка срабатывает, не системно.
|
||||
- **Побочно (→ бэкенду):** **draft-эхо классической zh — системно:** deepseek-v4-flash эхнул **13/24** zh-чанков Лу Синя, grok-non-reason **10/24** (лёгкая правка исходника вместо перевода, не усечение) → ловит интринсик echo-гейт; single-hop эскалация черновика оправдана; вебновеллы вне претрейна — риск ниже.
|
||||
|
||||
- **Задача 2 — COGS v2 на grok-editor стеке → оба порога мертвы.** [experiments/08](experiments/08-cost-model-v2.md). Прайсы — офиц. доки, датированы 2026-07-05, кросс-верифицированы (воркфлоу). **Стандарт-микс (draft+editor):** ja→ru ранобэ **$0.69**, zh→ru вебновелла-500 **$10.94**, en→ru роман **$0.93** — **редактор ~88–90% стоимости** (grok-выход ×9 draft). **$0.6 мёртв.** **Премиум (Gemini apex):** ранобэ $5.0, вебновелла центр **~$82** (rf-условно $66–112; ниже якоря $100), роман $6.8 — **полный apex больших работ НЕ дефолт** (переполняет $30). Селективный apex (15%): вебновелла $24.6. **[→ бэкенду/оркестратору]** (1) **[ИСПРАВЛЕНО 05.07 — проба была багом]** editor slug остаётся **grok-4.3**; reasoning отключается ЯВНЫМ `reasoning_effort:none` (дефолт grok = low → без явного none думает), переснято (xAI docs + exp08:70-74). Прежнее «grok-4.3 форсирует / не отключается» — НЕВЕРНО; (2) `budget_usd` под селективный apex ($2 ранобэ/роман; вебновелла — потолок-на-главу/`apex_fraction`); (3) батч −50% только Gemini-судье; (4) **rf Gemini НЕ измерим через OpenAI-слой** (thoughts=0) — нужен нативный API перед привязкой премиум-бюджета.
|
||||
|
||||
- **Задача 3 — подготовка пилота Ф2.5.** [experiments/09](experiments/09-pilot-protocol.md) (протокол: ядро C0–C3 BWS, судья-панель+s\*, memory-eval WMT25-3-режим, think-ON/OFF, Annotator A/B, en-якорь для zh/ja верности) + харнесс `eval/pilot/`. **Decl-метрика** (`declmetric.py`, pymorphy3+stored-decl, mirror Go post-check) — склонённые формы (Вэйчжуане/Вана/Дэна) 0 ложных флагов. **memory_eval.py** — WMT25-3-режим, инъекция = **зеркало Go-контракта memory.go** (спойлер/disposition/sticky/containment/per-lang-minkey валидированы; `memory_hotpath.py` устарел до cc57c7b — не переиспользовал). **Индикатив (Ah-Q, N=5):** C0 консист. 0.58, **C1(банк) 1.0 = C2(длинный контекст) 1.0**, C3(неверный) 0.60 → банк ≈ длинный контекст по консистентности при меньшей инъекции; неверная инъекция не помогает. **[← владельцу нужно]** корпус 25–35 глав с приватными эталонами (рекуррентные имена, диалог/нарратив); человеческие BWS-аннотаторы; explicit-18+ фрагменты для канала B (gitignored).
|
||||
|
||||
**[ПРОСЬБА ВЛАДЕЛЬЦУ]** 3–5 глав реальной вебновеллы/ранобэ zh/ja с любым русским ориентиром → `eval/data/samples/<lang>/` — закрывает (а) диалог-плотный срез coverage-precision (эксп.07), (б) довалидацию токен-калибровки r (эксп.01/08), (в) старт memory-eval на большом глоссарии. Для zh — вне претрейна (обход эхо-мины).
|
||||
|
||||
|
||||
## Память
|
||||
|
||||
(секция сессии «Валидация банка памяти» — записи добавлять сюда)
|
||||
|
||||
### 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/ja→ru стеке **не проведено**, acceptance-критериев/baseline/cost-модели нет.
|
||||
|
||||
**Находки (1–2 строки):**
|
||||
- **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 молча теряет 17–36% терминов → **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/archive/prompts/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.5–3B; 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 — принята как инженерная гигиена, отклонена как путь к «обучающемуся модулю, бьющему базис».
|
||||
|
||||
> **[ОРКЕСТРАТОР → на РАСХОЖДЕНИЕ, 05.07]** Принято, расхождение закрыто. (1) Урок «проверяй пробой» — тот же, что сработал против находки exp08 про grok-reasoning (перепроверено 05.07 по xAI docs: reasoning ОТКЛЮЧАЕТСЯ через явный `reasoning_effort:none`); статус logprob-доступа занесён в provider-wiring-память. (2) Сильный сигнал soft-глоссаря на zh→ru (0.458→0.875) фолдится в in-house memory-eval пилота Ф2.5 как подтверждение направления (валидация банка его не мерила). (3) VRAM-гипотеза — согласен: инженерная гигиена (эмбеддер→CPU), не путь к обучающемуся модулю; M2 (детерминированный, 0 ML) — в банк v2.
|
||||
|
||||
> **[БЭКЕНДУ]** Из 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), не регэксп** — ПЕРВЫМ (наивный регэксп даёт **18–36% ЛОЖНЫХ флагов** на трудном чанке; 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 без разделяющего порога), не в костяке.
|
||||
|
||||
|
||||
## Голос и состояние
|
||||
|
||||
(секция ресёрч-сессии «Голос и состояние» — записи добавлять сюда)
|
||||
|
||||
### 2026-07-09 — Сессия «Голос и состояние» ЗАВЕРШЕНА → [research/15-voice-and-state.md](research/15-voice-and-state.md)
|
||||
|
||||
Метод: 12 направлений-сборщиков → адверсариальная верификация несущих клеймов refute-by-default (~60 верификаторов) → completeness-критик → 6 доборов (91 агент, ~3.2M ток., 0 отказов) + **живые пробы на SFW-чанках 蛊真人** ($0.04 — знаменатель $2.50 это жёсткий кап probe_runner.py, мандат ≤$3 на ec578ef / ≤$4 после 17ccea4; итог сессии с P4 — $0.28 (уточнено оркестратором); сырые артефакты в scratchpad сессии + дубль `/home/ubuntu/books/gu-zhenren/research15-probes/`; боевой драфт-промпт deepseek, редактор grok `reasoning_effort:none`, судьи кросс-семейно со свапом позиций). Зоны чужие не тронуты, ничего не закоммичено.
|
||||
|
||||
**Вердикт (кратко):**
|
||||
- **Клейм «voice exemplars > дескрипторов» — REFUTED в универсальной форме** (прямого сравнения не существует нигде; ChatHaruhi количественной абляции НЕ содержит), но количественное ядро есть: RoleLLM — формат демо важнее наличия (9.85→30.19→61.79% win-rate; arXiv-v1, в ACL-версии 9.3→29.8→63.3 — ревью); дистиллированный voice-sheet бьёт RAG-пример; насыщение ~5 реплик; **similarity-retrieval вредит** (69→36 AA) — удачно совпадает с детерминизмом банка. Строить **гибрид «1 строка регистра + 3–5 RU-реплик»**. Проба подтвердила направление: гибрид — ранг-1 у судей 5/5 (2 семейства); детерминированный маркер (奴婢-самоуничижение служанки): база 1/4, дескрипторы 3/4, **экземпляры/гибрид 4/4**; на «лёгкой» сцене (братья) инъекция нейтральна/шумит → **селективность по яркости голоса**.
|
||||
- **Голос выигрывается на ДРАФТЕ:** grok-редактор с узким мандатом вернул черновик **дословно** в 3/4 проб (сглаживание НЕ воспроизвелось; восстановление сплющенного голоса voice-блоком — тоже НЕ произошло). Редактору — констрейнты сохранения, переводчику — инъекция.
|
||||
- **Прайор-арт: клейм стратревью «аналогов нет» сузить, не снять.** Пер-персонажный голос в промышленном MT существует как продукт-клейм (NAVER «캐릭터 인식 번역», Mantra, XL8 — механизмы не раскрыты); детерминированный no-LLM словарный слой и селективная инъекция по матчу — массовая практика фан-стека (GalTransl/LunaTranslator/SakuraLLM — «учебник» найден). **Уникальными остаются:** спойлер-окна since/until (нигде, вкл. патентные индексы), scene-state и voice-exemplars в MT, формула «disposition+окна+бюджет+детерминизм».
|
||||
- **Scene-state: полная схема — ниша пуста; единственный доказанный срез — направленный регистр пары** (ты/вы = 67% деиксис-ошибок En→Ru; тег-контроль 73–92% acc) → **реестр обращений пар** (speaker→addressee, ты/вы, since/until; индустриальный прототип — Netflix Treatments list / 呼称表) — самый дешёвый новый тип записи. DelTA после сверки первоисточника: чистый вклад памяти = +3.95 пп LTCR при −0.02 COMET (консистентность и качество **развязаны** — выигрыш виден только специализированной осью).
|
||||
- **Эпистемика читателя: spoiler-aware MT — 0 работ (ниша пуста);** механика у нас есть — reveal-окна = расширение спойлер-окон (`reveal_ch` + pre/post-reveal алиасы); механический спойлер-канал zh→ru — **род прошедшего времени** (конкретизация C3). Имплицитному трекингу «кто что знает» доверять нельзя (FANToM 26.6% vs человек 87.5%). Dramatic irony registry в Ф1–Ф2 не строить.
|
||||
- **Промптинг/параметры:** «двухпроходность в одном вызове» (V1.13) — арм НЕ ставить (план не работает, работает refinement = наш draft→editor); NO_CHANGE давать, но доля — опция-артефакт (плацебо-эффект −15.75 пп); формат инъекции — модель-специфичный гиперпараметр пилота (JSON худший по замеру OpenAI); менять draft 0.3/editor 0.4 оснований нет, НО **thinking DeepSeek молча игнорирует temperature → temp драфта, вероятно, no-op** (wire-аудит — пре-шаг любого свипа).
|
||||
- **Живые грабли проб (все с сырыми артефактами):** deepseek-эхо воспроизведено на приёмочной книге (2/3 сэмплов одной конфигурации, стохастично); **gemini-2.5-flash — интермиттентный 404 «no longer available» при наличии в /models** (⚠ это судья fidelity-оси `memory_eval`!); **gemini-3.5-flash эмитит `finish_reason=content_filter: PROHIBITED_CONTENT`** на сцене насилия → вывод exp07 «ветка content_filter мертва» НЕ переносится на Gemini 3.5; gemini-3.1-flash-lite работает; CJK-утечка «每人» в ru-выход (cjk-гейт нужен, класс живой).
|
||||
|
||||
> **[ОРКЕСТРАТОРУ — что ратифицировать]** (1) **Voice-профиль** (схема research/15 §1.5: register/self_ref/lexicon_markers/ng_lexicon/exemplars 3–5 RU-реплик/brightness/окна) и **реестр обращений пар** (§2.1) — как механизмы Ф2 в план/реестр; сид обоих для приёмочной книги дёшев и делается вручную. (2) **Reveal-окна** (`reveal_ch`+pre/post-reveal алиасы) — расширение спойлер-окон, Ф2. (3) **Новые армы пилота:** voice-A/B/C/D (скаффолд готов — проба), формат инъекции (plain vs markdown vs XML, отдельно deepseek/grok), «сэндвич» (повтор констрейнтов после чанка), minimal-diff редактор (search/replace + гибкий апплай — режет output-токены 90%-статьи COGS); **армы НЕ ставить:** двухпроходность-в-одном-вызове, min_p. (4) **Скоуп Annotator Ф2** (§2.3): ядро = speaker+addressee с disposition (детерминированный пре-гейт 说/道-кии + LLM на implicit; CONFIRMED-only в инъекцию); отношения курировать как глоссарий (zero-shot F1 0.26–0.52 — непригоден); мусор не аннотировать (пространство/эмоции/эпистемика вне reveal). (5) Поправка постановки: SAMAS (2602.19840) — style-fidelity мультиагентник, НЕ speaker-aware. (6) Сузить формулировку «аналогов не найдено» в доках по таблице research/15 §5.
|
||||
> **[ПОЛИГОНУ — готовые ТЗ]** (1) ⚠ **СРОЧНО: судья `memory_eval` gemini-2.5-flash интермиттентно 404** («model no longer available», при этом модель ЕСТЬ в /models — «есть в /models ≠ работает»); мигрировать судью (gemini-3.1-flash-lite проверен пробой — работает; 3.5-flash — 503 + content_filter) и **перепроверить refusal-таксономию exp02/07 на Gemini 3.x** — content_filter-ветка ожила (`PROHIBITED_CONTENT` на сцене пощёчин!). (2) **Параметр-свип** (ТЗ — research/15 §4): пре-шаг wire-аудита (пишутся ли sampling-параметры в thinking-канале DeepSeek; V4-маппинг temp; grok `effort:none`+penalties) → потом temp-армы с ДВУМЯ осями (fidelity + натуральность). (3) **Анти-эхо матрица** (ТЗ — §3-bis): {DeepSeek beta prefix русским × совместимость с thinking; дубль инструкции после чанка; 2 микропримера zh→ru в кэш-префиксе} на плотных CJK-чанках 蛊真人; метрика echo-rate уже в харнессе. (4) **Voice-A/B на трудном материале**: скаффолд пробы переиспользуй (scratchpad сессии `/tmp/claude-1000/-home-ubuntu-projects-textmachine/6960d2e3-8669-4b06-a5ed-12d603f53907/scratchpad/probes/` — `probe_voice.py`+`analyze_voice.py`+сырые выходы; /tmp волатилен — забрать до ребута; книжные производные в git не класть); мерить на вебновелл-срезе вне претрейна и на ТРУДНЫХ ты/вы-парах (равный статус, смена отношений — наши пары оказались «лёгкими», лифт реестра не измерен). (5) Эвал-база ru-voice-детектора: IWSLT22 formality EN→RU (600 золотых пар) + ru-срез mSynthSTEL + пертурбации 蛊真人.
|
||||
> **[БЭКЕНДУ — требования к схеме на будущую веху, НЕ код сейчас]** (1) Банк v2 — заложить МЕСТО (не реализацию) под два новых типа записей: `voice_profile` (расширение `speech`: register/self_ref/lexicon_markers/ng_lexicon/exemplars[]/brightness + окна) и `address_pair` (направленная пара speaker→addressee, register ты/вы, since/until — активация по ДВУМ именам тем же AC); оба ездят существующим Select/disposition/бюджетом. (2) Reveal-окна: полю сущности — `reveal_ch` + pre/post-reveal алиасы (механика since/until уже есть). (3) Инъекция голоса — в ДРАФТ-слот (проба P3: редактор не восстанавливает); редактору — только констрейнт сохранения. (4) Wire-probe в бэклог: пишется ли temperature в thinking-канале DeepSeek (наш temp 0.3, вероятно, no-op — молчаливый вендор-факт); grok-4.3: вендорская дока на слаг исчезла (доки описывают 4.5) — квирки держатся на наших фактчеках. (5) Формат инъекции не менять до пилота (модель-специфично); в system-префиксе явно объявить формат блока (дешёвый буст робастности).
|
||||
|
||||
### 2026-07-09 (дополнение, поздний вечер) — проба 3-bis выполнена (амендмент мандата 17ccea4 увиден постфактум)
|
||||
|
||||
Коммиты 17ccea4 (эхо-под-мандат 3-bis + бюджет ≤$4), 3d183bc (пакет-2 полигона) и 3011b88 (D19) залетели ПОСЛЕ старта сессии — промт читался на ec578ef. Сверка постфактум: веб-часть 3-bis (а)–(б) оказалась закрыта completeness-критиком ещё до прочтения амендмента (copy-collapse наука + инвентарь prefill-каналов — research/15 §3-bis); мандатная проба (в) выполнена дополнением, exp10/D19 увязаны в док. Итого потрачено **$0.28 из $4**; сырые артефакты — scratchpad `probes/raw/echo-*.json`; конфиги — точная реплика exp10 (сопоставимость с полигонским 40%-замером); корпус — их же `refusal_corpus_gu` (уровень-2, скрин уровня-3 чист их аудитом) + мой SFW-кейс.
|
||||
|
||||
**Результаты P4 (эхо-митигции; метрика cjk_share>0.15; КАЧЕСТВО переводов не судилось):** grok-4.3 `reasoning:none`, 10 фрагментов: **база 3/10 эха** (реплика полигонских 4/10; эхо-фрагменты пересекаются лишь частично → эхо стохастично per-fragment) → **инструкция ПОСЛЕ текста 0/10 · микро-few-shot (2 пары zh→ru в system) 0/10 · комбо 0/10 · ⚠ языковой констрейнт («весь вывод — на русском, кириллицей») — ИНВЕРСИЯ: 9/10 эха** (verbatim-китайский без единого русского слова; diff с базой — одна строка system). DeepSeek (gu-008, база 2/3; T1+реестр, база 2/3): инструкция-после **0/6**, **микро-few-shot 0/3 (gu-008)**, **префилл «Перевод:\n» (beta prefix-completion) 0/6**. **Wire-аудит пост-верификацией по сохранённым usage (`completion_tokens_details.reasoning_tokens`): все v1-базы шли с thinking-ON per-call (111–3204 > 0 — дефолт конфига providers.json подтверждён проводом, не докой), и все три deepseek-эха P4 случились ПРИ thinking-ON (базовые gu-008: rt 111/182; L-арм T1: rt 149 — испр. оркестратором по пересчёту) — thinking снижает, но не исключает эхо (сходится с exp10-контролем 1/10 и «25% на вебновелле»); префилл же отключает thinking — reasoning_tokens=0 во всех 6/6** (вопрос «beta prefix × thinking» закрыт wire-фактом; вендор-док о взаимодействии молчит — при смене API перепроверить; цена по качеству реалий не мерена — thinking их чинит, exp03).
|
||||
|
||||
> **[ОРКЕСТРАТОРУ — к D19.2]** (1) **Рекомендую в боевые промпты канала A/B**: микро-few-shot в кэшируемый префикс (≈$0) + дубль инструкции после чанка (~10 ток. хвоста) — суммарно **0/29 эха против базовых 30–67% по армам (пул ~44%)** на обоих провайдерах (счёт испр. оркестратором); понижает частоту эскалаций (COGS); echo-гейт не трогаем (рамка D19.2 соблюдена). (2) **Анти-находка для ратификации: явный языковой констрейнт в system на grok-none ИНВЕРТИРУЕТ эхо 3/10→9/10** — запретить «пиши по-русски»-строки в промптах reasoning-off путей без per-model замера; предостережение к любым будущим анти-эхо правкам. (3) Префилл DeepSeek — кандидат для драфт-канала только после fidelity-проверки (обходит thinking → возможен налог на реалии); каналу B нерелевантен (Mistral чист, grok-эскалация reasoning-ON — D19.1).
|
||||
> **[ПОЛИГОНУ]** (1) В обобщающую строку quirks (поручение D19.2) добавить инверсию: «языковой констрейнт в system у reasoning-off моделей может УСИЛИВАТЬ эхо (grok-none 3/10→9/10, P4 research/15; проверена одна формулировка — чувствительность неизвестна)». (2) Fidelity-хвост P4: отсудить митигированные переводы против базы (35 пар, копейки) — если fidelity не падает, митигции готовы к wiring через оркестратора. (3) Эхо стохастично per-fragment (gu-009 эхнул у нас, не у вас; gu-001/006 — наоборот) → echo-rate мерить с повторами, не одним прогоном.
|
||||
> **[БЭКЕНДУ]** НЕ вносить языковые констрейнты в промпты reasoning-off путей (P4-инверсия). Микро-few-shot пары zh→ru — кандидат в стабильный префикс шаблонов draft/канала B (кэшируется; 0/26 эха) — только через оркестратора при следующей правке промптов (prompt_version-бамп, снапшот-дисциплина).
|
||||
|
||||
|
||||
## Ридер-IDE
|
||||
|
||||
(секция ресёрч-сессии «Ридер-IDE: выравнивание, статусы, HITL-редактура» — записи добавлять сюда)
|
||||
|
||||
### 2026-07-11 — Сессия «Ридер-IDE» ЗАВЕРШЕНА → [research/16-reader-ide-alignment.md](research/16-reader-ide-alignment.md)
|
||||
|
||||
Метод (research/13–15): мультиагентный веб-ресёрч (13 сборщиков по 5 кластерам) → адверсариальная верификация refute-by-default (13 верификаторов; вендор-клейм ≠ замер; доки/скриншоты CAT — источник поведения) → 26 агентов, 0 ошибок, ~1.23M ток., 652 веб-обращения; вердикты CONFIRMED/PLAUSIBLE/REFUTED. **+ $0-проба парности абзацев** на боевом прогоне этапа A (read-only `acceptance/guzhenren-25ch-parallel.txt` + `guzhenren-acc-a.db`). Живых LLM-вызовов: **$0**. Зоны чужие не тронуты, ничего не закоммичено.
|
||||
|
||||
**Вердикт (кратко):**
|
||||
- **$0-проба парности абзацев (этап A, deepseek→glm-5, 25 гл):** src↔финал **58% точно / 72% в ±1**, агрегат абзацев 0.987; **расхождение рождается на ДРАФТЕ (редактор сохранил число абзацев в 93% чанков), и это ЛЕГИТИМНОЕ слияние/дробление, не тихое вырезание** (границы двух худших чанков целы, объём нормален); объём ru/zh ≈3.0× (в символах; «1.9×» промта — токены). Внешне валидировано: CJK-литература 60.2% 1:1 на предложениях (Bertalign/MAC), структурный текст 85% абзацев (JRC) — наши 58% = норма жанра.
|
||||
- **Гипотеза оркестратора «страница=артефакт, якорить узлы» — CONFIRMED** (все инструменты якорят узел/сегмент, никогда страницу; атом = «бед» Gale-Church = наш чанк). Но расщепляется: потребительские ридеры парят 1:1 по узлу; N:M split-diff + «флаг не-1:1 первыми» — из выравнивателей/InterText. **Синк — КО-ЛОКАЦИЕЙ спаренных якорей (интерлив/общий грид), НЕ свободным скролл-синком двух панелей** (дрейфует на N:M).
|
||||
- **Самое консеквентное — калибровка YELLOW, не якорь.** QE4PE (TACL 2025, 42 профредактора): подсветка ошибок НЕ ускоряет PE и мешает при неточности; **точность флага важнее покрытия.** Google Tricorder (<10% ложных/чекер), alert-fatigue (49–96% игнора) → преимущественно-жёлтая полоса бросается целиком. Замер precision каждого флага — ГЕЙТ перед показом цветов.
|
||||
- **Контракт под фронт целиком выводится из read-model** (`status.go`): цвета = проекция disposition/passport/retrieval_state ($0). Net-new: `annotations.json`-схема, политика красных (editor-facing плейсхолдер / reader-facing fail-closed — D25.1), **human_override** (в D15.2 НЕ спроектирован; аналог CAT lock + PerfectMatch/X-Translate content-keyed carry-over), chat-edit фрагмента.
|
||||
- **Форсировать структуру промптом — НЕТ** (инструкция ненадёжна: gpt-4o-mini сливает вопреки «do not merge»; жёсткость деградирует качество — Karpinska); индустрия конвергировала на **detect-and-recover ФЛАГГЕР** (GalTransl 8 категорий + retranslKey redrive ≈ наш per-flag redrive). Bertalign (MAC F1 0.909, $0 на GTX 1070) — для GOLD-пар канона в eval, НЕ в прод.
|
||||
|
||||
> **[ОРКЕСТРАТОРУ — что ратифицировать]** (1) **Иерархия якорей** глава→чанк(нативный,точный)→абзац(best-effort ~58%)→предложение; **чанк = несущий якорь** (src_range↔dst_range), абзац — мягкий оверлей; синк ко-локацией, не скролл-синком. (2) **Контракт `annotations.json`** (§4.1: per-chunk state/color/reasons/src_range/dst_range/paragraph_anchors + version-хеши snapshot/chunker/source) как экспорт-артефакт пакета №4. (3) **Политика красных:** editor-facing — помеченный плейсхолдер (текущее, честно); **reader-facing fail-closed на красных = якорь release-state D25.1** (structurally_complete требует 0 красных) — ратифицировать при постройке reader-экспорта. (4) **human_override — скоуп в контракт (не полный дизайн):** 2 слоя — provenance LOCK safe-by-default (иммутабелен на redrive/resume) + content/context-keyed carry-over через --resnapshot с ТРЕТЬИМ состоянием «override needs re-review» (YELLOW-конфликт при смене src/контекста, никогда тихо-хранить/тихо-клоббить); НЕ авто-кормить override в TM; полный дизайн — с реализацией D15.2 v3.1 (wire/verdict-split = та же машинерия — синергия D26.4). (5) **Конвенция цвета:** добавить GREY=pending (CAT-конвенция: непереведённое=серое, красное=жёсткий провал); passport-rollup расширить до 3-тир (done+escalated/glossary_miss/style → YELLOW; сегодня «attention» триггерит только на RED). (6) Reader-embedded книго-полоса из детерминированных вердиктов + ru + серия — при скрининге аналогов не найдено (новый синтез; сузить как в research/15, не «аналогов нет»).
|
||||
|
||||
> **[БЭКЕНДУ — требования к экспорту, НЕ код сейчас]** (1) Экспорт `annotations.json` — проекция `chunk_status`+`retrieval_state`+`request_log` ($0, как `status --json`; `tmctl` сегодня не имеет export-команды — параллельный экспорт этапа A был ad-hoc). Поля §4.1; `src_range/dst_range` в нормализованный источник/собранный перевод — чанкер lossless даёт точно. (2) **Цвет-мап детерминирован из УЖЕ существующих полей** (§3.1): RED=flagged-без-dst; YELLOW=done+escalated ∨ glossary_miss ∨ postcheck_misses>0 ∨ style_flags>0; GREEN=чисто; GREY=pending. `flagReasonSeverity()` уже даёт приоритет. (3) **Диалог-аварный флаггер парности абзацев** — класс style-флага (наблюдаемость/YELLOW, НЕ hard-fail: 1:N на диалоге — норма Розенталь §52; описательное слияние — слабее вес); пере-инжектить правки через span-map, не LLM-apply. (4) **passport несёт arity-распределение абзацев** (1:1/1:N/N:1 vs полоса ~60% CJK…85% структурный) — чтобы 58% читалось как норма. (5) **human_override — provenance-слой вне RequestHash** (как post-check: live-recomputed, verdict-нейтрален), ключ по content_hash чанка; проектировать вместе с D15.2 v3.1. Реализация — не сейчас; армит фронт Ф3.
|
||||
|
||||
> **[ПОЛИГОНУ — ТЗ]** (1) **Диалог-аварная пере-нарезка $0-пробы парности** (фальсифицируемо, §5-🧪): классифицировать 53 чанка этапа A на диалог/описание, проверить — концентрируется ли расхождение в (i) легитимно-развернувшихся диалогах и (ii) слияниях; если равномерно — норма-гипотеза неверна. Скрипт-затравка: `scratchpad/parity_probe.py` (переиспользуем; /tmp волатилен — забрать). (2) **Замер precision флаггеров** для калибровки YELLOW (гейт §3.2): per-flag-reason точность против blind-чтения владельца/редактора на срезе; демоут флага <10% истинных в «слабые сигналы». Совместить с exp12 (диагностика уже читает те же главы). (3) **Bertalign zh→ru spot-check** до доверия (нет измеренных zh→ru; всё внешнее — zh→en): ручная сверка на held-out срезе перед использованием для GOLD-пар пилота. Свежие прогоны НЕ требуются — проба сделана на сохранённых выходах этапа A.
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
Один и тот же чанк проходит 4 конфигурации ядра, все на ратифицированном стеке (draft=DeepSeek-v4-flash, editor=grok-non-reason):
|
||||
|
||||
- **C0 baseline** — один проход переводчика (+ детерминированный глоссарий = уровень VseGPT; baseline метрики, PROGRESS §синтез).
|
||||
- **C0 baseline** — один проход переводчика (+ детерминированный глоссарий = уровень VseGPT; baseline метрики, §синтез дня-0 — ныне `../archive/PROGRESS-2026-07-04-10.md`).
|
||||
- **C1 draft→editor** — черновик → моноязычный редактор (D1). Дефолт Ф1.
|
||||
- **C2 generate-then-select** — N черновиков → судья-селектор выбирает лучший (arXiv:2603.20324). Висит на калибровке s\* и валидности судьи (§5). **D13.2: кандидаты ГЕТЕРОГЕННЫ** — draft'ы от РАЗНЫХ моделей (deepseek/glm/kimi/mistral), НЕ N сэмплов одной. Основание: на гомогенных селекция ≈ монета (2603.20324 WR 0.512; LitMT 2606.05924 best-of-8+судья — последнее место). На гомогенных C2 предрешён и жжёт бюджет впустую.
|
||||
- **C3 select-then-refine** — селект + точечный re-ask/refine на выбранном (verifier-gated, research/14 M2; рычаг L3 эксп.adaptive_reask).
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue