193 lines
20 KiB
Markdown
193 lines
20 KiB
Markdown
# ДОФИКС платформенному паку 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` перед отправкой; канала нет — нормальный случай, сессии подряд не опрашивать.
|