textmachine/docs/BACKEND_WIREBATCH_SESSION_PROMPT.md

256 lines
25 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.

# Промт сессии: БЭКЕНД — вайр-батч «род, экран цели, заголовки инъекций»
> **Роль:** бэкенд. **Зона записи:** `backend/` и своя секция «Бэкенд» в `docs/PROGRESS.md` — это
> единственное разрешённое каноном исключение из «`docs/` — зона оркестратора». Чужие зоны
> (`platform/`, `frontend/`, `eval/`) читаешь, не правишь. **Не коммитишь** и не трогаешь индекс и
> историю — полный список запретов и причина: `CLAUDE.md`, «Git-координация мультисессий».
> Норматив стиля — `docs/architecture/12-go-style-notes.md`.
## Какая проблема и что изменит твой результат
Движок обещает род персонажей на проводе — директива ратифицирована `D39.21`, механизм доставки
построен и работает. **Данных ему не даёт никто:** промпт терминолога возвращает ровно три поля
(термин · перевод · уверенность), поля рода в ответе нет, а майнер берёт `gender` только из ручного
сида. Значит на любой книге, которую никто не сидировал руками, ось рода мертва **по построению**, и
«плывущий род» в тексте — не дефект рендера, а отсутствие входа. Рядом лежат ещё три правки того же
провода, каждая ратифицирована и ни одна не построена.
После пака: род производится авто-путём · полный связный перевод на чужой язык перестаёт проходить
как здоровый · редактор получает единый закон-блок вместо двухсекционки · банковый контур включён в
боевой конфиг · жанр ушёл из промптов. И всё это одним пере-захватом голдена, а не пятью.
## Карта чтения — пять позиций, дальше только по их ссылкам
1. `backend/README.md` — устройство движка · `docs/architecture/12-go-style-notes.md` — норматив.
2. `docs/PROGRESS.md`: CURRENT-STATE и строки бэклога **210 · 46 · 113 · 134 · 140 · 184 · 197 · 198 · 204**
(греп по номеру в таблице).
3. **Состав и его доводы — здесь, в этом файле.** Разбор «почему пункты собраны вместе и что
намеренно НЕ берётся» лежит в отработавшем плане `docs/archive/reports/NEXT_PACKS_PLAN_2026-09-03.md`
§1 — ⚠ это АРХИВ: читать как ДОВОД, инструкции оттуда не исполняются, приказ несёт этот промт.
Ратифицированные решения по очереди — нота **D39.190** (грепом по номеру).
4. Журнал решений, номера грепом (`grep -n '^## D39.NNN'`): **D39.21** (род должен доезжать) ·
**D39.93** (форма экрана цели) · **D39.104** (банк на проводе — закон) · **D39.105/D39.108**
(доктрина заголовков и павший гейт) · **D39.147** п.2в (140 — стройка, не развилка) ·
**D39.138** п.2в (жанр выкидываем) · **D39.64** П0 (безусловный фолд `EmbeddedVersion`).
5. `docs/architecture/15-money-path.md` — денежный путь; читать §2 про суб-бюджеты банк-ролей.
⚠ Ратифицированное вложено в тело этого промта; **код-факты добываешь САМ** — указатели ниже
отправные точки, код первичен. Числа даны с командой получения: пере-ранишь — сойдётся; не сошлось —
это находка, неси пингом, а не подгоняй работу под текст.
## Состав — шесть пунктов, в этом порядке
### 1. Строка 210 — РОД НЕ ПРОИЗВОДИТСЯ ВОВСЕ (цель №1 бэклога)
Механизм доставки построен: `backend/internal/membank/memory.go` (греп `genderConstraintNote`) кладёт
род в черновую инъекцию. Входа нет:
```
grep -n -i gender backend/prompts/zh-ru/terminologist.md # ноль полей рода
grep -n 'meta.gender' backend/internal/miner/miner_emit.go # род только из сида
```
**Делай РОВНО так:** род начинает производиться авто-путём, и это доказывается СКВОЗНЫМ прогоном
«терминолог произвёл → отрендерилось в инъекции», а не юнит-тестом на конструкцию.
**Решаешь сам и аргументируешь — развилка НЕ выбрана за тебя:** поле рода в ответе терминолога ·
отдельный проход · признать сид-только и закрыть строку отказом. Выбор объявляешь с ценой (байты
батча терминолога двигают его `RequestHash`).
**ВТОРОЙ ЗАМОК, без которого первый пункт не даёт НИЧЕГО.** Род рендерится только у строк со
статусом `Confirmed`, а произведённое терминологом приезжает auto-строкой. Снятие замка следует из
доктрины `D39.104` (банк на проводе — закон для всех строк независимо от статуса), **но оно обязано
быть СКАЗАНО и вынесено пингом на ратификацию оркестратору, а не выведено тобой молча.** Пока замок
не снят, поле у терминолога ничего не меняет на проводе — так и напиши в отчёте, если решишь не
снимать.
Вес: следующий платный замер полигона (15 глав с характер-листами) без этого пункта
**ложно-отрицателен по построению** — «полей пола в банке нет вовсе».
### 2. Строка 113 → потом 46 — экран целевого языка. ПОРЯДОК ОБЯЗАТЕЛЕН
**Сначала 113, и это не формальность.** Числа, на которых стоит вся строка 46 («18 из 20 · 0 ложных
на 1055 · запас 13×»), получены ВРЕМЕННЫМ тестом, который сессия удалила; воспроизвести их сегодня
нечем. **Делай РОВНО так:** корпус-фикстура в репо (~20 off-target + ~40 здоровых, с движковой
предобработкой) плюс регресс-тест на реальный запас.
**СТОП и пинг**, если фикстура не воспроизводит 18/20 при нуле ложных или запас меньше 3×: тогда
предпосылка строки 46 пала, и стройка по ней — трата.
Затем сам экран. Дизайн ЗАМОРОЖЕН и ратифицирован: closed-set причин (`D39.92` п.1) и изолированный
модуль с именованными причинами (`D39.93`).
**Три вещи, которых нет в спеке, и они меняют работу:**
- `EFFORT_HANDLE §5.4` шаг 6 велит переиспользовать `FlagCJKArtifact`**это СНЯТО `D39.93` п.2**
(именованный флаг + явный вход в `escalatable()`). Нота бьёт спеку.
- Вторая половина дыры — `detectLatinInsertion` без `TargetScriptNonLatin()`
(`backend/internal/checks/sanitizer.go`); реестр §Б-46 велит «чинить тем же диффом».
- Новый именованный флаг — **16-я причина**, а карта платформы рукописная на 15
(`grep -c '":' platform/internal/ingest/notes.go` → 15) ⇒ платформа отдаст `unspecified` с ERROR.
Носитель — строка **204** / ряд `PD-246`. **Пинг платформе обязателен** (в отчёт, чужую зону не правишь).
**Решаешь сам и аргументируешь:** состав и форма корпус-фикстуры 113 · имя и текст новой причины
флага · где именно стоит вход в `escalatable()`.
### 3. Строка 134 — инжект-заголовки под доктрину D39.105
Гейт ПАЛ (`D39.108`): текст = отправленная строка пробы 18 **БЕЗ** оговорки области (оговорка
опровергнута §A.4 — НЕ вносить).
**Делай РОВНО так — ТЕКСТ заголовка не меняется вовсе.** Меняется рендер: секция
`editor_unverified_header` не рендерится (двухсекционка → один блок) · маркер ⟨проверить⟩ не
рендерится · то же у заголовка транслятора. Статусы строк и подписная таблица **не трогаются**
(`D39.104` п.1).
**МИНА, и выбор твой, но объявленный.** Правка `backend/internal/lang/data/injection.txt` двигает
`EmbeddedVersion` БЕЗУСЛОВНЫМ фолдом (`D39.64` П0) и `cutTag` манифеста ⇒ пере-чеканку ВСЕХ `unit.id`
⇒ платформа при смене `manifest_key` СНОСИТ `unit_resolutions` книги
(`platform/internal/pgstore/readmodel.go`, греп `recut :=` и `delete from unit_resolutions`) — это
строка **198**, и её гейт «до первого реального пользователя». Рычаг у тебя есть: **снять рендер в
Go, данные не трогать** — тогда двигается только `RequestHash`, мёртвые строки данных допустимы до
следующего касания. **Решаешь сам и аргументируешь, но выбор ОБЪЯВЛЯЕШЬ явно** и, если тронул
данные, пишешь об этом первой строкой отчёта.
### 4. Строка 140 — банковый контур в shipping-c1: СТРОЙКА, не развилка
⚠ Текст строки называет это «СТОП-решением» — он СТАРШЕ ратификации. `D39.147` п.2(в) уточнением
владельца 17.08: внесение «ратифицированно живёт в wire-батче 182 — одним касанием перед первым
платным прогоном; **отдельной развилки нет**». Журнал бьёт бэклог.
```
grep -n 'terminology\|banknote\|classify' backend/configs/pipeline-c1.yaml # 0 — не построено
```
**Делай РОВНО так:** банковый контур (банкнота + терминолог + классификатор) включается в c1.
**Суб-бюджеты банк-ролей калибровать ×4.47**`15-money-path.md` §2 прямо говорит, что сегодня они
«режут ОПЛАЧЕННУЮ работу по протухшей калибровке»: на холодном прогоне `classify_budget_usd` 0.02
оборвал классификатор дважды. **Решаешь сам:** конкретные числа после умножения и надо ли поднимать
их сверх множителя.
**Цена НАЗЫВАЕТСЯ в отчёте** (двигает промпт черновика ⇒ `RequestHash` книг на c1), но не спрашивается.
### 5. Строка 184(а) — снять `{{genre}}` из промптов пары
Слово владельца 16.08, `D39.138` п.2в дословно: «Просто выкидываем». Состав числом не держим:
```
grep -rln '{{genre}}' backend/prompts/ # сегодня шесть файлов
```
**Делай РОВНО так:** снять из промптов И поле из канона брифа (двигает `BriefHash`, то есть КАЖДЫЙ
`RequestHash` — потому и внесено в это окно, а не потом). Влияние жанра на качество не измерено и уже
не будет.
**Свободы здесь нет намеренно:** пункт предписан целиком, решать в нём нечего. Упрёшься во что-то,
чего промт не предусмотрел, — пинг, а не своё усмотрение.
### 6. ДОФИКС чужого пака + ФЧ-7 — одним пунктом
**Почему это здесь.** По канону дофикс адресуется той же сессии, что делала пак. Её больше нет
(проверено `ListAgents` 04.09), поэтому остаток едет сюда. **Это чужая недоделка, а не новый заказ**
и в отчёте её надо называть отдельно от своей работы.
Остаток приёмки (`D39.187` п.4):
- **Развилка операторской строки прибита с ОДНОЙ стороны.** `VolumeStop.String()` развёл предложение
на «книга кончилась» и «грант придержал», но две посадки в новый код переживают весь пакет: под ними
в смешанном состоянии (`Carried=3, Left()=1`) печатается «reached the END of the book … Still in the
book: 1 unit(s) NEVER delivered» — то же самопротиворечие в зеркальной форме. Лог-развилка при этом
прибита с обеих сторон, то есть образец рядом.
- **Граница `bound()` не прибита:** `Carried > 0``Carried > 1` переживает пакет, и прогон с ОДНИМ
перенесённым юнитом на конце книги не отдаёт отчёт вовсе — тихий лимит, анти-паттерн `D39.165` §1б.
- **Три числа отчёта протухли снова** — сняты до последней правки каталога.
**Делай РОВНО так:** каждая из двух посадок получает тест, который от неё краснеет, И запись в
`backend/cmd/tmmutate/mutations.json`.
**ФЧ-7 фикс-листа (строка 197) — паника поверх ПОЙМАННОГО потолка.** Денежный шов, не проверялся
никем. **Форма — проверка ИСПОЛНЕНИЕМ, а не стройка: воспроизвести, и чинить ТОЛЬКО если
воспроизводится.** Тем же касанием пере-скоупить строку 197: ФЧ-1/4/5 закрыты, ФЧ-6 по коду выглядит
закрытым, **ФЧ-2/3/8 остаются НЕ ПРОВЕРЕННЫМИ и обязаны быть названы непроверенными**, а не тихо
опущены.
## Границы — что НЕ делать
-**Не двигать:** схему хранилища движка · `manifestVersion` · `StreamVersion` · версию контракта.
Понадобилось — **стоп и пинг**, не «сделаю аккуратно».
-**Не заводить новый embed-файл** (реестр §Б-46: это перекупка всех пар).
-**Не переиспользовать `FlagCJKArtifact`** (снято `D39.93` п.2).
-**Не менять семантику переноса слота** — владелец 03.09 отложил её словом «подумаем».
-**Не брать строки 131 · 105(а) · 14 · 119 · 124 · 115 · 160 · 161 · 142** — они жильцы того же
окна или отдельных паков, и их очередь решает оркестратор, не ты.
-Не трогать чужие зоны, `.env`, соседний worktree `/home/ubuntu/projects/textmachine`.
-**Общность движка:** Go-логика не ветвится по паре и книге. Ревью-вопрос по умолчанию —
«заработает ли пара, которой в репо ещё НЕТ, без правки Go?». Пара-данные — `internal/lang` и
`configs/langpacks/`, книго-каноны — сид и бриф.
## Свобода и её разметка
**«Делай РОВНО так» (отступление = пинг):** порядок 113 → 46 · СТОП по фикстуре, если запас < 3× ·
текст заголовка не меняется · статусы и подписная таблица не трогаются · нота бьёт спеку у
`FlagCJKArtifact` · суб-бюджеты ×4.47 · жанр снимается и из промптов, и из канона брифа · обе посадки
дофикса краснеют · ФЧ-7 проверка, а не стройка · все запреты раздела «Границы».
**«Решаешь сам и аргументируешь» и только это:** развилка производства рода · снимать ли второй
замок (со СКАЗАННЫМ пингом) · трогать ли данные в 134 (с объявлением) · конкретные числа суб-бюджетов ·
форма фикстуры 113 · форма тестов и записей каталога · порядок работ внутри пака.
Катч-олла «всё остальное сам» нет: чего нет ни в одном списке это пинг, а не твоё усмотрение.
## Мандат самопроверки — исполнением, не перечитыванием
`make battery` **предусловие, а не отчёт.** Обязательны все четыре, каждое с ПРЕДЪЯВЛЯЕМЫМ артефактом:
1. **Дифф `^func Test` исполнением, а не памятью:** `grep -rn '^func Test' backend --include=*_test.go | wc -l`
до и после, плюс пофамильный дифф. **Удалённых имён должно быть 0**; не 0 назвать каждое.
2. **Голден пере-захватывается с МАСКИРОВАННЫМ диффом:** в нём меняются только названные версионные
оси и **ровно две строки диспозиций**. Изменилась хоть одна здоровая строка **СТОП и
эскалация**, а не пере-захват.
3. **Собственные адверсариальные посадки ВНЕ шести пунктов** механизм `cmd/tmmutate` на копии дерева
(`cp -a backend /tmp/<имя>/backend`). Артефакт: красный вывод на каждую посадку и **отдельный список
тех, что батарея ПЕРЕЖИЛА** это и есть находки.
4. **Отдельный проход по СВОЕЙ ГОТОВОЙ работе свежим контекстом.** Субагенты разрешены явно; модель
задавай ИМЕНЕМ и знай, сколько их у тебя работает.
**«Прошёл, находок нет» отчётом НЕ является:** ноль обосновывается тем, ЧТО искалось и какими
командами.
**Отчёт о движении провода обязателен:** двинулся ли `cutTag` предъяви `tmctl manifest` до и после
на стендовой книге и дифф `unit.id`.
### Предметные оси ревью — уязвимы ИМЕННО в этом паке
1. **Ложные срабатывания экрана цели на ЗДОРОВОМ русском с латинскими термами.** Положительный
контроль фикстура 113: 18/20 при нуле ложных и запас 3×. Без него экран не сдан.
2. **Род: все существующие тесты конструируют его руками.** Нужен сквозной контроль «терминолог
произвёл отрендерилось» И отрицательный «сид побеждает произведённое».
3. **134: маркер снят, а пост-чек жив.** Проверь, что снятие маркера не сломало обработку `Ambiguous`.
4. **140: бюджеты режут оплаченную работу.** После ×4.47 предъяви, что классификатор на стендовой
книге не обрывается.
Запрет подгонки тестов и гейтов `CLAUDE.md` (`D39.183`). Край, который тебе понадобится: **этот
промт ЗАКАЗЫВАЕТ смену поведения в пунктах 15**, и протухший под неё тест правится как обслуживание
но правка ОБЪЯВЛЯЕТСЯ: что изменилось, какой тест это описывал, куда уехала гарантия.
## Отчёт
**Записка-план ДО работы** эхо-протокол старта, 10 строк «скоуп · инварианты · что НЕ делаю», в
секцию «Бэкенд» `docs/PROGRESS.md`. Первым действием, до кода.
**Комплектность против заказа — механически:** пройди по шести пунктам состава и по таблице разметки и
отчитайся **ПО КАЖДОМУ**. Эта тема проваливалась несколько раз на том, что исполнялся первый пункт, а
нумерованный остаток бросался.
**«Заявление = команда»:** каждое число и каждая категорика с командой получения, которая это число
реально печатает. Приёмка пере-ранит твои команды; команда, печатающая «ok» вместо числа, считается
отсутствующей. Гейты и счёты гнать **ПОСЛЕДНИМ действием**, после того как текст дописан.
**Обязательная секция «Что НЕ удалось и что НЕ проверено».** Исходов ТРИ, и «не проверено»
«опровергнуто» «сделано»; третий законен и ожидаем. Сюда обязательно попадают ФЧ-2/3/8 и решение по
второму замку рода, если ты его не снял.
**Конфликт промта с кодом или доками — ПИНГ через владельца, не интерпретация.** И у тебя есть **право
сказать «этого делать не надо»** с аргументом, включая пункты состава и границы: сессия, приносящая
развилку вместо тихой девиации, делает правильно. Промт писан по коду на HEAD своей смены; код
первичен, и если ты видишь другое это находка, а не твоя ошибка.
## Прямой канал
Механизм целиком `CLAUDE.md`, «Связь между сессиями»: свой блок в `/tmp/textmachine-channel`, сверка
с `ListAgents` перед отправкой, канала нет нормальный случай, сессии подряд не опрашивать. Что
добавляет этот пак: **эхо-записку отправь ПЕРВЫМ действием по адресу оркестратора** это и есть
проверка канала.