textmachine/docs/PLATFORM_P13_SESSION_PROMPT.md

11 KiB
Raw Blame History

Промт сессии: ПЛАТФОРМА, пак P13 — «шов возврата оплаченного прогона»

Роль: платформа. Зона записи: platform/. Не коммитишь — дерево готовишь и передаёшь на лендинг оркестратору (канон — CLAUDE.md, таблица ролей). Чужие зоны читаешь, не правишь. Обязателен к ссылке: platform/docs/ENGINEERING_STANDARDS.md; отступление от него — пинг, не самовольство. Направление зоны — platform/docs/PLATFORM_DIRECTION.md.

Какая проблема и что изменит твой результат

Оплаченный прогон сегодня может подорожать, зависнуть или замереть на экране — без вины пользователя и без единого сигнала оператору. Четыре независимых пути ведут к одному и тому же: человек заплатил, а получил либо не то, либо ничего, и вывести его из этого состояния нечем, кроме psql. После пака оплаченный прогон возвращается на те деньги, за которые был продан, оператор перестаёт начислять кредиты дважды, а чужой процесс перестаёт замораживать чужую проекцию.

⚠ ПРЕДУСЛОВИЕ, НЕ ПУНКТ РАБОТЫ — прочти прежде всего

Экспортируй TM_PLATFORM_TEST_DSN до первой команды. Замер 02.09 на этом хосте: go test ./... -count=1 в platform/ без DSN даёт 661 тест: PASS 342, SKIP 319, FAIL 0, exit 0, все 18 пакетов «ok». В pgstore тёмно 167 из 177, в runs — 110 из 135, и среди пропущенных — 105 тестов денежного пути реконсилятора.

make check про это ЧЕСТЕН — печатает «did NOT run (set TM_PLATFORM_TEST_DSN…)» и имена скипов. Молчит именно голый go test ./....

Цена, которую ты обязан не повторить: в регистре восемь рядов заведены с формулировкой «мутация пережила ПОЛНУЮ батарею», четыре из них открыты (PD-433, PD-386, PD-389, PD-388), и ни один не называет DSN. На хосте без базы такой вердикт не значит ничего. ⇒ Каждая посадка мутации в твоём отчёте обязана нести строку «гонялось при DSN = да». Иначе пак проверит себя ровно тем способом, каким заводились ряды, которые он чинит.

Состав пака — четыре правки и один гейт

1. ГЛАВНОЕ — денежный бюджет прогона ЧИТАТЬ, а не пере-выводить из ставки. internal/runs/reconcile.go, греп s.Pricing.Ceiling(l.CeilingChapters) в reopen: бюджет берётся из ставки СЕГОДНЯШНЕГО деплоя. Вызывающих двое — свиповый restart и контрактный Resume, то есть путь дёргает пользователь. Смена TM_PLATFORM_USD_PER_CHAPTER между покупкой и продолжением молча пере-оценивает уже оплаченный прогон в обе стороны; при удвоении ставки на тонком счёте он становится невозобновляемым. Носитель — PD-168 (стоит minor, вес занижен). Задача: сумма, на которую пользователь согласился, хранится при покупке и читается при перезапуске. Форму решаешь сам и аргументируешь.

2. PD-89 — печатать ключ идемпотентности НА ПУТИ ОШИБКИ. write() чеканит id = newKey(), зовёт денежную операцию и на ошибке возвращает err, не напечатав ключ. Неоднозначный обрыв на коммите → оператор повторяет без --keyвторое начисление. Комментарий тремя строками ниже описывает ровно эту ловушку, но только для пути чтения баланса. Лечение — одна строка; посадка обязательна.

3. PD-426 + PD-214 — решать «ЧЕЙ handshake» ПРЕЖДЕ, чем его валидировать. internal/ingest/tail.go, функция apply: четыре отказа (декод, checkVersion, пустой EngineRunID, Seq != 1) стоят ВЫШЕ ветки «another attempt's stream begins here». Чужой ЗАКОННЫЙ hello карантинит проекцию оплаченного живого прогона, снятия карантина в дереве нет, операторской ручки нет. Гейдж tm_platform_quarantined_attempts это видит и молчит о том, что делать. Задача: перестановка решения о принадлежности выше валидации + ручка снятия карантина.

