19 KiB
Промт: платформа, пак sqlc — конверсия свободного от склейки блока pgstore
0. Что это за работа и почему она отдельной сессией
Платформа собирает SQL строками в Go. Класс дефектов, который это порождает, зона ловила дважды
рантайм-падениями. Владелец 20.08 решил взять sqlc — генератор типизированных методов из
.sql-файлов (D39.153 п.6а, «я вообще за»), а 22.08 уточнил: отдельной сессией, не внутри
содержательного пака (D39.154), потому что правок много и мешать их с другой работой нельзя.
Ты — эта сессия. Носитель работы — platform/BACKLOG.md строка П-19.
⚠ И сразу главное, чего промт не скрывает: бо́льшую часть ценности sqlc зона уже получила другим
механизмом. Гейт pgstore.TestEverySQLStatementParsesAgainstTheMigratedSchema
(internal/pgstore/sqlgate_test.go:36) планирует ЖИВЫМ Postgres каждый собранный запрос пакета против
мигрированной схемы — то есть закрывает класс «нет такой колонки» для ВСЕХ операторов, включая те, куда
sqlc не дойдёт никогда, и где случились оба реальных падения зоны. По разбору D39.155 п.9 остаётся
узкий остаток: арность $n и цели Scan.
Что решит твой результат: снимет остаток, которого гейт не берёт, и уберёт ручную сборку там, где она не нужна. Чего не решит: склейки, read-модель и денежные транзакции остаются рукописными.
1. Зона записи и git
Пишешь только в platform/. Не коммитишь: дерево готовишь и передаёшь оркестратору, он лендит.
Канон git — CLAUDE.md, здесь не дублируется. Чужие незакоммиченные файлы не трогать.
2. Карта чтения — ПЯТЬ позиций, дальше только по их ссылкам
platform/docs/PLATFORM_DIRECTION.md§3 — сначала верхний слой-баннер 22.08: поsqlcдействует НЕ то решение, что записано ниже в разделе; отказ пака P7 там — история, а не действующая норма.platform/BACKLOG.mdстроки П-19 (эта работа) и П-21 (см. §3.5 — флейк в твоей же зоне).platform/docs/ENGINEERING_STANDARDS.md— норматив зоны; отступление от любого пункта = пинг.platform/internal/pgstore/sqlgate_test.go— гейт, который уже съел бо́льшую часть ценности, и его экстрактор. Прочти ДО решения, что строишь (§3.4 — там ловушка, решаемая до первой строки).platform/docs/STACK_DECISIONS.md§«Гейты батареи» — единственный носитель числа условий батареи.
3. Работа
3.0 ⛔ ПЕРВЫМ ДЕЙСТВИЕМ — СИНХРОНИЗАЦИЯ С КОДОМ (делай РОВНО так, слово владельца)
Все числа ниже — мои на 29.08, и часть из них уже расходилась с носителями. Пере-считай сам, до
первой правки, и назови расхождения в отчёте: расхождение — факт, а не твоя ошибка. Заодно сверь, что
git status чист и в дереве нет чужой незакоммиченной работы.
3.1 Затем — ОТВЕТ, а не код (реши сам, аргументируй)
Вопрос: что sqlc даёт СВЕРХ существующего гейта? Ответь ЧИСЛАМИ до первой строки конфигурации:
сколько запросов набора не проверяется сегодня ничем, какие классы ошибок это ловит, что из этого не
ловится дешевле.
⚠ Число «два запроса, не исполняемых ничем» взято из D39.155 п.9, НЕ проверено мной и, вероятно,
занижено. Мой опровергатель нашёл статически минимум четыре функции набора без единой ссылки из
тестов пакета: OpenReservations (credits.go:142), ReleaseUnspawned (credits.go:324),
DeleteOldLoginEvents (identity.go:73), UserByIdentity (identity.go:121) — их вызовы живут под
cmd/, где тесты есть, но достигают ли они этих путей, никто не проверял. Метод определения выбираешь
сам (покрытие живым прогоном / инструментальный анализ), но метод назови: это самое дорогое число
пака, и на нём висит развилка «строить или нет».
- Ответ «существенно больше остатка» — строй, покажи расчёт.
- Ответ «почти ничего» — СКАЖИ ЭТО и остановись. Законный исход (см. §7), а не провал: владелец сказал «БЕРЁМ», зная довод про гейт, но твоих чисел на сегодняшнем дереве он не видел.
3.2 Граница набора — числа уехали, носители расходятся (делай РОВНО так: считай сам)
П-19 называет 41 запрос. Моя пере-проверка 29.08 даёт 42: credits.go 15 · identity.go 13 ·
idempotency.go 7 · sessions.go 6 (было 5; пак P11 добавил StillLive, лендинг e548e5a) ·
observe.go 1. Операторов в пакете вне тестов — около 168, то есть набор это примерно четверть
пакета, а не шестая часть. ⚠ Сам гейт в комментарии (sqlgate_test.go:21-23) даёт третью оценку доли
склеенного — носители расходятся, выбери и назови свой метод счёта, а не наследуй чужой.
⚠ Граница описана оптимистичнее, чем есть (D39.155 п.9), и это твой главный риск:
- набор НЕ замкнут по транзакции: 8 запросов идут из транзакций неконвертируемого кода — все в
credits.go(lockBalance,holdTx,appendLedger,closeReservation,lockBook), достижимы изruns.go,books.go,readmodel.go,sink.go. Генерённый метод, вызванный внутри чужой транзакции, обязан её ПРИНИМАТЬ, а не открывать свою. - ⚠ Поправка к самой ноте, проверенная мной: её фраза про «занижено вдвое» неверна. Денежных
запросов в чужой транзакции — 11 из 15 в
credits.go, и это точно; 20 — это ВСЕ транзакционные запросы набора (11 денежных + 5identity+ 4idempotency). Не ищи девять несуществующих денежных запросов и не расширяй денежную границу наidentity/idempotency.
3.3 Стройка (форму выбираешь сам, ограничения жёсткие)
- Инструмент пинится ТОЧНОЙ версией, как
golangci-lintвplatform/Makefile:21с гейтом версии на:55. Версию бери ЖИВОЙ проверкой у вендора, не из памяти и не из этого промта.sqlcв тулчейне сейчас нет — установка твоя. - Гейт актуальности генерации — В БАТАРЕЕ (делай РОВНО так). Не просто цель
Makefile: цель, которуюmake checkне зовёт, гейтом не является, а П-19 заказывает именно гейт «сгенерённое актуально». Прогон на чистом дереве не меняет ни байта. - Строка в
STACK_DECISIONS.md— обязательный деливерабл зоны для любой новой зависимости (ENGINEERING_STANDARDS.md:12-14): дата релиза и «зачем». Ратифицирует оркестратор — пришли её вместе с деревом, не считай сделанной сама. - Денежные типы требуют
overrides: micro-USD целочисленный, и генерённый слой не имеет права превратить его в float ни на одном шаге (класс PD-15). - ⛔ Не двигать: склейки, фрагменты-константы, read-модель (
readmodel.go— страница, её ревизия, курсор, водяной знак и агрегаты в ОДНОЙ транзакции). - ⚠ Шов, который надо решить явно:
lockBookживёт в конвертируемомcredits.go:481, но зовётся изreadmodel.go:262иbooks.go:374— то есть стоит ровно на границе ⛔-зоны и набора. Конвертировать или оставить — реши и аргументируй, молча не бери ни то ни другое.
3.4 ⛔ РАЗВИЛКА, КОТОРУЮ РЕШАЮТ ДО ПЕРВОЙ СТРОКИ КОНФИГУРАЦИИ
Куда генерировать: в сам pgstore или в под-пакет (дефолт sqlc)? У экстрактора гейта жёсткий
пол — if len(stmts) < 140 (sqlgate_test.go:41), и глобит он *.go только в СВОЁМ каталоге. Уведи
42 оператора в под-пакет — счёт упадёт ниже пола, и гейт покраснеет по собственному полу. ⚠ Подвинуть
пол ради зелени НЕЛЬЗЯ: это подгонка гейта, запрещённая каноном. Значит либо генерируешь в тот же
каталог, либо расширяешь ОХВАТ экстрактора (не пол) так, чтобы генерённые операторы продолжали
проверяться живой схемой. Реши, аргументируй, и покажи прогоном, что гейт видит их после конверсии.
Второй носитель схемы. sqlc нужен вход-схема, а у зоны она уже имеет носителя с гейтом целостности:
internal/pgstore/migrations/ + манифест migrations.sha256 (migrations_test.go). Собственная копия
схемы в конфиге заведёт второй носитель факта, которого манифест не видит, — класс «один носитель на
факт». Реши и аргументируй, как этого избежать.
3.5 ⚠ Красное, которое НЕ твоё (знай заранее)
В idempotency_test.go:265 живёт TestAClaimThatLostARaceToAReleaseIsRetriedAndNotAnError — известный
флейк, PD-369 / BACKLOG.md П-21, замерено 1–2 падения на ~80 прогонов, разгоняется -race.
Файл idempotency.go — в твоём наборе. Увидишь красное — сперва пере-прогони серийно, и не приписывай
его конверсии. ⛔ И не «чини» его ради зелени: править или удалять тест, чтобы он прошёл, недопустимо
(D39.121); несогласие с тестом — пинг, а не правка.
4. Самопроверка ИСПОЛНЕНИЕМ (без неё работа не принята)
Мандат — не «перечитал», а прогон с числами:
- Батарея зоны с полным набором гейтов,
-raceобязателен. ⚠ Условий у батареи больше, чем помнит большинство доков, и часть требует РУЧНОЙ сборки стенда (движковый бинарь + $0-пайплайн, которого в репо нет; плюс условие проuser@<uid>.service, под WSL не выполняющееся). Рецепт — в карте чтения поз. 5. Заложи на это время отдельно и назови в отчёте, какие условия у тебя выполнены, а какие нет. - Поведенческая эквивалентность: каждый конвертированный запрос доказывается тем, что его тест проходит ДО и ПОСЛЕ. Дифф генерённого кода — не доказательство.
- Дифф
^func Test— ИСПОЛНЕНИЕМ, не памятью: покажи командой, что ни один тест не исчез и не переименовался при переписывании слоя. - СОБСТВЕННЫЕ мутационные посадки, не список из промта: сломай арность
$n, подмени цельScan, поменяй тип денежной колонки — каждая обязана падать АДРЕСНО. Посадка, которую никто не ловит, ценнее трёх пойманных: неси её в отчёт. - Разрешаю субагентов (иначе дефолт харнесса тихо запретит). Модель задавай ЯВНО и знай, сколько их работает. Трудный вопрос — старшей модели.
- Интервальная самоверификация (D39.121): пак длинный, поэтому в середине работы — проход субагента по СВОЕЙ готовой части против явных критериев, не в конце.
- ⚠ Адверсариальный проход по своей готовой работе перед сдачей — ОБЯЗАТЕЛЕН, изменения потенциально опасные (слово владельца). Направление, что уязвимо здесь: генерённый метод, открывающий свою транзакцию внутри чужой; денежный тип, потерявший целочисленность на границе; запрос, выпавший из-под гейта; тихо-зелёный тест — проходящий, ничего не проверив (D39.171). Глубину и веер выбираешь сам.
- Доказательная база — в РЕПОЗИТОРИЙ (логи посадок, числа прогонов идут в зонный журнал), а не в
/tmp: что должно пережить рестарт, живёт в дереве.
5. Оси ревью
Деньги (целочисленность micro-USD сквозь генерацию, транзакционные границы) · шов с гейтом (ни
один запрос не выпал из sqlgate_test.go) · воспроизводимость генерации. Вправе заменить ось с
аргументом.
6. Записка-план и комплектность
До стройки — короткая записка-план в зонный журнал: что берёшь, что не берёшь, чем докажешь. Перед сдачей — механическая сверка состава против §3, таблицей: пункт → сделано/нет → чем доказано. Пропуск подписывается пропуском. Последний абзац отчёта оказался планом или обещанием? Сделай сейчас.
7. Канал вопросов и право отказаться
Конфликт промта с кодом или доками — пинг через владельца, не интерпретация. Есть право сказать «этого делать не надо» с аргументом; по §3.1 это ожидаемый исход, а не поражение.
8. Заявление = команда
Любое число и любая категорика в отчёте — с командой, которой получены. Приёмка пере-ранит: клейм без пере-прогона записывается как «со слов сессии». «Проверено» без исполнения в этой зоне уже дважды оказывалось ложным.
9. Эхо-протокол старта
ДО первой правки — ≤10 строк: скоуп / инварианты / чего не делаешь. Отправь первым действием по
адресу оркестратора из /tmp/textmachine-channel (механизм — CLAUDE.md §«Связь между сессиями»; впиши
туда СВОЙ блок первым делом). Эхо служит и проверкой канала. Канала нет ⇒ НЕ искать: вопрос секцией
в отчёт, работа продолжается.
10. Obstacle reporting
Обязательная секция отчёта: что НЕ удалось и что осталось непроверенным. Пустой не бывает. Три исхода: «подтверждено» / «опровергнуто» / «не проверено» — третье не сваливать во второе.
11. Зонный журнал
Итоги, пинги и вопросы — platform/docs/platform-PROGRESS.md. В docs/PROGRESS.md платформа не пишет.