textmachine/docs/archive/prompts/PLATFORM_P13_DOFIX_2026-09-03.md

193 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ДОФИКС платформенному паку P13 «шов возврата оплаченного прогона» — по приёмке оркестратора №22 (03.09.2026)
> ⚠⚠ **АРХИВ. НАРЯД ОТРАБОТАН — ИНСТРУКЦИИ ОТСЮДА НЕ ИСПОЛНЯЮТСЯ.**
> Выдан 03.09 по приёмке пака P13, отработан той же сессией, принят (`D39.188`). Исход: П1П3 и П6
> исполнены и красны на двадцати посадках приёмки; П4 зона ОТКАЗАЛАСЬ исполнять — и отказ был ПРАВ,
> предпосылка наряда на её дереве была ложной (ряд стоял `open`, гейт и база согласованно печатали 12).
> Остаток — П5, записка о предусловии хоста; он пунктом 4 выданного пака
> `PLATFORM_EXPORT_SESSION_PROMPT.md`.
> **Роль:** платформа, та же сессия, что отработала пак 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` перед отправкой; канала нет — нормальный случай, сессии подряд не опрашивать.