textmachine/docs/BACKEND_MIGRATE_SESSION_PROMPT.md

7.3 KiB
Raw Blame History

Промт: бэкенд, малое касание — tmctl migrate (строка 174: деадлок деплоя v15)

Выдан оркестратором №16 14.08.2026. Запуск — по слову владельца (запуск = ратификация варианта А строки 174). Лёгкий класс: короткий промт, инлайн-приёмка — но самопроверка исполнением обязательна, это путь у денег и данных.

0. Какую проблему решаем

Движок TextMachine — CLI-процесс (tmctl) со своим SQLite на книгу. Read-only команды (status, report) требуют ТОЧНОГО совпадения версии схемы («schema vN … expects vM», internal/store/store.go:135-143) и мигрировать не вправе; мигрирует схему только write-команда. Платформа (platform/) зовёт tmctl status --json ПЕРЕД каждым спавном прогона и для расчёта денег. Следствие — деадлок деплоя: апгрейд бинаря движка запирает ВСЕ существующие книги — status отказывает старой схеме, а write-команда, которая мигрировала бы, не наступает никогда (строка 174 единого бэклога, найдена приёмкой D39.131). Прямо сейчас это блокирует деплой свежезаленденного эмиттер-бинаря (D39.131) на стенд платформы.

Твой результат: $0-команда tmctl migrate — явный write-open книги без прогона. Платформа вставит её деплой-шагом «стоп прогонов → migrate по каждой книге → новый бинарь в работу».

1. Онбординг

CLAUDE.md (корень; гардрейлы: зона записи ТОЛЬКО backend/, ты НЕ коммитишь, .env не читать, чужие незакоммиченные файлы не трогать) → backend/README.mddocs/architecture/12-go-style-notes.md (норматив общности §0). Entry-points (код первичен): cmd/tmctl/main.go (диспетчер команд), internal/store/store.go (Open — write-путь: миграции + recoverReservations; OpenReadOnly — отказ по версии).

Эхо-протокол: ≤10 строк «что я понял» до работы.

2. Задача (делай РОВНО так по границам; форму внутри — реши сам и аргументируй)

tmctl migrate --config <book.yaml> (алиасы/форма флагов — как у соседних команд):

  • Открывает проект write-путём (store.Open) — миграции применяются, recoverReservations проходит, — печатает schema vN -> vM (или «already at vM») и выходит. Никаких LLM-вызовов, сети, трат: $0-команда, как manifest/status.
  • Идемпотентна: повторный вызов на свежей схеме — успех и no-op.
  • Exit-коды — по свежей конвенции полосы отказов (D39.131: 10 конфиг · 12 лок · 19 безымянный); успех 0. Не изобретай новых кодов.
  • Тест: фикстура/БД старой версии → migrateOpenReadOnly/status работает; лок занят → exit 12; повторный вызов — no-op. Плюс дифф ^func Test исполнением, не памятью.

3. Границы и известные мины (приоры — опровергаются замером)

  • Деньги: recoverReservations обнуляет остаточный reserved_usd — на этом свойстве стоит ратифицированная формула потолка платформы (PD-158: аргумент = committed + прирост, БЕЗ reserved). migrate перед спавном делает status честнее, формулу не ломает — ПРОВЕРЬ это утверждение по коду и НАЗОВИ в отчёте явно; расхождение = пинг, не тихий фикс.
  • Гейт prices_checked не должен убивать миграцию. LoadModels жёстко отказывает конфигу с ценами старше 120 дней (internal/config/models.go:209-214), и строка 146 единого бэклога уже фиксирует: этот гейт стреляет на read-only/$0-путях, где перекупки нет. Если migrate соберёшь поверх полного конфиг-стека, протухшие цены превратят $0-миграцию в отказ — и деплой-деадлок вернётся ровно в той форме, которую команда лечит. Открывай store/книгу БЕЗ валидации свежести цен (или обоснуй, почему она тут уместна) — и назови выбор в отчёте.
  • Строка 49а (ALTER-шаги миграций v8v14 не идемпотентны на полу-применённой БД) — знать, НЕ чинить этим касанием (отдельная строка); твоя команда не должна усугубить (никаких новых ALTER, только вызов существующего механизма).
  • Снапшоты/голдены/RequestHash не двигаются — команда не трогает промпты и провод; голден-батарея обязана остаться бит-в-бит.
  • Общность §0: ничего пар-/книго-специфичного.

4. Самопроверка и сдача

cd backend && make battery EXIT=0; самопроверка исполнением (живой прогон команды на копии проектной БД двух версий — не чтением диффа); адверсариальная вычитка собственного диффа с установкой опровергать (субагент разрешён явно); «заявление = команда». Отчёт короткий: что построено · команды проверок · взаимодействие с PD-158 · чего не делал. Итог — пингом в docs/PROGRESS.md секция «Бэкенд» — ТОЛЬКО append своей записи (файл держат параллельные сессии: CURRENT-STATE и чужие секции не трогать, перед правкой git status); дерево НЕ коммитить — лендит оркестратор.

5. Канал вопросов

Непонятно / конфликт промта с кодом → пинг оркестратору через владельца, НЕ интерпретация.