From ea543551df3a481f45bc96904b156f5f290b42ab Mon Sep 17 00:00:00 2001 From: heaven Date: Thu, 3 Sep 2026 23:18:02 +0300 Subject: [PATCH] Issue dofix orders to both worked sessions after the acceptance: ten engine items, six platform items, each with the command that reproduces it --- docs/BACKEND_DOFIX_2026-09-03.md | 211 ++++++++++++++++++++++++++ docs/PLATFORM_P13_DOFIX_2026-09-03.md | 186 +++++++++++++++++++++++ 2 files changed, 397 insertions(+) create mode 100644 docs/BACKEND_DOFIX_2026-09-03.md create mode 100644 docs/PLATFORM_P13_DOFIX_2026-09-03.md diff --git a/docs/BACKEND_DOFIX_2026-09-03.md b/docs/BACKEND_DOFIX_2026-09-03.md new file mode 100644 index 00000000..6a8ce815 --- /dev/null +++ b/docs/BACKEND_DOFIX_2026-09-03.md @@ -0,0 +1,211 @@ +# ДОФИКС бэкенд-паку «число согласия на пути второй покупки» — по приёмке оркестратора №22 (03.09.2026) + +> **Роль:** бэкенд, та же сессия, что отработала пак. **Зона записи:** `backend/` + своя секция +> «Бэкенд» в `docs/PROGRESS.md`. Чужие зоны читаешь, не правишь. **Не коммитишь** и не трогаешь индекс +> и историю — запреты и причина: `CLAUDE.md`, «Git-координация мультисессий». +> ⛔ **В индексе сейчас лежит НЕЗАКОММИЧЕННАЯ работа двух смен (46 файлов).** Ни одной пишущей +> git-команды: ни `checkout`, ни `restore`, ни `stash`, ни `reset`, ни `clean`, ни `add`, ни `commit`. + +## Что это и почему оно пришло + +Пак **принят с дофиксом**. Приёмка шла не чтением отчёта: десять линз (пять на зону), каждая обязана +была проверять исполнением, каждая находка ушла опровергателю с мандатом её ОПРОВЕРГНУТЬ своей +командой. По бэкенду 20 находок, 19 пережили опровержение. + +⚠ **Твой код в основном подтверждён — ниже отдельная секция «что приёмка проверила и признала», и её +переделывать не нужно.** Дофикс про другое: пак создал один дефект в том, что сам чинил, оставил +ложным одно РАТИФИЦИРОВАННОЕ утверждение, и три свойства, объявленные твоими, тестом не прибиты — +мутации приёмки их пережили. + +## Карта чтения — три позиции + +1. Этот файл. Твой прежний промт `docs/BACKEND_CONSENT_SESSION_PROMPT.md` — уже прочитан, перечитывать + целиком не надо. +2. Свой отчёт в `docs/PROGRESS.md`, секция «Бэкенд», запись 03.09 — по пунктам Б7–Б10 правится он сам. +3. Улики ниже. **Каждая проверена приёмкой исполнением; воспроизведи их сам** — если что-то не + воспроизводится, это находка, неси её, а не подгоняй работу под текст. + +## Б1 [важное] — стоп-строка и лог лгут ровно в том случае, который пак СОЗДАЛ + +`bound()` теперь истинен при `Carried > 0`. Значит прогон, дошедший **до конца книги** и лишь +дописавший начатое, печатает оператору самопротиворечие: + +``` +backend/internal/pipeline/volume.go:220 — «stopped on the VOLUME ceiling (--max-units %d), + not on money and not at the end of the book» — префикс БЕЗУСЛОВЕН, внутри самого fmt.Sprintf +и тут же в том же предложении: «Still in the book: 0 unit(s) NEVER delivered» +``` + +Воспроизведено живым прогоном настоящего `Runner` (две главы, первый прогон умирает на редакторе, +второй с `MaxUnits=2`): `Left()=0 granted()=0 Paid()=2`, и обе половины предложения печатаются. +Тот же текст едет в лог `waverun.go:173`, а комментарий у вызова `waverun.go:169-170` («Only set when +the ceiling actually held work back») протух — **в файле, который пак правил**. + +**Делай РОВНО так:** предложение разводится на два случая — грант кончился / книга кончилась. +**Решаешь сам:** формулировки обеих веток и нужен ли отдельный текст для смешанного случая. +⚠ Пункт 2 пака закрывался ИМЕННО как дисклоужер — объявлять его закрытым до этой правки нельзя. + +## Б2 [важное] — ратифицированный контракт кадра `finished.volume` стал ЛОЖНЫМ + +`D39.181 п.2` объявляет ПРИСУТСТВИЕ поля булевым признаком «грант придержал работу»: + +``` +backend/internal/runevents/runevents.go:189 «present only when a volume grant actually held work back» +backend/internal/runevents/runevents.go:202-204 «its PRESENCE is the boolean: the engine attaches this + only when the grant actually held something back» +те же утверждения — backend/internal/pipeline/events.go:584-588 и bookrun.go:91 +``` + +Кадр теперь приезжает и у прогона, дошедшего до конца книги (`left_fresh:0`, `left_rework:0`), и +`carried` на провод не выходит вовсе — то есть читатель различить два состояния НЕ МОЖЕТ ничем. +Пак переписал соседние поля ТОЙ ЖЕ структуры (`Delivered`, `Free`), а утверждение тремя строками выше +оставил. Сегодня безопасно только потому, что потребителя нет: `platform/internal/ingest/events.go` +декодирует `Finished{Outcome}` и всё. + +**Делай РОВНО так:** текст контракта приводится в соответствие с поведением ВО ВСЕХ ЧЕТЫРЁХ местах. +**Решаешь сам:** формулировка. ⛔ **Поля на провод НЕ добавлять** — это класс «новое поле в +опубликованном документе», он требует ратификации и минора `StreamVersion`, и владелец 03.09 уже +сказал «оставить как есть». Если считаешь, что честный контракт без поля невозможен, — **пинг**, а не +поле. + +## Б3 [важное] — три свойства объявлены твоими и НЕ прибиты: мутации приёмки пережили весь пакет + +Все три посажены приёмкой на копии дерева, каждая SURVIVED на `./internal/pipeline/`, и в том же +прогоне соседние посадки дали RED — то есть положительный контроль стоит. + +- **(а) `volume.go:191`** — `case class == unitFresh && s.stop.Delivered > s.stop.Carried:`. Возврат к + форме `> 0` (и эквивалентной `>= 1`) переживает пакет. Существующий `TestReconcileKeepsCarriedInsideDelivered` + (`volumeslot_test.go:554`) гоняет только ветки `unitFree` и до этой ветки не доходит. + ⚠ Отчёт числит за этой находкой «посадку **Y3**», **которой в репозитории нет** — см. Б7. +- **(б) `rebill.go:450`** — подмена `projectionBasis(proj)` на `projectionBasis(book)` переживает пакет. + Ветка-близнец (scoped-клауза, `:505`) от той же подмены КРАСНЕЕТ через + `TestTheScopedClauseOfTheRefusalCarriesItsOwnBasis` — значит пакет эту подмену ловить умеет. +- **(в) `rebill.go:323`** — `if p.ModelMovedRows > 0` заменяется на `>= 0`, и «0 of the N unit(s) were + bought from a model…» уезжает в КАЖДЫЙ текст согласия; пакет зелёный. У близнеца `HistoricalRows` + отрицательный пин ЕСТЬ (`reprice_test.go:569-572` проверяет, что чистая сумма НЕ содержит + «originally billed»), у новой оговорки — нет нигде. + +**Делай РОВНО так:** каждое свойство получает тест, который от своей мутации краснеет, И запись в +`backend/cmd/tmmutate/mutations.json`. **Решаешь сам:** форма тестов и формулировки записей. +⚠ Приёмка сажала СВОИ формы мутаций — не копируй их, посади свою и убедись, что она красная. + +## Б4 [мелочь] — докстринг `classifyUnits` не пере-считан под собственную правку + +`volume.go:637`: «sorts every output unit into the **three** things this run can do to it», а `unitClass` +несёт ЧЕТЫРЕ члена, и добавленный паком `unitCarried` присваивается ВНУТРИ самой этой функции. +Вредно адресно: читатель, ищущий, куда попадает начатый-но-не-отгруженный юнит, по слову «three» +решит, что четвёртого класса нет, — и пойдёт искать в ветку `unitFresh`, ровно туда, где жил дефект +строки 232. **Делай РОВНО так**, правка на одно слово. + +## Б5 [мелочь] — пример в `backend/README.md:73` противоречит новой семантике + +Строка обещает «оплатить не больше 10 выходных юнитов», тогда как тело README:11 новую семантику +раскрывает верно. **Делай РОВНО так:** привести пример к телу. + +## Б6 [мелочь, по желанию] — шов `store → репрайсер` прибит с одной стороны + +Подмена `c.escalation` на `0` в `ledger.go:380` переживает `./internal/store/`, а `./internal/pipeline/` +краснеет через `TestAnEscalatedRowIsRePricedAtTheNewHopEndToEnd`. Дефектом сегодня не является — пин +живёт там, где живёт свойство. Но твой же довод по фильтру книги («мутация пережила обе батареи по +отдельности, значит одной мало» — оттого FC1-book-filter-**store** И -**pipeline**) применим и здесь. +**Решаешь сам:** заводить ли запись каталога на store-стороне; отказ аргументируй. + +## Б7 [среднее] — отчёт ссылается на ПЯТЬ несуществующих посадок как на живые гейты + +`Y2-silent-when-nothing-left` · `Y3` · `Z2` · `X29` · `Y4`. Каталог получил ровно ШЕСТЬ записей +(`FC1-*`×4, `FC5-*`×2); 35 заявленных собственных посадок жили в scratch-каталогах +(`own_mutations.json`, `round2_mut.json`, `round3_mut.json`, `draftonly_mut.json`), которых на машине +нет. Проверено грепом с границами слова, положительный контроль на ту же форму: `FC1-book-filter-store` +находится в двух местах. + +Читатель отчёта принимает пять несуществующих гейтов за живые — а один из них «закрывает» гарантию, +чья мутация переживает (Б3а). **Это ровно та болезнь, ради которой `tmmutate` и лежит в репозитории.** + +**Делай РОВНО так:** либо снять ссылки, либо посадить недостающие записи в каталог. +**Решаешь сам:** какие из пяти стоят записи, а какие были разведкой. + +## Б8 [мелочь] — четыре числа отчёта не печатаются командами, которые он для них называет + +- «денежного пути в каталоге было 0 файлов, стало **5**» — каталог даёт 18 → 21 различных файла, то + есть ТРИ новых (`reprice.go`, `volume.go`, `ledger.go`), шесть записей; греп из промта печатает 7. + Ни одно прочтение не даёт 5. +- «на входе **3** попадания» у грепа `can never quote a different number` — на входном коммите в + названной области попадание ОДНО. +- «все **18** строк» линта — гейт печатает **19**, и девятнадцатый создан самим отчётом + (строка, цитирующая `docs/PROGRESS.md:679`). +- «в файле **485** строк» — 499: число снято до того, как отчёт дорос. + +**Делай РОВНО так:** пере-считать каждое своей командой и вписать команду рядом с числом. +⚠ `python3 docs/scripts/counts.py --lint` гнать **ПОСЛЕДНИМ действием**, после того как отчёт дописан, +и починить 19-й якорь — иначе гейт остаётся красным по вине самого отчёта. + +## Б9 [мелочь] — неполнота самообъявления по D39.183 + +`TestCheckpointsOfOneGenerationSumToTheRowsCost` (`reprice_test.go:639`) адаптирован под третий возврат +`usd()`, а в блоке самообъявления не назван, хотя остальные четыре адаптации под ту же смену сигнатур +перечислены поимённо. Ослабления нет — правка механическая. Это ровно класс, который бэклог держит +строкой **248**. **Делай РОВНО так:** дописать имя. + +## Б10 [к сведению, НЕ заказ] — что приёмка нашла и что сознательно НЕ чинится этим дофиксом + +Назови это в отчёте, чтобы оно не умерло молча вместе с паком. + +- **`Carried` на провод не выходит**, а подсказка, дописанная паком в докстринг `Delivered`, ключуется + на `delivered > max_units` — и в форме «весь остаток перенесён» `delivered == max_units`, то есть + подсказка НЕ срабатывает и разложить кадр читателю нечем. Связано с открытым вопросом владельца о + семантике переноса; чинится вместе с ним, а не отдельно. +- **В перенос попадает и юнит, который ФЛАГНУЛСЯ и текста не отдал** — он «начат и не отгружен», + значит каждая следующая покупка снова платит за его пере-атаку ВНЕ гранта. Приёмка это вывела из + `classifyUnits` и подтвердила зелёными тестами пака, но **цикла из трёх последовательных покупок не + гонял никто**. Это вход в решение владельца, а не дефект — не чини, но не потеряй. + +## Границы — что НЕ делать + +- ⛔ **Не добавлять поле на провод** (см. Б2) и не двигать `StreamVersion`, форму манифеста, схему + хранилища, версию контракта. +- ⛔ **Не менять семантику переноса слота.** Владелец 03.09 отложил её словом «подумаем на этот счёт». + В коде сегодня «перенос ограничен грантом», и приёмка это ЗАМЕРИЛА: грант 2 оплачивает 4 выходных + юнита, 6 вызовов провайдера. Это открытый вопрос владельца, а не дефект — трогать нельзя. +- ⛔ **Не править `docs/architecture/15-money-path.md` и тело `D39.170`** — они противоречат новой + семантике `--max-units`, это правда, но это зона оркестратора, и он их правит сам. Ты правильно + сделал, что не полез. +- ⛔ Не трогать чужие зоны, `.env`, соседний worktree. + +## Что приёмка ПРОВЕРИЛА и признала — переделывать не нужно + +- Батарея зелёная: `EXIT=0`, `0 issues`, три известных SKIP, ни одного FAIL. Тестов **1083 → 1102**, + удалённых имён **НОЛЬ** (пофамильный дифф). +- Все ШЕСТЬ каталожных мутаций пере-посажены и **все шесть КРАСНЫЕ**. +- Четыре обязательства `D39.150 п.1` исполнены ВСЕ, включая четвёртое: обещание точности снято из + `status.go`, шапка `reprice.go` заявляет обратное прежнему. +- Инвариант направления ошибки держится по построению: в `repriceCheckpoint` цена только повышается — + пол по ответившей модели, подъём до сегодняшней. +- Правки существующих тестов проверены на МОТИВ: подгонки нет, все стали СИЛЬНЕЕ (проверка трёх полей + → проверка всей структуры; добавленное утверждение про basis). +- Границы соблюдены: схема, манифест, контракт не двинуты; `runevents/` тронут только комментариями; + два новых поля `status --json` аддитивны — платформа декодирует аллоулист. +- Кратность оценки `$0`-строки названа честно комментарием и ратифицирована «round up when it cannot + be known» — приёмка это принимает. + +## Мандат самопроверки — исполнением + +1. **Каждый пункт Б1–Б9 проверяется своей командой**, и в отчёте стоит её выход цитатой, а не пересказ. +2. **Мутации Б3 сажаются на копии дерева** (`cp -a backend /tmp/…`) и предъявляются КРАСНЫМИ. + Посадка, не покрасневшая, — находка, а не провал: так и пиши. +3. **Отдельный проход по своей готовой работе** свежим контекстом. Субагенты разрешены явно, модель + задавай ИМЕНЕМ и знай, сколько их работает. +4. ⚠ **«Прошёл, находок нет» отчётом НЕ является**: ноль находок обосновывается тем, ЧТО искалось и + какими командами. + +## Отчёт + +В свою секцию `docs/PROGRESS.md`. Пройди **по каждому** пункту Б1–Б9 и отчитайся по каждому — эта тема +в смене проваливалась несколько раз на том, что исполнялся первый пункт, а нумерованный остаток +бросался. Каждое число — с командой получения, которая его печатает; приёмка пере-ранит. +Обязательная секция **«Что НЕ удалось и что НЕ проверено»** — третий исход законен. +Конфликт этого наряда с кодом — **пинг**, не интерпретация: наряд писан по дереву индекса, код первичен. + +## Прямой канал + +Механизм — `CLAUDE.md`, «Связь между сессиями»: свой блок в `/tmp/textmachine-channel`, сверка с +`ListAgents` перед отправкой; канала нет — нормальный случай, сессии подряд не опрашивать. diff --git a/docs/PLATFORM_P13_DOFIX_2026-09-03.md b/docs/PLATFORM_P13_DOFIX_2026-09-03.md new file mode 100644 index 00000000..7427b690 --- /dev/null +++ b/docs/PLATFORM_P13_DOFIX_2026-09-03.md @@ -0,0 +1,186 @@ +# ДОФИКС платформенному паку P13 «шов возврата оплаченного прогона» — по приёмке оркестратора №22 (03.09.2026) + +> **Роль:** платформа, та же сессия, что отработала пак P13. **Зона записи:** `platform/`. Чужие зоны +> читаешь, не правишь. **Не коммитишь** и не трогаешь индекс и историю — запреты и причина: +> `CLAUDE.md`, «Git-координация мультисессий». Норматив — `platform/docs/ENGINEERING_STANDARDS.md`. +> ⛔ **В индексе сейчас лежит НЕЗАКОММИЧЕННАЯ работа двух смен (46 файлов).** Ни одной пишущей +> git-команды: ни `checkout`, ни `restore`, ни `stash`, ни `reset`, ни `clean`, ни `add`, ни `commit`. + +## Что это и почему оно пришло + +Пак **принят с дофиксом**. Приёмка шла исполнением: десять линз, каждая находка ушла опровергателю с +мандатом её ОПРОВЕРГНУТЬ своей командой. По платформе 24 находки, 18 пережили опровержение. + +⚠ **Главное сначала: правку тейлера НЕ ревертировать.** Заказанное свойство она даёт, и приёмка +подтвердила все три границы промта. Твой `PD-438` — сильная работа: ты нашла, что заказанное мной +пере-упорядочивание расширяло класс, доказала это до и после правки и вылечила глубже. Дофикс не про +это. + +## Карта чтения — три позиции + +1. Этот файл. Прежний промт `docs/PLATFORM_P13_SESSION_PROMPT.md` перечитывать целиком не надо. +2. Свой журнал `platform/docs/platform-PROGRESS.md`, запись 03.09 — по П5–П6 правится он сам. +3. Улики ниже. **Каждая воспроизведена приёмкой; воспроизведи сама** — не воспроизводится, значит + находка, неси пингом. + +## П1 [важное] — обоснование парковки ОПРОВЕРГНУТО исполнением; сама парковка остаётся + +`tail.go:157-159` утверждает абсолютно: «**Nothing of ours can follow**: the engine writes events only +under the project's exclusive flock … so a foreign handshake in this journal means our process no +longer holds it». Из этого выведено «попытка вот-вот закрывается свипом, вред ограничен по времени» — +и это записано в `PD-438`. + +**Опровергнуто путём, который лежит в этом же дереве.** При повторном запуске ТОЙ ЖЕ попытки платформа +отдаёт тот же id (`internal/runs/spawn.go:171` → `engineStreamID(l.RunID, l.AttemptNo)`), а движок +отказывается переиспользовать уже писавший id и **минтит свежий** (`backend/internal/pipeline/events.go:80` +→ `fresh := obs.NewTraceID()`). То есть «чужой» hello в журнале пишет **живой процесс нашей же +попытки**. Приёмка воспроизвела это своим probe-тестом на копии бэкенда (двойной `openEmitter` с одним +и тем же id на одном store). + +Последствие, которое надо назвать честно: прогон уходит в **полную немоту на весь свой срок** — курсор +припаркован, ошибки нет, карантина нет (значит колонка `QUARANTINE` пуста, гейдж +`quarantined_attempts` его не считает, `run unquarantine` отвечает `ErrNotQuarantined`), а `maybeResync` +такую попытку пропускает (`internal/runs/reconcile.go:806` — `l.Position.LastSeq > 0 && !l.Quarantined`). +Пользователь весь прогон видит замерший прогресс. ⚠ Опровергатель сузил радиус: путь — конъюнкция двух +признанных сбоев (претензия на юнит, отчитавшаяся ошибкой + исчезновение юнита без exit-marker), а не +рядовой рестарт. Вес от этого падает, но обоснование остаётся ложным. + +**Делай РОВНО так:** (1) снять абсолютное «Nothing of ours can follow» в `tail.go:157-159` и +формулировку «вред ограничен по времени» в ряде `PD-438` — заменить на то, что верно; (2) дать +припаркованной попытке **наблюдаемость**: сегодня у этого класса нет ни одного из трёх сигналов, +которые были у карантина. +**Решаешь сама и аргументируешь:** ЧЕМ именно её сделать видимой — счётчиком, отдельной причиной, +включением в `maybeResync`, колонкой или новым рядом регистра под отдельный пак. Дорогое решение +здесь не заказано: назвать проблему и предъявить минимум — законный исход. + +## П2 [важное] — гейт батареи заявляет покрытие, которого у него нет; `PD-374` как КЛАСС не снят + +Докблок обещает: «What it asserts is all three columns: the NAME appears, the **STATE follows the host** +rather than a word». По факту состояние сверяется **у одной строки из восьми**: + +``` +platform/internal/gates/battery_test.go:60-66 — два регэкспа только на TM_PLATFORM_TEST_DSN + (UNSET / set); у systemd проверяется лишь, что строка есть в любом состоянии +``` + +Приёмка воспроизвела ТРИ независимые дыры, каждую своей мутацией на копии: +- **состояния семи остальных условий можно заморозить литеральной ЛОЖЬЮ** — `state=MISSING` на + присутствующих бинарях и `UNREACHABLE` на живом systemd: `make conditions` печатает ложь про хост, + гейт зелёный; +- **обратного направления нет**: вставлены выдуманные `TM_PLATFORM_TEST_DEAD_KNOB` и бинарь `ffmpeg` + «read by: internal/ghost» — печатаются, гейт зелёный (положительный контроль: грепа этих имён в + дереве нет); +- **подсказка и гейт выводят из ОДНИХ И ТЕХ ЖЕ двух якорей**: тест, читающий `os.LookupEnv` вместо + `os.Getenv`, реально скипается, в `make conditions` не появляется, гейт зелёный. В обратную сторону + пакет, лишь УПОМЯНУВШИЙ вызов в комментарии, зачисляется в читатели — вопреки собственному докблоку. + +⇒ Первый же новый тест, написанный другой идиомой, возвращает зону в состояние `PD-374` при зелёной +батарее и зелёном гейте. + +**Делай РОВНО так:** сверять состояние по хосту для КАЖДОЙ строки, а не для одной. +**Решаешь сама:** как закрыть обратное направление (строка перечня → исходники) и расширять ли набор +идиом; если считаешь, что «второй карьер факта» тут недостижим — скажи это аргументом. +⚠ **До этого `PD-374` не считать снятым как класс** — экземпляр вылечен, класс нет. + +## П3 [важное] — три калитки нового гейта класса + +- **(а) `accepted-risk` уводит ряд из класса молча.** Приёмка заменила статус `PD-162` (open, minor, + «деньги + холд + блокир») на `accepted-risk`: `go test -run TestOpenRows` выходит нулём, счёт падает + до 10, а единственная строка — «PD-162 has left the class legitimately» — идёт через `t.Logf` и + **не начинается с `ALARM`**, поэтому лифтер цели `check` (`grep -o 'ALARM PD-.*'`) её не поднимает. + Это ровно та калитка, против которой гейт и построен. +- **(б) фильтр «ниже major» слеп к весу ВЫШЕ major.** `strings.Contains(r.weight, "major")`, а словарь + реестра содержит `**BLOCKER**`. Открытая BLOCKER-строка читается как «below major» и краснит + `make check`, причём совет в самом сообщении («either its weight is major») предлагает **понизить + вес самой громкой строки**. Воспроизведено вставкой `| PD-997 | bug | **BLOCKER** | … | open |`. + Сегодня латентно — все три BLOCKER-строки закрыты, — но словарь живой. +- **(в) при прозаическом статусе сообщение называет неверную причину.** Гейт печатает «is in + alarmBaseline and no longer a row of the register: … this is a gate reading the wrong document», хотя + документ верный и строка на месте — причина в прозе статуса. Соседняя ветка гейта такую строку уже + умеет отличать (она печатает её в списке `PD-439`). + +**Делай РОВНО так:** (а) и (в) закрываются. **Решаешь сама:** форма — поднимать ли уведомление об +уходе до `ALARM`, ужесточать ли словарь дверей, и что делать с (б) — чинить фильтр или объявить +BLOCKER частью класса. +⚠ Решение про `PD-439` (семь рядов со статусом вне словаря) — на оркестраторе, и от него зависит, +какой из двух путей в (в) законен. Упрёшься — пинг, не догадка. + +## П4 [мелочь] — `alarmBaseline` и числительное протухли ПОСЛЕ сдачи + +`register_test.go:52-53` всё ещё несёт `PD-168`, который акт лендинга перевёл в `fixed(e85295d)`; гейт +на каждом прогоне печатает `ALARM PD-count: 11 … (baseline 12)` и собственное поручение. Комментарий +`:151` («the same **twelve** rows») и таблица живых проб в журнале зоны говорят «12». +⚠ **На сданном тобой дереве 12 было ВЕРНО** — число протухло от закрытия ряда актом лендинга, это не +твоя ошибка. Но правится в зоне: **делай РОВНО так** — снять `PD-168` из базы, поправить числительное, +снять «12» из таблицы живых проб. По существу довод комментария жив: оба прочтения дают один и тот же +список. + +## П5 [мелочь] — записка о предусловии хоста неверна, и цена этого — потерянный старт следующей смены + +Журнал зоны (`platform-PROGRESS.md:39-40` и `:357`) заявляет «Postgres на 5432», «`~/go/bin` не +существует», «`sqlc` и `golangci-lint` в `~/.local/bin`, уже в PATH, `make tools-check` → 0». +На этом хосте: `~/go/bin` **существует и держит `sqlc`** (mtime 30.08, ДО смены), в `~/.local/bin` +его нет, `make tools-check` на дефолтном PATH даёт «got: none», живой сокет — только +`/tmp/.s.PGSQL.55433`. Это ровно тот класс, что лечит твой же пункт 4: подсказка, отправляющая +читателя не к той ручке. + +⚠ Записка ссылается на подтверждение владельца, что промт писан на другой машине. **Делай РОВНО так:** +либо привести записку к замеру на ЭТОМ хосте, либо вписать явно, что условия хоста замерены на другом +и здесь не проверялись. Молчаливое расхождение недопустимо — следующая смена теряет на нём заход. + +## П6 [мелочь, по желанию] — `RunBudget` без пина в своём пакете + +Подмена «читать ПОСЛЕДНИЙ холд вместо холда первой попытки» оставляет `go test ./internal/pgstore/` +зелёным; ловит её только соседний пакет (`internal/runs/sweep_test.go:1663`). Соседний денежный +читатель того же файла, `RunSpent`, пин в своём пакете имеет — то есть это асимметрия, а не норма. +⚠ Опровергатель понизил вес: штатная батарея зоны — `go test ./... -race`, так что «зелёный пакет» +достижим только ручным прогоном одного пакета, и дыры в защите инварианта нет. +**Решаешь сама:** заводить ли пин; отказ аргументируй. + +## Границы — что НЕ делать + +- ⛔ **Правку тейлера не ревертировать** и границы не двигать: отказ по декоду остаётся ВЫШЕ, + понижение только при известном `want`, при `want == ""` валидация ПОЛНАЯ. Приёмка все три проверила. +- ⛔ Не трогать форму манифеста, схему хранилища движка, версию контракта, `docs/scripts/counts.py`. +- ⛔ Не решать за оркестратора `PD-439` и не переносить ряды между секциями регистра — статус и + переезд суть акт лендинга, он их и делает. +- ⛔ Не трогать бэкенд-половину индекса, `.env`, соседний worktree. + +## Что приёмка ПРОВЕРИЛА и признала — переделывать не нужно + +- `make check` под всеми четырьмя условиями хоста: `0 issues`, 18 пакетов `ok`, три SKIP и все три от + `ENGINE_BIN`. Дефект `PD-374` предъявлен вылеченным вживую: при выставленном DSN рецепт больше не + посылает к DSN. +- Перечень условий **выводится из исходников по ВЫЗОВУ**, а не держится списком в прозе — это сильнее + заказанного. +- Оба новых гейта посажены мутацией приёмкой и оба КРАСНЕЮТ (выброшенный цикл `LookPath`; дописанные + слова тревоги в открытый не-major ряд). +- Тейлер: три границы соблюдены, зелёный пин `TestAnotherAttemptsStreamInTheSameJournalIsSkipped` жив, + два прохода подряд идемпотентны, чужие события на нашу попытку не ложатся. +- `reopen` читает бюджет из холда в обеих точках, прогон без первого холда отвечается ошибкой. +- Пин `held` в ветке чужого handshake'а: приёмка исполнила заявленную им мутацию — **ловится**, + обвинение в фиктивном покрытии снято. +- Строка рантбука исправлена верно; `PD-436` заведён. +- Число «55 посадок» против «60 строк таблицы» — расхождение снято: это ДВЕ таблицы, не одна. + +## Мандат самопроверки — исполнением + +1. **Каждый пункт П1–П6 проверяется своей командой**, выход — цитатой в отчёте. +2. **Мутации сажаются на копии** (`cp -a platform /tmp/…`), гейты предъявляются КРАСНЫМИ на своей + мутации и зелёными после её снятия. +3. **Отдельный проход по своей готовой работе** свежим контекстом. Субагенты разрешены явно, модель + ИМЕНЕМ, число знай. +4. ⚠ «Прошла, находок нет» отчётом не является — ноль обосновывается тем, ЧТО искалось. + +## Отчёт + +В `platform/docs/platform-PROGRESS.md` (в `docs/PROGRESS.md` платформа НЕ пишет). Пройди **по каждому** +пункту П1–П6 и отчитайся по каждому. Каждое число — с командой получения; приёмка пере-ранит. +⚠ Гейты и счёты гнать **ПОСЛЕДНИМ действием**, после того как текст дописан: на прошлом круге число +«12» протухло именно потому, что было снято до последней правки. +Обязательная секция **«Что НЕ удалось и что НЕ проверено»** — третий исход законен. + +## Прямой канал + +Механизм — `CLAUDE.md`, «Связь между сессиями»: свой блок в `/tmp/textmachine-channel`, сверка с +`ListAgents` перед отправкой; канала нет — нормальный случай, сессии подряд не опрашивать.