textmachine/docs/BACKEND_PLAN11_SESSION_PROMPT.md

218 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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

> **⚠ АКТУАЛИЗИРОВАН ПОД R1-ПРОДОЛЖЕНИЕ (19.07, пост-D39.14; предыдущие версии — в git-истории).** Сессия №1
> сдала Block A (`85f5b9e`, D39.13); сессия №2 сдала R2R5 + R1-аддитив (D39.14). **Осталось: R1 драйвер-свитч +
> 3-пунктовый фикс-лист рубежа-2 (ниже).** Дизайны — `docs/archive/reports/PACK11_CONT_REPORT_2026-07-19.md §R1` + `docs/archive/reports/PACK11_REPORT_2026-07-19.md §Резидуал`
> (авторитет наравне с планом). Сданное — под тестами, НЕ пере-строить.
>
> **ФИКС-ЛИСТ рубежа-2 (FL-1/2/3) — УЖЕ ЗАЛЕНДЕНЫ (D39.14/D39.16), здесь как КОНТЕКСТ; НЕ переделывать, если
> тронешь смежное — не регрессировать:** FL-1 `bankMaxLines`/`bankTokenBudget` свёрнут в `banknoteSnap` · FL-2
> `resumeFromChunkStatus` репопулирует `BankFlags` (банкнота-телеметрия не обнуляется на резюме) · FL-3
> `emitRankCap=200` перед emission-фильтрами (`miner_emit.go`, зеркало `a3[:200]`).
>
> **Ш-1/Ш-2 (D39.16-записка, ратифицированы → ДЕЛАТЬ В ЭТОМ R1-заходе, снапшот-двигающие):**
> - **Ш-2 (несущее):** вплести `unicode.Version` в `memoryNormVersion` (`memnorm.go:56`) + classifier/style-версии —
> сейчас NFKC/`unicode.Han/Cyrillic` привязаны к Unicode-версии тулчейна, но не фолдятся → бамп go1.27 сменил бы
> их ТИХО. **Фолдить в ТОТ ЖЕ единый resnapshot, что `pack.Version()`** (один заход). **ТРИПВАЕР: обязательно
> до любого go1.27-бампа** (мы на 1.26.4 — не горит, но не бампать тулчейн, пока Ш-2 не в снапшоте).
> - **Ш-1 (низкая срочность):** хелпер masked-diff при golden re-capture (`TM_UPDATE_GOLDEN=1` → маскировать
> хеш/версия-поля + печатать «N вердикт-изменений / M version-only» ДО записи). Делает re-capture безопасным
> по построению; можно в этом заходе или отдельной гигиеной.
# Промт: сессия БЭКЕНД — единый пак по плану 11 (волновой раннер · чанкер/единицы · банк W1.5 · банкнота · чекеры · армы), 2026-07-19
> **Место в очереди (пост-D39.12):** исследовательская программа арх-ресета (D39D39.10) и дизайн-синтез
> (D39.11) ЗАВЕРШЕНЫ. План **`docs/architecture/11-implementation-plan.md` РАТИФИЦИРОВАН (D39.12)** после трёх
> рубежей верификации ($0-симуляции с числами — исполнены и воспроизводимы). Эта сессия — СТРОЙКА строго по
> нему. **Решение владельца: весь объём — ОДНОЙ сессией**, четырьмя блоками с чекпойнт-ревью между.
## Кто ты и что сдаёшь
Бэкенд-сессия TextMachine. **Зона записи: `backend/`** (вкл. `configs/`, `prompts/`); всё остальное читать
можно, править нельзя (расхождения — пингом через отчёт/владельца). **НЕ коммитить** — лендит оркестратор
после приёмки (git-гардрейл CLAUDE.md: никаких reset --hard/rebase/checkout поверх грязного дерева). Сдаёшь:
1. Код резидуала R1 + Ш-1/Ш-2 + тесты из (д)-секций плана (пины/golden/race/kill-9).
2. **Отчёт — в финальном сообщении сессии** (per-буллет чек-лист ✓/девиация+причина, тест-логи, golden-диффы,
«багфиксы вне плана», residual). **НЕ заводить `backend/*_REPORT.md`** (процесс-правка владельца 19.07:
код-зона чистая; постоянный record = D-блоки+PROGRESS; если оркестратору нужен детальный артефакт — пиши
в `docs/archive/reports/<имя>_<дата>.md`, НЕ в `backend/`).
Онбординг-добавка: приёмочные детали прошлых заходов (Block A / continuation / арх-проход) — в
`docs/archive/reports/` + D-блоки D39.13/14/16; §Резидуал R1 — там же в отчётах и в плане §1.
## Онбординг (порядок чтения, ~45 мин)
1. `CLAUDE.md` (гардрейлы: `.env` НЕ читать · 18+ уровень 3 · PUML не рендерить · книга и производные ВНЕ git)
`backend/README.md` (**инварианты 18 — ломать нельзя, каждый закреплён тестами**) →
`docs/architecture/03-implementation-notes.md`.
2. **`docs/architecture/11-implementation-plan.md` ЦЕЛИКОМ — это твоя спека.** Структура: WS1WS6, каждый
(а) что менять / (б) алгоритм / (в) конфиг+снапшот / (г) исполненная $0-верификация с числами /
(д) тест-спека ПОСЛЕ стройки / (е) открытое; §7 порядок · §8 манифест resnapshot · §9 диспозиции ·
§10 развилки владельца · §11 гейтнутые армы. План верифицирован трижды — **не пере-решай его решения**;
несогласие или найденная дыра = эскалация запиской, не тихая девиация.
3. `docs/architecture/05-decisions-log.md`: карта актуальности в шапке + D39D39.12 подробно;
`09-target-architecture.md` §0.1 (**инвариант общности — НЕСУЩИЙ:** никакой захардкоженной структуры
книги/пары; пара = ось данных).
4. **`docs/experiments/00-provider-quirks.md`** — ПЕРЕД любым кодом около адаптеров/конфигов моделей
(вкл. свежую запись «mistral rate-limiter» в §Транспорт).
5. Референсы по мере работы: `eval/exp16/*.py` (**frozen miner-v1 — эталон порта WS3**, SHA в exp16 §1.10),
`eval/design11/` (симуляции/фикстуры плана — твои golden-входы; python — `eval/.venv`), `research/20` §B3
(банкнота), `research/19` §B (контекст чанкера). Авто-память сессий — point-in-time, верь коду/докам.
## Порядок работы (по §7 плана; единый пак, 4 блока, гейты между)
- **R1 = волновой ИСПОЛНИТЕЛЬ** (отчёт §R1, 7 шагов): `snapshotIDForWave` (W1 = draft-стадии +
`BaseVersion()`, W2 = edit + `Version()` — механика версий уже сдана), партиция стадий по роли, W0
sticky-precompute (golden: инъекц-байты ≡ последовательному раннеру), W1/W2-dispatch (W2: `prev` =
конкатенация draft-чекпоинтов единицы по `final_hash`, СВЕЖИЙ `Select` по тексту единицы над
enriched-банком; **W2 НИКОГДА не пере-рендерит draft** — несущий инвариант), W1.5-стоп + mined-write-путь
(пустая дельта → авто-продолжение), kill-9 с N живыми резервами, **golden-рерайт под волновую модель +
обновление ~10 последовательно-модельных тестов** (список — отчёт §0).
- **R2 = WS3 Go-майнер** (отчёт §R2: порт по frozen exp16, дефолт-лемматизатор B с пере-пином 古月→22,
инвариантные фикстуры EXACT, mined-write, `tmctl seed-lint`).
- **R3 = WS4 12 интеграционных точек** (отчёт §R3: срез ДО classify, derived-checkpoint с NULL-байтами,
re-point ПОСЛЕ резолва эскалации, `banknoteSnap`, инструкция в файл промпта, телеметрия).
- **R4 = WS5** чекеры + omission-бэкстоп + данные пакета zh-ru + `tmctl export --pairs` (отчёт §R4).
- **R5 = WS6** арм-пайплайн-конфиги + `echo_mine_test` под варианты + атрибуция арма (отчёт §R5).
После R1, после R2+R3 и после R4 — чекпойнт-ревью (см. §Верификация). Единый `--resnapshot` по §8 в сессии
**НЕ исполнять** (плановое событие после приёмки, одна переоплата); но **golden re-capture** под
ратифицированную смену поведения — исполнять по мере: маскированный структурный дифф обязан быть объясним
(только хеши/версии/новые поля) и прикладывается в отчёт каждый раз.
## Чек-лист исполнения (буллеты; ТОЧНАЯ спека — план + отчёт §Резидуал; при расхождении побеждает ПЛАН)
> **Статус после Block A (D39.13):** WS2 — ✅ сдан целиком (кроме «инъекция W2-единицы» — часть исполнителя
> R1); WS1 — ✅ сданы WS1a/b/c-инфра (eager-clients, rate-guard, base/enriched split), остался волновой
> ИСПОЛНИТЕЛЬ (R1); WS4 — ✅ сдано ядро `banknote.go`, остались 12 точек (R3); WS6 — ✅ rate_limit-конфиг,
> остались арм-конфиги (R5); WS3/WS5 — резидуал целиком (R2/R4). Сданные буллеты ниже читай как КОНТЕКСТ
> и контракт (не пере-строить — под тестами); строишь только резидуальные.
**WS1 (план §1):**
- Eager-build ВСЕХ клиентов в W0 (`Stages[].Model EscalateTo`); `client()` в волнах read-only + громкий
отказ на miss (закрывает гонку `runner.go:171-181`; трипваер на будущую 3-ю модель-ось).
- W0-precompute sticky-цепочки (`Select` — чистая src-производная функция). Golden: инъекц-байты precompute ≡
байтам последовательного раннера над НОВЫМ чанк-сетом WS2, fresh↔resume.
- **Пер-волновой снапшот:** `snapshot_W1` (draft-стадии + base-bank = хеш approved `Source∈{seed,ruby}`),
`snapshot_W2` (edit-стадии + enriched-bank = все approved вкл. mined). Механика для ОБОИХ состояний
`PostcheckGate` — по §1(в).
- **Инвариант секвенирования (НЕСУЩИЙ):** W2 НИКОГДА не пере-рендерит/пере-хеширует draft-стадию — редактор
читает черновик по `final_hash`-чекпоинту. Пин: draft `request_hash` байт-стабилен под обогащённым банком.
- W1.5-стоп-механика: стоп после W1 → карта подписи → подпись владельца → **персист дельты ОТДЕЛЬНЫМ
mined-write-путём (штамп `Source:mined`; НЕ через `loadGlossarySeed` — тот хардкодит `Source:seed`,
`memseed.go:131`)** → resume в W2. Подпись mid-run трогает ТОЛЬКО mined-строки; правка seed/ruby-строки
после W1 = громкий resnapshot-стоп, не тихий re-bill (пин-тест).
- Деньги под ∥: Reserve/settle из N горутин через single-writer; kill-9-тест с N живыми резервами
(`committed==SUM`, каждый потерянный вызов пере-оплачен один раз); overshoot-тест `cost>estimate`.
- Scheduler-aware ценовые окна (конфиг провайдера, не хардкод; DeepSeek ×2 = риск-пин до ре-чека 24.07) +
**пер-модельный rate-guard**: семафор конкуренции `models.yaml max_concurrency` (+опц. пейсинг);
транспорт-ось, НЕ снапшот. `waves.workers` конфиг (НЕ `Fanout` — тот занят C2).
- Grep legacy DeepSeek-слагов в `backend/configs/` (прод не задет по плану — подтверди; eval-долг только
отметь в отчёте, eval/ не правь — чужая зона).
**WS2 (план §2):**
- Бюджет draft-чанков в ВЫХОДНЫХ токенах: `est_out = 1.1978·cjk + 0.3852·other` (конфиг per-pair,
снапшот-folded `segmentationSnap`); классы символов — РЕАЛЬНЫЕ `unicode.RangeTable` из `EstimateTokens`
(НЕ ord-диапазоны скрипта — общность §0.1). Пин: `target_out=1797`**56 чанков** на 25 главах.
- Edit-единица = глава; **`EditCeilingOut=3200` (ратифицированный дефолт)**; глава >3200 → абзацный сплит
(never-split-paragraph, lossless tiling). Пин: 25 глав → **37 единиц** (фикстура `ws2_chunk_sim.py`).
8000-арм НЕ открывать (гейтнут Q2a).
- `Chunk` аддитивно: `EstOut`, `OversizedSentence` (мега-предложение = passthrough + флаг, БЕЗ клауза-сплита),
`EditUnitID`. Контракт Chapter/ChunkIdx/Text цел.
- Снос мёртвых `STMDepth`/`OverlapTokens` (`config/pipeline.go:47-48`) — carryover не строим.
- **src→dst-формат** `renderEditorConstraintBlock` (CONFIRMED-only дисциплина ЦЕЛА) + выделенный
**`render-format-version`** снапшот-компонент (НЕ `memoryMatchVersion`).
- Сайзинг max_tokens редактора: существующий механизм от `prev`-черновика (`stagerun.go:87-90`) — НОВОЙ
формулы НЕ вводить (пост-верифай F8); проверить достаточность под единицу-главу тестом.
- **Инъекция W2-единицы = СВЕЖИЙ `Select` по тексту ВСЕЙ единицы над enriched-банком** (sticky на уровне
глав вырожден); НЕ реюзить per-чанк memSel из W0 (тот над base-банком). Глоссарий-бюджет Select для
главы-единицы — открытый пункт §2(е): реши инженерно, при сомнении эскалируй.
**WS3 (план §3):**
- `miner*.go`: порт V-A→V-C **строго по frozen exp16 `arms.py`** (точные пороги §3(б); детерминизм-контракт:
сорт-ключи, целые, версии, tie-break). **Лемматизатор: дефолт B** — Палладий-подканал в Go-дефолте
дропается, зависимые фикстуры пере-пинятся (古月 21→22); **Палладий-ИНВАРИАНТНЫЕ гарантии — EXACT:
13618-кандидат-СЕТ (членство), recall 0.9649/0.9318, катастроф-скрин 方源/蛊/蛊师 ранги 0/1/2 ∈top-50.**
- Алиас-ярус-1 (R4-блоки ПЕРВЫМИ; юнит-фикстуры: 族长≠四代族长, компози-гард 古月+族长, кап-лемма-гейт
«найти»), консолидация §C2 (канон по ВСЕМ вхождениям; **майнер по построению НЕ пишет approved**), эмиссия
сид-дельты (схема `seedTerm` БЕЗ новых полей; эмиттер реюзит subsumption+fragment-фильтры, не сырой дамп).
- `Source:"mined"` (аддитивная миграция store) + mined-write-путь + `tmctl seed-lint` (сухой прогон
фейл-лаудов реального `loadGlossarySeed` по дельте).
- Паритет Go↔Python: **Python = референс**; при расхождении чинить Go; доказанный баг референса → эскалация.
**WS4 (план §4):**
- Все 12 интеграционных точек с пин-тестами (список §4(д)). Несущие: срез `⟦TM-BANK-v1⟧` ДО `classifyOutput`;
derived-checkpoint ТОЧНАЯ формула с NULL-байтами (`"tm-banknote-v1\x00"+reqHash+"\x00"+stripped`);
**re-point `final_hash` OK-пути draft на derived — ПОСЛЕ резолва эскалации** (`stagerun.go:163`, потреблять
`last.stripped` — эскалированный черновик тоже очищен); `banknoteSnap{enabled, parser_version}` в
`snapshotID()`; инструкция сноски — В ФАЙЛ промпта переводчика (PromptSHA256 двигается); генерации
**finish=stop-only**; телеметрия `n_banknote_lines`/`banknote_parse_fail`/`banknote_truncated` лауд.
- Пин: пере-парс 95 строк exp16 = 0 fail (фикстура `ws4_banknote_verify.py`); толерантный обрез — синтетика.
**WS5 (план §5):**
- Чекеры DC1 (时辰/единицы) / DC2 (масштабы чисел) / DC6 (регистр-негатив-лист) / DC7 (editor-инверсии
grade/role) — cheapgates-класс, target-gated, **наблюдаемость НЕ гейт** (landing гейтнут FP-замером §5(д)
на свежем прогоне).
- **DC3: инъекция пола — ВСЕ ТРИ состояния, вкл. hidden-мандат** (безродовые конструкции / surface-«он» до
`until_ch` — фикс класса Бай Нинбин D19.3); детерм. чекер — ТОЛЬКО male/female, паратекст-чанки исключены;
hidden-чекер НЕ строить (Ф2-кореференция).
- DC5-детекцию НЕ строить (74%/42% FP) — пак-локусы (данные) + слот сноски; рендер-политика за владельцем.
- Omission-бэкстоп: substring-матч `{dst, decl.forms, aliases}` + лёгкий детерминированный ru-стеммер
(Go-либа; БЕЗ pymorphy3); verdict-каскад и `inflection_gap`-флаг по плану.
- Данные пакета пары zh-ru (таблицы единиц, негатив-лист, verse-локусы) — версионируемый снапшот-folded пакет.
- `tmctl export --pairs` (source-join в Export уже есть) — пред-условие FP-замера DC1/DC2.
**WS6 (план §6):**
- Армы редактора = КОНФИГ (yaml/models: glm-5 / mistral-large-latest / deepseek-v4-pro), снапшот per-арм,
атрибуция арма в export/report; `echo_mine_test` обновить под варианты; editor pinned (эскалации нет — D12).
- mistral-арм разблокируется rate-guard'ом из WS1 — проверь связку тестом (семафор реально ограничивает).
## Свободы и рамки (решения владельца, 19.07)
- **Рефакторинг/перенос кода по папкам — РАЗРЕШЁН и приветствуется:** архитектурная чистота важнее
минимальности диффа. Границы: инварианты 18, контракты плана и поведение вне скоупа не менять молча;
крупные структурные переносы — отдельным разделом отчёта (ревью-абельность лендинга).
- **Без велосипедов:** реюз stdlib и существующих механизмов репо (эталоны: `coverageSnap`-фолд,
derived-checkpoint, role-registry, `baseRequestLog`, `config→stage-list`). Новая внешняя зависимость —
только с обоснованием в отчёте (канон Go: минимум зависимостей).
- **Временные тесты/харнесы** — можно и нужно: `_test.go` рядом с кодом; одноразовые скрипты — в scratchpad,
НЕ в репо; временное помечай.
- **Баги по пути** — чинить разрешено, каждый в раздел «багфиксы вне плана» (лендинг скоуп-раздельный).
- **Не костылить:** честная реализация (б)-алгоритмов; хак «чтобы тест прошёл» запрещён; недоделка =
явная строка residual, не тихий пропуск.
- **Go-каноны:** `gofmt`/`go vet`/`-race` чисто; идиоматика (обёртка ошибок `%w`, контексты, без глобального
мутабельного стейта, table-driven тесты); комментарии — в стиле окружающего кода (констрейнты, не пересказ).
- **Неконсистентность** (план↔код↔доки↔вендор): НЕ гадать — даблчек всеми тулзами (grep по репо, git log,
доки, официальная вендор-дока/вебсёрч — правило двух направлений CLAUDE.md); реальное расхождение → СТОП
по этому куску + эскалация. Провайдер-аномалия → сначала вендор-дока, интерпретацию без сверки не вшивать.
- **$0 к провайдерам:** LLM-вызовы НЕ делать (ни облако, ни локаль) — вся верификация build/test/golden/
фикстуры. Wire-корректность доказывается голденом и байт-диффами, не живыми вызовами.
## Верификация (мандат самопроверки владельца 12.07 — ОБЯЗАТЕЛЕН; + чекпойнт-ревью)
1. **Ревью исполнением непрерывно:** `go build ./... && go vet ./... && go test -race ./...` после каждого
куска; «зелёное» подтверждай ЛОГОМ, не словом (урок D37: «0 ошибок» ≠ 0 ошибок).
2. **Фикстуры плана — прогонять:** sticky-байты ≡ sequential · 56 чанков @1797 · 37 единиц @3200 ·
miner-паритет (инвариантные EXACT; зависимые — пере-пин B) · банкнота 95/0 · kill-9 с N резервами ·
seed-lint 0 фейл-лаудов · draft request_hash стабилен под обогащённым банком.
3. **Чекпойнт-ревью после блоков A/B/C** (адверсариальный воркфлоу, author≠reviewer, refute-by-default), три
линзы: (i) **алгоритм-vs-план** — реализация против (б)-секций построчно, детерминизм (сорты/целые/версии);
(ii) **сеньорское код-ревью** — Go-идиоматика, конкуренция, границы ошибок, чистота сеамов;
(iii) **функциональное** — деньги/resume/снапшот/гейты end-to-end на фикстурах. Находки чинить ДО
следующего блока; сводку каждого чекпойнта — в отчёт.
4. **Финал:** полный многоосевой адверсариал по паку (деньги/resume · снапшот/волны · детерминизм ·
банк/банкнота · чекеры · экспорт · код-качество) + отчёт в финальном сообщении (НЕ `backend/*_REPORT.md`).
5. Golden re-capture — только под ратифицированную смену поведения; маскированный дифф прикладывать всегда.
## Что НЕ строить (гейтнуто/анти-скоуп — план §0/§11; в код не тащить)
Крупно-главный арм >3200 out (Q2a-гейт; потолок остаётся конфигом) · наполнение `logical`-стратегии чанкера
(сеам без контента) · carryover/lookahead · diff-редактор · reflow-отдельным-пассом · W2.5-швейный пасс ·
LLM-сегментация/ML-сцены/эмбеддинг-границы/RAG-оверлап · DC5-детерм-гейт · DC3-hidden-чекер · локальный
9B-споттер · жанр-паки · платные вызовы. Единый resnapshot — НЕ в этой сессии.
## Эскалации и отчёт
Настоящие развилки (конфликт плана с кодом, нереализуемость (б)-алгоритма, скоуп/деньги, дыры плана) —
эскалируй БЫСТРО короткой запиской через владельца (развилка + варианты + твоя рекомендация); это норма и
поощряется (образцы эры №6 — в D-логе), тихие девиации запрещены. Приёмка оркестратора после сдачи:
верификация исполнением (build/race/пины/golden-репликация) + адверсариальный рубеж-2 по сырью → лендинг →
единый resnapshot → пере-прогон 310 глав → чтение владельца (планка 2 претензии).