diff --git a/docs/PLATFORM_SQLC_PACK_SESSION_PROMPT.md b/docs/PLATFORM_SQLC_PACK_SESSION_PROMPT.md new file mode 100644 index 00000000..c6905ea8 --- /dev/null +++ b/docs/PLATFORM_SQLC_PACK_SESSION_PROMPT.md @@ -0,0 +1,184 @@ +# Промт: платформа, пак `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. Карта чтения — ПЯТЬ позиций, дальше только по их ссылкам + +1. `platform/docs/PLATFORM_DIRECTION.md` §3 — **сначала верхний слой-баннер 22.08**: по `sqlc` действует + НЕ то решение, что записано ниже в разделе; отказ пака P7 там — история, а не действующая норма. +2. `platform/BACKLOG.md` строки **П-19** (эта работа) и **П-21** (см. §3.5 — флейк в твоей же зоне). +3. `platform/docs/ENGINEERING_STANDARDS.md` — норматив зоны; отступление от любого пункта = пинг. +4. `platform/internal/pgstore/sqlgate_test.go` — гейт, который уже съел бо́льшую часть ценности, и его + экстрактор. **Прочти ДО решения, что строишь** (§3.4 — там ловушка, решаемая до первой строки). +5. `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 денежных + 5 `identity` + 4 `idempotency`). Не ищи девять + несуществующих денежных запросов и не расширяй денежную границу на `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@.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` платформа не пишет. diff --git a/docs/README.md b/docs/README.md index 9259b0d8..e9f18bb5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -23,7 +23,7 @@ |---|---|---| | Оркестратор | [ORCHESTRATOR_SESSION_PROMPT.md](ORCHESTRATOR_SESSION_PROMPT.md) | роль и нормы; счётчик роли — CURRENT-STATE | | Бэкенд | активного НЕТ | пак «деньги» ПРИНЯТ И ЗАЛЕНДЖЕН 29.08 (**D39.170**): потолок ОБЪЁМА оплаченной работы + читающий путь `status` сворачивает банк, поэтому смета доезжает до покупателя ДО покупки. Промт отработан — `archive/prompts/`. ⚠ Следующий заказ уже назван строкой **232** (ось отгрузки на `once_key`), проводка `--max-units` в платформу ГЕЙЧЕНА | - | Платформа | активного НЕТ | пак **P11** ПРИНЯТ И ЗАЛЕНДЖЕН 29.08 (**D39.169**): `PD-379` закрыт живой пробой оркестратора (отзыв → поток гаснет за секунду кадром `session_ended` → переподключение `401`), видимость застрявших денег, денежная группа. Промт отработан — `archive/prompts/`. ⚠ Открытым остаётся денежный `major` `PD-425` (дверь коррекций теряет пост-verb факт при обрыве клиента), отсрочка на оркестраторе | + | Платформа | [PLATFORM_SQLC_PACK_SESSION_PROMPT.md](PLATFORM_SQLC_PACK_SESSION_PROMPT.md) | **ВЫДАН 29.08.** Пак `sqlc`: конверсия свободного от склейки блока `pgstore` (42 запроса в пяти файлах, строка П-19; решение владельца «БЕРЁМ» — D39.153 п.6а, отдельной сессией — D39.154). ⚠ Первым пунктом пака — не код, а ОТВЕТ числами: бо́льшую часть ценности уже съел гейт `sqlgate_test.go`, и «почти ничего» — законный исход. Оба рубежа пройдены, **14 находок опровергателя применены**, включая фантомную D-ссылку и ловушку пола экстрактора. Пред. пак P11 — принят и заленджен (D39.169) | | Полигон | [POLYGON_EXP2223_REDO_SESSION_PROMPT.md](POLYGON_EXP2223_REDO_SESSION_PROMPT.md) (отложенный — [POLYGON_PACKAGE4_SESSION_PROMPT.md](POLYGON_PACKAGE4_SESSION_PROMPT.md), строка 85) | фаза Д ИДЁТ; ⚠ живой носитель курса — в `eval/dovodka/`, какой именно называет зона (⚠ [POLYGON_PHASE_D_HANDOFF.md](POLYGON_PHASE_D_HANDOFF.md) — перекрытый снимок, читать не как курс) | | Фронт | активного НЕТ | **ЗОНА ЗАМОРОЖЕНА** (D39.136 п.2 + D39.147: разморозка отдельным словом владельца, не привязана к P7); перечень первого касания — в зонном журнале | | Контракт | активного НЕТ | минор **0.8.0** ПРИНЯТ и заленджен 29.08 (**D39.169**) вместе с паком P11: кадр `session_ended` — отзыв сессии гасит открытый поток и НАЗЫВАЕТ причину; кадр СОЕДИНЕНИЯ, своего номера не потребляет. До него в тот же день — **0.7.0** (D39.166, пере-проход как член `RunRequest.re_pass`), **0.6.0** (D39.162/163) и **0.5.0** (D39.161). ⚠ Названная цена 0.7.0 в силе: смету «затронуто N юнитов» ДО покупки провод НЕ несёт — строка **231** |