Fix what the preflight confirmed in the platform review prompt: subagents were isolated by tree but not by stand, a self-reference was dangling, the anchor gate demanded a forbidden stage, and two queue facts had gone stale
This commit is contained in:
parent
0f4c556906
commit
20a989b68e
1 changed files with 5 additions and 5 deletions
|
|
@ -18,7 +18,7 @@
|
|||
> уже найденное: `internal/metrics/metrics.go` (+гейдж `runs_stalled`) и `internal/pgstore/credits_test.go`
|
||||
> (+пин `PD-334`), плюс `internal/pgstore/isolation_test.go` (`PD-333`). Системного разбора ни та, ни
|
||||
> другая ось не получила — точечные находки при постройке это не он.
|
||||
> **(3) §4.7 работает В ОБРАТНУЮ СТОРОНУ:** релея тебе ждать не от кого, твои находки поедут в
|
||||
> **(3) Релей работает В ОБРАТНУЮ СТОРОНУ** (протокол — §4.7 АРХИВНОГО промта P8-FIX, `archive/PLATFORM_P8_FIX_SESSION_PROMPT_2026-08-21.md`; секции с таким номером в ЭТОМ файле нет — испр. 24.08): релея тебе ждать не от кого, твои находки поедут в
|
||||
> СЛЕДУЮЩИЙ кодовый пак — тем же протоколом, через оркестратора, с эхо-подтверждением.
|
||||
|
||||
## 0. Зачем
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
2. **`platform/docs/STACK_DECISIONS.md`** — правила, которые не выводятся из одной функции: §22 (порядок блокировок), §33–36 (долг материализации, `edit_wave`, техника `xmin`), раздел «Стенд разработчика» (сборка, ОБА гейта батареи, грабли).
|
||||
3. **`platform/docs/platform-PROGRESS.md`** — шапка (что построено и зачем) + **пинг оркестратора №18** в хвосте: там фикс-лист приёмки P7, и его **пункт 8 — это ты**.
|
||||
4. **`platform/docs/ENGINEERING_STANDARDS.md`** §3 — норма посадок мутаций зоны.
|
||||
⚠ Твой продукт — это ДЕСЯТКИ новых `file:line` в регистре, а гейт якорей с 21.08 видит `platform/docs` и умеет сверять по СОДЕРЖИМОМУ: `python3 docs/scripts/counts.py --lint --from-index` (от корня, ПОСЛЕ `git add` своих путей). ⚠ Именно `--from-index`: правило «на затронутых строках токен ТРЕБУЕТСЯ» живёт только на дельте индекса, поэтому прогон по рабочему дереву покажет ЗЕЛЁНОЕ там, где индекс краснеет — автор промта попался на этом сам 23.08, на двадцати девяти якорях сразу. Якорь может нести токен ожидания — `` `путь:12-14`=`подстрока` `` — и на строках, которые ты трогаешь, токен ТРЕБУЕТСЯ. Токен списывается из цели дословно, не по памяти: автор этого промта на этом попадался трижды за сутки.
|
||||
⚠ Твой продукт — это ДЕСЯТКИ новых `file:line` в регистре, а гейт якорей с 21.08 видит `platform/docs` и умеет сверять по СОДЕРЖИМОМУ: `python3 docs/scripts/counts.py --lint` от корня, БЕЗ `--from-index` и БЕЗ `git add` (⚠ испр. 24.08: прежняя редакция требовала стейджить свои пути, что прямо противоречило запрету §2 «git не трогать вовсе», и в дереве с живой полигон-сессией стейдж опаснее пропущенного токена). Чем ты за это платишь, знай точно: правило «на ЗАТРОНУТЫХ строках токен ТРЕБУЕТСЯ» живёт только на дельте индекса, поэтому твой прогон НЕ потребует токенов у новых якорей — он проверит лишь существование целей и уже написанные токены. Требование токена на своих строках остаётся на ТЕБЕ, и его пере-ранит приёмка со стейджем. Якорь может нести токен ожидания — `` `путь:12-14`=`подстрока` `` — и на строках, которые ты трогаешь, токен ТРЕБУЕТСЯ. Токен списывается из цели дословно, не по памяти: автор этого промта на этом попадался трижды за сутки.
|
||||
5. **`CLAUDE.md`**; жаргон — `docs/glossary.md`.
|
||||
|
||||
Всё остальное — код, и его ты достаёшь САМ: `file:line` ниже — отправные точки, а не пересказ. **Код первичен**: если док и код расходятся, верен код, а расхождение — находка.
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
|
||||
Отправные точки: `internal/pgstore/credits.go`, `internal/money/`, `internal/runs/reconcile.go` (`settle`, `restart`), миграции `00007_credits.sql`, `00010_spend_baseline.sql`, `00011_ceiling_argument.sql`. ⚠ Испр. оркестратором №19 23.08: прежняя редакция звала здесь `00019`, но это `00019_read_model_debt.sql` — долг read-модели, к деньгам отношения не имеет; ось 1 по ней ушла бы не туда.
|
||||
|
||||
**Норма, обязательная к исполнению (канон приёмок).** ⚠ Обязателен САМ ЗАМЕР, а не оформление уже найденного: сессия, ничего не нашедшая, чисел не производит — и норма «каждое число двумя путями» не связала бы ничего. Поэтому минимум: сведи на стенде баланс аккаунта, сумму леджера и открытые холды двумя путями ДО всякого поиска — расхождение здесь и есть первая находка. Дальше каждое число — из СЫРОГО леджера **двумя независимыми путями** (чтение кода/SQL и прямой `SELECT` по стенду). Пути обязаны сойтись или расхождение называется числом. ⚠ И вторая половина той же нормы, без которой первая обманывает: **леджер = НИЖНЯЯ граница**. Сходимость двух путей доказывает согласованность, а НЕ полноту: вызов, за который провайдер списал, а строка не легла, сойдётся в обоих путях одинаково неверно. Для оси, у которой этот путь прямо в предмете, ищи его отдельно.
|
||||
**Норма, обязательная к исполнению (канон приёмок).** ⚠ Обязателен САМ ЗАМЕР, а не оформление уже найденного: сессия, ничего не нашедшая, чисел не производит — и норма «каждое число двумя путями» не связала бы ничего. Поэтому минимум: сведи на стенде баланс аккаунта, сумму леджера и открытые холды двумя путями ДО всякого поиска — расхождение здесь и есть первая находка. ⚠ На СВЕЖЕМ стенде открытых холдов ноль, а леджер несёт одну строку гранта — сведение на нём сходится тривиально и ничего не доказывает; состояние, на котором замер осмыслен, создай сам (прогон, доводящий до резерва) и назови, на каком именно состоянии сводил. Дальше каждое число — из СЫРОГО леджера **двумя независимыми путями** (чтение кода/SQL и прямой `SELECT` по стенду). Пути обязаны сойтись или расхождение называется числом. ⚠ И вторая половина той же нормы, без которой первая обманывает: **леджер = НИЖНЯЯ граница**. Сходимость двух путей доказывает согласованность, а НЕ полноту: вызов, за который провайдер списал, а строка не легла, сойдётся в обоих путях одинаково неверно. Для оси, у которой этот путь прямо в предмете, ищи его отдельно.
|
||||
|
||||
### Ось 2 — ВХОД, СЕССИИ, CSRF
|
||||
|
||||
|
|
@ -77,7 +77,7 @@
|
|||
|
||||
### Ось 3 — ОЧЕРЕДЬ И ДЖОБЫ
|
||||
|
||||
⚠ **Блокер здесь УЖЕ НАЙДЕН — не ищи его заново, ищи его СИБЛИНГОВ.** Найденное: бюджет прохода свипа 2 минуты против бюджета одного прогона 60 секунд (⚠ **пак P8-FIX это ПОЧИНИЛ 22.08 и оба числа переехали** — теперь это дефолты операторских переменных `internal/config/config.go:433`=`SweepBudget: 2 * time.Minute` и `internal/config/config.go:434`=`RunBudget: 60 * time.Second`, пер-прогонный дефолт пакета — `internal/runs/reconcile.go:280`=`const defaultRunBudget = 60 * time.Second`; прежние якоря `runner.go:189` и `reconcile.go:70` мертвы, абзац оставлен как описание НАЙДЕННОГО, а не текущего кода) ⇒ двух медленных прогонов хватает, чтобы проход кончился до `UnsettledRuns` — единственного ретрая отложенного расчёта; `ListLiveRuns` сортирует по `started_at`, поэтому заклиненный прогон стоит в голове и голодит хвост детерминированно; ручки нет — `runs.Config.RunBudget` объявлен и в проде не присваивается.
|
||||
⚠ **Блокер здесь УЖЕ НАЙДЕН — не ищи его заново, ищи его СИБЛИНГОВ.** Найденное: бюджет прохода свипа 2 минуты против бюджета одного прогона 60 секунд (⚠ **пак P8-FIX это ПОЧИНИЛ 22.08 и оба числа переехали** — теперь это дефолты операторских переменных `internal/config/config.go:433`=`SweepBudget: 2 * time.Minute` и `internal/config/config.go:434`=`RunBudget: 60 * time.Second`, пер-прогонный дефолт пакета — `internal/runs/reconcile.go:280`=`const defaultRunBudget = 60 * time.Second`; прежние якоря `runner.go:189` и `reconcile.go:70` мертвы, абзац оставлен как описание НАЙДЕННОГО, а не текущего кода) ⇒ двух медленных прогонов хватает, чтобы проход кончился до `UnsettledRuns` — единственного ретрая отложенного расчёта; заклиненный прогон стоит в голове выборки и голодит хвост детерминированно. ⚠ **Две фактуры этого абзаца ПРОТУХЛИ, испр. 24.08 — знай, чтобы не искать уже построенное:** читателем свипа стал `internal/runs/reconcile.go:54`=`s.Store.RunsToReconcile(phase, s.now())` (это `ListLiveRuns` минус попытки, обслуживающие отсрочку — `internal/pgstore/runs.go:256`=`RunsToReconcile is ListLiveRuns minus`), а `ListLiveRuns` остался у телеметрии; и «ручки нет» БОЛЬШЕ НЕ ВЕРНО — `RunBudget` присваивается в проде: `cmd/tmplatformd/runner.go:40`=`RunBudget: cfg.Runner.RunBudget`. Класс дефекта абзац описывает верно, конкретные его носители — нет.
|
||||
|
||||
Приор: это класс «арифметика двух констант в разных пакетах, ни одна не покрыта тестом». Ищи такие же: где ещё поведение задаётся парой чисел, живущих врозь, и где у функции нет ни одного теста. Предмет шире: River-задания и их повторы · идемпотентность обработчиков · крэш-окна между сигналом и записью · свипы (интейк, идемпотентность, материализация) и их взаимное голодание.
|
||||
|
||||
|
|
@ -98,7 +98,7 @@
|
|||
## 5. Нормы
|
||||
|
||||
- **Самопроверка ИСПОЛНЕНИЕМ — механизмом, а не перечтением.** Названный механизм: (а) **посадки мутаций** по норме зоны — портишь инвариант ровно так, как его называет комментарий или строка регистра, и смотришь, краснеет ли пин; непойманная мутация в несущем инварианте — находка, а не примечание; (б) прямые `SELECT` по стенду для денежных чисел; (в) **субагенты РАЗРЕШЕНЫ и рекомендуются** — четыре оси независимы и делятся между ними без потерь (иначе дефолт-запрет харнесса тихо победит). Артефакт самопроверки — таблица «**ось** → что посадил → какой пин обязан был упасть → упал ли». ⚠ **Пол — не меньше одной посадки НА КАЖДУЮ ось**: без него буква промта удовлетворяется одной посадкой на весь пак и четырьмя непрочитанными осями.
|
||||
- **Мутации — в КОПИИ дерева**, не в репозитории, и КАЖДОМУ агенту своя: `cp -a platform ~/tm-p8-review/<имя-агента>/platform`, путь выдаётся агенту ЯВНО в его задании — «работай в копии» без выданного пути есть приглашение к инциденту (D39.113). Каждому агенту — тот же запрет state-changing git ПЕРЕЧИСЛЕНИЕМ, что и тебе. В дереве живут незакоммиченные работы параллельных сессий; правка = их потеря (норма изоляции D39.113).
|
||||
- **Мутации — в КОПИИ дерева**, не в репозитории, и КАЖДОМУ агенту своя: `mkdir -p ~/tm-p8-review/<имя-агента> && cp -a platform ~/tm-p8-review/<имя-агента>/platform` (⚠ испр. 24.08: без `mkdir -p` команда падает `cp: cannot create directory` — проверено исполнением). ⚠ **Копии дерева НЕДОСТАТОЧНО: изолируй и СТЕНД.** Общими остаются база, порты и каталоги, поэтому два агента на одном стенде затирают друг другу состояние и меряют чужие числа. Каждому агенту выдаётся СВОЙ набор: `TM_PLATFORM_TEST_DSN` (своя база — `createdb`), `TM_PLATFORM_ADDR`, порт метрик, `TM_PLATFORM_STATE_DIR`, `TM_PLATFORM_BOOKS_DIR`. Путь копии и весь набор выдаются агенту ЯВНО в его задании — «работай в копии» без выданного пути есть приглашение к инциденту (D39.113). Каждому агенту — тот же запрет state-changing git ПЕРЕЧИСЛЕНИЕМ, что и тебе. В дереве живут незакоммиченные работы параллельных сессий; правка = их потеря (норма изоляции D39.113).
|
||||
- **Батарея.** `make check` с ТРЕМЯ условиями, а не двумя (испр. 22.08, `PD-374`): `TM_PLATFORM_TEST_DSN` · `TM_PLATFORM_TEST_ENGINE_BIN`+`_BOOK_TEMPLATE` · ДОСТИЖИМЫЙ пользовательский менеджер systemd (без него три теста `internal/runner` скипаются молча, и «скипов 0» на таком хосте недостижимо в принципе). **Скипов 0 — гейт**, а если условие на твоём хосте не выполнено — НАЗОВИ его вместе с числом скипов, не объявляй батарею зелёной; без переменных батарея МОЛЧА скипует ~200 тестов, и её зелень тогда не значит ничего. Рецепт стенда — `STACK_DECISIONS`, раздел «Стенд разработчика».
|
||||
- **Тесты и гейты не подгонять под зелень.** Правка или удаление теста ради прохода недопустимы; несогласие с тестом — вопрос через владельца, не правка.
|
||||
- **Заявление = команда.** Каждое число и каждая категорика отчёта — с командой, которой они получены; приёмка пере-ранит и сверит. **Перед отчётом сверь КАЖДЫЙ клейм с результатом инструмента ЭТОЙ сессии**, а не с памятью о том, что видел час назад — у пака, чей единственный продукт это утверждения, цена неверного клейма выше, чем у кода.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue