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

20 KiB
Raw Permalink Blame History

ДОФИКС платформенному паку 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:171engineStreamID(l.RunID, l.AttemptNo)), а движок отказывается переиспользовать уже писавший id и минтит свежий (backend/internal/pipeline/events.go:80fresh := obs.NewTraceID()). То есть «чужой» hello в журнале пишет живой процесс нашей же попытки. Приёмка воспроизвела это своим probe-тестом на копии бэкенда (двойной openEmitter с одним и тем же id на одном store).

Последствие, которое надо назвать честно: прогон уходит в полную немоту на весь свой срок — курсор припаркован, ошибки нет, карантина нет (значит колонка QUARANTINE пуста, гейдж quarantined_attempts его не считает, run unquarantine отвечает ErrNotQuarantined), а maybeResync такую попытку пропускает (internal/runs/reconcile.go:806l.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.mddocs/PROGRESS.md платформа НЕ пишет). Пройди по каждому пункту П1П6 и отчитайся по каждому. Каждое число — с командой получения; приёмка пере-ранит. ⚠ Гейты и счёты гнать ПОСЛЕДНИМ действием, после того как текст дописан: на прошлом круге число «12» протухло именно потому, что было снято до последней правки. Обязательная секция «Что НЕ удалось и что НЕ проверено» — третий исход законен.

Прямой канал

Механизм — CLAUDE.md, «Связь между сессиями»: свой блок в /tmp/textmachine-channel, сверка с ListAgents перед отправкой; канала нет — нормальный случай, сессии подряд не опрашивать.