textmachine/docs/BACKEND_SEAM_FIX3_SESSION_PROMPT.md

221 lines
21 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.

# Промт: БЭКЕНД ФИКС-ЛИСТ ПРИЁМКИ дофикса-2 — четыре пина, один снос, ноль новых механизмов
> Выдан оркестратором №19, 27.08.2026. Активный промт зоны бэкенда — один; этот заменяет
> `BACKEND_SEAM_FIX2_SESSION_PROMPT.md` (отработан, **пак ПРИНЯТ**, уезжает в архив при лендинге).
> Параллельно законен только `platform/docs/archive/PLATFORM_P8_REVIEW_SESSION_PROMPT_2026-08-22.md (ОТРАБОТАН 27.08)`.
## 1. Какая проблема и что решит твой результат
Дофикс-2 **ПРИНЯТ**: флажок стал флажком в самом движке, точка фиксации отчёта закрыта, живых дефектов
приёмка не нашла ни одного. Проверено её исполнением: батарея зелёная, стенд красен ровно на парити,
каталог мутаций 58 — ноль неожиданных, модель владельца работает (флаг поднят → стоп → возобновление
с поднятым флагом и НУЛЁМ решений → редакторская волна).
Осталось шесть предметов, и **ни один из них не механизм**. Четыре — там, где инвариант объявлен
комментарием и не держится ничем; один — артефакт отменённой модели, переживший свип; один — текст,
который учит читателя движка неверной модели.
**Твой результат: у каждого несущего инварианта этого пака есть пин, а в дереве не остаётся двух
контрактов об одном.** Кода почти нет — есть тесты и удаление.
**Дерево трёх предыдущих паков НЕ закоммичено и лежит в рабочем каталоге.** Ты продолжаешь его.
## 2. Зона записи и git
Пишешь ТОЛЬКО в `backend/`. `platform/`, `frontend/`, `eval/`, `docs/` — чужие зоны, правки запрещены.
**Единственное исключение:** пинги и итог — в `docs/PROGRESS.md`, секция «Бэкенд». **Ты не коммитишь.**
`git add -A`, `git add .`, `git commit -a` запрещены. В дереве живёт незакоммиченная работа
параллельных сессий — не трогай её и не «прибирай».
## 3. Карта чтения (три позиции, больше не нужно)
1. **`backend/docs/SEAM_PACK_FINDINGS.md`, §36§45** — доказательная база принятого пака. Вход — §43.
2. **`docs/architecture/05-decisions-log.md`, нота D39.144** — ратифицированная модель флажка. Нужна
для §4.4: ты будешь править тексты, которые ей противоречат.
3. **`docs/architecture/17-seam-inbound-law.md`** — закон входной двери.
**Код первичен.** Все места ниже названы приёмкой с воспроизведением; открывай и проверяй сам.
## 4. Состав
Шесть пунктов. Комплектность — `grep -cE '^### 4\.'` обязан дать **6**.
### 4.1 ⛔ ГЛАВНОЕ: пин на порядок «карта → память» — ДЕЛАЙ РОВНО ТАК
`internal/pipeline/mining.go` объявляет асимметрию несущей, дословно: «*the memory write depends on
the map being on disk first (never the reverse: a remembered surface whose map was never written is a
silent loss)*». **Её не держит ни один тест.**
**Воспроизведено приёмкой:** понизив отказ записи карты до предупреждения (`return false, fmt.Errorf(...)`
`Log.WarnContext`), получаем зелёную батарею. Мутация проверена в ТРЁХ кандидатных пакетах пина —
`./internal/pipeline/`, `./cmd/tmctl/`, `./internal/store/`**выжила во всех трёх**, то есть это не
ложное «мутация выжила».
**Цена, если инвариант сломают:** прогон встаёт на стопе, указывая владельцу на файл, которого нет,
помечает кластеры предъявленными — и следующий подъём флажка на них **не встанет уже никогда**. Ровно
та молчаливая потеря, против которой комментарий и написан.
**Заказ:** пин, краснеющий на этой мутации. Форму выбираешь ты; рабочий приём приёмки — сделать
переименование карты невозможным (например, занять её путь непустым каталогом) и проверить, что
`StopPresentedSurfaces` книги остался ПУСТ, а прогон вернул ошибку. Каталог мутаций получает запись.
### 4.2 Отчёт класса 15 мерит подпись по НАМЕРЕНИЮ — ДЕЛАЙ РОВНО ТАК
`internal/pipeline/bankdecisions.go` объявляет: «*The POST-state, re-read from disk: for an outcome
that touched the world the report describes the files as they now are, never the bytes the call
intended*». Для исхода «прервано» это закрыто пином; для **`write_incomplete`** — нет.
**Утверждение панели приёмки, оркестратором НЕ пере-проверено исполнением:** подменив источник
пост-состояния на результат вызова, отчёт класса 15, у которого ничего не долетело, печатает
`signature.undecided: 0` — success-shaped блок ровно на том исходе, ради честности которого пак и
делался. **Воспроизведи сам прежде, чем чинить.** Названная панелью причина слепоты: существующий
пин зовёт конструктор с ПУСТЫМИ состояниями, где оба источника неразличимы.
**Заказ:** пин, различающий диск и намерение на исходе `write_incomplete`, — как у его брата.
### 4.3 Старый пол полосы выжил в двух носителях — ДЕЛАЙ РОВНО ТАК
Дофикс-2 переформулировал пол полосы в «нет работы, которую надо откатывать; повтор безопасен» и
завёл класс 15, про который сам пишет, что это **единственный класс, который не может обещать
«ничего не произошло»**. Старая формулировка выжила (проверено оркестратором грепом):
- `internal/pipeline/runner.go:206` — «*nothing reached a provider, nothing was spent, nothing was written*»;
- `cmd/tmctl/panic_exit_test.go:78` — та же фраза, и здесь она заявлена как обещание **ВСЕЙ полосы**,
которое класс 15 опровергает.
⚠ Второе хуже первого: это не описание одной ветки, а контракт полосы в тесте.
**Заказ:** обе привести к двухъярусной формулировке — пол полосы плюс клауза класса. Файлы пак не
трогал, поэтому это правка, а не дочистка своего диффа.
### 4.4 Отменённая формула выжила в четырёх файлах — ДЕЛАЙ РОВНО ТАК, ГРЕПОМ, А НЕ СПИСКОМ
Дерево несёт **два контракта об одном**. `internal/pipeline/mining.go:94-97` (этот пак) пишет:
«*whether the run stops is the presented memory's question alone (D39.144 — deciding terms is a right,
not what the stop waits for)*». А рядом живёт отменённая причинность (проверено оркестратором грепом):
| носитель | что говорит |
|---|---|
| `internal/miner/miner_test.go:306-307` | «*The stop clears only once every proposal is promoted or rejected*» — **сама отменённая формула, дословно** |
| `internal/miner/miner_emit.go:61` | «*dropped from the delta so a declined term never re-fires the stop*» |
| `internal/miner/miner_emit.go:175` | «*dropped WITH its whole cluster, so it never re-fires the stop*» |
| `internal/seed/decode.go:26` | «*which the bank-mining emission drops so a declined term never re-fires the stop*» |
| `internal/seed/decode_test.go:33` | «*every declined term re-fires the stop, forever*» |
⚠ Два из этих файлов — **новые, написанные этими же сессиями**. То есть свип §4.12 прошлого промта шёл
по списку, а не грепом, и наследие пережило его в файлах самого пака.
**Заказ:** зачистка **грепом** (`re-fire the stop`, `re-fires the stop`, `stop clears only`, и подумай,
какие ещё формы искать), а не по этому списку — он получен тем же способом, который уже один раз
оказался неполон. Отказ по-прежнему исключает терм из ЭМИССИИ — это верно и остаётся; неверна
причинность «чтобы не пере-фаерил стоп».
### 4.5 Снести мёртвый артефакт отменённой модели — ДЕЛАЙ РОВНО ТАК
`.bank-stop.json` — машинная таблица стопа. Её собственный комментарий называет читателя: «*this one
is what a signing screen is built from*» — то есть **пер-термный экран подписи, упразднённый D39.144**.
Проверено оркестратором: читателя нет **ни в одной зоне** — греп по `platform/`, `frontend/`, `eval/`
даёт только тесты про снятие стопа, к таблице отношения не имеющие.
**Заказ:** снести — вместе с писателем, дисциплиной отказа и упоминаниями. ⚠ **Человеческую таблицу
`.bank-stop.txt` НЕ трогать** — у неё читатель есть, это оператор.
⚠ Если увидишь основание оставить (например, читателя, которого приёмка не нашла) — **скажи пингом,
а не оставляй молча**: снос мёртвой публикации и сохранение живой — разные решения, и второе требует
имени читателя.
### 4.6 Якорь свежести у читаемого банка — РЕШИ САМ форму
**Утверждение консилиума, оркестратором НЕ пере-проверено:** дисциплина отказа записи банк-экспорта
— «громко, но не фатально» (верно: деньги дороже проекции), но «может быть устаревшим» живёт **только
в логе**; в самом документе нет поля, по которому потребитель отличит проекцию этой границы прогона от
прошлой. Конверт документа уже версионирован, поэтому добавление аддитивно и дёшево.
**Заказ:** проверь утверждение; если верно — заведи внутрикадровый признак свежести. Форма твоя.
Если считаешь, что признак не нужен (например, потребитель и так знает границу) — **отклони с
аргументом**, это законный ответ.
## 5. Мандат самопроверки ИСПОЛНЕНИЕМ
- **Батарея целиком, ИЗ КАТАЛОГА `backend/`**: `go build ./...`, `go vet ./...`, `go test ./... -count=1`,
`make lint`. ⚠ `go.mod` в корне репозитория НЕТ. **И `make battery-stand` один раз в конце**
ожидаемая картина: всё зелено, кроме парити на отсутствующем jieba-контрасте (вне git по построению).
Красный тест не «подгоняется»: править или удалять тест ради зелени — **НЕДОПУСТИМО**.
- **Каталог мутаций расширяется:** каждый пин §4.1§4.2 получает запись в `cmd/tmmutate/mutations.json`,
и `go run ./cmd/tmmutate -root <копия>` обязан дать ноль неожиданных исходов на итоговом дереве.
⚠ Посадка называет ПАКЕТ, в котором ищется пин, — не тот, где лежит правка. ⚠ Если мутация «выжила» —
пере-проверь во ВСЕХ кандидатных пакетах прежде, чем звать это находкой.
- **Субагенты разрешены явно** — на ревью своего кода и на опровержение своих выводов. ⚠ Соразмеряй
параллельность с ресурсами.
- **Артефакт-находки:** дописывай `backend/docs/SEAM_PACK_FINDINGS.md` новой секцией, старые не переписывай.
-**Закрытие проверяется ОТДЕЛЬНО от починки и не тем, кто чинил.** Это правило вывела предыдущая
сессия сама, и оно подтвердилось четыре раза подряд: ни одно «всё исправлено» без отдельной проверки
не выдержало. Пак маленький — тем легче заложить отдельный проход.
- ⚠ **И правило, стоившее этому проекту трёх раундов: прежде чем проектировать — прочти
ратифицированное.** Здесь это §4.4: ты правишь тексты, и правильный текст берётся из ноты, а не из
соседнего файла.
## 6. Оси ревью (две)
1. **Держится ли инвариант** — для §4.1 и §4.2: краснеет ли пин НА САМОМ ДЕЛЕ на названной мутации,
и не только в том пакете, где лежит правка.
2. **Не осталось ли двух контрактов** — после §4.3 и §4.4 греп по дереву не должен находить текста,
противоречащего ноте.
## 7. Записка-план
До кода — короткая записка `backend/docs/SEAM_FIX3_PLAN.md`. Пак маленький, записка соразмерная:
что делаешь, в каком порядке, какие развилки видишь. Комплектность — грепом, `^### 4\.`**6**.
## 8. Заявление = команда
Каждое число и каждая категорика — с командой, которой получены, прямо рядом. Приёмка пере-ранит.
## 9. Эхо-протокол старта
ДО работы — не больше десяти строк: скоуп · инварианты, которые не тронешь · что делать НЕ будешь.
## 10. Что НЕ удалось
Обязательная секция отчёта. «Не проверено» ≠ «работает».
## 11. Канал вопросов
Конфликт промта с кодом или доками — **пинг через владельца, не интерпретация**. Ты вправе сказать
«этого делать не надо» с аргументом. §4.5 и §4.6 прямо приглашают такой ответ.
---
## Приложение: что делает ОРКЕСТРАТОР, а не ты
Названо, чтобы ты этого не «допилил попутно» и чтобы видел, что предметы не потеряны:
- **Ратификация** класса полосы `write_incomplete`/exit 15 и версии отчёта v2 — D-нотой; тем же актом
**эрраты к строкам бэклога 191 и 203(з)**: движковая половина теперь УСТРАНЕНА, а не обойдена.
- **Порядок деплоя**: движок первым, `tmctl migrate` до прогонов, **сброс флага платформой умирает
ТОЛЬКО ПОСЛЕ** лендинга движка. Плюс миграционная нота: пустая память даёт один доброкачественный
стоп на книгу.
- **Снятие стендовых `book.yaml`-ключей** `mined_delta`/`mined_rejects` — в `books/` зона бэкенда не пишет.
- **Страница онтологии банка** в носителе архитектуры: таблица «роль · писатель · читатель · дисциплина
свежести» для источников, вида и проекций. Консилиум показал, что форма строгая — поток
«источники → вид → проекции» с единственными писателями и полным пересбором на границах, — но она
**не записана нигде**, и именно поэтому выглядит набором заплаток.
- **Строки бэклога:** джойн «предложено × решено × нерешено» существует только в движке, и экран
подписи при разморозке фронта заставит платформу пере-реализовать закон у себя — публиковать
нерешённость движком, когда экран закажут (сейчас — ноль кода) · межкнижный остаток оси арбитра
(второй конфиг ТОЙ ЖЕ книги с другим `project_db`) · майнерский хвост за потолком структурно
недостижим · банк-экспорт на стопе пуст.
## Приложение: что приёмка ПОДТВЕРДИЛА — не чини заново
- **Модель владельца исполняет движок:** флаг поднят → стоп → возобновление с поднятым флагом и НУЛЁМ
решений → редакторская волна. Проверено собственным тестом приёмки.
- **Батарея** `EXIT=0`, линтер 0 issues, флейков не было; **стенд-батарея** красна ровно на парити.
- **Каталог мутаций 58 — ноль неожиданных**, дерево после прогона чистое.
- **Четыре из пяти посадок приёмки вне каталога пойманы** (память не персистится · кластер вырождается
в поверхность · предикат новизны инвертирован · отказ записи отчитывается успехом). Пятая — §4.1.
- **`translate --dry-run`** теперь громкий отказ (раньше молча запускал платный прогон).
- **Ключи решений** сняты retired-отказом, называющим причину и лечение.
- **Форма архитектурно чистая** — консилиум проверил поток целиком: расхождение источников с видом
структурно невозможно дольше одной границы прогона. Глобальный пересмотр НЕ нужен.