4. МЕЛКОЕ, закрывающее урок пака: гейт батареи печатает ВСЕ условия хоста, а не первое. Сегодня platform/Makefile подсказывает роль первого недостающего условия и молчит про остальные.

5. ГЕЙТ ПРОТИВ КЛАССА, а не против ряда (заказ оркестратора №22, замер 02.09): колонка серьёзности регистра разъехалась с сутью — 21 открытый ряд несёт два и более слова тревоги (деньги · холд · «молча» · блокирует · невидим · 500 · паника) при minor/info. Добавь в гейт зоны печать таких рядов. Без него следующая разведка снова доложит «major всего два».

Границы — что НАМЕРЕННО не берём

  • PD-412/PD-413 (LATERAL в полосном агрегате). Находки настоящие и замеренные (1.359 мс → 0.307 мс на книге 2283 глав), но это переписывание запроса в горячем read-модельном пути, а арифметика полосы в этом паке не трогается. Контенция, а не корректность денег.
  • PD-162 (клин на удалённом каталоге). Настоящий и денежный, но его терминальность — это эскроу (П-18), а половину эскроу рядом с проектируемым целым зона уже отказывалась строить (диспозиция P7).
  • Дверь выдачи — отдельный пак: он требует минора канона и сводит на себя все точки столкновения.

⚠ ПОРЯДОК ДЕПЛОЯ — почему пак безопасен параллельно бэкенду

Зоны независимы по коду (разные модули, импортов нет, go.work в корне отсутствует), но НЕ по деплою, и сцеплений ДВА с противоположным порядком: форма манифеста ⇒ «сначала платформа, потом движок» (незнакомая форма → parser_unavailable, интейк массово отклоняет); схема хранилища v16 и обход ⇒ «движок первым → tmctl migrate → потом платформа» (D39.158 п.6). Поэтому: пак НЕ меняет форму манифеста, схему хранилища и версию контракта. Понадобилось — стоп и пинг, не «сделаю аккуратно».

Свобода и её разметка

«Делай РОВНО так» — предусловие DSN · строка «DSN = да» у каждой посадки · границы выше · запрет на три вещи из порядка деплоя. Всё остальное — решаешь сам и аргументируешь: форма хранения бюджета, форма ручки снятия карантина, состав посадок, порядок работ внутри пака.

Мандат самопроверки — исполнением, не перечитыванием

Батарея зелёная — это НЕ отчёт. Обязательны: живая проба каждого из четырёх путей под DSN · собственные адверсариальные посадки ВНЕ списка выше · и отдельный проход по СВОЕЙ ГОТОВОЙ работе свежим контекстом. Субагенты разрешены явно; модель задавай ИМЕНЕМ и знай, сколько их работает. ⚠ Класс, купленный этой сменой: веер по исходным уликам находит втрое меньше, чем веер, читающий готовый результат.

Отчёт

Записка-план ДО работы (эхо-протокол: скоуп · инварианты · не-делать) в platform/docs/platform-PROGRESS.md. Итог — туда же. Каждое число и каждая категорика — с командой получения: приёмка пере-ранит. Обязательная секция «Что НЕ удалось и что НЕ проверено» — «не проверено» ≠ «опровергнуто». Конфликт промта с кодом — пинг через владельца, не интерпретация; право сказать «этого делать не надо» с аргументом у тебя есть.

Прямой канал

Механизм — CLAUDE.md, секция «Связь между сессиями». Впиши свой блок в /tmp/textmachine-channel первым делом; адрес роли бери оттуда, но сверяйся с ListAgents: адрес из файла не доказательство, что сессия жива. Нужной роли нет ⇒ канала нет, и это НОРМАЛЬНЫЙ случай — не опрашивай сессии подряд, вопрос секцией в отчёт.